comanage-dev - [comanage-dev] r654 - in registry/trunk/app: Config/Schema Controller Lib Model View/CoInvites View/EmailAddresses View/Layouts
Subject: COmanage Developers List
List archive
[comanage-dev] r654 - in registry/trunk/app: Config/Schema Controller Lib Model View/CoInvites View/EmailAddresses View/Layouts
Chronological Thread
- From:
- To:
- Subject: [comanage-dev] r654 - in registry/trunk/app: Config/Schema Controller Lib Model View/CoInvites View/EmailAddresses View/Layouts
- Date: Tue, 31 Dec 2013 19:55:27 -0500
Author: benno
Date: 2013-12-31 19:55:27 -0500 (Tue, 31 Dec 2013)
New Revision: 654
Added:
registry/trunk/app/View/CoInvites/verify_email_address.ctp
Modified:
registry/trunk/app/Config/Schema/schema.xml
registry/trunk/app/Controller/CoInvitesController.php
registry/trunk/app/Controller/EmailAddressesController.php
registry/trunk/app/Lib/enum.php
registry/trunk/app/Lib/lang.php
registry/trunk/app/Model/CoInvite.php
registry/trunk/app/Model/EmailAddress.php
registry/trunk/app/View/CoInvites/reply.ctp
registry/trunk/app/View/EmailAddresses/fields.inc
registry/trunk/app/View/Layouts/default.ctp
Log:
Implement "Verify This Address" (CO-462)
Modified: registry/trunk/app/Config/Schema/schema.xml
===================================================================
--- registry/trunk/app/Config/Schema/schema.xml 2013-12-26 19:11:12 UTC (rev
653)
+++ registry/trunk/app/Config/Schema/schema.xml 2014-01-01 00:55:27 UTC (rev
654)
@@ -306,6 +306,9 @@
<notnull />
</field>
<field name="mail" type="C" size="256" />
+ <field name="email_address_id" type="I">
+ <constraint>REFERENCES cm_email_addresses(id)</constraint>
+ </field>
<field name="expires" type="T" />
<field name="created" type="T" />
<field name="modified" type="T" />
Modified: registry/trunk/app/Controller/CoInvitesController.php
===================================================================
--- registry/trunk/app/Controller/CoInvitesController.php 2013-12-26
19:11:12 UTC (rev 653)
+++ registry/trunk/app/Controller/CoInvitesController.php 2014-01-01
00:55:27 UTC (rev 654)
@@ -35,6 +35,8 @@
)
);
+ public $uses = array('CoInvite', 'CoOrgIdentityLink', 'EmailAddress');
+
// This controller needs a CO to be set, but only for send
public $requires_co = false;
@@ -67,6 +69,23 @@
}
/**
+ * Verify the email address, requiring authentication
+ * - precondition: $invite must exist, be valid, and attached to a valid
CO person
+ * - postcondition: Email Address set to valid
+ * - postcondition: $inviteid deleted
+ * - postcondition: Session flash message updated (HTML)
+ *
+ * @since COmanage Registry v0.9
+ * @param Integer Invitation ID
+ */
+
+ public function authverify($inviteid) {
+ // We basically do the same thing as authconfirm().
+
+ $this->process_invite($inviteid, true,
$this->Session->read('Auth.User.username'));
+ }
+
+ /**
* Callback before other controller methods are invoked or views are
rendered.
* - postcondition: Auth component is configured
*
@@ -198,8 +217,11 @@
// Send an invite? (REST only)
$p['add'] = $roles['apiuser'];
- // Confirm an invite? (HTML, auth reequired)
+ // Confirm an invite? (HTML, auth required)
$p['authconfirm'] = true;
+
+ // Verify an email address?
+ $p['authverify'] = true;
// Confirm an invite? (HTML only)
$p['confirm'] = true;
@@ -218,6 +240,13 @@
$p['send'] = ($roles['cmadmin']
|| ($managed && ($roles['coadmin'] ||
$roles['couadmin'])));
+ // Request verification of an email address?
+ // This needs to correlate with EmailAddressesController
+ $p['verifyEmailAddress'] =
(!empty($this->request->params['named']['email_address_id'])
+ ?
$this->Role->canRequestVerificationOfEmailAddress($roles['copersonid'],
+
$this->request->params['named']['email_address_id'])
+ : false);
+
$this->set('permissions', $p);
return $p[$this->action];
}
@@ -256,6 +285,8 @@
}
} else {
$this->Session->setFlash($e->getMessage(), '', array(), 'error');
+ $this->redirect("/");
+ return;
}
}
catch(OutOfBoundsException $e) {
@@ -263,6 +294,8 @@
$this->restResultHeader(403, "Expired");
} else {
$this->Session->setFlash($e->getMessage(), '', array(), 'error');
+ $this->redirect("/");
+ return;
}
}
catch(Exception $e) {
@@ -275,6 +308,8 @@
$this->restResultHeader(500, "Other Error");
} else {
$this->Session->setFlash($e->getMessage(), '', array(), 'error');
+ $this->redirect("/");
+ return;
}
}
}
@@ -287,7 +322,7 @@
$targetUrl = null;
- if(isset($invite['CoPetition']['id'])) {
+ if(!empty($invite['CoPetition']['id'])) {
$targetUrl =
$this->CoInvite->CoPetition->CoEnrollmentFlow->field('redirect_on_confirm',
array('CoEnrollmentFlow.id' =>
$invite['CoPetition']['co_enrollment_flow_id']));
}
@@ -299,14 +334,21 @@
// Make sure the petition ID is available in the session.
$this->Session->write('CoPetition.id', $invite['CoPetition']['id']);
$this->redirect($targetUrl);
- } elseif($loginIdentifier) {
+ } else {
+ if(!empty($invite['CoPetition']['id']) && $loginIdentifier) {
+ $this->Session->setFlash(_txt('rs.pt.relogin'), '', array(),
'success');
+ } elseif(!empty($invite['CoInvite']['email_address_id'])) {
+ $this->Session->setFlash($confirm ? _txt('rs.ev.ver') :
_txt('rs.ev.cxl'), '', array(), 'success');
+ } else {
+ $this->Session->setFlash($confirm ? _txt('rs.inv.conf') :
_txt('rs.inv.dec'), '', array(), 'success');
+ }
+
// If a login identifier was provided, force a logout
-
- $this->Session->setFlash(_txt('rs.pt.relogin'), '', array(),
'success');
- $this->redirect("/auth/logout");
- } else {
- $this->Session->setFlash($confirm ? _txt('rs.inv.conf') :
_txt('rs.inv.dec'), '', array(), 'success');
- $this->redirect("/");
+ if($loginIdentifier) {
+ $this->redirect("/auth/logout");
+ } else {
+ $this->redirect("/");
+ }
}
}
}
@@ -325,18 +367,12 @@
*/
function reply($inviteid) {
- if(!$this->restful)
- {
- // Set page title
- $this->set('title_for_layout', _txt('op.inv.reply'));
- }
-
$invite = $this->CoInvite->findByInvitation($inviteid);
- if(!$invite)
+ if(!$invite) {
$this->Session->setFlash(_txt('er.inv.nf'), '', array(), 'error');
- else
- {
+ // XXX what if this->restful?
+ } else {
// Database foreign key constraints should prevent inconsistencies
here, so extra
// error checking shouldn't be needed
@@ -347,6 +383,15 @@
$this->set('invite', $invite);
$this->set('invitee', $invitee);
+ if(!$this->restful) {
+ // Set page title
+ if(!empty($invite['CoInvite']['email_address_id'])) {
+ $this->set('title_for_layout', _txt('fd.ev.verify',
array($invite['EmailAddress']['mail'])));
+ } else {
+ $this->set('title_for_layout', _txt('fd.inv.to',
array($co['Co']['name'])));
+ }
+ }
+
// We also want to pull the enrollment flow and petition attributes,
if appropriate
if(isset($invite['CoPetition']['id'])) {
@@ -399,7 +444,6 @@
* - postcondition: Session flash message updated (HTML) or HTTP status
returned (REST)
*
* @since COmanage Registry v0.1
- * @param Integer ID invitation
*/
function send() {
@@ -561,4 +605,101 @@
$this->redirect($nextPage);
}
}
+
+ /**
+ * Send an email address verification request.
+ * - precondition: $this->request->params holds Email Address ID to verify
+ * - postcondition: Email invitation sent to address
+ * - postcondition: Session flash message updated (HTML) or HTTP status
returned (REST)
+ *
+ * @since COmanage Registry v0.9
+ * @todo Add rest support
+ */
+
+ public function verifyEmailAddress() {
+ if(!empty($this->request->params['named']['email_address_id'])) {
+ $args = array();
+ $args['conditions']['EmailAddress.id'] =
$this->request->params['named']['email_address_id'];
+ $args['contain'] = false;
+
+ $ea = $this->EmailAddress->find('first', $args);
+
+ if(!empty($ea)) {
+ // We currently need a CO Person ID, even if verifying an org
identity email address.
+ // CoInvite stores the CO Person ID and uses the Org Identity ID in
generating history.
+ // For now, we'll just map using co_org_identity_links and hope we
pull the right
+ // record. This should get fixed as part of CO-753.
+
+ $largs = array();
+ $largs['contain'] = false;
+
+ if(!empty($ea['EmailAddress']['co_person_id'])) {
+ $largs['conditions']['CoOrgIdentityLink.co_person_id'] =
$ea['EmailAddress']['co_person_id'];
+ } elseif(!empty($ea['EmailAddress']['org_identity_id'])) {
+ $largs['conditions']['CoOrgIdentityLink.org_identity_id'] =
$ea['EmailAddress']['org_identity_id'];
+ }
+
+ $lnk = $this->CoOrgIdentityLink->find('first', $largs);
+
+ if(!empty($lnk)) {
+ if($this->restful) {
+ // XXX implement this (CO-754)
+ throw new RuntimeException("Not implemented");
+ } else {
+ try {
+
$this->CoInvite->send($lnk['CoOrgIdentityLink']['co_person_id'],
+
$lnk['CoOrgIdentityLink']['org_identity_id'],
+
$this->Session->read('Auth.User.co_person_id'),
+ $ea['EmailAddress']['mail'],
+ null, // use default from address
+ (!empty($this->cur_co['Co']['name']) ?
$this->cur_co['Co']['name'] : _txt('er.unknown')),
+ _txt('em.invite.subject.ver'),
+ _txt('em.invite.body.ver'),
+ $ea['EmailAddress']['id']);
+
+ $this->set('vv_co_invite',
$this->CoInvite->findById($this->CoInvite->id));
+ $this->set('vv_recipient', $ea);
+
+ $this->Session->setFlash(_txt('rs.ev.sent',
array($ea['EmailAddress']['mail'])), '', array(), 'success');
+ }
+ catch(Exception $e) {
+ $this->Session->setFlash($e->getMessage(), '', array(),
'error');
+ }
+
+ $debug = Configure::read('debug');
+
+ if(!$debug) {
+ if(!empty($ea['EmailAddress']['co_person_id'])) {
+ // Redirect to the CO Person view
+ $nextPage = array('controller' => 'co_people',
+ 'action' => 'edit',
+ $lnk['CoOrgIdentityLink']['co_person_id']);
+ } elseif(!empty($ea['EmailAddress']['org_identity_id'])) {
+ // Redirect to the CO Person view
+ $nextPage = array('controller' => 'org_identity_id',
+ 'action' => 'edit',
+
$lnk['CoOrgIdentityLink']['org_identity_id']);
+ }
+
+ if(!empty($this->cur_co['Co']['id'])) {
+ $nextPage['co'] = $this->cur_co['Co']['id'];
+ }
+ $nextPage['tab'] = 'email';
+
+ $this->redirect($nextPage);
+ }
+ }
+ } else {
+ $this->Session->setFlash(_txt('er.person.noex'), '', array(),
'error');
+ }
+ } else {
+ $this->Session->setFlash(_txt('er.notfound',
+ array(_txt('ct.email_addresses.1'),
+
Sanitize::html($this->request->params['named']['email_address_id']))),
+ '', array(), 'error');
+ }
+ } else {
+ $this->Session->setFlash(_txt('er.notprov.id',
array(_txt('ct.email_addresses.1'))), '', array(), 'error');
+ }
+ }
}
Modified: registry/trunk/app/Controller/EmailAddressesController.php
===================================================================
--- registry/trunk/app/Controller/EmailAddressesController.php 2013-12-26
19:11:12 UTC (rev 653)
+++ registry/trunk/app/Controller/EmailAddressesController.php 2014-01-01
00:55:27 UTC (rev 654)
@@ -134,6 +134,11 @@
// Currently only supported via REST since there's no use case for
viewing all
$p['index'] = $this->restful && ($roles['cmadmin'] || $roles['coadmin']);
+ // Generate an email verification request?
+ // This needs to correlate with CoInvitesController.
+ $p['verifyEmailAddress'] =
$this->Role->canRequestVerificationOfEmailAddress($roles['copersonid'],
+
$this->request->params['pass'][0]);
+
// View an existing Email Address?
$p['view'] = ($roles['cmadmin']
|| ($managed && ($roles['coadmin'] || $roles['couadmin']))
@@ -142,5 +147,4 @@
$this->set('permissions', $p);
return $p[$this->action];
}
-
}
Modified: registry/trunk/app/Lib/enum.php
===================================================================
--- registry/trunk/app/Lib/enum.php 2013-12-26 19:11:12 UTC (rev 653)
+++ registry/trunk/app/Lib/enum.php 2014-01-01 00:55:27 UTC (rev 654)
@@ -45,9 +45,12 @@
const CoTAndCAgreement = 'TCAG';
const CoTAndCAgreementBehalf = 'TCAB';
const EmailAddressVerified = 'EMLV';
+ const EmailAddressVerifyCanceled = 'EMLC';
+ const EmailAddressVerifyReqSent = 'EMLS';
const IdentifierAutoAssigned = 'AIDA';
const InvitationConfirmed = 'INVC';
const InvitationDeclined = 'INVD';
+ const InvitationExpired = 'INVE';
const InvitationSent = 'INVS';
const NameAdded = 'ANAM';
const NameDeleted = 'DNAM';
Modified: registry/trunk/app/Lib/lang.php
===================================================================
--- registry/trunk/app/Lib/lang.php 2013-12-26 19:11:12 UTC (rev 653)
+++ registry/trunk/app/Lib/lang.php 2014-01-01 00:55:27 UTC (rev 654)
@@ -123,11 +123,18 @@
'em.approval.body.ef' => 'Your petition to join (@CO_NAME) as been
approved. You may now log in to the platform.',
'em.invite.subject' => 'Invitation to join %1$s',
'em.invite.subject.ef' => 'Invitation to join (@CO_NAME)',
+ 'em.invite.subject.ver' => 'Please confirm your email address
(@CO_NAME)',
'em.invite.body' => 'You have been invited to join %1$s. Please
click the link below to accept or decline.',
'em.invite.body.ef' => 'You have been invited to join (@CO_NAME).
Please click the link below to accept or decline.
(@INVITE_URL)',
+ 'em.invite.body.ver' => 'You or an administrator for @CO_NAME has
added or updated an email address.
+Please click the link below to confirm that this is a valid request.
+
+(@INVITE_URL)
+
+For questions regarding this process, please contact your administrator.',
'em.invite.ok' => 'Invitation has been emailed to %1$s',
'em.invite.footer' => 'This email was sent using %1$s.',
@@ -152,9 +159,12 @@
ActionEnum::CoPersonOrgIdLinked => 'CO Person and Org Identity
Linked',
ActionEnum::CoPersonOrgIdUnlinked => 'CO Person and Org Identity
Unlinked',
ActionEnum::EmailAddressVerified => 'Email Address Verified',
+ ActionEnum::EmailAddressVerifyCanceled => 'Email Address Verification
Canceled',
+ ActionEnum::EmailAddressVerifyReqSent => 'Email Address Verification
Sent',
ActionEnum::IdentifierAutoAssigned => 'Identifier Auto Assigned',
ActionEnum::InvitationConfirmed => 'Invitation Confirmed',
ActionEnum::InvitationDeclined => 'Invitation Declined',
+ ActionEnum::InvitationExpired => 'Invitation Expired',
ActionEnum::InvitationSent => 'Invitation Sent',
ActionEnum::OrgIdAddedManual => 'Org Identity Created
(Manual)',
ActionEnum::OrgIdAddedPetition => 'Org Identity Created
(Petition)',
@@ -415,6 +425,7 @@
'er.ia.none' => 'No identifier assignments configured',
'er.id.unk' => 'Unknown Identifier',
'er.inv.exp' => 'Invitation Expired',
+ 'er.inv.exp.use' => 'Processing of invitation failed due to invitation
expiration',
'er.inv.nf' => 'Invitation Not Found',
'er.loc.exists' => 'A localization already exists for the key "%1$s" and
language "%2$s"',
'er.nd.already' => 'NSF Demographic data already exists for this person',
@@ -564,13 +575,16 @@
'fd.ef.vsub' => 'Subject For Verification Email',
'fd.ef.vsub.desc' => 'Subject line for email message sent as part of
verification step.',
// (End enrollment configuration fields)
- 'fd.et.forattr' => 'For Attribute',
// This must be named fd.model.validation-field
'fd.email_address.mail' => 'Email',
'fd.email_address.verified' => 'Verified',
'fd.email_address.unverified' => 'Unverified',
'fd.email_address.verified.warn' => 'Editing a verified email address will
make it unverified',
'fd.enrollee' => 'Enrollee',
+ 'fd.et.forattr' => 'For Attribute',
+ 'fd.ev.for' => 'Verification for %1$s',
+ 'fd.ev.verify' => 'Verify email address %1$s',
+ 'fd.ev.verify.desc' => 'Please confirm %1$s is your email address by
clicking the <b>Confirm</b> button, below.',
'fd.false' => 'False',
'fd.group.desc.adm' => '%1$s Administrators',
'fd.group.grmem' => 'Group Member',
@@ -760,6 +774,7 @@
'op.tc.review.pt' => 'Review All Agreed To Terms and Conditions',
'op.unlink' => 'Unlink',
'op.unlink.confirm' => 'Are you sure you wish to unlink this identity?',
+ 'op.verify' => 'Verify',
'op.view' => 'View',
'op.view-a' => 'View %1$s',
'op.view-f' => 'View %1$s for %2$s',
@@ -769,6 +784,11 @@
'rs.added-a' => '"%1$s" Added',
'rs.added-a2' => '%1$s "%2$s" Added',
'rs.deleted-a2' => '%1$s "%2$s" Deleted',
+ 'rs.ev.cxl' => 'Verification of Email Address canceled',
+ 'rs.ev.cxl-a' => 'Verification of Email Address %1$s canceled',
+ 'rs.ev.sent' => 'Email verification request sent to %1$s',
+ 'rs.ev.ver' => 'Email Address verified',
+ 'rs.ev.ver-a' => 'Email Address %1$s verified by %2$s',
'rs.grm.added' => 'Added to CO Group %1$s (%2$s) (member=%3$s,
owner=%4$s)',
'rs.grm.deleted' => 'Removed from CO Group %1$s (%2$s)',
'rs.grm.edited' => 'Edited CO Group Roles %1$s (%2$s) (from member=%3$s,
owner=%4$s to member=%5$s, owner=%6$s)',
Modified: registry/trunk/app/Model/CoInvite.php
===================================================================
--- registry/trunk/app/Model/CoInvite.php 2013-12-26 19:11:12 UTC (rev
653)
+++ registry/trunk/app/Model/CoInvite.php 2014-01-01 00:55:27 UTC (rev
654)
@@ -35,7 +35,8 @@
public $actsAs = array('Containable');
// Association rules from this model to other models
- public $belongsTo = array("CoPerson"); // An invitation belongs to a CO
Person
+ public $belongsTo = array("CoPerson",
+ "EmailAddress");
public $hasOne = array("CoPetition");
@@ -60,6 +61,11 @@
'required' => false,
'allowEmpty' => true
),
+ 'email_address_id' => array(
+ 'rule' => 'numeric',
+ 'required' => false,
+ 'allowEmpty' => true
+ ),
'expires' => array(
'rule' => '/.*/', // The 'date' rule is too constraining
'required' => false,
@@ -90,10 +96,27 @@
$invite = $this->find('first', $args);
if(!empty($invite)) {
+ $verifyEmail = !empty($invite['CoInvite']['email_address_id']);
+
// Check invite validity
if(time() < strtotime($invite['CoInvite']['expires'])) {
- if(isset($invite['CoPetition']['id'])) {
+ if($verifyEmail) {
+ // Verifying an email address
+
+ try {
+ // XXX Note we're passing a bunch of stuff just so verify() can
create a history record,
+ // which we do below anyway. Refactor as part of CO-753.
+
$this->CoPerson->EmailAddress->verify($invite['EmailAddress']['org_identity_id'],
+
$invite['EmailAddress']['co_person_id'],
+
$invite['CoInvite']['mail'],
+
$invite['EmailAddress']['co_person_id']);
+ }
+ catch(Exception $e) {
+ $dbc->rollback();
+ throw new RuntimeException($e->getMessage());
+ }
+ } elseif(isset($invite['CoPetition']['id'])) {
// Let CoPetition handle the relevant updates
// We don't bother checking if confirm_email is still true, since
it's not really
@@ -192,7 +215,7 @@
if($orgId) {
try {
- $this->CoPerson->EmailAddress->verify($orgId,
$invite['CoInvite']['mail'], $invite['CoPetition']['enrollee_co_person_id']);
+ $this->CoPerson->EmailAddress->verify($orgId, null,
$invite['CoInvite']['mail'], $invite['CoPetition']['enrollee_co_person_id']);
}
catch(Exception $e) {
$dbc->rollback();
@@ -205,6 +228,21 @@
$this->delete($invite['CoInvite']['id']);
} else {
$this->delete($invite['CoInvite']['id']);
+
+ // Record a history record that the invitation expired
+ try {
+
$this->CoPerson->HistoryRecord->record($invite['CoInvite']['co_person_id'],
+ null,
+ null,
+ null,
+
ActionEnum::InvitationExpired,
+ _txt('er.inv.exp.use'));
+ }
+ catch(Exception $e) {
+ $dbc->rollback();
+ throw new RuntimeException($e->getMessage());
+ }
+
// Commit here, don't roll back!
$dbc->commit();
throw new OutOfBoundsException(_txt('er.inv.exp'));
@@ -212,13 +250,33 @@
// Create a history record
+ if($verifyEmail) {
+ // XXX Note that EmailAddress->verify() will also record almost the
same history message on success.
+ // This should probably be refactored as part of CO-753.
+ $hcopid = $invite['EmailAddress']['co_person_id'];
+ $hcoprid = null;
+ $horgid = $invite['EmailAddress']['org_identity_id'];
+ $hactorid = $hcopid; // XXX Should it be mapped from
$loginidentifier instead? (review as part of CO-753)
+ $hop = $confirm ? ActionEnum::EmailAddressVerified :
ActionEnum::EmailAddressVerifyCanceled;
+ $htxt = _txt(($confirm ? 'rs.ev.ver-a' : 'rs.ev.cxl-a'),
+ array($invite['EmailAddress']['mail'],
$loginIdentifier));
+ } else {
+ $hcopid = $invite['CoInvite']['co_person_id'];
+ $hcoprid =
isset($invite['CoPetition']['enrollee_co_person_role_id']) ?
$invite['CoPetition']['enrollee_co_person_role_id'] : null;
+ $horgid = isset($invite['CoPetition']['enrollee_org_identity_id']) ?
$invite['CoPetition']['enrollee_org_identity_id'] : null;
+ $hactorid = $invite['CoPetition']['enrollee_co_person_id'];
+ $hop = $confirm ? ActionEnum::InvitationConfirmed :
ActionEnum::InvitationDeclined;
+ $htxt = _txt(($confirm ? 'rs.inv.conf-a' : 'rs.inv.dec-a'),
+ array($invite['CoInvite']['mail']));
+ }
+
try {
-
$this->CoPerson->HistoryRecord->record($invite['CoInvite']['co_person_id'],
-
isset($invite['CoPetition']['enrollee_co_person_role_id']) ?
$invite['CoPetition']['enrollee_co_person_role_id'] : null,
-
isset($invite['CoPetition']['enrollee_org_identity_id']) ?
$invite['CoPetition']['enrollee_org_identity_id'] : null,
-
$invite['CoPetition']['enrollee_co_person_id'],
- ($confirm ?
ActionEnum::InvitationConfirmed : ActionEnum::InvitationDeclined),
- _txt(($confirm ?
'rs.inv.conf-a' : 'rs.inv.dec-a'), array($invite['CoInvite']['mail'])));
+ $this->CoPerson->HistoryRecord->record($hcopid,
+ $hcoprid,
+ $horgid,
+ $hactorid,
+ $hop,
+ $htxt);
}
catch(Exception $e) {
$dbc->rollback();
@@ -265,19 +323,20 @@
* @param String CO Name (to pass into invite)
* @param String Subject text (for configured templates stored in the
database)
* @param String Template text (for configured templates stored in the
database)
+ * @param Integer Email Address ID to verify
* @return Integer CO Invitation ID
* @throws RuntimeException
*/
- public function send($coPersonId, $orgIdentityID, $actorPersonId,
$toEmail, $fromEmail=null, $coName, $subject=null, $template=null) {
+ public function send($coPersonId, $orgIdentityID, $actorPersonId,
$toEmail, $fromEmail=null, $coName, $subject=null, $template=null,
$emailAddressID=null) {
// Toss any prior invitations for $coPersonId to $toEmail
try {
- $this->deleteAll(array('co_person_id' => $coPersonId,
- 'mail' => $toEmail));
+ $this->deleteAll(array('CoInvite.co_person_id' => $coPersonId,
+ 'CoInvite.mail' => $toEmail));
}
catch(Exception $e) {
- throw RuntimeException($e->getMessage());
+ throw new RuntimeException($e->getMessage());
}
$invite = array();
@@ -287,6 +346,9 @@
// XXX make expiration time configurable
// XXX date format may not be portable
$invite['CoInvite']['expires'] = date('Y-m-d H:i:s', strtotime('+1
day'));
+ if($emailAddressID) {
+ $invite['CoInvite']['email_address_id'] = $emailAddressID;
+ }
$this->create($invite);
@@ -339,13 +401,21 @@
// Create a history record
+ if($emailAddressID) {
+ $haction = ActionEnum::EmailAddressVerifyReqSent;
+ $htxt = _txt('rs.ev.sent', array($toEmail));
+ } else {
+ $haction = ActionEnum::InvitationSent;
+ $htxt = _txt('rs.inv.sent', array($toEmail));
+ }
+
try {
$this->CoPerson->HistoryRecord->record($coPersonId,
null,
$orgIdentityID,
$actorPersonId,
- ActionEnum::InvitationSent,
- _txt('rs.inv.sent',
array($toEmail)));
+ $haction,
+ $htxt);
}
catch(Exception $e) {
throw new RuntimeException($e->getMessage());
Modified: registry/trunk/app/Model/EmailAddress.php
===================================================================
--- registry/trunk/app/Model/EmailAddress.php 2013-12-26 19:11:12 UTC (rev
653)
+++ registry/trunk/app/Model/EmailAddress.php 2014-01-01 00:55:27 UTC (rev
654)
@@ -40,11 +40,13 @@
"OrgIdentity"
);
+ public $hasOne = array("CoInvite");
+
// Default display field for cake generated views
- public $displayField = "mail";
+ public $displayField = "EmailAddress.mail";
// Default ordering for find operations
- public $order = array("mail");
+// public $order = array("mail");
// Validation rules for table elements
// Validation rules must be named 'content' for petition dynamic rule
adjustment
@@ -158,18 +160,24 @@
* Mark an address as verified.
*
* @since COmanage Registry v0.7
- * @param Integer Org Identity ID
+ * @param Integer Org Identity ID address is associated with
+ * @param Integer CO Person ID address is associated with
* @param String Email address to mark verified
* @param Integer CO Person ID of verifier
* @throws InvalidArgumentException
* @throws RuntimeException
*/
- public function verify($orgIdentityId, $address, $verifierCoPersonId) {
+ public function verify($orgIdentityId, $coPersonId, $address,
$verifierCoPersonId) {
// First find the record
$args = array();
- $args['conditions']['EmailAddress.org_identity_id'] = $orgIdentityId;
+ if($orgIdentityId) {
+ $args['conditions']['EmailAddress.org_identity_id'] = $orgIdentityId;
+ }
+ if($coPersonId) {
+ $args['conditions']['EmailAddress.co_person_id'] = $coPersonId;
+ }
$args['conditions']['EmailAddress.mail'] = $address;
$args['contain'] = false;
@@ -180,17 +188,17 @@
}
// And then update it
-
$this->id = $mail['EmailAddress']['id'];
- if(!$this->saveField('verified', true)) {
+ // Make sure to disable callbacks since beforeSave will try to update
this field, too
+ if(!$this->saveField('verified', true, array('callbacks' => false))) {
throw new RuntimeException(_txt('er.db.save'));
}
// Finally, create a history record
try {
- $this->CoPerson->HistoryRecord->record(null,
+ $this->CoPerson->HistoryRecord->record($coPersonId,
null,
$orgIdentityId,
$verifierCoPersonId,
Modified: registry/trunk/app/View/CoInvites/reply.ctp
===================================================================
--- registry/trunk/app/View/CoInvites/reply.ctp 2013-12-26 19:11:12 UTC (rev
653)
+++ registry/trunk/app/View/CoInvites/reply.ctp 2014-01-01 00:55:27 UTC (rev
654)
@@ -24,29 +24,52 @@
-->
<?php if(!empty($invite)): ?>
<?php
- $params = array('title' => _txt('fd.inv.to',
array($cur_co['Co']['name'])));
+ $params = array('title' => $title_for_layout);
print $this->element("pageTitle", $params);
+
+ $verifyEmail = !empty($invite['CoInvite']['email_address_id']);
?>
-<h2 class="ui-state-default"><?php print _txt('fd.inv.for',
array(generateCn($invitee['PrimaryName']))); ?></h2>
+<h2 class="ui-state-default"><?php print _txt(($verifyEmail ? 'fd.ev.for' :
'fd.inv.for'),
+
array(generateCn($invitee['PrimaryName']))); ?></h2>
<?php
- print $this->Html->link(
- _txt('op.accept'),
- array('controller' => 'co_invites',
- 'action' =>
(isset($co_enrollment_flow['CoEnrollmentFlow']['require_authn'])
- &&
$co_enrollment_flow['CoEnrollmentFlow']['require_authn']) ? 'authconfirm' :
'confirm',
- $invite['CoInvite']['invitation']),
- array('class' => 'checkbutton')
- );
-
- print $this->Html->link(
- _txt('op.decline'),
- array('controller' => 'co_invites',
- 'action' => 'decline',
- $invite['CoInvite']['invitation']),
- array('class' => 'cancelbutton')
- );
+ if($verifyEmail) {
+ print "<p>" . _txt('fd.ev.verify.desc',
array($invite['EmailAddress']['mail'])) . "</p>";
+
+ print $this->Html->link(
+ _txt('op.confirm'),
+ array('controller' => 'co_invites',
+ 'action' => 'authverify',
+ $invite['CoInvite']['invitation']),
+ array('class' => 'checkbutton')
+ );
+
+ print $this->Html->link(
+ _txt('op.cancel'),
+ array('controller' => 'co_invites',
+ 'action' => 'decline',
+ $invite['CoInvite']['invitation']),
+ array('class' => 'cancelbutton')
+ );
+ } else {
+ print $this->Html->link(
+ _txt('op.accept'),
+ array('controller' => 'co_invites',
+ 'action' =>
(isset($co_enrollment_flow['CoEnrollmentFlow']['require_authn'])
+ &&
$co_enrollment_flow['CoEnrollmentFlow']['require_authn']) ? 'authconfirm' :
'confirm',
+ $invite['CoInvite']['invitation']),
+ array('class' => 'checkbutton')
+ );
+
+ print $this->Html->link(
+ _txt('op.decline'),
+ array('controller' => 'co_invites',
+ 'action' => 'decline',
+ $invite['CoInvite']['invitation']),
+ array('class' => 'cancelbutton')
+ );
+ }
$e = false;
Modified: registry/trunk/app/View/EmailAddresses/fields.inc
===================================================================
--- registry/trunk/app/View/EmailAddresses/fields.inc 2013-12-26 19:11:12
UTC (rev 653)
+++ registry/trunk/app/View/EmailAddresses/fields.inc 2014-01-01 00:55:27
UTC (rev 654)
@@ -100,7 +100,28 @@
// For an add, verified is by definition no and can't (currently,
anyway) be set manually.
// This will be caught by $email_addresses being null.
- print ($isVerified ? _txt('fd.yes') : _txt('fd.no'));
+ $url = array(
+ 'controller' => 'co_invites',
+ 'action' => 'verifyEmailAddress',
+ 'email_address_id' => $email_addresses[0]['EmailAddress']['id']
+ );
+
+ if(!empty($cur_co['Co']['id'])) {
+ $url['co'] = $cur_co['Co']['id'];
+ }
+
+ print ($isVerified ? _txt('fd.yes') : _txt('fd.no')) . "\n";
+
+ if(!$isVerified && $permissions['verifyEmailAddress']) {
+ print '<button class="checkbutton" title="Verify" type="button"
+ onclick="javascript:js_confirm_verification(\''
+ .
_jtxt(Sanitize::html($email_addresses[0]['EmailAddress']['mail']))
+ . '\', \''
+ . $this->Html->url($url)
+ . '\');">'
+ . "Verify"
+ . '</button>' . "\n";
+ }
?>
</td>
</tr>
@@ -111,7 +132,7 @@
<td>
<?php
if($e) {
- echo $this->Form->submit($submit_label);
+ print $this->Form->submit($submit_label);
print $this->Form->button(_txt('op.reset'),
array('type'=>'reset'));
}
Modified: registry/trunk/app/View/Layouts/default.ctp
===================================================================
--- registry/trunk/app/View/Layouts/default.ctp 2013-12-26 19:11:12 UTC (rev
653)
+++ registry/trunk/app/View/Layouts/default.ctp 2014-01-01 00:55:27 UTC (rev
654)
@@ -131,6 +131,30 @@
$('#dialog').dialog('open');
}
+ function js_confirm_verification(email, url)
+ {
+ // Generate a dialog box confirming a request to verify <email>. On
confirmation, forward to <url>, which executes the sending.
+ // XXX This should be merged with js_confirm_reinvite, above, perhaps
as part of CO-753.
+
+ // Set the title of the dialog
+ $("#dialog").dialog("option", "title", "<?php print _txt('op.verify');
?>");
+
+ // Set the body of the dialog
+ // XXX need to I18N this, but arg passing currently only works within
php not javascript
+ $("#dialog-text").text("Are you sure you wish to send a verification
request to " + email + "? Any previous request will be invalidated.");
+
+ // Set the dialog buttons
+ $("#dialog").dialog("option",
+ "buttons",
+ {
+ "<?php print _txt('op.cancel'); ?>": function()
{ $(this).dialog("close"); },
+ "<?php print _txt('op.verify'); ?>": function()
{ window.location=url; }
+ });
+
+ // Open the dialog
+ $('#dialog').dialog('open');
+ }
+
function js_onload_call_hooks()
{
// On page load, call any defined initialization functions.
- [comanage-dev] r654 - in registry/trunk/app: Config/Schema Controller Lib Model View/CoInvites View/EmailAddresses View/Layouts, svnlog, 12/31/2013
Archive powered by MHonArc 2.6.16.