Skip to content

Commit

Permalink
WIP Move to SSP UI
Browse files Browse the repository at this point in the history
  • Loading branch information
Marko Ivančić committed Nov 26, 2024
1 parent 5eb4f81 commit c7d4699
Show file tree
Hide file tree
Showing 11 changed files with 180 additions and 18 deletions.
4 changes: 4 additions & 0 deletions public/assets/css/src/default.css
Original file line number Diff line number Diff line change
Expand Up @@ -114,3 +114,7 @@ table.client-table {
}

.confirm-action {}

form.pure-form-stacked input {
width: 100%;
}
5 changes: 1 addition & 4 deletions routing/routes/routes.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,7 @@
->controller([ClientController::class, 'index']);
$routes->add(RoutesEnum::AdminClientsAdd->name, RoutesEnum::AdminClientsAdd->value)
->controller([ClientController::class, 'add'])
->methods([HttpMethodsEnum::GET->value]);
$routes->add(RoutesEnum::AdminClientsAddPersist->name, RoutesEnum::AdminClientsAddPersist->value)
->controller([ClientController::class, 'addPersist'])
->methods([HttpMethodsEnum::POST->value]);
->methods([HttpMethodsEnum::GET->value, HttpMethodsEnum::POST->value]);
$routes->add(RoutesEnum::AdminClientsShow->name, RoutesEnum::AdminClientsShow->value)
->controller([ClientController::class, 'show'])
->methods([HttpMethodsEnum::GET->value]);
Expand Down
1 change: 0 additions & 1 deletion src/Codebooks/RoutesEnum.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ enum RoutesEnum: string
case AdminClients = 'admin/clients';
case AdminClientsShow = 'admin/clients/show';
case AdminClientsAdd = 'admin/clients/add';
case AdminClientsAddPersist = 'admin/clients/add/persist';
case AdminClientsResetSecret = 'admin/clients/reset-secret';
case AdminClientsDelete = 'admin/clients/delete';

Expand Down
120 changes: 119 additions & 1 deletion src/Controllers/Admin/ClientController.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,21 @@

namespace SimpleSAML\Module\oidc\Controllers\Admin;

use Nette\Forms\Form;
use SimpleSAML\Locale\Translate;
use SimpleSAML\Module\oidc\Admin\Authorization;
use SimpleSAML\Module\oidc\Bridges\SspBridge;
use SimpleSAML\Module\oidc\Codebooks\ParametersEnum;
use SimpleSAML\Module\oidc\Codebooks\RegistrationTypeEnum;
use SimpleSAML\Module\oidc\Codebooks\RoutesEnum;
use SimpleSAML\Module\oidc\Entities\ClientEntity;
use SimpleSAML\Module\oidc\Entities\Interfaces\ClientEntityInterface;
use SimpleSAML\Module\oidc\Exceptions\OidcException;
use SimpleSAML\Module\oidc\Factories\Entities\ClientEntityFactory;
use SimpleSAML\Module\oidc\Factories\FormFactory;
use SimpleSAML\Module\oidc\Factories\TemplateFactory;
use SimpleSAML\Module\oidc\Forms\ClientForm;
use SimpleSAML\Module\oidc\Helpers;
use SimpleSAML\Module\oidc\Repositories\AllowedOriginRepository;
use SimpleSAML\Module\oidc\Repositories\ClientRepository;
use SimpleSAML\Module\oidc\Services\AuthContextService;
Expand All @@ -29,11 +34,13 @@ public function __construct(
protected readonly TemplateFactory $templateFactory,
protected readonly Authorization $authorization,
protected readonly ClientRepository $clientRepository,
protected readonly ClientEntityFactory $clientEntityFactory,
protected readonly AllowedOriginRepository $allowedOriginRepository,
protected readonly FormFactory $formFactory,
protected readonly SspBridge $sspBridge,
protected readonly SessionMessagesService $sessionMessagesService,
protected readonly Routes $routes,
protected readonly Helpers $helpers,
protected readonly LoggerService $logger,
) {
$this->authorization->requireAdminOrUserWithPermission(AuthContextService::PERM_CLIENT);

Check warning on line 46 in src/Controllers/Admin/ClientController.php

View check run for this annotation

Codecov / codecov/patch

src/Controllers/Admin/ClientController.php#L46

Added line #L46 was not covered by tests
Expand Down Expand Up @@ -146,15 +153,53 @@ public function delete(Request $request): Response
);

