dev/core#1945 Fix recur access regression
authoreileen <emcnaughton@wikimedia.org>
Mon, 17 Aug 2020 09:17:09 +0000 (21:17 +1200)
committereileen <emcnaughton@wikimedia.org>
Wed, 19 Aug 2020 01:09:39 +0000 (13:09 +1200)
CRM/Contribute/Form/ContributionRecur.php
CRM/Contribute/Page/Tab.php
CRM/Core/Form.php

index 8378d60599d52861afc4c0f2ffacc04cd456b073..ef6a633f45e6393c1c465255a02245eacb91699b 100644 (file)
@@ -192,21 +192,22 @@ class CRM_Contribute_Form_ContributionRecur extends CRM_Core_Form {
    */
   protected function getSubscriptionContactID() {
     $sub = $this->getSubscriptionDetails();
-    return $sub->contact_id ?? FALSE;
+    return $sub->contact_id ? (int) $sub->contact_id : FALSE;
   }
 
   /**
    * Is this being used by a front end user to update their own recurring.
    *
    * @return bool
+   * @throws \CRM_Core_Exception
    */
   protected function isSelfService() {
-    if (!is_null($this->selfService)) {
+    if ($this->selfService !== NULL) {
       return $this->selfService;
     }
     $this->selfService = FALSE;
     if (!CRM_Core_Permission::check('edit contributions')) {
-      if ($this->_subscriptionDetails->contact_id != $this->getContactID()) {
+      if ($this->getSubscriptionContactID() !== $this->getContactIDIfAccessingOwnRecord()) {
         CRM_Core_Error::statusBounce(ts('You do not have permission to cancel this recurring contribution.'));
       }
       $this->selfService = TRUE;
index 0a5a4f67e5050380abb9a9bc2ff4349daa7ae41b..fac5a250bc7bf7907cd5913985a540ca8754268a 100644 (file)
@@ -86,7 +86,11 @@ class CRM_Contribute_Page_Tab extends CRM_Core_Page {
           ];
         }
 
-        if (!$paymentProcessorObj->supports('ChangeSubscriptionAmount') && !$paymentProcessorObj->supports('EditRecurringContribution')) {
+        if (
+        (!CRM_Core_Permission::check('edit contributions') && $context === 'contribution') ||
+        (!$paymentProcessorObj->supports('ChangeSubscriptionAmount')
+          && !$paymentProcessorObj->supports('EditRecurringContribution')
+        )) {
           unset($links[CRM_Core_Action::UPDATE]);
         }
       }
index 158a6eedbb51adf1329769869710479e33671bc0..fe06bb9915289b3ba8f27b36e1d7c62758aca263 100644 (file)
@@ -2235,11 +2235,13 @@ class CRM_Core_Form extends HTML_QuickForm_Page {
 
   /**
    * Get the contact id of the logged in user.
+   *
+   * @return int|false
    */
   public function getLoggedInUserContactID() {
     // check if the user is logged in and has a contact ID
     $session = CRM_Core_Session::singleton();
-    return $session->get('userID');
+    return $session->get('userID') ? (int) $session->get('userID') : FALSE;
   }
 
   /**
@@ -2263,6 +2265,7 @@ class CRM_Core_Form extends HTML_QuickForm_Page {
    *   - id_field
    *   - url (for ajax lookup)
    *
+   * @throws \CRM_Core_Exception
    * @todo add data attributes so we can deal with multiple instances on a form
    */
   public function addAutoSelector($profiles = [], $autoCompleteField = []) {
@@ -2656,4 +2659,26 @@ class CRM_Core_Form extends HTML_QuickForm_Page {
     }
   }
 
+  /**
+   * Get the contact if from the url, using the checksum or the cid if it is the logged in user.
+   *
+   * This function returns the user being validated. It is not intended to get another user
+   * they have permission to (setContactID does do that) and can be used to check if the user is
+   * accessing their own record.
+   *
+   * @return int|false
+   * @throws \CRM_Core_Exception
+   */
+  protected function getContactIDIfAccessingOwnRecord() {
+    $contactID = (int) CRM_Utils_Request::retrieve('cid', 'Positive', $this);
+    if (!$contactID) {
+      return FALSE;
+    }
+    if ($contactID === $this->getLoggedInUserContactID()) {
+      return $contactID;
+    }
+    $userChecksum = CRM_Utils_Request::retrieve('cs', 'String', $this);
+    return CRM_Contact_BAO_Contact_Utils::validChecksum($contactID, $userChecksum) ? $contactID : FALSE;
+  }
+
 }