Merge pull request #11409 from nextcloud/feature/consolidated-2fa-settings

Consolidate personal two-factor provider settings
This commit is contained in:
Roeland Jago Douma 2018-10-03 09:56:21 +02:00 committed by GitHub
commit f9e201adfe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 227 additions and 68 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -25,12 +25,15 @@ namespace OCA\TwoFactorBackupCodes\Provider;
use OC\App\AppManager;
use OCA\TwoFactorBackupCodes\Service\BackupCodeStorage;
use OCA\TwoFactorBackupCodes\Settings\Personal;
use OCP\Authentication\TwoFactorAuth\IPersonalProviderSettings;
use OCP\Authentication\TwoFactorAuth\IProvider;
use OCP\Authentication\TwoFactorAuth\IProvidesPersonalSettings;
use OCP\IL10N;
use OCP\IUser;
use OCP\Template;
class BackupCodesProvider implements IProvider {
class BackupCodesProvider implements IProvider, IProvidesPersonalSettings {
/** @var string */
private $appName;
@ -139,4 +142,14 @@ class BackupCodesProvider implements IProvider {
return false;
}
/**
* @param IUser $user
*
* @return IPersonalProviderSettings
*/
public function getPersonalSettings(IUser $user): IPersonalProviderSettings {
return new Personal();
}
}

View File

@ -1,8 +1,9 @@
<?php
declare(strict_types=1);
/**
* @copyright Copyright (c) 2017 Arthur Schiwon <blizzz@arthur-schiwon.de>
*
* @author Arthur Schiwon <blizzz@arthur-schiwon.de>
* @author Christoph Wurst <christoph@winzerhof-wurst.at>
*
* @license GNU AGPL version 3 or any later version
*
@ -24,59 +25,13 @@
namespace OCA\TwoFactorBackupCodes\Settings;
use OCA\TwoFactorBackupCodes\AppInfo\Application;
use OCA\TwoFactorBackupCodes\Provider\BackupCodesProvider;
use OCP\AppFramework\Http\TemplateResponse;
use OCP\IUserSession;
use OCP\Settings\ISettings;
use OCP\Authentication\TwoFactorAuth\IPersonalProviderSettings;
use OCP\Template;
class Personal implements ISettings {
class Personal implements IPersonalProviderSettings {
/** @var Application */
private $app;
/** @var BackupCodesProvider */
private $provider;
/** @var IUserSession */
private $userSession;
public function __construct(Application $app, BackupCodesProvider $provider, IUserSession $userSession) {
$this->app = $app;
$this->provider = $provider;
$this->userSession = $userSession;
public function getBody(): Template {
return new Template('twofactor_backupcodes', 'personal');
}
/**
* @return TemplateResponse returns the instance with all parameters set, ready to be rendered
* @since 9.1
*/
public function getForm() {
$templateOwner = 'settings';
$templateName = 'settings/empty';
if ($this->provider->isActive($this->userSession->getUser())) {
$templateOwner = $this->app->getContainer()->getAppName();
$templateName = 'personal';
}
return new TemplateResponse($templateOwner, $templateName, [], '');
}
/**
* @return string the section ID, e.g. 'sharing'
* @since 9.1
*/
public function getSection() {
return 'security';
}
/**
* @return int whether the form should be rather on the top or bottom of
* the admin section. The forms are arranged in ascending order of the
* priority values. It is required to return a value between 0 and 100.
*
* E.g.: 70
* @since 9.1
*/
public function getPriority() {
return 40;
}
}

View File

@ -14,7 +14,7 @@
<li v-for="code in codes" class="backup-code">{{code}}</li>
</ul>
<a :href="downloadUrl"
class="button"
class="button primary"
download="Nextcloud-backup-codes.txt">{{ t('twofactor_backupcodes', 'Save backup codes') }}</a>
<button class="button"
v-on:click="printCodes">{{ t('twofactor_backupcodes', 'Print backup codes') }}</button>
@ -25,9 +25,9 @@
:class="{'icon-loading-small': generatingCodes}"
v-on:click="generateBackupCodes">{{ t('twofactor_backupcodes', 'Regenerate backup codes') }}</button>
</p>
<p>
<p><em>
{{ t('twofactor_backupcodes', 'If you regenerate backup codes, you automatically invalidate old codes.') }}
</p>
</em></p>
</template>
</div>
</template>

View File

@ -5,7 +5,4 @@ style('twofactor_backupcodes', 'style');
?>
<div class="section">
<h2 data-anchor-name="second-factor-backup-codes"><?php p($l->t('Second-factor backup codes')); ?></h2>
<div id="twofactor-backupcodes-settings"></div>
</div>
<div id="twofactor-backupcodes-settings"></div>

View File

@ -72,9 +72,11 @@ return array(
'OCP\\Authentication\\LoginCredentials\\IStore' => $baseDir . '/lib/public/Authentication/LoginCredentials/IStore.php',
'OCP\\Authentication\\TwoFactorAuth\\IActivatableByAdmin' => $baseDir . '/lib/public/Authentication/TwoFactorAuth/IActivatableByAdmin.php',
'OCP\\Authentication\\TwoFactorAuth\\IDeactivatableByAdmin' => $baseDir . '/lib/public/Authentication/TwoFactorAuth/IDeactivatableByAdmin.php',
'OCP\\Authentication\\TwoFactorAuth\\IPersonalProviderSettings' => $baseDir . '/lib/public/Authentication/TwoFactorAuth/IPersonalProviderSettings.php',
'OCP\\Authentication\\TwoFactorAuth\\IProvider' => $baseDir . '/lib/public/Authentication/TwoFactorAuth/IProvider.php',
'OCP\\Authentication\\TwoFactorAuth\\IProvidesCustomCSP' => $baseDir . '/lib/public/Authentication/TwoFactorAuth/IProvidesCustomCSP.php',
'OCP\\Authentication\\TwoFactorAuth\\IProvidesIcons' => $baseDir . '/lib/public/Authentication/TwoFactorAuth/IProvidesIcons.php',
'OCP\\Authentication\\TwoFactorAuth\\IProvidesPersonalSettings' => $baseDir . '/lib/public/Authentication/TwoFactorAuth/IProvidesPersonalSettings.php',
'OCP\\Authentication\\TwoFactorAuth\\IRegistry' => $baseDir . '/lib/public/Authentication/TwoFactorAuth/IRegistry.php',
'OCP\\Authentication\\TwoFactorAuth\\RegistryEvent' => $baseDir . '/lib/public/Authentication/TwoFactorAuth/RegistryEvent.php',
'OCP\\Authentication\\TwoFactorAuth\\TwoFactorException' => $baseDir . '/lib/public/Authentication/TwoFactorAuth/TwoFactorException.php',

View File

@ -102,9 +102,11 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
'OCP\\Authentication\\LoginCredentials\\IStore' => __DIR__ . '/../../..' . '/lib/public/Authentication/LoginCredentials/IStore.php',
'OCP\\Authentication\\TwoFactorAuth\\IActivatableByAdmin' => __DIR__ . '/../../..' . '/lib/public/Authentication/TwoFactorAuth/IActivatableByAdmin.php',
'OCP\\Authentication\\TwoFactorAuth\\IDeactivatableByAdmin' => __DIR__ . '/../../..' . '/lib/public/Authentication/TwoFactorAuth/IDeactivatableByAdmin.php',
'OCP\\Authentication\\TwoFactorAuth\\IPersonalProviderSettings' => __DIR__ . '/../../..' . '/lib/public/Authentication/TwoFactorAuth/IPersonalProviderSettings.php',
'OCP\\Authentication\\TwoFactorAuth\\IProvider' => __DIR__ . '/../../..' . '/lib/public/Authentication/TwoFactorAuth/IProvider.php',
'OCP\\Authentication\\TwoFactorAuth\\IProvidesCustomCSP' => __DIR__ . '/../../..' . '/lib/public/Authentication/TwoFactorAuth/IProvidesCustomCSP.php',
'OCP\\Authentication\\TwoFactorAuth\\IProvidesIcons' => __DIR__ . '/../../..' . '/lib/public/Authentication/TwoFactorAuth/IProvidesIcons.php',
'OCP\\Authentication\\TwoFactorAuth\\IProvidesPersonalSettings' => __DIR__ . '/../../..' . '/lib/public/Authentication/TwoFactorAuth/IProvidesPersonalSettings.php',
'OCP\\Authentication\\TwoFactorAuth\\IRegistry' => __DIR__ . '/../../..' . '/lib/public/Authentication/TwoFactorAuth/IRegistry.php',
'OCP\\Authentication\\TwoFactorAuth\\RegistryEvent' => __DIR__ . '/../../..' . '/lib/public/Authentication/TwoFactorAuth/RegistryEvent.php',
'OCP\\Authentication\\TwoFactorAuth\\TwoFactorException' => __DIR__ . '/../../..' . '/lib/public/Authentication/TwoFactorAuth/TwoFactorException.php',

View File

@ -24,18 +24,41 @@
namespace OC\Settings\Personal;
use function array_filter;
use function array_map;
use function is_null;
use OC\Authentication\TwoFactorAuth\Manager as TwoFactorManager;
use OC\Authentication\TwoFactorAuth\ProviderLoader;
use OCP\AppFramework\Http\TemplateResponse;
use OCP\Authentication\TwoFactorAuth\IProvider;
use OCP\Authentication\TwoFactorAuth\IProvidesPersonalSettings;
use OCP\IUserManager;
use OCP\IUserSession;
use OCP\Settings\ISettings;
class Security implements ISettings {
/** @var IUserManager */
private $userManager;
public function __construct(
IUserManager $userManager
) {
/** @var TwoFactorManager */
private $twoFactorManager;
/** @var ProviderLoader */
private $providerLoader;
/** @var IUserSession */
private $userSession;
public function __construct(IUserManager $userManager,
TwoFactorManager $providerManager,
ProviderLoader $providerLoader,
IUserSession $userSession) {
$this->userManager = $userManager;
$this->twoFactorManager = $providerManager;
$this->providerLoader = $providerLoader;
$this->userSession = $userSession;
}
/**
@ -50,7 +73,8 @@ class Security implements ISettings {
}
return new TemplateResponse('settings', 'settings/personal/security', [
'passwordChangeSupported' => $passwordChangeSupported
'passwordChangeSupported' => $passwordChangeSupported,
'twoFactorProviderData' => $this->getTwoFactorProviderData(),
]);
}
@ -73,4 +97,24 @@ class Security implements ISettings {
public function getPriority() {
return 10;
}
private function getTwoFactorProviderData(): array {
$user = $this->userSession->getUser();
if (is_null($user)) {
// Actually impossible, but still …
return [];
}
return [
'isEnabled' => $this->twoFactorManager->isTwoFactorAuthenticated($user),
'providers' => array_map(function (IProvidesPersonalSettings $provider) use ($user) {
return [
'provider' => $provider,
'settings' => $provider->getPersonalSettings($user)
];
}, array_filter($this->providerLoader->getProviders($user), function (IProvider $provider) {
return $provider instanceof IProvidesPersonalSettings;
}))
];
}
}

View File

@ -0,0 +1,43 @@
<?php
declare(strict_types=1);
/**
* @author Christoph Wurst <christoph@owncloud.com>
*
* @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 OCP\Authentication\TwoFactorAuth;
use OCP\Template;
/**
* Interface IPersonalProviderSettings
*
* @since 15.0.0
*/
interface IPersonalProviderSettings {
/**
* @return Template
*
* @since 15.0.0
*/
public function getBody(): Template;
}

View File

@ -0,0 +1,47 @@
<?php
declare(strict_types=1);
/**
* @author Christoph Wurst <christoph@owncloud.com>
*
* @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 OCP\Authentication\TwoFactorAuth;
use OCP\IUser;
/**
* Interface for admins that have personal settings. These settings will be shown in the
* security sections. Some information like the display name of the provider is read
* from the provider directly.
*
* @since 15.0.0
*/
interface IProvidesPersonalSettings extends IProvider {
/**
* @param IUser $user
*
* @return IPersonalProviderSettings
*
* @since 15.0.0
*/
public function getPersonalSettings(IUser $user): IPersonalProviderSettings;
}

View File

@ -471,6 +471,27 @@ table.nostyle {
}
}
/* Two-Factor Authentication (2FA) */
#two-factor-auth {
h3 {
margin-top: 24px;
}
li > div {
margin-left: 20px;
}
.two-factor-provider-settings-icon {
width: 16px;
height: 16px;
vertical-align: sub;
}
}
#new-app-login-name,
#new-app-password {
width: 245px;

View File

@ -101,3 +101,38 @@ if($_['passwordChangeSupported']) {
</div>
</div>
</div>
<div id="two-factor-auth" class="section">
<h2><?php p($l->t('Two-Factor Authentication'));?></h2>
<p class="settings-hint">
<?php
if ($_['twoFactorProviderData']['enabled']) {
p($l->t('Two-factor authentication is enabled on your account.'));
} else {
p($l->t('Two-factor authentication is disabled on your account.'));
}
?>
</p>
<ul>
<?php foreach ($_['twoFactorProviderData']['providers'] as $data) { ?>
<li>
<?php
/** @var \OCP\Authentication\TwoFactorAuth\IProvidesPersonalSettings $provider */
$provider = $data['provider'];
if ($provider instanceof \OCP\Authentication\TwoFactorAuth\IProvidesIcons) {
$icon = $provider->getDarkIcon();
} else {
$icon = image_path('core', 'actions/password.svg');
}
/** @var \OCP\Authentication\TwoFactorAuth\IPersonalProviderSettings $settings */
$settings = $data['settings'];
?>
<h3>
<img class="two-factor-provider-settings-icon" src="<?php p($icon) ?>" alt="">
<?php p($provider->getDisplayName()) ?>
</h3>
<?php print_unescaped($settings->getBody()->fetchPage()) ?>
</li>
<?php } ?>
</ul>
</div>