From 308e21941ae2d98247b097f99973e22d82cddf44 Mon Sep 17 00:00:00 2001
From: rnsrk
Date: Wed, 15 Nov 2023 01:53:03 +0100
Subject: [PATCH] full working version
---
css/style.css | 45 +-
js/accountOptions.js | 29 +-
js/provisionStatus.js | 37 ++
src/Access/AccountRouteAccessCheck.php | 36 +
.../WisskiCloudAccountManagerController.php | 98 ++-
.../WisskiCloudAccountManagerCreateForm.php | 56 +-
.../WisskiCloudAccountManagerDeleteForm.php | 111 ++++
...WisskiCloudAccountManagerProvisionForm.php | 115 ++++
.../WisskiCloudAccountManagerPurgeForm.php | 105 +++
.../WisskiCloudAccountManagerSettingsForm.php | 56 +-
...isskiCloudAccountManagerValidationForm.php | 113 ++++
...skiCloudAccountManagerDaemonApiActions.php | 616 +++++++++++++-----
...nt-manager-account-managing-page.html.twig | 90 ++-
...ccount-manager-health-check-page.html.twig | 27 +
...account-manager-validation-email.html.twig | 10 +
...-account-manager-validation-page.html.twig | 62 +-
wisski_cloud_account_manager.install | 61 ++
wisski_cloud_account_manager.libraries.yml | 11 +-
wisski_cloud_account_manager.links.menu.yml | 17 +-
wisski_cloud_account_manager.module | 57 +-
wisski_cloud_account_manager.routing.yml | 36 +-
wisski_cloud_account_manager.services.yml | 12 +-
22 files changed, 1434 insertions(+), 366 deletions(-)
mode change 100644 => 100755 js/accountOptions.js
create mode 100644 js/provisionStatus.js
create mode 100644 src/Access/AccountRouteAccessCheck.php
create mode 100755 src/Form/WisskiCloudAccountManagerDeleteForm.php
create mode 100755 src/Form/WisskiCloudAccountManagerProvisionForm.php
create mode 100755 src/Form/WisskiCloudAccountManagerPurgeForm.php
create mode 100755 src/Form/WisskiCloudAccountManagerValidationForm.php
create mode 100755 templates/wisski-cloud-account-manager-health-check-page.html.twig
create mode 100644 templates/wisski-cloud-account-manager-validation-email.html.twig
create mode 100755 wisski_cloud_account_manager.install
diff --git a/css/style.css b/css/style.css
index 47aa2fb..10b2abe 100755
--- a/css/style.css
+++ b/css/style.css
@@ -1,43 +1,4 @@
-/* Reset the table styles */
-table.wcam--table {
- border-collapse: collapse;
- width: 100%;
-}
-
-/* Style for table headers */
-table.wcam--table th {
- background-color: #f2f2f2;
- padding: 8px;
- text-align: center;
-}
-
-/* Alternate row background color */
-table.wcam--table tr:nth-child(even) {
- background-color: #f2f2f2;
-}
-
-/* Style for table cells */
-table.wcam--table td {
- padding: 8px;
- border: 1px solid #dddddd;
-}
-
-/* Center-align certain cells */
-table.wcam--table td.valid,
-table.wcam--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;
+.spinner-border {
+ height: 1em !important;
+ width: 1em !important;
}
diff --git a/js/accountOptions.js b/js/accountOptions.js
old mode 100644
new mode 100755
index 6416bbd..3ad3dd9
--- a/js/accountOptions.js
+++ b/js/accountOptions.js
@@ -5,30 +5,37 @@
*/
Drupal.behaviors.accountOptions = {
attach: function (context, settings) {
- once('accountOptions', '#wcam--table', context).forEach(function (form) {
+ once('accountOptions', '#wcam--table', context).forEach(function () {
$('.wcam--select').change(function () {
- console.log($(this))
let selectedOption = $(this).val();
- let itemId = $(this).closest('tr').find('.wcam--row--item-id').text();
+ let aid = $(this).closest('tr').find('.wcam--row--account-id').text().trim();
switch (selectedOption) {
case 'delete':
- // Führen Sie hier Ihren JavaScript-Code für 'delete' aus.
-
- console.log('delete:', itemId);
+ // Construct the URL for the delete route.
+ let deleteUrl = Drupal.url('wisski-cloud-account-manager/delete/' + aid);
+ // Redirect to the delete route.
+ window.location.href = deleteUrl;
break;
case 'edit':
- // Führen Sie hier Ihren JavaScript-Code für 'edit' aus.
- console.log('Edit:', itemId);
+ console.log('Edit:', aid);
break;
case 'provise':
- // Führen Sie hier Ihren JavaScript-Code für 'provise' aus.
- console.log('Provise', itemId);
+ // Construct the URL for the provise route.
+ let proviseUrl = Drupal.url('wisski-cloud-account-manager/provise/' + aid);
+ // Redirect to the provise route.
+ window.location.href = proviseUrl;
+ break;
+
+ case 'purge':
+ // Construct the URL for the purge route.
+ let purgeUrl = Drupal.url('wisski-cloud-account-manager/purge/' + aid);
+ // Redirect to the purge route.
+ window.location.href = purgeUrl;
break;
case 'validate':
- // Führen Sie hier Ihren JavaScript-Code für 'validate' aus.
console.log('Die Option "validate" wurde ausgewählt.');
break;
diff --git a/js/provisionStatus.js b/js/provisionStatus.js
new file mode 100644
index 0000000..015689a
--- /dev/null
+++ b/js/provisionStatus.js
@@ -0,0 +1,37 @@
+(function ($, Drupal, once) {
+ Drupal.behaviors.wcamProvisionStatus = {
+ attach: function (context, settings) {
+ once('wcamProvisionStatus', 'html', context).forEach(function () {
+ // Get the process idle animation.
+ let $animation = $('#process-idle-animation');
+ $animation.show(); // Show the spinner.
+ // Get the aid and initial provision status from the HTML.
+ let $rows = $('.wcam--table--row');
+ $rows.each(function () {
+ let $row = $(this);
+ let aid = $row.find('.wcam--row--account-id').text().trim();
+ let initialStatus = $row.find('#provision-status--aid-' + aid).text().trim();
+ // If the initial provision status is 'ongoing', start checking the provision status.
+ if (initialStatus === 'ongoing' || initialStatus === 'unknown') {
+ let intervalId = setInterval(function () {
+ $.get('/wisski-cloud-account-manager/provision-status/' + aid, function (data) {
+ // Update the provision status on the page.
+ let $status = $('#provision-status--aid-' + aid);
+ $status.text(data.status);
+ // If the provision status is not 'ongoing', stop the process idle animation.
+ if (data.status !== 'ongoing') {
+ if (data.status !== 'unknown') {
+ $row.find('#provision-status--row--aid-' + aid).text(data.status);
+ $animation.hide(); // Hide the spinner.
+ clearInterval(intervalId);
+ location.reload();
+ }
+ }
+ });
+ }, 3000);
+ }
+ });
+ });
+ }
+ };
+})(jQuery, Drupal, once);
diff --git a/src/Access/AccountRouteAccessCheck.php b/src/Access/AccountRouteAccessCheck.php
new file mode 100644
index 0000000..c88803c
--- /dev/null
+++ b/src/Access/AccountRouteAccessCheck.php
@@ -0,0 +1,36 @@
+currentUser = $currentUser;
+ $this->database = $database;
+ }
+
+ public function access($aid) {
+ // If the user has the "Administer WissKI Cloud Account Manager" role, allow access.
+ if ($this->currentUser->hasPermission('Administer WissKI Cloud Account Manager')) {
+ return AccessResult::allowed()->cachePerUser();
+ }
+ // Otherwise, check if the aid matches the user's aid in the database.
+ $uid = $this->currentUser->id();
+ $query = $this->database->select('wisski_cloud_account_manager_accounts', 'w')
+ ->fields('w', ['aid'])
+ ->condition('uid', $uid)
+ ->condition('aid', $aid)
+ ->execute();
+
+ $result = $query->fetchField();
+
+ return AccessResult::allowedIf($result)->cachePerUser();
+ }
+}
diff --git a/src/Controller/WisskiCloudAccountManagerController.php b/src/Controller/WisskiCloudAccountManagerController.php
index 5a651d7..722f43b 100755
--- a/src/Controller/WisskiCloudAccountManagerController.php
+++ b/src/Controller/WisskiCloudAccountManagerController.php
@@ -5,6 +5,7 @@ namespace Drupal\wisski_cloud_account_manager\Controller;
use Drupal\Core\Controller\ControllerBase;
use Drupal\wisski_cloud_account_manager\WisskiCloudAccountManagerDaemonApiActions;
use Symfony\Component\DependencyInjection\ContainerInterface;
+use Symfony\Component\HttpFoundation\JsonResponse;
/**
* The Wisski Cloud account manager info controller.
@@ -39,6 +40,63 @@ class WisskiCloudAccountManagerController extends ControllerBase {
);
}
+ /**
+ * Page list the account statuses.
+ *
+ * @return array
+ * The page build array.
+ */
+ public function accountManagingPage(): array {
+ $currentUser = \Drupal::currentUser();
+ $healthCheck = $this->wisskiCloudAccountManagerDaemonApiActions->healthCheck();
+ $accounts = $this->wisskiCloudAccountManagerDaemonApiActions->getAccounts();
+ // If the user is not an admin, filter the accounts to only include their own.
+ if (!$currentUser->hasPermission('admister wisski cloud account manager')) {
+ $accounts = array_filter($accounts, function($account) use ($currentUser) {
+ return $account['uid'] === $currentUser->id();
+ });
+ }
+ return [
+ '#theme' => 'wisski_cloud_account_manager_account_managing_page',
+ '#accounts' => $accounts,
+ '#healthCheck' => $healthCheck,
+ '#attached' => [
+ 'library' => [
+ 'wisski_cloud_account_manager/accountOptions',
+ 'wisski_cloud_account_manager/globalStyling',
+ 'wisski_cloud_account_manager/provisionStatus'
+ ],
+ ],
+ '#cache' => [
+ 'max-age' => 0,
+ ],
+ ];
+ }
+
+ // @todo Implement healthcheckPage().
+ public function healthcheckPage(): array {
+ return [
+ '#theme' => 'wisski_cloud_account_manager_healthcheck_page',
+ '#healthCheck' => $this->wisskiCloudAccountManagerDaemonApiActions->healthCheck(),
+ ];
+ }
+
+ public function provisionStatusPage($aid) {
+ $accounts = $this->wisskiCloudAccountManagerDaemonApiActions->getAccounts($aid);
+ // Return the status as a JSON response.
+ switch ($accounts[0]['provisioned']) {
+ case '0':
+ return new JsonResponse(['status' => 'no']);
+ case '1':
+ return new JsonResponse(['status' => 'ongoing']);
+ case '2':
+ return new JsonResponse(['status' => 'yes']);
+ case '3':
+ return new JsonResponse(['status' => 'unknown']);
+ }
+ return new JsonResponse(['status' => $accounts[0]['provisioned']]);
+ }
+
/**
* Info page for terms and conditions.
*
@@ -63,41 +121,13 @@ class WisskiCloudAccountManagerController extends ControllerBase {
* The page build array.
*/
public function validationPage(string $validationCode): array {
- $account = $this->wisskiCloudAccountManagerDaemonApiActions->validateAccount($validationCode);
+ $user = $this->wisskiCloudAccountManagerDaemonApiActions->validateAccount($validationCode);
+
return [
- '#theme' => 'wisski_cloud_account_manager_validation_page',
- '#account' => $account,
- '#attached' => [
- 'library' => [
- 'wisski_cloud_account_manager/wisski_cloud_account_manager',
- ],
- ],
- '#cache' => [
- 'max-age' => 0,
- ],
+ '#markup' => $this->t('Your WissKI Cloud account for user :name is now validated. You can now login and start a provision!.', [
+ ':name' => $user['name'],
+ ]),
];
}
-
- /**
- * Page list the account statuses.
- *
- * @return array
- * The page build array.
- */
- public function accountManagingPage(): array {
- $accounts = $this->wisskiCloudAccountManagerDaemonApiActions->getAccounts();
- return [
- '#theme' => 'wisski_cloud_account_manager_account_managing_page',
- '#accounts' => $accounts,
- '#attached' => [
- 'library' => [
- 'wisski_cloud_account_manager/wisski_cloud_account_manager',
- ],
- ],
- '#cache' => [
- 'max-age' => 0,
- ],
- ];
- }
-
}
+
diff --git a/src/Form/WisskiCloudAccountManagerCreateForm.php b/src/Form/WisskiCloudAccountManagerCreateForm.php
index a88890a..cc63d16 100755
--- a/src/Form/WisskiCloudAccountManagerCreateForm.php
+++ b/src/Form/WisskiCloudAccountManagerCreateForm.php
@@ -16,9 +16,6 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
*/
class WisskiCloudAccountManagerCreateForm extends FormBase {
-
-
-
/**
* The config factory service.
*
@@ -126,7 +123,7 @@ class WisskiCloudAccountManagerCreateForm extends FormBase {
'#type' => 'textfield',
'#title' => $this->t('Username'),
'#maxlength' => 20,
- '#description' => $this->t('WissKI cloud login user. Only small caps (a-z), underscore (_), minus (-) and 20 letter maximum allowed, i.e. "wisski_user".'),
+ '#description' => $this->t('WissKI cloud login - NOT your password for your instance - this will be send separately. Only small caps (a-z), underscore (_), minus (-) and 20 letter maximum allowed, i.e. "wisski_user".'),
'#pattern' => '[a-z]+([_-]{1}[a-z]+)*',
'#required' => TRUE,
];
@@ -175,38 +172,54 @@ class WisskiCloudAccountManagerCreateForm extends FormBase {
$dataToCheck['email'] = $form_state->getValue('email');
$dataToCheck['emailProvider'] = explode('@', $dataToCheck['email'])[1];
$dataToCheck['subdomain'] = $form_state->getValue('subdomain');
+ $dataToCheck['usernameBlacklist'] = $this->settings->get('usernameBlacklist') ?? '';
+ $dataToCheck['emailProviderBlacklist'] = $this->settings->get('emailProviderBlacklist') ?? '';
+ $dataToCheck['subdomainBlacklist'] = $this->settings->get('subdomainBlacklist') ?? '';
- $response = $this->wisskiCloudAccountManagerDaemonApiActions->checkAccountData($dataToCheck);
+ // Check if username is too short.
+ if (strlen($dataToCheck['username']) < 2) {
+ $form_state->setErrorByName('username', $this->t('The username "@username" is too short, please use at least 2 characters.', ['@username' => $dataToCheck['username']]));
+ }
- if (!$response['success']) {
- $this->messenger->addError('Can not communicate with the provision daemon, please try again later or write an email to cloud@wiss-ki.eu.');
- }
- if (strlen($dataToCheck['username']) < 3) {
- $form_state->setErrorByName('username', $this->t('The username "@username" is too short, please use at least 3 characters.', ['@username' => $dataToCheck['username']]));
- }
- if (in_array($dataToCheck['username'], preg_split('/\r\n|\r|\n/', $this->settings->get('usernameBlacklist')))) {
+ // Check if username is in blacklist.
+ if (in_array($dataToCheck['username'], preg_split('/\r\n|\r|\n/', $dataToCheck['usernameBlacklist']))) {
$form_state->setErrorByName('username', $this->t('The username "@username" is not allowed.', ['@username' => $dataToCheck['username']]));
}
- if ($response['accountData']['accountWithUsername']) {
- $form_state->setErrorByName('username', $this->t('The username "@username" is already in use.', ['@username' => $dataToCheck['username']]));
+
+ // Check if username only contains lowercase letters, numbers, and underscores
+ if (!preg_match('/^[a-z0-9_]+$/', $dataToCheck['username'])) {
+ $form_state->setErrorByName('username', t('Username can only contain lowercase letters, numbers, and underscores.'));
}
- if (in_array($dataToCheck['emailProvider'], preg_split('/\r\n|\r|\n/', $this->settings->get('emailProviderBlacklist')))) {
+ // Check if username is unique
+ $userFromUsername = \Drupal::entityTypeManager()->getStorage('user')->loadByProperties(['name' =>$dataToCheck['username']]);
+ if (!empty($userFromUsername)) {
+ $form_state->setErrorByName('username', $this->t('The username is already taken.'));
+ }
+
+ // Check if email provider is in blacklist.
+ if (in_array($dataToCheck['emailProvider'], preg_split('/\r\n|\r|\n/', $dataToCheck['emailProviderBlacklist']))) {
$form_state->setErrorByName('email', $this->t('The email provider "@provider"is not allowed.', ['@provider' => $dataToCheck['emailProvider']]));
}
- if ($response['accountData']['accountWithEmail']) {
+ // Check if email is already in use.
+ $userFromEmail = \Drupal::entityTypeManager()->getStorage('user')->loadByProperties(['name' => $dataToCheck['email']]);
+ if (!empty($userFromEmail)) {
$form_state->setErrorByName('email', $this->t('The email "@email" is already in use.', ['@email' => $dataToCheck['email']]));
}
+ // Check if subdomain is too short.
if (strlen($dataToCheck['subdomain']) < 3) {
$form_state->setErrorByName('subdomain', $this->t('The subdomain "@subdomain" is too short, please use at least 3 characters.', ['@subdomain' => $dataToCheck['subdomain']]));
}
- if (in_array($dataToCheck['subdomain'], preg_split('/\r\n|\r|\n/', $this->settings->get('subdomainBlacklist')))) {
+ // Check if subdomain is in blacklist.
+ if (in_array($dataToCheck['subdomain'], preg_split('/\r\n|\r|\n/', $dataToCheck['emailProviderBlacklist']))) {
$form_state->setErrorByName('subdomain', $this->t('The subdomain "@subdomain" is not allowed.', ['@subdomain' => $dataToCheck['subdomain']]));
}
- if ($response['accountData']['accountWithSubdomain']) {
+
+ // Check if subdomain is already in use.
+ if ($this->wisskiCloudAccountManagerDaemonApiActions->checkForRedundantAccountData('subdomain', $dataToCheck['subdomain'])) {
$form_state->setErrorByName('subdomain', $this->t('The subdomain "@subdomain" is already in use.', ['@subdomain' => $dataToCheck['subdomain']]));
}
@@ -230,11 +243,8 @@ class WisskiCloudAccountManagerCreateForm extends FormBase {
$account["password"] = $field['password'];
$account["subdomain"] = $field['subdomain'];
- $accountResponse = $this->wisskiCloudAccountManagerDaemonApiActions->addAccount($account);
- if (!$accountResponse['success']) {
- throw new Exception('Get no valid response from api daemon. Can not send validiation email.');
- };
- $this->wisskiCloudAccountManagerDaemonApiActions->sendValidationEmail($accountResponse['data']['email'], $accountResponse['data']['validationCode']);
+ $user = $this->wisskiCloudAccountManagerDaemonApiActions->addAccount($account);
+ $this->wisskiCloudAccountManagerDaemonApiActions->sendValidationEmail($user['email'], $user['personName'], $user['validationCode']);
$this->messenger()
->addMessage($this->t('The account data has been successfully saved, please check your email for validation!'));
diff --git a/src/Form/WisskiCloudAccountManagerDeleteForm.php b/src/Form/WisskiCloudAccountManagerDeleteForm.php
new file mode 100755
index 0000000..1ac53de
--- /dev/null
+++ b/src/Form/WisskiCloudAccountManagerDeleteForm.php
@@ -0,0 +1,111 @@
+wisskiCloudAccountManagerDaemonApiActions = $wisskiCloudAccountManagerDaemonApiActions;
+ $aid = \Drupal::routeMatch()->getParameter('aid');
+ $this->account = $this->wisskiCloudAccountManagerDaemonApiActions->getAccounts($aid)[0];
+ }
+
+ /**
+ * 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'),
+ );
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getQuestion() {
+ return $this->t('Do you really want to delete your WissKI Cloud Instance?');
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getCancelUrl() {
+ return Url::fromRoute('wisski_cloud_account_manager.validate')
+ ->setRouteParameter('validationCode', $this->account['validation_code']);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getDescription() {
+ return $this->t('This will delete your WissKI Cloud instance. This action cannot be undone. Your Drupal user and WissKI Cloud account will remain.');
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getConfirmText() {
+ return $this->t('Delete');
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function buildForm(array $form, FormStateInterface $form_state) {
+ $form = parent::buildForm($form, $form_state);
+
+ $form['account_table'] = [
+ '#type' => 'table',
+ '#rows' => [
+ [$this->t('Subdomain'), $this->account['subdomain']],
+ ],
+ ];
+
+ return $form;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function submitForm(array &$form, FormStateInterface $form_state) {
+
+ $aid = \Drupal::routeMatch()->getParameter('aid');
+ $this->wisskiCloudAccountManagerDaemonApiActions->crudInstance('delete', $aid);
+ $form_state->setRedirect('wisski_cloud_account_manager.manage');
+ }
+
+}
diff --git a/src/Form/WisskiCloudAccountManagerProvisionForm.php b/src/Form/WisskiCloudAccountManagerProvisionForm.php
new file mode 100755
index 0000000..631ae32
--- /dev/null
+++ b/src/Form/WisskiCloudAccountManagerProvisionForm.php
@@ -0,0 +1,115 @@
+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'),
+ );
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getQuestion() {
+ return $this->t('Do you really want to start WissKI Cloud provision?');
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getCancelUrl() {
+ return Url::fromRoute('wisski_cloud_account_manager.settings');
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getDescription() {
+ return $this->t('This will start a WissKI Cloud account provision.');
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getConfirmText() {
+ return $this->t('Provise a WissKI Cloud account');
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function buildForm(array $form, FormStateInterface $form_state) {
+ $form = parent::buildForm($form, $form_state);
+ $aid = \Drupal::routeMatch()->getParameter('aid');
+ $account = $this->wisskiCloudAccountManagerDaemonApiActions->getAccounts($aid)[0];
+ $form['info'] = [
+ '#type' => 'table',
+ '#header' => [
+ $this->t('Account id'),
+ $this->t('Account name'),
+ $this->t('Account email'),
+ $this->t('Domain'),
+
+ ],
+ '#rows' => [
+ [
+ $account['aid'],
+ $account['name'],
+ $account['mail'],
+ $account['subdomain'] . '.wisski.cloud',
+ ],
+ ],
+ ];
+ return $form;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function submitForm(array &$form, FormStateInterface $form_state) {
+
+ $aid = \Drupal::routeMatch()->getParameter('aid');
+
+ $result = $this->wisskiCloudAccountManagerDaemonApiActions->crudInstance('create', $aid);
+ $form_state->setRedirect('wisski_cloud_account_manager.manage');
+ }
+
+}
diff --git a/src/Form/WisskiCloudAccountManagerPurgeForm.php b/src/Form/WisskiCloudAccountManagerPurgeForm.php
new file mode 100755
index 0000000..553e459
--- /dev/null
+++ b/src/Form/WisskiCloudAccountManagerPurgeForm.php
@@ -0,0 +1,105 @@
+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'),
+ );
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getQuestion() {
+ return $this->t('Do you really want to purge your WissKI Cloud account?');
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getCancelUrl() {
+ return Url::fromRoute('wisski_cloud_account_manager.settings');
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getDescription() {
+ return $this->t('This will delete your WissKI Cloud account, your Drupal user, your WissKI Cloud instance and all data associated with it. This action cannot be undone.');
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getConfirmText() {
+ return $this->t('Purge');
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function buildForm(array $form, FormStateInterface $form_state) {
+ $form = parent::buildForm($form, $form_state);
+ $aid = \Drupal::routeMatch()->getParameter('aid');
+ $account = $this->wisskiCloudAccountManagerDaemonApiActions->getAccounts($aid)[0];
+ $form['account_table'] = [
+ '#type' => 'table',
+ '#rows' => [
+ [$this->t('Subdomain'), $account['subdomain']],
+ [$this->t('Account name'), $account['name'] ?: $this->t('Seems that Drupal user has already been deleted, delete the remaining account data and instance.')],
+ ],
+ ];
+
+ return $form;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function submitForm(array &$form, FormStateInterface $form_state) {
+
+ $aid = \Drupal::routeMatch()->getParameter('aid');
+ $this->wisskiCloudAccountManagerDaemonApiActions->purgeAccount($aid);
+
+ $form_state->setRedirect('wisski_cloud_account_manager.manage');
+ }
+
+}
diff --git a/src/Form/WisskiCloudAccountManagerSettingsForm.php b/src/Form/WisskiCloudAccountManagerSettingsForm.php
index 6d380a5..f631eff 100755
--- a/src/Form/WisskiCloudAccountManagerSettingsForm.php
+++ b/src/Form/WisskiCloudAccountManagerSettingsForm.php
@@ -42,32 +42,39 @@ class WisskiCloudAccountManagerSettingsForm extends ConfigFormBase {
'#default_value' => $config->get('daemonUrl'),
];
- $form['allAccounts'] = [
+ $form['wsUrl'] = [
'#type' => 'textfield',
- '#title' => $this->t('All accounts URL path'),
- '#description' => $this->t('Provide the endpoint to the GET endpoint for all accounts, i. e. "/account/all"'),
- '#default_value' => $config->get('allAccounts'),
+ '#title' => $this->t('The websocket URL of the WissKI Cloud'),
+ '#description' => $this->t('Provide the complete base URL with protocol, domain (resp. service name in docker), ports and API path, i. e. "wss://panel.wisski.cloud/api/v1/ws"'),
+ '#default_value' => $config->get('wsUrl'),
];
- $form['accountPostUrlPath'] = [
- '#type' => 'textfield',
- '#title' => $this->t('POST URL path'),
- '#description' => $this->t('Provide the path to the POST endpoint, i. e. "/account"'),
- '#default_value' => $config->get('accountPostUrlPath'),
+ $form['wsToken'] = [
+ '#type' => 'password',
+ '#title' => $this->t('The websocket access token of the WissKI Cloud provisioning account.'),
+ '#description' => $this->t('Provide the access token for the websocket, i. e. "1234567890"'),
+ '#default_value' => $config->get('wsToken'),
];
- $form['accountFilterByData'] = [
+ $form['provisionRoute'] = [
'#type' => 'textfield',
- '#title' => $this->t('Filter by Data URL path'),
- '#description' => $this->t('Provide the path to the Get account by data endpoint, i. e. "/account/by_data"'),
- '#default_value' => $config->get('accountFilterByData'),
+ '#title' => $this->t('Instance provision URL path'),
+ '#description' => $this->t('Provide the path to the account validation PUT endpoint, i. e. "/provision"'),
+ '#default_value' => $config->get('provisionRoute'),
];
- $form['accountValidation'] = [
+ $form['deleteRoute'] = [
'#type' => 'textfield',
- '#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'),
+ '#title' => $this->t('Instance delete URL path'),
+ '#description' => $this->t('Provide the path to the account validation DELETE endpoint, i. e. "/delete"'),
+ '#default_value' => $config->get('deleteRoute'),
+ ];
+
+ $form['healthCheckRoute'] = [
+ '#type' => 'textfield',
+ '#title' => $this->t('Deamon health check URL path'),
+ '#description' => $this->t('Provide the path to the health check GET endpoint, i. e. "/health-check"'),
+ '#default_value' => $config->get('healthCheckRoute'),
];
$form['usernameBlacklist'] = [
@@ -121,15 +128,16 @@ class WisskiCloudAccountManagerSettingsForm extends ConfigFormBase {
public function submitForm(array &$form, FormStateInterface $form_state) {
$config = $this->config('wisski_cloud_account_manager.settings');
- $config->set('daemonUrl', $form_state->getValue('daemonUrl'))
- ->set('accountPostUrlPath', $form_state->getValue('accountPostUrlPath'))
- ->set('allAccounts', $form_state->getValue('allAccounts'))
- ->set('accountFilterByData', $form_state->getValue('accountFilterByData'))
- ->set('accountProvisionAndValidationCheck', $form_state->getValue('accountProvisionAndValidationCheck'))
- ->set('accountValidation', $form_state->getValue('accountValidation'))
- ->set('usernameBlacklist', $form_state->getValue('usernameBlacklist'))
+ $config
+ ->set('daemonUrl', $form_state->getValue('daemonUrl'))
+ ->set('deleteRoute', $form_state->getValue('deleteRoute'))
->set('emailProviderBlacklist', $form_state->getValue('emailProviderBlacklist'))
+ ->set('healthCheckRoute', $form_state->getValue('healthCheckRoute'))
+ ->set('provisionRoute', $form_state->getValue('provisionRoute'))
+ ->set('usernameBlacklist', $form_state->getValue('usernameBlacklist'))
->set('subdomainBlacklist', $form_state->getValue('subdomainBlacklist'))
+ ->set('wsUrl', $form_state->getValue('wsUrl'))
+ ->set('wsToken', $form_state->getValue('wsToken'))
->save();
parent::submitForm($form, $form_state);
diff --git a/src/Form/WisskiCloudAccountManagerValidationForm.php b/src/Form/WisskiCloudAccountManagerValidationForm.php
new file mode 100755
index 0000000..9e8dd11
--- /dev/null
+++ b/src/Form/WisskiCloudAccountManagerValidationForm.php
@@ -0,0 +1,113 @@
+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'),
+ );
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getQuestion() {
+ return $this->t('Do you really want to start WissKI Cloud validation?');
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getCancelUrl() {
+ return Url::fromRoute('wisski_cloud_account_manager.settings');
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getDescription() {
+ return $this->t('This will start a WissKI Cloud account validation.');
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getConfirmText() {
+ return $this->t('Validate a WissKI Cloud account');
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function buildForm(array $form, FormStateInterface $form_state) {
+ $form = parent::buildForm($form, $form_state);
+ $aid = \Drupal::routeMatch()->getParameter('aid');
+ $account = $this->wisskiCloudAccountManagerDaemonApiActions->getAccounts($aid)[0];
+ $form['info'] = [
+ '#type' => 'table',
+ '#header' => [
+ $this->t('Account id'),
+ $this->t('Account name'),
+ $this->t('Account email'),
+ $this->t('Domain'),
+
+ ],
+ '#rows' => [
+ [
+ $account['aid'],
+ $account['name'],
+ $account['mail'],
+ $account['subdomain'] . '.wisski.cloud',
+ ],
+ ],
+ ];
+ return $form;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function submitForm(array &$form, FormStateInterface $form_state) {
+ $aid = \Drupal::routeMatch()->getParameter('aid');
+ $this->wisskiCloudAccountManagerDaemonApiActions->validateAccount($aid);
+ $form_state->setRedirect('wisski_cloud_account_manager.manage');
+ }
+
+}
diff --git a/src/WisskiCloudAccountManagerDaemonApiActions.php b/src/WisskiCloudAccountManagerDaemonApiActions.php
index 75b7148..113d5de 100755
--- a/src/WisskiCloudAccountManagerDaemonApiActions.php
+++ b/src/WisskiCloudAccountManagerDaemonApiActions.php
@@ -5,13 +5,17 @@ namespace Drupal\wisski_cloud_account_manager;
use Symfony\Component\HttpFoundation\RequestStack;
use Drupal\Core\Config\Config;
use Drupal\Core\Config\ConfigFactoryInterface;
+use Drupal\Core\Config\Schema\Undefined;
+use Drupal\Core\Database\Connection;
use Drupal\Core\DependencyInjection\DependencySerializationTrait;
use Drupal\Core\Language\LanguageManagerInterface;
use Drupal\Core\Logger\LoggerChannelFactoryInterface;
use Drupal\Core\Mail\MailManagerInterface;
use Drupal\Core\Messenger\MessengerInterface;
use Drupal\Core\Render\Markup;
+use Drupal\Core\Template\TwigEnvironment;
use Drupal\Core\StringTranslation\TranslationInterface;
+use Drupal\user\Entity\User;
use GuzzleHttp\ClientInterface;
/**
@@ -22,32 +26,19 @@ class WisskiCloudAccountManagerDaemonApiActions {
use DependencySerializationTrait;
/**
- * The URL path to all account data GET endpoint.
+ * The admin email address.
*
* @var string
*/
- private string $ALL_ACCOUNTS = '/account/all';
+ private string $ADMIN_EMAIL;
/**
- * The URL path to the POST endpoint.
+ * The URL path to provision PUT endpoint.
*
* @var string
*/
- private string $ACCOUNT_POST_URL_PART = '/account';
+ private string $PROVISION_ROUTE;
- /**
- * The URL path to provision and validation GET endpoint.
- *
- * @var string
- */
- private string $ACCOUNT_PROVISION_AND_VALIDATION_URL_PART;
-
- /**
- * The URL path to provision and validation GET endpoint.
- *
- * @var string
- */
- private string $ACCOUNT_VALIDATION_URL_PART = '/account/validation';
/**
* The base URL of the WissKI Cloud account manager daemon.
@@ -57,18 +48,34 @@ class WisskiCloudAccountManagerDaemonApiActions {
private string $DAEMON_URL;
/**
- * The URL path to the filter by account data GET endpoint.
+ * The URL path to delete DELETE endpoint.
*
* @var string
*/
- private string $FILTER_BY_DATA_URL_PART = '/account/by_data';
+ private string $DELETE_ROUTE;
+
/**
- * The settings config.
+ * The database.
*
- * @var \Drupal\Core\Config\Config
+ * @var \Drupal\Core\Database\Connection
*/
- protected Config $settings;
+ protected Connection $database;
+
+ /**
+ * The Route to the health check GET endpoint.
+ *
+ * @var string
+ */
+ private string $HEALTH_CHECK_ROUTE;
+
+ /**
+ * The Route to the info GET endpoint.
+ *
+ * @var string
+ * @todo not yet implemented
+ */
+ private string $INFO_ROUTE = '/info';
/**
* The HTTP client.
@@ -77,6 +84,13 @@ class WisskiCloudAccountManagerDaemonApiActions {
*/
protected ClientInterface $httpClient;
+ /**
+ * The language manager.
+ *
+ * @var \Drupal\Core\Language\LanguageManagerInterface
+ */
+ protected LanguageManagerInterface $languageManager;
+
/**
* The logger factory.
*
@@ -84,6 +98,13 @@ class WisskiCloudAccountManagerDaemonApiActions {
*/
protected LoggerChannelFactoryInterface $loggerFactory;
+ /**
+ * The mail manager.
+ *
+ * @var \Drupal\Core\Mail\MailManagerInterface
+ */
+ protected MailManagerInterface $mailManager;
+
/**
* The messenger service.
*
@@ -91,20 +112,6 @@ class WisskiCloudAccountManagerDaemonApiActions {
*/
protected MessengerInterface $messenger;
- /**
- * The language manager.
- *
- * @var \Drupal\Core\Language\LanguageManagerInterface
- */
- protected LanguageManagerInterface $languageManager;
-
- /**
- * The mail manager.
- *
- * @var \Drupal\Core\Mail\MailManagerInterface
- */
- protected MailManagerInterface $mailManager;
-
/**
* The request stack.
*
@@ -112,6 +119,15 @@ class WisskiCloudAccountManagerDaemonApiActions {
*/
protected RequestStack $requestStack;
+
+
+ /**
+ * The settings config.
+ *
+ * @var \Drupal\Core\Config\Config
+ */
+ protected Config $settings;
+
/**
* The string translation service.
*
@@ -119,61 +135,212 @@ class WisskiCloudAccountManagerDaemonApiActions {
*/
protected TranslationInterface $stringTranslation;
+ /**
+ * The Twig renderer.
+ *
+ * @var \Drupal\Core\Template\TwigEnvironment
+ */
+ protected TwigEnvironment $twig;
+
/**
* Class constructor.
*/
public function __construct(
ConfigFactoryInterface $configFactory,
+ Connection $database,
ClientInterface $httpClient,
LanguageManagerInterface $languageManager,
LoggerChannelFactoryInterface $loggerFactory,
- MessengerInterface $messenger,
MailManagerInterface $mailManager,
+ MessengerInterface $messenger,
RequestStack $requestStack,
TranslationInterface $stringTranslation,
+ TwigEnvironment $twig
) {
// Services from container.
$settings = $configFactory
- ->getEditable('wisski_cloud_account_manager.settings');
+ ->getEditable('wisski_cloud_account_manager.settings');
+ $this->httpClient = $httpClient;
+ $this->database = $database;
+ $this->languageManager = $languageManager;
+ $this->loggerFactory = $loggerFactory;
+ $this->mailManager = $mailManager;
+ $this->messenger = $messenger;
+ $this->requestStack = $requestStack;
$this->settings = $settings;
$this->stringTranslation = $stringTranslation;
- $this->loggerFactory = $loggerFactory;
- $this->messenger = $messenger;
- $this->httpClient = $httpClient;
- $this->mailManager = $mailManager;
- $this->requestStack = $requestStack;
- $this->languageManager = $languageManager;
+ $this->twig = $twig;
// 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->ALL_ACCOUNTS = $settings->get('allAccounts') ?: '/account/all';
- $this->ACCOUNT_POST_URL_PART = $settings->get('accountPostUrlPath') ?: '/account';
- $this->FILTER_BY_DATA_URL_PART = $settings->get('accountFilterByData') ?: '/account/by_data';
- $this->ACCOUNT_PROVISION_AND_VALIDATION_URL_PART = $settings->get('accountProvisionAndValidationUrlPart') ?: '/account/provision_and_validation';
- $this->ACCOUNT_VALIDATION_URL_PART = $settings->get('accountValidationUrlPart') ?: '/account/validation';
+ $this->DAEMON_URL = $settings->get('daemonUrl') ?: 'http://wisski_cloud_api_daemon_app:2912/wisski-cloud-daemon/api/v1';
+ $this->DELETE_ROUTE = $settings->get('deleteRoute') ?: '/delete';
+ $this->PROVISION_ROUTE = $settings->get('provisionRoute') ?: '/provision';
+ $this->ADMIN_EMAIL = \Drupal::config('system.site')->get('mail');
+ $this->HEALTH_CHECK_ROUTE= $settings->get('healthCheckRoute') ?: '/health-check';
}
/**
- * Adds a new account to the WissKI Cloud account manager daemon.
+ * Adds a new account to the instance.
+ *
+ * First a new Drupal user is created. Additional data is
+ * stored in the wisski_cloud_account_manager_accounts table.
*
* @param array $account
* The account to add.
*
* @return array
- * The response from the daemon (account id with validation code).
+ * The account id with validation code.
*/
public function addAccount(array $account): array {
try {
- $request = [
- 'headers' => [
- 'Content-Type' => 'application/json',
- ],
- 'body' => json_encode($account),
+
+ // Get current language.
+ $language = $this->languageManager->getCurrentLanguage()->getId();
+ // Create Drupal user object.
+ $user = User::create();
+
+ // Mandatory.
+ $user->setPassword($account['password']);
+ $user->enforceIsNew();
+ $user->setEmail($account['email']);
+ $user->setUsername($account['username']); // This username must be unique and accepts only string. It must be a minimum of two characters and can contain only lowercase letters, numbers, and underscores.
+
+ // Optional.
+ $user->set('init', $account['email']);
+ $user->set('langcode', $language);
+ $user->set('preferred_langcode', $language);
+ $user->set('preferred_admin_langcode', $language);
+
+ // Save user.
+ $result = $user->save();
+ $validationCode = $this->generateValidationCode();
+
+ $database = $this->database;
+
+ // Check if a record with this user ID already exists.
+ $query = $database->select('wisski_cloud_account_manager_accounts', 'w')
+ ->fields('w', ['uid'])
+ ->condition('w.uid', $user->id(), '=');
+ $result = $query->execute()->fetchField();
+
+ if ($result) {
+ throw new \Exception('A record with this user ID already exists.');
+ }
+ $query = $database->insert('wisski_cloud_account_manager_accounts')
+ ->fields([
+ 'uid' => $user->id(),
+ 'person_name' => $account['personName'],
+ 'organisation' => $account['organisation'],
+ 'subdomain' => $account['subdomain'],
+ 'validation_code' => $validationCode,
+ ]);
+ $query->execute();
+ return [
+ 'userId' => $user->id(),
+ 'username' => $account['username'],
+ 'personName' => $account['personName'],
+ 'email' => $account['email'],
+ 'subdomain' => $account['subdomain'],
+ 'validationCode' => $validationCode ,
];
- $accountPostUrl = $this->DAEMON_URL . $this->ACCOUNT_POST_URL_PART;
- $response = $this->httpClient->post($accountPostUrl, $request);
- return json_decode($response->getBody()
- ->getContents(), TRUE);
+ }
+ catch (\Exception $e) {
+ // Request failed, handle the error.
+ $this->loggerFactory
+ ->get('wisski_cloud_account_manager')
+ ->error('Can not create account: ' . $e->getMessage());
+ $this->messenger
+ ->addError($this->stringTranslation->translate('Error creating account. See logs for details.'));
+ return [];
+ }
+ }
+
+ /**
+ * Check for redundant account data.
+ *
+ * @param string $column
+ * The column to check.
+ * @param string $value
+ * The value to check.
+ */
+ public function checkForRedundantAccountData(string $column, string $value) {
+ $database = \Drupal::database();
+ $query = $database->select('wisski_cloud_account_manager_accounts', 'w');
+ $query->fields('w', [$column]);
+ $query->condition('w.' . $column, $value, '=');
+ if ($query->execute()->fetchField()) {
+ return TRUE;
+ }
+ else {
+ return FALSE;
+ }
+ }
+
+ /**
+ * Provisions an account in the WissKI Cloud account manager daemon.
+ *
+ * @param string $action
+ * The action to perform: create, delete, get.
+ * @param int $aid
+ * The account ID to provision.
+ *
+ * @return array
+ * The response from the daemon.
+ */
+ public function crudInstance($action, $aid) {
+ try {
+
+ $aid = trim($aid);
+ // Build the query string from the parameters.
+ $query_string = http_build_query([
+ 'aid' => $aid,
+ ]);
+
+ // Determine the route part depending on the action.
+ switch ($action) {
+ case 'create':
+ $restMethod = 'put';
+ $routePart = $this->PROVISION_ROUTE;
+ break;
+ case 'delete':
+ $restMethod = 'delete';
+ $routePart = $this->DELETE_ROUTE;
+ break;
+ default:
+ $restMethod = 'get';
+ $routePart = $this->INFO_ROUTE;
+ break;
+ }
+
+ // Combine the base URL and the query string.
+ $request_url = $this->DAEMON_URL . $routePart . '?' . $query_string;
+ // Send the GET request using the `drupal_http_request()` function.
+ $response = $this->httpClient->request($restMethod, $request_url);
+ // Check the response and handle the data accordingly.
+ if ($response->getStatusCode() == 200 || $response->getStatusCode() == 201) {
+ // Request successful, handle the data in $response->data.
+ $resultArray = json_decode($response->getBody()->getContents(), TRUE);
+ $this->messenger
+ ->addMessage($this->stringTranslation->translate('@message', ['@message' => $resultArray['message']]));
+ return $resultArray;
+
+ }
+ if ($response->getStatusCode() == 404) {
+ // Request successful, handle the data in $response->data.
+ $resultArray = json_decode($response->getBody()->getContents(), TRUE);
+ $this->messenger
+ ->addError($this->stringTranslation->translate('@message', ['@message' => $resultArray['message']]));
+ return $resultArray;
+ }
+ else {
+ // Request failed, handle the error.
+ return [
+ "message" => 'Request failed with code: ' . $response->getStatusCode(),
+ "data" => [],
+ 'success' => FALSE,
+ 'error' => $response->getBody()->getContents(),
+ ];
+ }
}
catch (\Exception $e) {
// Request failed, handle the error.
@@ -181,60 +348,130 @@ class WisskiCloudAccountManagerDaemonApiActions {
->get('wisski_cloud_account_manager')
->error('Request failed with exception: ' . $e->getMessage());
$this->messenger
- ->addError($this->stringTranslation->translate('Can not communicate with the WissKI Cloud account manager daemon. Try again later or contact cloud@wiss-ki.eu.'));
+ ->addError($this->stringTranslation->translate('Can not communicate with the WissKI Cloud account manager daemon. Try again later or contact @email.',
+ ['@email'
+ => $this->ADMIN_EMAIL]));
return [
- "message" => 'Request failed with exception: ' . $e->getMessage(),
- "data" => [
- 'email' => NULL,
- 'validationCode' => NULL,
- ],
+ "message" => 'Request failed with exception.',
+ "data" => [],
'success' => FALSE,
+ 'error' => $e->getMessage(),
];
- }
}
+}
/**
- * Check if an account with the given data already exists.
+ * Deletes an account from the WissKI Cloud account manager daemon.
*
- * @param array $dataToCheck
- * The data to check. Possible keys are:
- * - email
- * - subdomain
- * - username.
+ * @param int $uid
+ * The user ID of the account to delete.
*
* @return array
* The response from the daemon.
*/
- public function checkAccountData(array $dataToCheck): array {
+ public function deleteAccount(int $aid): array {
try {
- // Build the query string from the parameters.
- $query_string = http_build_query($dataToCheck);
+ $database = $this->database;
+ // Select the user ID from the accounts table.
+ $selectQuery = $database->select('wisski_cloud_account_manager_accounts', 'w')
+ ->fields('w', ['uid'])
+ ->condition('w.aid', $aid, '=');
+ $uid = $selectQuery->execute()->fetchField();
+
+ // Delete the account from the accounts table.
+ $deleteQuery = $database->delete('wisski_cloud_account_manager_accounts')
+ ->condition('aid', $aid, '=');
+ $deleteQuery->execute();
+
+ // Delete the user if exists.
+ $user = User::load($uid);
+ $user ? $user->delete() : NULL;
+ $this->messenger
+ ->addMessage($this->stringTranslation->translate('Account deleted successfully.'));
+ return [
+ 'message' => 'Account deleted successfully.',
+ 'success' => TRUE,
+ ];
+ }
+ catch (\Exception $e) {
+ // Request failed, handle the error.
+ $this->loggerFactory
+ ->get('wisski_cloud_account_manager')
+ ->error('Request failed with exception: ' . $e->getMessage());
+ $this->messenger
+ ->addError($this->stringTranslation->translate('Something went wrong!' . $e->getMessage()));
+ }
+ }
+
+ /**
+ * Generates a random validation code with 32 characters.
+ *
+ * @return string
+ * The generated validation code.
+ */
+ function generateValidationCode() {
+ // Generate 16 random bytes and convert them to a 32 characters hexadecimal string
+ $code = bin2hex(random_bytes(16));
+ return $code;
+ }
+
+ /**
+ * Query accounts from the WissKI Cloud account manager daemon.
+ *
+ * @param int $aid
+ * The account ID to query.
+ *
+ * @return array[aid, name, mail, organisation, person_name, provisioned, status, subdomain, uid, validation_code]
+ * The accounts response from the daemon.
+ */
+ public function getAccounts($aid = null): array {
+ try {
+ $query = $this->database->select('wisski_cloud_account_manager_accounts', 'w');
+ $query->fields('w', ['aid', 'organisation', 'person_name', 'provisioned', 'subdomain', 'uid', 'validation_code']);
+ $query->leftjoin('users_field_data', 'u', 'w.uid = u.uid');
+ $query->fields('u', ['name', 'mail', 'status']);
+ if ($aid) {
+ $query->condition('w.aid', $aid, '=');
+ }
+ $accounts = $query->execute()->fetchAll(\PDO::FETCH_ASSOC);
+ return $accounts;
+ }
+ catch (\Exception $e) {
+ // Request failed, handle the error.
+ $this->loggerFactory
+ ->get('wisski_cloud_account_manager')
+ ->error('Request failed with exception: ' . $e->getMessage());
+ $this->messenger
+ ->addError($this->stringTranslation->translate('Can not communicate with the WissKI Cloud account manager daemon. Try again later or contact cloud@wiss-ki.eu.'));
+ return [];
+ }
+ }
+
+ /**
+ * Checks if the WissKI Cloud account manager daemon is available.
+ *
+ * @return array[message:string, success:boolean]
+ *
+ */
+ public function healthCheck() {
+ try {
// Combine the base URL and the query string.
- $request_url = $this->DAEMON_URL . $this->FILTER_BY_DATA_URL_PART . '?' . $query_string;
-
+ $request_url = $this->DAEMON_URL . $this->HEALTH_CHECK_ROUTE;
// Send the GET request using the `drupal_http_request()` function.
- $response = $this->httpClient->get($request_url);
-
+ $response = $this->httpClient->request('get', $request_url);
// Check the response and handle the data accordingly.
if ($response->getStatusCode() == 200) {
// Request successful, handle the data in $response->data.
return [
- "message" => "Get account data",
- "accountData" => json_decode($response->getBody()->getContents(),
- TRUE)['data'],
+ "message" => "WissKI Cloud account manager daemon is available.",
'success' => TRUE,
];
}
else {
// Request failed, handle the error.
return [
- "message" => 'Request failed with code: ' . $response->getStatusCode(),
- "accountData" => [
- 'accountWithUsername' => NULL,
- 'accountWithEmail' => NULL,
- 'accountWithSubdomain' => NULL,
- ],
+ "message" => 'WissKI Cloud account manager daemon is not available: ' . $response->getStatusCode(),
'success' => FALSE,
];
}
@@ -243,90 +480,93 @@ class WisskiCloudAccountManagerDaemonApiActions {
// Request failed, handle the error.
$this->loggerFactory
->get('wisski_cloud_account_manager')
- ->error('Request failed with exception: ' . $e->getMessage());
+ ->error('Something went wrong: ' . $e->getMessage());
$this->messenger
- ->addError($this->stringTranslation->translate('Can not communicate with the WissKI Cloud account manager daemon. Try again later or contact cloud@wiss-ki.eu.'));
- return [
- "message" => 'Request failed with exception: ' . $e->getMessage(),
- "accountData" => [
- 'accountWithUsername' => NULL,
- 'accountWithEmail' => NULL,
- 'accountWithSubdomain' => NULL,
- ],
- 'success' => FALSE,
- ];
+ ->addError($this->stringTranslation->translate('Can not communicate with the WissKI Cloud account manager daemon. Try again later or contact @adminMail.',
+ ['@adminMail'
+ => $this->ADMIN_EMAIL]));
}
}
-
/**
- * Gets all accounts from the WissKI Cloud account manager daemon.
- *
+ * Purges an account via the WissKI Cloud account manager daemon.
+ * Deletes the account from the accounts table and the Drupal user.
+ * Deletes the instance via the daemon from the WissKI Cloud.
+ * @param int $aid
+ * The account ID to purge.
* @return array
- * The accounts response from the daemon.
+ * The response from the daemon.
*/
- public function getAccounts(): array {
+ public function purgeAccount(int $aid) {
try {
- // Combine the base URL and the query string.
- $request_url = $this->DAEMON_URL . $this->ALL_ACCOUNTS;
- // Send the GET request using the `drupal_http_request()` function.
- $response = $this->httpClient->get($request_url);
- return json_decode($response->getBody()->getContents(), TRUE);
+ // Get the account ID from the route.
+
+ // @todo Why is there a space in the account ID?
+ $aid = trim($aid);
+
+
+ // Delete the instance via the daemon from the WissKI Cloud.
+ $response = $this->crudInstance('delete', $aid);
+ if ($response['success']) {
+ // Delete the account and Drupal user.
+ $this->deleteAccount($aid);
+ $this->messenger
+ ->addMessage($this->stringTranslation->translate('Account purged successfully.'));
+ return [
+ 'data' => NULL,
+ 'error' => NULL,
+ 'message' => 'Account purged successfully.',
+ 'success' => TRUE,
+ ];
+
+ }
+ else {
+ if (!$response['error']) {
+ // No success and no error.
+ $this->messenger
+ ->addMessage($this->stringTranslation->translate('Account not found or already purged.'));
+ return [
+ 'data' => NULL,
+ 'error' => NULL,
+ 'message' => $response['message'],
+ 'success' => FALSE,
+ ];
+ }
+ else {
+ // No success and error.
+ $this->messenger
+ ->addError($this->stringTranslation->translate('Something went wrong: ' . $response['message']));
+ $this->loggerFactory->get('wisski_cloud_account_manager')->error($response['error']);
+ return [
+ 'data' => NULL,
+ 'error' => $response['error'],
+ 'message' => 'Something went wrong: ' . $response['message'],
+ 'success' => FALSE,
+ ];
+ }
+ }
}
+
catch (\Exception $e) {
// Request failed, handle the error.
$this->loggerFactory
->get('wisski_cloud_account_manager')
->error('Request failed with exception: ' . $e->getMessage());
$this->messenger
- ->addError($this->stringTranslation->translate('Can not communicate with the WissKI Cloud account manager daemon. Try again later or contact cloud@wiss-ki.eu.'));
- return [
- "message" => 'Request failed with exception: ' . $e->getMessage(),
- "accounts" => [],
- 'success' => FALSE,
- ];
+ ->addError($this->stringTranslation->translate('Something went wrong!' . $e->getMessage()));
}
}
- /**
- * Checks the validation status of the given validation code.
- *
- * @param string $validationCode
- * The validation code to check.
- *
- * @return array
- * The account data from the daemon.
- */
- public function validateAccount(string $validationCode): array {
- try {
- $url = $this->DAEMON_URL . $this->ACCOUNT_VALIDATION_URL_PART . '/' . $validationCode;
- $validationResponse = $this->httpClient->put($url);
- return json_decode($validationResponse->getBody()
- ->getContents(), TRUE);
- }
- catch (\Exception $e) {
- // Request failed, handle the error.
- $this->loggerFactory
- ->get('wisski_cloud_account_manager')
- ->error('Request failed with exception: ' . $e->getMessage());
- $this->messenger
- ->addError($this->stringTranslation->translate('Can not communicate with the WissKI Cloud account manager daemon. Try again later or contact cloud@wiss-ki.eu.'));
- return [
- "message" => 'Request failed with exception: ' . $e->getMessage(),
- "accounts" => [],
- 'success' => FALSE,
- ];
- }
- }
-
- /**
+ /**
* Sends a validation email to the given email address.
*
* @param string $email
* The email address to send the validation email to.
+ * @param string $personName
+ * The person name to be used in the validation email.
* @param string $validationCode
* The validation code to be used in the validation link.
*/
- public function sendValidationEmail(string $email, string $validationCode): void {
+ public function sendValidationEmail(string $email, string $personName, string $validationCode): void {
try {
$module = 'wisski_cloud_account_manager';
$key = 'wisski_cloud_account_validation';
@@ -336,17 +576,19 @@ class WisskiCloudAccountManagerDaemonApiActions {
$validationLink = $this->requestStack->getCurrentRequest()
->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');
- $result = $this->mailManager->mail($module, $key, $to, $langcode, $params, NULL, TRUE);
- if ($result['result'] === TRUE) {
- $this->messenger
- ->addMessage($this->stringTranslation->translate('Email send successfully.'));
- }
- else {
- $this->messenger
- ->addMessage($this->stringTranslation->translate('There was an error sending the email.'), 'error');
+ $message = $this->twig->render('@wisski_cloud_account_manager/wisski-cloud-account-manager-validation-email.html.twig', [
+ 'personName' => $personName,
+ 'validationLink' => $validationLink,
+ ]);
+
+ $params['subject'] = $this->stringTranslation->translate('WissKI Cloud account validation');
+ $params['message'] = Markup::create($message);
+ $result = $this->mailManager->mail($module, $key, $to, $langcode, $params, NULL, TRUE);
+ if ($result['result'] != TRUE) {
+ $this->loggerFactory
+ ->get('wisski_cloud_account_manager')
+ ->error('Email sending operation ended with error: ' . $result['message']);
}
}
catch (\Exception $e) {
@@ -360,4 +602,58 @@ class WisskiCloudAccountManagerDaemonApiActions {
}
+
+ /**
+ * Validates the account.
+ *
+ * @param string $validationCode
+ * The validation code to check.
+ *
+ * @return array [uid, name]
+ */
+ public function validateAccount(string $validationCode): array {
+ try {
+ $selectQuery = $this->database->select('wisski_cloud_account_manager_accounts', 'w')
+ ->fields('w', ['aid', 'organisation', 'person_name', 'provisioned','subdomain', 'validation_code'])
+ ->condition('w.validation_code', $validationCode, '=');
+ $selectQuery->join('users_field_data', 'u', 'w.uid = u.uid');
+ $selectQuery->fields('u', ['uid', 'name', 'mail', 'status']);
+ $account = $selectQuery->execute()->fetchAll(\PDO::FETCH_ASSOC);
+ if (isset($account[0]['status'])) {
+ if ($account[0]['status'] == 0) {
+ $updateQuery = $this->database->update('users_field_data')
+ ->fields(['status' => 1])
+ ->condition('uid', $account['0']['uid'], '=');
+ $updateQuery->execute();
+ $account = $selectQuery->execute()->fetchAll(\PDO::FETCH_ASSOC);
+ $this->messenger
+ ->addMessage($this->stringTranslation->translate('Account validated successfully.'));
+
+ } else {
+ $this->messenger
+ ->addMessage($this->stringTranslation->translate('Account already validated.'));
+ }
+ return [
+ 'uid' => $account[0]['uid'],
+ 'name' => $account[0]['name']];
+ }
+ else {
+ $this->messenger
+ ->addError($this->stringTranslation->translate('Account validation failed. Please contact @adminEmail.',
+ ['@adminEmail'
+ => $this->ADMIN_EMAIL]));
+ return [];
+ }
+ }
+ catch (\Exception $e) {
+ // Request failed, handle the error.
+ $this->loggerFactory
+ ->get('wisski_cloud_account_manager')
+ ->error('Request failed with exception: ' . $e->getMessage());
+ $this->messenger
+ ->addError($this->stringTranslation->translate('Can not communicate with the WissKI Cloud account manager daemon. Try again later or contact cloud@wiss-ki.eu.'));
+ return [];
+ }
+ }
+
}
diff --git a/templates/wisski-cloud-account-manager-account-managing-page.html.twig b/templates/wisski-cloud-account-manager-account-managing-page.html.twig
index 588cf96..d96ee2a 100755
--- a/templates/wisski-cloud-account-manager-account-managing-page.html.twig
+++ b/templates/wisski-cloud-account-manager-account-managing-page.html.twig
@@ -1,56 +1,88 @@
{# wisski_cloud_account_manager/templates/wisski_cloud_account_manager_account_managing_page.html.twig #}
+ {% if healthCheck %}
+
+
{{ healthCheck.message }}
+
+ {% endif %}
{% if accounts is not empty %}
-
+
+
- Id
- Person name
- Email
- Username
- Subdomain
- Valid
- Provisioned
- Options
+ AID
+ UID
+ Person name
+ Organisation
+ Email
+ Username
+ Subdomain
+ Valid
+ Provisioned
+ Options
- {% for item in accounts.data %}
-
- {{ item._id }}
- {{ item.personName }}
- {{ item.email }}
- {{ item.username }}
- {{ item.subdomain }}
+
+ {% for item in accounts %}
+
+ {{ item.aid }}
+ {{ item.uid }} {% if item.status is null %}error_outline {% endif %}
+ {{ item.person_name }}
+ {{ item.organisation }}
+
+ {{ item.mail }}
+
+ {{ item.name }}
+
+ {% if item.provisioned == 2 %}
+ {{ item.subdomain }}.wisski.cloud
+ {% else %}
+ {{ item.subdomain }}.wisski.cloud
+ {% endif %}
+
- {% if item.valid == 1 %}
+ {% if item.status is same as("1") %}
yes
- {% elseif item.valid == 0 %}
+ {% elseif item.status is same as("0") %}
no
{% else %}
unknown
{% endif %}
- {% if item.provisioned == 1 %}
- ongoing
+
+ {% if item.provisioned == 1 %}
+
+ ongoing
+
{% elseif item.provisioned == 2 %}
yes
- {% elseif item.provisioned == 3 %}
+ {% elseif item.provisioned == 0 %}
no
{% else %}
- unknown
+
+ unknown
+
+
{% endif %}
-
-
+
+
select...
- edit
- {% if item.valid == 0 %}
- validate
+ {% if item.status is not null %}
+ edit
+ {% if item.status == 0 %}
+ validate
{% endif %}
{% if item.provisioned == 0 %}
- provise
+ provise
{% endif %}
- delete
+ {% endif %}
+ {% if item.provisioned >= 2 %}
+ delete
+ {% endif %}
+ purge
{% endfor %}
+ {% else %}
+ No accounts found. Go get some friends.
{% endif %}
diff --git a/templates/wisski-cloud-account-manager-health-check-page.html.twig b/templates/wisski-cloud-account-manager-health-check-page.html.twig
new file mode 100755
index 0000000..aaf867b
--- /dev/null
+++ b/templates/wisski-cloud-account-manager-health-check-page.html.twig
@@ -0,0 +1,27 @@
+{# wisski_cloud_account_manager/templates/wisski_cloud_account_manager_validation_page.html.twig #}
+
+
+
+
+ Check
+ Values
+ Test
+ Result
+
+
+
+ {% if healthCheck %}
+
+ healthCheck
+ -
+
+
+
+
+
+ {% endif %}
+
+
+
diff --git a/templates/wisski-cloud-account-manager-validation-email.html.twig b/templates/wisski-cloud-account-manager-validation-email.html.twig
new file mode 100644
index 0000000..92b6672
--- /dev/null
+++ b/templates/wisski-cloud-account-manager-validation-email.html.twig
@@ -0,0 +1,10 @@
+
+
Hi {{ personName }},
+
Thank you for registering to our site.
+
Please validate your account by clicking on this
+ link or copy this to the address bar of your browser:
+
+
{{ validationLink }}
+
You have 24 hours to validate your account.
+
+
diff --git a/templates/wisski-cloud-account-manager-validation-page.html.twig b/templates/wisski-cloud-account-manager-validation-page.html.twig
index cd76b80..7d42596 100755
--- a/templates/wisski-cloud-account-manager-validation-page.html.twig
+++ b/templates/wisski-cloud-account-manager-validation-page.html.twig
@@ -1,52 +1,58 @@
{# wisski_cloud_account_manager/templates/wisski_cloud_account_manager_validation_page.html.twig #}
{% if account is not empty %}
-
+
+
- Person name
- Email
- Username
- Subdomain
- Valid
- Provisioned
+ Account ID
+ Person name
+ Organisation
+ Email
+ Username
+ Subdomain
+ Valid
+ Provisioned
+
+
- {{ account.data.personName }}
- {{ account.data.email }}
- {{ account.data.username }}
- {{ account.data.subdomain }}
+ {{ account.aid }}
+ {{ account.person_name }}
+ {{ account.organisation }}
+ {{ account.mail }}
+ {{ account.name }}
+ {{ account.subdomain }}
- {% if account.data.valid == 1 %}
+ {% if account.status == 1 %}
yes
- {% elseif account.data.valid == 0 %}
+ {% elseif account.status == 0 %}
no
{% else %}
unknown
{% endif %}
- {% if account.data.provisioned == 1 %}
+ {% if account.provisioned == 1 %}
ongoing
- {% elseif account.data.provisioned == 2 %}
+ {% elseif account.provisioned == 2 %}
yes
- {% elseif account.data.provisioned == 3 %}
- failed
- {% else %}
+ {% elseif account.provisioned == 3 %}
unknown
{% endif %}
+
-
- {% if account.data.valid == 1 and account.data.provisioned == 2 %}
-
Your account is valid and provisioned. You can now log in to your account at https://{{ account.data.subdomain }}.wisski.cloud .
- {% elseif account.data.valid == 1 and (account.data.provisioned == 0 or account.data.provisioned == 3)%}
-
Your account is valid but the provision failed or the state is unknown. Please refresh this site and if the state persists contact cloud@wiss-ki.eu to resolve this issue.
- {% elseif account.data.valid == 1 and account.data.provisioned == 1 %}
-
Your account is valid and the provision of your WissKI Cloud instance has started. Please wait a few minutes and refresh this page.
- {% elseif account.data.valid == 0 %}
-
Your account is not valid. Please contact info@wiss-ki.eu to resolve this issue.
+
+ {% if account.status == 1 and account.provisioned == 2 %}
+
Your account is valid and provisioned. You can now log in to your account at https://{{ account.subdomain }}.wisski.cloud .
+ {% elseif account.status == 1 and (account.provisioned == 0 or account.provisioned == 3)%}
+
Your account is valid but the provision failed or the state is unknown. Please refresh this site and if the state persists contact cloud@wiss-ki.eu to resolve this issue.
+ {% elseif account.status == 1 and account.provisioned == 1 %}
+
Your account is valid and the provision of your WissKI Cloud instance has started. Please wait a few minutes and refresh this page.
+ {% elseif account.status == 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.
+
Something went wrong. Please contact info@wiss-ki.eu to resolve this issue.
{% endif %}
diff --git a/wisski_cloud_account_manager.install b/wisski_cloud_account_manager.install
new file mode 100755
index 0000000..b3148ae
--- /dev/null
+++ b/wisski_cloud_account_manager.install
@@ -0,0 +1,61 @@
+ 'The base table for accounts.',
+ 'fields' => [
+ 'aid' => [
+ 'description' => 'The primary identifier for the account.',
+ 'type' => 'serial',
+ 'unsigned' => TRUE,
+ 'not null' => TRUE,
+ ],
+ 'uid' => [
+ 'description' => 'The primary identifier for the account. Same id as user id in drupal.',
+ 'type' => 'int',
+ 'size' => 'tiny',
+ 'not null' => TRUE,
+ ],
+ 'person_name' => [
+ 'description' => 'The name of the person.',
+ 'type' => 'varchar',
+ 'length' => 255,
+ 'not null' => TRUE,
+ ],
+ 'organisation' => [
+ 'description' => 'The organisation of the person.',
+ 'type' => 'varchar',
+ 'length' => 255,
+ 'not null' => FALSE,
+ ],
+ 'subdomain' => [
+ 'description' => 'The subdomain of the account.',
+ 'type' => 'varchar',
+ 'length' => 255,
+ 'not null' => TRUE,
+ ],
+ 'validation_code' => [
+ 'description' => 'The validation code of the account.',
+ 'type' => 'varchar',
+ 'length' => 255,
+ 'not null' => TRUE,
+ ],
+ 'provisioned' => [
+ 'description' => 'The provisioning status of the account. 0 = no, 1 = ongoing, 2 = yes 3 = unknown',
+ 'type' => 'int',
+ 'size' => 'tiny',
+ 'not null' => TRUE,
+ 'default' => 0,
+ ],
+ ],
+ 'primary key' => ['aid'],
+ 'unique keys' => [
+ 'subdomain' => ['subdomain'],
+ 'validation_code' => ['validation_code'],
+ ],
+ ];
+ return $schema;
+}
diff --git a/wisski_cloud_account_manager.libraries.yml b/wisski_cloud_account_manager.libraries.yml
index 106a83b..3cc6a03 100755
--- a/wisski_cloud_account_manager.libraries.yml
+++ b/wisski_cloud_account_manager.libraries.yml
@@ -1,11 +1,20 @@
-wisski_cloud_account_manager:
+globalStyling:
version: 1.x
css:
theme:
css/style.css: {}
+
+accountOptions:
js:
js/accountOptions.js: {}
dependencies:
- core/jquery
- core/drupalSettings
- core/Drupal
+
+provisionStatus:
+ js:
+ js/provisionStatus.js: {}
+ dependencies:
+ - core/jquery
+ - core/Drupal
diff --git a/wisski_cloud_account_manager.links.menu.yml b/wisski_cloud_account_manager.links.menu.yml
index 24068e2..a133423 100755
--- a/wisski_cloud_account_manager.links.menu.yml
+++ b/wisski_cloud_account_manager.links.menu.yml
@@ -1,3 +1,15 @@
+wisski_cloud_account_manager.create_account_page:
+ title: 'WissKI cloud account manager create account page'
+ description: 'Create an account for the WissKI cloud'
+ parent: wisski_cloud_account_manager.settings_menu_block
+ route_name: wisski_cloud_account_manager.create
+
+wisski_cloud_account_manager.overview_page:
+ title: 'WissKI cloud account manager overview page'
+ description: 'WissKI cloud account manager overview page'
+ parent: wisski_cloud_account_manager.settings_menu_block
+ route_name: wisski_cloud_account_manager.manage
+
wisski_cloud_account_manager.settings_menu_block:
title: 'WissKI cloud account manager'
description: 'WissKI cloud account manager'
@@ -10,8 +22,3 @@ wisski_cloud_account_manager.settings_form:
parent: wisski_cloud_account_manager.settings_menu_block
route_name: wisski_cloud_account_manager.settings
-wisski_cloud_account_manager.overview_page:
- title: 'WissKI cloud account manager overview page'
- description: 'WissKI cloud account manager overview page'
- parent: wisski_cloud_account_manager.settings_menu_block
- route_name: wisski_cloud_account_manager.manage
diff --git a/wisski_cloud_account_manager.module b/wisski_cloud_account_manager.module
index 01c9b02..d70ebca 100755
--- a/wisski_cloud_account_manager.module
+++ b/wisski_cloud_account_manager.module
@@ -1,8 +1,44 @@
getRequestTime() - 24 * 60 * 60;
+
+ $ids = \Drupal::entityQuery('user')
+ ->condition('status', 0)
+ ->condition('created', $time_limit, '<')
+ ->accessCheck(TRUE)
+ ->execute();
+
+ // Delete rows from the wisski_cloud_account_manager table.
+ $connection = \Drupal::database();
+
+ $wisskiCloudUsers = $connection->select('wisski_cloud_account_manager', 'wcam')
+ ->fields('wcam', ['uid'])
+ ->condition('uid', $ids, 'IN')
+ ->execute()
+ ->fetchAll();
+
+ $ids = array_map(function($wisskiCloudUser) {
+ return $wisskiCloudUser->uid;
+ }, $wisskiCloudUsers);
+
+ if (empty($ids)) {
+ return;
+ }
+
+ \Drupal::logger('wisski_cloud_account_manager')->notice('Deleting users, who missed the validation: @ids', ['@ids' => implode(', ', $ids)]);
+ $connection->delete('wisski_cloud_account_manager')
+ ->condition('uid', $ids, 'IN')
+ ->execute();
+
+ $storage_handler = \Drupal::entityTypeManager()->getStorage('user');
+ $entities = $storage_handler->loadMultiple($ids);
+ $storage_handler->delete($entities);
+
+}
/**
* Implements hook_help().
@@ -28,6 +64,7 @@ function wisski_cloud_account_manager_help($route_name, \Drupal\Core\Routing\Rou
return $output;
}
+
/**
* Implements hook_mail().
*/
@@ -63,12 +100,22 @@ function wisski_cloud_account_manager_theme($existing, $type, $theme, $path) {
'variables' => ['date' => NULL],
],
'wisski_cloud_account_manager_account_managing_page' => [
- 'variables' => ['accounts' => NULL],
+ 'variables' => [
+ 'accounts' => NULL,
+ 'healthCheck' => NULL,],
],
'wisski_cloud_account_manager_validation_page' => [
'variables' => ['account' => NULL],
],
-
+ 'wisski_cloud_account_manager_health_check_page' => [
+ 'variables' => ['healthCheck' => NULL],
+ ],
+ 'wisski_cloud_account_manager_validation_email' => [
+ 'variables' => [
+ 'personName' => NULL,
+ 'validationLink' => NULL,
+ ],
+ ],
];
}
diff --git a/wisski_cloud_account_manager.routing.yml b/wisski_cloud_account_manager.routing.yml
index 536e4e2..f408b47 100755
--- a/wisski_cloud_account_manager.routing.yml
+++ b/wisski_cloud_account_manager.routing.yml
@@ -14,13 +14,45 @@ wisski_cloud_account_manager.create:
requirements:
_access: 'TRUE'
+wisski_cloud_account_manager.delete:
+ path: '/wisski-cloud-account-manager/delete/{aid}'
+ defaults:
+ _form: '\Drupal\wisski_cloud_account_manager\Form\WisskiCloudAccountManagerDeleteForm'
+ _title: 'Delete WissKI cloud account'
+ requirements:
+ _custom_access: 'wisski_cloud_account_manager.account_route_access_check:access'
+
+wisski_cloud_account_manager.provision_status:
+ path: '/wisski-cloud-account-manager/provision-status/{aid}'
+ defaults:
+ _controller: '\Drupal\wisski_cloud_account_manager\Controller\WisskiCloudAccountManagerController::provisionStatusPage'
+ _title: 'Provision status'
+ requirements:
+ _custom_access: 'wisski_cloud_account_manager.account_route_access_check:access'
+
+wisski_cloud_account_manager.purge:
+ path: '/wisski-cloud-account-manager/purge/{aid}'
+ defaults:
+ _form: '\Drupal\wisski_cloud_account_manager\Form\WisskiCloudAccountManagerPurgeForm'
+ _title: 'Purge WissKI cloud account and WissKI instance'
+ requirements:
+ _custom_access: 'wisski_cloud_account_manager.account_route_access_check:access'
+
wisski_cloud_account_manager.manage:
path: '/wisski-cloud-account-manager/manage'
defaults:
_controller: '\Drupal\wisski_cloud_account_manager\Controller\WisskiCloudAccountManagerController::accountManagingPage'
_title: 'Account managing page'
requirements:
- _permission: 'admister wisski cloud account manager'
+ _permission: 'access content'
+
+wisski_cloud_account_manager.provise:
+ path: '/wisski-cloud-account-manager/provise/{aid}'
+ defaults:
+ _form: '\Drupal\wisski_cloud_account_manager\Form\WisskiCloudAccountManagerProvisionForm'
+ _title: 'Provision WissKI cloud account'
+ requirements:
+ _custom_access: 'wisski_cloud_account_manager.account_route_access_check:access'
wisski_cloud_account_manager.settings:
path: '/admin/config/wisski-cloud-account-manager/settings'
@@ -42,7 +74,7 @@ wisski_cloud_account_manager.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'
+ _title: ' WissKI Cloud account validation'
requirements:
_access: 'TRUE'
token: '[a-zA-Z0-9]+'
diff --git a/wisski_cloud_account_manager.services.yml b/wisski_cloud_account_manager.services.yml
index 655d3b6..008eb87 100755
--- a/wisski_cloud_account_manager.services.yml
+++ b/wisski_cloud_account_manager.services.yml
@@ -3,11 +3,19 @@ services:
class: Drupal\wisski_cloud_account_manager\WisskiCloudAccountManagerDaemonApiActions
arguments:
- '@config.factory'
+ - '@database'
- '@http_client'
- '@language_manager'
- '@logger.factory'
- - '@messenger'
- '@plugin.manager.mail'
+ - '@messenger'
- '@request_stack'
- '@string_translation'
-
+ - '@twig'
+ wisski_cloud_account_manager.account_route_access_check:
+ class: Drupal\wisski_cloud_account_manager\Access\AccountRouteAccessCheck
+ arguments:
+ - '@current_user'
+ - '@database'
+ tags:
+ - { name: access_check, applies_to: _account_route_access_check }