Skip to content

Commit

Permalink
Merge pull request #142 from danielmaier42/hotfix/executeActionsEmail
Browse files Browse the repository at this point in the history
Fix executeActionsEmail via explicit ContentType declaration
  • Loading branch information
fschmtt authored Jan 23, 2025
2 parents ab02f04 + f8cd4fe commit b13ebf5
Show file tree
Hide file tree
Showing 10 changed files with 82 additions and 20 deletions.
6 changes: 6 additions & 0 deletions src/Http/Command.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ public function __construct(
/** @var Representation|Collection|array<mixed>|null */
private readonly Representation|Collection|array|null $payload = null,
private readonly ?Criteria $criteria = null,
private readonly ContentType $contentType = ContentType::JSON,
) {}

public function getMethod(): Method
Expand Down Expand Up @@ -61,4 +62,9 @@ public function getQuery(): string

return '?' . http_build_query($this->criteria->jsonSerialize());
}

public function getContentType(): ContentType
{
return $this->contentType;
}
}
27 changes: 9 additions & 18 deletions src/Http/CommandExecutor.php
Original file line number Diff line number Diff line change
Expand Up @@ -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,
);
}
}
14 changes: 14 additions & 0 deletions src/Http/ContentType.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php

declare(strict_types=1);

namespace Fschmtt\Keycloak\Http;

/**
* @internal
*/
enum ContentType: string
{
case JSON = 'application/json';
case FORM_PARAMS = 'application/x-www-form-urlencoded';
}
2 changes: 2 additions & 0 deletions src/Resource/Organizations.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use Fschmtt\Keycloak\Collection\OrganizationCollection;
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;
Expand Down Expand Up @@ -71,6 +72,7 @@ public function inviteUser(string $realm, string $id, string $email, string $fir
'firstName' => $firstName,
'lastName' => $lastName,
],
contentType: ContentType::FORM_PARAMS,
),
);
}
Expand Down
1 change: 1 addition & 0 deletions src/Resource/Users.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
28 changes: 28 additions & 0 deletions tests/Integration/Resource/UsersTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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 */
Expand Down
6 changes: 4 additions & 2 deletions tests/Unit/Http/CommandExecutorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -43,7 +44,7 @@ public function testCallsClientWithoutBodyIfCommandHasNoRepresentation(): void
);
}

public function testCallsClientWithBodyIfCommandHasRepresentation(): void
public function testCallsClientWithJsonIfCommandHasRepresentation(): void
{
$command = new Command(
'/path/to/resource',
Expand Down Expand Up @@ -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);
Expand Down
15 changes: 15 additions & 0 deletions tests/Unit/Http/CommandTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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());
}
}
2 changes: 2 additions & 0 deletions tests/Unit/Resource/OrganizationsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -148,6 +149,7 @@ public function testInviteUser(): void
'firstName' => 'first name',
'lastName' => 'last name',
],
contentType: ContentType::FORM_PARAMS,
);

$commandExecutor = $this->createMock(CommandExecutor::class);
Expand Down
1 change: 1 addition & 0 deletions tests/Unit/Resource/UsersTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit b13ebf5

Please sign in to comment.