From 81ae855828c600c2c43660ad13ef01dfbb3514be Mon Sep 17 00:00:00 2001 From: Tinny Nguyen <cnguyen.biz@gmail.com> Date: Mon, 24 Feb 2025 13:17:32 +1100 Subject: [PATCH 1/3] Implement the resave method --- src/WebformEncryptSubmissionStorage.php | 29 ++++++- .../WebformEncryptSubmissionStorageTest.php | 79 +++++++++++++++++++ 2 files changed, 106 insertions(+), 2 deletions(-) diff --git a/src/WebformEncryptSubmissionStorage.php b/src/WebformEncryptSubmissionStorage.php index 6e5622b..28304e7 100644 --- a/src/WebformEncryptSubmissionStorage.php +++ b/src/WebformEncryptSubmissionStorage.php @@ -143,6 +143,12 @@ class WebformEncryptSubmissionStorage extends WebformSubmissionStorage { * @throws \Drupal\encrypt\Exception\EncryptException */ protected function encrypt($string, EncryptionProfileInterface $encryption_profile) { + // Prevent multiple encryptions. + $unserialized = @unserialize($string, ['allowed_classes' => FALSE]); + if ($unserialized !== FALSE && !empty($unserialized['data']) && !empty($unserialized['encrypt_profile'])) { + return $string; + } + // Serialize the data to include the encryption profile. // This is used later to check for changes in the profile. $encrypted_data = [ @@ -169,8 +175,8 @@ class WebformEncryptSubmissionStorage extends WebformSubmissionStorage { if ($check_permissions && !$this->currentUser->hasPermission('view encrypted values')) { return '[Value Encrypted]'; } - $unserialized = unserialize($data); - if (isset($unserialized['data']) && isset($unserialized['encrypt_profile'])) { + $unserialized = @unserialize($data, ['allowed_classes' => FALSE]); + if ($unserialized !== FALSE && isset($unserialized['data']) && isset($unserialized['encrypt_profile'])) { $encryption_profile = EncryptionProfile::load($unserialized['encrypt_profile']); return $this->encryptionService->decrypt($unserialized['data'], $encryption_profile); } @@ -236,6 +242,25 @@ class WebformEncryptSubmissionStorage extends WebformSubmissionStorage { } } + /** + * {@inheritdoc} + */ + public function resave(EntityInterface $entity) { + /** @var \Drupal\webform\WebformSubmissionInterface $entity */ + + $data_original = $entity->getData(); + $webform = $entity->getWebform(); + + $encrypted_data = $this->encryptElements($data_original, $webform); + $entity->setData($encrypted_data); + + $id = parent::resave($entity); + + $entity->setData($data_original); + + return $id; + } + /** * {@inheritdoc} */ diff --git a/tests/src/Kernel/WebformEncryptSubmissionStorageTest.php b/tests/src/Kernel/WebformEncryptSubmissionStorageTest.php index 298bbcb..d0052a9 100644 --- a/tests/src/Kernel/WebformEncryptSubmissionStorageTest.php +++ b/tests/src/Kernel/WebformEncryptSubmissionStorageTest.php @@ -216,4 +216,83 @@ class WebformEncryptSubmissionStorageTest extends KernelTestBase { $this->assertEquals('Test text field value', $data['test_text_field']); } + /** + * Tests save and resave methods encrypt data correctly. + */ + public function testSaveResaveWebform() { + $this->assertEquals(NULL, $this->container->get('state')->get('test_webform_handler_counter')); + + $webform = Webform::load('test_encryption'); + $original_values = [ + 'id' => 'webform_submission_test', + 'webform_id' => $webform->id(), + 'data' => [ + 'test_text_field' => 'Test text field value', + 'test_multiple_text_field' => [ + 0 => 'Test multiple text field value 1', + ], + 'test_text_area' => 'Test text area value', + 'test_not_encrypted' => 'Test not encrypted value', + 'test_address_field' => [ + 'address' => 'Test address field address', + 'address_2' => 'Test address field address 2', + 'city' => 'Test address field city', + 'state_province' => 'California', + 'postal_code' => 'AA11AA', + 'country' => 'United Kingdom', + ], + 'test_multiple_address_field' => [ + 0 => [ + 'address' => 'Test multiple address field address', + 'address_2' => 'Test multiple address field address 2', + 'city' => 'Test multiple address field city', + 'state_province' => 'California', + 'postal_code' => 'AA11AA', + 'country' => 'United Kingdom', + ], + ], + ], + ]; + /** @var \Drupal\webform\WebformSubmissionInterface $webform_submission */ + $webform_submission = WebformSubmission::create($original_values); + // Calling the save method should encrypt the data in the DB. + $webform_submission->save(); + $submissions_after_save = \Drupal::database()->select('webform_submission_data', 'wsd') + ->fields('wsd', []) + ->execute() + ->fetchAllAssoc('name'); + foreach ($submissions_after_save as $name => $submission) { + if ($name == 'test_not_encrypted') { + $this->assertEquals($original_values['data'][$name], $submission->value); + continue; + } + $this->assertNotEquals($original_values['data'][$name], $submission->value); + } + // All data should be decrypted as normally after being saved. + $data = $webform_submission->getData(); + foreach ($data as $name => $value) { + $this->assertEquals($original_values['data'][$name], $value); + } + + // Calling the resave method should keep the data encrypted in the DB. + $webform_submission->resave(); + $submissions_after_resave = \Drupal::database()->select('webform_submission_data', 'wsd') + ->fields('wsd', []) + ->execute() + ->fetchAllAssoc('name'); + foreach ($submissions_after_resave as $name => $submission) { + if ($name == 'test_not_encrypted') { + $this->assertEquals($original_values['data'][$name], $submission->value); + continue; + } + $this->assertNotEquals($original_values['data'][$name], $submission->value); + } + + // All data should be decrypted as normally after calling resave. + $data = $webform_submission->getData(); + foreach ($data as $name => $value) { + $this->assertEquals($original_values['data'][$name], $value); + } + } + } -- GitLab From 9298a3ad5bfc96edbfe1da5091c612cd30c76622 Mon Sep 17 00:00:00 2001 From: tinny <67820-tinny@users.noreply.drupalcode.org> Date: Thu, 27 Feb 2025 22:53:24 +0000 Subject: [PATCH 2/3] Add gitlab ci template. --- .gitlab-ci.yml | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 .gitlab-ci.yml diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000..c6cd69a --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,29 @@ +################ +# GitLabCI template for Drupal projects. +# +# This template is designed to give any Contrib maintainer everything they need to test, without requiring modification. +# It is also designed to keep up to date with Core Development automatically through the use of include files that can be centrally maintained. +# As long as you include the project, ref and three files below, any future updates added by the Drupal Association will be used in your +# pipelines automatically. However, you can modify this template if you have additional needs for your project. +# The full documentation is on https://project.pages.drupalcode.org/gitlab_templates/ +################ + +# For information on alternative values for 'ref' see https://project.pages.drupalcode.org/gitlab_templates/info/templates-version/ +# To test a Drupal 7 project, change the first include filename from .main.yml to .main-d7.yml +include: + - project: $_GITLAB_TEMPLATES_REPO + ref: $_GITLAB_TEMPLATES_REF + file: + - '/includes/include.drupalci.main.yml' + - '/includes/include.drupalci.variables.yml' + - '/includes/include.drupalci.workflows.yml' +# +################ +# Pipeline configuration variables are defined with default values and descriptions in the file +# https://git.drupalcode.org/project/gitlab_templates/-/blob/main/includes/include.drupalci.variables.yml +# Uncomment the lines below if you want to override any of the variables. The following is just an example. +################ +# variables: +# SKIP_ESLINT: '1' +# OPT_IN_TEST_NEXT_MAJOR: '1' +# _CURL_TEMPLATES_REF: 'main' -- GitLab From 68c9e94a4bb632c273e9898efddec217fe64c638 Mon Sep 17 00:00:00 2001 From: tinny <67820-tinny@users.noreply.drupalcode.org> Date: Fri, 28 Feb 2025 00:40:13 +0000 Subject: [PATCH 3/3] Update PHP and Core variables for tests. --- .gitlab-ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index c6cd69a..f787f8b 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -23,7 +23,7 @@ include: # https://git.drupalcode.org/project/gitlab_templates/-/blob/main/includes/include.drupalci.variables.yml # Uncomment the lines below if you want to override any of the variables. The following is just an example. ################ -# variables: -# SKIP_ESLINT: '1' -# OPT_IN_TEST_NEXT_MAJOR: '1' -# _CURL_TEMPLATES_REF: 'main' +variables: + _TARGET_PHP: "8.1" + _TARGET_CORE: "10.1.3" + SYMFONY_DEPRECATIONS_HELPER: disabled -- GitLab