diff --git a/Command/CreateClientCommand.php b/Command/CreateClientCommand.php index 5d4b8208..fbbcad6f 100644 --- a/Command/CreateClientCommand.php +++ b/Command/CreateClientCommand.php @@ -34,23 +34,23 @@ protected function configure() ->addOption( 'redirect-uri', null, - InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY, + InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Sets redirect uri for client. Use this option multiple times to set multiple redirect URIs.', - null + [] ) ->addOption( 'grant-type', null, - InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY, + InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Sets allowed grant type for client. Use this option multiple times to set multiple grant types.', - null + [] ) ->addOption( 'scope', null, - InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY, + InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Sets allowed scope for client. Use this option multiple times to set multiple scopes.', - null + [] ) ->addArgument( 'identifier', @@ -81,7 +81,7 @@ protected function execute(InputInterface $input, OutputInterface $output) return 0; } - private function buildClientFromInput(InputInterface $input) + private function buildClientFromInput(InputInterface $input): Client { $identifier = $input->getArgument('identifier') ?? hash('md5', random_bytes(16)); $secret = $input->getArgument('secret') ?? hash('sha512', random_bytes(32)); @@ -90,19 +90,19 @@ private function buildClientFromInput(InputInterface $input) $client->setActive(true); $redirectUris = array_map( - function (string $redirectUri) { return new RedirectUri($redirectUri); }, + function (string $redirectUri): RedirectUri { return new RedirectUri($redirectUri); }, $input->getOption('redirect-uri') ); $client->setRedirectUris(...$redirectUris); $grants = array_map( - function (string $grant) { return new Grant($grant); }, + function (string $grant): Grant { return new Grant($grant); }, $input->getOption('grant-type') ); $client->setGrants(...$grants); $scopes = array_map( - function (string $scope) { return new Scope($scope); }, + function (string $scope): Scope { return new Scope($scope); }, $input->getOption('scope') ); $client->setScopes(...$scopes); diff --git a/Command/DeleteClientCommand.php b/Command/DeleteClientCommand.php new file mode 100644 index 00000000..257ff773 --- /dev/null +++ b/Command/DeleteClientCommand.php @@ -0,0 +1,50 @@ +clientManager = $clientManager; + } + + protected function configure(): void + { + $this + ->setDescription('Deletes an oAuth2 client') + ->addArgument( + 'identifier', + InputArgument::REQUIRED, + 'The client ID' + ) + ; + } + + protected function execute(InputInterface $input, OutputInterface $output): int + { + $io = new SymfonyStyle($input, $output); + $identifier = $input->getArgument('identifier'); + $client = $this->clientManager->find($identifier); + if (null === $client) { + $io->error(sprintf('oAuth2 client identified as "%s" does not exist', $identifier)); + + return 1; + } + $this->clientManager->remove($client); + $io->success('Given oAuth2 client deleted successfully.'); + + return 0; + } +} diff --git a/Command/ListClientsCommand.php b/Command/ListClientsCommand.php new file mode 100644 index 00000000..ae45b1dc --- /dev/null +++ b/Command/ListClientsCommand.php @@ -0,0 +1,127 @@ +clientManager = $clientManager; + } + + protected function configure(): void + { + $this + ->setDescription('Lists existing oAuth2 clients') + ->addOption( + 'columns', + null, + InputOption::VALUE_IS_ARRAY | InputOption::VALUE_REQUIRED, + 'Determine which columns are shown. Can be used multiple times to specify multiple columns.', + self::ALLOWED_COLUMNS + ) + ->addOption( + 'redirect-uri', + null, + InputOption::VALUE_IS_ARRAY | InputOption::VALUE_REQUIRED, + 'Finds by redirect uri for client. Use this option multiple times to filter by multiple redirect URIs.', + [] + ) + ->addOption( + 'grant-type', + null, + InputOption::VALUE_IS_ARRAY | InputOption::VALUE_REQUIRED, + 'Finds by allowed grant type for client. Use this option multiple times to filter by multiple grant types.', + [] + ) + ->addOption( + 'scope', + null, + InputOption::VALUE_IS_ARRAY | InputOption::VALUE_REQUIRED, + 'Finds by allowed scope for client. Use this option multiple times to find by multiple scopes.', + [] + ) + ; + } + + protected function execute(InputInterface $input, OutputInterface $output): int + { + $criteria = $this->getFindByCriteria($input); + $clients = $this->clientManager->list($criteria); + $this->drawTable($input, $output, $clients); + + return 0; + } + + private function getFindByCriteria(InputInterface $input): ClientFilter + { + return + ClientFilter + ::create() + ->addGrantCriteria(...array_map(function (string $grant): Grant { + return new Grant($grant); + }, $input->getOption('grant-type'))) + ->addRedirectUriCriteria(...array_map(function (string $redirectUri): RedirectUri { + return new RedirectUri($redirectUri); + }, $input->getOption('redirect-uri'))) + ->addScopeCriteria(...array_map(function (string $scope): Scope { + return new Scope($scope); + }, $input->getOption('scope'))) + ; + } + + private function drawTable(InputInterface $input, OutputInterface $output, array $clients): void + { + $io = new SymfonyStyle($input, $output); + $columns = $this->getColumns($input); + $rows = $this->getRows($clients, $columns); + $io->table($columns, $rows); + } + + private function getRows(array $clients, array $columns): array + { + return array_map(function (Client $client) use ($columns): array { + $values = [ + 'identifier' => $client->getIdentifier(), + 'secret' => $client->getSecret(), + 'scope' => implode(', ', $client->getScopes()), + 'redirect uri' => implode(', ', $client->getRedirectUris()), + 'grant type' => implode(', ', $client->getGrants()), + ]; + + return array_map(function (string $column) use ($values): string { + return $values[$column]; + }, $columns); + }, $clients); + } + + private function getColumns(InputInterface $input): array + { + $allowedColumns = self::ALLOWED_COLUMNS; + + $requestedColumns = $input->getOption('columns'); + $requestedColumns = array_map(function (string $column): string { + return strtolower(trim($column)); + }, $requestedColumns); + + return array_intersect($requestedColumns, $allowedColumns); + } +} diff --git a/Command/UpdateClientCommand.php b/Command/UpdateClientCommand.php index fa9908ca..d6f8e278 100644 --- a/Command/UpdateClientCommand.php +++ b/Command/UpdateClientCommand.php @@ -27,30 +27,30 @@ public function __construct(ClientManagerInterface $clientManager) $this->clientManager = $clientManager; } - protected function configure() + protected function configure(): void { $this ->setDescription('Updates an oAuth2 client') ->addOption( 'redirect-uri', null, - InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY, + InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Sets redirect uri for client. Use this option multiple times to set multiple redirect URIs.', - null + [] ) ->addOption( 'grant-type', null, - InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY, + InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Sets allowed grant type for client. Use this option multiple times to set multiple grant types.', - null + [] ) ->addOption( 'scope', null, - InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY, + InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Sets allowed scope for client. Use this option multiple times to set multiple scopes.', - null + [] ) ->addOption( 'deactivated', @@ -66,7 +66,7 @@ protected function configure() ; } - protected function execute(InputInterface $input, OutputInterface $output) + protected function execute(InputInterface $input, OutputInterface $output): int { $io = new SymfonyStyle($input, $output); @@ -88,19 +88,19 @@ private function updateClientFromInput(Client $client, InputInterface $input): C $client->setActive(!$input->getOption('deactivated')); $redirectUris = array_map( - function (string $redirectUri) { return new RedirectUri($redirectUri); }, + function (string $redirectUri): RedirectUri { return new RedirectUri($redirectUri); }, $input->getOption('redirect-uri') ); $client->setRedirectUris(...$redirectUris); $grants = array_map( - function (string $grant) { return new Grant($grant); }, + function (string $grant): Grant { return new Grant($grant); }, $input->getOption('grant-type') ); $client->setGrants(...$grants); $scopes = array_map( - function (string $scope) { return new Scope($scope); }, + function (string $scope): Scope { return new Scope($scope); }, $input->getOption('scope') ); $client->setScopes(...$scopes); diff --git a/Manager/ClientFilter.php b/Manager/ClientFilter.php new file mode 100644 index 00000000..e1ca217e --- /dev/null +++ b/Manager/ClientFilter.php @@ -0,0 +1,86 @@ +addCriteria($this->grants, ...$grants); + } + + public function addRedirectUriCriteria(RedirectUri ...$redirectUris): self + { + return $this->addCriteria($this->redirectUris, ...$redirectUris); + } + + public function addScopeCriteria(Scope ...$scopes): self + { + return $this->addCriteria($this->scopes, ...$scopes); + } + + private function addCriteria(&$field, ...$values): self + { + if (0 === \count($values)) { + return $this; + } + + $field = array_merge($field, $values); + + return $this; + } + + /** + * @return Grant[] + */ + public function getGrants(): array + { + return $this->grants; + } + + /** + * @return RedirectUri[] + */ + public function getRedirectUris(): array + { + return $this->redirectUris; + } + + /** + * @return Scope[] + */ + public function getScopes(): array + { + return $this->scopes; + } + + public function hasFilters(): bool + { + return + !empty($this->grants) + || !empty($this->redirectUris) + || !empty($this->scopes); + } +} diff --git a/Manager/ClientManagerInterface.php b/Manager/ClientManagerInterface.php index cb12f490..4560e45e 100644 --- a/Manager/ClientManagerInterface.php +++ b/Manager/ClientManagerInterface.php @@ -9,4 +9,11 @@ interface ClientManagerInterface public function find(string $identifier): ?Client; public function save(Client $client): void; + + public function remove(Client $client): void; + + /** + * @return Client[] + */ + public function list(?ClientFilter $clientFilter): array; } diff --git a/Manager/Doctrine/ClientManager.php b/Manager/Doctrine/ClientManager.php index 19d16add..70e13d20 100644 --- a/Manager/Doctrine/ClientManager.php +++ b/Manager/Doctrine/ClientManager.php @@ -3,6 +3,7 @@ namespace Trikoder\Bundle\OAuth2Bundle\Manager\Doctrine; use Doctrine\ORM\EntityManagerInterface; +use Trikoder\Bundle\OAuth2Bundle\Manager\ClientFilter; use Trikoder\Bundle\OAuth2Bundle\Manager\ClientManagerInterface; use Trikoder\Bundle\OAuth2Bundle\Model\Client; @@ -34,4 +35,50 @@ public function save(Client $client): void $this->entityManager->persist($client); $this->entityManager->flush(); } + + /** + * {@inheritdoc} + */ + public function remove(Client $client): void + { + $this->entityManager->remove($client); + $this->entityManager->flush(); + } + + /** + * {@inheritdoc} + */ + public function list(?ClientFilter $clientFilter): array + { + $repository = $this->entityManager->getRepository(Client::class); + $criteria = self::filterToCriteria($clientFilter); + + return $repository->findBy($criteria); + } + + private static function filterToCriteria(?ClientFilter $clientFilter): array + { + if (null === $clientFilter || false === $clientFilter->hasFilters()) { + return []; + } + + $criteria = []; + + $grants = $clientFilter->getGrants(); + if ($grants) { + $criteria['grants'] = $grants; + } + + $redirectUris = $clientFilter->getRedirectUris(); + if ($redirectUris) { + $criteria['redirect_uris'] = $redirectUris; + } + + $scopes = $clientFilter->getScopes(); + if ($scopes) { + $criteria['scopes'] = $scopes; + } + + return $criteria; + } } diff --git a/Manager/InMemory/ClientManager.php b/Manager/InMemory/ClientManager.php index 4d6d765c..70e85cd6 100644 --- a/Manager/InMemory/ClientManager.php +++ b/Manager/InMemory/ClientManager.php @@ -2,6 +2,7 @@ namespace Trikoder\Bundle\OAuth2Bundle\Manager\InMemory; +use Trikoder\Bundle\OAuth2Bundle\Manager\ClientFilter; use Trikoder\Bundle\OAuth2Bundle\Manager\ClientManagerInterface; use Trikoder\Bundle\OAuth2Bundle\Model\Client; @@ -27,4 +28,44 @@ public function save(Client $client): void { $this->clients[$client->getIdentifier()] = $client; } + + /** + * {@inheritdoc} + */ + public function remove(Client $client): void + { + unset($this->clients[$client->getIdentifier()]); + } + + /** + * {@inheritdoc} + */ + public function list(?ClientFilter $clientFilter): array + { + if (!$clientFilter || !$clientFilter->hasFilters()) { + return $this->clients; + } + + return array_filter($this->clients, function (Client $client) use ($clientFilter) { + $grantsPassed = self::passesFilter($client->getGrants(), $clientFilter->getGrants()); + $scopesPassed = self::passesFilter($client->getScopes(), $clientFilter->getScopes()); + $redirectUrisPassed = self::passesFilter($client->getRedirectUris(), $clientFilter->getRedirectUris()); + + return $grantsPassed && $scopesPassed && $redirectUrisPassed; + }); + } + + private static function passesFilter(array $clientValues, array $filterValues): bool + { + if (empty($filterValues)) { + return true; + } + + $clientValues = array_map('strval', $clientValues); + $filterValues = array_map('strval', $filterValues); + + $valuesPassed = array_intersect($filterValues, $clientValues); + + return \count($valuesPassed) > 0; + } } diff --git a/Resources/config/services.xml b/Resources/config/services.xml index edfc68a3..7e50064c 100644 --- a/Resources/config/services.xml +++ b/Resources/config/services.xml @@ -82,6 +82,14 @@ + + + + + + + + diff --git a/Tests/Acceptance/AbstractAcceptanceTest.php b/Tests/Acceptance/AbstractAcceptanceTest.php index e7dcd426..994dc2a4 100644 --- a/Tests/Acceptance/AbstractAcceptanceTest.php +++ b/Tests/Acceptance/AbstractAcceptanceTest.php @@ -5,11 +5,6 @@ use Symfony\Bundle\FrameworkBundle\Client; use Symfony\Bundle\FrameworkBundle\Console\Application; use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; -use Trikoder\Bundle\OAuth2Bundle\Manager\AccessTokenManagerInterface; -use Trikoder\Bundle\OAuth2Bundle\Manager\ClientManagerInterface; -use Trikoder\Bundle\OAuth2Bundle\Manager\RefreshTokenManagerInterface; -use Trikoder\Bundle\OAuth2Bundle\Manager\ScopeManagerInterface; -use Trikoder\Bundle\OAuth2Bundle\Tests\Fixtures\FixtureFactory; use Trikoder\Bundle\OAuth2Bundle\Tests\TestHelper; abstract class AbstractAcceptanceTest extends WebTestCase @@ -31,12 +26,5 @@ protected function setUp() $this->application = new Application($this->client->getKernel()); TestHelper::initializeDoctrineSchema($this->application); - - FixtureFactory::initializeFixtures( - $this->client->getContainer()->get(ScopeManagerInterface::class), - $this->client->getContainer()->get(ClientManagerInterface::class), - $this->client->getContainer()->get(AccessTokenManagerInterface::class), - $this->client->getContainer()->get(RefreshTokenManagerInterface::class) - ); } } diff --git a/Tests/Acceptance/CreateClientCommandTest.php b/Tests/Acceptance/CreateClientCommandTest.php index fa863d6b..d34e2008 100644 --- a/Tests/Acceptance/CreateClientCommandTest.php +++ b/Tests/Acceptance/CreateClientCommandTest.php @@ -8,7 +8,7 @@ final class CreateClientCommandTest extends AbstractAcceptanceTest { - public function testCreateClient() + public function testCreateClient(): void { $command = $this->application->find('trikoder:oauth2:create-client'); $commandTester = new CommandTester($command); @@ -20,7 +20,7 @@ public function testCreateClient() $this->assertContains('New oAuth2 client created successfully', $output); } - public function testCreateClientWithIdentifier() + public function testCreateClientWithIdentifier(): void { $command = $this->application->find('trikoder:oauth2:create-client'); $commandTester = new CommandTester($command); @@ -40,7 +40,7 @@ public function testCreateClientWithIdentifier() $this->assertInstanceOf(Client::class, $client); } - public function testCreateClientWithSecret() + public function testCreateClientWithSecret(): void { $command = $this->application->find('trikoder:oauth2:create-client'); $commandTester = new CommandTester($command); @@ -60,7 +60,7 @@ public function testCreateClientWithSecret() $this->assertSame('quzbaz', $client->getSecret()); } - public function testCreateClientWithRedirectUris() + public function testCreateClientWithRedirectUris(): void { $command = $this->application->find('trikoder:oauth2:create-client'); $commandTester = new CommandTester($command); @@ -80,7 +80,7 @@ public function testCreateClientWithRedirectUris() $this->assertCount(2, $client->getRedirectUris()); } - public function testCreateClientWithGrantTypes() + public function testCreateClientWithGrantTypes(): void { $command = $this->application->find('trikoder:oauth2:create-client'); $commandTester = new CommandTester($command); @@ -100,7 +100,7 @@ public function testCreateClientWithGrantTypes() $this->assertCount(2, $client->getGrants()); } - public function testCreateClientWithScopes() + public function testCreateClientWithScopes(): void { $command = $this->application->find('trikoder:oauth2:create-client'); $commandTester = new CommandTester($command); diff --git a/Tests/Acceptance/DeleteClientCommandTest.php b/Tests/Acceptance/DeleteClientCommandTest.php new file mode 100644 index 00000000..d067a8cd --- /dev/null +++ b/Tests/Acceptance/DeleteClientCommandTest.php @@ -0,0 +1,71 @@ +fakeAClient('foobar'); + $this->getClientManager()->save($client); + + $command = $this->command(); + $commandTester = new CommandTester($command); + $commandTester->execute([ + 'command' => $command->getName(), + 'identifier' => $client->getIdentifier(), + ]); + $output = $commandTester->getDisplay(); + $this->assertContains('Given oAuth2 client deleted successfully', $output); + + $client = $this->getClient($client->getIdentifier()); + $this->assertNull($client); + } + + public function testDeleteNonExistentClient(): void + { + $identifierName = 'invalid identifier'; + $command = $this->command(); + $commandTester = new CommandTester($command); + $commandTester->execute([ + 'command' => $command->getName(), + 'identifier' => $identifierName, + ]); + $output = $commandTester->getDisplay(); + $this->assertContains(sprintf('oAuth2 client identified as "%s" does not exist', $identifierName), $output); + } + + private function getClient($identifier): ?Client + { + return + $this + ->client + ->getContainer() + ->get(ClientManagerInterface::class) + ->find($identifier) + ; + } + + private function fakeAClient($identifier): Client + { + return new Client($identifier, 'quzbaz'); + } + + private function getClientManager(): ClientManagerInterface + { + return $this->client + ->getContainer() + ->get(ClientManagerInterface::class) + ; + } + + private function command(): Command + { + return $this->application->find('trikoder:oauth2:delete-client'); + } +} diff --git a/Tests/Acceptance/ListClientsCommandTest.php b/Tests/Acceptance/ListClientsCommandTest.php new file mode 100644 index 00000000..2f9b6b24 --- /dev/null +++ b/Tests/Acceptance/ListClientsCommandTest.php @@ -0,0 +1,141 @@ +fakeAClient('foobar'); + $this->getClientManager()->save($client); + + $command = $this->command(); + $commandTester = new CommandTester($command); + $commandTester->execute([ + 'command' => $command->getName(), + ]); + $output = $commandTester->getDisplay(); + $expected = <<assertEquals(trim($expected), trim($output)); + } + + public function testListClientsEmpty(): void + { + $command = $this->command(); + $commandTester = new CommandTester($command); + $commandTester->execute([ + 'command' => $command->getName(), + ]); + $output = $commandTester->getDisplay(); + $expected = <<
assertEquals(trim($expected), trim($output)); + } + + public function testListClientColumns(): void + { + $scopes = [ + new Scope('client-scope-1'), + new Scope('client-scope-2'), + ]; + + $redirectUris = [ + new RedirectUri('http://client-redirect-url'), + ]; + + $client = + $this + ->fakeAClient('foobar') + ->setScopes(...$scopes) + ->setRedirectUris(...$redirectUris) + ; + $this->getClientManager()->save($client); + + $command = $this->command(); + $commandTester = new CommandTester($command); + $commandTester->execute([ + 'command' => $command->getName(), + '--columns' => ['identifier', 'scope'], + ]); + $output = $commandTester->getDisplay(); + + $expected = <<
assertEquals(trim($expected), trim($output)); + } + + public function testListFiltersClients(): void + { + $clientA = $this->fakeAClient('client-a', 'client-a-secret'); + $this->getClientManager()->save($clientA); + + $clientB = + $this + ->fakeAClient('client-b', 'client-b-secret') + ->setScopes(new Scope('client-b-scope')) + ; + $this->getClientManager()->save($clientB); + + $command = $this->command(); + $commandTester = new CommandTester($command); + $commandTester->execute([ + 'command' => $command->getName(), + '--scope' => $clientB->getScopes(), + ]); + $output = $commandTester->getDisplay(); + + $expected = <<
assertEquals(trim($expected), trim($output)); + } + + private function fakeAClient($identifier, $secret = 'quzbaz'): Client + { + return new Client($identifier, $secret); + } + + private function getClientManager(): ClientManagerInterface + { + return + $this + ->client + ->getContainer() + ->get(ClientManagerInterface::class) + ; + } + + private function command(): Command + { + return $this->application->find('trikoder:oauth2:list-clients'); + } +} diff --git a/Tests/Acceptance/SecurityLayerTest.php b/Tests/Acceptance/SecurityLayerTest.php index 3d925c5b..13f0638d 100644 --- a/Tests/Acceptance/SecurityLayerTest.php +++ b/Tests/Acceptance/SecurityLayerTest.php @@ -3,11 +3,26 @@ namespace Trikoder\Bundle\OAuth2Bundle\Tests\Acceptance; use Trikoder\Bundle\OAuth2Bundle\Manager\AccessTokenManagerInterface; +use Trikoder\Bundle\OAuth2Bundle\Manager\ClientManagerInterface; +use Trikoder\Bundle\OAuth2Bundle\Manager\RefreshTokenManagerInterface; +use Trikoder\Bundle\OAuth2Bundle\Manager\ScopeManagerInterface; use Trikoder\Bundle\OAuth2Bundle\Tests\Fixtures\FixtureFactory; use Trikoder\Bundle\OAuth2Bundle\Tests\TestHelper; final class SecurityLayerTest extends AbstractAcceptanceTest { + protected function setUp() + { + parent::setUp(); + + FixtureFactory::initializeFixtures( + $this->client->getContainer()->get(ScopeManagerInterface::class), + $this->client->getContainer()->get(ClientManagerInterface::class), + $this->client->getContainer()->get(AccessTokenManagerInterface::class), + $this->client->getContainer()->get(RefreshTokenManagerInterface::class) + ); + } + public function testAuthenticatedGuestRequest() { $accessToken = $this->client diff --git a/Tests/Acceptance/TokenEndpointTest.php b/Tests/Acceptance/TokenEndpointTest.php index 4b90a682..94b85f24 100644 --- a/Tests/Acceptance/TokenEndpointTest.php +++ b/Tests/Acceptance/TokenEndpointTest.php @@ -4,12 +4,27 @@ use DateTime; use Trikoder\Bundle\OAuth2Bundle\Event\UserResolveEvent; +use Trikoder\Bundle\OAuth2Bundle\Manager\AccessTokenManagerInterface; +use Trikoder\Bundle\OAuth2Bundle\Manager\ClientManagerInterface; use Trikoder\Bundle\OAuth2Bundle\Manager\RefreshTokenManagerInterface; +use Trikoder\Bundle\OAuth2Bundle\Manager\ScopeManagerInterface; use Trikoder\Bundle\OAuth2Bundle\Tests\Fixtures\FixtureFactory; use Trikoder\Bundle\OAuth2Bundle\Tests\TestHelper; final class TokenEndpointTest extends AbstractAcceptanceTest { + protected function setUp() + { + parent::setUp(); + + FixtureFactory::initializeFixtures( + $this->client->getContainer()->get(ScopeManagerInterface::class), + $this->client->getContainer()->get(ClientManagerInterface::class), + $this->client->getContainer()->get(AccessTokenManagerInterface::class), + $this->client->getContainer()->get(RefreshTokenManagerInterface::class) + ); + } + public function testSuccessfulClientCredentialsRequest() { timecop_freeze(new DateTime()); diff --git a/Tests/Acceptance/UpdateClientCommandTest.php b/Tests/Acceptance/UpdateClientCommandTest.php index 0b769d24..181c90a1 100644 --- a/Tests/Acceptance/UpdateClientCommandTest.php +++ b/Tests/Acceptance/UpdateClientCommandTest.php @@ -8,7 +8,7 @@ final class UpdateClientCommandTest extends AbstractAcceptanceTest { - public function testUpdateRedirectUris() + public function testUpdateRedirectUris(): void { $client = $this->fakeAClient('foobar'); $this->getClientManager()->save($client); @@ -26,7 +26,7 @@ public function testUpdateRedirectUris() $this->assertCount(2, $client->getRedirectUris()); } - public function testUpdateGrantTypes() + public function testUpdateGrantTypes(): void { $client = $this->fakeAClient('foobar'); $this->getClientManager()->save($client); @@ -44,7 +44,7 @@ public function testUpdateGrantTypes() $this->assertCount(2, $client->getGrants()); } - public function testUpdateScopes() + public function testUpdateScopes(): void { $client = $this->fakeAClient('foobar'); $this->getClientManager()->save($client); @@ -62,7 +62,7 @@ public function testUpdateScopes() $this->assertCount(2, $client->getScopes()); } - public function testDeactivate() + public function testDeactivate(): void { $client = $this->fakeAClient('foobar'); $this->getClientManager()->save($client); diff --git a/Tests/Integration/AbstractIntegrationTest.php b/Tests/Integration/AbstractIntegrationTest.php index c889cc44..f7609c1d 100644 --- a/Tests/Integration/AbstractIntegrationTest.php +++ b/Tests/Integration/AbstractIntegrationTest.php @@ -37,7 +37,6 @@ use Trikoder\Bundle\OAuth2Bundle\Manager\ScopeManagerInterface; use Trikoder\Bundle\OAuth2Bundle\Model\AccessToken; use Trikoder\Bundle\OAuth2Bundle\Model\RefreshToken; -use Trikoder\Bundle\OAuth2Bundle\Tests\Fixtures\FixtureFactory; use Trikoder\Bundle\OAuth2Bundle\Tests\TestHelper; abstract class AbstractIntegrationTest extends TestCase @@ -93,13 +92,6 @@ protected function setUp() $this->refreshTokenManager = new RefreshTokenManager(); $this->eventDispatcher = new EventDispatcher(); - FixtureFactory::initializeFixtures( - $this->scopeManager, - $this->clientManager, - $this->accessTokenManager, - $this->refreshTokenManager - ); - $scopeConverter = new ScopeConverter(); $scopeRepository = new ScopeRepository($this->scopeManager, $this->clientManager, $scopeConverter, $this->eventDispatcher); $clientRepository = new ClientRepository($this->clientManager); diff --git a/Tests/Integration/AuthorizationServerTest.php b/Tests/Integration/AuthorizationServerTest.php index 4ddebce9..f68e8192 100644 --- a/Tests/Integration/AuthorizationServerTest.php +++ b/Tests/Integration/AuthorizationServerTest.php @@ -11,6 +11,18 @@ final class AuthorizationServerTest extends AbstractIntegrationTest { + protected function setUp() + { + parent::setUp(); + + FixtureFactory::initializeFixtures( + $this->scopeManager, + $this->clientManager, + $this->accessTokenManager, + $this->refreshTokenManager + ); + } + public function testSuccessfulAuthorizationThroughHeaders(): void { $request = $this->createAuthorizationRequest('foo:secret', [ diff --git a/Tests/Integration/ResourceServerTest.php b/Tests/Integration/ResourceServerTest.php index 2e7ad719..3beb0edc 100644 --- a/Tests/Integration/ResourceServerTest.php +++ b/Tests/Integration/ResourceServerTest.php @@ -7,6 +7,18 @@ final class ResourceServerTest extends AbstractIntegrationTest { + protected function setUp() + { + parent::setUp(); + + FixtureFactory::initializeFixtures( + $this->scopeManager, + $this->clientManager, + $this->accessTokenManager, + $this->refreshTokenManager + ); + } + public function testValidAccessToken(): void { $existingAccessToken = $this->accessTokenManager->find(FixtureFactory::FIXTURE_ACCESS_TOKEN_PUBLIC); diff --git a/docs/basic-setup.md b/docs/basic-setup.md index a41ea15b..ff7b1bbb 100644 --- a/docs/basic-setup.md +++ b/docs/basic-setup.md @@ -61,10 +61,34 @@ $ bin/console trikoder:oauth2:update-client --scope create --scope read foo ``` ### Delete a client -For now, clients deletion have to be managed manually using SQL queries. +To delete a client you should use the `trikoder:oauth2:delete-client` command. -```sql -DELETE FROM `oauth2_client` WHERE `identifier` = 'foo'; +```sh +Description: + Deletes an oAuth2 client + +Usage: + trikoder:oauth2:delete-client + +Arguments: + identifier The client ID +``` + +### List clients +To list clients you should use the `trikoder:oauth2:list-clients` command. + +```sh +Description: + Lists existing oAuth2 clients + +Usage: + trikoder:oauth2:list-clients [options] + +Options: + --columns[=COLUMNS] Determine which columns are shown. Comma separated list. [default: "identifier, secret, scope, redirect uri, grant type"] + --redirect-uri[=REDIRECT-URI] Finds by redirect uri for client. Use this option multiple times to filter by multiple redirect URIs. (multiple values allowed) + --grant-type[=GRANT-TYPE] Finds by allowed grant type for client. Use this option multiple times to filter by multiple grant types. (multiple values allowed) + --scope[=SCOPE] Finds by allowed scope for client. Use this option multiple times to find by multiple scopes. (multiple values allowed)__ ``` ## Configuring the Security layer