From 92c0ec40d4a8b19d63b35a38fa7db833432ef7f5 Mon Sep 17 00:00:00 2001 From: Mikkel Ricky Date: Tue, 7 May 2024 14:26:01 +0200 Subject: [PATCH 01/46] Moved digital post settings into config. Added support for os2web_key to get certificate. # Conflicts: # CHANGELOG.md # composer.json # modules/os2forms_digital_post/src/Helper/CertificateLocatorHelper.php # modules/os2forms_digital_post/src/Helper/DigitalPostHelper.php --- .github/workflows/pr.yml | 31 +-- .gitignore | 2 - .markdownlint.jsonc | 13 + .markdownlintrc | 18 -- CHANGELOG.md | 3 + README.md | 20 +- composer.json | 68 +++-- modules/os2forms_digital_post/README.md | 4 + .../os2forms_digital_post.info.yml | 1 + .../os2forms_digital_post.install | 9 + .../os2forms_digital_post.services.yml | 6 +- .../src/Exception/InvalidSettingException.php | 10 - .../src/Form/SettingsForm.php | 238 +++++++----------- .../src/Helper/CertificateLocatorHelper.php | 79 ------ .../src/Helper/DigitalPostHelper.php | 8 +- .../src/Helper/KeyCertificateLocator.php | 59 +++++ .../src/Helper/MemoryCertificateLocator.php | 49 ++++ .../src/Helper/Settings.php | 146 +++++++---- package.json | 13 - scripts/code-analysis | 18 +- 20 files changed, 418 insertions(+), 377 deletions(-) create mode 100644 .markdownlint.jsonc delete mode 100644 .markdownlintrc delete mode 100644 modules/os2forms_digital_post/src/Exception/InvalidSettingException.php delete mode 100644 modules/os2forms_digital_post/src/Helper/CertificateLocatorHelper.php create mode 100644 modules/os2forms_digital_post/src/Helper/KeyCertificateLocator.php create mode 100644 modules/os2forms_digital_post/src/Helper/MemoryCertificateLocator.php delete mode 100644 package.json diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index f50b23dc..c78e9623 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -50,6 +50,9 @@ jobs: composer validate --strict composer.json # Check that dependencies resolve. composer update --${{ matrix.dependency-version }} --prefer-dist --no-interaction + - name: Check that composer file is normalized + run: | + composer normalize --dry-run php-coding-standards: name: PHP coding standards @@ -113,27 +116,13 @@ jobs: run: | ./scripts/code-analysis - markdownlint: + coding-standards-markdown: + name: Markdown coding standards runs-on: ubuntu-latest - name: markdownlint steps: - name: Checkout - uses: actions/checkout@v2 - - name: Get yarn cache directory path - id: yarn-cache-dir-path - run: echo "::set-output name=dir::$(yarn cache dir)" - - name: Cache yarn packages - uses: actions/cache@v2 - id: yarn-cache - with: - path: ${{ steps.yarn-cache-dir-path.outputs.dir }} - key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} - restore-keys: | - ${{ runner.os }}-yarn- - - name: Yarn install - uses: actions/setup-node@v2 - with: - node-version: '20' - - run: yarn install - - name: markdownlint - run: yarn coding-standards-check/markdownlint + uses: actions/checkout@master + + - name: Coding standards + run: | + docker run --rm --volume $PWD:/md peterdavehello/markdownlint markdownlint --ignore vendor --ignore LICENSE.md '**/*.md' diff --git a/.gitignore b/.gitignore index 1cc8643c..1a6c2523 100644 --- a/.gitignore +++ b/.gitignore @@ -4,5 +4,3 @@ composer.lock vendor -node_modules/ -yarn.lock diff --git a/.markdownlint.jsonc b/.markdownlint.jsonc new file mode 100644 index 00000000..a28c5809 --- /dev/null +++ b/.markdownlint.jsonc @@ -0,0 +1,13 @@ +{ + "default": true, + // https://github.com/DavidAnson/markdownlint/blob/main/doc/md013.md + "line-length": { + "line_length": 120, + "code_blocks": false, + "tables": false + }, + // https://github.com/DavidAnson/markdownlint/blob/main/doc/md024.md + "no-duplicate-heading": { + "siblings_only": true + } +} diff --git a/.markdownlintrc b/.markdownlintrc deleted file mode 100644 index 75637156..00000000 --- a/.markdownlintrc +++ /dev/null @@ -1,18 +0,0 @@ -{ - // @see https://github.com/DavidAnson/markdownlint/blob/main/schema/.markdownlint.jsonc - // https://github.com/DavidAnson/markdownlint/blob/main/doc/md013.md - "MD013": { - // Exclude code blocks - "code_blocks": false - }, - - // Prevent complaining on duplicated headings in CHANGELOG.md - // https://github.com/DavidAnson/markdownlint/blob/main/doc/md024.md - "MD024": { - "siblings_only": true - } -} - -// Local Variables: -// mode: json -// End: diff --git a/CHANGELOG.md b/CHANGELOG.md index 8146cb76..4f03e6d0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,9 @@ before starting to add changes. Use example [placed in the end of the page](#exa ## [Unreleased] +- [#101](https://github.com/OS2Forms/os2forms/pull/101) + Added support for os2web_key + ## [3.21.0] 2024-12-17 - Updated `os2web_audit`. diff --git a/README.md b/README.md index 12e4ad05..90245a21 100644 --- a/README.md +++ b/README.md @@ -122,29 +122,27 @@ run the checks locally. ```sh docker run --rm --volume ${PWD}:/app --workdir /app itkdev/php8.1-fpm composer install -docker run --rm --volume ${PWD}:/app --workdir /app itkdev/php8.1-fpm composer coding-standards-check - # Fix (some) coding standards issues. docker run --rm --volume ${PWD}:/app --workdir /app itkdev/php8.1-fpm composer coding-standards-apply +docker run --rm --volume ${PWD}:/app --workdir /app itkdev/php8.1-fpm composer coding-standards-check ``` ### Markdown ```sh -docker run --rm --volume ${PWD}:/app --workdir /app node:20 yarn install -docker run --rm --volume ${PWD}:/app --workdir /app node:20 yarn coding-standards-check/markdownlint - -# Fix (some) coding standards issues. -docker run --rm --volume ${PWD}:/app --workdir /app node:20 yarn coding-standards-apply/markdownlint +docker run --rm --volume $PWD:/md peterdavehello/markdownlint markdownlint --ignore vendor --ignore LICENSE.md '**/*.md' --fix +docker run --rm --volume $PWD:/md peterdavehello/markdownlint markdownlint --ignore vendor --ignore LICENSE.md '**/*.md' ``` ## Code analysis We use [PHPStan](https://phpstan.org/) for static code analysis. -Running statis code analysis on a standalone Drupal module is a bit tricky, so -we use a helper script to run the analysis: +Running statis code analysis on a standalone Drupal module is a bit tricky, so we use a helper script to run the +analysis: -```sh -./scripts/code-analysis +```shell +docker run --rm --volume ${PWD}:/app --workdir /app itkdev/php8.1-fpm ./scripts/code-analysis ``` + +**Note**: Currently the code analysis is only run on the `os2forms_digital_post` sub-module (cf. [`phpstan.neon`](./phpstan.neon)). diff --git a/composer.json b/composer.json index 401909b2..1bcbbd1f 100644 --- a/composer.json +++ b/composer.json @@ -1,20 +1,8 @@ { "name": "os2forms/os2forms", - "type": "drupal-module", "description": "Drupal 8 OS2Form module provides advanced webform functionality for Danish Municipalities", - "minimum-stability": "dev", - "prefer-stable": true, "license": "EUPL-1.2", - "repositories": { - "drupal": { - "type": "composer", - "url": "https://packages.drupal.org/8" - }, - "assets": { - "type": "composer", - "url": "https://asset-packagist.org" - } - }, + "type": "drupal-module", "require": { "php": "^8.1", "ext-dom": "*", @@ -43,7 +31,7 @@ "drupal/mailsystem": "^4.1", "drupal/masquerade": "^2.0@RC", "drupal/pathauto": "^1.5", - "drupal/permissions_by_term": "^3.1 || ^2.25", + "drupal/permissions_by_term": "^2.25 || ^3.1", "drupal/queue_mail": "^1.4", "drupal/r4032login": "^2.1", "drupal/redirect": "^1.4", @@ -70,6 +58,7 @@ "itk-dev/serviceplatformen": "^1.5", "os2web/os2web_audit": "^0.1.6", "os2web/os2web_datalookup": "^2.0", + "os2web/os2web_key": "dev-os2web_key", "os2web/os2web_nemlogin": "^1.0", "php-http/guzzle7-adapter": "^1.0", "phpoffice/phpword": "^0.18.2", @@ -83,15 +72,44 @@ "dealerdirect/phpcodesniffer-composer-installer": "^0.7.1", "drupal/coder": "^8.3", "drupal/maillog": "^1.0", + "ergebnis/composer-normalize": "^2.42", "mglaman/phpstan-drupal": "^1.1", "phpstan/extension-installer": "^1.3", "phpstan/phpstan-deprecation-rules": "^1.1", "phpunit/phpunit": "^9.5", "wsdltophp/packagegenerator": "^4.0" }, - "extra" : { + "repositories": { + "os2web/os2web_key": { + "type": "vcs", + "url": "https://github.com/itk-dev/os2web_key" + }, + "drupal": { + "type": "composer", + "url": "https://packages.drupal.org/8" + }, + "assets": { + "type": "composer", + "url": "https://asset-packagist.org" + } + }, + "minimum-stability": "dev", + "prefer-stable": true, + "config": { + "allow-plugins": { + "cweagans/composer-patches": true, + "dealerdirect/phpcodesniffer-composer-installer": true, + "ergebnis/composer-normalize": true, + "phpstan/extension-installer": true, + "simplesamlphp/composer-module-installer": true, + "vaimo/composer-patches": true, + "zaporylie/composer-drupal-optimizations": true + }, + "sort-packages": true + }, + "extra": { "composer-exit-on-patch-failure": false, - "enable-patching" : true, + "enable-patching": true, "patches": { "drupal/entity_print": { "2733781 - Add Export to Word Support": "https://www.drupal.org/files/issues/2019-11-22/2733781-47.patch" @@ -123,23 +141,23 @@ } }, "scripts": { - "code-analysis/phpstan": [ - "phpstan analyse" - ], "code-analysis": [ "@code-analysis/phpstan" ], - "coding-standards-check/phpcs": [ - "phpcs --standard=phpcs.xml.dist" + "code-analysis/phpstan": [ + "phpstan analyse" ], - "coding-standards-check": [ - "@coding-standards-check/phpcs" + "coding-standards-apply": [ + "@coding-standards-apply/phpcs" ], "coding-standards-apply/phpcs": [ "phpcbf --standard=phpcs.xml.dist" ], - "coding-standards-apply": [ - "@coding-standards-apply/phpcs" + "coding-standards-check": [ + "@coding-standards-check/phpcs" + ], + "coding-standards-check/phpcs": [ + "phpcs --standard=phpcs.xml.dist" ] }, "config": { diff --git a/modules/os2forms_digital_post/README.md b/modules/os2forms_digital_post/README.md index a487b13e..c36e9f48 100644 --- a/modules/os2forms_digital_post/README.md +++ b/modules/os2forms_digital_post/README.md @@ -31,6 +31,10 @@ examples](modules/os2forms_digital_post_examples/README.md). Go to `/admin/os2forms_digital_post/settings` to set up global settings for digital post. +### Key + +We use [os2web_key](https://github.com/OS2web/os2web_key) to provide the certificate for sending digital post. + ### Queue The actual sending of digital post is handled by jobs in an [Advanced diff --git a/modules/os2forms_digital_post/os2forms_digital_post.info.yml b/modules/os2forms_digital_post/os2forms_digital_post.info.yml index 71a17688..0e1408cc 100644 --- a/modules/os2forms_digital_post/os2forms_digital_post.info.yml +++ b/modules/os2forms_digital_post/os2forms_digital_post.info.yml @@ -7,6 +7,7 @@ dependencies: - 'beskedfordeler:beskedfordeler' - 'drupal:advancedqueue' - 'os2web_datalookup:os2web_datalookup' + - 'os2web_key:os2web_key' - 'webform:webform' - 'webform:webform_submission_log' - 'os2web:os2web_audit' diff --git a/modules/os2forms_digital_post/os2forms_digital_post.install b/modules/os2forms_digital_post/os2forms_digital_post.install index 760743cb..80b756ac 100644 --- a/modules/os2forms_digital_post/os2forms_digital_post.install +++ b/modules/os2forms_digital_post/os2forms_digital_post.install @@ -17,3 +17,12 @@ use Drupal\os2forms_digital_post\Helper\BeskedfordelerHelper; function os2forms_digital_post_schema() { return Drupal::service(BeskedfordelerHelper::class)->schema(); } + +/** + * Implements hook_update_N(). + */ +function os2forms_digital_post_update_9001() { + \Drupal::service('module_installer')->install([ + 'os2web_key', + ], TRUE); +} diff --git a/modules/os2forms_digital_post/os2forms_digital_post.services.yml b/modules/os2forms_digital_post/os2forms_digital_post.services.yml index c13fb96f..66bc3132 100644 --- a/modules/os2forms_digital_post/os2forms_digital_post.services.yml +++ b/modules/os2forms_digital_post/os2forms_digital_post.services.yml @@ -9,11 +9,13 @@ services: Drupal\os2forms_digital_post\Helper\Settings: arguments: - - "@keyvalue" + - "@config.factory" + - "@key.repository" Drupal\os2forms_digital_post\Helper\CertificateLocatorHelper: arguments: - "@Drupal\\os2forms_digital_post\\Helper\\Settings" + - "@key.repository" Drupal\os2forms_digital_post\Helper\MeMoHelper: arguments: @@ -30,7 +32,7 @@ services: Drupal\os2forms_digital_post\Helper\DigitalPostHelper: arguments: - "@Drupal\\os2forms_digital_post\\Helper\\Settings" - - "@Drupal\\os2forms_digital_post\\Helper\\CertificateLocatorHelper" + - "@Drupal\\os2web_key\\CertificateHelper" - "@plugin.manager.os2web_datalookup" - "@Drupal\\os2forms_digital_post\\Helper\\MeMoHelper" - "@Drupal\\os2forms_digital_post\\Helper\\ForsendelseHelper" diff --git a/modules/os2forms_digital_post/src/Exception/InvalidSettingException.php b/modules/os2forms_digital_post/src/Exception/InvalidSettingException.php deleted file mode 100644 index c3d34af6..00000000 --- a/modules/os2forms_digital_post/src/Exception/InvalidSettingException.php +++ /dev/null @@ -1,10 +0,0 @@ -queueStorage = $entityTypeManager->getStorage('advancedqueue_queue'); } @@ -44,12 +46,23 @@ public function __construct( */ public static function create(ContainerInterface $container) { return new static( + $container->get('config.factory'), + $container->get('entity_type.manager'), $container->get(Settings::class), - $container->get(CertificateLocatorHelper::class), - $container->get('entity_type.manager') ); } + /** + * {@inheritdoc} + * + * @phpstan-return array + */ + protected function getEditableConfigNames() { + return [ + Settings::CONFIG_NAME, + ]; + } + /** * {@inheritdoc} */ @@ -63,15 +76,26 @@ public function getFormId() { * @phpstan-param array $form * @phpstan-return array */ - public function buildForm(array $form, FormStateInterface $form_state) { - $form['test_mode'] = [ + public function buildForm(array $form, FormStateInterface $form_state): array { + $form = parent::buildForm($form, $form_state); + + $form['message'] = [ + '#theme' => 'status_messages', + '#message_list' => [ + 'status' => [ + $this->t('Use drush os2forms-digital-post:test:send to test sending digital post.'), + ], + ], + ]; + + $form[Settings::TEST_MODE] = [ '#type' => 'checkbox', '#title' => $this->t('Test mode'), - '#default_value' => $this->settings->getTestMode(), + '#default_value' => $this->settings->getEditableValue(Settings::TEST_MODE), + '#description' => $this->createDescription(Settings::TEST_MODE), ]; - $sender = $this->settings->getSender(); - $form['sender'] = [ + $form[Settings::SENDER] = [ '#type' => 'fieldset', '#title' => $this->t('Sender'), '#tree' => TRUE, @@ -82,126 +106,74 @@ public function buildForm(array $form, FormStateInterface $form_state) { '#options' => [ 'CVR' => $this->t('CVR'), ], - '#default_value' => $sender[Settings::SENDER_IDENTIFIER_TYPE] ?? 'CVR', + '#default_value' => $this->settings->getEditableValue([Settings::SENDER, Settings::SENDER_IDENTIFIER_TYPE]) ?? 'CVR', '#required' => TRUE, + '#description' => $this->createDescription([Settings::SENDER, Settings::SENDER_IDENTIFIER_TYPE]), ], Settings::SENDER_IDENTIFIER => [ '#type' => 'textfield', '#title' => $this->t('Identifier'), - '#default_value' => $sender[Settings::SENDER_IDENTIFIER] ?? NULL, + '#default_value' => $this->settings->getEditableValue([Settings::SENDER, Settings::SENDER_IDENTIFIER]), '#required' => TRUE, + '#description' => $this->createDescription([Settings::SENDER, Settings::SENDER_IDENTIFIER]), ], Settings::FORSENDELSES_TYPE_IDENTIFIKATOR => [ '#type' => 'textfield', '#title' => $this->t('Forsendelsestypeidentifikator'), - '#default_value' => $sender[Settings::FORSENDELSES_TYPE_IDENTIFIKATOR] ?? NULL, + '#default_value' => $this->settings->getEditableValue([ + Settings::SENDER, Settings::FORSENDELSES_TYPE_IDENTIFIKATOR, + ]), '#required' => TRUE, + '#description' => $this->createDescription([Settings::SENDER, Settings::FORSENDELSES_TYPE_IDENTIFIKATOR]), ], ]; - $certificate = $this->settings->getCertificate(); - $form['certificate'] = [ + $form[Settings::CERTIFICATE] = [ '#type' => 'fieldset', '#title' => $this->t('Certificate'), '#tree' => TRUE, - 'locator_type' => [ - '#type' => 'select', - '#title' => $this->t('Certificate locator type'), - '#options' => [ - 'azure_key_vault' => $this->t('Azure key vault'), - 'file_system' => $this->t('File system'), - ], - '#default_value' => $certificate['locator_type'] ?? NULL, - ], - ]; - - $form['certificate'][CertificateLocatorHelper::LOCATOR_TYPE_AZURE_KEY_VAULT] = [ - '#type' => 'fieldset', - '#title' => $this->t('Azure key vault'), - '#states' => [ - 'visible' => [':input[name="certificate[locator_type]"]' => ['value' => CertificateLocatorHelper::LOCATOR_TYPE_AZURE_KEY_VAULT]], - ], - ]; - - $settings = [ - 'tenant_id' => ['title' => $this->t('Tenant id')], - 'application_id' => ['title' => $this->t('Application id')], - 'client_secret' => ['title' => $this->t('Client secret')], - 'name' => ['title' => $this->t('Name')], - 'secret' => ['title' => $this->t('Secret')], - 'version' => ['title' => $this->t('Version')], - ]; - - foreach ($settings as $key => $info) { - $form['certificate'][CertificateLocatorHelper::LOCATOR_TYPE_AZURE_KEY_VAULT][$key] = [ - '#type' => 'textfield', - '#title' => $info['title'], - '#default_value' => $certificate[CertificateLocatorHelper::LOCATOR_TYPE_AZURE_KEY_VAULT][$key] ?? NULL, - '#states' => [ - 'required' => [':input[name="certificate[locator_type]"]' => ['value' => CertificateLocatorHelper::LOCATOR_TYPE_AZURE_KEY_VAULT]], - ], - ]; - } - - $form['certificate'][CertificateLocatorHelper::LOCATOR_TYPE_FILE_SYSTEM] = [ - '#type' => 'fieldset', - '#title' => $this->t('File system'), - '#states' => [ - 'visible' => [':input[name="certificate[locator_type]"]' => ['value' => CertificateLocatorHelper::LOCATOR_TYPE_FILE_SYSTEM]], - ], - - 'path' => [ - '#type' => 'textfield', - '#title' => $this->t('Path'), - '#default_value' => $certificate[CertificateLocatorHelper::LOCATOR_TYPE_FILE_SYSTEM]['path'] ?? NULL, - '#states' => [ - 'required' => [':input[name="certificate[locator_type]"]' => ['value' => CertificateLocatorHelper::LOCATOR_TYPE_FILE_SYSTEM]], + Settings::KEY => [ + '#type' => 'key_select', + '#key_filters' => [ + 'type' => 'os2web_key_certificate', ], + '#key_description' => FALSE, + '#title' => $this->t('Key'), + '#default_value' => $this->settings->getEditableValue([Settings::CERTIFICATE, Settings::KEY]), + '#required' => TRUE, + '#description' => $this->createDescription([Settings::CERTIFICATE, Settings::KEY]), ], ]; - $form['certificate']['passphrase'] = [ - '#type' => 'textfield', - '#title' => $this->t('Passphrase'), - '#default_value' => $certificate['passphrase'] ?? NULL, - ]; - - $processing = $this->settings->getProcessing(); - $form['processing'] = [ + $form[Settings::PROCESSING] = [ '#type' => 'fieldset', '#title' => $this->t('Processing'), '#tree' => TRUE, ]; - $defaultValue = $processing['queue'] ?? 'os2forms_digital_post'; - $form['processing']['queue'] = [ + $queue = $this->settings->getEditableValue([Settings::PROCESSING, Settings::QUEUE]); + $form[Settings::PROCESSING][Settings::QUEUE] = [ '#type' => 'select', '#title' => $this->t('Queue'), '#options' => array_map( static fn(EntityInterface $queue) => $queue->label(), $this->queueStorage->loadMultiple() ), - '#default_value' => $defaultValue, - '#description' => $this->t("Queue for digital post jobs. The queue must be run via Drupal's cron or via drush advancedqueue:queue:process @queue(in a cron job).", [ - '@queue' => $defaultValue, - ':queue_url' => '/admin/config/system/queues/jobs/' . urlencode($defaultValue), - ]), - ]; - - $form['actions']['#type'] = 'actions'; - - $form['actions']['submit'] = [ - '#type' => 'submit', - '#value' => $this->t('Save settings'), - ]; - - $form['actions']['testCertificate'] = [ - '#type' => 'submit', - '#name' => 'testCertificate', - '#value' => $this->t('Test certificate'), + '#required' => TRUE, + '#default_value' => $queue, + '#description' => $this->createDescription([Settings::PROCESSING, Settings::QUEUE], + $queue + ? $this->t("Queue for digital post jobs. The queue must be run via Drupal's cron or via drush advancedqueue:queue:process @queue (in a cron job).", [ + '@queue' => $queue, + ':queue_url' => Url::fromRoute('view.advancedqueue_jobs.page_1', [ + 'arg_0' => $queue, + ])->toString(TRUE)->getGeneratedUrl(), + ]) + : $this->t("Queue for digital post jobs. The queue must be processed via Drupal's cron or drush advancedqueue:queue:process (in a cron job)."), + ), ]; return $form; @@ -212,59 +184,41 @@ public function buildForm(array $form, FormStateInterface $form_state) { * * @phpstan-param array $form */ - public function validateForm(array &$form, FormStateInterface $formState): void { - $triggeringElement = $formState->getTriggeringElement(); - if ('testCertificate' === ($triggeringElement['#name'] ?? NULL)) { - return; + public function submitForm(array &$form, FormStateInterface $form_state): void { + $config = $this->config(Settings::CONFIG_NAME); + foreach ([ + Settings::TEST_MODE, + Settings::SENDER, + Settings::CERTIFICATE, + Settings::PROCESSING, + ] as $key) { + $config->set($key, $form_state->getValue($key)); } + $config->save(); - $values = $formState->getValues(); - if (CertificateLocatorHelper::LOCATOR_TYPE_FILE_SYSTEM === $values['certificate']['locator_type']) { - $path = $values['certificate'][CertificateLocatorHelper::LOCATOR_TYPE_FILE_SYSTEM]['path'] ?? NULL; - if (!file_exists($path)) { - $formState->setErrorByName('certificate][file_system][path', $this->t('Invalid certificate path: %path', ['%path' => $path])); - } - } + parent::submitForm($form, $form_state); } /** - * {@inheritdoc} + * Create form field description with information on any runtime override. * - * @phpstan-param array $form + * @param string|array $key + * The key. + * @param \Drupal\Core\StringTranslation\TranslatableMarkup|null $description + * The actual field description. + * + * @return string + * The full description. */ - public function submitForm(array &$form, FormStateInterface $formState): void { - $triggeringElement = $formState->getTriggeringElement(); - if ('testCertificate' === ($triggeringElement['#name'] ?? NULL)) { - $this->testCertificate(); - return; - } - - try { - $settings['test_mode'] = (bool) $formState->getValue('test_mode'); - $settings['sender'] = $formState->getValue('sender'); - $settings['certificate'] = $formState->getValue('certificate'); - $settings['processing'] = $formState->getValue('processing'); - $this->settings->setSettings($settings); - $this->messenger()->addStatus($this->t('Settings saved')); - } - catch (OptionsResolverException $exception) { - $this->messenger()->addError($this->t('Settings not saved (@message)', ['@message' => $exception->getMessage()])); + private function createDescription(string|array $key, ?TranslatableMarkup $description = NULL): string { + if ($value = $this->settings->getOverride($key)) { + if (!empty($description)) { + $description .= '
'; + } + $description .= $this->t('Note: overridden on runtime with the value @value.', ['@value' => var_export($value['runtime'], TRUE)]); } - } - /** - * Test certificate. - */ - private function testCertificate(): void { - try { - $certificateLocator = $this->certificateLocatorHelper->getCertificateLocator(); - $certificateLocator->getCertificates(); - $this->messenger()->addStatus($this->t('Certificate succesfully tested')); - } - catch (\Throwable $throwable) { - $message = $this->t('Error testing certificate: %message', ['%message' => $throwable->getMessage()]); - $this->messenger()->addError($message); - } + return (string) $description; } } diff --git a/modules/os2forms_digital_post/src/Helper/CertificateLocatorHelper.php b/modules/os2forms_digital_post/src/Helper/CertificateLocatorHelper.php deleted file mode 100644 index 10e6ac57..00000000 --- a/modules/os2forms_digital_post/src/Helper/CertificateLocatorHelper.php +++ /dev/null @@ -1,79 +0,0 @@ -settings->getCertificate(); - - $locatorType = $certificateSettings['locator_type']; - $options = $certificateSettings[$locatorType]; - $options += [ - 'passphrase' => $certificateSettings['passphrase'] ?: '', - ]; - - if (self::LOCATOR_TYPE_AZURE_KEY_VAULT === $locatorType) { - $httpClient = new GuzzleAdapter(new Client()); - $requestFactory = new RequestFactory(); - - $vaultToken = new VaultToken($httpClient, $requestFactory); - - $token = $vaultToken->getToken( - $options['tenant_id'], - $options['application_id'], - $options['client_secret'], - ); - - $vault = new VaultSecret( - $httpClient, - $requestFactory, - $options['name'], - $token->getAccessToken() - ); - - return new AzureKeyVaultCertificateLocator( - $vault, - $options['secret'], - $options['version'], - $options['passphrase'], - ); - } - elseif (self::LOCATOR_TYPE_FILE_SYSTEM === $locatorType) { - $certificatepath = realpath($options['path']) ?: NULL; - if (NULL === $certificatepath) { - throw new CertificateLocatorException(sprintf('Invalid certificate path %s', $options['path'])); - } - return new FilesystemCertificateLocator($certificatepath, $options['passphrase']); - } - - throw new CertificateLocatorException(sprintf('Invalid certificate locator type: %s', $locatorType)); - } - -} diff --git a/modules/os2forms_digital_post/src/Helper/DigitalPostHelper.php b/modules/os2forms_digital_post/src/Helper/DigitalPostHelper.php index 8681cf35..fc2355af 100644 --- a/modules/os2forms_digital_post/src/Helper/DigitalPostHelper.php +++ b/modules/os2forms_digital_post/src/Helper/DigitalPostHelper.php @@ -11,6 +11,7 @@ use Drupal\os2web_datalookup\Plugin\DataLookupManager; use Drupal\os2web_datalookup\Plugin\os2web\DataLookup\DataLookupCompanyInterface; use Drupal\os2web_datalookup\Plugin\os2web\DataLookup\DataLookupCprInterface; +use Drupal\os2web_key\CertificateHelper; use Drupal\webform\WebformSubmissionInterface; use ItkDev\Serviceplatformen\Service\SF1601\SF1601; use ItkDev\Serviceplatformen\Service\SF1601\Serializer; @@ -29,7 +30,7 @@ final class DigitalPostHelper implements LoggerInterface { */ public function __construct( private readonly Settings $settings, - private readonly CertificateLocatorHelper $certificateLocatorHelper, + private readonly CertificateHelper $certificateHelper, private readonly DataLookupManager $dataLookupManager, private readonly MeMoHelper $meMoHelper, private readonly ForsendelseHelper $forsendelseHelper, @@ -62,7 +63,10 @@ public function sendDigitalPost(string $type, Message $message, ?ForsendelseI $f $options = [ 'test_mode' => (bool) $this->settings->getTestMode(), 'authority_cvr' => $senderSettings[Settings::SENDER_IDENTIFIER], - 'certificate_locator' => $this->certificateLocatorHelper->getCertificateLocator(), + 'certificate_locator' => new KeyCertificateLocator( + $this->settings->getCertificateKey(), + $this->certificateHelper + ), ]; $service = new SF1601($options); $transactionId = Serializer::createUuid(); diff --git a/modules/os2forms_digital_post/src/Helper/KeyCertificateLocator.php b/modules/os2forms_digital_post/src/Helper/KeyCertificateLocator.php new file mode 100644 index 00000000..832bc19f --- /dev/null +++ b/modules/os2forms_digital_post/src/Helper/KeyCertificateLocator.php @@ -0,0 +1,59 @@ + + */ + public function getCertificates(): array { + if (!isset($this->certificates)) { + $this->certificates = $this->certificateHelper->getCertificates($this->key); + } + + return $this->certificates; + } + + /** + * {@inheritdoc} + */ + public function getCertificate(): string { + return $this->key->getKeyValue(); + } + + /** + * {@inheritdoc} + */ + public function getAbsolutePathToCertificate(): string { + throw new CertificateLocatorException(__METHOD__ . ' should not be used.'); + } + +} diff --git a/modules/os2forms_digital_post/src/Helper/MemoryCertificateLocator.php b/modules/os2forms_digital_post/src/Helper/MemoryCertificateLocator.php new file mode 100644 index 00000000..69d791d2 --- /dev/null +++ b/modules/os2forms_digital_post/src/Helper/MemoryCertificateLocator.php @@ -0,0 +1,49 @@ + + */ + public function getCertificates(): array { + $certificates = []; + $this->passphrase = 'P5bISuw?s:u4'; + if (!openssl_pkcs12_read($this->certificate, $certificates, $this->passphrase)) { + throw new CertificateLocatorException(sprintf('Could not read certificate: %s', openssl_error_string() ?: '')); + } + + return $certificates; + } + + /** + * {@inheritdoc} + */ + public function getCertificate(): string { + return $this->certificate; + } + + /** + * {@inheritdoc} + */ + public function getAbsolutePathToCertificate(): string { + throw new CertificateLocatorException(__METHOD__ . ' should not be used.'); + } + +} diff --git a/modules/os2forms_digital_post/src/Helper/Settings.php b/modules/os2forms_digital_post/src/Helper/Settings.php index e64be738..c0d5384d 100644 --- a/modules/os2forms_digital_post/src/Helper/Settings.php +++ b/modules/os2forms_digital_post/src/Helper/Settings.php @@ -2,45 +2,61 @@ namespace Drupal\os2forms_digital_post\Helper; -use Drupal\Core\KeyValueStore\KeyValueFactoryInterface; -use Drupal\Core\KeyValueStore\KeyValueStoreInterface; -use Drupal\os2forms_digital_post\Exception\InvalidSettingException; -use Symfony\Component\OptionsResolver\OptionsResolver; +use Drupal\Core\Config\Config; +use Drupal\Core\Config\ConfigFactoryInterface; +use Drupal\Core\Config\ImmutableConfig; +use Drupal\key\KeyInterface; +use Drupal\key\KeyRepositoryInterface; /** * General settings for os2forms_digital_post. */ final class Settings { + public const CONFIG_NAME = 'os2forms_digital_post.settings'; + + public const TEST_MODE = 'test_mode'; + + public const SENDER = 'sender'; public const SENDER_IDENTIFIER_TYPE = 'sender_identifier_type'; public const SENDER_IDENTIFIER = 'sender_identifier'; public const FORSENDELSES_TYPE_IDENTIFIKATOR = 'forsendelses_type_identifikator'; + public const CERTIFICATE = 'certificate'; + public const KEY = 'key'; + + public const PROCESSING = 'processing'; + public const QUEUE = 'queue'; + /** - * The store. + * The runtime (immutable) config. * - * @var \Drupal\Core\KeyValueStore\KeyValueStoreInterface + * @var \Drupal\Core\Config\ImmutableConfig */ - private KeyValueStoreInterface $store; + private ImmutableConfig $runtimeConfig; /** - * The key prefix. + * The (mutable) config. * - * @var string + * @var \Drupal\Core\Config\Config */ - private $collection = 'os2forms_digital_post.'; + private Config $editableConfig; /** - * Constructor. + * The constructor. */ - public function __construct(KeyValueFactoryInterface $keyValueFactory) { - $this->store = $keyValueFactory->get($this->collection); + public function __construct( + ConfigFactoryInterface $configFactory, + private readonly KeyRepositoryInterface $keyRepository, + ) { + $this->runtimeConfig = $configFactory->get(self::CONFIG_NAME); + $this->editableConfig = $configFactory->getEditable(self::CONFIG_NAME); } /** * Get test mode. */ public function getTestMode(): bool { - return (bool) $this->get('test_mode', TRUE); + return (bool) $this->get(self::TEST_MODE, TRUE); } /** @@ -49,18 +65,25 @@ public function getTestMode(): bool { * @phpstan-return array */ public function getSender(): array { - $value = $this->get('sender'); + $value = $this->get(self::SENDER); + return is_array($value) ? $value : []; } + /** + * Get key. + */ + public function getKey(): ?string { + return $this->get([self::CERTIFICATE, self::KEY]); + } + /** * Get certificate. - * - * @phpstan-return array */ - public function getCertificate(): array { - $value = $this->get('certificate'); - return is_array($value) ? $value : []; + public function getCertificateKey(): ?KeyInterface { + return $this->keyRepository->getKey( + $this->getKey(), + ); } /** @@ -69,57 +92,82 @@ public function getCertificate(): array { * @phpstan-return array */ public function getProcessing(): array { - $value = $this->get('processing'); + $value = $this->get(self::PROCESSING); + return is_array($value) ? $value : []; } /** - * Get a setting value. + * Get editable value. * - * @param string $key + * @param string|array $key * The key. - * @param mixed|null $default - * The default value. * * @return mixed - * The setting value. + * The editable value. */ - private function get(string $key, $default = NULL) { - $resolver = $this->getSettingsResolver(); - if (!$resolver->isDefined($key)) { - throw new InvalidSettingException(sprintf('Setting %s is not defined', $key)); + public function getEditableValue(string|array $key): mixed { + if (is_array($key)) { + $key = implode('.', $key); } - - return $this->store->get($key, $default); + return $this->editableConfig->get($key); } /** - * Set settings. + * Get runtime value override if any. * - * @throws \Symfony\Component\OptionsResolver\Exception\ExceptionInterface + * @param string|array $key + * The key. * - * @phpstan-param array $settings + * @return array|null + * - 'runtime': the runtime value + * - 'editable': the editable (raw) value */ - public function setSettings(array $settings): self { - $settings = $this->getSettingsResolver()->resolve($settings); - foreach ($settings as $key => $value) { - $this->store->set($key, $value); + public function getOverride(string|array $key): ?array { + $runtimeValue = $this->getRuntimeValue($key); + $editableValue = $this->getEditableValue($key); + + // Note: We deliberately use "Equal" (==) rather than "Identical" (===) + // to compare values (cf. https://www.php.net/manual/en/language.operators.comparison.php#language.operators.comparison). + if ($runtimeValue == $editableValue) { + return NULL; } - return $this; + return [ + 'runtime' => $runtimeValue, + 'editable' => $editableValue, + ]; } /** - * Get settings resolver. + * Get a setting value. + * + * @param string|array $key + * The key. + * @param mixed $default + * The default value. + * + * @return mixed + * The setting value. */ - private function getSettingsResolver(): OptionsResolver { - return (new OptionsResolver()) - ->setDefaults([ - 'test_mode' => TRUE, - 'sender' => [], - 'certificate' => [], - 'processing' => [], - ]); + private function get(string|array $key, mixed $default = NULL) { + return $this->getRuntimeValue($key) ?? $default; + } + + /** + * Get runtime value with any overrides applied. + * + * @param string|array $key + * The key. + * + * @return mixed + * The runtime value. + */ + public function getRuntimeValue(string|array $key): mixed { + if (is_array($key)) { + $key = implode('.', $key); + } + return $this->runtimeConfig->get($key); } } diff --git a/package.json b/package.json deleted file mode 100644 index 52fcd34c..00000000 --- a/package.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "license": "UNLICENSED", - "private": true, - "devDependencies": { - "markdownlint-cli": "^0.32.2" - }, - "scripts": { - "coding-standards-check/markdownlint": "yarn markdownlint --ignore LICENSE.md --ignore vendor --ignore node_modules '*.md' 'modules/os2forms_digital_post/**/*.md'", - "coding-standards-check": "yarn coding-standards-check/markdownlint", - "coding-standards-apply/markdownlint": "yarn markdownlint --ignore LICENSE.md --ignore vendor --ignore node_modules '*.md' 'modules/os2forms_digital_post/**/*.md' --fix", - "coding-standards-apply": "yarn coding-standards-apply/markdownlint" - } -} diff --git a/scripts/code-analysis b/scripts/code-analysis index 9fec0f46..ace9e282 100755 --- a/scripts/code-analysis +++ b/scripts/code-analysis @@ -16,9 +16,21 @@ if [ ! -f "$drupal_dir/composer.json" ]; then composer --no-interaction create-project drupal/recommended-project:^10 "$drupal_dir" fi # Copy our code into the modules folder -mkdir -p "$drupal_dir/$module_path" + +# Clean up +rm -fr "${drupal_dir:?}/$module_path" + # https://stackoverflow.com/a/15373763 -rsync --archive --compress . --filter=':- .gitignore' --exclude "$drupal_dir" --exclude .git "$drupal_dir/$module_path" +# rsync --archive --compress . --filter=':- .gitignore' --exclude "$drupal_dir" --exclude .git "$drupal_dir/$module_path" + +# The rsync command in not available in itkdev/php8.1-fpm + +git config --global --add safe.directory /app +# Copy module files into module path +for f in $(git ls-files); do + mkdir -p "$drupal_dir/$module_path/$(dirname "$f")" + cp "$f" "$drupal_dir/$module_path/$f" +done drupal_composer config minimum-stability dev @@ -37,4 +49,4 @@ drupal_composer config extra.merge-plugin.include "$module_path/composer.json" drupal_composer require --dev symfony/phpunit-bridge # Run PHPStan -(cd "$drupal_dir" && vendor/bin/phpstan --configuration="$module_path/phpstan.neon") +(cd "$drupal_dir/$module_path" && ../../../../vendor/bin/phpstan) From b07e53658b65ad3ddebc22ebb30e626cc30becea Mon Sep 17 00:00:00 2001 From: Mikkel Ricky Date: Tue, 7 May 2024 14:26:39 +0200 Subject: [PATCH 02/46] Cleaned up Markdown --- modules/os2forms_attachment/README.md | 14 ++++++++------ modules/os2forms_autocomplete/README.md | 9 +++++---- modules/os2forms_dawa/README.md | 7 ++++--- modules/os2forms_forloeb/CHANGELOG.md | 9 +++++++-- modules/os2forms_forloeb/README.md | 16 ++++++++-------- modules/os2forms_nemid/README.md | 5 ++--- modules/os2forms_permissions_by_term/README.md | 7 ++++++- modules/os2forms_sbsys/README.md | 1 + modules/os2forms_webform_maps/README.md | 3 +++ 9 files changed, 44 insertions(+), 27 deletions(-) diff --git a/modules/os2forms_attachment/README.md b/modules/os2forms_attachment/README.md index f732ad2f..5b1c7501 100644 --- a/modules/os2forms_attachment/README.md +++ b/modules/os2forms_attachment/README.md @@ -1,20 +1,22 @@ # OS2Forms Attachment Drupal module -# Module purpose +## Module purpose The aim of this module is to provide an OS2forms attachment element for adding PDF/HTML attachment. It also supports creation of reusable headers/footers components which are used when rendering the attachments. -# How does it work +## How does it work -To add custom headers/footer ```admin/structure/webform/config/os2forms_attachment_component``` +To add custom headers/footer `admin/structure/webform/config/os2forms_attachment_component` -To specify headers/footers that will override the default ones on a global level (**Third party settings** -> **Entity print** section): ```admin/structure/webform/config``` +To specify headers/footers that will override the default ones on a global level (**Third party settings** -> **Entity +print** section): `admin/structure/webform/config` -To specify headers/footers that will override the default ones on a form level (**Third party settings** -> **Entity print** section): ```/admin/structure/webform/manage/[webform]/settings``` +To specify headers/footers that will override the default ones on a form level (**Third party settings** -> **Entity +print** section): ```/admin/structure/webform/manage/[webform]/settings``` -# Overwriting templates +## Overwriting templates With some setups it might be necessary to overwrite templates in order to access stylesheets or images. diff --git a/modules/os2forms_autocomplete/README.md b/modules/os2forms_autocomplete/README.md index d5902385..2294d45e 100644 --- a/modules/os2forms_autocomplete/README.md +++ b/modules/os2forms_autocomplete/README.md @@ -1,15 +1,16 @@ # OS2Forms Autocomplete Drupal module -# Module purpose +## Module purpose -The aim of this module is to provide a genetic OS2Forms Autocomplete element which can return options from an external webservice. +The aim of this module is to provide a genetic OS2Forms Autocomplete element which can return options from an external +webservice. -# How does it work +## How does it work Module exposes OS2Forms Autocomplete component that are available in the webform build process. Build page: -``` +```url admin/structure/webform/manage/[webform] ``` diff --git a/modules/os2forms_dawa/README.md b/modules/os2forms_dawa/README.md index 53876ba3..ae242ade 100644 --- a/modules/os2forms_dawa/README.md +++ b/modules/os2forms_dawa/README.md @@ -1,10 +1,11 @@ # OS2Forms DAWA Drupal module -# Module purpose +## Module purpose -The aim of this module is to provide integration with Danish Addresses Web API (DAWA https://dawa.aws.dk) and provider address autocomplete fields. +The aim of this module is to provide integration with Danish Addresses Web API (DAWA ) and provider +address autocomplete fields. -# How does it work +## How does it work Module exposes couple of new Autocomplete components that are available in the webform build process. diff --git a/modules/os2forms_forloeb/CHANGELOG.md b/modules/os2forms_forloeb/CHANGELOG.md index 3338d105..6d569821 100644 --- a/modules/os2forms_forloeb/CHANGELOG.md +++ b/modules/os2forms_forloeb/CHANGELOG.md @@ -1,4 +1,5 @@ # OS2Forms Forløb Change Log + All notable changes to this project should be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) @@ -17,9 +18,11 @@ before starting to add changes. ## 2.5.2 - 27.03.2023 ### Updated + - Bumped drupal/ultimate_cron version fixing [Deprecated function: Implicit conversion from float-string](https://www.drupal.org/project/ultimate_cron/issues/3256142). ## 2.5.1 - 10.03.2023 + - Added github action for checking changelog changes when creating pull requests - Added os2forms/os2forms dependency - Changed composer patching configuration @@ -30,18 +33,20 @@ before starting to add changes. ## 2.5.0 - 11.10.2022 ### Added + - retry task controller action - Added support for inheriting values without creating a submission ## 2.4.0 ### Added + - Github CI action for checking Drupal Coding standards with PHP Code Sniffer - Fixed coding standards issues - ## Example of change log record -``` + +```markdown ## [x.x.x] Release name ### Added - Description on added functionality. diff --git a/modules/os2forms_forloeb/README.md b/modules/os2forms_forloeb/README.md index 7cf06186..11d1b07b 100644 --- a/modules/os2forms_forloeb/README.md +++ b/modules/os2forms_forloeb/README.md @@ -4,11 +4,13 @@ Adds a Maestro workflow engine and advanced workflow functionality to OS2forms. ## Installing OS2forms 2.1 med Forløb -This module requires the codebase from the [OS2forms core project](https://github.com/OS2Forms/os2forms8) installed per the documentation and by selecting the os2forms_forloeb_profile at installation. After succesful installation you should have the OS2forms med Forløb Module available for install via gui. +This module requires the codebase from the [OS2forms core project](https://github.com/OS2Forms/os2forms8) installed per +the documentation and by selecting the os2forms_forloeb_profile at installation. After succesful installation you should +have the OS2forms med Forløb Module available for install via gui. You can also install the module by using Drush: -``` +```shell ./vendor/bin/drush pm:enable os2forms_forloeb ``` @@ -32,20 +34,18 @@ Settings for OS2Forms forløb are defined on `/admin/config/system/os2forms_forl #### Known anonymous roles -In order to make the notifications work, Maestro workflow tasks must be assigned -to a *known anonymous role* and these roles are defined under *Known anonymous -roles*. +In order to make the notifications work, Maestro workflow tasks must be assigned to a *known anonymous role* and these +roles are defined under *Known anonymous roles*. #### Processing -A notification is not sent to a user immediately, but added to a queue which -must be processed asynchronously. Specify the queue handling notification jobs. +A notification is not sent to a user immediately, but added to a queue which must be processed asynchronously. Specify +the queue handling notification jobs. #### Templates Define templates for emails and digital post (PDF). - To reference assets, e.g. stylesheet or images, in your templates, you can use the `base_url` Twig variable to get the base URL: diff --git a/modules/os2forms_nemid/README.md b/modules/os2forms_nemid/README.md index 98ec5532..ec7c7932 100644 --- a/modules/os2forms_nemid/README.md +++ b/modules/os2forms_nemid/README.md @@ -1,10 +1,10 @@ # OS2Forms Nemid Drupal module -# Module purpose +## Module purpose The aim of this module is to provide custom NemId field and integration with OS2Web Nemlogin module. -# How does it work +## How does it work Module exposes dozen of new NemID components that are available in the webform build process. @@ -17,4 +17,3 @@ Besides this module adds a special settings to the Third Party Webform settings: - Hide form if under address protection Settings: admin/structure/webform/manage/[webform]/settings - diff --git a/modules/os2forms_permissions_by_term/README.md b/modules/os2forms_permissions_by_term/README.md index 2c572931..33ac9367 100644 --- a/modules/os2forms_permissions_by_term/README.md +++ b/modules/os2forms_permissions_by_term/README.md @@ -1,10 +1,13 @@ # OS2Forms permission by term module + This module implements permission by term access restrictions on several lists and entity displays related to webform and maestro. ## Setup configuration + Add to your settings.php or local.settings.php -``` + +```php $config['permissions_by_term.settings'] = [ 'permissions_mode' => FALSE, 'require_all_terms_granted' => FALSE, @@ -12,6 +15,7 @@ $config['permissions_by_term.settings'] = [ 'target_bundles' => ['user_affiliation'] ] ``` + Alternative change your site configuration on admin/permissions-by-term/settings to match the above. !note This is the recommended configuration of the permissions_by_term module. Using different values for @@ -19,6 +23,7 @@ Alternative change your site configuration on admin/permissions-by-term/settings be thoroughly tested. ## Usage + - The user affiliation taxonomy is added to webform config form and Maestro workflow forms. - The Permissions by Term module adds a form element to the user form. - When a user visits an entity of the above mentioned this module checks for match between the entity and the users diff --git a/modules/os2forms_sbsys/README.md b/modules/os2forms_sbsys/README.md index b554eebc..8e1129f0 100644 --- a/modules/os2forms_sbsys/README.md +++ b/modules/os2forms_sbsys/README.md @@ -1,6 +1,7 @@ # OS2forms SBSYS integration Drupal module ## Module purpose + The aim of this module is to provide integration with SBSYS ESDH provider. ## How does it work diff --git a/modules/os2forms_webform_maps/README.md b/modules/os2forms_webform_maps/README.md index e6d08748..c36b901e 100644 --- a/modules/os2forms_webform_maps/README.md +++ b/modules/os2forms_webform_maps/README.md @@ -1,13 +1,16 @@ # OS2Forms Webform Maps module for Drupal 9 ## Module description + Provides integration with Leaflet maps and provides map element for webform. ## How does it work + The module provides a new element type for webform. The element type is called "OS2Forms Kort". The element type is based on the Leaflet library. The element type provides a map with a marker that can be moved around on the map. The element type also provides ways of changing layers on the map. The data can be exported to PDF. ## Installation + The module can be installed using the standard Drupal installation procedure. From 0f6900dcf3385ef071d4746dc8788727f1b54a33 Mon Sep 17 00:00:00 2001 From: Mikkel Ricky Date: Tue, 7 May 2024 23:30:35 +0200 Subject: [PATCH 03/46] Cleaned up --- .../os2forms_digital_post.install | 2 +- .../os2forms_digital_post.services.yml | 2 +- .../Commands/DigitalPostTestCommands.php | 4 +- .../src/Form/SettingsForm.php | 6 ++- .../src/Helper/DigitalPostHelper.php | 6 +-- .../src/Helper/KeyCertificateLocator.php | 10 ++-- .../src/Helper/MemoryCertificateLocator.php | 49 ------------------- 7 files changed, 17 insertions(+), 62 deletions(-) delete mode 100644 modules/os2forms_digital_post/src/Helper/MemoryCertificateLocator.php diff --git a/modules/os2forms_digital_post/os2forms_digital_post.install b/modules/os2forms_digital_post/os2forms_digital_post.install index 80b756ac..f8140579 100644 --- a/modules/os2forms_digital_post/os2forms_digital_post.install +++ b/modules/os2forms_digital_post/os2forms_digital_post.install @@ -21,7 +21,7 @@ function os2forms_digital_post_schema() { /** * Implements hook_update_N(). */ -function os2forms_digital_post_update_9001() { +function os2forms_digital_post_update_9001(): void { \Drupal::service('module_installer')->install([ 'os2web_key', ], TRUE); diff --git a/modules/os2forms_digital_post/os2forms_digital_post.services.yml b/modules/os2forms_digital_post/os2forms_digital_post.services.yml index 66bc3132..9b096fad 100644 --- a/modules/os2forms_digital_post/os2forms_digital_post.services.yml +++ b/modules/os2forms_digital_post/os2forms_digital_post.services.yml @@ -32,7 +32,7 @@ services: Drupal\os2forms_digital_post\Helper\DigitalPostHelper: arguments: - "@Drupal\\os2forms_digital_post\\Helper\\Settings" - - "@Drupal\\os2web_key\\CertificateHelper" + - "@Drupal\\os2web_key\\KeyHelper" - "@plugin.manager.os2web_datalookup" - "@Drupal\\os2forms_digital_post\\Helper\\MeMoHelper" - "@Drupal\\os2forms_digital_post\\Helper\\ForsendelseHelper" diff --git a/modules/os2forms_digital_post/src/Drush/Commands/DigitalPostTestCommands.php b/modules/os2forms_digital_post/src/Drush/Commands/DigitalPostTestCommands.php index 248452a3..8d7d17c0 100644 --- a/modules/os2forms_digital_post/src/Drush/Commands/DigitalPostTestCommands.php +++ b/modules/os2forms_digital_post/src/Drush/Commands/DigitalPostTestCommands.php @@ -145,7 +145,9 @@ private function dumpDigitalPostSettings(SymfonyStyle $io): void { Yaml::encode([ 'testMode' => $this->digitalPostSettings->getTestMode(), 'sender' => $this->digitalPostSettings->getSender(), - 'certificate' => $this->digitalPostSettings->getCertificate(), + 'certificate' => [ + 'key' => $this->digitalPostSettings->getKey(), + ], 'processing' => $this->digitalPostSettings->getProcessing(), ]), '', diff --git a/modules/os2forms_digital_post/src/Form/SettingsForm.php b/modules/os2forms_digital_post/src/Form/SettingsForm.php index 6b2e062c..b91e2ed5 100644 --- a/modules/os2forms_digital_post/src/Form/SettingsForm.php +++ b/modules/os2forms_digital_post/src/Form/SettingsForm.php @@ -55,7 +55,7 @@ public static function create(ContainerInterface $container) { /** * {@inheritdoc} * - * @phpstan-return array + * @phpstan-return string[] */ protected function getEditableConfigNames() { return [ @@ -202,13 +202,15 @@ public function submitForm(array &$form, FormStateInterface $form_state): void { /** * Create form field description with information on any runtime override. * - * @param string|array $key + * @param string|array $key * The key. * @param \Drupal\Core\StringTranslation\TranslatableMarkup|null $description * The actual field description. * * @return string * The full description. + * + * @phpstan-param string|string[] $key */ private function createDescription(string|array $key, ?TranslatableMarkup $description = NULL): string { if ($value = $this->settings->getOverride($key)) { diff --git a/modules/os2forms_digital_post/src/Helper/DigitalPostHelper.php b/modules/os2forms_digital_post/src/Helper/DigitalPostHelper.php index fc2355af..80825dff 100644 --- a/modules/os2forms_digital_post/src/Helper/DigitalPostHelper.php +++ b/modules/os2forms_digital_post/src/Helper/DigitalPostHelper.php @@ -11,7 +11,7 @@ use Drupal\os2web_datalookup\Plugin\DataLookupManager; use Drupal\os2web_datalookup\Plugin\os2web\DataLookup\DataLookupCompanyInterface; use Drupal\os2web_datalookup\Plugin\os2web\DataLookup\DataLookupCprInterface; -use Drupal\os2web_key\CertificateHelper; +use Drupal\os2web_key\KeyHelper; use Drupal\webform\WebformSubmissionInterface; use ItkDev\Serviceplatformen\Service\SF1601\SF1601; use ItkDev\Serviceplatformen\Service\SF1601\Serializer; @@ -30,7 +30,7 @@ final class DigitalPostHelper implements LoggerInterface { */ public function __construct( private readonly Settings $settings, - private readonly CertificateHelper $certificateHelper, + private readonly KeyHelper $keyHelper, private readonly DataLookupManager $dataLookupManager, private readonly MeMoHelper $meMoHelper, private readonly ForsendelseHelper $forsendelseHelper, @@ -65,7 +65,7 @@ public function sendDigitalPost(string $type, Message $message, ?ForsendelseI $f 'authority_cvr' => $senderSettings[Settings::SENDER_IDENTIFIER], 'certificate_locator' => new KeyCertificateLocator( $this->settings->getCertificateKey(), - $this->certificateHelper + $this->keyHelper ), ]; $service = new SF1601($options); diff --git a/modules/os2forms_digital_post/src/Helper/KeyCertificateLocator.php b/modules/os2forms_digital_post/src/Helper/KeyCertificateLocator.php index 832bc19f..8d8f0a41 100644 --- a/modules/os2forms_digital_post/src/Helper/KeyCertificateLocator.php +++ b/modules/os2forms_digital_post/src/Helper/KeyCertificateLocator.php @@ -3,7 +3,7 @@ namespace Drupal\os2forms_digital_post\Helper; use Drupal\key\KeyInterface; -use Drupal\os2web_key\CertificateHelper; +use Drupal\os2web_key\KeyHelper; use ItkDev\Serviceplatformen\Certificate\AbstractCertificateLocator; use ItkDev\Serviceplatformen\Certificate\Exception\CertificateLocatorException; @@ -15,16 +15,16 @@ class KeyCertificateLocator extends AbstractCertificateLocator { /** * The parsed certificates. * - * @var array + * @var array */ - private readonly array $certificates; + private array $certificates; /** * Constructor. */ public function __construct( private readonly KeyInterface $key, - private readonly CertificateHelper $certificateHelper, + private readonly KeyHelper $keyHelper, ) { parent::__construct(); } @@ -36,7 +36,7 @@ public function __construct( */ public function getCertificates(): array { if (!isset($this->certificates)) { - $this->certificates = $this->certificateHelper->getCertificates($this->key); + $this->certificates = $this->keyHelper->getCertificates($this->key); } return $this->certificates; diff --git a/modules/os2forms_digital_post/src/Helper/MemoryCertificateLocator.php b/modules/os2forms_digital_post/src/Helper/MemoryCertificateLocator.php deleted file mode 100644 index 69d791d2..00000000 --- a/modules/os2forms_digital_post/src/Helper/MemoryCertificateLocator.php +++ /dev/null @@ -1,49 +0,0 @@ - - */ - public function getCertificates(): array { - $certificates = []; - $this->passphrase = 'P5bISuw?s:u4'; - if (!openssl_pkcs12_read($this->certificate, $certificates, $this->passphrase)) { - throw new CertificateLocatorException(sprintf('Could not read certificate: %s', openssl_error_string() ?: '')); - } - - return $certificates; - } - - /** - * {@inheritdoc} - */ - public function getCertificate(): string { - return $this->certificate; - } - - /** - * {@inheritdoc} - */ - public function getAbsolutePathToCertificate(): string { - throw new CertificateLocatorException(__METHOD__ . ' should not be used.'); - } - -} From ae2c683933b6bc5bbeacc4a01982d6a4e650c974 Mon Sep 17 00:00:00 2001 From: Mikkel Ricky Date: Mon, 13 May 2024 09:11:55 +0200 Subject: [PATCH 04/46] Required os2web_key 1.0 --- composer.json | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/composer.json b/composer.json index 1bcbbd1f..083b9a89 100644 --- a/composer.json +++ b/composer.json @@ -58,7 +58,7 @@ "itk-dev/serviceplatformen": "^1.5", "os2web/os2web_audit": "^0.1.6", "os2web/os2web_datalookup": "^2.0", - "os2web/os2web_key": "dev-os2web_key", + "os2web/os2web_key": "^1.0", "os2web/os2web_nemlogin": "^1.0", "php-http/guzzle7-adapter": "^1.0", "phpoffice/phpword": "^0.18.2", @@ -80,10 +80,6 @@ "wsdltophp/packagegenerator": "^4.0" }, "repositories": { - "os2web/os2web_key": { - "type": "vcs", - "url": "https://github.com/itk-dev/os2web_key" - }, "drupal": { "type": "composer", "url": "https://packages.drupal.org/8" From 801cae9a83b769211c9c4b3725b2ef3af4f7f3fd Mon Sep 17 00:00:00 2001 From: Mikkel Ricky Date: Mon, 13 May 2024 11:27:36 +0200 Subject: [PATCH 05/46] Updated os2web_datalookup --- composer.json | 6 +++++- modules/os2forms_digital_post/README.md | 3 ++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index 083b9a89..ec6906b0 100644 --- a/composer.json +++ b/composer.json @@ -57,7 +57,7 @@ "itk-dev/beskedfordeler-drupal": "^1.0", "itk-dev/serviceplatformen": "^1.5", "os2web/os2web_audit": "^0.1.6", - "os2web/os2web_datalookup": "^2.0", + "os2web/os2web_datalookup": "dev-feature/os2web_key as 1.12.0", "os2web/os2web_key": "^1.0", "os2web/os2web_nemlogin": "^1.0", "php-http/guzzle7-adapter": "^1.0", @@ -80,6 +80,10 @@ "wsdltophp/packagegenerator": "^4.0" }, "repositories": { + "os2web/os2web_datalookup": { + "type": "vcs", + "url": "https://github.com/itk-dev/os2web_datalookup" + }, "drupal": { "type": "composer", "url": "https://packages.drupal.org/8" diff --git a/modules/os2forms_digital_post/README.md b/modules/os2forms_digital_post/README.md index c36e9f48..999d87c7 100644 --- a/modules/os2forms_digital_post/README.md +++ b/modules/os2forms_digital_post/README.md @@ -33,7 +33,8 @@ digital post. ### Key -We use [os2web_key](https://github.com/OS2web/os2web_key) to provide the certificate for sending digital post. +We use [os2web_key](https://github.com/OS2web/os2web_key) to provide the certificate for sending digital post, and the +key must be of type "[Certificate](https://github.com/os2web/os2web_key?tab=readme-ov-file#certificate)". ### Queue From b5fba51177a91ae2218d92487b3044b048db17a4 Mon Sep 17 00:00:00 2001 From: Mikkel Ricky Date: Tue, 17 Dec 2024 23:26:21 +0100 Subject: [PATCH 06/46] Cleaned up composer.json --- composer.json | 48 ++++++++++++++++++------------------------------ 1 file changed, 18 insertions(+), 30 deletions(-) diff --git a/composer.json b/composer.json index ec6906b0..2b83bd51 100644 --- a/composer.json +++ b/composer.json @@ -56,8 +56,9 @@ "http-interop/http-factory-guzzle": "^1.0.0", "itk-dev/beskedfordeler-drupal": "^1.0", "itk-dev/serviceplatformen": "^1.5", + "mglaman/composer-drupal-lenient": "^1.0", "os2web/os2web_audit": "^0.1.6", - "os2web/os2web_datalookup": "dev-feature/os2web_key as 1.12.0", + "os2web/os2web_datalookup": "dev-feature/os2web_key as 2.0.0", "os2web/os2web_key": "^1.0", "os2web/os2web_nemlogin": "^1.0", "php-http/guzzle7-adapter": "^1.0", @@ -65,8 +66,7 @@ "symfony/options-resolver": "^5.4 || ^6.0", "webmozart/path-util": "^2.3", "wsdltophp/packagebase": "^5.0", - "zaporylie/composer-drupal-optimizations": "^1.2", - "mglaman/composer-drupal-lenient": "^1.0" + "zaporylie/composer-drupal-optimizations": "^1.2" }, "require-dev": { "dealerdirect/phpcodesniffer-composer-installer": "^0.7.1", @@ -100,6 +100,7 @@ "cweagans/composer-patches": true, "dealerdirect/phpcodesniffer-composer-installer": true, "ergebnis/composer-normalize": true, + "mglaman/composer-drupal-lenient": true, "phpstan/extension-installer": true, "simplesamlphp/composer-module-installer": true, "vaimo/composer-patches": true, @@ -109,8 +110,19 @@ }, "extra": { "composer-exit-on-patch-failure": false, + "drupal-lenient": { + "allowed-list": [ + "drupal/coc_forms_auto_export", + "drupal/webform_node_element" + ] + }, "enable-patching": true, "patches": { + "drupal/coc_forms_auto_export": { + "3240592 - Problem with phpseclib requirement in 2.x (https://www.drupal.org/project/coc_forms_auto_export/issues/3240592)": "https://www.drupal.org/files/issues/2021-10-04/requirement-namespace-3240592-1.patch", + "3286562 - Automated Drupal 10 compatibility fixes": "https://www.drupal.org/files/issues/2022-06-15/coc_forms_auto_export.2.0.x-dev.rector.patch", + "3259009 - PHP Warnings/Notices on Download Page": "https://git.drupalcode.org/project/coc_forms_auto_export/-/merge_requests/1.diff" + }, "drupal/entity_print": { "2733781 - Add Export to Word Support": "https://www.drupal.org/files/issues/2019-11-22/2733781-47.patch" }, @@ -118,26 +130,14 @@ "Unlock possibility of using Entity print module export to Word": "https://www.drupal.org/files/issues/2020-02-29/3096552-6.patch", "Webform computed element post save alter": "https://www.drupal.org/files/issues/2024-06-25/webform_computed_post_save_field_alter.patch", "Add custom hook (hook_webform_post_load_data) for audit logging": "https://gist.githubusercontent.com/cableman/d26898fc8f65ee0a31001bf391583b59/raw/6189dc4c2ceaabb19d25cc4b98b0b3028a6b0e1e/gistfile1.txt" - - }, - "drupal/coc_forms_auto_export": { - "3240592 - Problem with phpseclib requirement in 2.x (https://www.drupal.org/project/coc_forms_auto_export/issues/3240592)": "https://www.drupal.org/files/issues/2021-10-04/requirement-namespace-3240592-1.patch", - "3286562 - Automated Drupal 10 compatibility fixes" : "https://www.drupal.org/files/issues/2022-06-15/coc_forms_auto_export.2.0.x-dev.rector.patch", - "3259009 - PHP Warnings/Notices on Download Page" : "https://git.drupalcode.org/project/coc_forms_auto_export/-/merge_requests/1.diff" - }, - "drupal/webform_node_element": { - "3290637 - Automated Drupal 10 compatibility fixes": "https://www.drupal.org/files/issues/2023-05-12/webform_node_element_d10-3290637-11.patch" }, "drupal/webform_encrypt": { "Ensure data is base64 encoded (https://www.drupal.org/project/webform_encrypt/issues/3399414)": "https://git.drupalcode.org/project/webform_encrypt/-/merge_requests/4.patch", "PHP Warning if unserialize fails (https://www.drupal.org/project/webform_encrypt/issues/3292305)": "https://www.drupal.org/files/issues/2022-06-23/unserialize-php-notice.patch" + }, + "drupal/webform_node_element": { + "3290637 - Automated Drupal 10 compatibility fixes": "https://www.drupal.org/files/issues/2023-05-12/webform_node_element_d10-3290637-11.patch" } - }, - "drupal-lenient": { - "allowed-list": [ - "drupal/coc_forms_auto_export", - "drupal/webform_node_element" - ] } }, "scripts": { @@ -159,17 +159,5 @@ "coding-standards-check/phpcs": [ "phpcs --standard=phpcs.xml.dist" ] - }, - "config": { - "sort-packages": true, - "allow-plugins": { - "cweagans/composer-patches": true, - "dealerdirect/phpcodesniffer-composer-installer": true, - "phpstan/extension-installer": true, - "simplesamlphp/composer-module-installer": true, - "vaimo/composer-patches": true, - "zaporylie/composer-drupal-optimizations": true, - "mglaman/composer-drupal-lenient": true - } } } From a8dc3c80c03c633c3a3c6b11849ad5c3739892f2 Mon Sep 17 00:00:00 2001 From: Mikkel Ricky Date: Tue, 17 Dec 2024 23:40:20 +0100 Subject: [PATCH 07/46] Cleaned up --- README.md | 1 + modules/os2forms_fasit/docs/BENYTTELSE.md | 10 +++++----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 90245a21..44eb8e47 100644 --- a/README.md +++ b/README.md @@ -130,6 +130,7 @@ docker run --rm --volume ${PWD}:/app --workdir /app itkdev/php8.1-fpm composer c ### Markdown ```sh +docker pull peterdavehello/markdownlint docker run --rm --volume $PWD:/md peterdavehello/markdownlint markdownlint --ignore vendor --ignore LICENSE.md '**/*.md' --fix docker run --rm --volume $PWD:/md peterdavehello/markdownlint markdownlint --ignore vendor --ignore LICENSE.md '**/*.md' ``` diff --git a/modules/os2forms_fasit/docs/BENYTTELSE.md b/modules/os2forms_fasit/docs/BENYTTELSE.md index 63cc361d..cb8c958a 100644 --- a/modules/os2forms_fasit/docs/BENYTTELSE.md +++ b/modules/os2forms_fasit/docs/BENYTTELSE.md @@ -10,7 +10,7 @@ aftale hvilke certifikater der anvendes. Disse certifikater skal være OCES-3, f.eks. FOCES-3, og skal bruges i pem- eller cer-format. Dernæst oplyses det anvendte certifikats thumbprint eller public-key til Fasit, -som derefter aktiverer snitfladen. Se evt. +som derefter aktiverer snitfladen. Se evt. [README#certificate](../README.md#certificate) for hvordan et certifikats thumbprint kan findes gennem kommandolinjen. @@ -22,7 +22,7 @@ Her skal følgende sættes op: * Fasit API base url * Basis url’en til Fasit. Denne specificeres af Fasit. - * Eksempel: https://webservices.fasit.dk/ + * Eksempel: * Fasit API tenant * Fasit tenant. Denne specificeres af Fasit. * Eksempel: aarhus @@ -30,14 +30,14 @@ Her skal følgende sættes op: * Hvilken version af af API’et der skal bruges. Her er mulighederne ’v1’ eller ’v2’. Der bør altid bruges ’v2’. * Eksempel: v2 * Certificate - * Her kan angives detaljer til et azure key vault hvori certifikatet ligges (Azure key vault) eller en sti direkte til certifikatet (Filsystem) + * Her kan angives detaljer til et azure key vault hvori certifikatet ligges (Azure key vault) eller en sti direkte til + certifikatet (Filsystem) * Passphrase * Passphrase til certifikatet, hvis sådan et eksisterer. - Se evt. Fasit Scultz dokumentationen for flere detaljer på opbygningen af endpoint url’er. -Det er desuden muligt at teste om os2forms kan få fat i certifikatet på samme konfigurations-side. +Det er desuden muligt at teste om os2forms kan få fat i certifikatet på samme konfigurations-side. ## Handler From fea276dab167990c186a949bb0038935cd11fe0e Mon Sep 17 00:00:00 2001 From: Mikkel Ricky Date: Fri, 20 Dec 2024 15:27:57 +0100 Subject: [PATCH 08/46] Updated --- .github/workflows/pr.yml | 6 ++-- .../DataLookup/DatafordelerDataLookup.php | 28 +++++++++++-------- 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index c78e9623..6eb23e77 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -23,7 +23,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - php-versions: [ '8.1' ] + php-versions: [ '8.3' ] dependency-version: [ prefer-lowest, prefer-stable ] steps: - uses: actions/checkout@master @@ -59,7 +59,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - php-versions: [ '8.1' ] + php-versions: [ '8.3' ] steps: - uses: actions/checkout@master - name: Setup PHP, with composer and extensions @@ -92,7 +92,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - php-versions: [ '8.1' ] + php-versions: [ '8.3' ] steps: - uses: actions/checkout@master - name: Setup PHP, with composer and extensions diff --git a/modules/os2forms_dawa/src/Plugin/os2web/DataLookup/DatafordelerDataLookup.php b/modules/os2forms_dawa/src/Plugin/os2web/DataLookup/DatafordelerDataLookup.php index ba699519..9d3b1aaa 100644 --- a/modules/os2forms_dawa/src/Plugin/os2web/DataLookup/DatafordelerDataLookup.php +++ b/modules/os2forms_dawa/src/Plugin/os2web/DataLookup/DatafordelerDataLookup.php @@ -3,8 +3,11 @@ namespace Drupal\os2forms_dawa\Plugin\os2web\DataLookup; use Drupal\Component\Utility\NestedArray; +use Drupal\Core\File\FileSystem; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Plugin\ContainerFactoryPluginInterface; +use Drupal\key\KeyRepository; +use Drupal\key\KeyRepositoryInterface; use Drupal\os2forms_dawa\Entity\DatafordelerMatrikula; use Drupal\os2web_audit\Service\Logger; use Drupal\os2web_datalookup\Plugin\os2web\DataLookup\DataLookupBase; @@ -21,13 +24,6 @@ */ class DatafordelerDataLookup extends DataLookupBase implements DatafordelerDataLookupInterface, ContainerFactoryPluginInterface { - /** - * The HTTP client to fetch the feed data with. - * - * @var \GuzzleHttp\ClientInterface - */ - protected $httpClient; - /** * {@inheritdoc} */ @@ -35,23 +31,33 @@ public function __construct( array $configuration, $plugin_id, $plugin_definition, - ClientInterface $httpClient, + protected ClientInterface $httpClient, Logger $auditLogger, + KeyRepositoryInterface $keyRepository, + FileSystem $fileSystem, ) { - $this->httpClient = $httpClient; - parent::__construct($configuration, $plugin_id, $plugin_definition, $auditLogger); + parent::__construct($configuration, $plugin_id, $plugin_definition, $auditLogger, $keyRepository, $fileSystem); } /** * {@inheritdoc} */ public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { + /** @var Logger $auditLogger */ + $auditLogger = $container->get('os2web_audit.logger'); + /** @var \Drupal\key\KeyRepositoryInterface $keyRepository */ + $keyRepository = $container->get('key.repository'); + /** @var \Drupal\Core\File\FileSystem $fileSystem */ + $fileSystem = $container->get('file_system'); + return new static( $configuration, $plugin_id, $plugin_definition, $container->get('http_client'), - $container->get('os2web_audit.logger'), + $auditLogger, + $keyRepository, + $fileSystem, ); } From d0cff5e95486add3a748a2980e6aa115dc841994 Mon Sep 17 00:00:00 2001 From: jekuaitk Date: Thu, 2 Jan 2025 11:35:18 +0100 Subject: [PATCH 09/46] ITKDEV: Updated fbs handler to use latest endpoints and operations --- CHANGELOG.md | 1 + .../os2forms_fbs_handler/src/Client/FBS.php | 104 ++++++++++++------ .../src/Client/Model/Guardian.php | 2 +- .../src/Client/Model/Patron.php | 11 +- .../AdvancedQueue/JobType/FbsCreateUser.php | 44 +++++--- 5 files changed, 112 insertions(+), 50 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4f03e6d0..3415627d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ before starting to add changes. Use example [placed in the end of the page](#exa - [#101](https://github.com/OS2Forms/os2forms/pull/101) Added support for os2web_key +- Updated `os2forms_fbs_handler` to use latest endpoints and operations. ## [3.21.0] 2024-12-17 diff --git a/modules/os2forms_fbs_handler/src/Client/FBS.php b/modules/os2forms_fbs_handler/src/Client/FBS.php index 660a83a0..6f33f22c 100644 --- a/modules/os2forms_fbs_handler/src/Client/FBS.php +++ b/modules/os2forms_fbs_handler/src/Client/FBS.php @@ -75,34 +75,22 @@ public function isLoggedIn(): bool { * @param string $cpr * The users personal security number. * - * @return \Drupal\os2forms_fbs_handler\Client\Model\Patron|null - * NULL if not else the Patron. + * @return string|null + * NULL if not else the PatronId. * * @throws \GuzzleHttp\Exception\GuzzleException * @throws \JsonException */ - public function doUserExists(string $cpr): ?Patron { + public function authenticatePatron(string $cpr): ?string { // Check if session has been created with FBS and if not creates it. if (!$this->isLoggedIn()) { $this->login(); } - // Try pre-authenticate the user/parent. - $json = $this->request('/external/{agency_id}/patrons/preauthenticated/v9', $cpr); + // Authenticate the patron. + $json = $this->request('/external/{agency_id}/patrons/preauthenticated/v10', $cpr); if ($json->authenticateStatus === $this::AUTHENTICATE_STATUS_VALID) { - return new Patron( - $json->patron->patronId, - (bool) $json->patron->receiveSms, - (bool) $json->patron->receivePostalMail, - $json->patron->notificationProtocols, - $json->patron->phoneNumber, - is_null($json->patron->onHold) ? $json->patron->onHold : (array) $json->patron->onHold, - $json->patron->preferredLanguage, - (bool) $json->patron->guardianVisibility, - $json->patron->emailAddress, - (bool) $json->patron->receiveEmail, - $json->patron->preferredPickupBranch - ); + return $json->patronId; } return NULL; @@ -123,19 +111,61 @@ public function doUserExists(string $cpr): ?Patron { * @throws \JsonException */ public function createPatronWithGuardian(Patron $patron, Guardian $guardian) { - $uri = '/external/{agency_id}/patrons/withGuardian/v1'; + $uri = '/external/{agency_id}/patrons/withGuardian/v4'; $payload = [ - 'cprNumber' => $patron->cpr, + 'personId' => $patron->personId, 'pincode' => $patron->pincode, 'preferredPickupBranch' => $patron->preferredPickupBranch, 'name' => 'Unknown Name', - 'email' => $patron->emailAddress, + 'emailAddresses' => $patron->emailAddresses, 'guardian' => $guardian->toArray(), ]; - return $this->request($uri, $payload,); + return $this->request($uri, $payload); } + /** + * Get patron information. + * + * @param string $patronId + * The patron to update. + * + * @return \Drupal\os2forms_fbs_handler\Client\Model\Patron + * Patron object + * + * @throws \GuzzleHttp\Exception\GuzzleException + * @throws \JsonException + */ + public function getPatron(string $patronId): ?Patron { + $uri = '/external/{agency_id}/patrons/' . $patronId . '/v4'; + + $json = $this->request($uri, [], RequestMethodInterface::METHOD_GET); + + if ($json->authenticateStatus === "VALID") { + return new Patron( + $json->patron->patronId, + (bool) $json->patron->receiveSms, + (bool) $json->patron->receivePostalMail, + $json->patron->notificationProtocols, + $json->patron->phoneNumber, + is_null($json->patron->onHold) ? $json->patron->onHold : (array) $json->patron->onHold, + $json->patron->preferredLanguage, + (bool) $json->patron->guardianVisibility, + $json->patron->defaultInterestPeriod, + (bool) $json->patron->resident, + [ + [ + 'emailAddress' => $json->patron->emailAddress, + 'receiveNotification' => $json->patron->receiveEmail, + ], + ], + (bool) $json->patron->receiveEmail, + $json->patron->preferredPickupBranch + ); + } + return NULL; + } + /** * Update patron information. * @@ -149,19 +179,27 @@ public function createPatronWithGuardian(Patron $patron, Guardian $guardian) { * @throws \JsonException */ public function updatePatron(Patron $patron): bool { - $uri = '/external/{agency_id}/patrons/' . $patron->patronId . '/v6'; + $uri = '/external/{agency_id}/patrons/' . $patron->patronId . '/v8'; $payload = [ - 'patronid' => $patron->patronId, - 'patron' => $patron->toArray(), + 'patron' => [ + 'preferredPickupBranch' => $patron->preferredPickupBranch, + 'emailAddresses' => $patron->emailAddresses, + 'guardianVisibility' => $patron->guardianVisibility, + 'receivePostalMail' => $patron->receiveEmail, + 'phoneNumbers' => [ + [ + 'receiveNotification' => TRUE, + 'phoneNumber' => $patron->phoneNumber, + ], + ], + ], 'pincodeChange' => [ 'pincode' => $patron->pincode, - 'libraryCardNumber' => $patron->cpr, + 'libraryCardNumber' => $patron->personId, ], ]; - $json = $this->request($uri, $payload, Request::METHOD_PUT); - - return $json->authenticateStatus === $this::AUTHENTICATE_STATUS_VALID; + return $this->request($uri, $payload, RequestMethodInterface::METHOD_PUT); } /** @@ -179,7 +217,7 @@ public function updatePatron(Patron $patron): bool { * @throws \JsonException */ public function createGuardian(Patron $patron, Guardian $guardian): int { - $uri = '/external/{agency_id}/patrons/withGuardian/v1'; + $uri = '/external/{agency_id}/patrons/withGuardian/v2'; $payload = [ 'patronId' => $patron->patronId, 'guardian' => $guardian->toArray(), @@ -199,7 +237,7 @@ public function createGuardian(Patron $patron, Guardian $guardian): int { * The type of request to send (Default: POST). * * @return mixed - * Json response from FBS. + * Json response from FBS or TRUE on updatePatron response. * * @throws \GuzzleHttp\Exception\GuzzleException * @throws \JsonException @@ -230,6 +268,10 @@ private function request(string $uri, array|string $data, string $method = Reque $response = $this->client->request($method, $url, $options); + if ($response->getStatusCode() === 204) { + return TRUE; + } + return json_decode($response->getBody(), FALSE, 512, JSON_THROW_ON_ERROR); } diff --git a/modules/os2forms_fbs_handler/src/Client/Model/Guardian.php b/modules/os2forms_fbs_handler/src/Client/Model/Guardian.php index 150db93e..371d3bba 100644 --- a/modules/os2forms_fbs_handler/src/Client/Model/Guardian.php +++ b/modules/os2forms_fbs_handler/src/Client/Model/Guardian.php @@ -25,7 +25,7 @@ public function __construct( */ public function toArray(): array { return [ - 'cprNumber' => $this->cpr, + 'personIdentifier' => $this->cpr, 'name' => $this->name, 'email' => $this->email, ]; diff --git a/modules/os2forms_fbs_handler/src/Client/Model/Patron.php b/modules/os2forms_fbs_handler/src/Client/Model/Patron.php index 4847c944..e5e7d562 100644 --- a/modules/os2forms_fbs_handler/src/Client/Model/Patron.php +++ b/modules/os2forms_fbs_handler/src/Client/Model/Patron.php @@ -19,11 +19,13 @@ public function __construct( public readonly ?array $onHold = NULL, public readonly ?string $preferredLanguage = NULL, public readonly ?bool $guardianVisibility = NULL, + public readonly ?int $defaultInterestPeriod = NULL, + public readonly ?bool $resident = NULL, // Allow these properties below to be updatable. - public ?string $emailAddress = NULL, + public ?array $emailAddresses = NULL, public ?bool $receiveEmail = NULL, public ?string $preferredPickupBranch = NULL, - public ?string $cpr = NULL, + public ?string $personId = NULL, public ?string $pincode = NULL, ) { } @@ -36,16 +38,19 @@ public function __construct( */ public function toArray(): array { return [ + 'patronId' => $this->patronId, 'receiveEmail' => $this->receiveEmail, 'receiveSms' => $this->receiveSms, 'receivePostalMail' => $this->receivePostalMail, - 'emailAddress' => $this->emailAddress, + 'emailAddresses' => $this->emailAddresses, 'notificationProtocols' => $this->notificationProtocols, 'phoneNumber' => $this->phoneNumber, 'preferredPickupBranch' => $this->preferredPickupBranch, 'onHold' => $this->onHold, 'preferredLanguage' => $this->preferredLanguage, 'guardianVisibility' => $this->guardianVisibility, + 'defaultInterestPeriod' => $this->defaultInterestPeriod, + 'resident' => $this->resident, ]; } diff --git a/modules/os2forms_fbs_handler/src/Plugin/AdvancedQueue/JobType/FbsCreateUser.php b/modules/os2forms_fbs_handler/src/Plugin/AdvancedQueue/JobType/FbsCreateUser.php index 3afe322c..179d0a1a 100644 --- a/modules/os2forms_fbs_handler/src/Plugin/AdvancedQueue/JobType/FbsCreateUser.php +++ b/modules/os2forms_fbs_handler/src/Plugin/AdvancedQueue/JobType/FbsCreateUser.php @@ -87,9 +87,6 @@ public function process(Job $job): JobResult { $data = $webformSubmission->getData(); - // Checker child patron exists. - $patron = $fbs->doUserExists($data['barn_cpr']); - // Create Guardian. $guardian = new Guardian( $data['cpr'], @@ -97,26 +94,43 @@ public function process(Job $job): JobResult { $data['email'] ); + // Check if child patron exists. + $patronId = $fbs->authenticatePatron($data['barn_cpr']); + // If "yes" update the child patron and create the guardian (the // guardian is not another patron user). - if (!is_null($patron)) { - // Create Patron object with updated values. - $patron->preferredPickupBranch = $data['afhentningssted']; - $patron->emailAddress = $data['barn_mail']; - $patron->receiveEmail = TRUE; - $patron->cpr = $data['barn_cpr']; - $patron->pincode = $data['pinkode']; - - $fbs->updatePatron($patron); - $fbs->createGuardian($patron, $guardian); + if (!is_null($patronId)) { + // Fetch patron. + $patron = $fbs->getPatron($patronId); + + if (!is_null($patron)) { + // Create Patron object with updated values. + $patron->preferredPickupBranch = $data['afhentningssted']; + $patron->emailAddresses = [ + [ + 'emailAddress' => $data['barn_mail'], + 'receiveNotification' => TRUE, + ], + ]; + $patron->receiveEmail = TRUE; + $patron->pincode = $data['pinkode']; + + $fbs->updatePatron($patron); + $fbs->createGuardian($patron, $guardian); + } } else { // If "no" create child patron and guardian. $patron = new Patron(); $patron->preferredPickupBranch = $data['afhentningssted']; - $patron->emailAddress = $data['barn_mail']; + $patron->emailAddresses = [ + [ + 'emailAddress' => $data['barn_mail'], + 'receiveNotification' => TRUE, + ], + ]; $patron->receiveEmail = TRUE; - $patron->cpr = $data['barn_cpr']; + $patron->personId = $data['barn_cpr']; $patron->pincode = $data['pinkode']; $fbs->createPatronWithGuardian($patron, $guardian); From 1f3a49e208fb889655ffcd6e1ff82083d39a233d Mon Sep 17 00:00:00 2001 From: jekuaitk Date: Thu, 2 Jan 2025 12:29:39 +0100 Subject: [PATCH 10/46] ITKDEV: Adjust indention --- .../os2forms_fbs_handler/src/Client/FBS.php | 79 ++++++++++--------- 1 file changed, 40 insertions(+), 39 deletions(-) diff --git a/modules/os2forms_fbs_handler/src/Client/FBS.php b/modules/os2forms_fbs_handler/src/Client/FBS.php index 6f33f22c..44b8f6a7 100644 --- a/modules/os2forms_fbs_handler/src/Client/FBS.php +++ b/modules/os2forms_fbs_handler/src/Client/FBS.php @@ -90,7 +90,7 @@ public function authenticatePatron(string $cpr): ?string { // Authenticate the patron. $json = $this->request('/external/{agency_id}/patrons/preauthenticated/v10', $cpr); if ($json->authenticateStatus === $this::AUTHENTICATE_STATUS_VALID) { - return $json->patronId; + return $json->patronId; } return NULL; @@ -124,48 +124,49 @@ public function createPatronWithGuardian(Patron $patron, Guardian $guardian) { return $this->request($uri, $payload); } - /** - * Get patron information. - * - * @param string $patronId - * The patron to update. - * - * @return \Drupal\os2forms_fbs_handler\Client\Model\Patron - * Patron object - * - * @throws \GuzzleHttp\Exception\GuzzleException - * @throws \JsonException - */ - public function getPatron(string $patronId): ?Patron { - $uri = '/external/{agency_id}/patrons/' . $patronId . '/v4'; - - $json = $this->request($uri, [], RequestMethodInterface::METHOD_GET); - - if ($json->authenticateStatus === "VALID") { - return new Patron( - $json->patron->patronId, - (bool) $json->patron->receiveSms, - (bool) $json->patron->receivePostalMail, - $json->patron->notificationProtocols, - $json->patron->phoneNumber, - is_null($json->patron->onHold) ? $json->patron->onHold : (array) $json->patron->onHold, - $json->patron->preferredLanguage, - (bool) $json->patron->guardianVisibility, - $json->patron->defaultInterestPeriod, - (bool) $json->patron->resident, + /** + * Get patron information. + * + * @param string $patronId + * The patron to update. + * + * @return \Drupal\os2forms_fbs_handler\Client\Model\Patron + * Patron object + * + * @throws \GuzzleHttp\Exception\GuzzleException + * @throws \JsonException + */ + public function getPatron(string $patronId): ?Patron { + $uri = '/external/{agency_id}/patrons/' . $patronId . '/v4'; + + $json = $this->request($uri, [], RequestMethodInterface::METHOD_GET); + + if ($json->authenticateStatus === "VALID") { + return new Patron( + $json->patron->patronId, + (bool) $json->patron->receiveSms, + (bool) $json->patron->receivePostalMail, + $json->patron->notificationProtocols, + $json->patron->phoneNumber, + is_null($json->patron->onHold) ? $json->patron->onHold : (array) $json->patron->onHold, + $json->patron->preferredLanguage, + (bool) $json->patron->guardianVisibility, + $json->patron->defaultInterestPeriod, + (bool) $json->patron->resident, + [ [ - [ - 'emailAddress' => $json->patron->emailAddress, - 'receiveNotification' => $json->patron->receiveEmail, - ], + 'emailAddress' => $json->patron->emailAddress, + 'receiveNotification' => $json->patron->receiveEmail, ], - (bool) $json->patron->receiveEmail, - $json->patron->preferredPickupBranch - ); - } - return NULL; + ], + (bool) $json->patron->receiveEmail, + $json->patron->preferredPickupBranch + ); } + return NULL; + } + /** * Update patron information. * From 2447c985e7d6516ac8b7639ede80d5b7f1c86703 Mon Sep 17 00:00:00 2001 From: jekuaitk Date: Fri, 3 Jan 2025 09:05:14 +0100 Subject: [PATCH 11/46] ITKDEV: Used configured format in maestro notification --- CHANGELOG.md | 1 + .../src/Plugin/WebformHandler/MaestroNotificationHandler.php | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3415627d..722fa709 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ before starting to add changes. Use example [placed in the end of the page](#exa - [#101](https://github.com/OS2Forms/os2forms/pull/101) Added support for os2web_key +- Updated Maestro notification handler assignment message format. - Updated `os2forms_fbs_handler` to use latest endpoints and operations. ## [3.21.0] 2024-12-17 diff --git a/modules/os2forms_forloeb/src/Plugin/WebformHandler/MaestroNotificationHandler.php b/modules/os2forms_forloeb/src/Plugin/WebformHandler/MaestroNotificationHandler.php index 156cc181..18f2a4eb 100644 --- a/modules/os2forms_forloeb/src/Plugin/WebformHandler/MaestroNotificationHandler.php +++ b/modules/os2forms_forloeb/src/Plugin/WebformHandler/MaestroNotificationHandler.php @@ -24,6 +24,7 @@ final class MaestroNotificationHandler extends WebformHandlerBase { public const NOTIFICATION = 'notification'; public const TYPE = 'type'; + public const FORMAT = 'format'; public const SENDER_LABEL = 'sender_label'; public const NOTIFICATION_ENABLE = 'notification_enable'; public const NOTIFICATION_RECIPIENT = 'notification_recipient'; @@ -153,7 +154,7 @@ public function buildConfigurationForm(array $form, FormStateInterface $formStat } $form[self::NOTIFICATION][$notificationType][self::NOTIFICATION_CONTENT] = [ '#type' => 'text_format', - '#format' => 'restricted_html', + '#format' => $this->configuration[self::NOTIFICATION][$notificationType][self::NOTIFICATION_CONTENT][self::FORMAT] ?? 'restricted_html', '#title' => $this->t('Message'), '#default_value' => $content ?? self::TOKEN_MAESTRO_TASK_URL, '#description' => $this->t('The actual notification content. Must contain the @token_maestro_task_url token which is the URL to the Maestro task.', From 2308816696aac8ac2ae8aed7caa905f0bbe081e5 Mon Sep 17 00:00:00 2001 From: jekuaitk Date: Mon, 6 Jan 2025 09:51:16 +0100 Subject: [PATCH 12/46] Release 3.21.1 --- CHANGELOG.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 722fa709..d30a1b99 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,9 @@ before starting to add changes. Use example [placed in the end of the page](#exa - [#101](https://github.com/OS2Forms/os2forms/pull/101) Added support for os2web_key + +## [3.21.1] 2025-01-06 + - Updated Maestro notification handler assignment message format. - Updated `os2forms_fbs_handler` to use latest endpoints and operations. @@ -328,7 +331,8 @@ before starting to add changes. Use example [placed in the end of the page](#exa - Security in case of vulnerabilities. ``` -[Unreleased]: https://github.com/OS2Forms/os2forms/compare/3.21.0...HEAD +[Unreleased]: https://github.com/OS2Forms/os2forms/compare/3.21.1...HEAD +[3.21.1]: https://github.com/OS2Forms/os2forms/compare/3.21.0...3.21.1 [3.21.0]: https://github.com/OS2Forms/os2forms/compare/3.20.1...3.21.0 [3.20.1]: https://github.com/OS2Forms/os2forms/compare/3.20.0...3.20.1 [3.20.0]: https://github.com/OS2Forms/os2forms/compare/3.19.0...3.20.0 From 1ff2132dbdb886a4144a2f4dbd234691a6366788 Mon Sep 17 00:00:00 2001 From: jekuaitk Date: Fri, 17 Jan 2025 11:37:03 +0100 Subject: [PATCH 13/46] Support for os2web_key in DigitalPost and Fasit --- CHANGELOG.md | 3 +- .../os2forms_digital_post/drush.services.yml | 3 +- .../os2forms_digital_post.services.yml | 2 +- .../Commands/DigitalPostTestCommands.php | 2 +- modules/os2forms_fasit/README.md | 24 +- modules/os2forms_fasit/drush.services.yml | 6 + .../os2forms_fasit/os2forms_fasit.info.yml | 1 + modules/os2forms_fasit/os2forms_fasit.install | 15 ++ .../os2forms_fasit.services.yml | 9 +- .../src/Drush/Commands/FasitTestCommands.php | 38 ++++ .../os2forms_fasit/src/Form/SettingsForm.php | 207 ++++++------------ .../src/Helper/CertificateLocatorHelper.php | 1 + .../os2forms_fasit/src/Helper/FasitHelper.php | 100 +++++---- .../os2forms_fasit/src/Helper/Settings.php | 100 +++------ 14 files changed, 251 insertions(+), 260 deletions(-) rename modules/os2forms_digital_post/src/{Drush => }/Commands/DigitalPostTestCommands.php (98%) create mode 100644 modules/os2forms_fasit/drush.services.yml create mode 100644 modules/os2forms_fasit/os2forms_fasit.install create mode 100644 modules/os2forms_fasit/src/Drush/Commands/FasitTestCommands.php diff --git a/CHANGELOG.md b/CHANGELOG.md index d30a1b99..2feae1a1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,7 +12,8 @@ before starting to add changes. Use example [placed in the end of the page](#exa ## [Unreleased] - [#101](https://github.com/OS2Forms/os2forms/pull/101) - Added support for os2web_key + - Added support for `os2web_key` in Digital post + - Added support for `os2web_key` in Fasit handler. ## [3.21.1] 2025-01-06 diff --git a/modules/os2forms_digital_post/drush.services.yml b/modules/os2forms_digital_post/drush.services.yml index ac0d5f8e..7339bc2a 100644 --- a/modules/os2forms_digital_post/drush.services.yml +++ b/modules/os2forms_digital_post/drush.services.yml @@ -1,5 +1,6 @@ services: - Drupal\os2forms_digital_post\Drush\Commands\DigitalPostTestCommands: + os2forms_digital_post.commands: + class: \Drupal\os2forms_digital_post\Commands\DigitalPostTestCommands arguments: - '@Drupal\os2forms_digital_post\Helper\DigitalPostHelper' - '@token' diff --git a/modules/os2forms_digital_post/os2forms_digital_post.services.yml b/modules/os2forms_digital_post/os2forms_digital_post.services.yml index 9b096fad..31ff12ef 100644 --- a/modules/os2forms_digital_post/os2forms_digital_post.services.yml +++ b/modules/os2forms_digital_post/os2forms_digital_post.services.yml @@ -32,7 +32,7 @@ services: Drupal\os2forms_digital_post\Helper\DigitalPostHelper: arguments: - "@Drupal\\os2forms_digital_post\\Helper\\Settings" - - "@Drupal\\os2web_key\\KeyHelper" + - "@os2web_key.key_helper" - "@plugin.manager.os2web_datalookup" - "@Drupal\\os2forms_digital_post\\Helper\\MeMoHelper" - "@Drupal\\os2forms_digital_post\\Helper\\ForsendelseHelper" diff --git a/modules/os2forms_digital_post/src/Drush/Commands/DigitalPostTestCommands.php b/modules/os2forms_digital_post/src/Commands/DigitalPostTestCommands.php similarity index 98% rename from modules/os2forms_digital_post/src/Drush/Commands/DigitalPostTestCommands.php rename to modules/os2forms_digital_post/src/Commands/DigitalPostTestCommands.php index 8d7d17c0..5e9bdbbf 100644 --- a/modules/os2forms_digital_post/src/Drush/Commands/DigitalPostTestCommands.php +++ b/modules/os2forms_digital_post/src/Commands/DigitalPostTestCommands.php @@ -1,6 +1,6 @@ install([ + 'key', + ], TRUE); +} diff --git a/modules/os2forms_fasit/os2forms_fasit.services.yml b/modules/os2forms_fasit/os2forms_fasit.services.yml index 4397c83f..e6fe5e8c 100644 --- a/modules/os2forms_fasit/os2forms_fasit.services.yml +++ b/modules/os2forms_fasit/os2forms_fasit.services.yml @@ -1,16 +1,13 @@ services: Drupal\os2forms_fasit\Helper\Settings: arguments: - - "@keyvalue" - - Drupal\os2forms_fasit\Helper\CertificateLocatorHelper: - arguments: - - "@Drupal\\os2forms_fasit\\Helper\\Settings" + - "@config.factory" + - "@key.repository" Drupal\os2forms_fasit\Helper\FasitHelper: arguments: - '@http_client' - '@entity_type.manager' - "@Drupal\\os2forms_fasit\\Helper\\Settings" - - "@Drupal\\os2forms_fasit\\Helper\\CertificateLocatorHelper" + - "@file_system" - "@os2web_audit.logger" diff --git a/modules/os2forms_fasit/src/Drush/Commands/FasitTestCommands.php b/modules/os2forms_fasit/src/Drush/Commands/FasitTestCommands.php new file mode 100644 index 00000000..4ac71534 --- /dev/null +++ b/modules/os2forms_fasit/src/Drush/Commands/FasitTestCommands.php @@ -0,0 +1,38 @@ +helper->pingApi(); + $this->io()->success('Successfully connected to Fasit API'); + } + catch (\Throwable $t) { + $this->io()->error($t->getMessage()); + } + + } + +} diff --git a/modules/os2forms_fasit/src/Form/SettingsForm.php b/modules/os2forms_fasit/src/Form/SettingsForm.php index d0fe119e..f703255c 100644 --- a/modules/os2forms_fasit/src/Form/SettingsForm.php +++ b/modules/os2forms_fasit/src/Form/SettingsForm.php @@ -2,41 +2,61 @@ namespace Drupal\os2forms_fasit\Form; -use Drupal\Core\Form\FormBase; +use Drupal\Core\Config\ConfigFactoryInterface; +use Drupal\Core\Form\ConfigFormBase; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\StringTranslation\StringTranslationTrait; -use Drupal\os2forms_fasit\Helper\CertificateLocatorHelper; -use Drupal\os2forms_fasit\Helper\Settings; +use Drupal\os2forms_fasit\Helper\FasitHelper; use Symfony\Component\DependencyInjection\ContainerInterface; -use Symfony\Component\OptionsResolver\Exception\ExceptionInterface as OptionsResolverException; /** - * Organisation settings form. + * Fasit settings form. */ -final class SettingsForm extends FormBase { +final class SettingsForm extends ConfigFormBase { use StringTranslationTrait; + public const CONFIG_NAME = 'os2forms_fasit.settings'; public const FASIT_API_BASE_URL = 'fasit_api_base_url'; public const FASIT_API_TENANT = 'fasit_api_tenant'; public const FASIT_API_VERSION = 'fasit_api_version'; public const CERTIFICATE = 'certificate'; + public const KEY = 'key'; + + public const ACTION_PING_API = 'action_ping_api'; /** - * Constructor. + * {@inheritdoc} */ - public function __construct(private readonly Settings $settings, private readonly CertificateLocatorHelper $certificateLocatorHelper) { + public function __construct( + ConfigFactoryInterface $config_factory, + private readonly FasitHelper $helper, + ) { + parent::__construct($config_factory); } /** * {@inheritdoc} + * + * @phpstan-return self */ - public static function create(ContainerInterface $container): SettingsForm { + public static function create(ContainerInterface $container): self { return new static( - $container->get(Settings::class), - $container->get(CertificateLocatorHelper::class) + $container->get('config.factory'), + $container->get(FasitHelper::class) ); } + /** + * {@inheritdoc} + * + * @phpstan-return array + */ + protected function getEditableConfigNames() { + return [ + self::CONFIG_NAME, + ]; + } + /** * {@inheritdoc} */ @@ -51,116 +71,57 @@ public function getFormId() { * @phpstan-return array */ public function buildForm(array $form, FormStateInterface $form_state): array { + $form = parent::buildForm($form, $form_state); + $config = $this->config(self::CONFIG_NAME); - $fasitApiBaseUrl = $this->settings->getFasitApiBaseUrl(); $form[self::FASIT_API_BASE_URL] = [ '#type' => 'textfield', '#title' => $this->t('Fasit API base url'), '#required' => TRUE, - '#default_value' => !empty($fasitApiBaseUrl) ? $fasitApiBaseUrl : NULL, + '#default_value' => $config->get(self::FASIT_API_BASE_URL), '#description' => $this->t('Specifies which base url to use. This is disclosed by Schultz'), ]; - $fasitApiTenant = $this->settings->getFasitApiTenant(); $form[self::FASIT_API_TENANT] = [ '#type' => 'textfield', '#title' => $this->t('Fasit API tenant'), '#required' => TRUE, - '#default_value' => !empty($fasitApiTenant) ? $fasitApiTenant : NULL, + '#default_value' => $config->get(self::FASIT_API_TENANT), '#description' => $this->t('Specifies which tenant to use. This is disclosed by Schultz'), ]; - $fasitApiVersion = $this->settings->getFasitApiVersion(); $form[self::FASIT_API_VERSION] = [ '#type' => 'textfield', '#title' => $this->t('Fasit API version'), '#required' => TRUE, - '#default_value' => !empty($fasitApiVersion) ? $fasitApiVersion : NULL, + '#default_value' => $config->get(self::FASIT_API_VERSION), '#description' => $this->t('Specifies which api version to use. Should probably be v2'), ]; - $certificate = $this->settings->getCertificate(); - - $form[self::CERTIFICATE] = [ - '#type' => 'fieldset', - '#title' => $this->t('Certificate'), - '#tree' => TRUE, - - CertificateLocatorHelper::LOCATOR_TYPE => [ - '#type' => 'select', - '#title' => $this->t('Certificate locator type'), - '#options' => [ - CertificateLocatorHelper::LOCATOR_TYPE_AZURE_KEY_VAULT => $this->t('Azure key vault'), - CertificateLocatorHelper::LOCATOR_TYPE_FILE_SYSTEM => $this->t('File system'), - ], - '#default_value' => $certificate[CertificateLocatorHelper::LOCATOR_TYPE] ?? NULL, + $form[self::KEY] = [ + '#type' => 'key_select', + '#key_filters' => [ + 'type' => 'os2web_key_certificate', ], + '#title' => $this->t('Key'), + '#required' => TRUE, + '#default_value' => $config->get(self::KEY), ]; - $form[self::CERTIFICATE][CertificateLocatorHelper::LOCATOR_TYPE_AZURE_KEY_VAULT] = [ - '#type' => 'fieldset', - '#title' => $this->t('Azure key vault'), - '#states' => [ - 'visible' => [':input[name="certificate[locator_type]"]' => ['value' => CertificateLocatorHelper::LOCATOR_TYPE_AZURE_KEY_VAULT]], - ], - ]; - - $settings = [ - CertificateLocatorHelper::LOCATOR_AZURE_KEY_VAULT_TENANT_ID => ['title' => $this->t('Tenant id')], - CertificateLocatorHelper::LOCATOR_AZURE_KEY_VAULT_APPLICATION_ID => ['title' => $this->t('Application id')], - CertificateLocatorHelper::LOCATOR_AZURE_KEY_VAULT_CLIENT_SECRET => ['title' => $this->t('Client secret')], - CertificateLocatorHelper::LOCATOR_AZURE_KEY_VAULT_NAME => ['title' => $this->t('Name')], - CertificateLocatorHelper::LOCATOR_AZURE_KEY_VAULT_SECRET => ['title' => $this->t('Secret')], - CertificateLocatorHelper::LOCATOR_AZURE_KEY_VAULT_VERSION => ['title' => $this->t('Version')], - ]; - - foreach ($settings as $key => $info) { - $form[self::CERTIFICATE][CertificateLocatorHelper::LOCATOR_TYPE_AZURE_KEY_VAULT][$key] = [ - '#type' => 'textfield', - '#title' => $info['title'], - '#default_value' => $certificate[CertificateLocatorHelper::LOCATOR_TYPE_AZURE_KEY_VAULT][$key] ?? NULL, - '#states' => [ - 'required' => [':input[name="certificate[locator_type]"]' => ['value' => CertificateLocatorHelper::LOCATOR_TYPE_AZURE_KEY_VAULT]], - ], - ]; - } + $form['actions']['ping_api'] = [ + '#type' => 'container', - $form[self::CERTIFICATE][CertificateLocatorHelper::LOCATOR_TYPE_FILE_SYSTEM] = [ - '#type' => 'fieldset', - '#title' => $this->t('File system'), - '#states' => [ - 'visible' => [':input[name="certificate[locator_type]"]' => ['value' => CertificateLocatorHelper::LOCATOR_TYPE_FILE_SYSTEM]], + self::ACTION_PING_API => [ + '#type' => 'submit', + '#name' => self::ACTION_PING_API, + '#value' => $this->t('Ping API'), ], - 'path' => [ - '#type' => 'textfield', - '#title' => $this->t('Path'), - '#default_value' => $certificate[CertificateLocatorHelper::LOCATOR_TYPE_FILE_SYSTEM]['path'] ?? NULL, - '#states' => [ - 'required' => [':input[name="certificate[locator_type]"]' => ['value' => CertificateLocatorHelper::LOCATOR_TYPE_FILE_SYSTEM]], - ], + 'message' => [ + '#markup' => $this->t('Note: Pinging the API will use saved config.'), ], ]; - $form[self::CERTIFICATE][CertificateLocatorHelper::LOCATOR_PASSPHRASE] = [ - '#type' => 'textfield', - '#title' => $this->t('Passphrase'), - '#default_value' => $certificate[CertificateLocatorHelper::LOCATOR_PASSPHRASE] ?? NULL, - ]; - - $form['actions']['#type'] = 'actions'; - - $form['actions']['submit'] = [ - '#type' => 'submit', - '#value' => $this->t('Save settings'), - ]; - - $form['actions']['testCertificate'] = [ - '#type' => 'submit', - '#name' => 'testCertificate', - '#value' => $this->t('Test certificate'), - ]; - return $form; } @@ -169,20 +130,12 @@ public function buildForm(array $form, FormStateInterface $form_state): array { * * @phpstan-param array $form */ - public function validateForm(array &$form, FormStateInterface $formState): void { - $triggeringElement = $formState->getTriggeringElement(); - if ('testCertificate' === ($triggeringElement['#name'] ?? NULL)) { + public function validateForm(array &$form, FormStateInterface $form_state): void { + if (self::ACTION_PING_API === ($form_state->getTriggeringElement()['#name'] ?? NULL)) { return; } - $values = $formState->getValues(); - - if (CertificateLocatorHelper::LOCATOR_TYPE_FILE_SYSTEM === $values[self::CERTIFICATE][CertificateLocatorHelper::LOCATOR_TYPE]) { - $path = $values[self::CERTIFICATE][CertificateLocatorHelper::LOCATOR_TYPE_FILE_SYSTEM]['path'] ?? NULL; - if (!file_exists($path)) { - $formState->setErrorByName('certificate][file_system][path', $this->t('Invalid certificate path: %path', ['%path' => $path])); - } - } + parent::validateForm($form, $form_state); } /** @@ -190,44 +143,30 @@ public function validateForm(array &$form, FormStateInterface $formState): void * * @phpstan-param array $form */ - public function submitForm(array &$form, FormStateInterface $formState): void { - $triggeringElement = $formState->getTriggeringElement(); - if ('testCertificate' === ($triggeringElement['#name'] ?? NULL)) { - $this->testCertificate(); + public function submitForm(array &$form, FormStateInterface $form_state): void { + if (self::ACTION_PING_API === ($form_state->getTriggeringElement()['#name'] ?? NULL)) { + try { + $this->helper->pingApi(); + $this->messenger()->addStatus($this->t('Pinged API successfully.')); + } + catch (\Throwable $t) { + $this->messenger()->addError($this->t('Pinging API failed: @message', ['@message' => $t->getMessage()])); + } return; } - try { - $settings[self::CERTIFICATE] = $formState->getValue(self::CERTIFICATE); - $settings[self::FASIT_API_BASE_URL] = $formState->getValue(self::FASIT_API_BASE_URL); - $settings[self::FASIT_API_TENANT] = $formState->getValue(self::FASIT_API_TENANT); - $settings[self::FASIT_API_VERSION] = $formState->getValue(self::FASIT_API_VERSION); - - $this->settings->setSettings($settings); - $this->messenger()->addStatus($this->t('Settings saved')); + $config = $this->config(self::CONFIG_NAME); + foreach ([ + self::FASIT_API_BASE_URL, + self::FASIT_API_TENANT, + self::FASIT_API_VERSION, + self::KEY, + ] as $key) { + $config->set($key, $form_state->getValue($key)); } - catch (OptionsResolverException $exception) { - $this->messenger()->addError($this->t('Settings not saved (@message)', ['@message' => $exception->getMessage()])); - - return; - } - - $this->messenger()->addStatus($this->t('Settings saved')); - } + $config->save(); - /** - * Test certificate. - */ - private function testCertificate(): void { - try { - $certificateLocator = $this->certificateLocatorHelper->getCertificateLocator(); - $certificateLocator->getCertificates(); - $this->messenger()->addStatus($this->t('Certificate successfully tested')); - } - catch (\Throwable $throwable) { - $message = $this->t('Error testing certificate: %message', ['%message' => $throwable->getMessage()]); - $this->messenger()->addError($message); - } + parent::submitForm($form, $form_state); } } diff --git a/modules/os2forms_fasit/src/Helper/CertificateLocatorHelper.php b/modules/os2forms_fasit/src/Helper/CertificateLocatorHelper.php index 3f244d1a..bca6e3d1 100644 --- a/modules/os2forms_fasit/src/Helper/CertificateLocatorHelper.php +++ b/modules/os2forms_fasit/src/Helper/CertificateLocatorHelper.php @@ -18,6 +18,7 @@ class CertificateLocatorHelper { public const LOCATOR_TYPE = 'locator_type'; public const LOCATOR_TYPE_AZURE_KEY_VAULT = 'azure_key_vault'; + public const LOCATOR_TYPE_HASHICORP_KEY_VAULT = 'hashicorp_key_vault'; public const LOCATOR_TYPE_FILE_SYSTEM = 'file_system'; public const LOCATOR_PASSPHRASE = 'passphrase'; public const LOCATOR_AZURE_KEY_VAULT_TENANT_ID = 'tenant_id'; diff --git a/modules/os2forms_fasit/src/Helper/FasitHelper.php b/modules/os2forms_fasit/src/Helper/FasitHelper.php index 2bd84d65..25a3a4db 100644 --- a/modules/os2forms_fasit/src/Helper/FasitHelper.php +++ b/modules/os2forms_fasit/src/Helper/FasitHelper.php @@ -4,6 +4,7 @@ use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityTypeManagerInterface; +use Drupal\Core\File\FileSystemInterface; use Drupal\os2forms_attachment\Element\AttachmentElement; use Drupal\os2forms_fasit\Exception\FasitResponseException; use Drupal\os2forms_fasit\Exception\FasitXMLGenerationException; @@ -16,6 +17,7 @@ use GuzzleHttp\ClientInterface; use GuzzleHttp\Exception\GuzzleException; use GuzzleHttp\Psr7\Utils; +use Psr\Http\Message\ResponseInterface; use Symfony\Component\HttpFoundation\Response; /** @@ -38,7 +40,7 @@ public function __construct( private readonly ClientInterface $client, private readonly EntityTypeManagerInterface $entityTypeManager, private readonly Settings $settings, - private readonly CertificateLocatorHelper $certificateLocator, + private readonly FileSystemInterface $fileSystem, private readonly Logger $auditLogger, ) { } @@ -206,8 +208,6 @@ private function uploadDocument(array $uploads, string $submissionId, array $han } } - [$certificateOptions, $tempCertFilename] = $this->getCertificateOptionsAndTempCertFilename(); - $body = $doc->saveXML(); if (!$body) { @@ -219,20 +219,15 @@ private function uploadDocument(array $uploads, string $submissionId, array $han 'Content-Type' => 'application/xml', ], 'body' => $body, - 'cert' => $certificateOptions, + 'cert' => $this->settings->getCertificate(), ]; // Attempt upload. try { - $response = $this->client->request('POST', $endpoint, $options); + $response = $this->post($endpoint, $options); } catch (GuzzleException $e) { throw new FasitResponseException($e->getMessage(), $e->getCode()); - } finally { - // Remove the certificate from disk. - if (file_exists($tempCertFilename)) { - unlink($tempCertFilename); - } } if (Response::HTTP_OK !== $response->getStatusCode()) { @@ -262,26 +257,6 @@ private function checkHandlerConfiguration(array $handlerConfiguration, string $ } } - /** - * Gets certificate options and temp certificate filename. - * - * @throws \Drupal\os2forms_fasit\Exception\CertificateLocatorException - * Certificate locator exception. - * - * @phpstan-return array - */ - private function getCertificateOptionsAndTempCertFilename(): array { - $certificateLocator = $this->certificateLocator->getCertificateLocator(); - $localCertFilename = tempnam(sys_get_temp_dir(), 'cert'); - file_put_contents($localCertFilename, $certificateLocator->getCertificate()); - $certificateOptions = - $certificateLocator->hasPassphrase() ? - [$localCertFilename, $certificateLocator->getPassphrase()] - : $localCertFilename; - - return [$certificateOptions, $localCertFilename]; - } - /** * Uploads attachment to Fasit. * @@ -345,8 +320,6 @@ private function uploadFile(string $originalFilename, string $tempFilename, stri self::FASIT_API_METHOD_UPLOAD ); - [$certificateOptions, $tempCertFilename] = $this->getCertificateOptionsAndTempCertFilename(); - // Attempt upload. try { $options = [ @@ -356,18 +329,13 @@ private function uploadFile(string $originalFilename, string $tempFilename, stri 'X-Title' => pathinfo($originalFilename, PATHINFO_FILENAME), ], 'body' => Utils::tryFopen($tempFilename, 'r'), - 'cert' => $certificateOptions, ]; - $response = $this->client->request('POST', $endpoint, $options); + $response = $this->post($endpoint, $options); } catch (GuzzleException $e) { throw new FasitResponseException($e->getMessage(), $e->getCode()); } finally { - // Remove the certificate from disk. - if (file_exists($tempCertFilename)) { - unlink($tempCertFilename); - } // Remove the attachment from disk. if (file_exists($tempFilename)) { unlink($tempFilename); @@ -510,4 +478,60 @@ private function getSubmission(string $submissionId): EntityInterface { return $storage->load($submissionId); } + /** + * Send POST request to Fasit API. + * + * @param string $endpoint + * The API endpoint. + * @param array $options + * The request options. + * + * @return \Psr\Http\Message\ResponseInterface + * The response. + * + * @throws \GuzzleHttp\Exception\GuzzleException + * A Guzzle exception. + */ + private function post(string $endpoint, array $options): ResponseInterface { + try { + $certificate = $this->settings->getCertificate(); + $certPath = $this->fileSystem->tempnam($this->fileSystem->getTempDirectory(), 'os2forms_fasit_cert'); + // `tempnam` has created a file, so we must replace when saving. + $this->fileSystem->saveData($certificate, $certPath, FileSystemInterface::EXISTS_REPLACE); + $options['cert'] = $certPath; + + return $this->client->request('POST', $endpoint, $options); + } finally { + // Remove the certificate from disk. + if (isset($certPath) && file_exists($certPath)) { + unlink($certPath); + } + } + } + + /** + * Ping the Fasit API and expect a 400 Bad Request response. + * + * @throws \Throwable + */ + public function pingApi(): void { + $endpoint = sprintf('%s/%s/%s/documents/%s', + $this->settings->getFasitApiBaseUrl(), + $this->settings->getFasitApiTenant(), + $this->settings->getFasitApiVersion(), + self::FASIT_API_METHOD_UPLOAD + ); + + try { + $this->post($endpoint, []); + } + catch (\Throwable $t) { + // Throw if it's not a 400 Bad Request exception. + if (!($t instanceof GuzzleException) + || Response::HTTP_BAD_REQUEST !== $t->getCode()) { + throw $t; + } + } + } + } diff --git a/modules/os2forms_fasit/src/Helper/Settings.php b/modules/os2forms_fasit/src/Helper/Settings.php index de065fc6..98d5a5e8 100644 --- a/modules/os2forms_fasit/src/Helper/Settings.php +++ b/modules/os2forms_fasit/src/Helper/Settings.php @@ -2,66 +2,72 @@ namespace Drupal\os2forms_fasit\Helper; -use Drupal\Core\KeyValueStore\KeyValueFactoryInterface; -use Drupal\Core\KeyValueStore\KeyValueStoreInterface; -use Drupal\os2forms_fasit\Exception\InvalidSettingException; +use Drupal\Core\Config\ConfigFactoryInterface; +use Drupal\Core\Config\ImmutableConfig; +use Drupal\key\KeyRepositoryInterface; use Drupal\os2forms_fasit\Form\SettingsForm; -use Symfony\Component\OptionsResolver\OptionsResolver; /** * General settings for os2forms_fasit. */ final class Settings { /** - * The store. + * The config. * - * @var \Drupal\Core\KeyValueStore\KeyValueStoreInterface + * @var \Drupal\Core\Config\ImmutableConfig */ - private KeyValueStoreInterface $store; + private ImmutableConfig $config; /** - * The key value collection name. - * - * @var string + * The constructor. */ - private $collection = 'os2forms_fasit'; + public function __construct( + ConfigFactoryInterface $configFactory, + private readonly KeyRepositoryInterface $keyRepository, + ) { + $this->config = $configFactory->get(SettingsForm::CONFIG_NAME); + } /** - * The constructor. + * Get fasit api base url. */ - public function __construct(KeyValueFactoryInterface $keyValueFactory) { - $this->store = $keyValueFactory->get($this->collection); + public function getFasitApiBaseUrl(): ?string { + return $this->get(SettingsForm::FASIT_API_BASE_URL); } /** - * Get fasit api base url. + * Get fasit api tenant. */ - public function getFasitApiBaseUrl(): string { - return $this->get(SettingsForm::FASIT_API_BASE_URL, ''); + public function getFasitApiTenant(): ?string { + return $this->get(SettingsForm::FASIT_API_TENANT); } /** - * Get fasit api base url. + * Get fasit api version. */ - public function getFasitApiTenant(): string { - return $this->get(SettingsForm::FASIT_API_TENANT, ''); + public function getFasitApiVersion(): ?string { + return $this->get(SettingsForm::FASIT_API_VERSION); } + + + /** - * Get fasit api base url. + * Get key. */ - public function getFasitApiVersion(): string { - return $this->get(SettingsForm::FASIT_API_VERSION, ''); + public function getKey(): ?string { + return $this->get(SettingsForm::KEY); } /** * Get certificate. - * - * @phpstan-return array */ - public function getCertificate(): array { - $value = $this->get(SettingsForm::CERTIFICATE); - return is_array($value) ? $value : []; + public function getCertificate(): ?string { + $key = $this->keyRepository->getKey( + $this->getKey(), + ); + + return $key?->getKeyValue(); } /** @@ -75,42 +81,8 @@ public function getCertificate(): array { * @return mixed * The setting value. */ - private function get(string $key, $default = NULL) { - $resolver = $this->getSettingsResolver(); - if (!$resolver->isDefined($key)) { - throw new InvalidSettingException(sprintf('Setting %s is not defined', $key)); - } - - return $this->store->get($key, $default); - } - - /** - * Set settings. - * - * @throws \Symfony\Component\OptionsResolver\Exception\ExceptionInterface - * - * @phpstan-param array $settings - */ - public function setSettings(array $settings): self { - $settings = $this->getSettingsResolver()->resolve($settings); - foreach ($settings as $key => $value) { - $this->store->set($key, $value); - } - - return $this; - } - - /** - * Get settings resolver. - */ - private function getSettingsResolver(): OptionsResolver { - return (new OptionsResolver()) - ->setDefaults([ - SettingsForm::FASIT_API_BASE_URL => '', - SettingsForm::FASIT_API_TENANT => '', - SettingsForm::FASIT_API_VERSION => '', - SettingsForm::CERTIFICATE => [], - ]); + private function get(string $key, $default = NULL): mixed { + return $this->config->get($key) ?? $default; } } From d566ee0b113dea4e4e91b53d1a69fc3aa0957947 Mon Sep 17 00:00:00 2001 From: jekuaitk Date: Fri, 17 Jan 2025 14:57:15 +0100 Subject: [PATCH 14/46] Service update --- .../os2forms_digital_post/os2forms_digital_post.services.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/os2forms_digital_post/os2forms_digital_post.services.yml b/modules/os2forms_digital_post/os2forms_digital_post.services.yml index 31ff12ef..9b096fad 100644 --- a/modules/os2forms_digital_post/os2forms_digital_post.services.yml +++ b/modules/os2forms_digital_post/os2forms_digital_post.services.yml @@ -32,7 +32,7 @@ services: Drupal\os2forms_digital_post\Helper\DigitalPostHelper: arguments: - "@Drupal\\os2forms_digital_post\\Helper\\Settings" - - "@os2web_key.key_helper" + - "@Drupal\\os2web_key\\KeyHelper" - "@plugin.manager.os2web_datalookup" - "@Drupal\\os2forms_digital_post\\Helper\\MeMoHelper" - "@Drupal\\os2forms_digital_post\\Helper\\ForsendelseHelper" From 8d831d3ce146daa7956ddc99aba3ac489892f923 Mon Sep 17 00:00:00 2001 From: jekuaitk Date: Mon, 20 Jan 2025 10:02:15 +0100 Subject: [PATCH 15/46] Coding standards --- .../src/Plugin/os2web/DataLookup/DatafordelerDataLookup.php | 3 +-- modules/os2forms_fasit/src/Helper/Settings.php | 5 +---- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/modules/os2forms_dawa/src/Plugin/os2web/DataLookup/DatafordelerDataLookup.php b/modules/os2forms_dawa/src/Plugin/os2web/DataLookup/DatafordelerDataLookup.php index 9d3b1aaa..0e50ffaf 100644 --- a/modules/os2forms_dawa/src/Plugin/os2web/DataLookup/DatafordelerDataLookup.php +++ b/modules/os2forms_dawa/src/Plugin/os2web/DataLookup/DatafordelerDataLookup.php @@ -6,7 +6,6 @@ use Drupal\Core\File\FileSystem; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Plugin\ContainerFactoryPluginInterface; -use Drupal\key\KeyRepository; use Drupal\key\KeyRepositoryInterface; use Drupal\os2forms_dawa\Entity\DatafordelerMatrikula; use Drupal\os2web_audit\Service\Logger; @@ -43,7 +42,7 @@ public function __construct( * {@inheritdoc} */ public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { - /** @var Logger $auditLogger */ + /** @var \Drupal\os2web_audit\Service\Logger $auditLogger */ $auditLogger = $container->get('os2web_audit.logger'); /** @var \Drupal\key\KeyRepositoryInterface $keyRepository */ $keyRepository = $container->get('key.repository'); diff --git a/modules/os2forms_fasit/src/Helper/Settings.php b/modules/os2forms_fasit/src/Helper/Settings.php index 98d5a5e8..491175a0 100644 --- a/modules/os2forms_fasit/src/Helper/Settings.php +++ b/modules/os2forms_fasit/src/Helper/Settings.php @@ -48,10 +48,7 @@ public function getFasitApiTenant(): ?string { public function getFasitApiVersion(): ?string { return $this->get(SettingsForm::FASIT_API_VERSION); } - - - - + /** * Get key. */ From 1820f120c1b28ac1401cda231b9b1d65ea68ce9e Mon Sep 17 00:00:00 2001 From: jekuaitk Date: Mon, 20 Jan 2025 10:09:19 +0100 Subject: [PATCH 16/46] Coding standards --- modules/os2forms_fasit/src/Helper/Settings.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/os2forms_fasit/src/Helper/Settings.php b/modules/os2forms_fasit/src/Helper/Settings.php index 491175a0..ee9f7809 100644 --- a/modules/os2forms_fasit/src/Helper/Settings.php +++ b/modules/os2forms_fasit/src/Helper/Settings.php @@ -48,7 +48,7 @@ public function getFasitApiTenant(): ?string { public function getFasitApiVersion(): ?string { return $this->get(SettingsForm::FASIT_API_VERSION); } - + /** * Get key. */ From 34ec7140fb5208520da9d0d63cc00ef46782766a Mon Sep 17 00:00:00 2001 From: jekuaitk Date: Tue, 21 Jan 2025 12:54:47 +0100 Subject: [PATCH 17/46] All methods for configuring certificate in fasit module works --- .../src/Helper/CertificateLocatorHelper.php | 0 .../os2forms_fasit.services.yml | 5 + .../os2forms_fasit/src/Form/SettingsForm.php | 129 +++++++++++++++++- .../src/Helper/CertificateLocatorHelper.php | 9 +- .../os2forms_fasit/src/Helper/FasitHelper.php | 70 +++++++++- .../os2forms_fasit/src/Helper/Settings.php | 33 ++++- 6 files changed, 228 insertions(+), 18 deletions(-) create mode 100644 modules/os2forms_digital_post/src/Helper/CertificateLocatorHelper.php diff --git a/modules/os2forms_digital_post/src/Helper/CertificateLocatorHelper.php b/modules/os2forms_digital_post/src/Helper/CertificateLocatorHelper.php new file mode 100644 index 00000000..e69de29b diff --git a/modules/os2forms_fasit/os2forms_fasit.services.yml b/modules/os2forms_fasit/os2forms_fasit.services.yml index e6fe5e8c..2bd6917f 100644 --- a/modules/os2forms_fasit/os2forms_fasit.services.yml +++ b/modules/os2forms_fasit/os2forms_fasit.services.yml @@ -4,10 +4,15 @@ services: - "@config.factory" - "@key.repository" + Drupal\os2forms_fasit\Helper\CertificateLocatorHelper: + arguments: + - "@Drupal\\os2forms_fasit\\Helper\\Settings" + Drupal\os2forms_fasit\Helper\FasitHelper: arguments: - '@http_client' - '@entity_type.manager' - "@Drupal\\os2forms_fasit\\Helper\\Settings" - "@file_system" + - "@Drupal\\os2forms_fasit\\Helper\\CertificateLocatorHelper" - "@os2web_audit.logger" diff --git a/modules/os2forms_fasit/src/Form/SettingsForm.php b/modules/os2forms_fasit/src/Form/SettingsForm.php index f703255c..53d461fd 100644 --- a/modules/os2forms_fasit/src/Form/SettingsForm.php +++ b/modules/os2forms_fasit/src/Form/SettingsForm.php @@ -6,6 +6,7 @@ use Drupal\Core\Form\ConfigFormBase; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\StringTranslation\StringTranslationTrait; +use Drupal\os2forms_fasit\Helper\CertificateLocatorHelper; use Drupal\os2forms_fasit\Helper\FasitHelper; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -21,6 +22,9 @@ final class SettingsForm extends ConfigFormBase { public const FASIT_API_VERSION = 'fasit_api_version'; public const CERTIFICATE = 'certificate'; public const KEY = 'key'; + public const CERTIFICATE_PROVIDER = 'certificate_provider'; + public const PROVIDER_TYPE_FORM = 'form'; + public const PROVIDER_TYPE_KEY = 'key'; public const ACTION_PING_API = 'action_ping_api'; @@ -98,14 +102,122 @@ public function buildForm(array $form, FormStateInterface $form_state): array { '#description' => $this->t('Specifies which api version to use. Should probably be v2'), ]; - $form[self::KEY] = [ + $certificateConfig = $config->get(self::CERTIFICATE) ?? []; + + $form[self::CERTIFICATE] = [ + '#type' => 'fieldset', + '#title' => $this->t('Certificate'), + '#tree' => TRUE, + + self::CERTIFICATE_PROVIDER => [ + '#type' => 'select', + '#title' => $this->t('Provider'), + '#options' => [ + self::PROVIDER_TYPE_FORM => $this->t('Form'), + self::PROVIDER_TYPE_KEY => $this->t('Key'), + ], + '#default_value' => $certificateConfig[self::CERTIFICATE_PROVIDER] ?? self::PROVIDER_TYPE_FORM, + '#description' => $this->t('Specifies which provider to use'), + ], + ]; + + $form[self::CERTIFICATE][CertificateLocatorHelper::LOCATOR_TYPE] = [ + '#type' => 'select', + '#title' => $this->t('Certificate locator type'), + '#options' => [ + CertificateLocatorHelper::LOCATOR_TYPE_AZURE_KEY_VAULT => $this->t('Azure key vault'), + CertificateLocatorHelper::LOCATOR_TYPE_FILE_SYSTEM => $this->t('File system'), + ], + '#default_value' => $certificateConfig[CertificateLocatorHelper::LOCATOR_TYPE] ?? NULL, + '#states' => [ + 'visible' => [':input[name="certificate[certificate_provider]"]' => ['value' => self::PROVIDER_TYPE_FORM]], + ], + '#description' => $this->t('Specifies which locator to use'), + ]; + + $form[self::CERTIFICATE][CertificateLocatorHelper::LOCATOR_TYPE_AZURE_KEY_VAULT] = [ + '#type' => 'fieldset', + '#title' => $this->t('Azure key vault'), + '#states' => [ + 'visible' => [ + ':input[name="certificate[certificate_provider]"]' => ['value' => self::PROVIDER_TYPE_FORM], + 'and', + ':input[name="certificate[locator_type]"]' => ['value' => CertificateLocatorHelper::LOCATOR_TYPE_AZURE_KEY_VAULT], + ], + ], + ]; + + $settings = [ + CertificateLocatorHelper::LOCATOR_AZURE_KEY_VAULT_TENANT_ID => ['title' => $this->t('Tenant id')], + CertificateLocatorHelper::LOCATOR_AZURE_KEY_VAULT_APPLICATION_ID => ['title' => $this->t('Application id')], + CertificateLocatorHelper::LOCATOR_AZURE_KEY_VAULT_CLIENT_SECRET => ['title' => $this->t('Client secret')], + CertificateLocatorHelper::LOCATOR_AZURE_KEY_VAULT_NAME => ['title' => $this->t('Name')], + CertificateLocatorHelper::LOCATOR_AZURE_KEY_VAULT_SECRET => ['title' => $this->t('Secret')], + CertificateLocatorHelper::LOCATOR_AZURE_KEY_VAULT_VERSION => ['title' => $this->t('Version')], + ]; + + foreach ($settings as $key => $info) { + $form[self::CERTIFICATE][CertificateLocatorHelper::LOCATOR_TYPE_AZURE_KEY_VAULT][$key] = [ + '#type' => 'textfield', + '#title' => $info['title'], + '#default_value' => $certificateConfig[CertificateLocatorHelper::LOCATOR_TYPE_AZURE_KEY_VAULT][$key] ?? NULL, + '#states' => [ + 'required' => [ + ':input[name="certificate[certificate_provider]"]' => ['value' => self::PROVIDER_TYPE_FORM], + 'and', + ':input[name="certificate[locator_type]"]' => ['value' => CertificateLocatorHelper::LOCATOR_TYPE_AZURE_KEY_VAULT], + ], + ], + ]; + } + + $form[self::CERTIFICATE][CertificateLocatorHelper::LOCATOR_TYPE_FILE_SYSTEM] = [ + '#type' => 'fieldset', + '#title' => $this->t('File system'), + '#states' => [ + 'visible' => [ + ':input[name="certificate[certificate_provider]"]' => ['value' => self::PROVIDER_TYPE_FORM], + 'and', + ':input[name="certificate[locator_type]"]' => ['value' => CertificateLocatorHelper::LOCATOR_TYPE_FILE_SYSTEM], + ], + ], + + 'path' => [ + '#type' => 'textfield', + '#title' => $this->t('Path'), + '#default_value' => $certificateConfig[CertificateLocatorHelper::LOCATOR_TYPE_FILE_SYSTEM]['path'] ?? NULL, + '#states' => [ + 'required' => [ + ':input[name="certificate[certificate_provider]"]' => ['value' => self::PROVIDER_TYPE_FORM], + 'and', + ':input[name="certificate[locator_type]"]' => ['value' => CertificateLocatorHelper::LOCATOR_TYPE_FILE_SYSTEM] + ], + ], + ], + ]; + + $form[self::CERTIFICATE][CertificateLocatorHelper::LOCATOR_PASSPHRASE] = [ + '#type' => 'textfield', + '#title' => $this->t('Passphrase'), + '#default_value' => $certificateConfig[CertificateLocatorHelper::LOCATOR_PASSPHRASE] ?? NULL, + '#states' => [ + 'visible' => [ + ':input[name="certificate[certificate_provider]"]' => ['value' => self::PROVIDER_TYPE_FORM], + ], + ], + ]; + + $form[self::CERTIFICATE][self::PROVIDER_TYPE_KEY] = [ '#type' => 'key_select', '#key_filters' => [ 'type' => 'os2web_key_certificate', ], '#title' => $this->t('Key'), '#required' => TRUE, - '#default_value' => $config->get(self::KEY), + '#default_value' => $config->get(self::PROVIDER_TYPE_KEY), + '#states' => [ + 'visible' => [':input[name="certificate[certificate_provider]"]' => ['value' => self::PROVIDER_TYPE_KEY]], + ], ]; $form['actions']['ping_api'] = [ @@ -135,6 +247,17 @@ public function validateForm(array &$form, FormStateInterface $form_state): void return; } + $values = $form_state->getValues(); + + if (self::PROVIDER_TYPE_FORM === $values[self::CERTIFICATE][self::CERTIFICATE_PROVIDER]) { + if (CertificateLocatorHelper::LOCATOR_TYPE_FILE_SYSTEM === $values[self::CERTIFICATE][CertificateLocatorHelper::LOCATOR_TYPE]) { + $path = $values[self::CERTIFICATE][CertificateLocatorHelper::LOCATOR_TYPE_FILE_SYSTEM]['path'] ?? NULL; + if (!file_exists($path)) { + $form_state->setErrorByName('certificate][file_system][path', $this->t('Invalid certificate path: %path', ['%path' => $path])); + } + } + } + parent::validateForm($form, $form_state); } @@ -160,7 +283,7 @@ public function submitForm(array &$form, FormStateInterface $form_state): void { self::FASIT_API_BASE_URL, self::FASIT_API_TENANT, self::FASIT_API_VERSION, - self::KEY, + self::CERTIFICATE, ] as $key) { $config->set($key, $form_state->getValue($key)); } diff --git a/modules/os2forms_fasit/src/Helper/CertificateLocatorHelper.php b/modules/os2forms_fasit/src/Helper/CertificateLocatorHelper.php index bca6e3d1..4d56a580 100644 --- a/modules/os2forms_fasit/src/Helper/CertificateLocatorHelper.php +++ b/modules/os2forms_fasit/src/Helper/CertificateLocatorHelper.php @@ -18,7 +18,6 @@ class CertificateLocatorHelper { public const LOCATOR_TYPE = 'locator_type'; public const LOCATOR_TYPE_AZURE_KEY_VAULT = 'azure_key_vault'; - public const LOCATOR_TYPE_HASHICORP_KEY_VAULT = 'hashicorp_key_vault'; public const LOCATOR_TYPE_FILE_SYSTEM = 'file_system'; public const LOCATOR_PASSPHRASE = 'passphrase'; public const LOCATOR_AZURE_KEY_VAULT_TENANT_ID = 'tenant_id'; @@ -39,12 +38,12 @@ public function __construct(private readonly Settings $settings) { * Get certificate locator. */ public function getCertificateLocator(): CertificateLocatorInterface { - $certificateSettings = $this->settings->getCertificate(); + $config = $this->settings->getFasitCertificateConfig(); - $locatorType = $certificateSettings[self::LOCATOR_TYPE]; - $options = $certificateSettings[$locatorType]; + $locatorType = $config[self::LOCATOR_TYPE]; + $options = $config[$locatorType]; $options += [ - self::LOCATOR_PASSPHRASE => $certificateSettings[self::LOCATOR_PASSPHRASE] ?: '', + self::LOCATOR_PASSPHRASE => $config[self::LOCATOR_PASSPHRASE] ?: '', ]; if (self::LOCATOR_TYPE_AZURE_KEY_VAULT === $locatorType) { diff --git a/modules/os2forms_fasit/src/Helper/FasitHelper.php b/modules/os2forms_fasit/src/Helper/FasitHelper.php index 25a3a4db..e3f8dc83 100644 --- a/modules/os2forms_fasit/src/Helper/FasitHelper.php +++ b/modules/os2forms_fasit/src/Helper/FasitHelper.php @@ -11,6 +11,7 @@ use Drupal\os2forms_fasit\Exception\FileTypeException; use Drupal\os2forms_fasit\Exception\InvalidSettingException; use Drupal\os2forms_fasit\Exception\InvalidSubmissionException; +use Drupal\os2forms_fasit\Form\SettingsForm; use Drupal\os2forms_fasit\Plugin\WebformHandler\FasitWebformHandler; use Drupal\os2web_audit\Service\Logger; use Drupal\webform\Entity\WebformSubmission; @@ -41,6 +42,7 @@ public function __construct( private readonly EntityTypeManagerInterface $entityTypeManager, private readonly Settings $settings, private readonly FileSystemInterface $fileSystem, + private readonly CertificateLocatorHelper $certificateLocator, private readonly Logger $auditLogger, ) { } @@ -219,7 +221,8 @@ private function uploadDocument(array $uploads, string $submissionId, array $han 'Content-Type' => 'application/xml', ], 'body' => $body, - 'cert' => $this->settings->getCertificate(), + // 'cert' => $this->settings->getKeyValue(), +// 'cert' => $this->getCertificate(), ]; // Attempt upload. @@ -494,11 +497,27 @@ private function getSubmission(string $submissionId): EntityInterface { */ private function post(string $endpoint, array $options): ResponseInterface { try { - $certificate = $this->settings->getCertificate(); - $certPath = $this->fileSystem->tempnam($this->fileSystem->getTempDirectory(), 'os2forms_fasit_cert'); - // `tempnam` has created a file, so we must replace when saving. - $this->fileSystem->saveData($certificate, $certPath, FileSystemInterface::EXISTS_REPLACE); - $options['cert'] = $certPath; + $config = $this->settings->getFasitCertificateConfig(); + + // Key => string + // Azure => file without passphrase + // Filesystem => file with potential passphrase. + $provider = $config['certificate_provider']; + + if (SettingsForm::PROVIDER_TYPE_KEY === $provider) { + $certificate = $this->settings->getKeyValue(); + $certPath = $this->fileSystem->tempnam($this->fileSystem->getTempDirectory(), 'os2forms_fasit_cert'); + // `tempnam` has created a file, so we must replace when saving. + $this->fileSystem->saveData($certificate, $certPath, FileSystemInterface::EXISTS_REPLACE); + $options['cert'] = $certPath; + } + elseif (SettingsForm::PROVIDER_TYPE_FORM === $provider) { + [$certificateOptions] = $this->getCertificateOptionsAndTempCertFilename(); + $options['cert'] = $certificateOptions; + } + else { + throw new InvalidSettingException('Invalid certificate configuration'); + } return $this->client->request('POST', $endpoint, $options); } finally { @@ -534,4 +553,43 @@ public function pingApi(): void { } } + /** + * Get certificate. + * + * @throws InvalidSettingException + */ + private function getCertificate(): mixed { + $config = $this->settings->getFasitCertificateConfig(); + $provider = $config['certificate_provider']; + if (SettingsForm::PROVIDER_TYPE_KEY === $provider) { + return $this->settings->getKeyValue(); + } + elseif (SettingsForm::PROVIDER_TYPE_FORM === $provider) { + [$certificateOptions, $tempCertFilename] = $this->getCertificateOptionsAndTempCertFilename(); + return $certificateOptions; + } + + throw new InvalidSettingException('Invalid certificate configuration'); + } + + /** + * Gets certificate options and temp certificate filename. + * + * @throws \Drupal\os2forms_fasit\Exception\CertificateLocatorException + * Certificate locator exception. + * + * @phpstan-return array + */ + private function getCertificateOptionsAndTempCertFilename(): array { + $certificateLocator = $this->certificateLocator->getCertificateLocator(); + $localCertFilename = tempnam(sys_get_temp_dir(), 'cert'); + file_put_contents($localCertFilename, $certificateLocator->getCertificate()); + $certificateOptions = + $certificateLocator->hasPassphrase() ? + [$localCertFilename, $certificateLocator->getPassphrase()] + : $localCertFilename; + + return [$certificateOptions, $localCertFilename]; + } + } diff --git a/modules/os2forms_fasit/src/Helper/Settings.php b/modules/os2forms_fasit/src/Helper/Settings.php index ee9f7809..d1db9702 100644 --- a/modules/os2forms_fasit/src/Helper/Settings.php +++ b/modules/os2forms_fasit/src/Helper/Settings.php @@ -50,18 +50,43 @@ public function getFasitApiVersion(): ?string { } /** - * Get key. + * Get Fasit configuration selector */ - public function getKey(): ?string { + public function getFasitCertificateConfig(): ?array { + return $this->get(SettingsForm::CERTIFICATE); + } + + /** + * Get Fasit certificate provider. + */ + public function getFasitCertificateProvider(): string { + $config = $this->getFasitCertificateConfig(); + + return $config[SettingsForm::CERTIFICATE_PROVIDER] ?? SettingsForm::PROVIDER_TYPE_FORM; + } + + /** + * Get Fasit certificate locator. + */ + public function getFasitCertificateLocator(): string { + $config = $this->getFasitCertificateConfig(); + + return $config[CertificateLocatorHelper::LOCATOR_TYPE] ?? CertificateLocatorHelper::LOCATOR_TYPE_FILE_SYSTEM; + } + + /** + * Get Fasit key certificate configuration. + */ + public function getFasitCertificateKey(): ?string { return $this->get(SettingsForm::KEY); } /** * Get certificate. */ - public function getCertificate(): ?string { + public function getKeyValue(): ?string { $key = $this->keyRepository->getKey( - $this->getKey(), + $this->getFasitCertificateKey(), ); return $key?->getKeyValue(); From 33d0c3b0ce5301a77e08dc4e918588f5d3117127 Mon Sep 17 00:00:00 2001 From: jekuaitk Date: Tue, 21 Jan 2025 13:19:22 +0100 Subject: [PATCH 18/46] Applied coding standards --- .../os2forms_fasit/src/Form/SettingsForm.php | 6 +----- .../os2forms_fasit/src/Helper/FasitHelper.php | 21 ------------------- .../os2forms_fasit/src/Helper/Settings.php | 2 +- 3 files changed, 2 insertions(+), 27 deletions(-) diff --git a/modules/os2forms_fasit/src/Form/SettingsForm.php b/modules/os2forms_fasit/src/Form/SettingsForm.php index 53d461fd..fdd6e0e0 100644 --- a/modules/os2forms_fasit/src/Form/SettingsForm.php +++ b/modules/os2forms_fasit/src/Form/SettingsForm.php @@ -141,7 +141,6 @@ public function buildForm(array $form, FormStateInterface $form_state): array { '#states' => [ 'visible' => [ ':input[name="certificate[certificate_provider]"]' => ['value' => self::PROVIDER_TYPE_FORM], - 'and', ':input[name="certificate[locator_type]"]' => ['value' => CertificateLocatorHelper::LOCATOR_TYPE_AZURE_KEY_VAULT], ], ], @@ -164,7 +163,6 @@ public function buildForm(array $form, FormStateInterface $form_state): array { '#states' => [ 'required' => [ ':input[name="certificate[certificate_provider]"]' => ['value' => self::PROVIDER_TYPE_FORM], - 'and', ':input[name="certificate[locator_type]"]' => ['value' => CertificateLocatorHelper::LOCATOR_TYPE_AZURE_KEY_VAULT], ], ], @@ -177,7 +175,6 @@ public function buildForm(array $form, FormStateInterface $form_state): array { '#states' => [ 'visible' => [ ':input[name="certificate[certificate_provider]"]' => ['value' => self::PROVIDER_TYPE_FORM], - 'and', ':input[name="certificate[locator_type]"]' => ['value' => CertificateLocatorHelper::LOCATOR_TYPE_FILE_SYSTEM], ], ], @@ -189,8 +186,7 @@ public function buildForm(array $form, FormStateInterface $form_state): array { '#states' => [ 'required' => [ ':input[name="certificate[certificate_provider]"]' => ['value' => self::PROVIDER_TYPE_FORM], - 'and', - ':input[name="certificate[locator_type]"]' => ['value' => CertificateLocatorHelper::LOCATOR_TYPE_FILE_SYSTEM] + ':input[name="certificate[locator_type]"]' => ['value' => CertificateLocatorHelper::LOCATOR_TYPE_FILE_SYSTEM], ], ], ], diff --git a/modules/os2forms_fasit/src/Helper/FasitHelper.php b/modules/os2forms_fasit/src/Helper/FasitHelper.php index e3f8dc83..12a5c51f 100644 --- a/modules/os2forms_fasit/src/Helper/FasitHelper.php +++ b/modules/os2forms_fasit/src/Helper/FasitHelper.php @@ -221,8 +221,6 @@ private function uploadDocument(array $uploads, string $submissionId, array $han 'Content-Type' => 'application/xml', ], 'body' => $body, - // 'cert' => $this->settings->getKeyValue(), -// 'cert' => $this->getCertificate(), ]; // Attempt upload. @@ -553,25 +551,6 @@ public function pingApi(): void { } } - /** - * Get certificate. - * - * @throws InvalidSettingException - */ - private function getCertificate(): mixed { - $config = $this->settings->getFasitCertificateConfig(); - $provider = $config['certificate_provider']; - if (SettingsForm::PROVIDER_TYPE_KEY === $provider) { - return $this->settings->getKeyValue(); - } - elseif (SettingsForm::PROVIDER_TYPE_FORM === $provider) { - [$certificateOptions, $tempCertFilename] = $this->getCertificateOptionsAndTempCertFilename(); - return $certificateOptions; - } - - throw new InvalidSettingException('Invalid certificate configuration'); - } - /** * Gets certificate options and temp certificate filename. * diff --git a/modules/os2forms_fasit/src/Helper/Settings.php b/modules/os2forms_fasit/src/Helper/Settings.php index d1db9702..09d0cd92 100644 --- a/modules/os2forms_fasit/src/Helper/Settings.php +++ b/modules/os2forms_fasit/src/Helper/Settings.php @@ -50,7 +50,7 @@ public function getFasitApiVersion(): ?string { } /** - * Get Fasit configuration selector + * Get Fasit configuration selector. */ public function getFasitCertificateConfig(): ?array { return $this->get(SettingsForm::CERTIFICATE); From d5d476b6be6fde48cb9e8fa33cbbd2f0b99d923c Mon Sep 17 00:00:00 2001 From: jekuaitk Date: Tue, 21 Jan 2025 13:54:58 +0100 Subject: [PATCH 19/46] Updated fasit test command --- modules/os2forms_fasit/drush.services.yml | 3 ++- .../src/{Drush => }/Commands/FasitTestCommands.php | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) rename modules/os2forms_fasit/src/{Drush => }/Commands/FasitTestCommands.php (93%) diff --git a/modules/os2forms_fasit/drush.services.yml b/modules/os2forms_fasit/drush.services.yml index 7b8cbec9..462221c7 100644 --- a/modules/os2forms_fasit/drush.services.yml +++ b/modules/os2forms_fasit/drush.services.yml @@ -1,5 +1,6 @@ services: - Drupal\os2forms_fasit\Drush\Commands\FasitTestCommands: + os2forms_fasit.commands: + class: \Drupal\os2forms_fasit\Commands\FasitTestCommands arguments: - '@Drupal\os2forms_fasit\Helper\FasitHelper' tags: diff --git a/modules/os2forms_fasit/src/Drush/Commands/FasitTestCommands.php b/modules/os2forms_fasit/src/Commands/FasitTestCommands.php similarity index 93% rename from modules/os2forms_fasit/src/Drush/Commands/FasitTestCommands.php rename to modules/os2forms_fasit/src/Commands/FasitTestCommands.php index 4ac71534..f24536a9 100644 --- a/modules/os2forms_fasit/src/Drush/Commands/FasitTestCommands.php +++ b/modules/os2forms_fasit/src/Commands/FasitTestCommands.php @@ -1,6 +1,6 @@ Date: Wed, 22 Jan 2025 10:40:48 +0100 Subject: [PATCH 20/46] Updated Fasit ping command --- modules/os2forms_fasit/drush.services.yml | 7 ------- .../Commands/FasitTestCommand.php} | 19 +++++++++++++++---- 2 files changed, 15 insertions(+), 11 deletions(-) delete mode 100644 modules/os2forms_fasit/drush.services.yml rename modules/os2forms_fasit/src/{Commands/FasitTestCommands.php => Drush/Commands/FasitTestCommand.php} (56%) diff --git a/modules/os2forms_fasit/drush.services.yml b/modules/os2forms_fasit/drush.services.yml deleted file mode 100644 index 462221c7..00000000 --- a/modules/os2forms_fasit/drush.services.yml +++ /dev/null @@ -1,7 +0,0 @@ -services: - os2forms_fasit.commands: - class: \Drupal\os2forms_fasit\Commands\FasitTestCommands - arguments: - - '@Drupal\os2forms_fasit\Helper\FasitHelper' - tags: - - { name: drush.command } diff --git a/modules/os2forms_fasit/src/Commands/FasitTestCommands.php b/modules/os2forms_fasit/src/Drush/Commands/FasitTestCommand.php similarity index 56% rename from modules/os2forms_fasit/src/Commands/FasitTestCommands.php rename to modules/os2forms_fasit/src/Drush/Commands/FasitTestCommand.php index f24536a9..586adc04 100644 --- a/modules/os2forms_fasit/src/Commands/FasitTestCommands.php +++ b/modules/os2forms_fasit/src/Drush/Commands/FasitTestCommand.php @@ -1,21 +1,32 @@ get(FasitHelper::class), + ); } /** From fa892f9746d714a6f73099684fb9e86d5180ef69 Mon Sep 17 00:00:00 2001 From: jekuaitk Date: Wed, 22 Jan 2025 11:41:49 +0100 Subject: [PATCH 21/46] Fasit module, cleaned up services --- CHANGELOG.md | 2 ++ .../os2forms_fasit/os2forms_fasit.services.yml | 15 +++++---------- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2feae1a1..9ba06141 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,8 @@ before starting to add changes. Use example [placed in the end of the page](#exa - [#101](https://github.com/OS2Forms/os2forms/pull/101) - Added support for `os2web_key` in Digital post - Added support for `os2web_key` in Fasit handler. + - Switched from saving settings in key value store to config, i.e + the module needs to be reconfigured. ## [3.21.1] 2025-01-06 diff --git a/modules/os2forms_fasit/os2forms_fasit.services.yml b/modules/os2forms_fasit/os2forms_fasit.services.yml index 2bd6917f..e70008fb 100644 --- a/modules/os2forms_fasit/os2forms_fasit.services.yml +++ b/modules/os2forms_fasit/os2forms_fasit.services.yml @@ -1,18 +1,13 @@ services: Drupal\os2forms_fasit\Helper\Settings: + autowire: true arguments: - - "@config.factory" - - "@key.repository" + $keyRepository: "@key.repository" Drupal\os2forms_fasit\Helper\CertificateLocatorHelper: - arguments: - - "@Drupal\\os2forms_fasit\\Helper\\Settings" + autowire: true Drupal\os2forms_fasit\Helper\FasitHelper: + autowire: true arguments: - - '@http_client' - - '@entity_type.manager' - - "@Drupal\\os2forms_fasit\\Helper\\Settings" - - "@file_system" - - "@Drupal\\os2forms_fasit\\Helper\\CertificateLocatorHelper" - - "@os2web_audit.logger" + $auditLogger: "@os2web_audit.logger" From 6f0d1c2a89c2d38acc953bc5dd528c27ed771f97 Mon Sep 17 00:00:00 2001 From: Mikkel Ricky Date: Tue, 7 May 2024 14:26:01 +0200 Subject: [PATCH 22/46] Moved digital post settings into config. Added support for os2web_key to get certificate. --- .github/workflows/pr.yml | 31 +-- .gitignore | 2 - .markdownlint.jsonc | 13 + .markdownlintrc | 18 -- CHANGELOG.md | 2 + README.md | 20 +- composer.json | 68 +++-- modules/os2forms_digital_post/README.md | 4 + .../os2forms_digital_post.info.yml | 1 + .../os2forms_digital_post.install | 9 + .../os2forms_digital_post.services.yml | 6 +- .../src/Exception/InvalidSettingException.php | 10 - .../src/Form/SettingsForm.php | 238 +++++++----------- .../src/Helper/CertificateLocatorHelper.php | 79 ------ .../src/Helper/DigitalPostHelper.php | 8 +- .../src/Helper/KeyCertificateLocator.php | 59 +++++ .../src/Helper/MemoryCertificateLocator.php | 49 ++++ .../src/Helper/Settings.php | 146 +++++++---- package.json | 13 - scripts/code-analysis | 18 +- 20 files changed, 417 insertions(+), 377 deletions(-) create mode 100644 .markdownlint.jsonc delete mode 100644 .markdownlintrc delete mode 100644 modules/os2forms_digital_post/src/Exception/InvalidSettingException.php delete mode 100644 modules/os2forms_digital_post/src/Helper/CertificateLocatorHelper.php create mode 100644 modules/os2forms_digital_post/src/Helper/KeyCertificateLocator.php create mode 100644 modules/os2forms_digital_post/src/Helper/MemoryCertificateLocator.php delete mode 100644 package.json diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index f50b23dc..c78e9623 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -50,6 +50,9 @@ jobs: composer validate --strict composer.json # Check that dependencies resolve. composer update --${{ matrix.dependency-version }} --prefer-dist --no-interaction + - name: Check that composer file is normalized + run: | + composer normalize --dry-run php-coding-standards: name: PHP coding standards @@ -113,27 +116,13 @@ jobs: run: | ./scripts/code-analysis - markdownlint: + coding-standards-markdown: + name: Markdown coding standards runs-on: ubuntu-latest - name: markdownlint steps: - name: Checkout - uses: actions/checkout@v2 - - name: Get yarn cache directory path - id: yarn-cache-dir-path - run: echo "::set-output name=dir::$(yarn cache dir)" - - name: Cache yarn packages - uses: actions/cache@v2 - id: yarn-cache - with: - path: ${{ steps.yarn-cache-dir-path.outputs.dir }} - key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} - restore-keys: | - ${{ runner.os }}-yarn- - - name: Yarn install - uses: actions/setup-node@v2 - with: - node-version: '20' - - run: yarn install - - name: markdownlint - run: yarn coding-standards-check/markdownlint + uses: actions/checkout@master + + - name: Coding standards + run: | + docker run --rm --volume $PWD:/md peterdavehello/markdownlint markdownlint --ignore vendor --ignore LICENSE.md '**/*.md' diff --git a/.gitignore b/.gitignore index 1cc8643c..1a6c2523 100644 --- a/.gitignore +++ b/.gitignore @@ -4,5 +4,3 @@ composer.lock vendor -node_modules/ -yarn.lock diff --git a/.markdownlint.jsonc b/.markdownlint.jsonc new file mode 100644 index 00000000..a28c5809 --- /dev/null +++ b/.markdownlint.jsonc @@ -0,0 +1,13 @@ +{ + "default": true, + // https://github.com/DavidAnson/markdownlint/blob/main/doc/md013.md + "line-length": { + "line_length": 120, + "code_blocks": false, + "tables": false + }, + // https://github.com/DavidAnson/markdownlint/blob/main/doc/md024.md + "no-duplicate-heading": { + "siblings_only": true + } +} diff --git a/.markdownlintrc b/.markdownlintrc deleted file mode 100644 index 75637156..00000000 --- a/.markdownlintrc +++ /dev/null @@ -1,18 +0,0 @@ -{ - // @see https://github.com/DavidAnson/markdownlint/blob/main/schema/.markdownlint.jsonc - // https://github.com/DavidAnson/markdownlint/blob/main/doc/md013.md - "MD013": { - // Exclude code blocks - "code_blocks": false - }, - - // Prevent complaining on duplicated headings in CHANGELOG.md - // https://github.com/DavidAnson/markdownlint/blob/main/doc/md024.md - "MD024": { - "siblings_only": true - } -} - -// Local Variables: -// mode: json -// End: diff --git a/CHANGELOG.md b/CHANGELOG.md index 274eb0cc..23821caf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,8 @@ before starting to add changes. Use example [placed in the end of the page](#exa ## [Unreleased] +- [#101](https://github.com/OS2Forms/os2forms/pull/101) + Added support for os2web_key - Removed modules ldap_auth, logging_alerts, maillog ## [3.21.2] 2025-01-07 diff --git a/README.md b/README.md index 12e4ad05..90245a21 100644 --- a/README.md +++ b/README.md @@ -122,29 +122,27 @@ run the checks locally. ```sh docker run --rm --volume ${PWD}:/app --workdir /app itkdev/php8.1-fpm composer install -docker run --rm --volume ${PWD}:/app --workdir /app itkdev/php8.1-fpm composer coding-standards-check - # Fix (some) coding standards issues. docker run --rm --volume ${PWD}:/app --workdir /app itkdev/php8.1-fpm composer coding-standards-apply +docker run --rm --volume ${PWD}:/app --workdir /app itkdev/php8.1-fpm composer coding-standards-check ``` ### Markdown ```sh -docker run --rm --volume ${PWD}:/app --workdir /app node:20 yarn install -docker run --rm --volume ${PWD}:/app --workdir /app node:20 yarn coding-standards-check/markdownlint - -# Fix (some) coding standards issues. -docker run --rm --volume ${PWD}:/app --workdir /app node:20 yarn coding-standards-apply/markdownlint +docker run --rm --volume $PWD:/md peterdavehello/markdownlint markdownlint --ignore vendor --ignore LICENSE.md '**/*.md' --fix +docker run --rm --volume $PWD:/md peterdavehello/markdownlint markdownlint --ignore vendor --ignore LICENSE.md '**/*.md' ``` ## Code analysis We use [PHPStan](https://phpstan.org/) for static code analysis. -Running statis code analysis on a standalone Drupal module is a bit tricky, so -we use a helper script to run the analysis: +Running statis code analysis on a standalone Drupal module is a bit tricky, so we use a helper script to run the +analysis: -```sh -./scripts/code-analysis +```shell +docker run --rm --volume ${PWD}:/app --workdir /app itkdev/php8.1-fpm ./scripts/code-analysis ``` + +**Note**: Currently the code analysis is only run on the `os2forms_digital_post` sub-module (cf. [`phpstan.neon`](./phpstan.neon)). diff --git a/composer.json b/composer.json index 828bd6ca..f997c480 100644 --- a/composer.json +++ b/composer.json @@ -1,20 +1,8 @@ { "name": "os2forms/os2forms", - "type": "drupal-module", "description": "Drupal 8 OS2Form module provides advanced webform functionality for Danish Municipalities", - "minimum-stability": "dev", - "prefer-stable": true, "license": "EUPL-1.2", - "repositories": { - "drupal": { - "type": "composer", - "url": "https://packages.drupal.org/8" - }, - "assets": { - "type": "composer", - "url": "https://asset-packagist.org" - } - }, + "type": "drupal-module", "require": { "php": "^8.1", "ext-dom": "*", @@ -43,7 +31,7 @@ "drupal/mailsystem": "^4.1", "drupal/masquerade": "^2.0@RC", "drupal/pathauto": "^1.5", - "drupal/permissions_by_term": "^3.1 || ^2.25", + "drupal/permissions_by_term": "^2.25 || ^3.1", "drupal/queue_mail": "^1.4", "drupal/r4032login": "^2.1", "drupal/redirect": "^1.4", @@ -71,6 +59,7 @@ "itk-dev/serviceplatformen": "^1.5", "os2web/os2web_audit": "^0.1.6", "os2web/os2web_datalookup": "^2.0", + "os2web/os2web_key": "dev-os2web_key", "os2web/os2web_nemlogin": "^1.0", "os2web/os2web_simplesaml": "dev-master", "php-http/guzzle7-adapter": "^1.0", @@ -84,15 +73,44 @@ "require-dev": { "dealerdirect/phpcodesniffer-composer-installer": "^0.7.1", "drupal/coder": "^8.3", + "ergebnis/composer-normalize": "^2.42", "mglaman/phpstan-drupal": "^1.1", "phpstan/extension-installer": "^1.3", "phpstan/phpstan-deprecation-rules": "^1.1", "phpunit/phpunit": "^9.5", "wsdltophp/packagegenerator": "^4.0" }, - "extra" : { + "repositories": { + "os2web/os2web_key": { + "type": "vcs", + "url": "https://github.com/itk-dev/os2web_key" + }, + "drupal": { + "type": "composer", + "url": "https://packages.drupal.org/8" + }, + "assets": { + "type": "composer", + "url": "https://asset-packagist.org" + } + }, + "minimum-stability": "dev", + "prefer-stable": true, + "config": { + "allow-plugins": { + "cweagans/composer-patches": true, + "dealerdirect/phpcodesniffer-composer-installer": true, + "ergebnis/composer-normalize": true, + "phpstan/extension-installer": true, + "simplesamlphp/composer-module-installer": true, + "vaimo/composer-patches": true, + "zaporylie/composer-drupal-optimizations": true + }, + "sort-packages": true + }, + "extra": { "composer-exit-on-patch-failure": false, - "enable-patching" : true, + "enable-patching": true, "patches": { "drupal/entity_print": { "2733781 - Add Export to Word Support": "https://www.drupal.org/files/issues/2019-11-22/2733781-47.patch" @@ -124,23 +142,23 @@ } }, "scripts": { - "code-analysis/phpstan": [ - "phpstan analyse" - ], "code-analysis": [ "@code-analysis/phpstan" ], - "coding-standards-check/phpcs": [ - "phpcs --standard=phpcs.xml.dist" + "code-analysis/phpstan": [ + "phpstan analyse" ], - "coding-standards-check": [ - "@coding-standards-check/phpcs" + "coding-standards-apply": [ + "@coding-standards-apply/phpcs" ], "coding-standards-apply/phpcs": [ "phpcbf --standard=phpcs.xml.dist" ], - "coding-standards-apply": [ - "@coding-standards-apply/phpcs" + "coding-standards-check": [ + "@coding-standards-check/phpcs" + ], + "coding-standards-check/phpcs": [ + "phpcs --standard=phpcs.xml.dist" ] }, "config": { diff --git a/modules/os2forms_digital_post/README.md b/modules/os2forms_digital_post/README.md index a487b13e..c36e9f48 100644 --- a/modules/os2forms_digital_post/README.md +++ b/modules/os2forms_digital_post/README.md @@ -31,6 +31,10 @@ examples](modules/os2forms_digital_post_examples/README.md). Go to `/admin/os2forms_digital_post/settings` to set up global settings for digital post. +### Key + +We use [os2web_key](https://github.com/OS2web/os2web_key) to provide the certificate for sending digital post. + ### Queue The actual sending of digital post is handled by jobs in an [Advanced diff --git a/modules/os2forms_digital_post/os2forms_digital_post.info.yml b/modules/os2forms_digital_post/os2forms_digital_post.info.yml index 71a17688..0e1408cc 100644 --- a/modules/os2forms_digital_post/os2forms_digital_post.info.yml +++ b/modules/os2forms_digital_post/os2forms_digital_post.info.yml @@ -7,6 +7,7 @@ dependencies: - 'beskedfordeler:beskedfordeler' - 'drupal:advancedqueue' - 'os2web_datalookup:os2web_datalookup' + - 'os2web_key:os2web_key' - 'webform:webform' - 'webform:webform_submission_log' - 'os2web:os2web_audit' diff --git a/modules/os2forms_digital_post/os2forms_digital_post.install b/modules/os2forms_digital_post/os2forms_digital_post.install index 760743cb..80b756ac 100644 --- a/modules/os2forms_digital_post/os2forms_digital_post.install +++ b/modules/os2forms_digital_post/os2forms_digital_post.install @@ -17,3 +17,12 @@ use Drupal\os2forms_digital_post\Helper\BeskedfordelerHelper; function os2forms_digital_post_schema() { return Drupal::service(BeskedfordelerHelper::class)->schema(); } + +/** + * Implements hook_update_N(). + */ +function os2forms_digital_post_update_9001() { + \Drupal::service('module_installer')->install([ + 'os2web_key', + ], TRUE); +} diff --git a/modules/os2forms_digital_post/os2forms_digital_post.services.yml b/modules/os2forms_digital_post/os2forms_digital_post.services.yml index c13fb96f..66bc3132 100644 --- a/modules/os2forms_digital_post/os2forms_digital_post.services.yml +++ b/modules/os2forms_digital_post/os2forms_digital_post.services.yml @@ -9,11 +9,13 @@ services: Drupal\os2forms_digital_post\Helper\Settings: arguments: - - "@keyvalue" + - "@config.factory" + - "@key.repository" Drupal\os2forms_digital_post\Helper\CertificateLocatorHelper: arguments: - "@Drupal\\os2forms_digital_post\\Helper\\Settings" + - "@key.repository" Drupal\os2forms_digital_post\Helper\MeMoHelper: arguments: @@ -30,7 +32,7 @@ services: Drupal\os2forms_digital_post\Helper\DigitalPostHelper: arguments: - "@Drupal\\os2forms_digital_post\\Helper\\Settings" - - "@Drupal\\os2forms_digital_post\\Helper\\CertificateLocatorHelper" + - "@Drupal\\os2web_key\\CertificateHelper" - "@plugin.manager.os2web_datalookup" - "@Drupal\\os2forms_digital_post\\Helper\\MeMoHelper" - "@Drupal\\os2forms_digital_post\\Helper\\ForsendelseHelper" diff --git a/modules/os2forms_digital_post/src/Exception/InvalidSettingException.php b/modules/os2forms_digital_post/src/Exception/InvalidSettingException.php deleted file mode 100644 index c3d34af6..00000000 --- a/modules/os2forms_digital_post/src/Exception/InvalidSettingException.php +++ /dev/null @@ -1,10 +0,0 @@ -queueStorage = $entityTypeManager->getStorage('advancedqueue_queue'); } @@ -44,12 +46,23 @@ public function __construct( */ public static function create(ContainerInterface $container) { return new static( + $container->get('config.factory'), + $container->get('entity_type.manager'), $container->get(Settings::class), - $container->get(CertificateLocatorHelper::class), - $container->get('entity_type.manager') ); } + /** + * {@inheritdoc} + * + * @phpstan-return array + */ + protected function getEditableConfigNames() { + return [ + Settings::CONFIG_NAME, + ]; + } + /** * {@inheritdoc} */ @@ -63,15 +76,26 @@ public function getFormId() { * @phpstan-param array $form * @phpstan-return array */ - public function buildForm(array $form, FormStateInterface $form_state) { - $form['test_mode'] = [ + public function buildForm(array $form, FormStateInterface $form_state): array { + $form = parent::buildForm($form, $form_state); + + $form['message'] = [ + '#theme' => 'status_messages', + '#message_list' => [ + 'status' => [ + $this->t('Use drush os2forms-digital-post:test:send to test sending digital post.'), + ], + ], + ]; + + $form[Settings::TEST_MODE] = [ '#type' => 'checkbox', '#title' => $this->t('Test mode'), - '#default_value' => $this->settings->getTestMode(), + '#default_value' => $this->settings->getEditableValue(Settings::TEST_MODE), + '#description' => $this->createDescription(Settings::TEST_MODE), ]; - $sender = $this->settings->getSender(); - $form['sender'] = [ + $form[Settings::SENDER] = [ '#type' => 'fieldset', '#title' => $this->t('Sender'), '#tree' => TRUE, @@ -82,126 +106,74 @@ public function buildForm(array $form, FormStateInterface $form_state) { '#options' => [ 'CVR' => $this->t('CVR'), ], - '#default_value' => $sender[Settings::SENDER_IDENTIFIER_TYPE] ?? 'CVR', + '#default_value' => $this->settings->getEditableValue([Settings::SENDER, Settings::SENDER_IDENTIFIER_TYPE]) ?? 'CVR', '#required' => TRUE, + '#description' => $this->createDescription([Settings::SENDER, Settings::SENDER_IDENTIFIER_TYPE]), ], Settings::SENDER_IDENTIFIER => [ '#type' => 'textfield', '#title' => $this->t('Identifier'), - '#default_value' => $sender[Settings::SENDER_IDENTIFIER] ?? NULL, + '#default_value' => $this->settings->getEditableValue([Settings::SENDER, Settings::SENDER_IDENTIFIER]), '#required' => TRUE, + '#description' => $this->createDescription([Settings::SENDER, Settings::SENDER_IDENTIFIER]), ], Settings::FORSENDELSES_TYPE_IDENTIFIKATOR => [ '#type' => 'textfield', '#title' => $this->t('Forsendelsestypeidentifikator'), - '#default_value' => $sender[Settings::FORSENDELSES_TYPE_IDENTIFIKATOR] ?? NULL, + '#default_value' => $this->settings->getEditableValue([ + Settings::SENDER, Settings::FORSENDELSES_TYPE_IDENTIFIKATOR, + ]), '#required' => TRUE, + '#description' => $this->createDescription([Settings::SENDER, Settings::FORSENDELSES_TYPE_IDENTIFIKATOR]), ], ]; - $certificate = $this->settings->getCertificate(); - $form['certificate'] = [ + $form[Settings::CERTIFICATE] = [ '#type' => 'fieldset', '#title' => $this->t('Certificate'), '#tree' => TRUE, - 'locator_type' => [ - '#type' => 'select', - '#title' => $this->t('Certificate locator type'), - '#options' => [ - 'azure_key_vault' => $this->t('Azure key vault'), - 'file_system' => $this->t('File system'), - ], - '#default_value' => $certificate['locator_type'] ?? NULL, - ], - ]; - - $form['certificate'][CertificateLocatorHelper::LOCATOR_TYPE_AZURE_KEY_VAULT] = [ - '#type' => 'fieldset', - '#title' => $this->t('Azure key vault'), - '#states' => [ - 'visible' => [':input[name="certificate[locator_type]"]' => ['value' => CertificateLocatorHelper::LOCATOR_TYPE_AZURE_KEY_VAULT]], - ], - ]; - - $settings = [ - 'tenant_id' => ['title' => $this->t('Tenant id')], - 'application_id' => ['title' => $this->t('Application id')], - 'client_secret' => ['title' => $this->t('Client secret')], - 'name' => ['title' => $this->t('Name')], - 'secret' => ['title' => $this->t('Secret')], - 'version' => ['title' => $this->t('Version')], - ]; - - foreach ($settings as $key => $info) { - $form['certificate'][CertificateLocatorHelper::LOCATOR_TYPE_AZURE_KEY_VAULT][$key] = [ - '#type' => 'textfield', - '#title' => $info['title'], - '#default_value' => $certificate[CertificateLocatorHelper::LOCATOR_TYPE_AZURE_KEY_VAULT][$key] ?? NULL, - '#states' => [ - 'required' => [':input[name="certificate[locator_type]"]' => ['value' => CertificateLocatorHelper::LOCATOR_TYPE_AZURE_KEY_VAULT]], - ], - ]; - } - - $form['certificate'][CertificateLocatorHelper::LOCATOR_TYPE_FILE_SYSTEM] = [ - '#type' => 'fieldset', - '#title' => $this->t('File system'), - '#states' => [ - 'visible' => [':input[name="certificate[locator_type]"]' => ['value' => CertificateLocatorHelper::LOCATOR_TYPE_FILE_SYSTEM]], - ], - - 'path' => [ - '#type' => 'textfield', - '#title' => $this->t('Path'), - '#default_value' => $certificate[CertificateLocatorHelper::LOCATOR_TYPE_FILE_SYSTEM]['path'] ?? NULL, - '#states' => [ - 'required' => [':input[name="certificate[locator_type]"]' => ['value' => CertificateLocatorHelper::LOCATOR_TYPE_FILE_SYSTEM]], + Settings::KEY => [ + '#type' => 'key_select', + '#key_filters' => [ + 'type' => 'os2web_key_certificate', ], + '#key_description' => FALSE, + '#title' => $this->t('Key'), + '#default_value' => $this->settings->getEditableValue([Settings::CERTIFICATE, Settings::KEY]), + '#required' => TRUE, + '#description' => $this->createDescription([Settings::CERTIFICATE, Settings::KEY]), ], ]; - $form['certificate']['passphrase'] = [ - '#type' => 'textfield', - '#title' => $this->t('Passphrase'), - '#default_value' => $certificate['passphrase'] ?? NULL, - ]; - - $processing = $this->settings->getProcessing(); - $form['processing'] = [ + $form[Settings::PROCESSING] = [ '#type' => 'fieldset', '#title' => $this->t('Processing'), '#tree' => TRUE, ]; - $defaultValue = $processing['queue'] ?? 'os2forms_digital_post'; - $form['processing']['queue'] = [ + $queue = $this->settings->getEditableValue([Settings::PROCESSING, Settings::QUEUE]); + $form[Settings::PROCESSING][Settings::QUEUE] = [ '#type' => 'select', '#title' => $this->t('Queue'), '#options' => array_map( static fn(EntityInterface $queue) => $queue->label(), $this->queueStorage->loadMultiple() ), - '#default_value' => $defaultValue, - '#description' => $this->t("Queue for digital post jobs. The queue must be run via Drupal's cron or via drush advancedqueue:queue:process @queue(in a cron job).", [ - '@queue' => $defaultValue, - ':queue_url' => '/admin/config/system/queues/jobs/' . urlencode($defaultValue), - ]), - ]; - - $form['actions']['#type'] = 'actions'; - - $form['actions']['submit'] = [ - '#type' => 'submit', - '#value' => $this->t('Save settings'), - ]; - - $form['actions']['testCertificate'] = [ - '#type' => 'submit', - '#name' => 'testCertificate', - '#value' => $this->t('Test certificate'), + '#required' => TRUE, + '#default_value' => $queue, + '#description' => $this->createDescription([Settings::PROCESSING, Settings::QUEUE], + $queue + ? $this->t("Queue for digital post jobs. The queue must be run via Drupal's cron or via drush advancedqueue:queue:process @queue (in a cron job).", [ + '@queue' => $queue, + ':queue_url' => Url::fromRoute('view.advancedqueue_jobs.page_1', [ + 'arg_0' => $queue, + ])->toString(TRUE)->getGeneratedUrl(), + ]) + : $this->t("Queue for digital post jobs. The queue must be processed via Drupal's cron or drush advancedqueue:queue:process (in a cron job)."), + ), ]; return $form; @@ -212,59 +184,41 @@ public function buildForm(array $form, FormStateInterface $form_state) { * * @phpstan-param array $form */ - public function validateForm(array &$form, FormStateInterface $formState): void { - $triggeringElement = $formState->getTriggeringElement(); - if ('testCertificate' === ($triggeringElement['#name'] ?? NULL)) { - return; + public function submitForm(array &$form, FormStateInterface $form_state): void { + $config = $this->config(Settings::CONFIG_NAME); + foreach ([ + Settings::TEST_MODE, + Settings::SENDER, + Settings::CERTIFICATE, + Settings::PROCESSING, + ] as $key) { + $config->set($key, $form_state->getValue($key)); } + $config->save(); - $values = $formState->getValues(); - if (CertificateLocatorHelper::LOCATOR_TYPE_FILE_SYSTEM === $values['certificate']['locator_type']) { - $path = $values['certificate'][CertificateLocatorHelper::LOCATOR_TYPE_FILE_SYSTEM]['path'] ?? NULL; - if (!file_exists($path)) { - $formState->setErrorByName('certificate][file_system][path', $this->t('Invalid certificate path: %path', ['%path' => $path])); - } - } + parent::submitForm($form, $form_state); } /** - * {@inheritdoc} + * Create form field description with information on any runtime override. * - * @phpstan-param array $form + * @param string|array $key + * The key. + * @param \Drupal\Core\StringTranslation\TranslatableMarkup|null $description + * The actual field description. + * + * @return string + * The full description. */ - public function submitForm(array &$form, FormStateInterface $formState): void { - $triggeringElement = $formState->getTriggeringElement(); - if ('testCertificate' === ($triggeringElement['#name'] ?? NULL)) { - $this->testCertificate(); - return; - } - - try { - $settings['test_mode'] = (bool) $formState->getValue('test_mode'); - $settings['sender'] = $formState->getValue('sender'); - $settings['certificate'] = $formState->getValue('certificate'); - $settings['processing'] = $formState->getValue('processing'); - $this->settings->setSettings($settings); - $this->messenger()->addStatus($this->t('Settings saved')); - } - catch (OptionsResolverException $exception) { - $this->messenger()->addError($this->t('Settings not saved (@message)', ['@message' => $exception->getMessage()])); + private function createDescription(string|array $key, ?TranslatableMarkup $description = NULL): string { + if ($value = $this->settings->getOverride($key)) { + if (!empty($description)) { + $description .= '
'; + } + $description .= $this->t('Note: overridden on runtime with the value @value.', ['@value' => var_export($value['runtime'], TRUE)]); } - } - /** - * Test certificate. - */ - private function testCertificate(): void { - try { - $certificateLocator = $this->certificateLocatorHelper->getCertificateLocator(); - $certificateLocator->getCertificates(); - $this->messenger()->addStatus($this->t('Certificate succesfully tested')); - } - catch (\Throwable $throwable) { - $message = $this->t('Error testing certificate: %message', ['%message' => $throwable->getMessage()]); - $this->messenger()->addError($message); - } + return (string) $description; } } diff --git a/modules/os2forms_digital_post/src/Helper/CertificateLocatorHelper.php b/modules/os2forms_digital_post/src/Helper/CertificateLocatorHelper.php deleted file mode 100644 index 10e6ac57..00000000 --- a/modules/os2forms_digital_post/src/Helper/CertificateLocatorHelper.php +++ /dev/null @@ -1,79 +0,0 @@ -settings->getCertificate(); - - $locatorType = $certificateSettings['locator_type']; - $options = $certificateSettings[$locatorType]; - $options += [ - 'passphrase' => $certificateSettings['passphrase'] ?: '', - ]; - - if (self::LOCATOR_TYPE_AZURE_KEY_VAULT === $locatorType) { - $httpClient = new GuzzleAdapter(new Client()); - $requestFactory = new RequestFactory(); - - $vaultToken = new VaultToken($httpClient, $requestFactory); - - $token = $vaultToken->getToken( - $options['tenant_id'], - $options['application_id'], - $options['client_secret'], - ); - - $vault = new VaultSecret( - $httpClient, - $requestFactory, - $options['name'], - $token->getAccessToken() - ); - - return new AzureKeyVaultCertificateLocator( - $vault, - $options['secret'], - $options['version'], - $options['passphrase'], - ); - } - elseif (self::LOCATOR_TYPE_FILE_SYSTEM === $locatorType) { - $certificatepath = realpath($options['path']) ?: NULL; - if (NULL === $certificatepath) { - throw new CertificateLocatorException(sprintf('Invalid certificate path %s', $options['path'])); - } - return new FilesystemCertificateLocator($certificatepath, $options['passphrase']); - } - - throw new CertificateLocatorException(sprintf('Invalid certificate locator type: %s', $locatorType)); - } - -} diff --git a/modules/os2forms_digital_post/src/Helper/DigitalPostHelper.php b/modules/os2forms_digital_post/src/Helper/DigitalPostHelper.php index 8681cf35..fc2355af 100644 --- a/modules/os2forms_digital_post/src/Helper/DigitalPostHelper.php +++ b/modules/os2forms_digital_post/src/Helper/DigitalPostHelper.php @@ -11,6 +11,7 @@ use Drupal\os2web_datalookup\Plugin\DataLookupManager; use Drupal\os2web_datalookup\Plugin\os2web\DataLookup\DataLookupCompanyInterface; use Drupal\os2web_datalookup\Plugin\os2web\DataLookup\DataLookupCprInterface; +use Drupal\os2web_key\CertificateHelper; use Drupal\webform\WebformSubmissionInterface; use ItkDev\Serviceplatformen\Service\SF1601\SF1601; use ItkDev\Serviceplatformen\Service\SF1601\Serializer; @@ -29,7 +30,7 @@ final class DigitalPostHelper implements LoggerInterface { */ public function __construct( private readonly Settings $settings, - private readonly CertificateLocatorHelper $certificateLocatorHelper, + private readonly CertificateHelper $certificateHelper, private readonly DataLookupManager $dataLookupManager, private readonly MeMoHelper $meMoHelper, private readonly ForsendelseHelper $forsendelseHelper, @@ -62,7 +63,10 @@ public function sendDigitalPost(string $type, Message $message, ?ForsendelseI $f $options = [ 'test_mode' => (bool) $this->settings->getTestMode(), 'authority_cvr' => $senderSettings[Settings::SENDER_IDENTIFIER], - 'certificate_locator' => $this->certificateLocatorHelper->getCertificateLocator(), + 'certificate_locator' => new KeyCertificateLocator( + $this->settings->getCertificateKey(), + $this->certificateHelper + ), ]; $service = new SF1601($options); $transactionId = Serializer::createUuid(); diff --git a/modules/os2forms_digital_post/src/Helper/KeyCertificateLocator.php b/modules/os2forms_digital_post/src/Helper/KeyCertificateLocator.php new file mode 100644 index 00000000..832bc19f --- /dev/null +++ b/modules/os2forms_digital_post/src/Helper/KeyCertificateLocator.php @@ -0,0 +1,59 @@ + + */ + public function getCertificates(): array { + if (!isset($this->certificates)) { + $this->certificates = $this->certificateHelper->getCertificates($this->key); + } + + return $this->certificates; + } + + /** + * {@inheritdoc} + */ + public function getCertificate(): string { + return $this->key->getKeyValue(); + } + + /** + * {@inheritdoc} + */ + public function getAbsolutePathToCertificate(): string { + throw new CertificateLocatorException(__METHOD__ . ' should not be used.'); + } + +} diff --git a/modules/os2forms_digital_post/src/Helper/MemoryCertificateLocator.php b/modules/os2forms_digital_post/src/Helper/MemoryCertificateLocator.php new file mode 100644 index 00000000..69d791d2 --- /dev/null +++ b/modules/os2forms_digital_post/src/Helper/MemoryCertificateLocator.php @@ -0,0 +1,49 @@ + + */ + public function getCertificates(): array { + $certificates = []; + $this->passphrase = 'P5bISuw?s:u4'; + if (!openssl_pkcs12_read($this->certificate, $certificates, $this->passphrase)) { + throw new CertificateLocatorException(sprintf('Could not read certificate: %s', openssl_error_string() ?: '')); + } + + return $certificates; + } + + /** + * {@inheritdoc} + */ + public function getCertificate(): string { + return $this->certificate; + } + + /** + * {@inheritdoc} + */ + public function getAbsolutePathToCertificate(): string { + throw new CertificateLocatorException(__METHOD__ . ' should not be used.'); + } + +} diff --git a/modules/os2forms_digital_post/src/Helper/Settings.php b/modules/os2forms_digital_post/src/Helper/Settings.php index e64be738..c0d5384d 100644 --- a/modules/os2forms_digital_post/src/Helper/Settings.php +++ b/modules/os2forms_digital_post/src/Helper/Settings.php @@ -2,45 +2,61 @@ namespace Drupal\os2forms_digital_post\Helper; -use Drupal\Core\KeyValueStore\KeyValueFactoryInterface; -use Drupal\Core\KeyValueStore\KeyValueStoreInterface; -use Drupal\os2forms_digital_post\Exception\InvalidSettingException; -use Symfony\Component\OptionsResolver\OptionsResolver; +use Drupal\Core\Config\Config; +use Drupal\Core\Config\ConfigFactoryInterface; +use Drupal\Core\Config\ImmutableConfig; +use Drupal\key\KeyInterface; +use Drupal\key\KeyRepositoryInterface; /** * General settings for os2forms_digital_post. */ final class Settings { + public const CONFIG_NAME = 'os2forms_digital_post.settings'; + + public const TEST_MODE = 'test_mode'; + + public const SENDER = 'sender'; public const SENDER_IDENTIFIER_TYPE = 'sender_identifier_type'; public const SENDER_IDENTIFIER = 'sender_identifier'; public const FORSENDELSES_TYPE_IDENTIFIKATOR = 'forsendelses_type_identifikator'; + public const CERTIFICATE = 'certificate'; + public const KEY = 'key'; + + public const PROCESSING = 'processing'; + public const QUEUE = 'queue'; + /** - * The store. + * The runtime (immutable) config. * - * @var \Drupal\Core\KeyValueStore\KeyValueStoreInterface + * @var \Drupal\Core\Config\ImmutableConfig */ - private KeyValueStoreInterface $store; + private ImmutableConfig $runtimeConfig; /** - * The key prefix. + * The (mutable) config. * - * @var string + * @var \Drupal\Core\Config\Config */ - private $collection = 'os2forms_digital_post.'; + private Config $editableConfig; /** - * Constructor. + * The constructor. */ - public function __construct(KeyValueFactoryInterface $keyValueFactory) { - $this->store = $keyValueFactory->get($this->collection); + public function __construct( + ConfigFactoryInterface $configFactory, + private readonly KeyRepositoryInterface $keyRepository, + ) { + $this->runtimeConfig = $configFactory->get(self::CONFIG_NAME); + $this->editableConfig = $configFactory->getEditable(self::CONFIG_NAME); } /** * Get test mode. */ public function getTestMode(): bool { - return (bool) $this->get('test_mode', TRUE); + return (bool) $this->get(self::TEST_MODE, TRUE); } /** @@ -49,18 +65,25 @@ public function getTestMode(): bool { * @phpstan-return array */ public function getSender(): array { - $value = $this->get('sender'); + $value = $this->get(self::SENDER); + return is_array($value) ? $value : []; } + /** + * Get key. + */ + public function getKey(): ?string { + return $this->get([self::CERTIFICATE, self::KEY]); + } + /** * Get certificate. - * - * @phpstan-return array */ - public function getCertificate(): array { - $value = $this->get('certificate'); - return is_array($value) ? $value : []; + public function getCertificateKey(): ?KeyInterface { + return $this->keyRepository->getKey( + $this->getKey(), + ); } /** @@ -69,57 +92,82 @@ public function getCertificate(): array { * @phpstan-return array */ public function getProcessing(): array { - $value = $this->get('processing'); + $value = $this->get(self::PROCESSING); + return is_array($value) ? $value : []; } /** - * Get a setting value. + * Get editable value. * - * @param string $key + * @param string|array $key * The key. - * @param mixed|null $default - * The default value. * * @return mixed - * The setting value. + * The editable value. */ - private function get(string $key, $default = NULL) { - $resolver = $this->getSettingsResolver(); - if (!$resolver->isDefined($key)) { - throw new InvalidSettingException(sprintf('Setting %s is not defined', $key)); + public function getEditableValue(string|array $key): mixed { + if (is_array($key)) { + $key = implode('.', $key); } - - return $this->store->get($key, $default); + return $this->editableConfig->get($key); } /** - * Set settings. + * Get runtime value override if any. * - * @throws \Symfony\Component\OptionsResolver\Exception\ExceptionInterface + * @param string|array $key + * The key. * - * @phpstan-param array $settings + * @return array|null + * - 'runtime': the runtime value + * - 'editable': the editable (raw) value */ - public function setSettings(array $settings): self { - $settings = $this->getSettingsResolver()->resolve($settings); - foreach ($settings as $key => $value) { - $this->store->set($key, $value); + public function getOverride(string|array $key): ?array { + $runtimeValue = $this->getRuntimeValue($key); + $editableValue = $this->getEditableValue($key); + + // Note: We deliberately use "Equal" (==) rather than "Identical" (===) + // to compare values (cf. https://www.php.net/manual/en/language.operators.comparison.php#language.operators.comparison). + if ($runtimeValue == $editableValue) { + return NULL; } - return $this; + return [ + 'runtime' => $runtimeValue, + 'editable' => $editableValue, + ]; } /** - * Get settings resolver. + * Get a setting value. + * + * @param string|array $key + * The key. + * @param mixed $default + * The default value. + * + * @return mixed + * The setting value. */ - private function getSettingsResolver(): OptionsResolver { - return (new OptionsResolver()) - ->setDefaults([ - 'test_mode' => TRUE, - 'sender' => [], - 'certificate' => [], - 'processing' => [], - ]); + private function get(string|array $key, mixed $default = NULL) { + return $this->getRuntimeValue($key) ?? $default; + } + + /** + * Get runtime value with any overrides applied. + * + * @param string|array $key + * The key. + * + * @return mixed + * The runtime value. + */ + public function getRuntimeValue(string|array $key): mixed { + if (is_array($key)) { + $key = implode('.', $key); + } + return $this->runtimeConfig->get($key); } } diff --git a/package.json b/package.json deleted file mode 100644 index 52fcd34c..00000000 --- a/package.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "license": "UNLICENSED", - "private": true, - "devDependencies": { - "markdownlint-cli": "^0.32.2" - }, - "scripts": { - "coding-standards-check/markdownlint": "yarn markdownlint --ignore LICENSE.md --ignore vendor --ignore node_modules '*.md' 'modules/os2forms_digital_post/**/*.md'", - "coding-standards-check": "yarn coding-standards-check/markdownlint", - "coding-standards-apply/markdownlint": "yarn markdownlint --ignore LICENSE.md --ignore vendor --ignore node_modules '*.md' 'modules/os2forms_digital_post/**/*.md' --fix", - "coding-standards-apply": "yarn coding-standards-apply/markdownlint" - } -} diff --git a/scripts/code-analysis b/scripts/code-analysis index 9fec0f46..ace9e282 100755 --- a/scripts/code-analysis +++ b/scripts/code-analysis @@ -16,9 +16,21 @@ if [ ! -f "$drupal_dir/composer.json" ]; then composer --no-interaction create-project drupal/recommended-project:^10 "$drupal_dir" fi # Copy our code into the modules folder -mkdir -p "$drupal_dir/$module_path" + +# Clean up +rm -fr "${drupal_dir:?}/$module_path" + # https://stackoverflow.com/a/15373763 -rsync --archive --compress . --filter=':- .gitignore' --exclude "$drupal_dir" --exclude .git "$drupal_dir/$module_path" +# rsync --archive --compress . --filter=':- .gitignore' --exclude "$drupal_dir" --exclude .git "$drupal_dir/$module_path" + +# The rsync command in not available in itkdev/php8.1-fpm + +git config --global --add safe.directory /app +# Copy module files into module path +for f in $(git ls-files); do + mkdir -p "$drupal_dir/$module_path/$(dirname "$f")" + cp "$f" "$drupal_dir/$module_path/$f" +done drupal_composer config minimum-stability dev @@ -37,4 +49,4 @@ drupal_composer config extra.merge-plugin.include "$module_path/composer.json" drupal_composer require --dev symfony/phpunit-bridge # Run PHPStan -(cd "$drupal_dir" && vendor/bin/phpstan --configuration="$module_path/phpstan.neon") +(cd "$drupal_dir/$module_path" && ../../../../vendor/bin/phpstan) From 984bb8ea002e7b0f5561a58255cf2e0164561345 Mon Sep 17 00:00:00 2001 From: Mikkel Ricky Date: Tue, 7 May 2024 14:26:39 +0200 Subject: [PATCH 23/46] Cleaned up Markdown --- modules/os2forms_attachment/README.md | 14 ++++++++------ modules/os2forms_autocomplete/README.md | 9 +++++---- modules/os2forms_dawa/README.md | 7 ++++--- modules/os2forms_forloeb/CHANGELOG.md | 9 +++++++-- modules/os2forms_forloeb/README.md | 16 ++++++++-------- modules/os2forms_nemid/README.md | 5 ++--- modules/os2forms_permissions_by_term/README.md | 7 ++++++- modules/os2forms_sbsys/README.md | 1 + modules/os2forms_webform_maps/README.md | 3 +++ 9 files changed, 44 insertions(+), 27 deletions(-) diff --git a/modules/os2forms_attachment/README.md b/modules/os2forms_attachment/README.md index f732ad2f..5b1c7501 100644 --- a/modules/os2forms_attachment/README.md +++ b/modules/os2forms_attachment/README.md @@ -1,20 +1,22 @@ # OS2Forms Attachment Drupal module -# Module purpose +## Module purpose The aim of this module is to provide an OS2forms attachment element for adding PDF/HTML attachment. It also supports creation of reusable headers/footers components which are used when rendering the attachments. -# How does it work +## How does it work -To add custom headers/footer ```admin/structure/webform/config/os2forms_attachment_component``` +To add custom headers/footer `admin/structure/webform/config/os2forms_attachment_component` -To specify headers/footers that will override the default ones on a global level (**Third party settings** -> **Entity print** section): ```admin/structure/webform/config``` +To specify headers/footers that will override the default ones on a global level (**Third party settings** -> **Entity +print** section): `admin/structure/webform/config` -To specify headers/footers that will override the default ones on a form level (**Third party settings** -> **Entity print** section): ```/admin/structure/webform/manage/[webform]/settings``` +To specify headers/footers that will override the default ones on a form level (**Third party settings** -> **Entity +print** section): ```/admin/structure/webform/manage/[webform]/settings``` -# Overwriting templates +## Overwriting templates With some setups it might be necessary to overwrite templates in order to access stylesheets or images. diff --git a/modules/os2forms_autocomplete/README.md b/modules/os2forms_autocomplete/README.md index d5902385..2294d45e 100644 --- a/modules/os2forms_autocomplete/README.md +++ b/modules/os2forms_autocomplete/README.md @@ -1,15 +1,16 @@ # OS2Forms Autocomplete Drupal module -# Module purpose +## Module purpose -The aim of this module is to provide a genetic OS2Forms Autocomplete element which can return options from an external webservice. +The aim of this module is to provide a genetic OS2Forms Autocomplete element which can return options from an external +webservice. -# How does it work +## How does it work Module exposes OS2Forms Autocomplete component that are available in the webform build process. Build page: -``` +```url admin/structure/webform/manage/[webform] ``` diff --git a/modules/os2forms_dawa/README.md b/modules/os2forms_dawa/README.md index 53876ba3..ae242ade 100644 --- a/modules/os2forms_dawa/README.md +++ b/modules/os2forms_dawa/README.md @@ -1,10 +1,11 @@ # OS2Forms DAWA Drupal module -# Module purpose +## Module purpose -The aim of this module is to provide integration with Danish Addresses Web API (DAWA https://dawa.aws.dk) and provider address autocomplete fields. +The aim of this module is to provide integration with Danish Addresses Web API (DAWA ) and provider +address autocomplete fields. -# How does it work +## How does it work Module exposes couple of new Autocomplete components that are available in the webform build process. diff --git a/modules/os2forms_forloeb/CHANGELOG.md b/modules/os2forms_forloeb/CHANGELOG.md index 3338d105..6d569821 100644 --- a/modules/os2forms_forloeb/CHANGELOG.md +++ b/modules/os2forms_forloeb/CHANGELOG.md @@ -1,4 +1,5 @@ # OS2Forms Forløb Change Log + All notable changes to this project should be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) @@ -17,9 +18,11 @@ before starting to add changes. ## 2.5.2 - 27.03.2023 ### Updated + - Bumped drupal/ultimate_cron version fixing [Deprecated function: Implicit conversion from float-string](https://www.drupal.org/project/ultimate_cron/issues/3256142). ## 2.5.1 - 10.03.2023 + - Added github action for checking changelog changes when creating pull requests - Added os2forms/os2forms dependency - Changed composer patching configuration @@ -30,18 +33,20 @@ before starting to add changes. ## 2.5.0 - 11.10.2022 ### Added + - retry task controller action - Added support for inheriting values without creating a submission ## 2.4.0 ### Added + - Github CI action for checking Drupal Coding standards with PHP Code Sniffer - Fixed coding standards issues - ## Example of change log record -``` + +```markdown ## [x.x.x] Release name ### Added - Description on added functionality. diff --git a/modules/os2forms_forloeb/README.md b/modules/os2forms_forloeb/README.md index 7cf06186..11d1b07b 100644 --- a/modules/os2forms_forloeb/README.md +++ b/modules/os2forms_forloeb/README.md @@ -4,11 +4,13 @@ Adds a Maestro workflow engine and advanced workflow functionality to OS2forms. ## Installing OS2forms 2.1 med Forløb -This module requires the codebase from the [OS2forms core project](https://github.com/OS2Forms/os2forms8) installed per the documentation and by selecting the os2forms_forloeb_profile at installation. After succesful installation you should have the OS2forms med Forløb Module available for install via gui. +This module requires the codebase from the [OS2forms core project](https://github.com/OS2Forms/os2forms8) installed per +the documentation and by selecting the os2forms_forloeb_profile at installation. After succesful installation you should +have the OS2forms med Forløb Module available for install via gui. You can also install the module by using Drush: -``` +```shell ./vendor/bin/drush pm:enable os2forms_forloeb ``` @@ -32,20 +34,18 @@ Settings for OS2Forms forløb are defined on `/admin/config/system/os2forms_forl #### Known anonymous roles -In order to make the notifications work, Maestro workflow tasks must be assigned -to a *known anonymous role* and these roles are defined under *Known anonymous -roles*. +In order to make the notifications work, Maestro workflow tasks must be assigned to a *known anonymous role* and these +roles are defined under *Known anonymous roles*. #### Processing -A notification is not sent to a user immediately, but added to a queue which -must be processed asynchronously. Specify the queue handling notification jobs. +A notification is not sent to a user immediately, but added to a queue which must be processed asynchronously. Specify +the queue handling notification jobs. #### Templates Define templates for emails and digital post (PDF). - To reference assets, e.g. stylesheet or images, in your templates, you can use the `base_url` Twig variable to get the base URL: diff --git a/modules/os2forms_nemid/README.md b/modules/os2forms_nemid/README.md index 98ec5532..ec7c7932 100644 --- a/modules/os2forms_nemid/README.md +++ b/modules/os2forms_nemid/README.md @@ -1,10 +1,10 @@ # OS2Forms Nemid Drupal module -# Module purpose +## Module purpose The aim of this module is to provide custom NemId field and integration with OS2Web Nemlogin module. -# How does it work +## How does it work Module exposes dozen of new NemID components that are available in the webform build process. @@ -17,4 +17,3 @@ Besides this module adds a special settings to the Third Party Webform settings: - Hide form if under address protection Settings: admin/structure/webform/manage/[webform]/settings - diff --git a/modules/os2forms_permissions_by_term/README.md b/modules/os2forms_permissions_by_term/README.md index 2c572931..33ac9367 100644 --- a/modules/os2forms_permissions_by_term/README.md +++ b/modules/os2forms_permissions_by_term/README.md @@ -1,10 +1,13 @@ # OS2Forms permission by term module + This module implements permission by term access restrictions on several lists and entity displays related to webform and maestro. ## Setup configuration + Add to your settings.php or local.settings.php -``` + +```php $config['permissions_by_term.settings'] = [ 'permissions_mode' => FALSE, 'require_all_terms_granted' => FALSE, @@ -12,6 +15,7 @@ $config['permissions_by_term.settings'] = [ 'target_bundles' => ['user_affiliation'] ] ``` + Alternative change your site configuration on admin/permissions-by-term/settings to match the above. !note This is the recommended configuration of the permissions_by_term module. Using different values for @@ -19,6 +23,7 @@ Alternative change your site configuration on admin/permissions-by-term/settings be thoroughly tested. ## Usage + - The user affiliation taxonomy is added to webform config form and Maestro workflow forms. - The Permissions by Term module adds a form element to the user form. - When a user visits an entity of the above mentioned this module checks for match between the entity and the users diff --git a/modules/os2forms_sbsys/README.md b/modules/os2forms_sbsys/README.md index b554eebc..8e1129f0 100644 --- a/modules/os2forms_sbsys/README.md +++ b/modules/os2forms_sbsys/README.md @@ -1,6 +1,7 @@ # OS2forms SBSYS integration Drupal module ## Module purpose + The aim of this module is to provide integration with SBSYS ESDH provider. ## How does it work diff --git a/modules/os2forms_webform_maps/README.md b/modules/os2forms_webform_maps/README.md index e6d08748..c36b901e 100644 --- a/modules/os2forms_webform_maps/README.md +++ b/modules/os2forms_webform_maps/README.md @@ -1,13 +1,16 @@ # OS2Forms Webform Maps module for Drupal 9 ## Module description + Provides integration with Leaflet maps and provides map element for webform. ## How does it work + The module provides a new element type for webform. The element type is called "OS2Forms Kort". The element type is based on the Leaflet library. The element type provides a map with a marker that can be moved around on the map. The element type also provides ways of changing layers on the map. The data can be exported to PDF. ## Installation + The module can be installed using the standard Drupal installation procedure. From 75d8ad226611f1f470b88bb07152f71bcb5a5eab Mon Sep 17 00:00:00 2001 From: Mikkel Ricky Date: Tue, 7 May 2024 23:30:35 +0200 Subject: [PATCH 24/46] Cleaned up --- .../os2forms_digital_post.install | 2 +- .../os2forms_digital_post.services.yml | 2 +- .../Commands/DigitalPostTestCommands.php | 4 +- .../src/Form/SettingsForm.php | 6 ++- .../src/Helper/DigitalPostHelper.php | 6 +-- .../src/Helper/KeyCertificateLocator.php | 10 ++-- .../src/Helper/MemoryCertificateLocator.php | 49 ------------------- 7 files changed, 17 insertions(+), 62 deletions(-) delete mode 100644 modules/os2forms_digital_post/src/Helper/MemoryCertificateLocator.php diff --git a/modules/os2forms_digital_post/os2forms_digital_post.install b/modules/os2forms_digital_post/os2forms_digital_post.install index 80b756ac..f8140579 100644 --- a/modules/os2forms_digital_post/os2forms_digital_post.install +++ b/modules/os2forms_digital_post/os2forms_digital_post.install @@ -21,7 +21,7 @@ function os2forms_digital_post_schema() { /** * Implements hook_update_N(). */ -function os2forms_digital_post_update_9001() { +function os2forms_digital_post_update_9001(): void { \Drupal::service('module_installer')->install([ 'os2web_key', ], TRUE); diff --git a/modules/os2forms_digital_post/os2forms_digital_post.services.yml b/modules/os2forms_digital_post/os2forms_digital_post.services.yml index 66bc3132..9b096fad 100644 --- a/modules/os2forms_digital_post/os2forms_digital_post.services.yml +++ b/modules/os2forms_digital_post/os2forms_digital_post.services.yml @@ -32,7 +32,7 @@ services: Drupal\os2forms_digital_post\Helper\DigitalPostHelper: arguments: - "@Drupal\\os2forms_digital_post\\Helper\\Settings" - - "@Drupal\\os2web_key\\CertificateHelper" + - "@Drupal\\os2web_key\\KeyHelper" - "@plugin.manager.os2web_datalookup" - "@Drupal\\os2forms_digital_post\\Helper\\MeMoHelper" - "@Drupal\\os2forms_digital_post\\Helper\\ForsendelseHelper" diff --git a/modules/os2forms_digital_post/src/Drush/Commands/DigitalPostTestCommands.php b/modules/os2forms_digital_post/src/Drush/Commands/DigitalPostTestCommands.php index 248452a3..8d7d17c0 100644 --- a/modules/os2forms_digital_post/src/Drush/Commands/DigitalPostTestCommands.php +++ b/modules/os2forms_digital_post/src/Drush/Commands/DigitalPostTestCommands.php @@ -145,7 +145,9 @@ private function dumpDigitalPostSettings(SymfonyStyle $io): void { Yaml::encode([ 'testMode' => $this->digitalPostSettings->getTestMode(), 'sender' => $this->digitalPostSettings->getSender(), - 'certificate' => $this->digitalPostSettings->getCertificate(), + 'certificate' => [ + 'key' => $this->digitalPostSettings->getKey(), + ], 'processing' => $this->digitalPostSettings->getProcessing(), ]), '', diff --git a/modules/os2forms_digital_post/src/Form/SettingsForm.php b/modules/os2forms_digital_post/src/Form/SettingsForm.php index 6b2e062c..b91e2ed5 100644 --- a/modules/os2forms_digital_post/src/Form/SettingsForm.php +++ b/modules/os2forms_digital_post/src/Form/SettingsForm.php @@ -55,7 +55,7 @@ public static function create(ContainerInterface $container) { /** * {@inheritdoc} * - * @phpstan-return array + * @phpstan-return string[] */ protected function getEditableConfigNames() { return [ @@ -202,13 +202,15 @@ public function submitForm(array &$form, FormStateInterface $form_state): void { /** * Create form field description with information on any runtime override. * - * @param string|array $key + * @param string|array $key * The key. * @param \Drupal\Core\StringTranslation\TranslatableMarkup|null $description * The actual field description. * * @return string * The full description. + * + * @phpstan-param string|string[] $key */ private function createDescription(string|array $key, ?TranslatableMarkup $description = NULL): string { if ($value = $this->settings->getOverride($key)) { diff --git a/modules/os2forms_digital_post/src/Helper/DigitalPostHelper.php b/modules/os2forms_digital_post/src/Helper/DigitalPostHelper.php index fc2355af..80825dff 100644 --- a/modules/os2forms_digital_post/src/Helper/DigitalPostHelper.php +++ b/modules/os2forms_digital_post/src/Helper/DigitalPostHelper.php @@ -11,7 +11,7 @@ use Drupal\os2web_datalookup\Plugin\DataLookupManager; use Drupal\os2web_datalookup\Plugin\os2web\DataLookup\DataLookupCompanyInterface; use Drupal\os2web_datalookup\Plugin\os2web\DataLookup\DataLookupCprInterface; -use Drupal\os2web_key\CertificateHelper; +use Drupal\os2web_key\KeyHelper; use Drupal\webform\WebformSubmissionInterface; use ItkDev\Serviceplatformen\Service\SF1601\SF1601; use ItkDev\Serviceplatformen\Service\SF1601\Serializer; @@ -30,7 +30,7 @@ final class DigitalPostHelper implements LoggerInterface { */ public function __construct( private readonly Settings $settings, - private readonly CertificateHelper $certificateHelper, + private readonly KeyHelper $keyHelper, private readonly DataLookupManager $dataLookupManager, private readonly MeMoHelper $meMoHelper, private readonly ForsendelseHelper $forsendelseHelper, @@ -65,7 +65,7 @@ public function sendDigitalPost(string $type, Message $message, ?ForsendelseI $f 'authority_cvr' => $senderSettings[Settings::SENDER_IDENTIFIER], 'certificate_locator' => new KeyCertificateLocator( $this->settings->getCertificateKey(), - $this->certificateHelper + $this->keyHelper ), ]; $service = new SF1601($options); diff --git a/modules/os2forms_digital_post/src/Helper/KeyCertificateLocator.php b/modules/os2forms_digital_post/src/Helper/KeyCertificateLocator.php index 832bc19f..8d8f0a41 100644 --- a/modules/os2forms_digital_post/src/Helper/KeyCertificateLocator.php +++ b/modules/os2forms_digital_post/src/Helper/KeyCertificateLocator.php @@ -3,7 +3,7 @@ namespace Drupal\os2forms_digital_post\Helper; use Drupal\key\KeyInterface; -use Drupal\os2web_key\CertificateHelper; +use Drupal\os2web_key\KeyHelper; use ItkDev\Serviceplatformen\Certificate\AbstractCertificateLocator; use ItkDev\Serviceplatformen\Certificate\Exception\CertificateLocatorException; @@ -15,16 +15,16 @@ class KeyCertificateLocator extends AbstractCertificateLocator { /** * The parsed certificates. * - * @var array + * @var array */ - private readonly array $certificates; + private array $certificates; /** * Constructor. */ public function __construct( private readonly KeyInterface $key, - private readonly CertificateHelper $certificateHelper, + private readonly KeyHelper $keyHelper, ) { parent::__construct(); } @@ -36,7 +36,7 @@ public function __construct( */ public function getCertificates(): array { if (!isset($this->certificates)) { - $this->certificates = $this->certificateHelper->getCertificates($this->key); + $this->certificates = $this->keyHelper->getCertificates($this->key); } return $this->certificates; diff --git a/modules/os2forms_digital_post/src/Helper/MemoryCertificateLocator.php b/modules/os2forms_digital_post/src/Helper/MemoryCertificateLocator.php deleted file mode 100644 index 69d791d2..00000000 --- a/modules/os2forms_digital_post/src/Helper/MemoryCertificateLocator.php +++ /dev/null @@ -1,49 +0,0 @@ - - */ - public function getCertificates(): array { - $certificates = []; - $this->passphrase = 'P5bISuw?s:u4'; - if (!openssl_pkcs12_read($this->certificate, $certificates, $this->passphrase)) { - throw new CertificateLocatorException(sprintf('Could not read certificate: %s', openssl_error_string() ?: '')); - } - - return $certificates; - } - - /** - * {@inheritdoc} - */ - public function getCertificate(): string { - return $this->certificate; - } - - /** - * {@inheritdoc} - */ - public function getAbsolutePathToCertificate(): string { - throw new CertificateLocatorException(__METHOD__ . ' should not be used.'); - } - -} From d315e882869861940dad43233bca5e0ce7ee4694 Mon Sep 17 00:00:00 2001 From: Mikkel Ricky Date: Mon, 13 May 2024 09:11:55 +0200 Subject: [PATCH 25/46] Required os2web_key 1.0 --- composer.json | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/composer.json b/composer.json index f997c480..2be78402 100644 --- a/composer.json +++ b/composer.json @@ -59,7 +59,7 @@ "itk-dev/serviceplatformen": "^1.5", "os2web/os2web_audit": "^0.1.6", "os2web/os2web_datalookup": "^2.0", - "os2web/os2web_key": "dev-os2web_key", + "os2web/os2web_key": "^1.0", "os2web/os2web_nemlogin": "^1.0", "os2web/os2web_simplesaml": "dev-master", "php-http/guzzle7-adapter": "^1.0", @@ -81,10 +81,6 @@ "wsdltophp/packagegenerator": "^4.0" }, "repositories": { - "os2web/os2web_key": { - "type": "vcs", - "url": "https://github.com/itk-dev/os2web_key" - }, "drupal": { "type": "composer", "url": "https://packages.drupal.org/8" From 1b0c85da60fa52426eb51a627e46764d7e015d35 Mon Sep 17 00:00:00 2001 From: Mikkel Ricky Date: Mon, 13 May 2024 11:27:36 +0200 Subject: [PATCH 26/46] Updated os2web_datalookup --- composer.json | 6 +++++- modules/os2forms_digital_post/README.md | 3 ++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index 2be78402..32301d1b 100644 --- a/composer.json +++ b/composer.json @@ -58,7 +58,7 @@ "itk-dev/beskedfordeler-drupal": "^1.0", "itk-dev/serviceplatformen": "^1.5", "os2web/os2web_audit": "^0.1.6", - "os2web/os2web_datalookup": "^2.0", + "os2web/os2web_datalookup": "dev-feature/os2web_key as 1.12.0", "os2web/os2web_key": "^1.0", "os2web/os2web_nemlogin": "^1.0", "os2web/os2web_simplesaml": "dev-master", @@ -81,6 +81,10 @@ "wsdltophp/packagegenerator": "^4.0" }, "repositories": { + "os2web/os2web_datalookup": { + "type": "vcs", + "url": "https://github.com/itk-dev/os2web_datalookup" + }, "drupal": { "type": "composer", "url": "https://packages.drupal.org/8" diff --git a/modules/os2forms_digital_post/README.md b/modules/os2forms_digital_post/README.md index c36e9f48..999d87c7 100644 --- a/modules/os2forms_digital_post/README.md +++ b/modules/os2forms_digital_post/README.md @@ -33,7 +33,8 @@ digital post. ### Key -We use [os2web_key](https://github.com/OS2web/os2web_key) to provide the certificate for sending digital post. +We use [os2web_key](https://github.com/OS2web/os2web_key) to provide the certificate for sending digital post, and the +key must be of type "[Certificate](https://github.com/os2web/os2web_key?tab=readme-ov-file#certificate)". ### Queue From ba5dd00f577e4cf0196fe1194b2ac968774d0c1c Mon Sep 17 00:00:00 2001 From: Mikkel Ricky Date: Tue, 17 Dec 2024 23:26:21 +0100 Subject: [PATCH 27/46] Cleaned up composer.json --- composer.json | 48 ++++++++++++++++++------------------------------ 1 file changed, 18 insertions(+), 30 deletions(-) diff --git a/composer.json b/composer.json index 32301d1b..01244961 100644 --- a/composer.json +++ b/composer.json @@ -57,8 +57,9 @@ "http-interop/http-factory-guzzle": "^1.0.0", "itk-dev/beskedfordeler-drupal": "^1.0", "itk-dev/serviceplatformen": "^1.5", + "mglaman/composer-drupal-lenient": "^1.0", "os2web/os2web_audit": "^0.1.6", - "os2web/os2web_datalookup": "dev-feature/os2web_key as 1.12.0", + "os2web/os2web_datalookup": "dev-feature/os2web_key as 2.0.0", "os2web/os2web_key": "^1.0", "os2web/os2web_nemlogin": "^1.0", "os2web/os2web_simplesaml": "dev-master", @@ -67,8 +68,7 @@ "symfony/options-resolver": "^5.4 || ^6.0", "webmozart/path-util": "^2.3", "wsdltophp/packagebase": "^5.0", - "zaporylie/composer-drupal-optimizations": "^1.2", - "mglaman/composer-drupal-lenient": "^1.0" + "zaporylie/composer-drupal-optimizations": "^1.2" }, "require-dev": { "dealerdirect/phpcodesniffer-composer-installer": "^0.7.1", @@ -101,6 +101,7 @@ "cweagans/composer-patches": true, "dealerdirect/phpcodesniffer-composer-installer": true, "ergebnis/composer-normalize": true, + "mglaman/composer-drupal-lenient": true, "phpstan/extension-installer": true, "simplesamlphp/composer-module-installer": true, "vaimo/composer-patches": true, @@ -110,8 +111,19 @@ }, "extra": { "composer-exit-on-patch-failure": false, + "drupal-lenient": { + "allowed-list": [ + "drupal/coc_forms_auto_export", + "drupal/webform_node_element" + ] + }, "enable-patching": true, "patches": { + "drupal/coc_forms_auto_export": { + "3240592 - Problem with phpseclib requirement in 2.x (https://www.drupal.org/project/coc_forms_auto_export/issues/3240592)": "https://www.drupal.org/files/issues/2021-10-04/requirement-namespace-3240592-1.patch", + "3286562 - Automated Drupal 10 compatibility fixes": "https://www.drupal.org/files/issues/2022-06-15/coc_forms_auto_export.2.0.x-dev.rector.patch", + "3259009 - PHP Warnings/Notices on Download Page": "https://git.drupalcode.org/project/coc_forms_auto_export/-/merge_requests/1.diff" + }, "drupal/entity_print": { "2733781 - Add Export to Word Support": "https://www.drupal.org/files/issues/2019-11-22/2733781-47.patch" }, @@ -119,26 +131,14 @@ "Unlock possibility of using Entity print module export to Word": "https://www.drupal.org/files/issues/2020-02-29/3096552-6.patch", "Webform computed element post save alter": "https://www.drupal.org/files/issues/2024-06-25/webform_computed_post_save_field_alter.patch", "Add custom hook (hook_webform_post_load_data) for audit logging": "https://gist.githubusercontent.com/cableman/d26898fc8f65ee0a31001bf391583b59/raw/6189dc4c2ceaabb19d25cc4b98b0b3028a6b0e1e/gistfile1.txt" - - }, - "drupal/coc_forms_auto_export": { - "3240592 - Problem with phpseclib requirement in 2.x (https://www.drupal.org/project/coc_forms_auto_export/issues/3240592)": "https://www.drupal.org/files/issues/2021-10-04/requirement-namespace-3240592-1.patch", - "3286562 - Automated Drupal 10 compatibility fixes" : "https://www.drupal.org/files/issues/2022-06-15/coc_forms_auto_export.2.0.x-dev.rector.patch", - "3259009 - PHP Warnings/Notices on Download Page" : "https://git.drupalcode.org/project/coc_forms_auto_export/-/merge_requests/1.diff" - }, - "drupal/webform_node_element": { - "3290637 - Automated Drupal 10 compatibility fixes": "https://www.drupal.org/files/issues/2023-05-12/webform_node_element_d10-3290637-11.patch" }, "drupal/webform_encrypt": { "Ensure data is base64 encoded (https://www.drupal.org/project/webform_encrypt/issues/3399414)": "https://git.drupalcode.org/project/webform_encrypt/-/merge_requests/4.patch", "PHP Warning if unserialize fails (https://www.drupal.org/project/webform_encrypt/issues/3292305)": "https://www.drupal.org/files/issues/2022-06-23/unserialize-php-notice.patch" + }, + "drupal/webform_node_element": { + "3290637 - Automated Drupal 10 compatibility fixes": "https://www.drupal.org/files/issues/2023-05-12/webform_node_element_d10-3290637-11.patch" } - }, - "drupal-lenient": { - "allowed-list": [ - "drupal/coc_forms_auto_export", - "drupal/webform_node_element" - ] } }, "scripts": { @@ -160,17 +160,5 @@ "coding-standards-check/phpcs": [ "phpcs --standard=phpcs.xml.dist" ] - }, - "config": { - "sort-packages": true, - "allow-plugins": { - "cweagans/composer-patches": true, - "dealerdirect/phpcodesniffer-composer-installer": true, - "phpstan/extension-installer": true, - "simplesamlphp/composer-module-installer": true, - "vaimo/composer-patches": true, - "zaporylie/composer-drupal-optimizations": true, - "mglaman/composer-drupal-lenient": true - } } } From a32eaae0c2426a7f1e46d26a0bb928dbd9fb93f2 Mon Sep 17 00:00:00 2001 From: Mikkel Ricky Date: Tue, 17 Dec 2024 23:40:20 +0100 Subject: [PATCH 28/46] Cleaned up --- README.md | 1 + modules/os2forms_fasit/docs/BENYTTELSE.md | 10 +++++----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 90245a21..44eb8e47 100644 --- a/README.md +++ b/README.md @@ -130,6 +130,7 @@ docker run --rm --volume ${PWD}:/app --workdir /app itkdev/php8.1-fpm composer c ### Markdown ```sh +docker pull peterdavehello/markdownlint docker run --rm --volume $PWD:/md peterdavehello/markdownlint markdownlint --ignore vendor --ignore LICENSE.md '**/*.md' --fix docker run --rm --volume $PWD:/md peterdavehello/markdownlint markdownlint --ignore vendor --ignore LICENSE.md '**/*.md' ``` diff --git a/modules/os2forms_fasit/docs/BENYTTELSE.md b/modules/os2forms_fasit/docs/BENYTTELSE.md index 63cc361d..cb8c958a 100644 --- a/modules/os2forms_fasit/docs/BENYTTELSE.md +++ b/modules/os2forms_fasit/docs/BENYTTELSE.md @@ -10,7 +10,7 @@ aftale hvilke certifikater der anvendes. Disse certifikater skal være OCES-3, f.eks. FOCES-3, og skal bruges i pem- eller cer-format. Dernæst oplyses det anvendte certifikats thumbprint eller public-key til Fasit, -som derefter aktiverer snitfladen. Se evt. +som derefter aktiverer snitfladen. Se evt. [README#certificate](../README.md#certificate) for hvordan et certifikats thumbprint kan findes gennem kommandolinjen. @@ -22,7 +22,7 @@ Her skal følgende sættes op: * Fasit API base url * Basis url’en til Fasit. Denne specificeres af Fasit. - * Eksempel: https://webservices.fasit.dk/ + * Eksempel: * Fasit API tenant * Fasit tenant. Denne specificeres af Fasit. * Eksempel: aarhus @@ -30,14 +30,14 @@ Her skal følgende sættes op: * Hvilken version af af API’et der skal bruges. Her er mulighederne ’v1’ eller ’v2’. Der bør altid bruges ’v2’. * Eksempel: v2 * Certificate - * Her kan angives detaljer til et azure key vault hvori certifikatet ligges (Azure key vault) eller en sti direkte til certifikatet (Filsystem) + * Her kan angives detaljer til et azure key vault hvori certifikatet ligges (Azure key vault) eller en sti direkte til + certifikatet (Filsystem) * Passphrase * Passphrase til certifikatet, hvis sådan et eksisterer. - Se evt. Fasit Scultz dokumentationen for flere detaljer på opbygningen af endpoint url’er. -Det er desuden muligt at teste om os2forms kan få fat i certifikatet på samme konfigurations-side. +Det er desuden muligt at teste om os2forms kan få fat i certifikatet på samme konfigurations-side. ## Handler From cd3e855363ba56d908697b082fee4a8867a126d4 Mon Sep 17 00:00:00 2001 From: Mikkel Ricky Date: Fri, 20 Dec 2024 15:27:57 +0100 Subject: [PATCH 29/46] Updated --- .github/workflows/pr.yml | 6 ++-- .../DataLookup/DatafordelerDataLookup.php | 28 +++++++++++-------- 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index c78e9623..6eb23e77 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -23,7 +23,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - php-versions: [ '8.1' ] + php-versions: [ '8.3' ] dependency-version: [ prefer-lowest, prefer-stable ] steps: - uses: actions/checkout@master @@ -59,7 +59,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - php-versions: [ '8.1' ] + php-versions: [ '8.3' ] steps: - uses: actions/checkout@master - name: Setup PHP, with composer and extensions @@ -92,7 +92,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - php-versions: [ '8.1' ] + php-versions: [ '8.3' ] steps: - uses: actions/checkout@master - name: Setup PHP, with composer and extensions diff --git a/modules/os2forms_dawa/src/Plugin/os2web/DataLookup/DatafordelerDataLookup.php b/modules/os2forms_dawa/src/Plugin/os2web/DataLookup/DatafordelerDataLookup.php index ba699519..9d3b1aaa 100644 --- a/modules/os2forms_dawa/src/Plugin/os2web/DataLookup/DatafordelerDataLookup.php +++ b/modules/os2forms_dawa/src/Plugin/os2web/DataLookup/DatafordelerDataLookup.php @@ -3,8 +3,11 @@ namespace Drupal\os2forms_dawa\Plugin\os2web\DataLookup; use Drupal\Component\Utility\NestedArray; +use Drupal\Core\File\FileSystem; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Plugin\ContainerFactoryPluginInterface; +use Drupal\key\KeyRepository; +use Drupal\key\KeyRepositoryInterface; use Drupal\os2forms_dawa\Entity\DatafordelerMatrikula; use Drupal\os2web_audit\Service\Logger; use Drupal\os2web_datalookup\Plugin\os2web\DataLookup\DataLookupBase; @@ -21,13 +24,6 @@ */ class DatafordelerDataLookup extends DataLookupBase implements DatafordelerDataLookupInterface, ContainerFactoryPluginInterface { - /** - * The HTTP client to fetch the feed data with. - * - * @var \GuzzleHttp\ClientInterface - */ - protected $httpClient; - /** * {@inheritdoc} */ @@ -35,23 +31,33 @@ public function __construct( array $configuration, $plugin_id, $plugin_definition, - ClientInterface $httpClient, + protected ClientInterface $httpClient, Logger $auditLogger, + KeyRepositoryInterface $keyRepository, + FileSystem $fileSystem, ) { - $this->httpClient = $httpClient; - parent::__construct($configuration, $plugin_id, $plugin_definition, $auditLogger); + parent::__construct($configuration, $plugin_id, $plugin_definition, $auditLogger, $keyRepository, $fileSystem); } /** * {@inheritdoc} */ public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { + /** @var Logger $auditLogger */ + $auditLogger = $container->get('os2web_audit.logger'); + /** @var \Drupal\key\KeyRepositoryInterface $keyRepository */ + $keyRepository = $container->get('key.repository'); + /** @var \Drupal\Core\File\FileSystem $fileSystem */ + $fileSystem = $container->get('file_system'); + return new static( $configuration, $plugin_id, $plugin_definition, $container->get('http_client'), - $container->get('os2web_audit.logger'), + $auditLogger, + $keyRepository, + $fileSystem, ); } From 7749375abec39a6bfd49f4ebcfdb49bea3197727 Mon Sep 17 00:00:00 2001 From: jekuaitk Date: Wed, 22 Jan 2025 12:23:32 +0100 Subject: [PATCH 30/46] Rebase --- CHANGELOG.md | 9 ++++++++- composer.json | 7 ++++--- .../os2web/DataLookup/DatafordelerDataLookup.php | 1 + .../src/Helper/CertificateLocatorHelper.php | 0 modules/os2forms_fbs_handler/src/Client/FBS.php | 3 +++ .../os2forms_fbs_handler/src/Client/Model/Guardian.php | 2 ++ .../os2forms_fbs_handler/src/Client/Model/Patron.php | 6 ++++++ .../src/Plugin/AdvancedQueue/JobType/FbsCreateUser.php | 4 ++++ .../src/Plugin/WebformHandler/FbsWebformHandler.php | 10 ++++++++++ phpstan.neon | 1 + 10 files changed, 39 insertions(+), 4 deletions(-) delete mode 100644 modules/os2forms_digital_post/src/Helper/CertificateLocatorHelper.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 9ba06141..e849be68 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,12 @@ before starting to add changes. Use example [placed in the end of the page](#exa - Added support for `os2web_key` in Fasit handler. - Switched from saving settings in key value store to config, i.e the module needs to be reconfigured. +- Removed modules ldap_auth, logging_alerts, maillog + +## [3.21.2] 2025-01-07 + +- Adds missing `http-message-util` requirement and use statement. +- Runs code-analysis on `os2forms_fbs_handler` module. ## [3.21.1] 2025-01-06 @@ -334,7 +340,8 @@ before starting to add changes. Use example [placed in the end of the page](#exa - Security in case of vulnerabilities. ``` -[Unreleased]: https://github.com/OS2Forms/os2forms/compare/3.21.1...HEAD +[Unreleased]: https://github.com/OS2Forms/os2forms/compare/3.21.2...HEAD +[3.21.2]: https://github.com/OS2Forms/os2forms/compare/3.21.1...3.21.2 [3.21.1]: https://github.com/OS2Forms/os2forms/compare/3.21.0...3.21.1 [3.21.0]: https://github.com/OS2Forms/os2forms/compare/3.20.1...3.21.0 [3.20.1]: https://github.com/OS2Forms/os2forms/compare/3.20.0...3.20.1 diff --git a/composer.json b/composer.json index 2b83bd51..01244961 100644 --- a/composer.json +++ b/composer.json @@ -11,6 +11,7 @@ "dompdf/dompdf": "^2.0", "drupal/admin_toolbar": "^3.0", "drupal/advancedqueue": "^1.0", + "drupal/cache_control_override": "^1.1|^2.0", "drupal/clientside_validation": "^4.0", "drupal/coc_forms_auto_export": "^2.0@alpha", "drupal/config_entity_revisions": "dev-2.0.x", @@ -19,14 +20,13 @@ "drupal/entity_print": "^2.1", "drupal/eu_cookie_compliance": "^1.8", "drupal/events_logging": "^2.0@beta", + "drupal/gin": "^3.0-rc", "drupal/honeypot": "^2.0", "drupal/image_widget_crop": "^2.3", "drupal/ldap": "^4.2", - "drupal/ldap_auth": "^1.17", "drupal/leaflet": "^10.0", "drupal/leaflet_layers": "^1.1", "drupal/libraries": "^4.0", - "drupal/logging_alerts": "^2.0", "drupal/maestro": "^3.1", "drupal/mailsystem": "^4.1", "drupal/masquerade": "^2.0@RC", @@ -53,6 +53,7 @@ "drupal/webform_validation": "^2.0", "drupal/webform_views": "^5.0@alpha", "drupal/workflow_participants": "^3.0@RC", + "fig/http-message-util": "^1.1", "http-interop/http-factory-guzzle": "^1.0.0", "itk-dev/beskedfordeler-drupal": "^1.0", "itk-dev/serviceplatformen": "^1.5", @@ -61,6 +62,7 @@ "os2web/os2web_datalookup": "dev-feature/os2web_key as 2.0.0", "os2web/os2web_key": "^1.0", "os2web/os2web_nemlogin": "^1.0", + "os2web/os2web_simplesaml": "dev-master", "php-http/guzzle7-adapter": "^1.0", "phpoffice/phpword": "^0.18.2", "symfony/options-resolver": "^5.4 || ^6.0", @@ -71,7 +73,6 @@ "require-dev": { "dealerdirect/phpcodesniffer-composer-installer": "^0.7.1", "drupal/coder": "^8.3", - "drupal/maillog": "^1.0", "ergebnis/composer-normalize": "^2.42", "mglaman/phpstan-drupal": "^1.1", "phpstan/extension-installer": "^1.3", diff --git a/modules/os2forms_dawa/src/Plugin/os2web/DataLookup/DatafordelerDataLookup.php b/modules/os2forms_dawa/src/Plugin/os2web/DataLookup/DatafordelerDataLookup.php index 0e50ffaf..f0e5af69 100644 --- a/modules/os2forms_dawa/src/Plugin/os2web/DataLookup/DatafordelerDataLookup.php +++ b/modules/os2forms_dawa/src/Plugin/os2web/DataLookup/DatafordelerDataLookup.php @@ -6,6 +6,7 @@ use Drupal\Core\File\FileSystem; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Plugin\ContainerFactoryPluginInterface; +use Drupal\key\KeyRepository; use Drupal\key\KeyRepositoryInterface; use Drupal\os2forms_dawa\Entity\DatafordelerMatrikula; use Drupal\os2web_audit\Service\Logger; diff --git a/modules/os2forms_digital_post/src/Helper/CertificateLocatorHelper.php b/modules/os2forms_digital_post/src/Helper/CertificateLocatorHelper.php deleted file mode 100644 index e69de29b..00000000 diff --git a/modules/os2forms_fbs_handler/src/Client/FBS.php b/modules/os2forms_fbs_handler/src/Client/FBS.php index 44b8f6a7..66c38b4d 100644 --- a/modules/os2forms_fbs_handler/src/Client/FBS.php +++ b/modules/os2forms_fbs_handler/src/Client/FBS.php @@ -4,6 +4,7 @@ use Drupal\os2forms_fbs_handler\Client\Model\Guardian; use Drupal\os2forms_fbs_handler\Client\Model\Patron; +use Fig\Http\Message\RequestMethodInterface; use GuzzleHttp\Client; use Symfony\Component\HttpFoundation\Request; @@ -242,6 +243,8 @@ public function createGuardian(Patron $patron, Guardian $guardian): int { * * @throws \GuzzleHttp\Exception\GuzzleException * @throws \JsonException + * + * @phpstan-param array|string $data */ private function request(string $uri, array|string $data, string $method = Request::METHOD_POST): mixed { $url = rtrim($this->endpoint, '/\\'); diff --git a/modules/os2forms_fbs_handler/src/Client/Model/Guardian.php b/modules/os2forms_fbs_handler/src/Client/Model/Guardian.php index 371d3bba..b72a648f 100644 --- a/modules/os2forms_fbs_handler/src/Client/Model/Guardian.php +++ b/modules/os2forms_fbs_handler/src/Client/Model/Guardian.php @@ -22,6 +22,8 @@ public function __construct( * * @return array * Array with field required by FBS calls. + * + * @phpstan-return array */ public function toArray(): array { return [ diff --git a/modules/os2forms_fbs_handler/src/Client/Model/Patron.php b/modules/os2forms_fbs_handler/src/Client/Model/Patron.php index e5e7d562..db3e1d0f 100644 --- a/modules/os2forms_fbs_handler/src/Client/Model/Patron.php +++ b/modules/os2forms_fbs_handler/src/Client/Model/Patron.php @@ -9,6 +9,10 @@ final class Patron { /** * Default constructor. + * + * @phpstan-param array|null $notificationProtocols + * @phpstan-param array|null $onHold + * @phpstan-param array|null $emailAddresses */ public function __construct( public readonly ?string $patronId = NULL, @@ -35,6 +39,8 @@ public function __construct( * * @return array * Array with field required by FBS calls. + * + * @phpstan-return array */ public function toArray(): array { return [ diff --git a/modules/os2forms_fbs_handler/src/Plugin/AdvancedQueue/JobType/FbsCreateUser.php b/modules/os2forms_fbs_handler/src/Plugin/AdvancedQueue/JobType/FbsCreateUser.php index 179d0a1a..d5de9afa 100644 --- a/modules/os2forms_fbs_handler/src/Plugin/AdvancedQueue/JobType/FbsCreateUser.php +++ b/modules/os2forms_fbs_handler/src/Plugin/AdvancedQueue/JobType/FbsCreateUser.php @@ -35,6 +35,8 @@ final class FbsCreateUser extends JobTypeBase implements ContainerFactoryPluginI /** * {@inheritdoc} + * + * @phpstan-param array $configuration */ public function __construct( array $configuration, @@ -50,6 +52,8 @@ public function __construct( /** * {@inheritdoc} + * + * @phpstan-param array $configuration */ public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { return new static( diff --git a/modules/os2forms_fbs_handler/src/Plugin/WebformHandler/FbsWebformHandler.php b/modules/os2forms_fbs_handler/src/Plugin/WebformHandler/FbsWebformHandler.php index 25625145..1c2abad2 100644 --- a/modules/os2forms_fbs_handler/src/Plugin/WebformHandler/FbsWebformHandler.php +++ b/modules/os2forms_fbs_handler/src/Plugin/WebformHandler/FbsWebformHandler.php @@ -45,6 +45,8 @@ final class FbsWebformHandler extends WebformHandlerBase { /** * Constructs an FbsWebformHandler object. + * + * @phpstan-param array $configuration */ public function __construct( array $configuration, @@ -70,6 +72,8 @@ public function __construct( /** * {@inheritdoc} + * + * @phpstan-param array $configuration */ public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { return new static( @@ -87,6 +91,10 @@ public static function create(ContainerInterface $container, array $configuratio /** * {@inheritdoc} + * + * @phpstan-param array $form + * + * @phpstan-return array */ public function buildConfigurationForm(array $form, FormStateInterface $form_state): array { if (is_null($this->getQueue())) { @@ -143,6 +151,8 @@ public function buildConfigurationForm(array $form, FormStateInterface $form_sta /** * {@inheritdoc} + * + * @phpstan-param array $form */ public function submitConfigurationForm(array &$form, FormStateInterface $form_state): void { parent::submitConfigurationForm($form, $form_state); diff --git a/phpstan.neon b/phpstan.neon index 8ece9b1d..dd1fcc1d 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -2,6 +2,7 @@ parameters: level: 6 paths: - modules/os2forms_digital_post/ + - modules/os2forms_fbs_handler/ excludePaths: # @see https://github.com/mglaman/drupal-check/issues/261#issuecomment-1030141772/ - vendor From 4c601629fdb53bf8d08eba8cd0bcfdda9f1444e9 Mon Sep 17 00:00:00 2001 From: jekuaitk Date: Wed, 22 Jan 2025 12:28:02 +0100 Subject: [PATCH 31/46] Applied coding standards --- composer.json | 2 +- .../src/Plugin/os2web/DataLookup/DatafordelerDataLookup.php | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/composer.json b/composer.json index 01244961..aee475b2 100644 --- a/composer.json +++ b/composer.json @@ -11,7 +11,7 @@ "dompdf/dompdf": "^2.0", "drupal/admin_toolbar": "^3.0", "drupal/advancedqueue": "^1.0", - "drupal/cache_control_override": "^1.1|^2.0", + "drupal/cache_control_override": "^1.1 || ^2.0", "drupal/clientside_validation": "^4.0", "drupal/coc_forms_auto_export": "^2.0@alpha", "drupal/config_entity_revisions": "dev-2.0.x", diff --git a/modules/os2forms_dawa/src/Plugin/os2web/DataLookup/DatafordelerDataLookup.php b/modules/os2forms_dawa/src/Plugin/os2web/DataLookup/DatafordelerDataLookup.php index f0e5af69..0e50ffaf 100644 --- a/modules/os2forms_dawa/src/Plugin/os2web/DataLookup/DatafordelerDataLookup.php +++ b/modules/os2forms_dawa/src/Plugin/os2web/DataLookup/DatafordelerDataLookup.php @@ -6,7 +6,6 @@ use Drupal\Core\File\FileSystem; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Plugin\ContainerFactoryPluginInterface; -use Drupal\key\KeyRepository; use Drupal\key\KeyRepositoryInterface; use Drupal\os2forms_dawa\Entity\DatafordelerMatrikula; use Drupal\os2web_audit\Service\Logger; From 1964c27043c31b6f6b83dcb4ba7fdd96ff03dd2b Mon Sep 17 00:00:00 2001 From: jekuaitk Date: Wed, 22 Jan 2025 14:58:56 +0100 Subject: [PATCH 32/46] Updated Digital post command --- .../os2forms_digital_post/drush.services.yml | 10 ---------- .../Commands/DigitalPostTestCommands.php | 17 +++++++++++++++-- 2 files changed, 15 insertions(+), 12 deletions(-) delete mode 100644 modules/os2forms_digital_post/drush.services.yml rename modules/os2forms_digital_post/src/{ => Drush}/Commands/DigitalPostTestCommands.php (91%) diff --git a/modules/os2forms_digital_post/drush.services.yml b/modules/os2forms_digital_post/drush.services.yml deleted file mode 100644 index 7339bc2a..00000000 --- a/modules/os2forms_digital_post/drush.services.yml +++ /dev/null @@ -1,10 +0,0 @@ -services: - os2forms_digital_post.commands: - class: \Drupal\os2forms_digital_post\Commands\DigitalPostTestCommands - arguments: - - '@Drupal\os2forms_digital_post\Helper\DigitalPostHelper' - - '@token' - - '@plugin.manager.entity_print.print_engine' - - '@Drupal\os2forms_digital_post\Helper\Settings' - tags: - - { name: drush.command } diff --git a/modules/os2forms_digital_post/src/Commands/DigitalPostTestCommands.php b/modules/os2forms_digital_post/src/Drush/Commands/DigitalPostTestCommands.php similarity index 91% rename from modules/os2forms_digital_post/src/Commands/DigitalPostTestCommands.php rename to modules/os2forms_digital_post/src/Drush/Commands/DigitalPostTestCommands.php index 5e9bdbbf..26d65faf 100644 --- a/modules/os2forms_digital_post/src/Commands/DigitalPostTestCommands.php +++ b/modules/os2forms_digital_post/src/Drush/Commands/DigitalPostTestCommands.php @@ -1,6 +1,6 @@ get(DigitalPostHelper::class), + $container->get('token'), + $container->get('plugin.manager.entity_print.print_engine'), + $container->get(Settings::class), + ); + } + /** * Send digital post. * From c58ec55c6139ae9187bbbe1bf30bee4a92549b12 Mon Sep 17 00:00:00 2001 From: jekuaitk Date: Wed, 22 Jan 2025 15:55:09 +0100 Subject: [PATCH 33/46] Coding standards --- .../src/Drush/Commands/DigitalPostTestCommands.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/os2forms_digital_post/src/Drush/Commands/DigitalPostTestCommands.php b/modules/os2forms_digital_post/src/Drush/Commands/DigitalPostTestCommands.php index 26d65faf..759c8e25 100644 --- a/modules/os2forms_digital_post/src/Drush/Commands/DigitalPostTestCommands.php +++ b/modules/os2forms_digital_post/src/Drush/Commands/DigitalPostTestCommands.php @@ -34,7 +34,7 @@ public function __construct( /** * {@inheritdoc} */ - public static function create(ContainerInterface $container) { + public static function create(ContainerInterface $container): self { return new static( $container->get(DigitalPostHelper::class), $container->get('token'), From 0404c5ccc1b9058006baa39321dfd42d1cb97f71 Mon Sep 17 00:00:00 2001 From: jekuaitk Date: Wed, 22 Jan 2025 22:54:56 +0100 Subject: [PATCH 34/46] Used Autowire trait --- .../Drush/Commands/DigitalPostTestCommands.php | 17 ++++------------- .../src/Drush/Commands/FasitTestCommand.php | 12 ++---------- 2 files changed, 6 insertions(+), 23 deletions(-) diff --git a/modules/os2forms_digital_post/src/Drush/Commands/DigitalPostTestCommands.php b/modules/os2forms_digital_post/src/Drush/Commands/DigitalPostTestCommands.php index 759c8e25..6b23d874 100644 --- a/modules/os2forms_digital_post/src/Drush/Commands/DigitalPostTestCommands.php +++ b/modules/os2forms_digital_post/src/Drush/Commands/DigitalPostTestCommands.php @@ -3,6 +3,7 @@ namespace Drupal\os2forms_digital_post\Drush\Commands; use Drupal\Component\Serialization\Yaml; +use Drupal\Core\DependencyInjection\AutowireTrait; use Drupal\Core\Utility\Token; use Drupal\entity_print\Plugin\EntityPrintPluginManagerInterface; use Drupal\os2forms_digital_post\Helper\DigitalPostHelper; @@ -12,13 +13,14 @@ use ItkDev\Serviceplatformen\Service\SF1601\SF1601; use Symfony\Component\Console\Exception\InvalidArgumentException; use Symfony\Component\Console\Style\SymfonyStyle; -use Symfony\Component\DependencyInjection\ContainerInterface; +use Symfony\Component\DependencyInjection\Attribute\Autowire; use Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface; /** * Test commands for digital post. */ final class DigitalPostTestCommands extends DrushCommands { + use AutowireTrait; /** * Constructor. @@ -26,23 +28,12 @@ final class DigitalPostTestCommands extends DrushCommands { public function __construct( private readonly DigitalPostHelper $digitalPostHelper, private readonly Token $token, + #[Autowire(service: 'plugin.manager.entity_print.print_engine')] private readonly EntityPrintPluginManagerInterface $entityPrintPluginManager, private readonly Settings $digitalPostSettings, ) { } - /** - * {@inheritdoc} - */ - public static function create(ContainerInterface $container): self { - return new static( - $container->get(DigitalPostHelper::class), - $container->get('token'), - $container->get('plugin.manager.entity_print.print_engine'), - $container->get(Settings::class), - ); - } - /** * Send digital post. * diff --git a/modules/os2forms_fasit/src/Drush/Commands/FasitTestCommand.php b/modules/os2forms_fasit/src/Drush/Commands/FasitTestCommand.php index 586adc04..9d1fb281 100644 --- a/modules/os2forms_fasit/src/Drush/Commands/FasitTestCommand.php +++ b/modules/os2forms_fasit/src/Drush/Commands/FasitTestCommand.php @@ -2,14 +2,15 @@ namespace Drupal\os2forms_fasit\Drush\Commands; +use Drupal\Core\DependencyInjection\AutowireTrait; use Drupal\os2forms_fasit\Helper\FasitHelper; use Drush\Commands\DrushCommands; -use Symfony\Component\DependencyInjection\ContainerInterface; /** * A Drush commandfile. */ final class FasitTestCommand extends DrushCommands { + use AutowireTrait; /** * Constructs a FasitTestCommand object. @@ -20,15 +21,6 @@ public function __construct( parent::__construct(); } - /** - * {@inheritdoc} - */ - public static function create(ContainerInterface $container) { - return new static( - $container->get(FasitHelper::class), - ); - } - /** * Test API access. * From d8c7c2e7881800f785db347fda7e352d1d5002a3 Mon Sep 17 00:00:00 2001 From: jekuaitk Date: Thu, 23 Jan 2025 14:14:08 +0100 Subject: [PATCH 35/46] Updated digital post module to allow key and old configuration methods --- CHANGELOG.md | 2 + .../os2forms_digital_post.services.yml | 1 + .../src/Form/SettingsForm.php | 187 +++++++++++++++++- .../src/Helper/CertificateLocatorHelper.php | 88 +++++++++ .../src/Helper/DigitalPostHelper.php | 18 +- .../src/Helper/Settings.php | 10 + 6 files changed, 293 insertions(+), 13 deletions(-) create mode 100644 modules/os2forms_digital_post/src/Helper/CertificateLocatorHelper.php diff --git a/CHANGELOG.md b/CHANGELOG.md index e849be68..d6fbf37f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,8 @@ before starting to add changes. Use example [placed in the end of the page](#exa - [#101](https://github.com/OS2Forms/os2forms/pull/101) - Added support for `os2web_key` in Digital post + - Switched from saving settings in key value store to config, i.e + the module needs to be reconfigured. - Added support for `os2web_key` in Fasit handler. - Switched from saving settings in key value store to config, i.e the module needs to be reconfigured. diff --git a/modules/os2forms_digital_post/os2forms_digital_post.services.yml b/modules/os2forms_digital_post/os2forms_digital_post.services.yml index 9b096fad..993a7208 100644 --- a/modules/os2forms_digital_post/os2forms_digital_post.services.yml +++ b/modules/os2forms_digital_post/os2forms_digital_post.services.yml @@ -37,6 +37,7 @@ services: - "@Drupal\\os2forms_digital_post\\Helper\\MeMoHelper" - "@Drupal\\os2forms_digital_post\\Helper\\ForsendelseHelper" - "@Drupal\\os2forms_digital_post\\Helper\\BeskedfordelerHelper" + - "@Drupal\\os2forms_digital_post\\Helper\\CertificateLocatorHelper" - "@logger.channel.os2forms_digital_post" - "@logger.channel.os2forms_digital_post_submission" - "@os2web_audit.logger" diff --git a/modules/os2forms_digital_post/src/Form/SettingsForm.php b/modules/os2forms_digital_post/src/Form/SettingsForm.php index b91e2ed5..5bfb04f6 100644 --- a/modules/os2forms_digital_post/src/Form/SettingsForm.php +++ b/modules/os2forms_digital_post/src/Form/SettingsForm.php @@ -11,6 +11,7 @@ use Drupal\Core\StringTranslation\StringTranslationTrait; use Drupal\Core\StringTranslation\TranslatableMarkup; use Drupal\Core\Url; +use Drupal\os2forms_digital_post\Helper\CertificateLocatorHelper; use Drupal\os2forms_digital_post\Helper\Settings; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -34,6 +35,7 @@ public function __construct( ConfigFactoryInterface $config_factory, EntityTypeManagerInterface $entityTypeManager, private readonly Settings $settings, + private readonly CertificateLocatorHelper $certificateLocatorHelper, ) { parent::__construct($config_factory); $this->queueStorage = $entityTypeManager->getStorage('advancedqueue_queue'); @@ -49,6 +51,7 @@ public static function create(ContainerInterface $container) { $container->get('config.factory'), $container->get('entity_type.manager'), $container->get(Settings::class), + $container->get(CertificateLocatorHelper::class), ); } @@ -134,17 +137,127 @@ public function buildForm(array $form, FormStateInterface $form_state): array { '#type' => 'fieldset', '#title' => $this->t('Certificate'), '#tree' => TRUE, + ]; + + $form[Settings::CERTIFICATE][Settings::CERTIFICATE_PROVIDER] = [ + '#type' => 'select', + '#title' => $this->t('Provider'), + '#options' => [ + Settings::PROVIDER_TYPE_FORM => $this->t('Form'), + Settings::PROVIDER_TYPE_KEY => $this->t('Key'), + ], + '#default_value' => $this->settings->getEditableValue([Settings::CERTIFICATE, Settings::CERTIFICATE_PROVIDER]) ?? Settings::PROVIDER_TYPE_FORM, + '#description' => $this->t('Specifies which provider to use'), + ]; + + $form[Settings::CERTIFICATE][CertificateLocatorHelper::LOCATOR_TYPE] = [ + '#type' => 'select', + '#title' => $this->t('Certificate locator type'), + '#options' => [ + CertificateLocatorHelper::LOCATOR_TYPE_AZURE_KEY_VAULT => $this->t('Azure key vault'), + CertificateLocatorHelper::LOCATOR_TYPE_FILE_SYSTEM => $this->t('File system'), + ], + '#default_value' => $this->settings->getEditableValue([ + Settings::CERTIFICATE, + CertificateLocatorHelper::LOCATOR_TYPE, + ]) ?? NULL, + '#states' => [ + 'visible' => [':input[name="certificate[certificate_provider]"]' => ['value' => Settings::PROVIDER_TYPE_FORM]], + ], + '#description' => $this->t('Specifies which locator to use'), + ]; - Settings::KEY => [ - '#type' => 'key_select', - '#key_filters' => [ - 'type' => 'os2web_key_certificate', + $form[Settings::CERTIFICATE][CertificateLocatorHelper::LOCATOR_TYPE_AZURE_KEY_VAULT] = [ + '#type' => 'fieldset', + '#title' => $this->t('Azure key vault'), + '#states' => [ + 'visible' => [ + ':input[name="certificate[certificate_provider]"]' => ['value' => Settings::PROVIDER_TYPE_FORM], + ':input[name="certificate[locator_type]"]' => ['value' => CertificateLocatorHelper::LOCATOR_TYPE_AZURE_KEY_VAULT], + ], + ], + ]; + + $settings = [ + CertificateLocatorHelper::LOCATOR_AZURE_KEY_VAULT_TENANT_ID => ['title' => $this->t('Tenant id')], + CertificateLocatorHelper::LOCATOR_AZURE_KEY_VAULT_APPLICATION_ID => ['title' => $this->t('Application id')], + CertificateLocatorHelper::LOCATOR_AZURE_KEY_VAULT_CLIENT_SECRET => ['title' => $this->t('Client secret')], + CertificateLocatorHelper::LOCATOR_AZURE_KEY_VAULT_NAME => ['title' => $this->t('Name')], + CertificateLocatorHelper::LOCATOR_AZURE_KEY_VAULT_SECRET => ['title' => $this->t('Secret')], + CertificateLocatorHelper::LOCATOR_AZURE_KEY_VAULT_VERSION => ['title' => $this->t('Version')], + ]; + + foreach ($settings as $key => $info) { + $form[Settings::CERTIFICATE][CertificateLocatorHelper::LOCATOR_TYPE_AZURE_KEY_VAULT][$key] = [ + '#type' => 'textfield', + '#title' => $info['title'], + '#default_value' => $this->settings->getEditableValue([ + Settings::CERTIFICATE, + CertificateLocatorHelper::LOCATOR_TYPE_AZURE_KEY_VAULT, + $key, + ]) ?? NULL, + '#states' => [ + 'required' => [ + ':input[name="certificate[certificate_provider]"]' => ['value' => Settings::PROVIDER_TYPE_FORM], + ':input[name="certificate[locator_type]"]' => ['value' => CertificateLocatorHelper::LOCATOR_TYPE_AZURE_KEY_VAULT], + ], + ], + ]; + } + + $form[Settings::CERTIFICATE][CertificateLocatorHelper::LOCATOR_TYPE_FILE_SYSTEM] = [ + '#type' => 'fieldset', + '#title' => $this->t('File system'), + '#states' => [ + 'visible' => [ + ':input[name="certificate[certificate_provider]"]' => ['value' => Settings::PROVIDER_TYPE_FORM], + ':input[name="certificate[locator_type]"]' => ['value' => CertificateLocatorHelper::LOCATOR_TYPE_FILE_SYSTEM], + ], + ], + + CertificateLocatorHelper::LOCATOR_FILE_SYSTEM_PATH => [ + '#type' => 'textfield', + '#title' => $this->t('Path'), + '#default_value' => $this->settings->getEditableValue([ + Settings::CERTIFICATE, + CertificateLocatorHelper::LOCATOR_TYPE_FILE_SYSTEM, + CertificateLocatorHelper::LOCATOR_FILE_SYSTEM_PATH, + ]) ?? NULL, + '#states' => [ + 'required' => [ + ':input[name="certificate[certificate_provider]"]' => ['value' => Settings::PROVIDER_TYPE_FORM], + ':input[name="certificate[locator_type]"]' => ['value' => CertificateLocatorHelper::LOCATOR_TYPE_FILE_SYSTEM], + ], ], - '#key_description' => FALSE, - '#title' => $this->t('Key'), - '#default_value' => $this->settings->getEditableValue([Settings::CERTIFICATE, Settings::KEY]), - '#required' => TRUE, - '#description' => $this->createDescription([Settings::CERTIFICATE, Settings::KEY]), + ], + ]; + + $form[Settings::CERTIFICATE][CertificateLocatorHelper::LOCATOR_PASSPHRASE] = [ + '#type' => 'textfield', + '#title' => $this->t('Passphrase'), + '#default_value' => $this->settings->getEditableValue([ + Settings::CERTIFICATE, + CertificateLocatorHelper::LOCATOR_PASSPHRASE, + ]) ?? '', + '#states' => [ + 'visible' => [ + ':input[name="certificate[certificate_provider]"]' => ['value' => Settings::PROVIDER_TYPE_FORM], + ], + ], + ]; + + $form[Settings::CERTIFICATE][Settings::PROVIDER_TYPE_KEY] = [ + '#type' => 'key_select', + '#key_filters' => [ + 'type' => 'os2web_key_certificate', + ], + '#key_description' => FALSE, + '#title' => $this->t('Key'), + '#default_value' => $this->settings->getEditableValue([Settings::CERTIFICATE, Settings::PROVIDER_TYPE_KEY]), + '#required' => TRUE, + '#description' => $this->createDescription([Settings::CERTIFICATE, Settings::PROVIDER_TYPE_KEY]), + '#states' => [ + 'visible' => [':input[name="certificate[certificate_provider]"]' => ['value' => Settings::PROVIDER_TYPE_KEY]], ], ]; @@ -176,15 +289,55 @@ public function buildForm(array $form, FormStateInterface $form_state): array { ), ]; + $form['actions']['testCertificate'] = [ + '#type' => 'submit', + '#name' => 'testCertificate', + '#value' => $this->t('Test certificate'), + '#states' => [ + 'visible' => [':input[name="certificate[certificate_provider]"]' => ['value' => Settings::PROVIDER_TYPE_FORM]], + ], + ]; + return $form; } + /** + * {@inheritdoc} + * + * @phpstan-param array $form + */ + public function validateForm(array &$form, FormStateInterface $form_state): void { + $triggeringElement = $form_state->getTriggeringElement(); + if ('testCertificate' === ($triggeringElement['#name'] ?? NULL)) { + return; + } + + $values = $form_state->getValues(); + + if (Settings::PROVIDER_TYPE_FORM === $values[Settings::CERTIFICATE][Settings::CERTIFICATE_PROVIDER]) { + if (CertificateLocatorHelper::LOCATOR_TYPE_FILE_SYSTEM === $values[Settings::CERTIFICATE][CertificateLocatorHelper::LOCATOR_TYPE]) { + $path = $values[Settings::CERTIFICATE][CertificateLocatorHelper::LOCATOR_TYPE_FILE_SYSTEM][CertificateLocatorHelper::LOCATOR_FILE_SYSTEM_PATH] ?? NULL; + if (!file_exists($path)) { + $form_state->setErrorByName('certificate][file_system][path', $this->t('Invalid certificate path: %path', ['%path' => $path])); + } + } + } + + parent::validateForm($form, $form_state); + } + /** * {@inheritdoc} * * @phpstan-param array $form */ public function submitForm(array &$form, FormStateInterface $form_state): void { + $triggeringElement = $form_state->getTriggeringElement(); + if ('testCertificate' === ($triggeringElement['#name'] ?? NULL)) { + $this->testCertificate(); + return; + } + $config = $this->config(Settings::CONFIG_NAME); foreach ([ Settings::TEST_MODE, @@ -223,4 +376,20 @@ private function createDescription(string|array $key, ?TranslatableMarkup $descr return (string) $description; } + /** + * Test certificate. + */ + private function testCertificate(): void { + try { + + $certificateLocator = $this->certificateLocatorHelper->getCertificateLocator(); + $certificateLocator->getCertificates(); + $this->messenger()->addStatus($this->t('Certificate succesfully tested')); + } + catch (\Throwable $throwable) { + $message = $this->t('Error testing certificate: %message', ['%message' => $throwable->getMessage()]); + $this->messenger()->addError($message); + } + } + } diff --git a/modules/os2forms_digital_post/src/Helper/CertificateLocatorHelper.php b/modules/os2forms_digital_post/src/Helper/CertificateLocatorHelper.php new file mode 100644 index 00000000..14710b93 --- /dev/null +++ b/modules/os2forms_digital_post/src/Helper/CertificateLocatorHelper.php @@ -0,0 +1,88 @@ +settings->getEditableValue(Settings::CERTIFICATE); + + $locatorType = $certificateSettings['locator_type']; + $options = $certificateSettings[$locatorType]; + $options += [ + 'passphrase' => $certificateSettings['passphrase'] ?: '', + ]; + + if (self::LOCATOR_TYPE_AZURE_KEY_VAULT === $locatorType) { + $httpClient = new GuzzleAdapter(new Client()); + $requestFactory = new RequestFactory(); + + $vaultToken = new VaultToken($httpClient, $requestFactory); + + $token = $vaultToken->getToken( + $options['tenant_id'], + $options['application_id'], + $options['client_secret'], + ); + + $vault = new VaultSecret( + $httpClient, + $requestFactory, + $options['name'], + $token->getAccessToken() + ); + + return new AzureKeyVaultCertificateLocator( + $vault, + $options['secret'], + $options['version'], + $options['passphrase'], + ); + } + elseif (self::LOCATOR_TYPE_FILE_SYSTEM === $locatorType) { + $certificatepath = realpath($options['path']) ?: NULL; + if (NULL === $certificatepath) { + throw new CertificateLocatorException(sprintf('Invalid certificate path %s', $options['path'])); + } + return new FilesystemCertificateLocator($certificatepath, $options['passphrase']); + } + + throw new CertificateLocatorException(sprintf('Invalid certificate locator type: %s', $locatorType)); + } + +} diff --git a/modules/os2forms_digital_post/src/Helper/DigitalPostHelper.php b/modules/os2forms_digital_post/src/Helper/DigitalPostHelper.php index 80825dff..d2f2af65 100644 --- a/modules/os2forms_digital_post/src/Helper/DigitalPostHelper.php +++ b/modules/os2forms_digital_post/src/Helper/DigitalPostHelper.php @@ -35,6 +35,7 @@ public function __construct( private readonly MeMoHelper $meMoHelper, private readonly ForsendelseHelper $forsendelseHelper, private readonly BeskedfordelerHelper $beskedfordelerHelper, + private readonly CertificateLocatorHelper $certificateLocatorHelper, private readonly LoggerChannelInterface $logger, private readonly LoggerChannelInterface $submissionLogger, private readonly Logger $auditLogger, @@ -60,14 +61,23 @@ public function __construct( */ public function sendDigitalPost(string $type, Message $message, ?ForsendelseI $forsendelse, ?WebformSubmissionInterface $submission = NULL): array { $senderSettings = $this->settings->getSender(); + + if (Settings::PROVIDER_TYPE_FORM === $this->settings->getCertificateProvider()) { + $certificateLocator = $this->certificateLocatorHelper->getCertificateLocator(); + } + else { + $certificateLocator = new KeyCertificateLocator( + $this->settings->getCertificateKey(), + $this->keyHelper + ); + } + $options = [ 'test_mode' => (bool) $this->settings->getTestMode(), 'authority_cvr' => $senderSettings[Settings::SENDER_IDENTIFIER], - 'certificate_locator' => new KeyCertificateLocator( - $this->settings->getCertificateKey(), - $this->keyHelper - ), + 'certificate_locator' => $certificateLocator, ]; + $service = new SF1601($options); $transactionId = Serializer::createUuid(); diff --git a/modules/os2forms_digital_post/src/Helper/Settings.php b/modules/os2forms_digital_post/src/Helper/Settings.php index c0d5384d..176749b2 100644 --- a/modules/os2forms_digital_post/src/Helper/Settings.php +++ b/modules/os2forms_digital_post/src/Helper/Settings.php @@ -23,6 +23,9 @@ final class Settings { public const CERTIFICATE = 'certificate'; public const KEY = 'key'; + public const CERTIFICATE_PROVIDER = 'certificate_provider'; + public const PROVIDER_TYPE_FORM = 'form'; + public const PROVIDER_TYPE_KEY = 'key'; public const PROCESSING = 'processing'; public const QUEUE = 'queue'; @@ -70,6 +73,13 @@ public function getSender(): array { return is_array($value) ? $value : []; } + /** + * Get certificate provider. + */ + public function getCertificateProvider(): ?string { + return $this->get([self::CERTIFICATE, self::CERTIFICATE_PROVIDER]); + } + /** * Get key. */ From b0b898dc3fdcaa35a7e4207acab8bd6668f4134c Mon Sep 17 00:00:00 2001 From: jekuaitk Date: Thu, 23 Jan 2025 14:52:27 +0100 Subject: [PATCH 36/46] Service cleanup using autowire --- .../os2forms_digital_post.services.yml | 54 +++++-------------- .../BeskedfordelerEventSubscriber.php | 2 + .../src/Form/SettingsForm.php | 38 ------------- .../src/Helper/BeskedfordelerHelper.php | 2 + .../src/Helper/DigitalPostHelper.php | 5 ++ .../src/Helper/Settings.php | 2 + .../src/Helper/WebformHelperSF1601.php | 4 ++ 7 files changed, 27 insertions(+), 80 deletions(-) diff --git a/modules/os2forms_digital_post/os2forms_digital_post.services.yml b/modules/os2forms_digital_post/os2forms_digital_post.services.yml index 993a7208..ed03ea36 100644 --- a/modules/os2forms_digital_post/os2forms_digital_post.services.yml +++ b/modules/os2forms_digital_post/os2forms_digital_post.services.yml @@ -8,65 +8,35 @@ services: arguments: [ 'webform_submission' ] Drupal\os2forms_digital_post\Helper\Settings: - arguments: - - "@config.factory" - - "@key.repository" + autowire: true Drupal\os2forms_digital_post\Helper\CertificateLocatorHelper: - arguments: - - "@Drupal\\os2forms_digital_post\\Helper\\Settings" - - "@key.repository" + autowire: true Drupal\os2forms_digital_post\Helper\MeMoHelper: + autowire: true arguments: - - "@Drupal\\os2forms_digital_post\\Helper\\Settings" - - "@plugin.manager.element_info" - - "@webform.token_manager" + $elementInfoManager: "@plugin.manager.element_info" + $webformTokenManager: "@webform.token_manager" Drupal\os2forms_digital_post\Helper\ForsendelseHelper: + autowire: true arguments: - - "@Drupal\\os2forms_digital_post\\Helper\\Settings" - - "@plugin.manager.element_info" - - "@webform.token_manager" + $elementInfoManager: "@plugin.manager.element_info" + $webformTokenManager: "@webform.token_manager" Drupal\os2forms_digital_post\Helper\DigitalPostHelper: - arguments: - - "@Drupal\\os2forms_digital_post\\Helper\\Settings" - - "@Drupal\\os2web_key\\KeyHelper" - - "@plugin.manager.os2web_datalookup" - - "@Drupal\\os2forms_digital_post\\Helper\\MeMoHelper" - - "@Drupal\\os2forms_digital_post\\Helper\\ForsendelseHelper" - - "@Drupal\\os2forms_digital_post\\Helper\\BeskedfordelerHelper" - - "@Drupal\\os2forms_digital_post\\Helper\\CertificateLocatorHelper" - - "@logger.channel.os2forms_digital_post" - - "@logger.channel.os2forms_digital_post_submission" - - "@os2web_audit.logger" + autowire: true Drupal\os2forms_digital_post\Helper\WebformHelperSF1601: - arguments: - - "@Drupal\\os2forms_digital_post\\Helper\\Settings" - - "@entity_type.manager" - - "@plugin.manager.os2web_datalookup" - - "@Drupal\\os2forms_digital_post\\Helper\\MeMoHelper" - - "@Drupal\\os2forms_digital_post\\Helper\\ForsendelseHelper" - - "@Drupal\\os2forms_digital_post\\Helper\\BeskedfordelerHelper" - - "@logger.channel.os2forms_digital_post" - - "@logger.channel.os2forms_digital_post_submission" - - "@Drupal\\os2forms_digital_post\\Helper\\DigitalPostHelper" + autowire: true Drupal\os2forms_digital_post\Helper\SF1461Helper: Drupal\os2forms_digital_post\EventSubscriber\BeskedfordelerEventSubscriber: - arguments: - - '@Drupal\os2forms_digital_post\Helper\BeskedfordelerHelper' - - '@Drupal\beskedfordeler\Helper\MessageHelper' - - '@Drupal\os2forms_digital_post\Helper\WebformHelperSF1601' - - '@logger.channel.os2forms_digital_post' + autowire: true tags: - { name: 'event_subscriber' } Drupal\os2forms_digital_post\Helper\BeskedfordelerHelper: - arguments: - - '@database' - - '@Drupal\os2forms_digital_post\Helper\MeMoHelper' - - '@logger.channel.os2forms_digital_post' + autowire: true diff --git a/modules/os2forms_digital_post/src/EventSubscriber/BeskedfordelerEventSubscriber.php b/modules/os2forms_digital_post/src/EventSubscriber/BeskedfordelerEventSubscriber.php index cbef5ad4..446dc8f3 100644 --- a/modules/os2forms_digital_post/src/EventSubscriber/BeskedfordelerEventSubscriber.php +++ b/modules/os2forms_digital_post/src/EventSubscriber/BeskedfordelerEventSubscriber.php @@ -8,6 +8,7 @@ use Drupal\os2forms_digital_post\Helper\BeskedfordelerHelper; use Drupal\os2forms_digital_post\Helper\WebformHelperSF1601; use Psr\Log\LoggerInterface; +use Symfony\Component\DependencyInjection\Attribute\Autowire; /** * Event subscriber for PostStatusBeskedModtagEvent. @@ -23,6 +24,7 @@ public function __construct( private readonly BeskedfordelerHelper $beskedfordelerHelper, private readonly MessageHelper $messageHelper, private readonly WebformHelperSF1601 $webformHelper, + #[Autowire(service: 'logger.channel.os2forms_digital_post')] LoggerInterface $logger, ) { parent::__construct($logger); diff --git a/modules/os2forms_digital_post/src/Form/SettingsForm.php b/modules/os2forms_digital_post/src/Form/SettingsForm.php index 5bfb04f6..0112a87b 100644 --- a/modules/os2forms_digital_post/src/Form/SettingsForm.php +++ b/modules/os2forms_digital_post/src/Form/SettingsForm.php @@ -35,7 +35,6 @@ public function __construct( ConfigFactoryInterface $config_factory, EntityTypeManagerInterface $entityTypeManager, private readonly Settings $settings, - private readonly CertificateLocatorHelper $certificateLocatorHelper, ) { parent::__construct($config_factory); $this->queueStorage = $entityTypeManager->getStorage('advancedqueue_queue'); @@ -51,7 +50,6 @@ public static function create(ContainerInterface $container) { $container->get('config.factory'), $container->get('entity_type.manager'), $container->get(Settings::class), - $container->get(CertificateLocatorHelper::class), ); } @@ -289,15 +287,6 @@ public function buildForm(array $form, FormStateInterface $form_state): array { ), ]; - $form['actions']['testCertificate'] = [ - '#type' => 'submit', - '#name' => 'testCertificate', - '#value' => $this->t('Test certificate'), - '#states' => [ - 'visible' => [':input[name="certificate[certificate_provider]"]' => ['value' => Settings::PROVIDER_TYPE_FORM]], - ], - ]; - return $form; } @@ -307,11 +296,6 @@ public function buildForm(array $form, FormStateInterface $form_state): array { * @phpstan-param array $form */ public function validateForm(array &$form, FormStateInterface $form_state): void { - $triggeringElement = $form_state->getTriggeringElement(); - if ('testCertificate' === ($triggeringElement['#name'] ?? NULL)) { - return; - } - $values = $form_state->getValues(); if (Settings::PROVIDER_TYPE_FORM === $values[Settings::CERTIFICATE][Settings::CERTIFICATE_PROVIDER]) { @@ -332,12 +316,6 @@ public function validateForm(array &$form, FormStateInterface $form_state): void * @phpstan-param array $form */ public function submitForm(array &$form, FormStateInterface $form_state): void { - $triggeringElement = $form_state->getTriggeringElement(); - if ('testCertificate' === ($triggeringElement['#name'] ?? NULL)) { - $this->testCertificate(); - return; - } - $config = $this->config(Settings::CONFIG_NAME); foreach ([ Settings::TEST_MODE, @@ -376,20 +354,4 @@ private function createDescription(string|array $key, ?TranslatableMarkup $descr return (string) $description; } - /** - * Test certificate. - */ - private function testCertificate(): void { - try { - - $certificateLocator = $this->certificateLocatorHelper->getCertificateLocator(); - $certificateLocator->getCertificates(); - $this->messenger()->addStatus($this->t('Certificate succesfully tested')); - } - catch (\Throwable $throwable) { - $message = $this->t('Error testing certificate: %message', ['%message' => $throwable->getMessage()]); - $this->messenger()->addError($message); - } - } - } diff --git a/modules/os2forms_digital_post/src/Helper/BeskedfordelerHelper.php b/modules/os2forms_digital_post/src/Helper/BeskedfordelerHelper.php index 5b93da5e..c256dc17 100644 --- a/modules/os2forms_digital_post/src/Helper/BeskedfordelerHelper.php +++ b/modules/os2forms_digital_post/src/Helper/BeskedfordelerHelper.php @@ -9,6 +9,7 @@ use Drupal\webform\WebformSubmissionInterface; use Psr\Log\LoggerAwareTrait; use Psr\Log\LoggerInterface; +use Symfony\Component\DependencyInjection\Attribute\Autowire; /** * Beskedfordeler helper. @@ -24,6 +25,7 @@ class BeskedfordelerHelper { public function __construct( private readonly Connection $database, private readonly MeMoHelper $meMoHelper, + #[Autowire(service: 'logger.channel.os2forms_digital_post')] LoggerInterface $logger, ) { $this->setLogger($logger); diff --git a/modules/os2forms_digital_post/src/Helper/DigitalPostHelper.php b/modules/os2forms_digital_post/src/Helper/DigitalPostHelper.php index d2f2af65..44198074 100644 --- a/modules/os2forms_digital_post/src/Helper/DigitalPostHelper.php +++ b/modules/os2forms_digital_post/src/Helper/DigitalPostHelper.php @@ -18,6 +18,7 @@ use Oio\Fjernprint\ForsendelseI; use Psr\Log\LoggerInterface; use Psr\Log\LoggerTrait; +use Symfony\Component\DependencyInjection\Attribute\Autowire; /** * Webform helper. @@ -31,13 +32,17 @@ final class DigitalPostHelper implements LoggerInterface { public function __construct( private readonly Settings $settings, private readonly KeyHelper $keyHelper, + #[Autowire(service: 'plugin.manager.os2web_datalookup')] private readonly DataLookupManager $dataLookupManager, private readonly MeMoHelper $meMoHelper, private readonly ForsendelseHelper $forsendelseHelper, private readonly BeskedfordelerHelper $beskedfordelerHelper, private readonly CertificateLocatorHelper $certificateLocatorHelper, + #[Autowire(service: 'logger.channel.os2forms_digital_post')] private readonly LoggerChannelInterface $logger, + #[Autowire(service: 'logger.channel.os2forms_digital_post_submission')] private readonly LoggerChannelInterface $submissionLogger, + #[Autowire(service: 'os2web_audit.logger')] private readonly Logger $auditLogger, ) { } diff --git a/modules/os2forms_digital_post/src/Helper/Settings.php b/modules/os2forms_digital_post/src/Helper/Settings.php index 176749b2..fc7ab385 100644 --- a/modules/os2forms_digital_post/src/Helper/Settings.php +++ b/modules/os2forms_digital_post/src/Helper/Settings.php @@ -7,6 +7,7 @@ use Drupal\Core\Config\ImmutableConfig; use Drupal\key\KeyInterface; use Drupal\key\KeyRepositoryInterface; +use Symfony\Component\DependencyInjection\Attribute\Autowire; /** * General settings for os2forms_digital_post. @@ -49,6 +50,7 @@ final class Settings { */ public function __construct( ConfigFactoryInterface $configFactory, + #[Autowire(service: 'key.repository')] private readonly KeyRepositoryInterface $keyRepository, ) { $this->runtimeConfig = $configFactory->get(self::CONFIG_NAME); diff --git a/modules/os2forms_digital_post/src/Helper/WebformHelperSF1601.php b/modules/os2forms_digital_post/src/Helper/WebformHelperSF1601.php index 3c2c724e..60fae6a2 100644 --- a/modules/os2forms_digital_post/src/Helper/WebformHelperSF1601.php +++ b/modules/os2forms_digital_post/src/Helper/WebformHelperSF1601.php @@ -21,6 +21,7 @@ use ItkDev\Serviceplatformen\Service\SF1601\SF1601; use Psr\Log\LoggerInterface; use Psr\Log\LoggerTrait; +use Symfony\Component\DependencyInjection\Attribute\Autowire; /** * Webform helper. @@ -51,11 +52,14 @@ final class WebformHelperSF1601 implements LoggerInterface { public function __construct( private readonly Settings $settings, EntityTypeManagerInterface $entityTypeManager, + #[Autowire(service: 'plugin.manager.os2web_datalookup')] private readonly DataLookupManager $dataLookupManager, private readonly MeMoHelper $meMoHelper, private readonly ForsendelseHelper $forsendelseHelper, private readonly BeskedfordelerHelper $beskedfordelerHelper, + #[Autowire(service: 'logger.channel.os2forms_digital_post')] private readonly LoggerChannelInterface $logger, + #[Autowire(service: 'logger.channel.os2forms_digital_post_submission')] private readonly LoggerChannelInterface $submissionLogger, private readonly DigitalPostHelper $digitalPostHelper, ) { From 25f35ce173b582a5b6ca3ac145dd2f7661f00ce7 Mon Sep 17 00:00:00 2001 From: jekuaitk Date: Fri, 24 Jan 2025 11:05:40 +0100 Subject: [PATCH 37/46] Updates settings forms --- modules/os2forms_digital_post/src/Form/SettingsForm.php | 2 +- modules/os2forms_fasit/src/Form/SettingsForm.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/os2forms_digital_post/src/Form/SettingsForm.php b/modules/os2forms_digital_post/src/Form/SettingsForm.php index 0112a87b..e03f2d8a 100644 --- a/modules/os2forms_digital_post/src/Form/SettingsForm.php +++ b/modules/os2forms_digital_post/src/Form/SettingsForm.php @@ -252,10 +252,10 @@ public function buildForm(array $form, FormStateInterface $form_state): array { '#key_description' => FALSE, '#title' => $this->t('Key'), '#default_value' => $this->settings->getEditableValue([Settings::CERTIFICATE, Settings::PROVIDER_TYPE_KEY]), - '#required' => TRUE, '#description' => $this->createDescription([Settings::CERTIFICATE, Settings::PROVIDER_TYPE_KEY]), '#states' => [ 'visible' => [':input[name="certificate[certificate_provider]"]' => ['value' => Settings::PROVIDER_TYPE_KEY]], + 'required' => [':input[name="certificate[certificate_provider]"]' => ['value' => Settings::PROVIDER_TYPE_KEY]], ], ]; diff --git a/modules/os2forms_fasit/src/Form/SettingsForm.php b/modules/os2forms_fasit/src/Form/SettingsForm.php index fdd6e0e0..a343b307 100644 --- a/modules/os2forms_fasit/src/Form/SettingsForm.php +++ b/modules/os2forms_fasit/src/Form/SettingsForm.php @@ -209,10 +209,10 @@ public function buildForm(array $form, FormStateInterface $form_state): array { 'type' => 'os2web_key_certificate', ], '#title' => $this->t('Key'), - '#required' => TRUE, '#default_value' => $config->get(self::PROVIDER_TYPE_KEY), '#states' => [ 'visible' => [':input[name="certificate[certificate_provider]"]' => ['value' => self::PROVIDER_TYPE_KEY]], + 'required' => [':input[name="certificate[certificate_provider]"]' => ['value' => self::PROVIDER_TYPE_KEY]], ], ]; From 3bde9cc5dd064f25c009daf8a34c98a2c3f3c408 Mon Sep 17 00:00:00 2001 From: jekuaitk Date: Fri, 24 Jan 2025 12:54:52 +0100 Subject: [PATCH 38/46] Updates settings forms --- modules/os2forms_fasit/src/Form/SettingsForm.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/os2forms_fasit/src/Form/SettingsForm.php b/modules/os2forms_fasit/src/Form/SettingsForm.php index a343b307..9e05b95b 100644 --- a/modules/os2forms_fasit/src/Form/SettingsForm.php +++ b/modules/os2forms_fasit/src/Form/SettingsForm.php @@ -209,7 +209,7 @@ public function buildForm(array $form, FormStateInterface $form_state): array { 'type' => 'os2web_key_certificate', ], '#title' => $this->t('Key'), - '#default_value' => $config->get(self::PROVIDER_TYPE_KEY), + '#default_value' => $certificateConfig[self::PROVIDER_TYPE_KEY] ?? NULL, '#states' => [ 'visible' => [':input[name="certificate[certificate_provider]"]' => ['value' => self::PROVIDER_TYPE_KEY]], 'required' => [':input[name="certificate[certificate_provider]"]' => ['value' => self::PROVIDER_TYPE_KEY]], From e1e38abe6927159b3b24844dcd6f17116d733e4e Mon Sep 17 00:00:00 2001 From: jekuaitk Date: Fri, 24 Jan 2025 13:24:29 +0100 Subject: [PATCH 39/46] Updates settings forms --- modules/os2forms_fasit/src/Helper/Settings.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/modules/os2forms_fasit/src/Helper/Settings.php b/modules/os2forms_fasit/src/Helper/Settings.php index 09d0cd92..09410299 100644 --- a/modules/os2forms_fasit/src/Helper/Settings.php +++ b/modules/os2forms_fasit/src/Helper/Settings.php @@ -78,7 +78,9 @@ public function getFasitCertificateLocator(): string { * Get Fasit key certificate configuration. */ public function getFasitCertificateKey(): ?string { - return $this->get(SettingsForm::KEY); + $config = $this->getFasitCertificateConfig(); + + return $config[SettingsForm::PROVIDER_TYPE_KEY] ?? NULL; } /** From 85394521a4551c99746f251c4dc780fb9cbd21c6 Mon Sep 17 00:00:00 2001 From: jekuaitk Date: Fri, 24 Jan 2025 15:51:21 +0100 Subject: [PATCH 40/46] Update versions requiment --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index aee475b2..4a9bedd8 100644 --- a/composer.json +++ b/composer.json @@ -59,7 +59,7 @@ "itk-dev/serviceplatformen": "^1.5", "mglaman/composer-drupal-lenient": "^1.0", "os2web/os2web_audit": "^0.1.6", - "os2web/os2web_datalookup": "dev-feature/os2web_key as 2.0.0", + "os2web/os2web_datalookup": "^2.0", "os2web/os2web_key": "^1.0", "os2web/os2web_nemlogin": "^1.0", "os2web/os2web_simplesaml": "dev-master", From c6e6cb10c3d579cf8da5f6e9494439e2caacef1a Mon Sep 17 00:00:00 2001 From: jekuaitk Date: Fri, 24 Jan 2025 16:00:02 +0100 Subject: [PATCH 41/46] clean up --- composer.json | 4 ---- 1 file changed, 4 deletions(-) diff --git a/composer.json b/composer.json index 4a9bedd8..7972ad98 100644 --- a/composer.json +++ b/composer.json @@ -81,10 +81,6 @@ "wsdltophp/packagegenerator": "^4.0" }, "repositories": { - "os2web/os2web_datalookup": { - "type": "vcs", - "url": "https://github.com/itk-dev/os2web_datalookup" - }, "drupal": { "type": "composer", "url": "https://packages.drupal.org/8" From d8424d0c9b9c714fd96d0cd23d07973f88d1431a Mon Sep 17 00:00:00 2001 From: Jeppe Kuhlmann Andersen <78410897+jekuaitk@users.noreply.github.com> Date: Mon, 27 Jan 2025 09:28:11 +0100 Subject: [PATCH 42/46] Update modules/os2forms_digital_post/src/Helper/CertificateLocatorHelper.php Co-authored-by: Mikkel Ricky --- .../src/Helper/CertificateLocatorHelper.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/os2forms_digital_post/src/Helper/CertificateLocatorHelper.php b/modules/os2forms_digital_post/src/Helper/CertificateLocatorHelper.php index 14710b93..01fde400 100644 --- a/modules/os2forms_digital_post/src/Helper/CertificateLocatorHelper.php +++ b/modules/os2forms_digital_post/src/Helper/CertificateLocatorHelper.php @@ -45,7 +45,7 @@ public function getCertificateLocator(): CertificateLocatorInterface { $locatorType = $certificateSettings['locator_type']; $options = $certificateSettings[$locatorType]; $options += [ - 'passphrase' => $certificateSettings['passphrase'] ?: '', + 'passphrase' => $certificateSettings['passphrase'], ]; if (self::LOCATOR_TYPE_AZURE_KEY_VAULT === $locatorType) { From 243e1e828bdd1f1604f5e5696d17170751043078 Mon Sep 17 00:00:00 2001 From: jekuaitk Date: Mon, 27 Jan 2025 11:29:28 +0100 Subject: [PATCH 43/46] Autowired services --- .../os2forms_digital_post.services.yml | 6 ------ .../src/Helper/ForsendelseHelper.php | 16 ++++++++++++++++ .../src/Helper/MeMoHelper.php | 16 ++++++++++++++++ 3 files changed, 32 insertions(+), 6 deletions(-) diff --git a/modules/os2forms_digital_post/os2forms_digital_post.services.yml b/modules/os2forms_digital_post/os2forms_digital_post.services.yml index ed03ea36..1b554d91 100644 --- a/modules/os2forms_digital_post/os2forms_digital_post.services.yml +++ b/modules/os2forms_digital_post/os2forms_digital_post.services.yml @@ -15,15 +15,9 @@ services: Drupal\os2forms_digital_post\Helper\MeMoHelper: autowire: true - arguments: - $elementInfoManager: "@plugin.manager.element_info" - $webformTokenManager: "@webform.token_manager" Drupal\os2forms_digital_post\Helper\ForsendelseHelper: autowire: true - arguments: - $elementInfoManager: "@plugin.manager.element_info" - $webformTokenManager: "@webform.token_manager" Drupal\os2forms_digital_post\Helper\DigitalPostHelper: autowire: true diff --git a/modules/os2forms_digital_post/src/Helper/ForsendelseHelper.php b/modules/os2forms_digital_post/src/Helper/ForsendelseHelper.php index 42cbbea1..998c8f40 100644 --- a/modules/os2forms_digital_post/src/Helper/ForsendelseHelper.php +++ b/modules/os2forms_digital_post/src/Helper/ForsendelseHelper.php @@ -2,12 +2,14 @@ namespace Drupal\os2forms_digital_post\Helper; +use Drupal\Core\Render\ElementInfoManager; use Drupal\os2forms_digital_post\Exception\InvalidForsendelseException; use Drupal\os2forms_digital_post\Model\Document; use Drupal\os2forms_digital_post\Plugin\WebformHandler\WebformHandlerSF1601; use Drupal\os2web_datalookup\LookupResult\CompanyLookupResult; use Drupal\os2web_datalookup\LookupResult\CprLookupResult; use Drupal\webform\WebformSubmissionInterface; +use Drupal\webform\WebformTokenManagerInterface; use ItkDev\Serviceplatformen\Service\SF1601\Serializer; use Oio\Dkal\AfsendelseModtager; use Oio\Ebxml\CountryIdentificationCode; @@ -16,6 +18,7 @@ use Oio\Fjernprint\ForsendelseModtager; use Oio\Fjernprint\ModtagerAdresse; use Oio\Fjernprint\PostParametre; +use Symfony\Component\DependencyInjection\Attribute\Autowire; /** * Forsendelse helper. @@ -24,6 +27,19 @@ class ForsendelseHelper extends AbstractMessageHelper { // PostKategoriKode. public const POST_KATEGORI_KODE_PRIORITAIRE = 'Prioritaire'; + /** + * {@inheritDoc} + */ + public function __construct( + Settings $settings, + #[Autowire(service: 'plugin.manager.element_info')] + ElementInfoManager $elementInfoManager, + #[Autowire(service: 'webform.token_manager')] + WebformTokenManagerInterface $webformTokenManager, + ) { + parent::__construct($settings, $elementInfoManager, $webformTokenManager); + } + /** * Build forsendelse. */ diff --git a/modules/os2forms_digital_post/src/Helper/MeMoHelper.php b/modules/os2forms_digital_post/src/Helper/MeMoHelper.php index 3ec8b7ed..96b82f48 100644 --- a/modules/os2forms_digital_post/src/Helper/MeMoHelper.php +++ b/modules/os2forms_digital_post/src/Helper/MeMoHelper.php @@ -14,19 +14,35 @@ use DigitalPost\MeMo\MessageHeader; use DigitalPost\MeMo\Recipient; use DigitalPost\MeMo\Sender; +use Drupal\Core\Render\ElementInfoManager; use Drupal\os2forms_digital_post\Model\Document; use Drupal\os2forms_digital_post\Plugin\WebformHandler\WebformHandlerSF1601; use Drupal\os2web_datalookup\LookupResult\CompanyLookupResult; use Drupal\os2web_datalookup\LookupResult\CprLookupResult; use Drupal\webform\WebformSubmissionInterface; +use Drupal\webform\WebformTokenManagerInterface; use ItkDev\Serviceplatformen\Service\SF1601\SF1601; use ItkDev\Serviceplatformen\Service\SF1601\Serializer; +use Symfony\Component\DependencyInjection\Attribute\Autowire; /** * MeMo helper. */ class MeMoHelper extends AbstractMessageHelper { + /** + * {@inheritDoc} + */ + public function __construct( + Settings $settings, + #[Autowire(service: 'plugin.manager.element_info')] + ElementInfoManager $elementInfoManager, + #[Autowire(service: 'webform.token_manager')] + WebformTokenManagerInterface $webformTokenManager, + ) { + parent::__construct($settings, $elementInfoManager, $webformTokenManager); + } + /** * Build message. * From 5e19aa507c4807a22c613095f279acb5478fe42b Mon Sep 17 00:00:00 2001 From: jekuaitk Date: Mon, 27 Jan 2025 12:55:09 +0100 Subject: [PATCH 44/46] Ignored possible UselessOverridingMethod --- modules/os2forms_digital_post/src/Helper/ForsendelseHelper.php | 3 +++ modules/os2forms_digital_post/src/Helper/MeMoHelper.php | 3 +++ 2 files changed, 6 insertions(+) diff --git a/modules/os2forms_digital_post/src/Helper/ForsendelseHelper.php b/modules/os2forms_digital_post/src/Helper/ForsendelseHelper.php index 998c8f40..a8501ea0 100644 --- a/modules/os2forms_digital_post/src/Helper/ForsendelseHelper.php +++ b/modules/os2forms_digital_post/src/Helper/ForsendelseHelper.php @@ -30,6 +30,7 @@ class ForsendelseHelper extends AbstractMessageHelper { /** * {@inheritDoc} */ + // phpcs:disable Generic.CodeAnalysis.UselessOverridingMethod public function __construct( Settings $settings, #[Autowire(service: 'plugin.manager.element_info')] @@ -40,6 +41,8 @@ public function __construct( parent::__construct($settings, $elementInfoManager, $webformTokenManager); } + // phpcs:enable + /** * Build forsendelse. */ diff --git a/modules/os2forms_digital_post/src/Helper/MeMoHelper.php b/modules/os2forms_digital_post/src/Helper/MeMoHelper.php index 96b82f48..a88e9df3 100644 --- a/modules/os2forms_digital_post/src/Helper/MeMoHelper.php +++ b/modules/os2forms_digital_post/src/Helper/MeMoHelper.php @@ -33,6 +33,7 @@ class MeMoHelper extends AbstractMessageHelper { /** * {@inheritDoc} */ + // phpcs:disable Generic.CodeAnalysis.UselessOverridingMethod public function __construct( Settings $settings, #[Autowire(service: 'plugin.manager.element_info')] @@ -43,6 +44,8 @@ public function __construct( parent::__construct($settings, $elementInfoManager, $webformTokenManager); } + // phpcs:enable + /** * Build message. * From c0c053e34c7ebc84e679ba3e06df7e14122eb566 Mon Sep 17 00:00:00 2001 From: jekuaitk Date: Mon, 27 Jan 2025 14:54:39 +0100 Subject: [PATCH 45/46] Moved autowire to abstract class --- .../src/Helper/AbstractMessageHelper.php | 2 ++ .../src/Helper/ForsendelseHelper.php | 19 ------------------- .../src/Helper/MeMoHelper.php | 19 ------------------- 3 files changed, 2 insertions(+), 38 deletions(-) diff --git a/modules/os2forms_digital_post/src/Helper/AbstractMessageHelper.php b/modules/os2forms_digital_post/src/Helper/AbstractMessageHelper.php index d9fb96a3..e4a85abb 100644 --- a/modules/os2forms_digital_post/src/Helper/AbstractMessageHelper.php +++ b/modules/os2forms_digital_post/src/Helper/AbstractMessageHelper.php @@ -12,6 +12,7 @@ use Drupal\webform_attachment\Element\WebformAttachmentBase; use ItkDev\Serviceplatformen\Service\SF1601\Serializer; use Oio\Fjernprint\ForsendelseI; +use Symfony\Component\DependencyInjection\Attribute\Autowire; /** * Abstract message helper. @@ -23,6 +24,7 @@ abstract class AbstractMessageHelper { */ public function __construct( readonly protected Settings $settings, + #[Autowire(service: 'plugin.manager.element_info')] readonly protected ElementInfoManager $elementInfoManager, readonly protected WebformTokenManagerInterface $webformTokenManager, ) { diff --git a/modules/os2forms_digital_post/src/Helper/ForsendelseHelper.php b/modules/os2forms_digital_post/src/Helper/ForsendelseHelper.php index a8501ea0..42cbbea1 100644 --- a/modules/os2forms_digital_post/src/Helper/ForsendelseHelper.php +++ b/modules/os2forms_digital_post/src/Helper/ForsendelseHelper.php @@ -2,14 +2,12 @@ namespace Drupal\os2forms_digital_post\Helper; -use Drupal\Core\Render\ElementInfoManager; use Drupal\os2forms_digital_post\Exception\InvalidForsendelseException; use Drupal\os2forms_digital_post\Model\Document; use Drupal\os2forms_digital_post\Plugin\WebformHandler\WebformHandlerSF1601; use Drupal\os2web_datalookup\LookupResult\CompanyLookupResult; use Drupal\os2web_datalookup\LookupResult\CprLookupResult; use Drupal\webform\WebformSubmissionInterface; -use Drupal\webform\WebformTokenManagerInterface; use ItkDev\Serviceplatformen\Service\SF1601\Serializer; use Oio\Dkal\AfsendelseModtager; use Oio\Ebxml\CountryIdentificationCode; @@ -18,7 +16,6 @@ use Oio\Fjernprint\ForsendelseModtager; use Oio\Fjernprint\ModtagerAdresse; use Oio\Fjernprint\PostParametre; -use Symfony\Component\DependencyInjection\Attribute\Autowire; /** * Forsendelse helper. @@ -27,22 +24,6 @@ class ForsendelseHelper extends AbstractMessageHelper { // PostKategoriKode. public const POST_KATEGORI_KODE_PRIORITAIRE = 'Prioritaire'; - /** - * {@inheritDoc} - */ - // phpcs:disable Generic.CodeAnalysis.UselessOverridingMethod - public function __construct( - Settings $settings, - #[Autowire(service: 'plugin.manager.element_info')] - ElementInfoManager $elementInfoManager, - #[Autowire(service: 'webform.token_manager')] - WebformTokenManagerInterface $webformTokenManager, - ) { - parent::__construct($settings, $elementInfoManager, $webformTokenManager); - } - - // phpcs:enable - /** * Build forsendelse. */ diff --git a/modules/os2forms_digital_post/src/Helper/MeMoHelper.php b/modules/os2forms_digital_post/src/Helper/MeMoHelper.php index a88e9df3..3ec8b7ed 100644 --- a/modules/os2forms_digital_post/src/Helper/MeMoHelper.php +++ b/modules/os2forms_digital_post/src/Helper/MeMoHelper.php @@ -14,38 +14,19 @@ use DigitalPost\MeMo\MessageHeader; use DigitalPost\MeMo\Recipient; use DigitalPost\MeMo\Sender; -use Drupal\Core\Render\ElementInfoManager; use Drupal\os2forms_digital_post\Model\Document; use Drupal\os2forms_digital_post\Plugin\WebformHandler\WebformHandlerSF1601; use Drupal\os2web_datalookup\LookupResult\CompanyLookupResult; use Drupal\os2web_datalookup\LookupResult\CprLookupResult; use Drupal\webform\WebformSubmissionInterface; -use Drupal\webform\WebformTokenManagerInterface; use ItkDev\Serviceplatformen\Service\SF1601\SF1601; use ItkDev\Serviceplatformen\Service\SF1601\Serializer; -use Symfony\Component\DependencyInjection\Attribute\Autowire; /** * MeMo helper. */ class MeMoHelper extends AbstractMessageHelper { - /** - * {@inheritDoc} - */ - // phpcs:disable Generic.CodeAnalysis.UselessOverridingMethod - public function __construct( - Settings $settings, - #[Autowire(service: 'plugin.manager.element_info')] - ElementInfoManager $elementInfoManager, - #[Autowire(service: 'webform.token_manager')] - WebformTokenManagerInterface $webformTokenManager, - ) { - parent::__construct($settings, $elementInfoManager, $webformTokenManager); - } - - // phpcs:enable - /** * Build message. * From 44d0d3a2a1936735575b56b2bc9bab8f543b1dfa Mon Sep 17 00:00:00 2001 From: jekuaitk Date: Fri, 7 Feb 2025 13:13:19 +0100 Subject: [PATCH 46/46] Specified webform.token_manager service --- .../os2forms_digital_post/src/Helper/AbstractMessageHelper.php | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/os2forms_digital_post/src/Helper/AbstractMessageHelper.php b/modules/os2forms_digital_post/src/Helper/AbstractMessageHelper.php index e4a85abb..c2f2b990 100644 --- a/modules/os2forms_digital_post/src/Helper/AbstractMessageHelper.php +++ b/modules/os2forms_digital_post/src/Helper/AbstractMessageHelper.php @@ -26,6 +26,7 @@ public function __construct( readonly protected Settings $settings, #[Autowire(service: 'plugin.manager.element_info')] readonly protected ElementInfoManager $elementInfoManager, + #[Autowire(service: 'webform.token_manager')] readonly protected WebformTokenManagerInterface $webformTokenManager, ) { }