diff --git a/app/plugins/CoreEnroller/config/routes.php b/app/plugins/CoreEnroller/config/routes.php new file mode 100644 index 000000000..1cfe2b477 --- /dev/null +++ b/app/plugins/CoreEnroller/config/routes.php @@ -0,0 +1,53 @@ +plugin( + 'CoreEnroller', + ['path' => '/core-enroller/'], + function ($routes) { + $routes->setRouteClass(DashedRoute::class); + + $routes->get( + 'email-verifiers/resend', + [ + 'plugin' => 'CoreEnroller', + 'controller' => 'EmailVerifiers', + 'action' => 'resend', + ]) + ->setPass(['id']) + ->setPatterns(['id' => '[0-9]+']); + } +); \ No newline at end of file diff --git a/app/plugins/CoreEnroller/resources/locales/en_US/core_enroller.po b/app/plugins/CoreEnroller/resources/locales/en_US/core_enroller.po index 5a41e73cb..0a1f6f085 100644 --- a/app/plugins/CoreEnroller/resources/locales/en_US/core_enroller.po +++ b/app/plugins/CoreEnroller/resources/locales/en_US/core_enroller.po @@ -98,7 +98,22 @@ msgid "information.EmailVerifiers.A" msgstr "The following email addresses have been found in this Petition. You must verify all of them in order to proceed to the next Enrollment Step." msgid "information.EmailVerifiers.code_sent" -msgstr "A code has been sent to {0}. Please enter it below. You may also request a new code if you haven't received it after a few minutes, or cancel verification and return to the list of available Email Addresses." +msgstr "A code has been sent to {0}. Please enter it below. You may also request a new code if you haven't received it after a few minutes, or cancel verification and return to the list of available Email Addresses." + +msgid "information.EmailVerifiers.resend-pre-text" +msgstr "Didn't receive the code?" + +msgid "information.EmailVerifiers.resend" +msgstr "Resend" + +msgid "information.EmailVerifiers.sending" +msgstr "Sending" + +msgid "information.EmailVerifiers.success" +msgstr "New Code Submitted!" + +msgid "information.EmailVerifiers.abort" +msgstr "Abort" msgid "field.AttributeCollectors.valid_through.default.after.desc" msgstr "Days After Finalization" @@ -257,4 +272,7 @@ msgid "result.InvitationAccepters.declined" msgstr "Invitation Declined at {0}" msgid "result.InvitationAccepters.none" -msgstr "No response to invitation yet" \ No newline at end of file +msgstr "No response to invitation yet" + +msgid "op.EmailVerifiers.verify" +msgstr "Verify Email" \ No newline at end of file diff --git a/app/plugins/CoreEnroller/src/Controller/EmailVerifiersController.php b/app/plugins/CoreEnroller/src/Controller/EmailVerifiersController.php index 23dd271df..ac86386d9 100644 --- a/app/plugins/CoreEnroller/src/Controller/EmailVerifiersController.php +++ b/app/plugins/CoreEnroller/src/Controller/EmailVerifiersController.php @@ -29,6 +29,7 @@ namespace CoreEnroller\Controller; +use Cake\Http\Exception\BadRequestException; use Cake\ORM\TableRegistry; use App\Controller\StandardEnrollerController; use App\Lib\Enum\PetitionStatusEnum; @@ -60,9 +61,58 @@ public function beforeRender(\Cake\Event\EventInterface $event) { $this->set('vv_bc_parent_primarykey', $this->EmailVerifiers->EnrollmentFlowSteps->getPrimaryKey()); } + if ($this->getRequest()->getQuery("op") == "verify" || $this->getRequest()->getQuery("op") == "index") { + // This will suppress the default behavior. By default, we print the submit button in the + // unorderedList.php element. But for the verify view we want to override and customize + $this->set('suppress_submit', true); + } + return parent::beforeRender($event); } + /** + * Resend the email verification request. + * + * @param string $id Email Verifier ID + * @throws BadRequestException If the request is not AJAX + * @throws \InvalidArgumentException If required query parameters are missing + * @return void + * @since COmanage Registry v5.1.0 + */ + public function resend($id) + { + + $this->viewBuilder()->setClassName('Json'); + + if (!$this->getRequest()->is('ajax')) { + throw new BadRequestException(__('Bad Request')); + } + + if (!$this->getRequest()->getQuery('petition_id') || !$this->getRequest()->getQuery('m')) { + throw new \InvalidArgumentException(__('error', 'invalid.request')); + } + + // Generate a Verification request and send it + $Petitions = TableRegistry::getTableLocator()->get('Petitions'); + $petition = $Petitions->get($this->getRequest()->getQuery('petition_id')); + $cfg = $this->EmailVerifiers->get($id); + $mail = StringUtilities::urlbase64decode($this->requestParam('m')); + $status = $this->EmailVerifiers->sendVerificationRequest($cfg, $petition, $mail, true); + + if ($status) { + return $this->response + ->withType('application/json') + ->withStatus(200) + ->withStringBody(json_encode(['status' => 'ok'])); + } + + + return $this->response + ->withType('application/json') + ->withStatus(501) + ->withStringBody(json_encode(['status' => 'failed'])); + } + /** * Dispatch an Enrollment Flow Step. * diff --git a/app/plugins/CoreEnroller/src/Model/Table/EmailVerifiersTable.php b/app/plugins/CoreEnroller/src/Model/Table/EmailVerifiersTable.php index c515f1f0b..4f64ed4ef 100644 --- a/app/plugins/CoreEnroller/src/Model/Table/EmailVerifiersTable.php +++ b/app/plugins/CoreEnroller/src/Model/Table/EmailVerifiersTable.php @@ -85,7 +85,7 @@ public function initialize(array $config): void { $this->setPrimaryLink('enrollment_flow_step_id'); $this->setRequiresCO(true); - $this->setAllowLookupPrimaryLink(['dispatch', 'display']); + $this->setAllowLookupPrimaryLink(['dispatch', 'display', 'resend']); // All the tabs share the same configuration in the ModelTable file $this->setTabsConfig( @@ -112,6 +112,14 @@ public function initialize(array $config): void { 'type' => 'select', 'model' => 'MessageTemplates', 'where' => ['context' => \App\Lib\Enum\MessageTemplateContextEnum::Verification] + ], + 'cosettings' => [ + 'type' => 'auxiliary', + 'model' => 'CoSettings' + ], + 'types' => [ + 'type' => 'auxiliary', + 'model' => 'Types' ] ]); @@ -122,6 +130,7 @@ public function initialize(array $config): void { 'dispatch' => true, 'display' => true, 'edit' => ['platformAdmin', 'coAdmin'], + 'resend' => true, 'view' => ['platformAdmin', 'coAdmin'] ], // Actions that operate over a table (ie: do not require an $id) @@ -412,8 +421,10 @@ public function prepare( public function sendVerificationRequest( EmailVerifier $emailVerifier, Petition $petition, - string $mail - ) { + string $mail, + bool $resend = false, + ): bool + { // First check if there is already an existing Petition Verification. // If so, use that to get the existing Verification. @@ -427,21 +438,7 @@ public function sendVerificationRequest( ]) ->first(); - if(!empty($pVerification)) { - // Request a new code - - $this->llog('debug', "Sending replacement verification code to $mail for Petition " . $petition->id); - - $verificationId = $Verifications->requestCodeForPetition( - $petition->id, - $mail, - $emailVerifier->message_template_id, - $emailVerifier->request_validity, - $pVerification->verification_id - ); - - // There's nothing to update in the Petition Verification - } else { + if (empty($pVerification)) { // Request Verification and create an associated Petition Verification $this->llog('debug', "Sending verification code to $mail for Petition " . $petition->id); @@ -458,8 +455,28 @@ public function sendVerificationRequest( 'petition_id' => $petition->id, 'mail' => $mail, 'verification_id' => $verificationId - ])); + ])); + return true; } + + if ($resend) { + // Request a new code + + $this->llog('debug', "Sending replacement verification code to $mail for Petition " . $petition->id); + + $verificationId = $Verifications->requestCodeForPetition( + $petition->id, + $mail, + $emailVerifier->message_template_id, + $emailVerifier->request_validity, + $pVerification->verification_id + ); + // There's nothing to update in the Petition Verification + + return true; + } + + return false; } /** diff --git a/app/plugins/CoreEnroller/templates/EmailVerifiers/dispatch.inc b/app/plugins/CoreEnroller/templates/EmailVerifiers/dispatch.inc index 62b3b9c4e..c76132611 100644 --- a/app/plugins/CoreEnroller/templates/EmailVerifiers/dispatch.inc +++ b/app/plugins/CoreEnroller/templates/EmailVerifiers/dispatch.inc @@ -27,121 +27,21 @@ declare(strict_types = 1); -use CoreEnroller\Lib\Enum\VerificationModeEnum; -use App\Lib\Util\StringUtilities; - print $this->element('flash', []); // This view is intended to work with dispatch -if($vv_action == 'dispatch') { - if($vv_op == 'index') { - // Render the list of known email addresses and their verification statuses. - // The configuration drives how many email addresses are required to complete this step. - - print '
'; - - if($vv_all_done) { - print __d('core_enroller', 'information.EmailVerifiers.done'); - } else { - switch($vv_config->mode) { - case VerificationModeEnum::All: - print __d('core_enroller', 'information.EmailVerifiers.A'); - break; - case VerificationModeEnum::None: - print __d('core_enroller', 'information.EmailVerifiers.0'); - break; - case VerificationModeEnum::One: - if($vv_minimum_met) { - print __d('core_enroller', 'information.EmailVerifiers.1.met'); - } else { - print __d('core_enroller', 'information.EmailVerifiers.1.none'); - } - break; - } - } - - print '
'; - - print ' -| ' . __d('controller', 'EmailAddresses', [1]) . ' | -' . __d('field', 'status') . ' | -
|---|---|
| ' . $addr . ' | -' . __d('result', ($verified ? 'verified' : 'verified.not')) . $button . ' | -
= $title ?>
+| = __d('controller', 'EmailAddresses', [1]) ?> | += __d('field', 'status') ?> | +
|---|---|
| = $addr ?> | ++ + = __d('result', 'verified') ?> + + = __d('field', 'unverified')?> + = $button; ?> + + | +