Page MenuHomePhabricator

D7930.id17948.diff
No OneTemporary

D7930.id17948.diff

Index: src/__phutil_library_map__.php
===================================================================
--- src/__phutil_library_map__.php
+++ src/__phutil_library_map__.php
@@ -1395,6 +1395,7 @@
'PhabricatorExtendingPhabricatorConfigOptions' => 'applications/config/option/PhabricatorExtendingPhabricatorConfigOptions.php',
'PhabricatorExternalAccount' => 'applications/people/storage/PhabricatorExternalAccount.php',
'PhabricatorExternalAccountQuery' => 'applications/auth/query/PhabricatorExternalAccountQuery.php',
+ 'PhabricatorExternalEmailVerificationController' => 'applications/auth/controller/PhabricatorExternalEmailVerificationController.php',
'PhabricatorFactAggregate' => 'applications/fact/storage/PhabricatorFactAggregate.php',
'PhabricatorFactChartController' => 'applications/fact/controller/PhabricatorFactChartController.php',
'PhabricatorFactController' => 'applications/fact/controller/PhabricatorFactController.php',
@@ -3972,6 +3973,7 @@
1 => 'PhabricatorPolicyInterface',
),
'PhabricatorExternalAccountQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
+ 'PhabricatorExternalEmailVerificationController' => 'PhabricatorAuthController',
'PhabricatorFactAggregate' => 'PhabricatorFactDAO',
'PhabricatorFactChartController' => 'PhabricatorFactController',
'PhabricatorFactController' => 'PhabricatorController',
Index: src/applications/auth/application/PhabricatorApplicationAuth.php
===================================================================
--- src/applications/auth/application/PhabricatorApplicationAuth.php
+++ src/applications/auth/application/PhabricatorApplicationAuth.php
@@ -98,6 +98,8 @@
'/emailverify/(?P<code>[^/]+)/' =>
'PhabricatorEmailVerificationController',
+ '/externalemailverify/(?P<code>[^/]+)/(?P<email>[^/]+)/' =>
+ 'PhabricatorExternalEmailVerificationController',
'/logout/' => 'PhabricatorLogoutController',
);
Index: src/applications/auth/controller/PhabricatorExternalEmailVerificationController.php
===================================================================
--- /dev/null
+++ src/applications/auth/controller/PhabricatorExternalEmailVerificationController.php
@@ -0,0 +1,78 @@
+<?php
+
+final class PhabricatorExternalEmailVerificationController
+ extends PhabricatorAuthController {
+
+ private $code;
+ private $email;
+
+ public function willProcessRequest(array $data) {
+ $this->code = $data['code'];
+ $this->email = phutil_unescape_uri_path_component($data['email']);
+ }
+
+ public function shouldRequireEmailVerification() {
+ return false;
+ }
+
+ public function shouldRequireLogin() {
+ return false;
+ }
+
+ public function processRequest() {
+ $request = $this->getRequest();
+ $user = $request->getUser();
+
+ $email = new PhutilEmailAddress($this->email);
+
+ $external_account = id(new PhabricatorExternalAccountQuery())
+ ->setViewer($user)
+ ->withAccountTypes(array('email'))
+ ->withAccountDomains(array($email->getDomainName()))
+ ->withAccountIDs(array($email->getAddress()))
+ ->executeOne();
+
+ if (!$external_account) {
+ $title = pht('Unable to Verify Email');
+ $content = pht(
+ 'The verification code you provided is incorrect, or the email '.
+ 'address has been removed. '.
+ 'Make sure you followed the link in the email correctly.');
+ $continue = pht('Rats!');
+ } else if ($external_account->getEmailVerified()) {
+ $title = pht('Address Already Verified');
+ $content = pht(
+ 'This email address has already been verified.');
+ $continue = pht('Continue to Phabricator');
+ } else {
+ $external_account->setEmailVerified(1);
+ $external_account->save();
+ $title = pht('Address Verified');
+ $content = pht(
+ 'The email address %s is now verified.',
+ phutil_tag('strong', array(), $email->getAddress()));
+ $continue = pht('Continue to Phabricator');
+ }
+
+ $dialog = id(new AphrontDialogView())
+ ->setUser($user)
+ ->setTitle($title)
+ ->setMethod('GET')
+ ->addCancelButton('/', $continue)
+ ->appendChild($content);
+
+ $crumbs = $this->buildApplicationCrumbs();
+ $crumbs->addTextCrumb(pht('Verify Email'));
+
+ return $this->buildApplicationPage(
+ array(
+ $crumbs,
+ $dialog,
+ ),
+ array(
+ 'title' => pht('Verify Email'),
+ 'device' => true,
+ ));
+ }
+
+}
Index: src/applications/legalpad/controller/LegalpadDocumentSignController.php
===================================================================
--- src/applications/legalpad/controller/LegalpadDocumentSignController.php
+++ src/applications/legalpad/controller/LegalpadDocumentSignController.php
@@ -7,6 +7,10 @@
private $id;
+ public function shouldRequireLogin() {
+ return false;
+ }
+
public function willProcessRequest(array $data) {
$this->id = $data['id'];
}
@@ -25,38 +29,84 @@
return new Aphront404Response();
}
- $signature = id(new LegalpadDocumentSignature())
- ->loadOneWhere(
- 'documentPHID = %s AND documentVersion = %d AND signerPHID = %s',
- $document->getPHID(),
- $document->getVersions(),
- $user->getPHID());
+ $signer_type = 'unverified_email';
+ $external_account = null;
+ $signer_phid = null;
+ $signature = null;
+ $signature_data = array();
+ if ($user->isLoggedIn()) {
+ $signer_phid = $user->getPHID();
+ $signature_data = array(
+ 'name' => $user->getRealName(),
+ 'email' => $user->loadPrimaryEmailAddress());
+ $signer_type = 'user';
+ } else if ($request->isFormPost()) {
+ $email = new PhutilEmailAddress($request->getStr('email'));
+ $external_account = id(new PhabricatorExternalAccountQuery())
+ ->setViewer($user)
+ ->withAccountTypes(array('email'))
+ ->withAccountDomains(array($email->getDomainName()))
+ ->withAccountIDs(array($email->getAddress()))
+ ->executeOne();
+ if ($external_account) {
+ $signer_phid = $external_account->getPHID();
+ if ($external_account->getEmailVerified()) {
+ $signer_type = 'verified_email';
+ }
+ } else {
+ $external_account = id(new PhabricatorExternalAccount())
+ ->setAccountType('email')
+ ->setAccountID($email->getAddress())
+ ->setAccountDomain($email->getDomainName())
+ ->setAccountSecret(Filesystem::readRandomCharacters(32))
+ ->save();
+ $signer_phid = $external_account->getPHID();
+ }
+ }
+
+ if ($signer_phid) {
+ $signature = id(new LegalpadDocumentSignature())
+ ->loadOneWhere(
+ 'documentPHID = %s AND documentVersion = %d AND signerPHID = %s',
+ $document->getPHID(),
+ $document->getVersions(),
+ $signer_phid);
+ }
if (!$signature) {
$has_signed = false;
$error_view = null;
$signature = id(new LegalpadDocumentSignature())
- ->setSignerPHID($user->getPHID())
+ ->setSignerPHID($signer_phid)
->setDocumentPHID($document->getPHID())
->setDocumentVersion($document->getVersions());
- $data = array(
- 'name' => $user->getRealName(),
- 'email' => $user->loadPrimaryEmailAddress());
- $signature->setSignatureData($data);
+ $signature->setSignatureData($signature_data);
} else {
$has_signed = true;
+ switch ($signer_type) {
+ case 'user':
+ case 'verified_email':
+ $title = pht('Already Signed');
+ $body = $this->getVerifiedSignatureBlurb();
+ break;
+ case 'unverified_email':
+ default:
+ $title = pht('Already Signed but...');
+ $body = $this->getUnverifiedSignatureBlurb();
+ break;
+ }
$error_view = id(new AphrontErrorView())
->setSeverity(AphrontErrorView::SEVERITY_NOTICE)
- ->setTitle(pht('Already Signed'))
- ->appendChild(pht('Thank you for signing and agreeing'));
- $data = $signature->getSignatureData();
+ ->setTitle($title)
+ ->appendChild($body);
+ $signature_data = $signature->getSignatureData();
}
$e_name = true;
$e_email = true;
$e_address_1 = true;
$errors = array();
- if ($request->isFormPost()) {
+ if ($request->isFormPost() && !$has_signed) {
$name = $request->getStr('name');
$email = $request->getStr('email');
$address_1 = $request->getStr('address_1');
@@ -68,7 +118,7 @@
$e_name = pht('Required');
$errors[] = pht('Name field is required.');
}
- $data['name'] = $name;
+ $signature_data['name'] = $name;
if (!$email) {
$e_email = pht('Required');
@@ -81,16 +131,16 @@
$errors[] = pht('A valid email is required.');
}
}
- $data['email'] = $email;
+ $signature_data['email'] = $email;
if (!$address_1) {
$e_address_1 = pht('Required');
$errors[] = pht('Address line 1 field is required.');
}
- $data['address_1'] = $address_1;
- $data['address_2'] = $address_2;
- $data['phone'] = $phone;
- $signature->setSignatureData($data);
+ $signature_data['address_1'] = $address_1;
+ $signature_data['address_2'] = $address_2;
+ $signature_data['phone'] = $phone;
+ $signature->setSignatureData($signature_data);
if (!$agree) {
$errors[] = pht(
@@ -100,10 +150,24 @@
if (!$errors) {
$signature->save();
$has_signed = true;
+ switch ($signer_type) {
+ case 'user':
+ case 'verified_email':
+ $body = $this->getVerifiedSignatureBlurb();
+ break;
+ case 'unverified_email':
+ default:
+ $body = $this->getUnverifiedSignatureBlurb();
+ $this->sendVerifySignatureEmail(
+ $document,
+ $external_account,
+ $signature);
+ break;
+ }
$error_view = id(new AphrontErrorView())
->setSeverity(AphrontErrorView::SEVERITY_NOTICE)
- ->setTitle(pht('Signature successful'))
- ->appendChild(pht('Thank you for signing and agreeing'));
+ ->setTitle(pht('Signature Successful'))
+ ->appendChild($body);
} else {
$error_view = id(new AphrontErrorView())
->setTitle(pht('Error in submission.'))
@@ -218,10 +282,55 @@
->setValue(pht('Sign and Agree'))
->setDisabled($has_signed));
- return id(new PHUIObjectBoxView())
+ $view = id(new PHUIObjectBoxView())
->setHeaderText(pht('Sign and Agree'))
- ->setErrorView($error_view)
->setForm($form);
+ if ($error_view) {
+ $view->setErrorView($error_view);
+ }
+ return $view;
+ }
+
+ private function getVerifiedSignatureBlurb() {
+ return pht('Thank you for signing and agreeing.');
}
+ private function getUnverifiedSignatureBlurb() {
+ return pht('Thank you for signing and agreeing. However, you must '.
+ 'verify your email address. Please check your email '.
+ 'and follow the instructions.');
+ }
+
+ private function sendVerifySignatureEmail(
+ LegalpadDocument $doc,
+ PhabricatorExternalAccount $account,
+ LegalpadDocumentSignature $signature) {
+
+ $signature_data = $signature->getSignatureData();
+ $email = new PhutilEmailAddress($signature_data['email']);
+ $doc_link = PhabricatorEnv::getProductionURI($doc->getMonogram());
+ $path = sprintf(
+ '/externalemailverify/%s/%s/',
+ $account->getAccountSecret(),
+ phutil_escape_uri_path_component($email->getAddress()));
+ $link = PhabricatorEnv::getProductionURI($path);
+
+ $body = <<<EOBODY
+Hi {$signature_data['name']},
+
+This email address was used to sign a Legalpad document ({$doc_link}).
+Please verify you own this email address by clicking this link:
+
+ {$link}
+
+Your signature is invalid until you verify you own the email.
+EOBODY;
+
+ id(new PhabricatorMetaMTAMail())
+ ->addRawTos(array($signature_data['email']))
+ ->setSubject(pht('[Legalpad] Email Verification'))
+ ->setBody($body)
+ ->setRelatedPHID($account->getPHID())
+ ->saveAndSend();
+ }
}
Index: src/applications/legalpad/storage/LegalpadDocument.php
===================================================================
--- src/applications/legalpad/storage/LegalpadDocument.php
+++ src/applications/legalpad/storage/LegalpadDocument.php
@@ -61,6 +61,10 @@
return parent::save();
}
+ public function getMonogram() {
+ return 'L'.$this->getID();
+ }
+
/* -( PhabricatorSubscribableInterface Implementation )-------------------- */
public function isAutomaticallySubscribed($phid) {

File Metadata

Mime Type
text/plain
Expires
Sun, Nov 10, 6:22 AM (2 d, 18 h ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
6756527
Default Alt Text
D7930.id17948.diff (12 KB)

Event Timeline