Signed-off-by: Christoph Wurst <christoph@winzerhof-wurst.at>tags/v15.0.0beta1
@@ -993,6 +993,7 @@ return array( | |||
'OC\\Settings\\Controller\\LogSettingsController' => $baseDir . '/settings/Controller/LogSettingsController.php', | |||
'OC\\Settings\\Controller\\MailSettingsController' => $baseDir . '/settings/Controller/MailSettingsController.php', | |||
'OC\\Settings\\Controller\\PersonalSettingsController' => $baseDir . '/settings/Controller/PersonalSettingsController.php', | |||
'OC\\Settings\\Controller\\TwoFactorSettingsController' => $baseDir . '/settings/Controller/TwoFactorSettingsController.php', | |||
'OC\\Settings\\Controller\\UsersController' => $baseDir . '/settings/Controller/UsersController.php', | |||
'OC\\Settings\\Hooks' => $baseDir . '/settings/Hooks.php', | |||
'OC\\Settings\\Mailer\\NewUserMailHelper' => $baseDir . '/settings/Mailer/NewUserMailHelper.php', |
@@ -1023,6 +1023,7 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c | |||
'OC\\Settings\\Controller\\LogSettingsController' => __DIR__ . '/../../..' . '/settings/Controller/LogSettingsController.php', | |||
'OC\\Settings\\Controller\\MailSettingsController' => __DIR__ . '/../../..' . '/settings/Controller/MailSettingsController.php', | |||
'OC\\Settings\\Controller\\PersonalSettingsController' => __DIR__ . '/../../..' . '/settings/Controller/PersonalSettingsController.php', | |||
'OC\\Settings\\Controller\\TwoFactorSettingsController' => __DIR__ . '/../../..' . '/settings/Controller/TwoFactorSettingsController.php', | |||
'OC\\Settings\\Controller\\UsersController' => __DIR__ . '/../../..' . '/settings/Controller/UsersController.php', | |||
'OC\\Settings\\Hooks' => __DIR__ . '/../../..' . '/settings/Hooks.php', | |||
'OC\\Settings\\Mailer\\NewUserMailHelper' => __DIR__ . '/../../..' . '/settings/Mailer/NewUserMailHelper.php', |
@@ -0,0 +1,63 @@ | |||
<?php | |||
declare(strict_types=1); | |||
/** | |||
* @copyright 2018 Christoph Wurst <christoph@winzerhof-wurst.at> | |||
* | |||
* @author 2018 Christoph Wurst <christoph@winzerhof-wurst.at> | |||
* | |||
* @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/>. | |||
* | |||
*/ | |||
namespace OC\Settings\Controller; | |||
use OC\Authentication\TwoFactorAuth\MandatoryTwoFactor; | |||
use OCP\AppFramework\Controller; | |||
use OCP\AppFramework\Http\JSONResponse; | |||
use OCP\AppFramework\Http\Response; | |||
use OCP\IRequest; | |||
use OCP\JSON; | |||
class TwoFactorSettingsController extends Controller { | |||
/** @var MandatoryTwoFactor */ | |||
private $mandatoryTwoFactor; | |||
public function __construct(string $appName, | |||
IRequest $request, | |||
MandatoryTwoFactor $mandatoryTwoFactor) { | |||
parent::__construct($appName, $request); | |||
$this->mandatoryTwoFactor = $mandatoryTwoFactor; | |||
} | |||
public function index(): Response { | |||
return new JSONResponse([ | |||
'enabled' => $this->mandatoryTwoFactor->isEnforced(), | |||
]); | |||
} | |||
public function update(bool $enabled): Response { | |||
$this->mandatoryTwoFactor->setEnforced($enabled); | |||
return new JSONResponse([ | |||
'enabled' => $enabled | |||
]); | |||
} | |||
} |
@@ -3196,11 +3196,11 @@ | |||
} | |||
}, | |||
"follow-redirects": { | |||
"version": "1.4.1", | |||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.4.1.tgz", | |||
"integrity": "sha512-uxYePVPogtya1ktGnAAXOacnbIuRMB4dkvqeNz2qTtTQsuzSfbDolV+wMMKxAmCx0bLgAKLbBOkjItMbbkR1vg==", | |||
"version": "1.5.8", | |||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.8.tgz", | |||
"integrity": "sha512-sy1mXPmv7kLAMKW/8XofG7o9T+6gAjzdZK4AJF6ryqQYUa/hnzgiypoeUecZ53x7XiqKNEpNqLtS97MshW2nxg==", | |||
"requires": { | |||
"debug": "^3.1.0" | |||
"debug": "=3.1.0" | |||
} | |||
}, | |||
"for-in": { |
@@ -80,7 +80,9 @@ $application->registerRoutes($this, [ | |||
['name' => 'AdminSettings#index', 'url' => '/settings/admin/{section}', 'verb' => 'GET', 'defaults' => ['section' => 'server']], | |||
['name' => 'AdminSettings#form', 'url' => '/settings/admin/{section}', 'verb' => 'GET'], | |||
['name' => 'ChangePassword#changePersonalPassword', 'url' => '/settings/personal/changepassword', 'verb' => 'POST'], | |||
['name' => 'ChangePassword#changeUserPassword', 'url' => '/settings/users/changepassword', 'verb' => 'POST'] | |||
['name' => 'ChangePassword#changeUserPassword', 'url' => '/settings/users/changepassword', 'verb' => 'POST'], | |||
['name' => 'TwoFactorSettings#index', 'url' => '/settings/api/admin/twofactorauth', 'verb' => 'GET'], | |||
['name' => 'TwoFactorSettings#update', 'url' => '/settings/api/admin/twofactorauth', 'verb' => 'PUT'], | |||
] | |||
]); | |||
@@ -0,0 +1,76 @@ | |||
<template> | |||
<div> | |||
<p> | |||
{{ t('settings', 'Two-factor authentication can be enforced for all users. If they do not have a two-factor provider configured, they will be unable to log into the system.') }} | |||
</p> | |||
<p v-if="loading"> | |||
<span class="icon-loading-small two-factor-loading"></span> | |||
<span>{{ t('settings', 'Enforce two-factor authentication') }}</span> | |||
</p> | |||
<p v-else> | |||
<input type="checkbox" | |||
id="two-factor-enforced" | |||
class="checkbox" | |||
v-model="enabled" | |||
v-on:change="onEnforcedChanged"> | |||
<label for="two-factor-enforced">{{ t('settings', 'Enforce two-factor authentication') }}</label> | |||
</p> | |||
</div> | |||
</template> | |||
<script> | |||
import Axios from 'nextcloud-axios' | |||
export default { | |||
name: "AdminTwoFactor", | |||
data () { | |||
return { | |||
enabled: false, | |||
loading: false | |||
} | |||
}, | |||
mounted () { | |||
this.loading = true | |||
Axios.get(OC.generateUrl('/settings/api/admin/twofactorauth')) | |||
.then(resp => resp.data) | |||
.then(state => { | |||
this.enabled = state.enabled | |||
this.loading = false | |||
console.info('loaded') | |||
}) | |||
.catch(err => { | |||
console.error(error) | |||
this.loading = false | |||
throw err | |||
}) | |||
}, | |||
methods: { | |||
onEnforcedChanged () { | |||
this.loading = true | |||
const data = { | |||
enabled: this.enabled | |||
} | |||
Axios.put(OC.generateUrl('/settings/api/admin/twofactorauth'), data) | |||
.then(resp => resp.data) | |||
.then(state => { | |||
this.enabled = state.enabled | |||
this.loading = false | |||
}) | |||
.catch(err => { | |||
console.error(error) | |||
this.loading = false | |||
throw err | |||
}) | |||
} | |||
} | |||
} | |||
</script> | |||
<style> | |||
.two-factor-loading { | |||
display: inline-block; | |||
vertical-align: sub; | |||
margin-left: -2px; | |||
margin-right: 1px; | |||
} | |||
</style> |
@@ -0,0 +1,13 @@ | |||
import Vue from 'vue' | |||
import AdminTwoFactor from './components/AdminTwoFactor' | |||
Vue.prototype.t = t; | |||
new Vue({ | |||
el: '#two-factor-auth-settings', | |||
template: '<AdminTwoFactor/>', | |||
components: { | |||
AdminTwoFactor | |||
} | |||
}) |
@@ -24,8 +24,15 @@ | |||
/** @var \OCP\IL10N $l */ | |||
/** @var array $_ */ | |||
script('settings', 'settings-admin-security'); | |||
?> | |||
<div id="two-factor-auth" class="section"> | |||
<h2><?php p($l->t('Two-Factor Authentication'));?></h2> | |||
<div id="two-factor-auth-settings"></div> | |||
</div> | |||
<div class="section" id='encryptionAPI'> | |||
<h2><?php p($l->t('Server-side encryption')); ?></h2> | |||
<a target="_blank" rel="noreferrer noopener" class="icon-info" |
@@ -2,11 +2,14 @@ const path = require('path') | |||
const { VueLoaderPlugin } = require('vue-loader'); | |||
module.exports = { | |||
entry: './src/main.js', | |||
entry: { | |||
'settings-vue': './src/main.js', | |||
'settings-admin-security': './src/main-admin-security' | |||
}, | |||
output: { | |||
path: path.resolve(__dirname, './js'), | |||
publicPath: '/', | |||
filename: 'settings-vue.js' | |||
filename: '[name].js' | |||
}, | |||
module: { | |||
rules: [ |
@@ -0,0 +1,82 @@ | |||
<?php | |||
/** | |||
* @copyright 2018 Christoph Wurst <christoph@winzerhof-wurst.at> | |||
* | |||
* @author 2018 Christoph Wurst <christoph@winzerhof-wurst.at> | |||
* | |||
* @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/>. | |||
*/ | |||
namespace Tests\Settings\Controller; | |||
use OC\Authentication\TwoFactorAuth\MandatoryTwoFactor; | |||
use OC\Settings\Controller\TwoFactorSettingsController; | |||
use OCP\AppFramework\Http\JSONResponse; | |||
use OCP\IRequest; | |||
use PHPUnit\Framework\MockObject\MockObject; | |||
use Test\TestCase; | |||
class TwoFactorSettingsControllerTest extends TestCase { | |||
/** @var IRequest|MockObject */ | |||
private $request; | |||
/** @var MandatoryTwoFactor|MockObject */ | |||
private $mandatoryTwoFactor; | |||
/** @var TwoFactorSettingsController */ | |||
private $controller; | |||
protected function setUp() { | |||
parent::setUp(); | |||
$this->request = $this->createMock(IRequest::class); | |||
$this->mandatoryTwoFactor = $this->createMock(MandatoryTwoFactor::class); | |||
$this->controller = new TwoFactorSettingsController( | |||
'settings', | |||
$this->request, | |||
$this->mandatoryTwoFactor | |||
); | |||
} | |||
public function testIndex() { | |||
$this->mandatoryTwoFactor->expects($this->once()) | |||
->method('isEnforced') | |||
->willReturn(true); | |||
$expected = new JSONResponse([ | |||
'enabled' => true, | |||
]); | |||
$resp = $this->controller->index(); | |||
$this->assertEquals($expected, $resp); | |||
} | |||
public function testUpdate() { | |||
$this->mandatoryTwoFactor->expects($this->once()) | |||
->method('setEnforced') | |||
->with(true); | |||
$expected = new JSONResponse([ | |||
'enabled' => true, | |||
]); | |||
$resp = $this->controller->update(true); | |||
$this->assertEquals($expected, $resp); | |||
} | |||
} |