diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000000000000000000000000000000000000..f787f8b897e8ec6b3718158257f9f360e3bbb5b3 --- /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: + _TARGET_PHP: "8.1" + _TARGET_CORE: "10.1.3" + SYMFONY_DEPRECATIONS_HELPER: disabled diff --git a/src/WebformEncryptSubmissionStorage.php b/src/WebformEncryptSubmissionStorage.php index 6e5622bef99dc8e9dd54fb9f9afa22b9127f90fe..28304e7cd6001252dd9e40173006215f3d7ac9ee 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 298bbcbae1431c39beba53e62a36e75170cfb474..d0052a992204dc40784c731325e265da4877ae19 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); + } + } + }