CRM-15854 - Fix previews for user without 'create mailings'
authorTim Otten <totten@civicrm.org>
Sat, 28 Feb 2015 01:38:57 +0000 (18:38 -0700)
committerTim Otten <totten@civicrm.org>
Tue, 3 Mar 2015 02:45:36 +0000 (18:45 -0800)
CRM/Mailing/BAO/Mailing.php
api/v3/Mailing.php
js/angular-crmMailing/services.js

index 946558d3014ad7d4ed431cb608023ede59c123d3..998a4d74bbbab481faf488585dba4447e95d8284 100644 (file)
@@ -3132,4 +3132,31 @@ AND        m.id = %1
     return civicrm_api('MailingContact', 'getcount', $params);
   }
 
+  /**
+   * Get a list of permissions required for CRUD'ing each field
+   * (when workflow is enabled).
+   *
+   * @return array
+   *   Array (string $fieldName => string $permName)
+   */
+  public static function getWorkflowFieldPerms() {
+    $fieldNames = array_keys(CRM_Mailing_DAO_Mailing::fields());
+    $fieldPerms = array();
+    foreach ($fieldNames as $fieldName) {
+      if ($fieldName == 'id') {
+        $fieldPerms[$fieldName] = 'access CiviMail';
+      }
+      if (in_array($fieldName, array('scheduled_date', 'scheduled_id'))) {
+        $fieldPerms[$fieldName] = 'schedule mailings';
+      }
+      elseif (in_array($fieldName, array('approval_date', 'approver_id', 'approval_status_id', 'approval_note'))) {
+        $fieldPerms[$fieldName] = 'approve mailings';
+      }
+      else {
+        $fieldPerms[$fieldName] = 'create mailings';
+      }
+    }
+    return $fieldPerms;
+  }
+
 }
index d97176c1e7c512a40664a69d787dba9a0ec4cfd4..46a808a98b3e6edc447a4debb6b510b37b97e27b 100755 (executable)
  */
 function civicrm_api3_mailing_create($params) {
   if (CRM_Mailing_Info::workflowEnabled()) {
-    if (!CRM_Core_Permission::check('create mailings')) {
-      throw new \Civi\API\Exception\UnauthorizedException("This system uses advanced CiviMail workflows which require additional permissions");
-    }
-    if (!CRM_Core_Permission::check('schedule mailings')) {
-      unset($params['scheduled_date']);
-      unset($params['scheduled_id']);
-    }
-    if (!CRM_Core_Permission::check('approve mailings')) {
-      unset($params['approval_date']);
-      unset($params['approver_id']);
-      unset($params['approval_status_id']);
-      unset($params['approval_note']);
+    $safeParams = array();
+    $fieldPerms = CRM_Mailing_BAO_Mailing::getWorkflowFieldPerms();
+    foreach (array_keys($params) as $field) {
+      if (CRM_Core_Permission::check($fieldPerms[$field])) {
+        $safeParams[$field] = $params[$field];
+      }
     }
   }
-  $params['_evil_bao_validator_'] = 'CRM_Mailing_BAO_Mailing::checkSendable';
-  return _civicrm_api3_basic_create(_civicrm_api3_get_BAO(__FUNCTION__), $params);
+  else {
+    $safeParams = $params;
+  }
+  $safeParams['_evil_bao_validator_'] = 'CRM_Mailing_BAO_Mailing::checkSendable';
+  return _civicrm_api3_basic_create(_civicrm_api3_get_BAO(__FUNCTION__), $safeParams);
 }
 
 /**
index f2669367f664f26f3fcb5550a0f68e728470f0e7..deafdc5b64ca442946a94b0f52c4b569759eab54 100644 (file)
       // @param mailing Object (per APIv3)
       // @return Promise an object with "subject", "body_text", "body_html"
       preview: function preview(mailing) {
-        var params = angular.extend({}, mailing, mailing.recipients, {
-          options: {force_rollback: 1},
-          'api.Mailing.preview': {
-            id: '$value.id'
-          }
-        });
-        delete params.recipients; // the content was merged in
-        return crmApi('Mailing', 'create', params).then(function (result) {
-          // changes rolled back, so we don't care about updating mailing
-          return result.values[result.id]['api.Mailing.preview'].values;
-        });
+        if (CRM.crmMailing.workflowEnabled && !CRM.checkPerm('create mailings')) {
+          return crmApi('Mailing', 'preview', {id: mailing.id}).then(function(result) {
+            return result.values;
+          });
+        }
+        else {
+          // Protect against races in saving and previewing by chaining create+preview.
+          var params = angular.extend({}, mailing, mailing.recipients, {
+            options: {force_rollback: 1},
+            'api.Mailing.preview': {
+              id: '$value.id'
+            }
+          });
+          delete params.recipients; // the content was merged in
+          return crmApi('Mailing', 'create', params).then(function(result) {
+            // changes rolled back, so we don't care about updating mailing
+            return result.values[result.id]['api.Mailing.preview'].values;
+          });
+        }
       },
 
       // @param mailing Object (per APIv3)