Check warning on line 153 in src/Controllers/Admin/ClientController.php

View check run for this annotation

Codecov / codecov/patch

src/Controllers/Admin/ClientController.php#L151-L153

Added lines #L151 - L153 were not covered by tests
}

/**
* @throws \SimpleSAML\Error\ConfigurationError
* @throws \SimpleSAML\Error\Exception
* @throws \SimpleSAML\Module\oidc\Exceptions\OidcException
*/
public function add(): Response

Check warning on line 161 in src/Controllers/Admin/ClientController.php

View check run for this annotation

Codecov / codecov/patch

src/Controllers/Admin/ClientController.php#L161

Added line #L161 was not covered by tests
{
$form = $this->formFactory->build(ClientForm::class);

Check warning on line 163 in src/Controllers/Admin/ClientController.php

View check run for this annotation

Codecov / codecov/patch

src/Controllers/Admin/ClientController.php#L163

Added line #L163 was not covered by tests
$form->setAction($this->routes->urlAdminClientsAddPersist());

if ($form->isSuccess()) {
$createdAt = $this->helpers->dateTime()->getUtc();
$updatedAt = $createdAt;

Check warning on line 167 in src/Controllers/Admin/ClientController.php

View check run for this annotation

Codecov / codecov/patch

src/Controllers/Admin/ClientController.php#L165-L167

Added lines #L165 - L167 were not covered by tests

$owner = $this->authorization->isAdmin() ? null : $this->authorization->getUserId();

Check warning on line 169 in src/Controllers/Admin/ClientController.php

View check run for this annotation

Codecov / codecov/patch

src/Controllers/Admin/ClientController.php#L169

Added line #L169 was not covered by tests

$client = $this->buildClientFromFormData(
$form,
$this->sspBridge->utils()->random()->generateID(),
$this->sspBridge->utils()->random()->generateID(),
RegistrationTypeEnum::Manual,
$updatedAt,
$createdAt,
null,
$owner,
);

Check warning on line 180 in src/Controllers/Admin/ClientController.php

View check run for this annotation

Codecov / codecov/patch

src/Controllers/Admin/ClientController.php#L171-L180

Added lines #L171 - L180 were not covered by tests

$this->clientRepository->add($client);

Check warning on line 182 in src/Controllers/Admin/ClientController.php

View check run for this annotation

Codecov / codecov/patch

src/Controllers/Admin/ClientController.php#L182

Added line #L182 was not covered by tests

// Also persist allowed origins for this client.
is_array($allowedOrigins = $form->getValues('array')['allowed_origin'] ?? []) ||
throw new OidcException('Unexpected value for allowed origins.');

Check warning on line 186 in src/Controllers/Admin/ClientController.php

View check run for this annotation

Codecov / codecov/patch

src/Controllers/Admin/ClientController.php#L185-L186

Added lines #L185 - L186 were not covered by tests
/** @var string[] $allowedOrigins */
$this->allowedOriginRepository->set($client->getIdentifier(), $allowedOrigins);

Check warning on line 188 in src/Controllers/Admin/ClientController.php

View check run for this annotation

Codecov / codecov/patch

src/Controllers/Admin/ClientController.php#L188

Added line #L188 was not covered by tests

$this->sessionMessagesService->addMessage(Translate::noop('Client has been added.'));

Check warning on line 190 in src/Controllers/Admin/ClientController.php

View check run for this annotation

Codecov / codecov/patch

src/Controllers/Admin/ClientController.php#L190

Added line #L190 was not covered by tests

return $this->routes->getRedirectResponseToModuleUrl(
RoutesEnum::AdminClientsShow->value,
[ParametersEnum::ClientId->value => $client->getIdentifier()],
);

Check warning on line 195 in src/Controllers/Admin/ClientController.php

View check run for this annotation

Codecov / codecov/patch

src/Controllers/Admin/ClientController.php#L192-L195

Added lines #L192 - L195 were not covered by tests
}

return $this->templateFactory->build(
'oidc:clients/new.twig',
[
'form' => $form,
'actionRoute' => $this->routes->urlAdminClientsAdd(),
'regexUri' => ClientForm::REGEX_URI,
'regexAllowedOriginUrl' => ClientForm::REGEX_ALLOWED_ORIGIN_URL,
'regexHttpUri' => ClientForm::REGEX_HTTP_URI,
Expand All @@ -163,4 +208,77 @@ public function add(): Response
RoutesEnum::AdminClients->value,
);

Check warning on line 209 in src/Controllers/Admin/ClientController.php

View check run for this annotation

Codecov / codecov/patch

src/Controllers/Admin/ClientController.php#L198-L209

Added lines #L198 - L209 were not covered by tests
}

/**
* TODO mivanci Move to ClientEntityFactory::fromRegistrationData on dynamic client registration implementation.
* @throws \SimpleSAML\Module\oidc\Exceptions\OidcException
*/
protected function buildClientFromFormData(

Check warning on line 216 in src/Controllers/Admin/ClientController.php

View check run for this annotation

Codecov / codecov/patch

src/Controllers/Admin/ClientController.php#L216

Added line #L216 was not covered by tests
Form $form,
string $identifier,
string $secret,
RegistrationTypeEnum $registrationType,
\DateTimeImmutable $updatedAt,
?\DateTimeImmutable $createdAt = null,
?\DateTimeImmutable $expiresAt = null,
?string $owner = null,
): ClientEntityInterface {
/** @var array $data */
$data = $form->getValues('array');

Check warning on line 227 in src/Controllers/Admin/ClientController.php

View check run for this annotation

Codecov / codecov/patch

src/Controllers/Admin/ClientController.php#L227

Added line #L227 was not covered by tests

if (
!is_string($data[ClientEntity::KEY_NAME]) ||
!is_string($data[ClientEntity::KEY_DESCRIPTION]) ||
!is_array($data[ClientEntity::KEY_REDIRECT_URI]) ||
!is_array($data[ClientEntity::KEY_SCOPES]) ||
!is_array($data[ClientEntity::KEY_POST_LOGOUT_REDIRECT_URI])

Check warning on line 234 in src/Controllers/Admin/ClientController.php

View check run for this annotation

Codecov / codecov/patch

src/Controllers/Admin/ClientController.php#L230-L234

Added lines #L230 - L234 were not covered by tests
) {
throw new OidcException('Invalid Client Entity data');

Check warning on line 236 in src/Controllers/Admin/ClientController.php

View check run for this annotation

Codecov / codecov/patch

src/Controllers/Admin/ClientController.php#L236

Added line #L236 was not covered by tests
}

/** @var string[] $redirectUris */
$redirectUris = $data[ClientEntity::KEY_REDIRECT_URI];

Check warning on line 240 in src/Controllers/Admin/ClientController.php

View check run for this annotation

Codecov / codecov/patch

src/Controllers/Admin/ClientController.php#L240

Added line #L240 was not covered by tests
/** @var string[] $scopes */
$scopes = $data[ClientEntity::KEY_SCOPES];

Check warning on line 242 in src/Controllers/Admin/ClientController.php

View check run for this annotation

Codecov / codecov/patch

src/Controllers/Admin/ClientController.php#L242

Added line #L242 was not covered by tests
/** @var string[] $postLogoutRedirectUris */
$postLogoutRedirectUris = $data[ClientEntity::KEY_POST_LOGOUT_REDIRECT_URI];

Check warning on line 244 in src/Controllers/Admin/ClientController.php

View check run for this annotation

Codecov / codecov/patch

src/Controllers/Admin/ClientController.php#L244

Added line #L244 was not covered by tests
/** @var ?string[] $clientRegistrationTypes */
$clientRegistrationTypes = is_array($data[ClientEntity::KEY_CLIENT_REGISTRATION_TYPES]) ?
$data[ClientEntity::KEY_CLIENT_REGISTRATION_TYPES] : null;

Check warning on line 247 in src/Controllers/Admin/ClientController.php

View check run for this annotation

Codecov / codecov/patch

src/Controllers/Admin/ClientController.php#L246-L247

Added lines #L246 - L247 were not covered by tests
/** @var ?array[] $federationJwks */
$federationJwks = is_array($data[ClientEntity::KEY_FEDERATION_JWKS]) ?
$data[ClientEntity::KEY_FEDERATION_JWKS] : null;

Check warning on line 250 in src/Controllers/Admin/ClientController.php

View check run for this annotation

Codecov / codecov/patch

src/Controllers/Admin/ClientController.php#L249-L250

Added lines #L249 - L250 were not covered by tests
/** @var ?array[] $jwks */
$jwks = is_array($data[ClientEntity::KEY_JWKS]) ? $data[ClientEntity::KEY_JWKS] : null;
$jwksUri = empty($data[ClientEntity::KEY_JWKS_URI]) ? null : (string)$data[ClientEntity::KEY_JWKS_URI];
$signedJwksUri = empty($data[ClientEntity::KEY_SIGNED_JWKS_URI]) ?
null : (string)$data[ClientEntity::KEY_SIGNED_JWKS_URI];
$isFederated = (bool)$data[ClientEntity::KEY_IS_FEDERATED];

Check warning on line 256 in src/Controllers/Admin/ClientController.php

View check run for this annotation

Codecov / codecov/patch

src/Controllers/Admin/ClientController.php#L252-L256

Added lines #L252 - L256 were not covered by tests

return $this->clientEntityFactory->fromData(
$identifier,
$secret,
$data['name'],
$data['description'],
$redirectUris,
$scopes,
(bool) $data['is_enabled'],
(bool) $data['is_confidential'],
empty($data['auth_source']) ? null : (string)$data['auth_source'],
$owner,
$postLogoutRedirectUris,
empty($data['backchannel_logout_uri']) ? null : (string)$data['backchannel_logout_uri'],
empty($data['entity_identifier']) ? null : (string)$data['entity_identifier'],
$clientRegistrationTypes,
$federationJwks,
$jwks,
$jwksUri,
$signedJwksUri,
$registrationType,
$updatedAt,
$createdAt,
$expiresAt,
$isFederated,
);

Check warning on line 282 in src/Controllers/Admin/ClientController.php

View check run for this annotation

Codecov / codecov/patch

src/Controllers/Admin/ClientController.php#L258-L282

Added lines #L258 - L282 were not covered by tests
}
}
1 change: 1 addition & 0 deletions src/Controllers/Client/CreateController.php
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ public function __invoke(): Template|RedirectResponse
$jwks = is_array($client['jwks']) ? $client['jwks'] : null;
$jwksUri = empty($client['jwks_uri']) ? null : (string)$client['jwks_uri'];
$signedJwksUri = empty($client['signed_jwks_uri']) ? null : (string)$client['signed_jwks_uri'];

