From 8ec4b7b09459be4224d4fbb1aa1699af14e2d215 Mon Sep 17 00:00:00 2001 From: Seamus Lee Date: Tue, 14 Nov 2023 08:58:09 +1100 Subject: [PATCH] dev/core#4768 Fix validating contact when using checksum url Fix type error failures --- CRM/Core/Form.php | 18 ++++++++++--- CRM/Event/Form/SelfSvcTransfer.php | 13 ++++++--- .../CRM/Event/Form/SelfSvcTransferTest.php | 27 +++++++++++++++++++ 3 files changed, 51 insertions(+), 7 deletions(-) diff --git a/CRM/Core/Form.php b/CRM/Core/Form.php index 07e15afea7..10382406df 100644 --- a/CRM/Core/Form.php +++ b/CRM/Core/Form.php @@ -2477,7 +2477,7 @@ class CRM_Core_Form extends HTML_QuickForm_Page { * Ideally the forms would override this so only the cid in the url * would be checked in the shared form function. * - * @return int + * @return int|null * @throws \CRM_Core_Exception */ public function getRequestedContactID(): ?int { @@ -2526,9 +2526,21 @@ class CRM_Core_Form extends HTML_QuickForm_Page { */ protected function getAuthenticatedCheckSumContactID(): int { $requestedContactID = $this->getRequestedContactID(); + return $this->validateAuthenticatedCheckSumContactID($requestedContactID); + } + + /** + * Verify that a contact ID is authenticated as a valid contact by checksum + * + * @param int|null $contactID + * + * @return int + * @throws \CRM_Core_Exception + */ + protected function validateAuthenticatedCheckSumContactID(?int $contactID): int { $userChecksum = CRM_Utils_Request::retrieve('cs', 'String', $this); - if ($userChecksum && CRM_Contact_BAO_Contact_Utils::validChecksum($requestedContactID, $userChecksum)) { - return $requestedContactID; + if ($userChecksum && CRM_Contact_BAO_Contact_Utils::validChecksum($contactID, $userChecksum)) { + return $contactID; } return 0; } diff --git a/CRM/Event/Form/SelfSvcTransfer.php b/CRM/Event/Form/SelfSvcTransfer.php index 50e43054e9..eafb8fd202 100644 --- a/CRM/Event/Form/SelfSvcTransfer.php +++ b/CRM/Event/Form/SelfSvcTransfer.php @@ -125,7 +125,7 @@ class CRM_Event_Form_SelfSvcTransfer extends CRM_Core_Form { $this->_event_id = $this->_part_values['event_id']; $url = CRM_Utils_System::url('civicrm/event/info', "reset=1&id={$this->_event_id}"); $this->define('Contact', 'ContactFrom', ['id' => (int) $this->_part_values['participant_contact_id']]); - if (!$this->getAuthenticatedCheckSumContactID() && !CRM_Core_Permission::check('edit all events')) { + if (!$this->validateAuthenticatedCheckSumContactID($this->lookup('ContactFrom', 'id')) && !CRM_Core_Permission::check('edit all events')) { CRM_Core_Error::statusBounce(ts('You do not have sufficient permission to transfer/cancel this participant.'), $url); } $this->assign('action', $this->_action); @@ -154,9 +154,14 @@ class CRM_Event_Form_SelfSvcTransfer extends CRM_Core_Form { } // for front-end user show and use the basic three fields used to create a contact else { - $this->add('text', 'email', ts('To Email'), $this->lookup('ContactFrom', 'email_primary.email'), TRUE); - $this->add('text', 'last_name', ts('To Last Name'), $this->_to_contact_last_name, TRUE); - $this->add('text', 'first_name', ts('To First Name'), $this->_to_contact_first_name, TRUE); + $this->add('text', 'email', ts('To Email'), NULL, TRUE); + $this->add('text', 'last_name', ts('To Last Name'), NULL, TRUE); + $this->add('text', 'first_name', ts('To First Name'), NULL, TRUE); + $this->setDefaults([ + 'email' => $this->lookup('ContactFrom', 'email_primary.email'), + 'last_name' => $this->_to_contact_last_name, + 'first_name' => $this->_to_contact_first_name, + ]); } $this->addButtons([ diff --git a/tests/phpunit/CRM/Event/Form/SelfSvcTransferTest.php b/tests/phpunit/CRM/Event/Form/SelfSvcTransferTest.php index aef377b510..a0c2a09eb1 100644 --- a/tests/phpunit/CRM/Event/Form/SelfSvcTransferTest.php +++ b/tests/phpunit/CRM/Event/Form/SelfSvcTransferTest.php @@ -33,4 +33,31 @@ class CRM_Event_Form_SelfSvcTransferTest extends CiviUnitTestCase { $this->assertStringContainsString('fixme.domainemail@example.org', $emails[1]); } + /** + * Test Transfer as anonymous + */ + public function testTransferAnonymous(): void { + CRM_Core_Session::singleton()->getStatus(TRUE); + $event = $this->eventCreateUnpaid(['start_date' => date('Ymd', strtotime('+2 month')), 'end_date' => date('Ymd', strtotime('+2 month')), 'registration_end_date' => date('Ymd', strtotime('+1 month')), 'allow_selfcancelxfer' => 1]); + $_REQUEST['pid'] = $this->participantCreate(['status_id' => 'Registered', 'event_id' => $event['id']]); + $_REQUEST['cs'] = CRM_Contact_BAO_Contact_Utils::generateChecksum($this->callAPISuccess('Participant', 'getsingle', ['id' => $_REQUEST['pid']])['contact_id']); + $_REQUEST['is_backoffice'] = 0; + $this->addLocationBlockToDomain(); + $this->individualCreate(['email' => 'new2@example.org']); + CRM_Core_Config::singleton()->userPermissionClass->permissions = []; + /** @var CRM_Event_Form_SelfSvcTransfer $form*/ + $form = $this->getFormObject('CRM_Event_Form_SelfSvcTransfer', [ + 'first_name' => 'test', + 'last_name' => 'selftransfer', + 'email' => 'new2@example.org', + ]); + $form->buildForm(); + try { + $form->postProcess(); + } + catch (CRM_Core_Exception_PrematureExitException $e) { + $this->assertEquals('Registration Transferred', CRM_Core_Session::singleton()->getStatus()[1]['title']); + } + } + } -- 2.25.1