diff --git a/src/Http/Command.php b/src/Http/Command.php index c053f10..c4451b8 100644 --- a/src/Http/Command.php +++ b/src/Http/Command.php @@ -20,6 +20,7 @@ public function __construct( /** @var Representation|Collection|array|null */ private readonly Representation|Collection|array|null $payload = null, private readonly ?Criteria $criteria = null, + private readonly ContentType $contentType = ContentType::JSON, ) {} public function getMethod(): Method @@ -61,4 +62,9 @@ public function getQuery(): string return '?' . http_build_query($this->criteria->jsonSerialize()); } + + public function getContentType(): ContentType + { + return $this->contentType; + } } diff --git a/src/Http/CommandExecutor.php b/src/Http/CommandExecutor.php index baf4159..07e84c3 100644 --- a/src/Http/CommandExecutor.php +++ b/src/Http/CommandExecutor.php @@ -20,29 +20,20 @@ public function __construct( public function executeCommand(Command $command): void { - $payload = $command->getPayload(); - - if (is_array($payload)) { - $this->client->request( - $command->getMethod()->value, - $command->getPath(), - [ - 'form_params' => $payload, + $options = match ($command->getContentType()) { + ContentType::JSON => [ + 'body' => $this->serializer->serialize($command->getPayload()), + 'headers' => [ + 'Content-Type' => $command->getContentType()->value, ], - ); - - return; - } + ], + ContentType::FORM_PARAMS => ['form_params' => $command->getPayload()], + }; $this->client->request( $command->getMethod()->value, $command->getPath(), - [ - 'body' => $this->serializer->serialize($command->getPayload()), - 'headers' => [ - 'Content-Type' => 'application/json', - ], - ], + $options, ); } } diff --git a/src/Http/ContentType.php b/src/Http/ContentType.php new file mode 100644 index 0000000..fdb83e1 --- /dev/null +++ b/src/Http/ContentType.php @@ -0,0 +1,14 @@ + $firstName, 'lastName' => $lastName, ], + contentType: ContentType::FORM_PARAMS, ), ); } diff --git a/src/Resource/Users.php b/src/Resource/Users.php index ee42b99..bd278ac 100644 --- a/src/Resource/Users.php +++ b/src/Resource/Users.php @@ -9,6 +9,7 @@ use Fschmtt\Keycloak\Collection\RoleCollection; use Fschmtt\Keycloak\Collection\UserCollection; use Fschmtt\Keycloak\Http\Command; +use Fschmtt\Keycloak\Http\ContentType; use Fschmtt\Keycloak\Http\Criteria; use Fschmtt\Keycloak\Http\Method; use Fschmtt\Keycloak\Http\Query; diff --git a/tests/Integration/Resource/UsersTest.php b/tests/Integration/Resource/UsersTest.php index a9b4e05..10d95b5 100644 --- a/tests/Integration/Resource/UsersTest.php +++ b/tests/Integration/Resource/UsersTest.php @@ -13,6 +13,7 @@ use Fschmtt\Keycloak\Representation\Role; use Fschmtt\Keycloak\Representation\User; use Fschmtt\Keycloak\Test\Integration\IntegrationTestBehaviour; +use GuzzleHttp\Exception\ServerException; use PHPUnit\Framework\TestCase; use Ramsey\Uuid\Uuid; @@ -189,6 +190,33 @@ public function testGetUserCredentials(): void static::assertNull($user); } + public function testExecuteActionsEmail(): void + { + $users = $this->getKeycloak()->users(); + $username = Uuid::uuid4()->toString(); + + $users->create('master', new User( + email: 'john.doe@example.com', + enabled: true, + username: $username, + )); + + $user = $this->searchUserByUsername($username); + static::assertInstanceOf(User::class, $user); + + try { + $users->executeActionsEmail('master', $user->getId(), ['UPDATE_PASSWORD']); + } catch (ServerException $e) { + static::assertSame(500, $e->getResponse()->getStatusCode()); + static::assertStringContainsString('Failed to send execute actions email', $e->getResponse()->getBody()->getContents()); + } + + $users->delete('master', $user->getId()); + + $user = $this->searchUserByUsername($username); + static::assertNull($user); + } + private function searchUserByUsername(string $username, string $realm = 'master'): ?User { /** @var User|null $user */ diff --git a/tests/Unit/Http/CommandExecutorTest.php b/tests/Unit/Http/CommandExecutorTest.php index 70247e8..13986bb 100644 --- a/tests/Unit/Http/CommandExecutorTest.php +++ b/tests/Unit/Http/CommandExecutorTest.php @@ -7,6 +7,7 @@ use Fschmtt\Keycloak\Http\Client; use Fschmtt\Keycloak\Http\Command; use Fschmtt\Keycloak\Http\CommandExecutor; +use Fschmtt\Keycloak\Http\ContentType; use Fschmtt\Keycloak\Http\Method; use Fschmtt\Keycloak\Json\JsonEncoder; use Fschmtt\Keycloak\Serializer\Serializer; @@ -43,7 +44,7 @@ public function testCallsClientWithoutBodyIfCommandHasNoRepresentation(): void ); } - public function testCallsClientWithBodyIfCommandHasRepresentation(): void + public function testCallsClientWithJsonIfCommandHasRepresentation(): void { $command = new Command( '/path/to/resource', @@ -101,13 +102,14 @@ public function testCallsClientWithBodyIfCommandHasCollection(): void $executor->executeCommand($command); } - public function testCallsClientWithFormParamsIfCommandHasArrayPayload(): void + public function testCallsClientWithFormParamsIfCommandFormParamContentType(): void { $command = new Command( '/path/to/resource', Method::PUT, [], $payload = ['UPDATE_PASSWORD', 'VERIFY_EMAIL'], + contentType: ContentType::FORM_PARAMS, ); $client = $this->createMock(Client::class); diff --git a/tests/Unit/Http/CommandTest.php b/tests/Unit/Http/CommandTest.php index 7bae2ee..8513c6a 100644 --- a/tests/Unit/Http/CommandTest.php +++ b/tests/Unit/Http/CommandTest.php @@ -5,6 +5,7 @@ namespace Fschmtt\Keycloak\Test\Unit\Http; use Fschmtt\Keycloak\Http\Command; +use Fschmtt\Keycloak\Http\ContentType; use Fschmtt\Keycloak\Http\Criteria; use Fschmtt\Keycloak\Http\Method; use Fschmtt\Keycloak\Test\Unit\Stub\Collection; @@ -84,4 +85,18 @@ public function testBuildsPathWithQueryIfCriteriaIsProvided(): void ))->getPath(), ); } + + public function testContentTypeDefaultsToJson(): void + { + $command = new Command('/path', Method::GET); + + static::assertSame(ContentType::JSON, $command->getContentType()); + } + + public function testContentTypeCanBeSetToFormParams(): void + { + $command = new Command('/path', Method::GET, contentType: ContentType::FORM_PARAMS); + + static::assertSame(ContentType::FORM_PARAMS, $command->getContentType()); + } } diff --git a/tests/Unit/Resource/OrganizationsTest.php b/tests/Unit/Resource/OrganizationsTest.php index 82a53a2..4d18ac8 100644 --- a/tests/Unit/Resource/OrganizationsTest.php +++ b/tests/Unit/Resource/OrganizationsTest.php @@ -7,6 +7,7 @@ use Fschmtt\Keycloak\Collection\OrganizationCollection; use Fschmtt\Keycloak\Http\Command; use Fschmtt\Keycloak\Http\CommandExecutor; +use Fschmtt\Keycloak\Http\ContentType; use Fschmtt\Keycloak\Http\Method; use Fschmtt\Keycloak\Http\Query; use Fschmtt\Keycloak\Http\QueryExecutor; @@ -148,6 +149,7 @@ public function testInviteUser(): void 'firstName' => 'first name', 'lastName' => 'last name', ], + contentType: ContentType::FORM_PARAMS, ); $commandExecutor = $this->createMock(CommandExecutor::class); diff --git a/tests/Unit/Resource/UsersTest.php b/tests/Unit/Resource/UsersTest.php index c2ff178..a5f396f 100644 --- a/tests/Unit/Resource/UsersTest.php +++ b/tests/Unit/Resource/UsersTest.php @@ -10,6 +10,7 @@ use Fschmtt\Keycloak\Collection\UserCollection; use Fschmtt\Keycloak\Http\Command; use Fschmtt\Keycloak\Http\CommandExecutor; +use Fschmtt\Keycloak\Http\ContentType; use Fschmtt\Keycloak\Http\Criteria; use Fschmtt\Keycloak\Http\Method; use Fschmtt\Keycloak\Http\Query;