$registrationType = RegistrationTypeEnum::Manual;
$createdAt = $this->helpers->dateTime()->getUtc();
$updatedAt = $createdAt;
Expand Down
1 change: 1 addition & 0 deletions src/Controllers/Client/EditController.php
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ public function __invoke(ServerRequest $request): Template|RedirectResponse
$jwks = is_array($data['jwks']) ? $data['jwks'] : null;
$jwksUri = empty($data['jwks_uri']) ? null : (string)$data['jwks_uri'];
$signedJwksUri = empty($data['signed_jwks_uri']) ? null : (string)$data['signed_jwks_uri'];

$registrationType = $client->getRegistrationType();
$updatedAt = $this->helpers->dateTime()->getUtc();
$createdAt = $client->getCreatedAt();
Expand Down
9 changes: 5 additions & 4 deletions src/Forms/ClientForm.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

use Nette\Forms\Form;
use SimpleSAML\Auth\Source;
use SimpleSAML\Locale\Translate;
use SimpleSAML\Module\oidc\Forms\Controls\CsrfProtection;
use SimpleSAML\Module\oidc\ModuleConfig;
use SimpleSAML\OpenID\Codebooks\ClientRegistrationTypesEnum;
Expand Down Expand Up @@ -341,11 +342,11 @@ protected function buildForm(): void

