diff --git a/apps/oauth2/lib/Db/AccessTokenMapper.php b/apps/oauth2/lib/Db/AccessTokenMapper.php index 51b97bf8d7..2661c85337 100644 --- a/apps/oauth2/lib/Db/AccessTokenMapper.php +++ b/apps/oauth2/lib/Db/AccessTokenMapper.php @@ -21,6 +21,7 @@ namespace OCA\OAuth2\Db; +use OCA\OAuth2\Exceptions\AccessTokenNotFoundException; use OCP\AppFramework\Db\Mapper; use OCP\DB\QueryBuilder\IQueryBuilder; use OCP\IDBConnection; @@ -37,6 +38,7 @@ class AccessTokenMapper extends Mapper { /** * @param string $code * @return AccessToken + * @throws AccessTokenNotFoundException */ public function getByCode($code) { $qb = $this->db->getQueryBuilder(); @@ -47,6 +49,9 @@ class AccessTokenMapper extends Mapper { $result = $qb->execute(); $row = $result->fetch(); $result->closeCursor(); + if($row === false) { + throw new AccessTokenNotFoundException(); + } return AccessToken::fromRow($row); } diff --git a/apps/oauth2/lib/Db/ClientMapper.php b/apps/oauth2/lib/Db/ClientMapper.php index cf00afacb7..9df07e2789 100644 --- a/apps/oauth2/lib/Db/ClientMapper.php +++ b/apps/oauth2/lib/Db/ClientMapper.php @@ -21,6 +21,7 @@ namespace OCA\OAuth2\Db; +use OCA\OAuth2\Exceptions\ClientNotFoundException; use OCP\AppFramework\Db\Mapper; use OCP\DB\QueryBuilder\IQueryBuilder; use OCP\IDBConnection; @@ -37,6 +38,7 @@ class ClientMapper extends Mapper { /** * @param string $clientIdentifier * @return Client + * @throws ClientNotFoundException */ public function getByIdentifier($clientIdentifier) { $qb = $this->db->getQueryBuilder(); @@ -47,17 +49,16 @@ class ClientMapper extends Mapper { $result = $qb->execute(); $row = $result->fetch(); $result->closeCursor(); - - if (!is_array($row)) { - $row = []; + if($row === false) { + throw new ClientNotFoundException(); } - return Client::fromRow($row); } /** * @param string $uid internal uid of the client * @return Client + * @throws ClientNotFoundException */ public function getByUid($uid) { $qb = $this->db->getQueryBuilder(); @@ -68,11 +69,9 @@ class ClientMapper extends Mapper { $result = $qb->execute(); $row = $result->fetch(); $result->closeCursor(); - - if (!is_array($row)) { - $row = []; + if($row === false) { + throw new ClientNotFoundException(); } - return Client::fromRow($row); } diff --git a/apps/oauth2/tests/Controller/LoginRedirectorControllerTest.php b/apps/oauth2/tests/Controller/LoginRedirectorControllerTest.php new file mode 100644 index 0000000000..b33d3379be --- /dev/null +++ b/apps/oauth2/tests/Controller/LoginRedirectorControllerTest.php @@ -0,0 +1,91 @@ + + * + * @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 . + * + */ + +namespace OCA\OAuth2\Tests\Controller; + +use OCA\Files_Sharing\Tests\TestCase; +use OCA\OAuth2\Controller\LoginRedirectorController; +use OCA\OAuth2\Db\Client; +use OCA\OAuth2\Db\ClientMapper; +use OCP\AppFramework\Http\RedirectResponse; +use OCP\IRequest; +use OCP\ISession; +use OCP\IURLGenerator; + +/** + * @group DB + */ +class LoginRedirectorControllerTest extends TestCase { + /** @var IRequest|\PHPUnit_Framework_MockObject_MockObject */ + private $request; + /** @var IURLGenerator|\PHPUnit_Framework_MockObject_MockObject */ + private $urlGenerator; + /** @var ClientMapper|\PHPUnit_Framework_MockObject_MockObject */ + private $clientMapper; + /** @var ISession|\PHPUnit_Framework_MockObject_MockObject */ + private $session; + /** @var LoginRedirectorController */ + private $loginRedirectorController; + + public function setUp() { + parent::setUp(); + + $this->request = $this->createMock(IRequest::class); + $this->urlGenerator = $this->createMock(IURLGenerator::class); + $this->clientMapper = $this->createMock(ClientMapper::class); + $this->session = $this->createMock(ISession::class); + + $this->loginRedirectorController = new LoginRedirectorController( + 'oauth2', + $this->request, + $this->urlGenerator, + $this->clientMapper, + $this->session + ); + } + + public function testAuthorize() { + $client = new Client(); + $client->setClientIdentifier('MyClientIdentifier'); + $this->clientMapper + ->expects($this->once()) + ->method('getByIdentifier') + ->with('MyClientId') + ->willReturn($client); + $this->session + ->expects($this->once()) + ->method('set') + ->with('oauth.state', 'MyState'); + $this->urlGenerator + ->expects($this->once()) + ->method('linkToRouteAbsolute') + ->with( + 'core.ClientFlowLogin.showAuthPickerPage', + [ + 'clientIdentifier' => 'MyClientIdentifier', + ] + ) + ->willReturn('https://example.com/?clientIdentifier=foo'); + + $expected = new RedirectResponse('https://example.com/?clientIdentifier=foo'); + $this->assertEquals($expected, $this->loginRedirectorController->authorize('MyClientId', 'MyState')); + } +} diff --git a/apps/oauth2/tests/Controller/OauthApiControllerTest.php b/apps/oauth2/tests/Controller/OauthApiControllerTest.php new file mode 100644 index 0000000000..c90e2bf711 --- /dev/null +++ b/apps/oauth2/tests/Controller/OauthApiControllerTest.php @@ -0,0 +1,106 @@ + + * + * @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 . + * + */ + +namespace OCA\OAuth2\Tests\Controller; + +use OC\Authentication\Token\DefaultToken; +use OC\Authentication\Token\DefaultTokenMapper; +use OCA\OAuth2\Controller\OauthApiController; +use OCA\OAuth2\Db\AccessToken; +use OCA\OAuth2\Db\AccessTokenMapper; +use OCP\AppFramework\Http\JSONResponse; +use OCP\IRequest; +use OCP\Security\ICrypto; +use OCP\Security\ISecureRandom; +use Test\TestCase; + +class OauthApiControllerTest extends TestCase { + /** @var IRequest|\PHPUnit_Framework_MockObject_MockObject */ + private $request; + /** @var ICrypto|\PHPUnit_Framework_MockObject_MockObject */ + private $crypto; + /** @var AccessTokenMapper|\PHPUnit_Framework_MockObject_MockObject */ + private $accessTokenMapper; + /** @var DefaultTokenMapper|\PHPUnit_Framework_MockObject_MockObject */ + private $defaultTokenMapper; + /** @var ISecureRandom|\PHPUnit_Framework_MockObject_MockObject */ + private $secureRandom; + /** @var OauthApiController */ + private $oauthApiController; + + public function setUp() { + parent::setUp(); + + $this->request = $this->createMock(IRequest::class); + $this->crypto = $this->createMock(ICrypto::class); + $this->accessTokenMapper = $this->createMock(AccessTokenMapper::class); + $this->defaultTokenMapper = $this->createMock(DefaultTokenMapper::class); + $this->secureRandom = $this->createMock(ISecureRandom::class); + + $this->oauthApiController = new OauthApiController( + 'oauth2', + $this->request, + $this->crypto, + $this->accessTokenMapper, + $this->defaultTokenMapper, + $this->secureRandom + ); + } + + public function testGetToken() { + $accessToken = new AccessToken(); + $accessToken->setEncryptedToken('MyEncryptedToken'); + $accessToken->setTokenId(123); + $this->accessTokenMapper + ->expects($this->once()) + ->method('getByCode') + ->willReturn($accessToken); + $this->crypto + ->expects($this->once()) + ->method('decrypt') + ->with('MyEncryptedToken', 'MySecretCode') + ->willReturn('MyDecryptedToken'); + $this->secureRandom + ->expects($this->once()) + ->method('generate') + ->with(128) + ->willReturn('NewToken'); + $token = new DefaultToken(); + $token->setUid('JohnDoe'); + $this->defaultTokenMapper + ->expects($this->once()) + ->method('getTokenById') + ->with(123) + ->willReturn($token); + + $expected = new JSONResponse( + [ + 'access_token' => 'MyDecryptedToken', + 'token_type' => 'Bearer', + 'expires_in' => 3600, + 'refresh_token' => 'NewToken', + 'user_id' => 'JohnDoe', + ] + ); + $this->assertEquals($expected, $this->oauthApiController->getToken('MySecretCode')); + } + +} diff --git a/apps/oauth2/tests/Controller/SettingsControllerTest.php b/apps/oauth2/tests/Controller/SettingsControllerTest.php new file mode 100644 index 0000000000..a6c036949e --- /dev/null +++ b/apps/oauth2/tests/Controller/SettingsControllerTest.php @@ -0,0 +1,139 @@ + + * + * @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 . + * + */ + +namespace OCA\OAuth2\Tests\Controller; + +use OC\Authentication\Token\DefaultTokenMapper; +use OCA\OAuth2\Controller\SettingsController; +use OCA\OAuth2\Db\AccessTokenMapper; +use OCA\OAuth2\Db\Client; +use OCA\OAuth2\Db\ClientMapper; +use OCP\AppFramework\Http\RedirectResponse; +use OCP\IRequest; +use OCP\IURLGenerator; +use OCP\Security\ISecureRandom; +use Test\TestCase; + +class SettingsControllerTest extends TestCase { + /** @var IRequest|\PHPUnit_Framework_MockObject_MockObject */ + private $request; + /** @var IURLGenerator|\PHPUnit_Framework_MockObject_MockObject */ + private $urlGenerator; + /** @var ClientMapper|\PHPUnit_Framework_MockObject_MockObject */ + private $clientMapper; + /** @var ISecureRandom|\PHPUnit_Framework_MockObject_MockObject */ + private $secureRandom; + /** @var AccessTokenMapper|\PHPUnit_Framework_MockObject_MockObject */ + private $accessTokenMapper; + /** @var DefaultTokenMapper|\PHPUnit_Framework_MockObject_MockObject */ + private $defaultTokenMapper; + /** @var SettingsController */ + private $settingsController; + + public function setUp() { + parent::setUp(); + + $this->request = $this->createMock(IRequest::class); + $this->urlGenerator = $this->createMock(IURLGenerator::class); + $this->clientMapper = $this->createMock(ClientMapper::class); + $this->secureRandom = $this->createMock(ISecureRandom::class); + $this->accessTokenMapper = $this->createMock(AccessTokenMapper::class); + $this->defaultTokenMapper = $this->createMock(DefaultTokenMapper::class); + + $this->settingsController = new SettingsController( + 'oauth2', + $this->request, + $this->urlGenerator, + $this->clientMapper, + $this->secureRandom, + $this->accessTokenMapper, + $this->defaultTokenMapper + ); + } + + public function testAddClient() { + $this->secureRandom + ->expects($this->at(0)) + ->method('generate') + ->with(64, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789') + ->willReturn('MySecret'); + $this->secureRandom + ->expects($this->at(1)) + ->method('generate') + ->with(64, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789') + ->willReturn('MyClientIdentifier'); + + $client = new Client(); + $client->setName('My Client Name'); + $client->setRedirectUri('https://example.com/'); + $client->setSecret('MySecret'); + $client->setClientIdentifier('MyClientIdentifier'); + + $this->clientMapper + ->expects($this->once()) + ->method('insert') + ->with($client); + + $this->urlGenerator + ->expects($this->once()) + ->method('getAbsoluteURL') + ->with('/index.php/settings/admin/security') + ->willReturn('https://example.com/index.php/settings/admin/security'); + + $expected = new RedirectResponse('https://example.com/index.php/settings/admin/security'); + $this->assertEquals($expected, $this->settingsController->addClient('My Client Name', 'https://example.com/')); + } + + public function testDeleteClient() { + $client = new Client(); + $client->setName('My Client Name'); + $client->setRedirectUri('https://example.com/'); + $client->setSecret('MySecret'); + $client->setClientIdentifier('MyClientIdentifier'); + + $this->clientMapper + ->expects($this->at(0)) + ->method('getByUid') + ->with(123) + ->willReturn($client); + $this->accessTokenMapper + ->expects($this->once()) + ->method('deleteByClientId') + ->with(123); + $this->defaultTokenMapper + ->expects($this->once()) + ->method('deleteByName') + ->with('My Client Name'); + $this->clientMapper + ->expects($this->at(1)) + ->method('delete') + ->with($client); + + $this->urlGenerator + ->expects($this->once()) + ->method('getAbsoluteURL') + ->with('/index.php/settings/admin/security') + ->willReturn('https://example.com/index.php/settings/admin/security'); + + $expected = new RedirectResponse('https://example.com/index.php/settings/admin/security'); + $this->assertEquals($expected, $this->settingsController->deleteClient(123)); + } +} diff --git a/apps/oauth2/tests/Db/AccessTokenMapperTest.php b/apps/oauth2/tests/Db/AccessTokenMapperTest.php new file mode 100644 index 0000000000..58b36b1c24 --- /dev/null +++ b/apps/oauth2/tests/Db/AccessTokenMapperTest.php @@ -0,0 +1,69 @@ + + * + * @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 . + * + */ + +namespace OCA\OAuth2\Tests\Db; + +use OCA\OAuth2\Db\AccessToken; +use OCA\OAuth2\Db\AccessTokenMapper; +use Test\TestCase; + +/** + * @group DB + */ +class AccessTokenMapperTest extends TestCase { + /** @var AccessTokenMapper */ + private $accessTokenMapper; + + public function setUp() { + parent::setUp(); + $this->accessTokenMapper = new AccessTokenMapper(\OC::$server->getDatabaseConnection()); + } + + public function testGetByCode() { + $this->accessTokenMapper->deleteByClientId(1234); + $token = new AccessToken(); + $token->setClientId(1234); + $token->setTokenId((string)time()); + $token->setEncryptedToken('MyEncryptedToken'); + $token->setHashedCode(hash('sha512', 'MyAwesomeToken')); + $this->accessTokenMapper->insert($token); + $token->resetUpdatedFields(); + + $result = $this->accessTokenMapper->getByCode('MyAwesomeToken'); + $this->assertEquals($token, $result); + } + + /** + * @expectedException \OCA\OAuth2\Exceptions\AccessTokenNotFoundException + */ + public function testDeleteByClientId() { + $this->accessTokenMapper->deleteByClientId('TestId'); + $token = new AccessToken(); + $token->setClientId(1234); + $token->setTokenId((string)time()); + $token->setEncryptedToken('MyEncryptedToken'); + $token->setHashedCode(hash('sha512', 'MyAwesomeToken')); + $this->accessTokenMapper->insert($token); + $token->resetUpdatedFields(); + $this->accessTokenMapper->deleteByClientId(1234); + $this->accessTokenMapper->getByCode('MyAwesomeToken'); + } +} diff --git a/apps/oauth2/tests/Db/ClientMapperTest.php b/apps/oauth2/tests/Db/ClientMapperTest.php new file mode 100644 index 0000000000..80d69c3b1b --- /dev/null +++ b/apps/oauth2/tests/Db/ClientMapperTest.php @@ -0,0 +1,79 @@ + + * + * @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 . + * + */ + +namespace OCA\OAuth2\Tests\Db; + +use OCA\OAuth2\Db\Client; +use OCA\OAuth2\Db\ClientMapper; +use Test\TestCase; + +/** + * @group DB + */ +class ClientMapperTest extends TestCase { + /** @var ClientMapper */ + private $clientMapper; + + public function setUp() { + parent::setUp(); + $this->clientMapper = new ClientMapper(\OC::$server->getDatabaseConnection()); + } + + public function testGetByIdentifier() { + $client = new Client(); + $client->setClientIdentifier('MyAwesomeClientIdentifier'); + $client->setName('Client Name'); + $client->setRedirectUri('https://example.com/'); + $client->setSecret('TotallyNotSecret'); + $this->clientMapper->insert($client); + $client->resetUpdatedFields(); + $this->assertEquals($client, $this->clientMapper->getByIdentifier('MyAwesomeClientIdentifier')); + } + + /** + * @expectedException \OCA\OAuth2\Exceptions\ClientNotFoundException + */ + public function testGetByIdentifierNotExisting() { + $this->clientMapper->getByIdentifier('MyTotallyNotExistingClient'); + } + + public function testGetByUid() { + $client = new Client(); + $client->setClientIdentifier('MyNewClient'); + $client->setName('Client Name'); + $client->setRedirectUri('https://example.com/'); + $client->setSecret('TotallyNotSecret'); + $this->clientMapper->insert($client); + $client->resetUpdatedFields(); + $this->assertEquals($client, $this->clientMapper->getByUid($client->getId())); + } + + /** + * @expectedException \OCA\OAuth2\Exceptions\ClientNotFoundException + */ + public function testGetByUidNotExisting() { + $this->clientMapper->getByUid(1234); + } + + public function testGetClients() { + $this->assertSame('array', gettype($this->clientMapper->getClients())); + } +} diff --git a/apps/oauth2/tests/Settings/AdminTest.php b/apps/oauth2/tests/Settings/AdminTest.php new file mode 100644 index 0000000000..9c3d5ed144 --- /dev/null +++ b/apps/oauth2/tests/Settings/AdminTest.php @@ -0,0 +1,66 @@ + + * + * @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 . + * + */ + +namespace OCA\OAuth2\Tests\Settings; + +use OCA\OAuth2\Db\ClientMapper; +use OCA\OAuth2\Settings\Admin; +use OCP\AppFramework\Http\TemplateResponse; +use Test\TestCase; + +class AdminTest extends TestCase { + /** @var ClientMapper|\PHPUnit_Framework_MockObject_MockObject */ + private $clientMapper; + /** @var Admin|\PHPUnit_Framework_MockObject_MockObject */ + private $admin; + + public function setUp() { + parent::setUp(); + + $this->clientMapper = $this->createMock(ClientMapper::class); + $this->admin = new Admin($this->clientMapper); + } + + public function testGetForm() { + $this->clientMapper + ->expects($this->once()) + ->method('getClients') + ->willReturn(['MyClients']); + + $expected = new TemplateResponse( + 'oauth2', + 'admin', + [ + 'clients' => ['MyClients'], + ], + '' + ); + $this->assertEquals($expected, $this->admin->getForm()); + } + + public function testGetSection() { + $this->assertSame('security', $this->admin->getSection()); + } + + public function testGetPriority() { + $this->assertSame(0, $this->admin->getPriority()); + } +} diff --git a/tests/phpunit-autotest.xml b/tests/phpunit-autotest.xml index 9a9c9c957e..34166a09e2 100644 --- a/tests/phpunit-autotest.xml +++ b/tests/phpunit-autotest.xml @@ -30,6 +30,7 @@ ../apps/files_sharing/tests ../apps/files_trashbin/tests ../apps/files_versions/tests + ../apps/oauth2/tests ../apps/provisioning_api/tests ../apps/systemtags/tests ../apps/theming/tests