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..a86c2fbc5 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") && $this->getRequest()->getQuery("op")) {
+ // 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 '
-
-
- ';
-
- foreach(array_keys($vv_email_addresses) as $addr) {
- $verified = isset($vv_verified_addresses[$addr]) && $vv_verified_addresses[$addr];
-
- $button = "";
-
- if(!$verified) {
- // We're already in a form here, so we need to use a GET URL to not mess things up.
- // This also means we need to manually insert the token and petition ID, which is
- // a bit duplicative with templates/Standard/dispatch.php
-
- $url = [
- 'plugin' => 'CoreEnroller',
- 'controller' => 'email_verifiers',
- 'action' => 'dispatch',
- $vv_config->id,
- '?' => [
- 'op' => 'verify',
- 'petition_id' => $vv_petition->id,
- // We base64 encode the address partly to not have bare email addresses in URLs
- // and partly to avoid special characters (like dots) messing up the URL
- 'm' => StringUtilities::urlbase64encode($addr)
- ]
- ];
-
- if(isset($vv_token_ok) && $vv_token_ok && !empty($vv_petition->token)) {
- $url['?']['token'] = $vv_petition->token;
- }
-
- $button = $this->Html->link(__d('operation', 'verify'), $url);
- }
-
- print '
-