From e0db22915b21cd2279cf29065028283d5a557165 Mon Sep 17 00:00:00 2001
From: Robert Nasarek
Date: Mon, 4 Sep 2023 14:38:02 +0200
Subject: [PATCH] more validation
---
.../WisskiCloudAccountManagerController.php | 7 +-
.../WisskiCloudAccountManagerCreateForm.php | 11 +-
.../WisskiCloudAccountManagerSettingsForm.php | 33 +++-
...skiCloudAccountManagerDaemonApiActions.php | 148 +++++++++++++-----
...nt-manager-account-managing-page.html.twig | 2 -
...nager-terms-and-conditions-page.html.twig} | 0
...-account-manager-validation-page.html.twig | 2 -
wisski_cloud_account_manager.links.menu.yml | 23 ++-
wisski_cloud_account_manager.module | 25 ++-
wisski_cloud_account_manager.permissions.yml | 6 +
wisski_cloud_account_manager.routing.yml | 20 ++-
wisski_cloud_account_manager.services.yml | 1 +
12 files changed, 196 insertions(+), 82 deletions(-)
rename templates/{wisski_cloud_account_manager_terms-and-conditions-page.html.twig => wisski-cloud-account-manager-terms-and-conditions-page.html.twig} (100%)
create mode 100644 wisski_cloud_account_manager.permissions.yml
diff --git a/src/Controller/WisskiCloudAccountManagerController.php b/src/Controller/WisskiCloudAccountManagerController.php
index c9f54f2..5a651d7 100644
--- a/src/Controller/WisskiCloudAccountManagerController.php
+++ b/src/Controller/WisskiCloudAccountManagerController.php
@@ -47,7 +47,7 @@ class WisskiCloudAccountManagerController extends ControllerBase {
*/
public function termsAndConditionsPage(): array {
$build = [
- '#theme' => 'terms_and_conditions_page',
+ '#theme' => 'wisski_cloud_account_manager_terms_and_conditions_page',
'#date' => date('Y'),
];
return $build;
@@ -63,10 +63,7 @@ class WisskiCloudAccountManagerController extends ControllerBase {
* The page build array.
*/
public function validationPage(string $validationCode): array {
- $validationResponse = $this->wisskiCloudAccountManagerDaemonApiActions->validateAccount($validationCode);
-
- $account = json_decode($validationResponse->getBody()
- ->getContents(), TRUE);
+ $account = $this->wisskiCloudAccountManagerDaemonApiActions->validateAccount($validationCode);
return [
'#theme' => 'wisski_cloud_account_manager_validation_page',
'#account' => $account,
diff --git a/src/Form/WisskiCloudAccountManagerCreateForm.php b/src/Form/WisskiCloudAccountManagerCreateForm.php
index 7edeb11..3e77fff 100644
--- a/src/Form/WisskiCloudAccountManagerCreateForm.php
+++ b/src/Form/WisskiCloudAccountManagerCreateForm.php
@@ -172,6 +172,7 @@ class WisskiCloudAccountManagerCreateForm extends FormBase {
// @todo Check if username is WissKI Cloud accounts, i.e add direct by admin?.
$dataToCheck['username'] = $form_state->getValue('username');
$dataToCheck['email'] = $form_state->getValue('email');
+ $dataToCheck['emailProvider'] = explode('@', $dataToCheck['email'])[1];
$dataToCheck['subdomain'] = $form_state->getValue('subdomain');
$response = $this->wisskiCloudAccountManagerDaemonApiActions->checkAccountData($dataToCheck);
@@ -182,13 +183,17 @@ class WisskiCloudAccountManagerCreateForm extends FormBase {
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'], explode(',', $this->settings->get('usernameBlacklist')))) {
+ if (in_array($dataToCheck['username'], preg_split('/\r\n|\r|\n/', $this->settings->get('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']]));
}
+ if (in_array($dataToCheck['emailProvider'], preg_split('/\r\n|\r|\n/', $this->settings->get('emailProviderBlacklist')))) {
+ $form_state->setErrorByName('email', $this->t('The email provider "@provider"is not allowed.', ['@provider' => $dataToCheck['emailProvider']]));
+ }
+
if ($response['accountData']['accountWithEmail']) {
$form_state->setErrorByName('email', $this->t('The email "@email" is already in use.', ['@email' => $dataToCheck['email']]));
}
@@ -197,7 +202,7 @@ class WisskiCloudAccountManagerCreateForm extends FormBase {
$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'], explode(',', $this->settings->get('subdomainBlacklist')))) {
+ if (in_array($dataToCheck['subdomain'], preg_split('/\r\n|\r|\n/', $this->settings->get('subdomainBlacklist')))) {
$form_state->setErrorByName('subdomain', $this->t('The subdomain "@subdomain" is not allowed.', ['@subdomain' => $dataToCheck['subdomain']]));
}
if ($response['accountData']['accountWithSubdomain']) {
@@ -231,6 +236,8 @@ class WisskiCloudAccountManagerCreateForm extends FormBase {
->addMessage($this->t('The account data has been successfully saved, please check your email for validation!'));
}
catch (\Exception $ex) {
+ $this->messenger()
+ ->addError($this->t('The account data could not be saved, please try again later or write an email to cloud@wiss-ki.eu.'));
$this->logger('wisski_cloud_account_manager')->error($ex->getMessage());
}
}
diff --git a/src/Form/WisskiCloudAccountManagerSettingsForm.php b/src/Form/WisskiCloudAccountManagerSettingsForm.php
index ed63ad9..ca1c710 100644
--- a/src/Form/WisskiCloudAccountManagerSettingsForm.php
+++ b/src/Form/WisskiCloudAccountManagerSettingsForm.php
@@ -71,15 +71,28 @@ class WisskiCloudAccountManagerSettingsForm extends ConfigFormBase {
];
$form['usernameBlacklist'] = [
- '#type' => 'textfield',
+ '#type' => 'textarea',
'#title' => $this->t('Username blacklist'),
- '#description' => $this->t('Provide blocked usernames with a comma separated list, i. e. "admin,root"'),
+ '#rows' => '5',
+ '#cols' => '60',
+ '#description' => $this->t('Provide blocked usernames separeated by new lines, i. e. "\n admin \n root"'),
'#default_value' => $config->get('usernameBlacklist'),
];
+ $form['emailProviderBlacklist'] = [
+ '#type' => 'textarea',
+ '#title' => $this->t('Email provider blacklist'),
+ '#rows' => '5',
+ '#cols' => '60',
+ '#resizable' => 'vertical',
+ '#description' => $this->t('Provide blocked email providers with a comma separated list, i. e. "\n admin\nroot"'),
+ '#default_value' => $config->get('emailProviderBlacklist'),
+ ];
$form['subdomainBlacklist'] = [
- '#type' => 'textfield',
+ '#type' => 'textarea',
+ '#rows' => '5',
+ '#cols' => '60',
'#title' => $this->t('Subdomain blacklist'),
- '#description' => $this->t('Provide blocked subdomain with a comma separated list, i. e. "www,admin,root"'),
+ '#description' => $this->t('Provide blocked subdomain with a comma separated list, i. e. "\nwww\nadmin\nroot"'),
'#default_value' => $config->get('subdomainBlacklist'),
];
@@ -91,11 +104,14 @@ class WisskiCloudAccountManagerSettingsForm extends ConfigFormBase {
*/
public function validateForm(array &$form, FormStateInterface $form_state): void {
parent::validateForm($form, $form_state);
- if (!preg_match("/^(?:\w+(?:,\w+)*)?$/", $form_state->getValue('usernameBlacklist'))) {
- $form_state->setErrorByName('usernameBlacklist', $this->t('The username blacklist is not valid. Only words separated by commas are allowed.'));
+ if (!preg_match("/^[a-zA-Z0-9\-]+(\r?\n[a-zA-Z0-9\-]+)*$/", $form_state->getValue('usernameBlacklist'))) {
+ $form_state->setErrorByName('usernameBlacklist', $this->t('The username blacklist is not valid. Only words separated by new lines are allowed.'));
}
- if (!preg_match("/^(?:\w+(?:,\w+)*)?$/", $form_state->getValue('subdomainBlacklist'))) {
- $form_state->setErrorByName('subdomainBlacklist', $this->t('The subdomain blacklist is not valid. Only words separated by commas are allowed.'));
+ if (!preg_match("/^([a-zA-Z0-9-]+\.[a-zA-Z0-9-]+)+(\r?\n[a-zA-Z0-9-]+\.[a-zA-Z0-9-]+)*$/", $form_state->getValue('emailProviderBlacklist'))) {
+ $form_state->setErrorByName('emailProviderBlacklist', $this->t('The email provider blacklist is not valid. Only <second level domain> <dot> <first level domain> separated by new lines are allowed.'));
+ }
+ if (!preg_match("/^[a-zA-Z0-9\-]+(\r?\n[a-zA-Z0-9\-]+)*$/", $form_state->getValue('subdomainBlacklist'))) {
+ $form_state->setErrorByName('subdomainBlacklist', $this->t('The subdomain blacklist is not valid. Only words separated by new lines are allowed.'));
}
}
@@ -111,6 +127,7 @@ class WisskiCloudAccountManagerSettingsForm extends ConfigFormBase {
->set('accountProvisionAndValidationCheck', $form_state->getValue('accountProvisionAndValidationCheck'))
->set('accountValidation', $form_state->getValue('accountValidation'))
->set('usernameBlacklist', $form_state->getValue('usernameBlacklist'))
+ ->set('emailProviderBlacklist', $form_state->getValue('emailProviderBlacklist'))
->set('subdomainBlacklist', $form_state->getValue('subdomainBlacklist'))
->save();
diff --git a/src/WisskiCloudAccountManagerDaemonApiActions.php b/src/WisskiCloudAccountManagerDaemonApiActions.php
index 93630d1..75b7148 100644
--- a/src/WisskiCloudAccountManagerDaemonApiActions.php
+++ b/src/WisskiCloudAccountManagerDaemonApiActions.php
@@ -2,6 +2,7 @@
namespace Drupal\wisski_cloud_account_manager;
+use Symfony\Component\HttpFoundation\RequestStack;
use Drupal\Core\Config\Config;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\DependencyInjection\DependencySerializationTrait;
@@ -12,7 +13,6 @@ 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.
@@ -105,6 +105,13 @@ class WisskiCloudAccountManagerDaemonApiActions {
*/
protected MailManagerInterface $mailManager;
+ /**
+ * The request stack.
+ *
+ * @var \Symfony\Component\HttpFoundation\RequestStack
+ */
+ protected RequestStack $requestStack;
+
/**
* The string translation service.
*
@@ -122,21 +129,21 @@ class WisskiCloudAccountManagerDaemonApiActions {
LoggerChannelFactoryInterface $loggerFactory,
MessengerInterface $messenger,
MailManagerInterface $mailManager,
+ RequestStack $requestStack,
TranslationInterface $stringTranslation,
) {
// Services from container.
+ $settings = $configFactory
+ ->getEditable('wisski_cloud_account_manager.settings');
+ $this->settings = $settings;
$this->stringTranslation = $stringTranslation;
$this->loggerFactory = $loggerFactory;
$this->messenger = $messenger;
$this->httpClient = $httpClient;
$this->mailManager = $mailManager;
+ $this->requestStack = $requestStack;
$this->languageManager = $languageManager;
- // Settings.
- $settings = $configFactory
- ->getEditable('wisski_cloud_account_manager.settings');
- $this->settings = $settings;
-
// 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';
@@ -156,16 +163,34 @@ class WisskiCloudAccountManagerDaemonApiActions {
* The response from the daemon (account id with validation code).
*/
public function addAccount(array $account): array {
- $request = [
- 'headers' => [
- 'Content-Type' => 'application/json',
- ],
- 'body' => json_encode($account),
- ];
- $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()]);
+ try {
+ $request = [
+ 'headers' => [
+ 'Content-Type' => 'application/json',
+ ],
+ 'body' => json_encode($account),
+ ];
+ $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('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(),
+ "data" => [
+ 'email' => NULL,
+ 'validationCode' => NULL,
+ ],
+ 'success' => FALSE,
+ ];
+ }
}
/**
@@ -219,6 +244,8 @@ class WisskiCloudAccountManagerDaemonApiActions {
$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(),
"accountData" => [
@@ -238,11 +265,26 @@ class WisskiCloudAccountManagerDaemonApiActions {
* The accounts response from the daemon.
*/
public function getAccounts(): array {
- // 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);
+ 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);
+ }
+ 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,
+ ];
+ }
}
/**
@@ -251,12 +293,29 @@ class WisskiCloudAccountManagerDaemonApiActions {
* @param string $validationCode
* The validation code to check.
*
- * @return \Psr\Http\Message\ResponseInterface
- * The response from the daemon.
+ * @return array
+ * The account data from the daemon.
*/
- public function validateAccount(string $validationCode): ResponseInterface {
- $url = $this->DAEMON_URL . $this->ACCOUNT_VALIDATION_URL_PART . '/' . $validationCode;
- return $this->httpClient->put($url);
+ 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,
+ ];
+ }
}
/**
@@ -268,26 +327,37 @@ class WisskiCloudAccountManagerDaemonApiActions {
* The validation code to be used in the validation link.
*/
public function sendValidationEmail(string $email, string $validationCode): void {
- $module = 'wisski_cloud_account_manager';
- $key = 'wisski_cloud_account_validation';
- $langcode = $this->languageManager->getDefaultLanguage()->getId();
- $to = $email;
+ try {
+ $module = 'wisski_cloud_account_manager';
+ $key = 'wisski_cloud_account_validation';
+ $langcode = $this->languageManager->getDefaultLanguage()->getId();
+ $to = $email;
- $validationLink = \Drupal::request()
+ $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');
+ $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');
- $result = $this->mailManager->mail($module, $key, $to, $langcode, $params, NULL, TRUE);
- if ($result['result'] === TRUE) {
- $this->messenger
- ->addMessage($this->stringTranslation->translate('Email sent successfully.'));
+ }
}
- else {
+ catch (\Exception $e) {
+ // Request failed, handle the error.
+ $this->loggerFactory
+ ->get('wisski_cloud_account_manager')
+ ->error('Email sending operation ended with exception: ' . $e->getMessage());
$this->messenger
- ->addMessage($this->stringTranslation->translate('There was an error sending the email.'), 'error');
+ ->addError($this->stringTranslation->translate('Email sending operation ended with error. Try again later or contact cloud@wiss-ki.eu.'));
}
+
}
}
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 e457fe3..ffb3f5b 100644
--- a/templates/wisski-cloud-account-manager-account-managing-page.html.twig
+++ b/templates/wisski-cloud-account-manager-account-managing-page.html.twig
@@ -10,7 +10,6 @@
Subdomain |
Valid |
Provisioned |
- Error |
Options |
{% for item in accounts.data %}
@@ -38,7 +37,6 @@
{% else %}
unknown
{% endif %}
- {{ accounts.error }} |
|