mirror of
https://github.com/nextcloud/server.git
synced 2026-06-12 02:00:51 -04:00
Merge pull request #57216 from Roszakos/2fa-stateless-provider-interface
feat (2fa): Add IStatelessProvider interface
This commit is contained in:
commit
996fcfe443
7 changed files with 66 additions and 2 deletions
1
AUTHORS
1
AUTHORS
|
|
@ -630,6 +630,7 @@
|
|||
- zorn-v <zorn7@yandex.ru>
|
||||
- zulan <git@zulan.net>
|
||||
- Łukasz Buśko <busko.lukasz@pm.me>
|
||||
- Michał Roszak <m.roszakos@gmail.com>
|
||||
- Nextcloud GmbH
|
||||
- ownCloud GmbH
|
||||
- ownCloud, Inc.
|
||||
|
|
|
|||
|
|
@ -187,6 +187,7 @@ return array(
|
|||
'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\\IStatelessProvider' => $baseDir . '/lib/public/Authentication/TwoFactorAuth/IStatelessProvider.php',
|
||||
'OCP\\Authentication\\TwoFactorAuth\\RegistryEvent' => $baseDir . '/lib/public/Authentication/TwoFactorAuth/RegistryEvent.php',
|
||||
'OCP\\Authentication\\TwoFactorAuth\\TwoFactorException' => $baseDir . '/lib/public/Authentication/TwoFactorAuth/TwoFactorException.php',
|
||||
'OCP\\Authentication\\TwoFactorAuth\\TwoFactorProviderChallengeFailed' => $baseDir . '/lib/public/Authentication/TwoFactorAuth/TwoFactorProviderChallengeFailed.php',
|
||||
|
|
|
|||
|
|
@ -228,6 +228,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
|
|||
'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\\IStatelessProvider' => __DIR__ . '/../../..' . '/lib/public/Authentication/TwoFactorAuth/IStatelessProvider.php',
|
||||
'OCP\\Authentication\\TwoFactorAuth\\RegistryEvent' => __DIR__ . '/../../..' . '/lib/public/Authentication/TwoFactorAuth/RegistryEvent.php',
|
||||
'OCP\\Authentication\\TwoFactorAuth\\TwoFactorException' => __DIR__ . '/../../..' . '/lib/public/Authentication/TwoFactorAuth/TwoFactorException.php',
|
||||
'OCP\\Authentication\\TwoFactorAuth\\TwoFactorProviderChallengeFailed' => __DIR__ . '/../../..' . '/lib/public/Authentication/TwoFactorAuth/TwoFactorProviderChallengeFailed.php',
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ use OCP\Authentication\TwoFactorAuth\IActivatableByAdmin;
|
|||
use OCP\Authentication\TwoFactorAuth\IDeactivatableByAdmin;
|
||||
use OCP\Authentication\TwoFactorAuth\IProvider;
|
||||
use OCP\Authentication\TwoFactorAuth\IRegistry;
|
||||
use OCP\Authentication\TwoFactorAuth\IStatelessProvider;
|
||||
use OCP\IUser;
|
||||
|
||||
class ProviderManager {
|
||||
|
|
@ -43,7 +44,9 @@ class ProviderManager {
|
|||
public function tryEnableProviderFor(string $providerId, IUser $user): bool {
|
||||
$provider = $this->getProvider($providerId, $user);
|
||||
|
||||
if ($provider instanceof IActivatableByAdmin) {
|
||||
if ($provider instanceof IActivatableByAdmin
|
||||
&& !($provider instanceof IStatelessProvider)
|
||||
) {
|
||||
$provider->enableFor($user);
|
||||
$this->providerRegistry->enableProviderFor($provider, $user);
|
||||
return true;
|
||||
|
|
@ -62,7 +65,9 @@ class ProviderManager {
|
|||
public function tryDisableProviderFor(string $providerId, IUser $user): bool {
|
||||
$provider = $this->getProvider($providerId, $user);
|
||||
|
||||
if ($provider instanceof IDeactivatableByAdmin) {
|
||||
if ($provider instanceof IDeactivatableByAdmin
|
||||
&& !($provider instanceof IStatelessProvider)
|
||||
) {
|
||||
$provider->disableFor($user);
|
||||
$this->providerRegistry->disableProviderFor($provider, $user);
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ namespace OC\Authentication\TwoFactorAuth;
|
|||
use OC\Authentication\TwoFactorAuth\Db\ProviderUserAssignmentDao;
|
||||
use OCP\Authentication\TwoFactorAuth\IProvider;
|
||||
use OCP\Authentication\TwoFactorAuth\IRegistry;
|
||||
use OCP\Authentication\TwoFactorAuth\IStatelessProvider;
|
||||
use OCP\Authentication\TwoFactorAuth\RegistryEvent;
|
||||
use OCP\Authentication\TwoFactorAuth\TwoFactorProviderDisabled;
|
||||
use OCP\Authentication\TwoFactorAuth\TwoFactorProviderForUserRegistered;
|
||||
|
|
@ -34,6 +35,10 @@ class Registry implements IRegistry {
|
|||
|
||||
#[\Override]
|
||||
public function enableProviderFor(IProvider $provider, IUser $user) {
|
||||
if ($provider instanceof IStatelessProvider) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->assignmentDao->persist($provider->getId(), $user->getUID(), 1);
|
||||
|
||||
$event = new RegistryEvent($provider, $user);
|
||||
|
|
@ -43,6 +48,10 @@ class Registry implements IRegistry {
|
|||
|
||||
#[\Override]
|
||||
public function disableProviderFor(IProvider $provider, IUser $user) {
|
||||
if ($provider instanceof IStatelessProvider) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->assignmentDao->persist($provider->getId(), $user->getUID(), 0);
|
||||
|
||||
$event = new RegistryEvent($provider, $user);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,22 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
namespace OCP\Authentication\TwoFactorAuth;
|
||||
|
||||
use OCP\AppFramework\Attribute\Implementable;
|
||||
|
||||
/**
|
||||
* Marks the 2FA provider stateless. That means the state of 2FA activation
|
||||
* for user will be checked dynamically and not stored in the database.
|
||||
*
|
||||
* @since 35.0.0
|
||||
*/
|
||||
#[Implementable(since: '35.0.0')]
|
||||
interface IStatelessProvider extends IProvider {
|
||||
}
|
||||
|
|
@ -13,6 +13,7 @@ use OC\Authentication\TwoFactorAuth\Db\ProviderUserAssignmentDao;
|
|||
use OC\Authentication\TwoFactorAuth\Registry;
|
||||
use OCP\Authentication\TwoFactorAuth\IProvider;
|
||||
use OCP\Authentication\TwoFactorAuth\IRegistry;
|
||||
use OCP\Authentication\TwoFactorAuth\IStatelessProvider;
|
||||
use OCP\Authentication\TwoFactorAuth\RegistryEvent;
|
||||
use OCP\Authentication\TwoFactorAuth\TwoFactorProviderDisabled;
|
||||
use OCP\Authentication\TwoFactorAuth\TwoFactorProviderForUserRegistered;
|
||||
|
|
@ -77,6 +78,18 @@ class RegistryTest extends TestCase {
|
|||
$this->registry->enableProviderFor($provider, $user);
|
||||
}
|
||||
|
||||
public function testEnableStatelessProvider(): void {
|
||||
$user = $this->createMock(IUser::class);
|
||||
$provider = $this->createMock(IStatelessProvider::class);
|
||||
|
||||
$this->dao->expects($this->never())->method('persist');
|
||||
|
||||
$this->dispatcher->expects($this->never())->method('dispatch');
|
||||
$this->dispatcher->expects($this->never())->method('dispatchTyped');
|
||||
|
||||
$this->registry->enableProviderFor($provider, $user);
|
||||
}
|
||||
|
||||
public function testDisableProvider(): void {
|
||||
$user = $this->createMock(IUser::class);
|
||||
$provider = $this->createMock(IProvider::class);
|
||||
|
|
@ -103,6 +116,18 @@ class RegistryTest extends TestCase {
|
|||
$this->registry->disableProviderFor($provider, $user);
|
||||
}
|
||||
|
||||
public function testDisableStatelessProvider(): void {
|
||||
$user = $this->createMock(IUser::class);
|
||||
$provider = $this->createMock(IStatelessProvider::class);
|
||||
|
||||
$this->dao->expects($this->never())->method('persist');
|
||||
|
||||
$this->dispatcher->expects($this->never())->method('dispatch');
|
||||
$this->dispatcher->expects($this->never())->method('dispatchTyped');
|
||||
|
||||
$this->registry->disableProviderFor($provider, $user);
|
||||
}
|
||||
|
||||
public function testDeleteUserData(): void {
|
||||
$user = $this->createMock(IUser::class);
|
||||
$user->expects($this->once())->method('getUID')->willReturn('user123');
|
||||
|
|
|
|||
Loading…
Reference in a new issue