Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F14030758
D7930.id17948.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
12 KB
Referenced Files
None
Subscribers
None
D7930.id17948.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D7930: Legalpad - make it work for not logged in users
Attached
Detach File
Event Timeline
Log In to Comment