Merge pull request #9830 from nextcloud/feature/noid/oauth_vue_redirect_validate
Migrate OAuth Admin settings to vue
This commit is contained in:
commit
c3aea9cdf6
|
@ -0,0 +1,25 @@
|
|||
all: dev-setup build-js-production
|
||||
|
||||
dev-setup: clean clean-dev npm-init
|
||||
|
||||
npm-init:
|
||||
npm install
|
||||
|
||||
npm-update:
|
||||
npm update
|
||||
|
||||
build-js:
|
||||
npm run dev
|
||||
|
||||
build-js-production:
|
||||
npm run build
|
||||
|
||||
watch-js:
|
||||
npm run watch
|
||||
|
||||
clean:
|
||||
rm -f js/oauth2.js
|
||||
rm -f js/oauth2.map
|
||||
|
||||
clean-dev:
|
||||
rm -rf node_modules
|
|
@ -23,13 +23,18 @@ return [
|
|||
'routes' => [
|
||||
[
|
||||
'name' => 'Settings#addClient',
|
||||
'url' => '/settings',
|
||||
'url' => '/clients',
|
||||
'verb' => 'POST',
|
||||
],
|
||||
[
|
||||
'name' => 'Settings#getClients',
|
||||
'url' => '/clients',
|
||||
'verb' => 'GET',
|
||||
],
|
||||
[
|
||||
'name' => 'Settings#deleteClient',
|
||||
'url' => '/clients/{id}/delete',
|
||||
'verb' => 'POST'
|
||||
'url' => '/clients/{id}',
|
||||
'verb' => 'DELETE'
|
||||
],
|
||||
[
|
||||
'name' => 'LoginRedirector#authorize',
|
||||
|
|
|
@ -3,3 +3,18 @@
|
|||
opacity: 0.3;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#oauth2 .icon-toggle,
|
||||
#oauth2 .icon-delete {
|
||||
display: inline-block;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
padding: 10px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
#oauth2 .grid td code {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
padding: 3px;
|
||||
}
|
File diff suppressed because one or more lines are too long
|
@ -1,15 +0,0 @@
|
|||
$(document).ready(function () {
|
||||
|
||||
$('.show-oauth-credentials').click(function() {
|
||||
var row = $(this).parent();
|
||||
var code = $(row).find('code');
|
||||
if(code.text() === '****') {
|
||||
code.text(row.data('value'));
|
||||
$(this).css('opacity', 0.9);
|
||||
} else {
|
||||
code.text('****');
|
||||
$(this).css('opacity', 0.3);
|
||||
}
|
||||
})
|
||||
|
||||
});
|
|
@ -1,4 +1,5 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* @copyright Copyright (c) 2017 Lukas Reschke <lukas@statuscode.ch>
|
||||
*
|
||||
|
@ -26,14 +27,11 @@ use OCA\OAuth2\Db\AccessTokenMapper;
|
|||
use OCA\OAuth2\Db\Client;
|
||||
use OCA\OAuth2\Db\ClientMapper;
|
||||
use OCP\AppFramework\Controller;
|
||||
use OCP\AppFramework\Http\RedirectResponse;
|
||||
use OCP\AppFramework\Http\JSONResponse;
|
||||
use OCP\IRequest;
|
||||
use OCP\IURLGenerator;
|
||||
use OCP\Security\ISecureRandom;
|
||||
|
||||
class SettingsController extends Controller {
|
||||
/** @var IURLGenerator */
|
||||
private $urlGenerator;
|
||||
/** @var ClientMapper */
|
||||
private $clientMapper;
|
||||
/** @var ISecureRandom */
|
||||
|
@ -48,53 +46,68 @@ class SettingsController extends Controller {
|
|||
/**
|
||||
* @param string $appName
|
||||
* @param IRequest $request
|
||||
* @param IURLGenerator $urlGenerator
|
||||
* @param ClientMapper $clientMapper
|
||||
* @param ISecureRandom $secureRandom
|
||||
* @param AccessTokenMapper $accessTokenMapper
|
||||
* @param DefaultTokenMapper $defaultTokenMapper
|
||||
*/
|
||||
public function __construct($appName,
|
||||
public function __construct(string $appName,
|
||||
IRequest $request,
|
||||
IURLGenerator $urlGenerator,
|
||||
ClientMapper $clientMapper,
|
||||
ISecureRandom $secureRandom,
|
||||
AccessTokenMapper $accessTokenMapper,
|
||||
DefaultTokenMapper $defaultTokenMapper
|
||||
) {
|
||||
parent::__construct($appName, $request);
|
||||
$this->urlGenerator = $urlGenerator;
|
||||
$this->secureRandom = $secureRandom;
|
||||
$this->clientMapper = $clientMapper;
|
||||
$this->accessTokenMapper = $accessTokenMapper;
|
||||
$this->defaultTokenMapper = $defaultTokenMapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
* @param string $redirectUri
|
||||
* @return RedirectResponse
|
||||
*/
|
||||
public function addClient($name,
|
||||
$redirectUri) {
|
||||
public function addClient(string $name,
|
||||
string $redirectUri): JSONResponse {
|
||||
$client = new Client();
|
||||
$client->setName($name);
|
||||
$client->setRedirectUri($redirectUri);
|
||||
$client->setSecret($this->secureRandom->generate(64, self::validChars));
|
||||
$client->setClientIdentifier($this->secureRandom->generate(64, self::validChars));
|
||||
$this->clientMapper->insert($client);
|
||||
return new RedirectResponse($this->urlGenerator->getAbsoluteURL('/index.php/settings/admin/security'));
|
||||
$client = $this->clientMapper->insert($client);
|
||||
|
||||
$result = [
|
||||
'id' => $client->getId(),
|
||||
'name' => $client->getName(),
|
||||
'redirectUri' => $client->getRedirectUri(),
|
||||
'clientId' => $client->getClientIdentifier(),
|
||||
'clientSecret' => $client->getSecret(),
|
||||
];
|
||||
|
||||
return new JSONResponse($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $id
|
||||
* @return RedirectResponse
|
||||
*/
|
||||
public function deleteClient($id) {
|
||||
public function deleteClient(int $id): JSONResponse {
|
||||
$client = $this->clientMapper->getByUid($id);
|
||||
$this->accessTokenMapper->deleteByClientId($id);
|
||||
$this->defaultTokenMapper->deleteByName($client->getName());
|
||||
$this->clientMapper->delete($client);
|
||||
return new RedirectResponse($this->urlGenerator->getAbsoluteURL('/index.php/settings/admin/security'));
|
||||
return new JSONResponse([]);
|
||||
}
|
||||
|
||||
public function getClients(): JSONResponse {
|
||||
$clients = $this->clientMapper->getClients();
|
||||
|
||||
$result = [];
|
||||
|
||||
foreach ($clients as $client) {
|
||||
$result[] = [
|
||||
'id' => $client->getId(),
|
||||
'name' => $client->getName(),
|
||||
'redirectUri' => $client->getRedirectUri(),
|
||||
'clientId' => $client->getClientIdentifier(),
|
||||
'clientSecret' => $client->getSecret(),
|
||||
];
|
||||
}
|
||||
|
||||
return new JSONResponse($result);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* @copyright Copyright (c) 2017 Lukas Reschke <lukas@statuscode.ch>
|
||||
*
|
||||
|
@ -21,46 +22,25 @@
|
|||
|
||||
namespace OCA\OAuth2\Settings;
|
||||
|
||||
use OCA\OAuth2\Db\ClientMapper;
|
||||
use OCP\AppFramework\Http\TemplateResponse;
|
||||
use OCP\Settings\ISettings;
|
||||
|
||||
class Admin implements ISettings {
|
||||
/** @var ClientMapper */
|
||||
private $clientMapper;
|
||||
|
||||
/**
|
||||
* @param ClientMapper $clientMapper
|
||||
*/
|
||||
public function __construct(ClientMapper $clientMapper) {
|
||||
$this->clientMapper = $clientMapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return TemplateResponse
|
||||
*/
|
||||
public function getForm() {
|
||||
public function getForm(): TemplateResponse {
|
||||
return new TemplateResponse(
|
||||
'oauth2',
|
||||
'admin',
|
||||
[
|
||||
'clients' => $this->clientMapper->getClients(),
|
||||
],
|
||||
[],
|
||||
''
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getSection() {
|
||||
public function getSection(): string {
|
||||
return 'security';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getPriority() {
|
||||
public function getPriority(): int {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,31 @@
|
|||
{
|
||||
"name": "oauth2",
|
||||
"version": "1.0.0",
|
||||
"description": "OAuth2 setup",
|
||||
"author": "Roeland Jago Douma <roeland@famdouma.nl>",
|
||||
"license": "AGPL-3.0-or-later",
|
||||
"main": "init.js",
|
||||
"directories": {
|
||||
"lib": "lib",
|
||||
"test": "tests"
|
||||
},
|
||||
"scripts": {
|
||||
"dev": "webpack --config src/webpack.dev.js",
|
||||
"watch": "webpack --progress --watch --config src/webpack.dev.js",
|
||||
"build": "webpack --progress --hide-modules --config src/webpack.prod.js",
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"dependencies": {
|
||||
"axios": "^0.18.0",
|
||||
"vue": "^2.5.16"
|
||||
},
|
||||
"devDependencies": {
|
||||
"css-loader": "^0.28.11",
|
||||
"file-loader": "^1.1.11",
|
||||
"vue-loader": "^15.2.4",
|
||||
"vue-template-compiler": "^2.5.16",
|
||||
"webpack": "^4.11.1",
|
||||
"webpack-cli": "^3.0.3",
|
||||
"webpack-merge": "^4.1.2"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,113 @@
|
|||
<!--
|
||||
- @copyright Copyright (c) 2018 Roeland Jago Douma <roeland@famdouma.nl>
|
||||
-
|
||||
- @author Roeland Jago Douma <roeland@famdouma.nl>
|
||||
-
|
||||
- @license GNU AGPL version 3 or any later version
|
||||
-
|
||||
- This program is free software: you can redistribute it and/or modify
|
||||
- it under the terms of the GNU Affero General Public License as
|
||||
- published by the Free Software Foundation, either version 3 of the
|
||||
- License, or (at your option) any later version.
|
||||
-
|
||||
- This program is distributed in the hope that it will be useful,
|
||||
- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
- GNU Affero General Public License for more details.
|
||||
-
|
||||
- You should have received a copy of the GNU Affero General Public License
|
||||
- along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
-
|
||||
-->
|
||||
<template>
|
||||
<div id="oauth2" class="section">
|
||||
<h2>{{ t('oauth2', 'OAuth 2.0 clients') }}</h2>
|
||||
<p class="settings-hint">{{ t('oauth2', 'OAuth 2.0 allows external services to request access to {instanceName}.', { instanceName: oc_defaults.name}) }}</p>
|
||||
<table class="grid">
|
||||
<thead>
|
||||
<tr>
|
||||
<th id="headerName" scope="col">{{ t('oauth2', 'Name') }}</th>
|
||||
<th id="headerRedirectUri" scope="col">{{ t('oauth2', 'Redirection URI') }}</th>
|
||||
<th id="headerClientIdentifier" scope="col">{{ t('oauth2', 'Client Identifier') }}</th>
|
||||
<th id="headerSecret" scope="col">{{ t('oauth2', 'Secret') }}</th>
|
||||
<th id="headerRemove"> </th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<OAuthItem v-for="client in clients"
|
||||
:key="client.id"
|
||||
:client="client"
|
||||
@delete="deleteClient"
|
||||
/>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<br/>
|
||||
<h3>{{ t('oauth2', 'Add client') }}</h3>
|
||||
<form @submit.prevent="addClient">
|
||||
<input type="text" id="name" name="name" :placeholder="t('oauth2', 'Name')" v-model="newClient.name">
|
||||
<input type="url" id="redirectUri" name="redirectUri" :placeholder="t('oauth2', 'Redirection URI')" v-model="newClient.redirectUri">
|
||||
<input type="submit" class="button" :value="t('oauth2', 'Add')">
|
||||
</form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import axios from 'axios';
|
||||
import OAuthItem from './components/OAuthItem';
|
||||
|
||||
export default {
|
||||
name: 'App',
|
||||
components: {
|
||||
OAuthItem
|
||||
},
|
||||
data: function() {
|
||||
return {
|
||||
clients: [],
|
||||
newClient: {
|
||||
name: '',
|
||||
redirectUri: ''
|
||||
}
|
||||
};
|
||||
},
|
||||
beforeMount: function() {
|
||||
let requestToken = OC.requestToken;
|
||||
let tokenHeaders = { headers: { requesttoken: requestToken } };
|
||||
|
||||
axios.get(OC.generateUrl('apps/oauth2/clients'), tokenHeaders)
|
||||
.then((response) => {
|
||||
this.clients = response.data;
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
deleteClient(id) {
|
||||
let requestToken = OC.requestToken;
|
||||
let tokenHeaders = { headers: { requesttoken: requestToken } };
|
||||
|
||||
axios.delete(OC.generateUrl('apps/oauth2/clients/{id}', {id: id}), tokenHeaders)
|
||||
.then((response) => {
|
||||
this.clients = this.clients.filter(client => client.id !== id);
|
||||
});
|
||||
},
|
||||
addClient() {
|
||||
let requestToken = OC.requestToken;
|
||||
let tokenHeaders = { headers: { requesttoken: requestToken } };
|
||||
|
||||
axios.post(
|
||||
OC.generateUrl('apps/oauth2/clients'),
|
||||
{
|
||||
name: this.newClient.name,
|
||||
redirectUri: this.newClient.redirectUri
|
||||
},
|
||||
tokenHeaders)
|
||||
.then((response) => {
|
||||
this.clients.push(response.data)
|
||||
|
||||
this.newClient.name = '';
|
||||
this.newClient.redirectUri = '';
|
||||
}
|
||||
);
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,66 @@
|
|||
<!--
|
||||
- @copyright Copyright (c) 2018 Roeland Jago Douma <roeland@famdouma.nl>
|
||||
-
|
||||
- @author Roeland Jago Douma <roeland@famdouma.nl>
|
||||
-
|
||||
- @license GNU AGPL version 3 or any later version
|
||||
-
|
||||
- This program is free software: you can redistribute it and/or modify
|
||||
- it under the terms of the GNU Affero General Public License as
|
||||
- published by the Free Software Foundation, either version 3 of the
|
||||
- License, or (at your option) any later version.
|
||||
-
|
||||
- This program is distributed in the hope that it will be useful,
|
||||
- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
- GNU Affero General Public License for more details.
|
||||
-
|
||||
- You should have received a copy of the GNU Affero General Public License
|
||||
- along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
-
|
||||
-->
|
||||
<template>
|
||||
<tr>
|
||||
<td>{{name}}</td>
|
||||
<td>{{redirectUri}}</td>
|
||||
<td><code>{{clientId}}</code></td>
|
||||
<td><code>{{renderedSecret}}</code><a class='icon-toggle has-tooltip' :title="t('oauth2', 'Show client secret')" @click="toggleSecret"></a></td>
|
||||
<td class="action-column"><span><a class="icon-delete has-tooltip" :title="t('oauth2', 'Delete')" @click="$emit('delete', id)"></a></span></td>
|
||||
</tr>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'OAuthItem',
|
||||
props: {
|
||||
client: {
|
||||
type: Object,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data: function() {
|
||||
return {
|
||||
id: this.client.id,
|
||||
name: this.client.name,
|
||||
redirectUri: this.client.redirectUri,
|
||||
clientId: this.client.clientId,
|
||||
clientSecret: this.client.clientSecret,
|
||||
renderSecret: false,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
renderedSecret: function() {
|
||||
if (this.renderSecret) {
|
||||
return this.clientSecret;
|
||||
} else {
|
||||
return '****';
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
toggleSecret() {
|
||||
this.renderSecret = !this.renderSecret;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,35 @@
|
|||
/**
|
||||
* @copyright Copyright (c) 2018 Roeland Jago Douma <roeland@famdouma.nl>
|
||||
*
|
||||
* @author Roeland Jago Douma <roeland@famdouma.nl>
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
import Vue from 'vue';
|
||||
import App from './App.vue';
|
||||
|
||||
Vue.prototype.t = t;
|
||||
Vue.prototype.oc_defaults = oc_defaults;
|
||||
Vue.prototype.OC = OC;
|
||||
|
||||
const app = new Vue({
|
||||
render: h => h(App)
|
||||
}).$mount('#oauth2');
|
||||
|
||||
export { app };
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
const path = require('path')
|
||||
const { VueLoaderPlugin } = require('vue-loader');
|
||||
|
||||
module.exports = {
|
||||
entry: path.join(__dirname, 'main.js'),
|
||||
output: {
|
||||
path: path.resolve(__dirname, '../js'),
|
||||
publicPath: '/js',
|
||||
filename: 'oauth2.js'
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.vue$/,
|
||||
loader: 'vue-loader',
|
||||
}
|
||||
]
|
||||
},
|
||||
plugins: [
|
||||
new VueLoaderPlugin()
|
||||
],
|
||||
resolve: {
|
||||
alias: {
|
||||
'vue$': 'vue/dist/vue.esm.js'
|
||||
},
|
||||
extensions: ['*', '.js', '.vue', '.json']
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
const merge = require('webpack-merge');
|
||||
const common = require('./webpack.common.js');
|
||||
|
||||
module.exports = merge(common, {
|
||||
mode: 'development',
|
||||
devServer: {
|
||||
historyApiFallback: true,
|
||||
noInfo: true,
|
||||
overlay: true
|
||||
},
|
||||
devtool: '#eval-source-map',
|
||||
})
|
|
@ -0,0 +1,7 @@
|
|||
const merge = require('webpack-merge')
|
||||
const common = require('./webpack.common.js')
|
||||
|
||||
module.exports = merge(common, {
|
||||
mode: 'production',
|
||||
devtool: '#source-map'
|
||||
})
|
|
@ -19,58 +19,9 @@
|
|||
*
|
||||
*/
|
||||
|
||||
$urlGenerator = \OC::$server->getURLGenerator();
|
||||
$themingDefaults = \OC::$server->getThemingDefaults();
|
||||
|
||||
script('oauth2', 'setting-admin');
|
||||
script('oauth2', 'oauth2');
|
||||
style('oauth2', 'setting-admin');
|
||||
|
||||
/** @var array $_ */
|
||||
/** @var \OCA\OAuth2\Db\Client[] $clients */
|
||||
$clients = $_['clients'];
|
||||
?>
|
||||
|
||||
<div id="oauth2" class="section">
|
||||
<h2><?php p($l->t('OAuth 2.0 clients')); ?></h2>
|
||||
<p class="settings-hint"><?php p($l->t('OAuth 2.0 allows external services to request access to %s.', [$themingDefaults->getName()])); ?></p>
|
||||
|
||||
<table class="grid">
|
||||
<thead>
|
||||
<tr>
|
||||
<th id="headerName" scope="col"><?php p($l->t('Name')); ?></th>
|
||||
<th id="headerRedirectUri" scope="col"><?php p($l->t('Redirection URI')); ?></th>
|
||||
<th id="headerClientIdentifier" scope="col"><?php p($l->t('Client Identifier')); ?></th>
|
||||
<th id="headerSecret" scope="col"><?php p($l->t('Secret')); ?></th>
|
||||
<th id="headerRemove"> </th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php
|
||||
$imageUrl = $urlGenerator->imagePath('core', 'actions/toggle.svg');
|
||||
foreach ($clients as $client) {
|
||||
?>
|
||||
<tr>
|
||||
<td><?php p($client->getName()); ?></td>
|
||||
<td><?php p($client->getRedirectUri()); ?></td>
|
||||
<td><code><?php p($client->getClientIdentifier()); ?></code></td>
|
||||
<td data-value="<?php p($client->getSecret()); ?>"><code>****</code><img class='show-oauth-credentials' src="<?php p($imageUrl); ?>"/></td>
|
||||
<td>
|
||||
<form id="form-inline" class="delete" action="<?php p($urlGenerator->linkToRoute('oauth2.Settings.deleteClient', ['id' => $client->getId()])); ?>" method="POST">
|
||||
<input type="hidden" name="requesttoken" value="<?php p($_['requesttoken']) ?>" />
|
||||
<input type="submit" class="button icon-delete" value="">
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
<?php } ?>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<br/>
|
||||
<h3><?php p($l->t('Add client')); ?></h3>
|
||||
<form action="<?php p($urlGenerator->linkToRoute('oauth2.Settings.addClient')); ?>" method="POST">
|
||||
<input type="text" id="name" name="name" placeholder="<?php p($l->t('Name')); ?>">
|
||||
<input type="url" id="redirectUri" name="redirectUri" placeholder="<?php p($l->t('Redirection URI')); ?>">
|
||||
<input type="hidden" name="requesttoken" value="<?php p($_['requesttoken']) ?>" />
|
||||
<input type="submit" class="button" value="<?php p($l->t('Add')); ?>">
|
||||
</form>
|
||||
</div>
|
||||
<div id="oauth2"></div>
|
||||
|
|
|
@ -26,17 +26,14 @@ use OCA\OAuth2\Controller\SettingsController;
|
|||
use OCA\OAuth2\Db\AccessTokenMapper;
|
||||
use OCA\OAuth2\Db\Client;
|
||||
use OCA\OAuth2\Db\ClientMapper;
|
||||
use OCP\AppFramework\Http\RedirectResponse;
|
||||
use OCP\AppFramework\Http\JSONResponse;
|
||||
use OCP\IRequest;
|
||||
use OCP\IURLGenerator;
|
||||
use OCP\Security\ISecureRandom;
|
||||
use Test\TestCase;
|
||||
|
||||
class SettingsControllerTest extends TestCase {
|
||||
/** @var IRequest|\PHPUnit_Framework_MockObject_MockObject */
|
||||
private $request;
|
||||
/** @var IURLGenerator|\PHPUnit_Framework_MockObject_MockObject */
|
||||
private $urlGenerator;
|
||||
/** @var ClientMapper|\PHPUnit_Framework_MockObject_MockObject */
|
||||
private $clientMapper;
|
||||
/** @var ISecureRandom|\PHPUnit_Framework_MockObject_MockObject */
|
||||
|
@ -52,7 +49,6 @@ class SettingsControllerTest extends TestCase {
|
|||
parent::setUp();
|
||||
|
||||
$this->request = $this->createMock(IRequest::class);
|
||||
$this->urlGenerator = $this->createMock(IURLGenerator::class);
|
||||
$this->clientMapper = $this->createMock(ClientMapper::class);
|
||||
$this->secureRandom = $this->createMock(ISecureRandom::class);
|
||||
$this->accessTokenMapper = $this->createMock(AccessTokenMapper::class);
|
||||
|
@ -61,7 +57,6 @@ class SettingsControllerTest extends TestCase {
|
|||
$this->settingsController = new SettingsController(
|
||||
'oauth2',
|
||||
$this->request,
|
||||
$this->urlGenerator,
|
||||
$this->clientMapper,
|
||||
$this->secureRandom,
|
||||
$this->accessTokenMapper,
|
||||
|
@ -90,27 +85,39 @@ class SettingsControllerTest extends TestCase {
|
|||
$this->clientMapper
|
||||
->expects($this->once())
|
||||
->method('insert')
|
||||
->with($client);
|
||||
->with($this->callback(function (Client $c) {
|
||||
return $c->getName() === 'My Client Name' &&
|
||||
$c->getRedirectUri() === 'https://example.com/' &&
|
||||
$c->getSecret() === 'MySecret' &&
|
||||
$c->getClientIdentifier() === 'MyClientIdentifier';
|
||||
}))->will($this->returnCallback(function (Client $c) {
|
||||
$c->setId(42);
|
||||
return $c;
|
||||
}));
|
||||
|
||||
$this->urlGenerator
|
||||
->expects($this->once())
|
||||
->method('getAbsoluteURL')
|
||||
->with('/index.php/settings/admin/security')
|
||||
->willReturn('https://example.com/index.php/settings/admin/security');
|
||||
$result = $this->settingsController->addClient('My Client Name', 'https://example.com/');
|
||||
$this->assertInstanceOf(JSONResponse::class, $result);
|
||||
|
||||
$expected = new RedirectResponse('https://example.com/index.php/settings/admin/security');
|
||||
$this->assertEquals($expected, $this->settingsController->addClient('My Client Name', 'https://example.com/'));
|
||||
$data = $result->getData();
|
||||
|
||||
$this->assertEquals([
|
||||
'id' => 42,
|
||||
'name' => 'My Client Name',
|
||||
'redirectUri' => 'https://example.com/',
|
||||
'clientId' => 'MyClientIdentifier',
|
||||
'clientSecret' => 'MySecret',
|
||||
], $data);
|
||||
}
|
||||
|
||||
public function testDeleteClient() {
|
||||
$client = new Client();
|
||||
$client->setId(123);
|
||||
$client->setName('My Client Name');
|
||||
$client->setRedirectUri('https://example.com/');
|
||||
$client->setSecret('MySecret');
|
||||
$client->setClientIdentifier('MyClientIdentifier');
|
||||
|
||||
$this->clientMapper
|
||||
->expects($this->at(0))
|
||||
->method('getByUid')
|
||||
->with(123)
|
||||
->willReturn($client);
|
||||
|
@ -123,17 +130,52 @@ class SettingsControllerTest extends TestCase {
|
|||
->method('deleteByName')
|
||||
->with('My Client Name');
|
||||
$this->clientMapper
|
||||
->expects($this->at(1))
|
||||
->method('delete')
|
||||
->with($client);
|
||||
|
||||
$this->urlGenerator
|
||||
->expects($this->once())
|
||||
->method('getAbsoluteURL')
|
||||
->with('/index.php/settings/admin/security')
|
||||
->willReturn('https://example.com/index.php/settings/admin/security');
|
||||
$result = $this->settingsController->deleteClient(123);
|
||||
$this->assertInstanceOf(JSONResponse::class, $result);
|
||||
$this->assertEquals([], $result->getData());
|
||||
}
|
||||
|
||||
$expected = new RedirectResponse('https://example.com/index.php/settings/admin/security');
|
||||
$this->assertEquals($expected, $this->settingsController->deleteClient(123));
|
||||
public function testGetClients() {
|
||||
$client1 = new Client();
|
||||
$client1->setId(123);
|
||||
$client1->setName('My Client Name');
|
||||
$client1->setRedirectUri('https://example.com/');
|
||||
$client1->setSecret('MySecret');
|
||||
$client1->setClientIdentifier('MyClientIdentifier');
|
||||
|
||||
$client2 = new Client();
|
||||
$client2->setId(42);
|
||||
$client2->setName('My Client Name2');
|
||||
$client2->setRedirectUri('https://example.com/2');
|
||||
$client2->setSecret('MySecret2');
|
||||
$client2->setClientIdentifier('MyClientIdentifier2');
|
||||
|
||||
$this->clientMapper->method('getClients')
|
||||
->willReturn([$client1, $client2]);
|
||||
|
||||
$result = $this->settingsController->getClients();
|
||||
$this->assertInstanceOf(JSONResponse::class, $result);
|
||||
|
||||
$data = $result->getData();
|
||||
|
||||
$this->assertSame([
|
||||
[
|
||||
'id' => 123,
|
||||
'name' => 'My Client Name',
|
||||
'redirectUri' => 'https://example.com/',
|
||||
'clientId' => 'MyClientIdentifier',
|
||||
'clientSecret' => 'MySecret',
|
||||
],
|
||||
[
|
||||
'id' => 42,
|
||||
'name' => 'My Client Name2',
|
||||
'redirectUri' => 'https://example.com/2',
|
||||
'clientId' => 'MyClientIdentifier2',
|
||||
'clientSecret' => 'MySecret2',
|
||||
],
|
||||
], $data);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,35 +21,25 @@
|
|||
|
||||
namespace OCA\OAuth2\Tests\Settings;
|
||||
|
||||
use OCA\OAuth2\Db\ClientMapper;
|
||||
use OCA\OAuth2\Settings\Admin;
|
||||
use OCP\AppFramework\Http\TemplateResponse;
|
||||
use Test\TestCase;
|
||||
|
||||
class AdminTest extends TestCase {
|
||||
/** @var ClientMapper|\PHPUnit_Framework_MockObject_MockObject */
|
||||
private $clientMapper;
|
||||
/** @var Admin|\PHPUnit_Framework_MockObject_MockObject */
|
||||
private $admin;
|
||||
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->clientMapper = $this->createMock(ClientMapper::class);
|
||||
$this->admin = new Admin($this->clientMapper);
|
||||
$this->admin = new Admin();
|
||||
}
|
||||
|
||||
public function testGetForm() {
|
||||
$this->clientMapper
|
||||
->expects($this->once())
|
||||
->method('getClients')
|
||||
->willReturn(['MyClients']);
|
||||
|
||||
$expected = new TemplateResponse(
|
||||
'oauth2',
|
||||
'admin',
|
||||
[
|
||||
'clients' => ['MyClients'],
|
||||
],
|
||||
''
|
||||
);
|
||||
|
|
Loading…
Reference in New Issue