$this->addText('name', '{oidc:client:name}')
->setMaxLength(255)
->setRequired('Set a name');
->setRequired(Translate::noop('Name is required.'));

$this->addTextArea('description', '{oidc:client:description}', null, 5);
$this->addTextArea('redirect_uri', '{oidc:client:redirect_uri}', null, 5)
->setRequired('Write one redirect URI at least');
->setRequired(Translate::noop('At least one redirect URI is required.'));

$this->addCheckbox('is_enabled', '{oidc:client:is_enabled}');

Expand All @@ -355,14 +356,14 @@ protected function buildForm(): void
$this->addSelect('auth_source', '{oidc:client:auth_source}:')
->setHtmlAttribute('class', 'ui fluid dropdown clearable')
->setItems(Source::getSources(), false)
->setPrompt('Pick an AuthSource');
->setPrompt(Translate::noop('Pick an AuthSource'));

$scopes = $this->getScopes();

$this->addMultiSelect('scopes', '{oidc:client:scopes}')
->setHtmlAttribute('class', 'ui fluid dropdown')
->setItems($scopes)
->setRequired('Select one scope at least');
->setRequired(Translate::noop('At least one scope is required.'));

$this->addText('owner', '{oidc:client:owner}')
->setMaxLength(190);
Expand Down
5 changes: 0 additions & 5 deletions src/Utils/Routes.php
Original file line number Diff line number Diff line change
Expand Up @@ -80,11 +80,6 @@ public function urlAdminClientsAdd(array $parameters = []): string
return $this->getModuleUrl(RoutesEnum::AdminClientsAdd->value, $parameters);

