Merge pull request #26594 from nextcloud/enh/2fa/bootstrap

Move 2FA registration to IBootstrap
pull/26669/head
Morris Jobke 2021-04-20 21:30:15 +07:00 committed by GitHub
commit 6c0bb2c338
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 92 additions and 8 deletions

@ -5,7 +5,7 @@
<name>Two factor backup codes</name>
<summary>A two-factor auth backup codes provider</summary>
<description>A two-factor auth backup codes provider</description>
<version>1.10.0</version>
<version>1.10.1</version>
<licence>agpl</licence>
<author>Christoph Wurst</author>
<namespace>TwoFactorBackupCodes</namespace>
@ -22,10 +22,6 @@
</post-migration>
</repair-steps>
<two-factor-providers>
<provider>OCA\TwoFactorBackupCodes\Provider\BackupCodesProvider</provider>
</two-factor-providers>
<activity>
<providers>
<provider>OCA\TwoFactorBackupCodes\Activity\Provider</provider>

@ -36,6 +36,7 @@ use OCA\TwoFactorBackupCodes\Listener\ProviderEnabled;
use OCA\TwoFactorBackupCodes\Listener\RegistryUpdater;
use OCA\TwoFactorBackupCodes\Listener\UserDeleted;
use OCA\TwoFactorBackupCodes\Notifications\Notifier;
use OCA\TwoFactorBackupCodes\Provider\BackupCodesProvider;
use OCP\AppFramework\App;
use OCP\AppFramework\Bootstrap\IBootContext;
use OCP\AppFramework\Bootstrap\IBootstrap;
@ -59,6 +60,9 @@ class Application extends App implements IBootstrap {
$context->registerEventListener(IRegistry::EVENT_PROVIDER_ENABLED, ProviderEnabled::class);
$context->registerEventListener(IRegistry::EVENT_PROVIDER_DISABLED, ProviderDisabled::class);
$context->registerEventListener(UserDeletedEvent::class, UserDeleted::class);
$context->registerTwoFactorProvider(BackupCodesProvider::class);
}
public function boot(IBootContext $context): void {

@ -92,7 +92,10 @@ class RegistrationContext {
private $templateProviders = [];
/** @var ServiceRegistration<INotifier>[] */
private $notifierServices;
private $notifierServices = [];
/** @var ServiceRegistration<\OCP\Authentication\TwoFactorAuth\IProvider>[] */
private $twoFactorProviders = [];
/** @var ILogger */
private $logger;
@ -217,6 +220,13 @@ class RegistrationContext {
$notifierClass
);
}
public function registerTwoFactorProvider(string $twoFactorProviderClass): void {
$this->context->registerTwoFactorProvider(
$this->appId,
$twoFactorProviderClass
);
}
};
}
@ -288,6 +298,10 @@ class RegistrationContext {
$this->notifierServices[] = new ServiceRegistration($appId, $class);
}
public function registerTwoFactorProvider(string $appId, string $class): void {
$this->twoFactorProviders[] = new ServiceRegistration($appId, $class);
}
/**
* @param App[] $apps
*/
@ -479,4 +493,11 @@ class RegistrationContext {
public function getNotifierServices(): array {
return $this->notifierServices;
}
/**
* @return ServiceRegistration<\OCP\Authentication\TwoFactorAuth\IProvider>[]
*/
public function getTwoFactorProviders(): array {
return $this->twoFactorProviders;
}
}

@ -40,8 +40,12 @@ class ProviderLoader {
/** @var IAppManager */
private $appManager;
public function __construct(IAppManager $appManager) {
/** @var OC\AppFramework\Bootstrap\Coordinator */
private $coordinator;
public function __construct(IAppManager $appManager, OC\AppFramework\Bootstrap\Coordinator $coordinator) {
$this->appManager = $appManager;
$this->coordinator = $coordinator;
}
/**
@ -72,6 +76,18 @@ class ProviderLoader {
}
}
$registeredProviders = $this->coordinator->getRegistrationContext()->getTwoFactorProviders();
foreach ($registeredProviders as $provider) {
try {
$this->loadTwoFactorApp($provider->getAppId());
$provider = OC::$server->query($provider->getService());
$providers[$provider->getId()] = $provider;
} catch (QueryException $exc) {
// Provider class can not be resolved
throw new Exception('Could not load two-factor auth provider ' . $provider->getService());
}
}
return $providers;
}

@ -30,6 +30,7 @@ declare(strict_types=1);
namespace OCP\AppFramework\Bootstrap;
use OCP\AppFramework\IAppContainer;
use OCP\Authentication\TwoFactorAuth\IProvider;
use OCP\Capabilities\ICapability;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\Files\Template\ICustomTemplateProvider;
@ -219,4 +220,13 @@ interface IRegistrationContext {
* @since 22.0.0
*/
public function registerNotifierService(string $notifierClass): void;
/**
* Register a two-factor provider
*
* @param string $twoFactorProviderClass
* @psalm-param class-string<IProvider> $twoFactorProviderClass
* @since 22.0.0
*/
public function registerTwoFactorProvider(string $twoFactorProviderClass): void;
}

@ -26,9 +26,13 @@ declare(strict_types=1);
namespace lib\Authentication\TwoFactorAuth;
use OC\AppFramework\Bootstrap\Coordinator;
use OC\AppFramework\Bootstrap\RegistrationContext;
use OC\AppFramework\Bootstrap\ServiceRegistration;
use OC\Authentication\TwoFactorAuth\ProviderLoader;
use OCP\App\IAppManager;
use OCP\Authentication\TwoFactorAuth\IProvider;
use PHPUnit\Framework\MockObject\MockObject;
use Test\TestCase;
class ProviderLoaderTest extends TestCase {
@ -39,6 +43,9 @@ class ProviderLoaderTest extends TestCase {
/** @var \OCP\IUser|\PHPUnit\Framework\MockObject\MockObject */
private $user;
/** @var RegistrationContext|MockObject */
private $registrationContext;
/** @var ProviderLoader */
private $loader;
@ -48,7 +55,12 @@ class ProviderLoaderTest extends TestCase {
$this->appManager = $this->createMock(IAppManager::class);
$this->user = $this->createMock(\OCP\IUser::class);
$this->loader = new ProviderLoader($this->appManager);
$this->registrationContext = $this->createMock(RegistrationContext::class);
$coordinator = $this->createMock(Coordinator::class);
$coordinator->method('getRegistrationContext')
->willReturn($this->registrationContext);
$this->loader = new ProviderLoader($this->appManager, $coordinator);
}
@ -97,4 +109,29 @@ class ProviderLoaderTest extends TestCase {
$this->assertArrayHasKey('test', $providers);
$this->assertSame($provider, $providers['test']);
}
public function testGetProvidersBootstrap() {
$provider = $this->createMock(IProvider::class);
$provider->method('getId')->willReturn('test');
\OC::$server->registerService('\\OCA\\TwoFactorTest\\Provider', function () use ($provider) {
return $provider;
});
$this->appManager->expects($this->once())
->method('getEnabledAppsForUser')
->with($this->user)
->willReturn([]);
$this->registrationContext->method('getTwoFactorProvider')
->willReturn([
new ServiceRegistration('twofactor_test', '\\OCA\\TwoFactorTest\\Provider')
]);
$providers = $this->loader->getProviders($this->user);
$this->assertCount(1, $providers);
$this->assertArrayHasKey('test', $providers);
$this->assertSame($provider, $providers['test']);
}
}