From cee3aefec57942361c9b19158da410d729189339 Mon Sep 17 00:00:00 2001
From: Robert Nasarek
Date: Tue, 8 Aug 2023 00:09:15 +0200
Subject: [PATCH] add validation process
---
css/style.css | 43 ++++++++++++++
.../WisskiCloudAccountManagerController.php | 58 +++++++++++++++++-
.../WisskiCloudAccountManagerCreateForm.php | 29 ++++++---
.../WisskiCloudAccountManagerSettingsForm.php | 25 +++++---
...skiCloudAccountManagerDaemonApiActions.php | 59 ++++++++++++++-----
...-account-manager-validation-page.html.twig | 52 ++++++++++++++++
wisski_cloud_account_manager.libraries.yml | 5 ++
wisski_cloud_account_manager.module | 12 ++++
wisski_cloud_account_manager.routing.yml | 14 ++++-
9 files changed, 263 insertions(+), 34 deletions(-)
create mode 100644 css/style.css
create mode 100644 templates/wisski-cloud-account-manager-validation-page.html.twig
create mode 100644 wisski_cloud_account_manager.libraries.yml
diff --git a/css/style.css b/css/style.css
new file mode 100644
index 0000000..2a37794
--- /dev/null
+++ b/css/style.css
@@ -0,0 +1,43 @@
+/* Reset the table styles */
+table.wisski-cloud-account-manager-table {
+ border-collapse: collapse;
+ width: 100%;
+}
+
+/* Style for table headers */
+table.wisski-cloud-account-manager-table th {
+ background-color: #f2f2f2;
+ padding: 8px;
+ text-align: center;
+}
+
+/* Alternate row background color */
+table.wisski-cloud-account-manager-table tr:nth-child(even) {
+ background-color: #f2f2f2;
+}
+
+/* Style for table cells */
+table.wisski-cloud-account-manager-table td {
+ padding: 8px;
+ border: 1px solid #dddddd;
+}
+
+/* Center-align certain cells */
+table.wisski-cloud-account-manager-table td.valid,
+table.wisski-cloud-account-manager-table td.provisioned {
+ text-align: center;
+}
+
+.wisski-cloud-account-manager-success {
+ background-color: green;
+}
+.wisski-cloud-account-manager-warning {
+ background-color: orange;
+}
+.wisski-cloud-account-manager-error {
+ background-color: red;
+}
+
+.wisski-cloud-account-manager-center {
+ text-align: center;
+}
diff --git a/src/Controller/WisskiCloudAccountManagerController.php b/src/Controller/WisskiCloudAccountManagerController.php
index efdd4fc..da9aaed 100644
--- a/src/Controller/WisskiCloudAccountManagerController.php
+++ b/src/Controller/WisskiCloudAccountManagerController.php
@@ -3,23 +3,79 @@
namespace Drupal\wisski_cloud_account_manager\Controller;
use Drupal\Core\Controller\ControllerBase;
+use Drupal\wisski_cloud_account_manager\WisskiCloudAccountManagerDaemonApiActions;
+use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* The Wisski Cloud account manager info controller.
*/
class WisskiCloudAccountManagerController extends ControllerBase {
+ /**
+ * @var \Drupal\wisski_cloud_account_manager\WisskiCloudAccountManagerDaemonApiActions
+ * The WissKi Cloud account manager daemon API actions service.
+ */
+ protected WisskiCloudAccountManagerDaemonApiActions $wisskiCloudAccountManagerDaemonApiActions;
+
+ /**
+ * Class constructor.
+ *
+ * @param \Drupal\wisski_cloud_account_manager\WisskiCloudAccountManagerDaemonApiActions $wisskiCloudAccountManagerDaemonApiActions
+ * The WissKi Cloud account manager daemon API actions service.
+ */
+ public function __construct(WisskiCloudAccountManagerDaemonApiActions $wisskiCloudAccountManagerDaemonApiActions) {
+ $this->wisskiCloudAccountManagerDaemonApiActions = $wisskiCloudAccountManagerDaemonApiActions;
+ }
+
+ /**
+ * Populate the reachable variables from services.
+ *
+ * @param \Symfony\Component\DependencyInjection\ContainerInterface $container
+ * The class container.
+ */
+ public static function create(ContainerInterface $container) {
+ return new static(
+ $container->get('wisski_cloud_account_manager.daemon_api.actions'),
+ );
+ }
+
/**
* Info page for terms and conditions.
*
* @return array
* The page build array.
*/
- public function termsAndConditions(): array {
+ public function termsAndConditionsPage(): array {
$build = [
'#markup' => $this->t('Hello World!'),
];
return $build;
}
+ /**
+ * Page to check the validation and provision status.
+ *
+ * @param string $validationCode
+ * The token to check the status for.
+ *
+ * @return array
+ * The page build array.
+ */
+ public function validationPage(string $validationCode): array {
+ $validationResponse = $this->wisskiCloudAccountManagerDaemonApiActions->validateAccount($validationCode);
+
+ $responseContents = json_decode($validationResponse->getBody()
+ ->getContents(), TRUE);
+
+ return [
+ '#theme' => 'wisski_cloud_account_manager_validation_page',
+ '#responseContents' => $responseContents,
+ '#attached' => [
+ 'library' => [
+ 'wisski_cloud_account_manager/wisski_cloud_account_manager',
+ ],
+ ],
+ ];
+ }
+
}
diff --git a/src/Form/WisskiCloudAccountManagerCreateForm.php b/src/Form/WisskiCloudAccountManagerCreateForm.php
index 447220c..9ef2c95 100644
--- a/src/Form/WisskiCloudAccountManagerCreateForm.php
+++ b/src/Form/WisskiCloudAccountManagerCreateForm.php
@@ -2,6 +2,7 @@
namespace Drupal\wisski_cloud_account_manager\Form;
+use Drupal\Component\Utility\EmailValidatorInterface;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\wisski_cloud_account_manager\WisskiCloudAccountManagerDaemonApiActions;
@@ -18,10 +19,16 @@ class WisskiCloudAccountManagerCreateForm extends FormBase {
*/
protected WisskiCloudAccountManagerDaemonApiActions $wisskiCloudAccountManagerDaemonApiActions;
+ /**
+ * @var \Drupal\Component\Utility\EmailValidatorInterface
+ * The email validator service.
+ */
+ private EmailValidatorInterface $emailValidator;
+
/**
* {@inheritdoc}
*/
- public function getFormId() {
+ public function getFormId(): string {
return 'wisski_cloud_account_manager_create';
}
@@ -30,9 +37,12 @@ class WisskiCloudAccountManagerCreateForm extends FormBase {
*
* @param \Drupal\wisski_cloud_account_manager\WisskiCloudAccountManagerDaemonApiActions $wisskiCloudAccountManagerDaemonApiActions
* The WissKi Cloud account manager daemon API actions service.
+ * @param \Drupal\Component\Utility\EmailValidatorInterface $emailValidator
+ * The email validator service.
*/
- public function __construct(WisskiCloudAccountManagerDaemonApiActions $wisskiCloudAccountManagerDaemonApiActions) {
+ public function __construct(WisskiCloudAccountManagerDaemonApiActions $wisskiCloudAccountManagerDaemonApiActions, EmailValidatorInterface $emailValidator) {
$this->wisskiCloudAccountManagerDaemonApiActions = $wisskiCloudAccountManagerDaemonApiActions;
+ $this->emailValidator = $emailValidator;
}
/**
@@ -44,6 +54,7 @@ class WisskiCloudAccountManagerCreateForm extends FormBase {
public static function create(ContainerInterface $container) {
return new static(
$container->get('wisski_cloud_account_manager.daemon_api.actions'),
+ $container->get('email.validator'),
);
}
@@ -126,20 +137,20 @@ class WisskiCloudAccountManagerCreateForm extends FormBase {
$response = $this->wisskiCloudAccountManagerDaemonApiActions->checkAccountData($dataToCheck);
- if ($response['accountData']['userWithUsername']) {
+ if ($response['accountData']['accountWithUsername']) {
$form_state->setErrorByName('username', $this->t('The username "@username" is already in use.', ['@username' => $dataToCheck['username']]));
}
- if ($response['accountData']['userWithEmail']) {
+ if ($response['accountData']['accountWithEmail']) {
$form_state->setErrorByName('email', $this->t('The email "@email" is already in use.', ['@email' => $dataToCheck['email']]));
}
- if ($response['accountData']['userWithSubdomain']) {
+ if ($response['accountData']['accountWithSubdomain']) {
$form_state->setErrorByName('subdomain', $this->t('The subdomain "@subdomain" is already in use.', ['@subdomain' => $dataToCheck['subdomain']]));
}
// Check if email is in valid form.
- if (!\Drupal::service('email.validator')->isValid($dataToCheck['email'])) {
+ if (!$this->emailValidator->isValid($dataToCheck['email'])) {
$form_state->setErrorByName('email', $this->t('Email not in valid form, i.e. "name@example.com".'));
}
}
@@ -160,13 +171,13 @@ class WisskiCloudAccountManagerCreateForm extends FormBase {
$accountResponse = $this->wisskiCloudAccountManagerDaemonApiActions->addAccount($account);
dpm($accountResponse, 'accountResponse');
- $this->wisskiCloudAccountManagerDaemonApiActions->sendValidationEmail($accountResponse['user']['email'], $accountResponse['user']['validationCode']);
+ $this->wisskiCloudAccountManagerDaemonApiActions->sendValidationEmail($accountResponse['account']['email'], $accountResponse['account']['validationCode']);
- \Drupal::messenger()
+ $this->messenger()
->addMessage($this->t('The account data has been successfully saved, please check your email for validation!'));
}
catch (\Exception $ex) {
- \Drupal::logger('wisski_cloud_account_manager')->error($ex->getMessage());
+ $this->logger('wisski_cloud_account_manager')->error($ex->getMessage());
}
}
diff --git a/src/Form/WisskiCloudAccountManagerSettingsForm.php b/src/Form/WisskiCloudAccountManagerSettingsForm.php
index c32cf81..6ece673 100644
--- a/src/Form/WisskiCloudAccountManagerSettingsForm.php
+++ b/src/Form/WisskiCloudAccountManagerSettingsForm.php
@@ -42,18 +42,25 @@ class WisskiCloudAccountManagerSettingsForm extends ConfigFormBase {
'#default_value' => $config->get('daemonUrl'),
];
- $form['userPostUrlPath'] = [
+ $form['accountPostUrlPath'] = [
'#type' => 'url',
'#title' => $this->t('POST URL path'),
- '#description' => $this->t('Provide the path to the POST endpoint, i. e. "/user"'),
- '#default_value' => $config->get('userPostUrlPath'),
+ '#description' => $this->t('Provide the path to the POST endpoint, i. e. "/account"'),
+ '#default_value' => $config->get('accountPostUrlPath'),
];
- $form['userFilterByData'] = [
+ $form['accountFilterByData'] = [
'#type' => 'url',
'#title' => $this->t('Filter by Data URL path'),
- '#description' => $this->t('Provide the path to the Get user by data endpoint, i. e. "/user/by_data"'),
- '#default_value' => $config->get('userFilterByData'),
+ '#description' => $this->t('Provide the path to the Get account by data endpoint, i. e. "/account/by_data"'),
+ '#default_value' => $config->get('accountFilterByData'),
+ ];
+
+ $form['accountValidation'] = [
+ '#type' => 'url',
+ '#title' => $this->t('User Validation URL path'),
+ '#description' => $this->t('Provide the path to the account validation PUT endpoint, i. e. "/account/validation"'),
+ '#default_value' => $config->get('accountValidation'),
];
return $form;
@@ -66,8 +73,10 @@ class WisskiCloudAccountManagerSettingsForm extends ConfigFormBase {
$config = $this->config('wisski_cloud_account_manager.settings');
$config->set('daemonURL', $form_state->getValue('daemonURL'))
- ->set('userPostUrlPath', $form_state->getValue('userPostUrlPath'))
- ->set('userFilterByData', $form_state->getValue('userFilterByData'))
+ ->set('accountPostUrlPath', $form_state->getValue('accountPostUrlPath'))
+ ->set('accountFilterByData', $form_state->getValue('accountFilterByData'))
+ ->set('accountProvisionAndValidationCheck', $form_state->getValue('accountProvisionAndValidationCheck'))
+ ->set('accountValidation', $form_state->getValue('accountValidation'))
->save();
parent::submitForm($form, $form_state);
diff --git a/src/WisskiCloudAccountManagerDaemonApiActions.php b/src/WisskiCloudAccountManagerDaemonApiActions.php
index 8bc0b70..1ac70cd 100644
--- a/src/WisskiCloudAccountManagerDaemonApiActions.php
+++ b/src/WisskiCloudAccountManagerDaemonApiActions.php
@@ -11,6 +11,7 @@ use Drupal\Core\Messenger\MessengerInterface;
use Drupal\Core\Render\Markup;
use Drupal\Core\StringTranslation\TranslationInterface;
use GuzzleHttp\ClientInterface;
+use Psr\Http\Message\ResponseInterface;
/**
* Handles the communication with the WissKI Cloud account manager daemon.
@@ -31,14 +32,21 @@ class WisskiCloudAccountManagerDaemonApiActions {
*
* @var string
*/
- private string $USER_POST_URL_PART = '/user';
+ private string $ACCOUNT_POST_URL_PART = '/account';
/**
* The URL path to the GET endpoint.
*
* @var string
*/
- private string $FILTER_BY_DATA_URL_PART = '/user/by_data';
+ private string $FILTER_BY_DATA_URL_PART = '/account/by_data';
+
+ /**
+ * The URL path to provision and validation GET endpoint.
+ *
+ * @var string
+ */
+ private string $ACCOUNT_VALIDATION_URL_PART = '/account/validation';
/**
* The string translation service.
@@ -68,8 +76,6 @@ class WisskiCloudAccountManagerDaemonApiActions {
*/
protected Config $settings;
-
-
/**
* The mail manager.
*
@@ -93,7 +99,8 @@ class WisskiCloudAccountManagerDaemonApiActions {
ClientInterface $httpClient,
ConfigFactoryInterface $configFactory,
MailManagerInterface $mailManager,
- LanguageManagerInterface $languageManager) {
+ LanguageManagerInterface $languageManager
+ ) {
// Services from container.
$this->stringTranslation = $stringTranslation;
$this->messenger = $messenger;
@@ -108,9 +115,10 @@ class WisskiCloudAccountManagerDaemonApiActions {
// Set the daemon URL and the URL parts class variables.
$this->DAEMON_URL = $settings->get('daemonUrl') ?: 'http://wisski_cloud_api_daemon:3000/wisski-cloud-daemon/api/v1';
- $this->USER_POST_URL_PART = $settings->get('userPostUrlPath') ?: '/user';
- $this->FILTER_BY_DATA_URL_PART = $settings->get('userFilterByData') ?: '/user/by_data';
-
+ $this->USER_POST_URL_PART = $settings->get('accountPostUrlPath') ?: '/account';
+ $this->FILTER_BY_DATA_URL_PART = $settings->get('accountFilterByData') ?: '/account/by_data';
+ $this->USER_PROVISION_AND_VALIDATION_URL_PART = $settings->get('accountProvisionAndValidationUrlPart') ?: '/account/provision_and_validation';
+ $this->ACCOUNT_VALIDATION_URL_PART = $settings->get('accountValidationUrlPart') ?: '/account/validation';
}
/**
@@ -120,7 +128,7 @@ class WisskiCloudAccountManagerDaemonApiActions {
* The account to add.
*
* @return array
- * The response from the daemon (user id with validation code).
+ * The response from the daemon (account id with validation code).
*/
public function addAccount(array $account): array {
$request = [
@@ -129,21 +137,25 @@ class WisskiCloudAccountManagerDaemonApiActions {
],
'body' => json_encode($account),
];
- $userPostUrl = $this->DAEMON_URL . $this->USER_POST_URL_PART;
- $response = $this->httpClient->post($userPostUrl, $request);
- return array_merge(json_decode($response->getBody()->getContents(), TRUE), ['statusCode' => $response->getStatusCode()]);
+ $accountPostUrl = $this->DAEMON_URL . $this->ACCOUNT_POST_URL_PART;
+ $response = $this->httpClient->post($accountPostUrl, $request);
+ return array_merge(json_decode($response->getBody()
+ ->getContents(), TRUE), ['statusCode' => $response->getStatusCode()]);
}
/**
* Check if an account with the given data already exists.
*
* @param array $dataToCheck
- * The data to check.
+ * The data to check. Possible keys are:
+ * - email
+ * - subdomain
+ * - username.
*
* @return array
* The response from the daemon.
*/
- public function checkAccountData($dataToCheck): array {
+ public function checkAccountData(array $dataToCheck): array {
// Build the query string from the parameters.
$query_string = http_build_query($dataToCheck);
@@ -170,6 +182,22 @@ class WisskiCloudAccountManagerDaemonApiActions {
}
}
+ /**
+ * Checks the validation status of the given validation code.
+ *
+ * @param string $validationCode
+ * The validation code to check.
+ *
+ * @return \Psr\Http\Message\ResponseInterface
+ * The response from the daemon.
+ */
+ public function validateAccount(string $validationCode): ResponseInterface {
+ $url = $this->DAEMON_URL . $this->ACCOUNT_VALIDATION_URL_PART . '/' . $validationCode;
+ return $this->httpClient->put($url);
+
+ }
+
+
/**
* Sends a validation email to the given email address.
*
@@ -184,7 +212,8 @@ class WisskiCloudAccountManagerDaemonApiActions {
$langcode = $this->languageManager->getDefaultLanguage()->getId();
$to = $email;
- $validationLink = \Drupal::request()->getSchemeAndHttpHost() . '/wisski-cloud-account-manager/validate/' . $validationCode;
+ $validationLink = \Drupal::request()
+ ->getSchemeAndHttpHost() . '/wisski-cloud-account-manager/validate/' . $validationCode;
$params['message'] = Markup::create($this->stringTranslation->translate('Please validate your account by clicking on this link or copy this to the address bar of your browser:
@validationLink
.
', ['@validationLink' => $validationLink]));
$params['subject'] = $this->stringTranslation->translate('WissKI Cloud account validation');
diff --git a/templates/wisski-cloud-account-manager-validation-page.html.twig b/templates/wisski-cloud-account-manager-validation-page.html.twig
new file mode 100644
index 0000000..cab9176
--- /dev/null
+++ b/templates/wisski-cloud-account-manager-validation-page.html.twig
@@ -0,0 +1,52 @@
+{# wisski_cloud_account_manager/templates/wisski_cloud_account_manager_validation_page.html.twig #}
+
+ {% if responseContents is not empty %}
+
+
+ | Person name |
+ Email |
+ Username |
+ Subdomain |
+ Valid |
+ Provisioned |
+
+
+ | {{ responseContents.data.personName }} |
+ {{ responseContents.data.email }} |
+ {{ responseContents.data.username }} |
+ {{ responseContents.data.subdomain }} |
+
+ {% if responseContents.data.valid == 1 %}
+ yes
+ {% elseif responseContents.data.valid == 0 %}
+ no
+ {% else %}
+ unknown
+ {% endif %}
+ |
+ {% if responseContents.data.provisioned == 1 %}
+ yes
+ {% elseif responseContents.data.provisioned == 0 %}
+ no
+ {% elseif responseContents.data.provisioned == 2 %}
+ ongoing
+ {% else %}
+ unknown
+ {% endif %} |
+
+
+
+
+ {% if responseContents.data.valid == 1 and responseContents.data.provisioned == 1 %}
+
Your account is valid and provisioned. You can now log in to your account at https://{{ responseContents.data.subdomain }}.wisski.cloud.
+ {% elseif responseContents.data.valid == 1 and responseContents.data.provisioned == 0 %}
+
Your account is valid but not yet provisioned. Please wait a few minutes and reload this page.
+ {% elseif responseContents.data.valid == 0 %}
+
Your account is not valid. Please contact info@wiss-ki.eu to resolve this issue.
+ {% else %}
+
Something went wrong. Please contact info@wiss-ki.eu to resolve this issue.
+ {% endif %}
+
+
+ {% endif %}
+
diff --git a/wisski_cloud_account_manager.libraries.yml b/wisski_cloud_account_manager.libraries.yml
new file mode 100644
index 0000000..8fb6984
--- /dev/null
+++ b/wisski_cloud_account_manager.libraries.yml
@@ -0,0 +1,5 @@
+wisski_cloud_account_manager:
+ version: 1.x
+ css:
+ theme:
+ css/style.css: {}
diff --git a/wisski_cloud_account_manager.module b/wisski_cloud_account_manager.module
index 6d1d99b..4ad28ea 100644
--- a/wisski_cloud_account_manager.module
+++ b/wisski_cloud_account_manager.module
@@ -42,3 +42,15 @@ function wisski_cloud_account_manager_mail($key, &$message, $params) {
break;
}
}
+
+/**
+ * Implements hook_theme().
+ */
+function wisski_cloud_account_manager_theme($existing, $type, $theme, $path) {
+ return [
+ 'wisski_cloud_account_manager_validation_page' => [
+ 'variables' => ['responseContents' => NULL],
+ ],
+ ];
+}
+
diff --git a/wisski_cloud_account_manager.routing.yml b/wisski_cloud_account_manager.routing.yml
index 1643fb1..23414a8 100644
--- a/wisski_cloud_account_manager.routing.yml
+++ b/wisski_cloud_account_manager.routing.yml
@@ -23,10 +23,22 @@ wisski_cloud_account.create:
requirements:
_access: 'TRUE'
+wisski_cloud_account.validate:
+ path: '/wisski-cloud-account-manager/validate/{validationCode}'
+ defaults:
+ _controller: '\Drupal\wisski_cloud_account_manager\Controller\WisskiCloudAccountManagerController::validationPage'
+ _title: 'Check validation and provision of your WissKI Cloud account'
+ requirements:
+ _access: 'TRUE'
+ token: '[a-zA-Z0-9]+'
+
wisski_cloud_account.terms_and_conditions:
path: '/wisski-cloud-account-manager/terms-and-conditions'
defaults:
- _controller: '\Drupal\wisski_cloud_account_manager\Controller\WisskiCloudAccountManagerController::termsAndConditions'
+ _controller: '\Drupal\wisski_cloud_account_manager\Controller\WisskiCloudAccountManagerController::termsAndConditionsPage'
_title: 'Terms and conditions'
requirements:
_access: 'TRUE'
+
+
+