Check warning on line 80 in src/Utils/Routes.php

View check run for this annotation

Codecov / codecov/patch

src/Utils/Routes.php#L80

Added line #L80 was not covered by tests
}

public function urlAdminClientsAddPersist(array $parameters = []): string
{
return $this->getModuleUrl(RoutesEnum::AdminClientsAddPersist->value, $parameters);
}

public function urlAdminClientsResetSecret(string $clientId, array $parameters = []): string

Check warning on line 83 in src/Utils/Routes.php

View check run for this annotation

Codecov / codecov/patch

src/Utils/Routes.php#L83

Added line #L83 was not covered by tests
{
$parameters[ParametersEnum::ClientId->value] = $clientId;
Expand Down
32 changes: 32 additions & 0 deletions templates/clients/includes/form.twig
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@

{% if form.hasErrors %}
<div class="message-box warning">
<ul>
{% for error in form.getErrors %}
<li>{{ error | trans }}</li>
{% endfor %}
</ul>
</div>
{% endif %}

<p>{{ form.hasErrors ? 'yes' : 'no' }}</p>

<form method="post"
action="{{ actionRoute }}"
class="pure-form pure-form-stacked">

{{ form['_token_'].control | raw }}

<fieldset>
<label for="frm-name">{{ 'Name'|trans }}</label>
{{ form.name.label |raw }}
{{ form.name.control | raw }}
{% if form.name.hasErrors %}
<span class="pure-form-message red-text">{{ form.name.getError }}</span>
{% endif %}


<br>
<button type="submit" class="pure-button ">{{ (actionText|default('Submit'))|trans }}</button>
</fieldset>
</form>
2 changes: 1 addition & 1 deletion templates/clients/new-old.twig
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{% extends "@oidc/clients/_form.twig" %}
{% extends "@oidc/clients/_form-old.twig" %}

{% set pagetitle = 'Create new OpenID Connect Client' | trans %}

Expand Down
18 changes: 16 additions & 2 deletions templates/clients/new.twig
Original file line number Diff line number Diff line change
@@ -1,9 +1,23 @@
{% set subPageTitle = 'Add Client '|trans %}
{% set subPageTitle = 'Add Client'|trans %}

{% extends "@oidc/base.twig" %}

{% block oidcContent %}

// TODO
<div class="pure-g">
<div class="pure-u-1-2">

</div>
<div class="pure-u-1-2">
<div class="right">
<a class="pure-button " href="{{ routes.urlAdminClients }}">
<i class="fa fa-chevron-left"></i>
{{ 'Back'|trans }}
</a>
</div>
</div>
</div>

{% include "@oidc/clients/includes/form.twig" %}

{% endblock oidcContent -%}

0 comments on commit c7d4699

Please sign in to comment.