diff options
author | Christoph Wurst <christoph@winzerhof-wurst.at> | 2018-05-22 08:52:16 +0200 |
---|---|---|
committer | Christoph Wurst <christoph@winzerhof-wurst.at> | 2018-06-20 08:30:26 +0200 |
commit | 13d93f5b25aa3e663146349583a0a8e01b216f7a (patch) | |
tree | 494950eefa4b27c980ebce22eeafa58eab08892d /tests | |
parent | cad8824a8e7da7fcf61960b6502b307672651c2b (diff) | |
download | nextcloud-server-13d93f5b25aa3e663146349583a0a8e01b216f7a.tar.gz nextcloud-server-13d93f5b25aa3e663146349583a0a8e01b216f7a.zip |
Make 2FA providers stateful
This adds persistence to the Nextcloud server 2FA logic so that the server
knows which 2FA providers are enabled for a specific user at any time, even
when the provider is not available.
The `IStatefulProvider` interface was added as tagging interface for providers
that are compatible with this new API.
Signed-off-by: Christoph Wurst <christoph@winzerhof-wurst.at>
Diffstat (limited to 'tests')
7 files changed, 490 insertions, 172 deletions
diff --git a/tests/Core/Controller/LoginControllerTest.php b/tests/Core/Controller/LoginControllerTest.php index ccd70111ae5..1e26d86a039 100644 --- a/tests/Core/Controller/LoginControllerTest.php +++ b/tests/Core/Controller/LoginControllerTest.php @@ -23,11 +23,13 @@ namespace Tests\Core\Controller; use OC\Authentication\Token\IToken; use OC\Authentication\TwoFactorAuth\Manager; +use OC\Authentication\TwoFactorAuth\ProviderSet; use OC\Core\Controller\LoginController; use OC\Security\Bruteforce\Throttler; use OC\User\Session; use OCP\AppFramework\Http\RedirectResponse; use OCP\AppFramework\Http\TemplateResponse; +use OCP\Authentication\TwoFactorAuth\IProvider; use OCP\Defaults; use OCP\IConfig; use OCP\ILogger; @@ -414,7 +416,7 @@ class LoginControllerTest extends TestCase { $user->expects($this->any()) ->method('getUID') ->will($this->returnValue('uid')); - $loginName = 'loginli'; + $loginName = 'loginli'; $password = 'secret'; $indexPageUrl = \OC_Util::getDefaultPageUrl(); @@ -539,7 +541,7 @@ class LoginControllerTest extends TestCase { $expected = new \OCP\AppFramework\Http\RedirectResponse(urldecode($redirectUrl)); $this->assertEquals($expected, $this->loginController->tryLogin('Jane', $password, $originalUrl)); } - + public function testLoginWithOneTwoFactorProvider() { /** @var IUser|\PHPUnit_Framework_MockObject_MockObject $user */ $user = $this->createMock(IUser::class); @@ -548,7 +550,7 @@ class LoginControllerTest extends TestCase { ->will($this->returnValue('john')); $password = 'secret'; $challengeUrl = 'challenge/url'; - $provider = $this->getMockBuilder('\OCP\Authentication\TwoFactorAuth\IProvider')->getMock(); + $provider = $this->createMock(IProvider::class); $this->request ->expects($this->once()) @@ -570,10 +572,11 @@ class LoginControllerTest extends TestCase { $this->twoFactorManager->expects($this->once()) ->method('prepareTwoFactorLogin') ->with($user); + $providerSet = new ProviderSet([$provider], false); $this->twoFactorManager->expects($this->once()) - ->method('getProviders') + ->method('getProviderSet') ->with($user) - ->will($this->returnValue([$provider])); + ->willReturn($providerSet); $provider->expects($this->once()) ->method('getId') ->will($this->returnValue('u2f')); @@ -593,7 +596,7 @@ class LoginControllerTest extends TestCase { $this->assertEquals($expected, $this->loginController->tryLogin('john@doe.com', $password, null)); } - public function testLoginWithMultpleTwoFactorProviders() { + public function testLoginWithMultipleTwoFactorProviders() { /** @var IUser|\PHPUnit_Framework_MockObject_MockObject $user */ $user = $this->createMock(IUser::class); $user->expects($this->any()) @@ -601,8 +604,10 @@ class LoginControllerTest extends TestCase { ->will($this->returnValue('john')); $password = 'secret'; $challengeUrl = 'challenge/url'; - $provider1 = $this->getMockBuilder('\OCP\Authentication\TwoFactorAuth\IProvider')->getMock(); - $provider2 = $this->getMockBuilder('\OCP\Authentication\TwoFactorAuth\IProvider')->getMock(); + $provider1 = $this->createMock(IProvider::class); + $provider2 = $this->createMock(IProvider::class); + $provider1->method('getId')->willReturn('prov1'); + $provider2->method('getId')->willReturn('prov2'); $this->request ->expects($this->once()) @@ -624,14 +629,11 @@ class LoginControllerTest extends TestCase { $this->twoFactorManager->expects($this->once()) ->method('prepareTwoFactorLogin') ->with($user); + $providerSet = new ProviderSet([$provider1, $provider2], false); $this->twoFactorManager->expects($this->once()) - ->method('getProviders') + ->method('getProviderSet') ->with($user) - ->will($this->returnValue([$provider1, $provider2])); - $provider1->expects($this->never()) - ->method('getId'); - $provider2->expects($this->never()) - ->method('getId'); + ->willReturn($providerSet); $this->urlGenerator->expects($this->once()) ->method('linkToRoute') ->with('core.TwoFactorChallenge.selectChallenge') @@ -661,7 +663,7 @@ class LoginControllerTest extends TestCase { ->method('checkPassword') ->with('john', 'just wrong') ->willReturn(false); - + $this->userManager->expects($this->once()) ->method('getByEmail') ->with('john@doe.com') diff --git a/tests/Core/Controller/TwoFactorChallengeControllerTest.php b/tests/Core/Controller/TwoFactorChallengeControllerTest.php index ed6452316ff..6a01c510ed2 100644 --- a/tests/Core/Controller/TwoFactorChallengeControllerTest.php +++ b/tests/Core/Controller/TwoFactorChallengeControllerTest.php @@ -23,6 +23,7 @@ namespace Test\Core\Controller; use OC\Authentication\TwoFactorAuth\Manager; +use OC\Authentication\TwoFactorAuth\ProviderSet; use OC\Core\Controller\TwoFactorChallengeController; use OC_Util; use OCP\AppFramework\Http\RedirectResponse; @@ -85,26 +86,26 @@ class TwoFactorChallengeControllerTest extends TestCase { public function testSelectChallenge() { $user = $this->getMockBuilder(IUser::class)->getMock(); - $providers = [ - 'prov1', - 'prov2', - ]; + $p1 = $this->createMock(IProvider::class); + $p1->method('getId')->willReturn('p1'); + $backupProvider = $this->createMock(IProvider::class); + $backupProvider->method('getId')->willReturn('backup_codes'); + $providerSet = new ProviderSet([$p1, $backupProvider], true); $this->userSession->expects($this->once()) ->method('getUser') ->will($this->returnValue($user)); $this->twoFactorManager->expects($this->once()) - ->method('getProviders') - ->with($user) - ->will($this->returnValue($providers)); - $this->twoFactorManager->expects($this->once()) - ->method('getBackupProvider') + ->method('getProviderSet') ->with($user) - ->will($this->returnValue('backup')); + ->will($this->returnValue($providerSet)); $expected = new TemplateResponse('core', 'twofactorselectchallenge', [ - 'providers' => $providers, - 'backupProvider' => 'backup', + 'providers' => [ + $p1, + ], + 'providerMissing' => true, + 'backupProvider' => $backupProvider, 'redirect_url' => '/some/url', 'logout_url' => 'logoutAttribute', ], 'guest'); @@ -115,20 +116,19 @@ class TwoFactorChallengeControllerTest extends TestCase { public function testShowChallenge() { $user = $this->createMock(IUser::class); $provider = $this->createMock(IProvider::class); + $provider->method('getId')->willReturn('myprovider'); $backupProvider = $this->createMock(IProvider::class); + $backupProvider->method('getId')->willReturn('backup_codes'); $tmpl = $this->createMock(Template::class); + $providerSet = new ProviderSet([$provider, $backupProvider], true); $this->userSession->expects($this->once()) ->method('getUser') ->will($this->returnValue($user)); $this->twoFactorManager->expects($this->once()) - ->method('getProvider') - ->with($user, 'myprovider') - ->will($this->returnValue($provider)); - $this->twoFactorManager->expects($this->once()) - ->method('getBackupProvider') + ->method('getProviderSet') ->with($user) - ->will($this->returnValue($backupProvider)); + ->will($this->returnValue($providerSet)); $provider->expects($this->once()) ->method('getId') ->will($this->returnValue('u2f')); @@ -166,14 +166,15 @@ class TwoFactorChallengeControllerTest extends TestCase { public function testShowInvalidChallenge() { $user = $this->createMock(IUser::class); + $providerSet = new ProviderSet([], false); $this->userSession->expects($this->once()) ->method('getUser') ->will($this->returnValue($user)); $this->twoFactorManager->expects($this->once()) - ->method('getProvider') - ->with($user, 'myprovider') - ->will($this->returnValue(null)); + ->method('getProviderSet') + ->with($user) + ->will($this->returnValue($providerSet)); $this->urlGenerator->expects($this->once()) ->method('linkToRoute') ->with('core.TwoFactorChallenge.selectChallenge') diff --git a/tests/lib/Authentication/TwoFactorAuth/Db/ProviderUserAssignmentDaoTest.php b/tests/lib/Authentication/TwoFactorAuth/Db/ProviderUserAssignmentDaoTest.php new file mode 100644 index 00000000000..adce55e11e3 --- /dev/null +++ b/tests/lib/Authentication/TwoFactorAuth/Db/ProviderUserAssignmentDaoTest.php @@ -0,0 +1,95 @@ +<?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 Test\Authentication\TwoFactorAuth\Db; + +use OC; +use OC\Authentication\TwoFactorAuth\Db\ProviderUserAssignmentDao; +use OCP\IDBConnection; +use Test\TestCase; + +/** + * @group DB + */ +class ProviderUserAssignmentDaoTest extends TestCase { + + /** @var IDBConnection */ + private $dbConn; + + /** @var ProviderUserAssignmentDao */ + private $dao; + + protected function setUp() { + parent::setUp(); + + $this->dbConn = OC::$server->getDatabaseConnection(); + $qb = $this->dbConn->getQueryBuilder(); + $q = $qb->delete(ProviderUserAssignmentDao::TABLE_NAME); + $q->execute(); + + $this->dao = new ProviderUserAssignmentDao($this->dbConn); + } + + public function testGetState() { + $qb = $this->dbConn->getQueryBuilder(); + $q1 = $qb->insert(ProviderUserAssignmentDao::TABLE_NAME)->values([ + 'provider_id' => $qb->createNamedParameter('twofactor_u2f'), + 'uid' => $qb->createNamedParameter('user123'), + 'enabled' => $qb->createNamedParameter(1), + ]); + $q1->execute(); + $q2 = $qb->insert(ProviderUserAssignmentDao::TABLE_NAME)->values([ + 'provider_id' => $qb->createNamedParameter('twofactor_totp'), + 'uid' => $qb->createNamedParameter('user123'), + 'enabled' => $qb->createNamedParameter(0), + ]); + $q2->execute(); + $expected = [ + 'twofactor_u2f' => true, + 'twofactor_totp' => false, + ]; + + $state = $this->dao->getState('user123'); + + $this->assertEquals($expected, $state); + } + + public function testPersist() { + $qb = $this->dbConn->getQueryBuilder(); + + $this->dao->persist('twofactor_totp', 'user123', 0); + + $q = $qb + ->select('*') + ->from(ProviderUserAssignmentDao::TABLE_NAME) + ->where($qb->expr()->eq('provider_id', $qb->createNamedParameter('twofactor_totp'))) + ->andWhere($qb->expr()->eq('uid', $qb->createNamedParameter('user123'))) + ->andWhere($qb->expr()->eq('enabled', $qb->createNamedParameter(0))); + $res = $q->execute(); + $data = $res->fetchAll(); + $res->closeCursor(); + $this->assertCount(1, $data); + } + +} diff --git a/tests/lib/Authentication/TwoFactorAuth/ManagerTest.php b/tests/lib/Authentication/TwoFactorAuth/ManagerTest.php index 3c617fe8442..e54e4353404 100644 --- a/tests/lib/Authentication/TwoFactorAuth/ManagerTest.php +++ b/tests/lib/Authentication/TwoFactorAuth/ManagerTest.php @@ -24,13 +24,14 @@ namespace Test\Authentication\TwoFactorAuth; use Exception; use OC; -use OC\App\AppManager; use OC\Authentication\Token\IProvider as TokenProvider; use OC\Authentication\TwoFactorAuth\Manager; +use OC\Authentication\TwoFactorAuth\ProviderLoader; use OCP\Activity\IEvent; use OCP\Activity\IManager; use OCP\AppFramework\Utility\ITimeFactory; use OCP\Authentication\TwoFactorAuth\IProvider; +use OCP\Authentication\TwoFactorAuth\IRegistry; use OCP\IConfig; use OCP\ILogger; use OCP\ISession; @@ -43,8 +44,11 @@ class ManagerTest extends TestCase { /** @var IUser|\PHPUnit_Framework_MockObject_MockObject */ private $user; - /** @var AppManager|\PHPUnit_Framework_MockObject_MockObject */ - private $appManager; + /** @var ProviderLoader|\PHPUnit_Framework_MockObject_MockObject */ + private $providerLoader; + + /** @var IRegistry|\PHPUnit_Framework_MockObject_MockObject */ + private $providerRegistry; /** @var ISession|\PHPUnit_Framework_MockObject_MockObject */ private $session; @@ -80,7 +84,8 @@ class ManagerTest extends TestCase { parent::setUp(); $this->user = $this->createMock(IUser::class); - $this->appManager = $this->createMock(AppManager::class); + $this->providerLoader = $this->createMock(\OC\Authentication\TwoFactorAuth\ProviderLoader::class); + $this->providerRegistry = $this->createMock(IRegistry::class); $this->session = $this->createMock(ISession::class); $this->config = $this->createMock(IConfig::class); $this->activityManager = $this->createMock(IManager::class); @@ -89,172 +94,145 @@ class ManagerTest extends TestCase { $this->timeFactory = $this->createMock(ITimeFactory::class); $this->eventDispatcher = $this->createMock(EventDispatcherInterface::class); - $this->manager = $this->getMockBuilder(Manager::class) - ->setConstructorArgs([ - $this->appManager, - $this->session, - $this->config, - $this->activityManager, - $this->logger, - $this->tokenProvider, - $this->timeFactory, - $this->eventDispatcher - ]) - ->setMethods(['loadTwoFactorApp']) // Do not actually load the apps - ->getMock(); + $this->manager = new Manager( + $this->providerLoader, + $this->providerRegistry, + $this->session, + $this->config, + $this->activityManager, + $this->logger, + $this->tokenProvider, + $this->timeFactory, + $this->eventDispatcher + ); $this->fakeProvider = $this->createMock(IProvider::class); - $this->fakeProvider->expects($this->any()) - ->method('getId') - ->will($this->returnValue('email')); - $this->fakeProvider->expects($this->any()) - ->method('isTwoFactorAuthEnabledForUser') - ->will($this->returnValue(true)); - OC::$server->registerService('\OCA\MyCustom2faApp\FakeProvider', function() { - return $this->fakeProvider; - }); + $this->fakeProvider->method('getId')->willReturn('email'); + $this->fakeProvider->method('isTwoFactorAuthEnabledForUser')->willReturn(true); $this->backupProvider = $this->getMockBuilder('\OCP\Authentication\TwoFactorAuth\IProvider')->getMock(); - $this->backupProvider->expects($this->any()) - ->method('getId') - ->will($this->returnValue('backup_codes')); - $this->backupProvider->expects($this->any()) - ->method('isTwoFactorAuthEnabledForUser') - ->will($this->returnValue(true)); - OC::$server->registerService('\OCA\TwoFactorBackupCodes\Provider\FakeBackupCodesProvider', function () { - return $this->backupProvider; - }); + $this->backupProvider->method('getId')->willReturn('backup_codes'); + $this->backupProvider->method('isTwoFactorAuthEnabledForUser')->willReturn(true); } private function prepareNoProviders() { - $this->appManager->expects($this->any()) - ->method('getEnabledAppsForUser') + $this->providerLoader->method('getProviders') ->with($this->user) ->will($this->returnValue([])); - - $this->appManager->expects($this->never()) - ->method('getAppInfo'); - - $this->manager->expects($this->never()) - ->method('loadTwoFactorApp'); } private function prepareProviders() { - $this->appManager->expects($this->any()) - ->method('getEnabledAppsForUser') + $this->providerRegistry->expects($this->once()) + ->method('getProviderStates') ->with($this->user) - ->will($this->returnValue(['mycustom2faapp'])); - - $this->appManager->expects($this->once()) - ->method('getAppInfo') - ->with('mycustom2faapp') - ->will($this->returnValue([ - 'two-factor-providers' => [ - '\OCA\MyCustom2faApp\FakeProvider', - ], - ])); - - $this->manager->expects($this->once()) - ->method('loadTwoFactorApp') - ->with('mycustom2faapp'); - } - - private function prepareProvidersWitBackupProvider() { - $this->appManager->expects($this->any()) - ->method('getEnabledAppsForUser') + ->willReturn([ + $this->fakeProvider->getId() => true, + ]); + $this->providerLoader->expects($this->once()) + ->method('getProviders') ->with($this->user) - ->will($this->returnValue([ - 'mycustom2faapp', - 'twofactor_backupcodes', - ])); - - $this->appManager->expects($this->exactly(2)) - ->method('getAppInfo') - ->will($this->returnValueMap([ - [ - 'mycustom2faapp', false, null, - ['two-factor-providers' => [ - '\OCA\MyCustom2faApp\FakeProvider', - ] - ] - ], - [ - 'twofactor_backupcodes', false, null, - ['two-factor-providers' => [ - '\OCA\TwoFactorBackupCodes\Provider\FakeBackupCodesProvider', - ] - ] - ], - ])); - - $this->manager->expects($this->exactly(2)) - ->method('loadTwoFactorApp'); + ->willReturn([$this->fakeProvider]); } - /** - * @expectedException Exception - * @expectedExceptionMessage Could not load two-factor auth provider \OCA\MyFaulty2faApp\DoesNotExist - */ - public function testFailHardIfProviderCanNotBeLoaded() { - $this->appManager->expects($this->once()) - ->method('getEnabledAppsForUser') + private function prepareProvidersWitBackupProvider() { + $this->providerLoader->method('getProviders') ->with($this->user) - ->will($this->returnValue(['faulty2faapp'])); - $this->manager->expects($this->once()) - ->method('loadTwoFactorApp') - ->with('faulty2faapp'); - - $this->appManager->expects($this->once()) - ->method('getAppInfo') - ->with('faulty2faapp') - ->will($this->returnValue([ - 'two-factor-providers' => [ - '\OCA\MyFaulty2faApp\DoesNotExist', - ], - ])); - - $this->manager->getProviders($this->user); + ->willReturn([ + $this->fakeProvider, + $this->backupProvider, + ]); } public function testIsTwoFactorAuthenticated() { - $this->prepareProviders(); - $this->user->expects($this->once()) ->method('getUID') ->will($this->returnValue('user123')); $this->config->expects($this->once()) ->method('getUserValue') ->with('user123', 'core', 'two_factor_auth_disabled', 0) - ->will($this->returnValue(0)); + ->willReturn(0); + $this->providerRegistry->expects($this->once()) + ->method('getProviderStates') + ->willReturn([ + 'twofactor_totp' => true, + 'twofactor_u2f' => false, + ]); $this->assertTrue($this->manager->isTwoFactorAuthenticated($this->user)); } public function testGetProvider() { - $this->prepareProviders(); - - $this->assertSame($this->fakeProvider, $this->manager->getProvider($this->user, 'email')); - } + $this->providerRegistry->expects($this->once()) + ->method('getProviderStates') + ->with($this->user) + ->willReturn([ + $this->fakeProvider->getId() => true, + ]); + $this->providerLoader->expects($this->once()) + ->method('getProviders') + ->with($this->user) + ->willReturn([$this->fakeProvider]); - public function testGetBackupProvider() { - $this->prepareProvidersWitBackupProvider(); + $provider = $this->manager->getProvider($this->user, $this->fakeProvider->getId()); - $this->assertSame($this->backupProvider, $this->manager->getBackupProvider($this->user)); + $this->assertSame($this->fakeProvider, $provider); } public function testGetInvalidProvider() { - $this->prepareProviders(); + $this->providerRegistry->expects($this->once()) + ->method('getProviderStates') + ->with($this->user) + ->willReturn([]); + $this->providerLoader->expects($this->once()) + ->method('getProviders') + ->with($this->user) + ->willReturn([]); - $this->assertSame(null, $this->manager->getProvider($this->user, 'nonexistent')); + $provider = $this->manager->getProvider($this->user, 'nonexistent'); + + $this->assertNull($provider); } public function testGetProviders() { - $this->prepareProviders(); + $this->providerRegistry->expects($this->once()) + ->method('getProviderStates') + ->with($this->user) + ->willReturn([ + $this->fakeProvider->getId() => true, + ]); + $this->providerLoader->expects($this->once()) + ->method('getProviders') + ->with($this->user) + ->willReturn([$this->fakeProvider]); $expectedProviders = [ 'email' => $this->fakeProvider, ]; - $this->assertEquals($expectedProviders, $this->manager->getProviders($this->user)); + $providerSet = $this->manager->getProviderSet($this->user); + $providers = $providerSet->getProviders(); + + $this->assertEquals($expectedProviders, $providers); + $this->assertFalse($providerSet->isProviderMissing()); + } + + public function testGetProvidersOneMissing() { + $this->providerRegistry->expects($this->once()) + ->method('getProviderStates') + ->with($this->user) + ->willReturn([ + $this->fakeProvider->getId() => true, + ]); + $this->providerLoader->expects($this->once()) + ->method('getProviders') + ->with($this->user) + ->willReturn([]); + $expectedProviders = [ + 'email' => $this->fakeProvider, + ]; + + $providerSet = $this->manager->getProviderSet($this->user); + + $this->assertTrue($providerSet->isProviderMissing()); } public function testVerifyChallenge() { @@ -266,7 +244,6 @@ class ManagerTest extends TestCase { ->method('verifyChallenge') ->with($this->user, $challenge) ->will($this->returnValue(true)); - $this->session->expects($this->once()) ->method('get') ->with('two_factor_remember_login') @@ -282,15 +259,12 @@ class ManagerTest extends TestCase { ->with(Manager::SESSION_UID_DONE, 'jos'); $this->session->method('getId') ->willReturn('mysessionid'); - $this->activityManager->expects($this->once()) ->method('generateEvent') ->willReturn($event); - $this->user->expects($this->any()) ->method('getUID') ->willReturn('jos'); - $event->expects($this->once()) ->method('setApp') ->with($this->equalTo('core')) @@ -316,19 +290,19 @@ class ManagerTest extends TestCase { 'provider' => 'Fake 2FA', ])) ->willReturnSelf(); - $token = $this->createMock(OC\Authentication\Token\IToken::class); $this->tokenProvider->method('getToken') ->with('mysessionid') ->willReturn($token); $token->method('getId') ->willReturn(42); - $this->config->expects($this->once()) ->method('deleteUserValue') ->with('jos', 'login_token_2fa', 42); - $this->assertTrue($this->manager->verifyChallenge('email', $this->user, $challenge)); + $result = $this->manager->verifyChallenge('email', $this->user, $challenge); + + $this->assertTrue($result); } public function testVerifyChallengeInvalidProviderId() { @@ -424,7 +398,8 @@ class ManagerTest extends TestCase { $manager = $this->getMockBuilder(Manager::class) ->setConstructorArgs([ - $this->appManager, + $this->providerLoader, + $this->providerRegistry, $this->session, $this->config, $this->activityManager, @@ -433,7 +408,7 @@ class ManagerTest extends TestCase { $this->timeFactory, $this->eventDispatcher ]) - ->setMethods(['loadTwoFactorApp','isTwoFactorAuthenticated']) // Do not actually load the apps + ->setMethods(['loadTwoFactorApp', 'isTwoFactorAuthenticated'])// Do not actually load the apps ->getMock(); $manager->method('isTwoFactorAuthenticated') @@ -531,7 +506,7 @@ class ManagerTest extends TestCase { ->willReturn('user'); $this->session->method('exists') - ->will($this->returnCallback(function($var) { + ->will($this->returnCallback(function ($var) { if ($var === Manager::SESSION_UID_KEY) { return false; } else if ($var === 'app_password') { diff --git a/tests/lib/Authentication/TwoFactorAuth/ProviderLoaderTest.php b/tests/lib/Authentication/TwoFactorAuth/ProviderLoaderTest.php new file mode 100644 index 00000000000..6479e41fffb --- /dev/null +++ b/tests/lib/Authentication/TwoFactorAuth/ProviderLoaderTest.php @@ -0,0 +1,86 @@ +<?php + +/** + * Created by PhpStorm. + * User: christoph + * Date: 04.06.18 + * Time: 13:29 + */ + +namespace lib\Authentication\TwoFactorAuth; + +use Exception; +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 { + + /** @var IAppManager|PHPUnit_Framework_MockObject_MockObject */ + private $appManager; + + /** @var IUser|PHPUnit_Framework_MockObject_MockObject */ + private $user; + + /** @var ProviderLoader */ + private $loader; + + protected function setUp() { + parent::setUp(); + + $this->appManager = $this->createMock(IAppManager::class); + $this->user = $this->createMock(\OCP\IUser::class); + + $this->loader = new ProviderLoader($this->appManager); + } + + /** + * @expectedException Exception + * @expectedExceptionMessage Could not load two-factor auth provider \OCA\MyFaulty2faApp\DoesNotExist + */ + public function testFailHardIfProviderCanNotBeLoaded() { + $this->appManager->expects($this->once()) + ->method('getEnabledAppsForUser') + ->with($this->user) + ->willReturn(['mail', 'twofactor_totp']); + $this->appManager + ->method('getAppInfo') + ->will($this->returnValueMap([ + ['mail', false, null, []], + ['twofactor_totp', false, null, [ + 'two-factor-providers' => [ + '\\OCA\\MyFaulty2faApp\\DoesNotExist', + ], + ]], + ])); + + $this->loader->getProviders($this->user); + } + + public function testGetProviders() { + $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(['twofactor_test']); + $this->appManager + ->method('getAppInfo') + ->with('twofactor_test') + ->willReturn(['two-factor-providers' => [ + '\\OCA\\TwoFactorTest\\Provider', + ]]); + + $providers = $this->loader->getProviders($this->user); + + $this->assertCount(1, $providers); + $this->assertArrayHasKey('test', $providers); + $this->assertSame($provider, $providers['test']); + } + +} diff --git a/tests/lib/Authentication/TwoFactorAuth/ProviderSetTest.php b/tests/lib/Authentication/TwoFactorAuth/ProviderSetTest.php new file mode 100644 index 00000000000..46191780f81 --- /dev/null +++ b/tests/lib/Authentication/TwoFactorAuth/ProviderSetTest.php @@ -0,0 +1,74 @@ +<?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 Test\Authentication\TwoFactorAuth; + +use OC\Authentication\TwoFactorAuth\ProviderSet; +use OCP\Authentication\TwoFactorAuth\IProvider; +use Test\TestCase; + +class ProviderSetTest extends TestCase { + + /** @var ProviderSet */ + private $providerSet; + + public function testIndexesProviders() { + $p1 = $this->createMock(IProvider::class); + $p1->method('getId')->willReturn('p1'); + $p2 = $this->createMock(IProvider::class); + $p2->method('getId')->willReturn('p2'); + $expected = [ + 'p1' => $p1, + 'p2' => $p2, + ]; + + $set = new ProviderSet([$p2, $p1], false); + + $this->assertEquals($expected, $set->getProviders()); + } + + public function testGetProvider() { + $p1 = $this->createMock(IProvider::class); + $p1->method('getId')->willReturn('p1'); + + $set = new ProviderSet([$p1], false); + $provider = $set->getProvider('p1'); + + $this->assertEquals($p1, $provider); + } + + public function testGetProviderNotFound() { + $set = new ProviderSet([], false); + $provider = $set->getProvider('p1'); + + $this->assertNull($provider); + } + + public function testIsProviderMissing() { + $set = new ProviderSet([], true); + + $this->assertTrue($set->isProviderMissing()); + } + +} diff --git a/tests/lib/Authentication/TwoFactorAuth/RegistryTest.php b/tests/lib/Authentication/TwoFactorAuth/RegistryTest.php new file mode 100644 index 00000000000..71f104ca429 --- /dev/null +++ b/tests/lib/Authentication/TwoFactorAuth/RegistryTest.php @@ -0,0 +1,85 @@ +<?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 Test\Authentication\TwoFactorAuth; + +use OC\Authentication\TwoFactorAuth\Db\ProviderUserAssignmentDao; +use OC\Authentication\TwoFactorAuth\Registry; +use OCP\Authentication\TwoFactorAuth\IProvider; +use OCP\IUser; +use PHPUnit_Framework_MockObject_MockObject; +use Test\TestCase; + +class RegistryTest extends TestCase { + + /** @var ProviderUserAssignmentDao|PHPUnit_Framework_MockObject_MockObject */ + private $dao; + + /** @var Registry */ + private $registry; + + protected function setUp() { + parent::setUp(); + + $this->dao = $this->createMock(ProviderUserAssignmentDao::class); + + $this->registry = new Registry($this->dao); + } + + public function testGetProviderStates() { + $user = $this->createMock(IUser::class); + $user->expects($this->once())->method('getUID')->willReturn('user123'); + $state = [ + 'twofactor_totp' => true, + ]; + $this->dao->expects($this->once())->method('getState')->willReturn($state); + + $actual = $this->registry->getProviderStates($user); + + $this->assertEquals($state, $actual); + } + + public function testEnableProvider() { + $user = $this->createMock(IUser::class); + $provider = $this->createMock(IProvider::class); + $user->expects($this->once())->method('getUID')->willReturn('user123'); + $provider->expects($this->once())->method('getId')->willReturn('p1'); + $this->dao->expects($this->once())->method('persist')->with('p1', 'user123', + true); + + $this->registry->enableProviderFor($provider, $user); + } + + public function testDisableProvider() { + $user = $this->createMock(IUser::class); + $provider = $this->createMock(IProvider::class); + $user->expects($this->once())->method('getUID')->willReturn('user123'); + $provider->expects($this->once())->method('getId')->willReturn('p1'); + $this->dao->expects($this->once())->method('persist')->with('p1', 'user123', + false); + + $this->registry->disableProviderFor($provider, $user); + } + +} |