From 989cc3f995bb1ef5fa8c10cffa947120beb101da Mon Sep 17 00:00:00 2001
From: Jan Zimpel <j.zimpel@ub.uni-mainz.de>
Date: Fri, 21 Aug 2020 14:35:31 +0200
Subject: [PATCH] Allow delete operations with secure token.

---
 includes/webform.theme.template.inc           | 22 +++++++++++++++++++
 src/WebformSubmissionAccessControlHandler.php | 18 +++++++++++++++
 2 files changed, 40 insertions(+)

diff --git a/includes/webform.theme.template.inc b/includes/webform.theme.template.inc
index f3c0e1717..4b79d7bcc 100644
--- a/includes/webform.theme.template.inc
+++ b/includes/webform.theme.template.inc
@@ -363,6 +363,28 @@ function template_preprocess_webform_submission_information(array &$variables) {
     $base_route_name = (strpos(\Drupal::routeMatch()->getRouteName(), 'webform.user.submission') !== FALSE) ? 'webform.user.submission.delete' : 'webform_submission.delete_form';
     $url = $request_handler->getUrl($webform_submission, $source_entity, $base_route_name);
 
+    if ($webform_submission->getToken()) {
+      // Send the token to enable the submission to bypass the access restrictions through the token.
+      $url->mergeOptions([
+          'query' => ['token' => $webform_submission->getToken()]
+      ]);
+    }
+
+    // Redirect if user has no access to submissions overview page.
+    if ($variables['submissions_view'] == FALSE) {
+      // Redirect back to source entity
+      if (($source_entity = $webform_submission->getSourceEntity()) && $source_entity->hasLinkTemplate('canonical')) {
+          $redirect = $source_entity->toUrl()->toString();
+      } else {
+          // Fallback: Redirect to front page
+          $redirect = '/';
+      }
+
+      $url->mergeOptions([
+          'query' => ['destination' => $redirect]
+      ]);
+    }
+
     $variables['delete'] = [
       '#type' => 'link',
       '#title' => t('Delete submission'),
diff --git a/src/WebformSubmissionAccessControlHandler.php b/src/WebformSubmissionAccessControlHandler.php
index 68c842818..d9df6b433 100644
--- a/src/WebformSubmissionAccessControlHandler.php
+++ b/src/WebformSubmissionAccessControlHandler.php
@@ -92,6 +92,24 @@ class WebformSubmissionAccessControlHandler extends EntityAccessControlHandler i
 
     }
 
+    // Allow delete operations with a (secure) token.
+    if ('delete' == $operation && $this->request->get('token')) {
+      // For security reasons check the token against the submission uuid.
+      if ('webform_submission_delete' == $this->request->attributes->get('operation')) {
+          $approved_submissions = \Drupal::entityQuery('webform_submission')
+              ->condition('uuid', $entity->uuid())
+              ->condition('token', $this->request->get('token'))
+              ->execute();
+
+          if (! count($approved_submissions)) {
+              return WebformAccessResult::forbidden();
+          }
+      }
+
+      return WebformAccessResult::allowed($entity)
+          ->addCacheContexts(['url']);
+    }
+
     // Check 'any' or 'own' webform submission permissions.
     $operations = [
       'view' => 'view',
-- 
2.22.0

