Skip to content

Commit 7d653ab

Browse files
authored
Move ClientEntity factory methods to dedicated ClientEntityFactory (#255)
* Move to ClientEntityFactory --------- Co-authored-by: Marko Ivančić <[email protected]>
1 parent c875ff4 commit 7d653ab

27 files changed

+670
-513
lines changed

src/Controller/Client/CreateController.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818

1919
use Laminas\Diactoros\Response\RedirectResponse;
2020
use SimpleSAML\Module\oidc\Codebooks\RegistrationTypeEnum;
21-
use SimpleSAML\Module\oidc\Entities\ClientEntity;
21+
use SimpleSAML\Module\oidc\Factories\Entities\ClientEntityFactory;
2222
use SimpleSAML\Module\oidc\Factories\FormFactory;
2323
use SimpleSAML\Module\oidc\Factories\TemplateFactory;
2424
use SimpleSAML\Module\oidc\Forms\ClientForm;
@@ -42,6 +42,7 @@ public function __construct(
4242
private readonly SessionMessagesService $messages,
4343
private readonly AuthContextService $authContextService,
4444
private readonly Helpers $helpers,
45+
private readonly ClientEntityFactory $clientEntityFactory,
4546
) {
4647
}
4748

@@ -100,7 +101,7 @@ public function __invoke(): Template|RedirectResponse
100101
$expiresAt = null;
101102
$isFederated = (bool)$client['is_federated'];
102103

103-
$this->clientRepository->add(ClientEntity::fromData(
104+
$this->clientRepository->add($this->clientEntityFactory->fromData(
104105
$client['id'],
105106
$client['secret'],
106107
$client['name'],

src/Controller/Client/EditController.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
use Laminas\Diactoros\Response\RedirectResponse;
2020
use Laminas\Diactoros\ServerRequest;
2121
use SimpleSAML\Module\oidc\Controller\Traits\AuthenticatedGetClientFromRequestTrait;
22-
use SimpleSAML\Module\oidc\Entities\ClientEntity;
22+
use SimpleSAML\Module\oidc\Factories\Entities\ClientEntityFactory;
2323
use SimpleSAML\Module\oidc\Factories\FormFactory;
2424
use SimpleSAML\Module\oidc\Factories\TemplateFactory;
2525
use SimpleSAML\Module\oidc\Forms\ClientForm;
@@ -44,6 +44,7 @@ public function __construct(
4444
private readonly SessionMessagesService $messages,
4545
AuthContextService $authContextService,
4646
private readonly Helpers $helpers,
47+
private readonly ClientEntityFactory $clientEntityFactory,
4748
) {
4849
$this->clientRepository = $clientRepository;
4950
$this->authContextService = $authContextService;
@@ -106,7 +107,7 @@ public function __invoke(ServerRequest $request): Template|RedirectResponse
106107
$expiresAt = $client->getExpiresAt();
107108
$isFederated = (bool)$data['is_federated'];
108109

109-
$this->clientRepository->update(ClientEntity::fromData(
110+
$this->clientRepository->update($this->clientEntityFactory->fromData(
110111
$client->getIdentifier(),
111112
$client->getSecret(),
112113
$data['name'],

src/Controller/Federation/Test.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77
namespace SimpleSAML\Module\oidc\Controller\Federation;
88

99
use SimpleSAML\Module\oidc\Codebooks\RegistrationTypeEnum;
10-
use SimpleSAML\Module\oidc\Factories\ClientEntityFactory;
1110
use SimpleSAML\Module\oidc\Factories\CoreFactory;
11+
use SimpleSAML\Module\oidc\Factories\Entities\ClientEntityFactory;
1212
use SimpleSAML\Module\oidc\Services\LoggerService;
1313
use SimpleSAML\Module\oidc\Utils\FederationCache;
1414
use SimpleSAML\Module\oidc\Utils\ProtocolCache;

src/Entities/ClientEntity.php

Lines changed: 72 additions & 180 deletions
Original file line numberDiff line numberDiff line change
@@ -20,16 +20,10 @@
2020
use League\OAuth2\Server\Entities\Traits\ClientTrait;
2121
use League\OAuth2\Server\Entities\Traits\EntityTrait;
2222
use PDO;
23-
// use SimpleSAML\Module\oidc\Codebooks\ClaimValues\ClientRegistrationTypesEnum;
2423
use SimpleSAML\Module\oidc\Codebooks\RegistrationTypeEnum;
2524
use SimpleSAML\Module\oidc\Entities\Interfaces\ClientEntityInterface;
26-
use SimpleSAML\Module\oidc\Server\Exceptions\OidcServerException;
27-
use SimpleSAML\Module\oidc\Utils\TimestampGenerator;
2825
use SimpleSAML\OpenID\Codebooks\ClientRegistrationTypesEnum;
2926

30-
/**
31-
* @psalm-suppress PropertyNotSetInConstructor
32-
*/
3327
class ClientEntity implements ClientEntityInterface
3428
{
3529
use EntityTrait;
@@ -101,13 +95,6 @@ class ClientEntity implements ClientEntityInterface
10195
private ?DateTimeImmutable $expiresAt;
10296
private bool $isFederated;
10397

104-
/**
105-
* Constructor.
106-
*/
107-
private function __construct()
108-
{
109-
}
110-
11198
/**
11299
* @param string[] $redirectUri
113100
* @param string[] $scopes
@@ -116,8 +103,8 @@ private function __construct()
116103
* @param array[] $federationJwks
117104
* @param array[] $jwks
118105
*/
119-
public static function fromData(
120-
string $id,
106+
public function __construct(
107+
string $identifier,
121108
string $secret,
122109
string $name,
123110
string $description,
@@ -140,125 +127,30 @@ public static function fromData(
140127
?DateTimeImmutable $createdAt = null,
141128
?DateTimeImmutable $expiresAt = null,
142129
bool $isFederated = false,
143-
): ClientEntityInterface {
144-
$client = new self();
145-
146-
$client->identifier = $id;
147-
$client->secret = $secret;
148-
$client->name = $name;
149-
$client->description = $description;
150-
$client->authSource = empty($authSource) ? null : $authSource;
151-
$client->redirectUri = $redirectUri;
152-
$client->scopes = $scopes;
153-
$client->isEnabled = $isEnabled;
154-
$client->isConfidential = $isConfidential;
155-
$client->owner = empty($owner) ? null : $owner;
156-
$client->postLogoutRedirectUri = $postLogoutRedirectUri;
157-
$client->backChannelLogoutUri = empty($backChannelLogoutUri) ? null : $backChannelLogoutUri;
158-
$client->entityIdentifier = empty($entityIdentifier) ? null : $entityIdentifier;
159-
$client->clientRegistrationTypes = $clientRegistrationTypes;
160-
$client->federationJwks = $federationJwks;
161-
$client->jwks = $jwks;
162-
$client->jwksUri = $jwksUri;
163-
$client->signedJwksUri = $signedJwksUri;
164-
$client->registrationType = $registrationType;
165-
$client->updatedAt = $updatedAt;
166-
$client->createdAt = $createdAt;
167-
$client->expiresAt = $expiresAt;
168-
$client->isFederated = $isFederated;
169-
170-
return $client;
171-
}
172-
173-
/**
174-
* TODO mivanci Move to dedicated factory class.
175-
* @throws \JsonException
176-
* @throws \SimpleSAML\Module\oidc\Server\Exceptions\OidcServerException
177-
*/
178-
public static function fromState(array $state): self
179-
{
180-
$client = new self();
181-
182-
if (
183-
!is_string($state['id']) ||
184-
!is_string($state['secret']) ||
185-
!is_string($state['name']) ||
186-
!is_string($state['redirect_uri']) ||
187-
!is_string($state['scopes']) ||
188-
!is_string($state['registration_type'])
189-
) {
190-
throw OidcServerException::serverError('Invalid Client Entity state');
191-
}
192-
193-
$client->identifier = $state['id'];
194-
$client->secret = $state['secret'];
195-
$client->name = $state['name'];
196-
$client->description = (string)($state['description'] ?? '');
197-
$client->authSource = empty($state['auth_source']) ? null : (string)$state['auth_source'];
198-
199-
/** @var string[] $redirectUris */
200-
$redirectUris = json_decode($state['redirect_uri'], true, 512, JSON_THROW_ON_ERROR);
201-
$client->redirectUri = $redirectUris;
202-
203-
/** @var string[] $scopes */
204-
$scopes = json_decode($state['scopes'], true, 512, JSON_THROW_ON_ERROR);
205-
$client->scopes = $scopes;
206-
207-
$client->isEnabled = (bool) $state['is_enabled'];
208-
$client->isConfidential = (bool) ($state['is_confidential'] ?? false);
209-
$client->owner = empty($state['owner']) ? null : (string)$state['owner'];
210-
211-
/** @var string[] $postLogoutRedirectUris */
212-
$postLogoutRedirectUris = json_decode(
213-
(string)($state['post_logout_redirect_uri'] ?? "[]"),
214-
true,
215-
512,
216-
JSON_THROW_ON_ERROR,
217-
);
218-
$client->postLogoutRedirectUri = $postLogoutRedirectUris;
219-
220-
221-
$client->backChannelLogoutUri = empty($state['backchannel_logout_uri']) ?
222-
null :
223-
(string)$state['backchannel_logout_uri'];
224-
225-
$client->entityIdentifier = empty($state['entity_identifier']) ?
226-
null :
227-
(string)$state['entity_identifier'];
228-
229-
/** @var ?string[] $clientRegistrationTypes */
230-
$clientRegistrationTypes = empty($state['client_registration_types']) ?
231-
null :
232-
json_decode((string)$state['client_registration_types'], true, 512, JSON_THROW_ON_ERROR);
233-
$client->clientRegistrationTypes = $clientRegistrationTypes;
234-
235-
/** @var ?array[] $federationJwks */
236-
$federationJwks = empty($state['federation_jwks']) ?
237-
null :
238-
json_decode((string)$state['federation_jwks'], true, 512, JSON_THROW_ON_ERROR);
239-
$client->federationJwks = $federationJwks;
240-
241-
/** @var ?array[] $jwks */
242-
$jwks = empty($state['jwks']) ?
243-
null :
244-
json_decode((string)$state['jwks'], true, 512, JSON_THROW_ON_ERROR);
245-
$client->jwks = $jwks;
246-
247-
$client->jwksUri = empty($state['jwks_uri']) ? null : (string)$state['jwks_uri'];
248-
$client->signedJwksUri = empty($state['signed_jwks_uri']) ? null : (string)$state['signed_jwks_uri'];
249-
250-
$client->registrationType = RegistrationTypeEnum::from(trim($state['registration_type']));
251-
252-
$client->updatedAt = empty($state['updated_at']) ? null :
253-
TimestampGenerator::utcImmutable((string)$state['updated_at']);
254-
$client->createdAt = empty($state['created_at']) ? null :
255-
TimestampGenerator::utcImmutable((string)$state['created_at']);
256-
$client->expiresAt = empty($state['expires_at']) ? null :
257-
TimestampGenerator::utcImmutable((string)$state['expires_at']);
258-
259-
$client->isFederated = (bool)$state['is_federated'];
260-
261-
return $client;
130+
) {
131+
$this->identifier = $identifier;
132+
$this->secret = $secret;
133+
$this->name = $name;
134+
$this->description = $description;
135+
$this->authSource = empty($authSource) ? null : $authSource;
136+
$this->redirectUri = $redirectUri;
137+
$this->scopes = $scopes;
138+
$this->isEnabled = $isEnabled;
139+
$this->isConfidential = $isConfidential;
140+
$this->owner = empty($owner) ? null : $owner;
141+
$this->postLogoutRedirectUri = $postLogoutRedirectUri;
142+
$this->backChannelLogoutUri = empty($backChannelLogoutUri) ? null : $backChannelLogoutUri;
143+
$this->entityIdentifier = empty($entityIdentifier) ? null : $entityIdentifier;
144+
$this->clientRegistrationTypes = $clientRegistrationTypes;
145+
$this->federationJwks = $federationJwks;
146+
$this->jwks = $jwks;
147+
$this->jwksUri = $jwksUri;
148+
$this->signedJwksUri = $signedJwksUri;
149+
$this->registrationType = $registrationType;
150+
$this->updatedAt = $updatedAt;
151+
$this->createdAt = $createdAt;
152+
$this->expiresAt = $expiresAt;
153+
$this->isFederated = $isFederated;
262154
}
263155

264156
/**
@@ -268,64 +160,64 @@ public static function fromState(array $state): self
268160
public function getState(): array
269161
{
270162
return [
271-
'id' => $this->getIdentifier(),
272-
'secret' => $this->getSecret(),
273-
'name' => $this->getName(),
274-
'description' => $this->getDescription(),
275-
'auth_source' => $this->getAuthSourceId(),
276-
'redirect_uri' => json_encode($this->getRedirectUri(), JSON_THROW_ON_ERROR),
277-
'scopes' => json_encode($this->getScopes(), JSON_THROW_ON_ERROR),
278-
'is_enabled' => [$this->isEnabled(), PDO::PARAM_BOOL],
279-
'is_confidential' => [$this->isConfidential(), PDO::PARAM_BOOL],
280-
'owner' => $this->getOwner(),
281-
'post_logout_redirect_uri' => json_encode($this->getPostLogoutRedirectUri(), JSON_THROW_ON_ERROR),
282-
'backchannel_logout_uri' => $this->getBackChannelLogoutUri(),
283-
'entity_identifier' => $this->getEntityIdentifier(),
284-
'client_registration_types' => is_null($this->clientRegistrationTypes) ?
163+
self::KEY_ID => $this->getIdentifier(),
164+
self::KEY_SECRET => $this->getSecret(),
165+
self::KEY_NAME => $this->getName(),
166+
self::KEY_DESCRIPTION => $this->getDescription(),
167+
self::KEY_AUTH_SOURCE => $this->getAuthSourceId(),
168+
self::KEY_REDIRECT_URI => json_encode($this->getRedirectUri(), JSON_THROW_ON_ERROR),
169+
self::KEY_SCOPES => json_encode($this->getScopes(), JSON_THROW_ON_ERROR),
170+
self::KEY_IS_ENABLED => [$this->isEnabled(), PDO::PARAM_BOOL],
171+
self::KEY_IS_CONFIDENTIAL => [$this->isConfidential(), PDO::PARAM_BOOL],
172+
self::KEY_OWNER => $this->getOwner(),
173+
self::KEY_POST_LOGOUT_REDIRECT_URI => json_encode($this->getPostLogoutRedirectUri(), JSON_THROW_ON_ERROR),
174+
self::KEY_BACKCHANNEL_LOGOUT_URI => $this->getBackChannelLogoutUri(),
175+
self::KEY_ENTITY_IDENTIFIER => $this->getEntityIdentifier(),
176+
self::KEY_CLIENT_REGISTRATION_TYPES => is_null($this->clientRegistrationTypes) ?
285177
null :
286178
json_encode($this->getClientRegistrationTypes(), JSON_THROW_ON_ERROR),
287-
'federation_jwks' => is_null($this->federationJwks) ?
179+
self::KEY_FEDERATION_JWKS => is_null($this->federationJwks) ?
288180
null :
289181
json_encode($this->getFederationJwks()),
290-
'jwks' => is_null($this->jwks) ?
182+
self::KEY_JWKS => is_null($this->jwks) ?
291183
null :
292184
json_encode($this->getJwks()),
293-
'jwks_uri' => $this->getJwksUri(),
294-
'signed_jwks_uri' => $this->getSignedJwksUri(),
295-
'registration_type' => $this->getRegistrationType()->value,
296-
'updated_at' => $this->getUpdatedAt()?->format('Y-m-d H:i:s'),
297-
'created_at' => $this->getCreatedAt()?->format('Y-m-d H:i:s'),
298-
'expires_at' => $this->getExpiresAt()?->format('Y-m-d H:i:s'),
299-
'is_federated' => [$this->isFederated(), PDO::PARAM_BOOL],
185+
self::KEY_JWKS_URI => $this->getJwksUri(),
186+
self::KEY_SIGNED_JWKS_URI => $this->getSignedJwksUri(),
187+
self::KEY_REGISTRATION_TYPE => $this->getRegistrationType()->value,
188+
self::KEY_UPDATED_AT => $this->getUpdatedAt()?->format('Y-m-d H:i:s'),
189+
self::KEY_CREATED_AT => $this->getCreatedAt()?->format('Y-m-d H:i:s'),
190+
self::KEY_EXPIRES_AT => $this->getExpiresAt()?->format('Y-m-d H:i:s'),
191+
self::KEY_IS_FEDERATED => [$this->isFederated(), PDO::PARAM_BOOL],
300192
];
301193
}
302194

303195
public function toArray(): array
304196
{
305197
return [
306-
'id' => $this->identifier,
307-
'secret' => $this->secret,
308-
'name' => $this->name,
309-
'description' => $this->description,
310-
'auth_source' => $this->authSource,
311-
'redirect_uri' => $this->redirectUri,
312-
'scopes' => $this->scopes,
313-
'is_enabled' => $this->isEnabled,
314-
'is_confidential' => $this->isConfidential,
315-
'owner' => $this->owner,
316-
'post_logout_redirect_uri' => $this->postLogoutRedirectUri,
317-
'backchannel_logout_uri' => $this->backChannelLogoutUri,
318-
'entity_identifier' => $this->entityIdentifier,
319-
'client_registration_types' => $this->clientRegistrationTypes,
320-
'federation_jwks' => $this->federationJwks,
321-
'jwks' => $this->jwks,
322-
'jwks_uri' => $this->jwksUri,
323-
'signed_jwks_uri' => $this->signedJwksUri,
324-
'registration_type' => $this->registrationType,
325-
'updated_at' => $this->updatedAt,
326-
'created_at' => $this->createdAt,
327-
'expires_at' => $this->expiresAt,
328-
'is_federated' => $this->isFederated,
198+
self::KEY_ID => $this->identifier,
199+
self::KEY_SECRET => $this->secret,
200+
self::KEY_NAME => $this->name,
201+
self::KEY_DESCRIPTION => $this->description,
202+
self::KEY_AUTH_SOURCE => $this->authSource,
203+
self::KEY_REDIRECT_URI => $this->redirectUri,
204+
self::KEY_SCOPES => $this->scopes,
205+
self::KEY_IS_ENABLED => $this->isEnabled,
206+
self::KEY_IS_CONFIDENTIAL => $this->isConfidential,
207+
self::KEY_OWNER => $this->owner,
208+
self::KEY_POST_LOGOUT_REDIRECT_URI => $this->postLogoutRedirectUri,
209+
self::KEY_BACKCHANNEL_LOGOUT_URI => $this->backChannelLogoutUri,
210+
self::KEY_ENTITY_IDENTIFIER => $this->entityIdentifier,
211+
self::KEY_CLIENT_REGISTRATION_TYPES => $this->clientRegistrationTypes,
212+
self::KEY_FEDERATION_JWKS => $this->federationJwks,
213+
self::KEY_JWKS => $this->jwks,
214+
self::KEY_JWKS_URI => $this->jwksUri,
215+
self::KEY_SIGNED_JWKS_URI => $this->signedJwksUri,
216+
self::KEY_REGISTRATION_TYPE => $this->registrationType,
217+
self::KEY_UPDATED_AT => $this->updatedAt,
218+
self::KEY_CREATED_AT => $this->createdAt,
219+
self::KEY_EXPIRES_AT => $this->expiresAt,
220+
self::KEY_IS_FEDERATED => $this->isFederated,
329221
];
330222
}
331223

src/Entities/Interfaces/ClientEntityInterface.php

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -10,23 +10,6 @@
1010

1111
interface ClientEntityInterface extends OAuth2ClientEntityInterface, MementoInterface
1212
{
13-
/**
14-
* @param string[] $redirectUri
15-
* @param string[] $scopes
16-
*/
17-
public static function fromData(
18-
string $id,
19-
string $secret,
20-
string $name,
21-
string $description,
22-
array $redirectUri,
23-
array $scopes,
24-
bool $isEnabled,
25-
bool $isConfidential = false,
26-
?string $authSource = null,
27-
?string $owner = null,
28-
): self;
29-
3013
public function toArray(): array;
3114

3215
public function getSecret(): string;

src/Entities/Interfaces/MementoInterface.php

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,6 @@
1717

1818
interface MementoInterface
1919
{
20-
public static function fromState(array $state): MementoInterface;
21-
2220
/**
2321
* @return array
2422
*/

0 commit comments

Comments
 (0)