Signed-off-by: Christoph Wurst <christoph@winzerhof-wurst.at>tags/v15.0.0beta1
@@ -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(); | |||
} | |||
} | |||
@@ -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; | |||
class Personal implements ISettings { | |||
/** @var Application */ | |||
private $app; | |||
/** @var BackupCodesProvider */ | |||
private $provider; | |||
/** @var IUserSession */ | |||
private $userSession; | |||
use OCP\Authentication\TwoFactorAuth\IPersonalProviderSettings; | |||
use OCP\Template; | |||
public function __construct(Application $app, BackupCodesProvider $provider, IUserSession $userSession) { | |||
$this->app = $app; | |||
$this->provider = $provider; | |||
$this->userSession = $userSession; | |||
} | |||
/** | |||
* @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'; | |||
} | |||
class Personal implements IPersonalProviderSettings { | |||
return new TemplateResponse($templateOwner, $templateName, [], ''); | |||
public function getBody(): Template { | |||
return new Template('twofactor_backupcodes', 'personal'); | |||
} | |||
/** | |||
* @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; | |||
} | |||
} |
@@ -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> |
@@ -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> |
@@ -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; | |||
})) | |||
]; | |||
} | |||
} |
@@ -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; | |||
} |
@@ -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; | |||
} |
@@ -471,6 +471,26 @@ 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; | |||
} | |||
} | |||
#new-app-login-name, | |||
#new-app-password { | |||
width: 245px; |
@@ -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> |