Add email invites to Phabricator (logic only)
Summary:
Ref T7152. This builds the core of email invites and implements all the hard logic for them, covering it with a pile of tests.
There's no UI to create these yet, so users can't actually get invites (and administrators can't send them).
This stuff is a complicated mess because there are so many interactions between accounts, email addresses, email verification, email primary-ness, and user verification. However, I think I got it right and got test coverage everwhere.
The degree to which this is exception-driven is a little icky, but I think it's a reasonable way to get the testability we want while still making it hard for callers to get the flow wrong. In particular, I expect there to be at least two callers (one invite flow in the upstream, and one derived invite flow in Instances) so I believe there is merit in burying as much of this logic inside the Engine as is reasonably possible.
Test Plan: Unit tests only.
Reviewers: btrahan
Reviewed By: btrahan
Subscribers: epriestley
Maniphest Tasks: T7152
Differential Revision: https://secure.phabricator.com/D11723
2015-02-10 01:12:36 +01:00
|
|
|
<?php
|
|
|
|
|
|
|
|
final class PhabricatorAuthInvite
|
2015-02-11 15:05:53 +01:00
|
|
|
extends PhabricatorUserDAO
|
|
|
|
implements PhabricatorPolicyInterface {
|
Add email invites to Phabricator (logic only)
Summary:
Ref T7152. This builds the core of email invites and implements all the hard logic for them, covering it with a pile of tests.
There's no UI to create these yet, so users can't actually get invites (and administrators can't send them).
This stuff is a complicated mess because there are so many interactions between accounts, email addresses, email verification, email primary-ness, and user verification. However, I think I got it right and got test coverage everwhere.
The degree to which this is exception-driven is a little icky, but I think it's a reasonable way to get the testability we want while still making it hard for callers to get the flow wrong. In particular, I expect there to be at least two callers (one invite flow in the upstream, and one derived invite flow in Instances) so I believe there is merit in burying as much of this logic inside the Engine as is reasonably possible.
Test Plan: Unit tests only.
Reviewers: btrahan
Reviewed By: btrahan
Subscribers: epriestley
Maniphest Tasks: T7152
Differential Revision: https://secure.phabricator.com/D11723
2015-02-10 01:12:36 +01:00
|
|
|
|
|
|
|
protected $authorPHID;
|
|
|
|
protected $emailAddress;
|
|
|
|
protected $verificationHash;
|
|
|
|
protected $acceptedByPHID;
|
|
|
|
|
|
|
|
private $verificationCode;
|
2015-02-11 15:05:53 +01:00
|
|
|
private $viewerHasVerificationCode;
|
Add email invites to Phabricator (logic only)
Summary:
Ref T7152. This builds the core of email invites and implements all the hard logic for them, covering it with a pile of tests.
There's no UI to create these yet, so users can't actually get invites (and administrators can't send them).
This stuff is a complicated mess because there are so many interactions between accounts, email addresses, email verification, email primary-ness, and user verification. However, I think I got it right and got test coverage everwhere.
The degree to which this is exception-driven is a little icky, but I think it's a reasonable way to get the testability we want while still making it hard for callers to get the flow wrong. In particular, I expect there to be at least two callers (one invite flow in the upstream, and one derived invite flow in Instances) so I believe there is merit in burying as much of this logic inside the Engine as is reasonably possible.
Test Plan: Unit tests only.
Reviewers: btrahan
Reviewed By: btrahan
Subscribers: epriestley
Maniphest Tasks: T7152
Differential Revision: https://secure.phabricator.com/D11723
2015-02-10 01:12:36 +01:00
|
|
|
|
|
|
|
protected function getConfiguration() {
|
|
|
|
return array(
|
2015-02-11 15:05:53 +01:00
|
|
|
self::CONFIG_AUX_PHID => true,
|
Add email invites to Phabricator (logic only)
Summary:
Ref T7152. This builds the core of email invites and implements all the hard logic for them, covering it with a pile of tests.
There's no UI to create these yet, so users can't actually get invites (and administrators can't send them).
This stuff is a complicated mess because there are so many interactions between accounts, email addresses, email verification, email primary-ness, and user verification. However, I think I got it right and got test coverage everwhere.
The degree to which this is exception-driven is a little icky, but I think it's a reasonable way to get the testability we want while still making it hard for callers to get the flow wrong. In particular, I expect there to be at least two callers (one invite flow in the upstream, and one derived invite flow in Instances) so I believe there is merit in burying as much of this logic inside the Engine as is reasonably possible.
Test Plan: Unit tests only.
Reviewers: btrahan
Reviewed By: btrahan
Subscribers: epriestley
Maniphest Tasks: T7152
Differential Revision: https://secure.phabricator.com/D11723
2015-02-10 01:12:36 +01:00
|
|
|
self::CONFIG_COLUMN_SCHEMA => array(
|
|
|
|
'emailAddress' => 'sort128',
|
|
|
|
'verificationHash' => 'bytes12',
|
|
|
|
'acceptedByPHID' => 'phid?',
|
|
|
|
),
|
|
|
|
self::CONFIG_KEY_SCHEMA => array(
|
|
|
|
'key_address' => array(
|
|
|
|
'columns' => array('emailAddress'),
|
|
|
|
'unique' => true,
|
|
|
|
),
|
|
|
|
'key_code' => array(
|
|
|
|
'columns' => array('verificationHash'),
|
|
|
|
'unique' => true,
|
|
|
|
),
|
|
|
|
),
|
|
|
|
) + parent::getConfiguration();
|
|
|
|
}
|
|
|
|
|
2015-02-11 15:05:53 +01:00
|
|
|
public function generatePHID() {
|
|
|
|
return PhabricatorPHID::generateNewPHID(
|
|
|
|
PhabricatorAuthInvitePHIDType::TYPECONST);
|
|
|
|
}
|
|
|
|
|
2015-02-11 15:06:09 +01:00
|
|
|
public function regenerateVerificationCode() {
|
|
|
|
$this->verificationCode = Filesystem::readRandomCharacters(16);
|
|
|
|
$this->verificationHash = null;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
Add email invites to Phabricator (logic only)
Summary:
Ref T7152. This builds the core of email invites and implements all the hard logic for them, covering it with a pile of tests.
There's no UI to create these yet, so users can't actually get invites (and administrators can't send them).
This stuff is a complicated mess because there are so many interactions between accounts, email addresses, email verification, email primary-ness, and user verification. However, I think I got it right and got test coverage everwhere.
The degree to which this is exception-driven is a little icky, but I think it's a reasonable way to get the testability we want while still making it hard for callers to get the flow wrong. In particular, I expect there to be at least two callers (one invite flow in the upstream, and one derived invite flow in Instances) so I believe there is merit in burying as much of this logic inside the Engine as is reasonably possible.
Test Plan: Unit tests only.
Reviewers: btrahan
Reviewed By: btrahan
Subscribers: epriestley
Maniphest Tasks: T7152
Differential Revision: https://secure.phabricator.com/D11723
2015-02-10 01:12:36 +01:00
|
|
|
public function getVerificationCode() {
|
2015-02-11 15:06:09 +01:00
|
|
|
if (!$this->verificationCode) {
|
Add email invites to Phabricator (logic only)
Summary:
Ref T7152. This builds the core of email invites and implements all the hard logic for them, covering it with a pile of tests.
There's no UI to create these yet, so users can't actually get invites (and administrators can't send them).
This stuff is a complicated mess because there are so many interactions between accounts, email addresses, email verification, email primary-ness, and user verification. However, I think I got it right and got test coverage everwhere.
The degree to which this is exception-driven is a little icky, but I think it's a reasonable way to get the testability we want while still making it hard for callers to get the flow wrong. In particular, I expect there to be at least two callers (one invite flow in the upstream, and one derived invite flow in Instances) so I believe there is merit in burying as much of this logic inside the Engine as is reasonably possible.
Test Plan: Unit tests only.
Reviewers: btrahan
Reviewed By: btrahan
Subscribers: epriestley
Maniphest Tasks: T7152
Differential Revision: https://secure.phabricator.com/D11723
2015-02-10 01:12:36 +01:00
|
|
|
if ($this->verificationHash) {
|
|
|
|
throw new Exception(
|
|
|
|
pht(
|
|
|
|
'Verification code can not be regenerated after an invite is '.
|
|
|
|
'created.'));
|
|
|
|
}
|
2015-02-11 15:06:09 +01:00
|
|
|
$this->regenerateVerificationCode();
|
Add email invites to Phabricator (logic only)
Summary:
Ref T7152. This builds the core of email invites and implements all the hard logic for them, covering it with a pile of tests.
There's no UI to create these yet, so users can't actually get invites (and administrators can't send them).
This stuff is a complicated mess because there are so many interactions between accounts, email addresses, email verification, email primary-ness, and user verification. However, I think I got it right and got test coverage everwhere.
The degree to which this is exception-driven is a little icky, but I think it's a reasonable way to get the testability we want while still making it hard for callers to get the flow wrong. In particular, I expect there to be at least two callers (one invite flow in the upstream, and one derived invite flow in Instances) so I believe there is merit in burying as much of this logic inside the Engine as is reasonably possible.
Test Plan: Unit tests only.
Reviewers: btrahan
Reviewed By: btrahan
Subscribers: epriestley
Maniphest Tasks: T7152
Differential Revision: https://secure.phabricator.com/D11723
2015-02-10 01:12:36 +01:00
|
|
|
}
|
|
|
|
return $this->verificationCode;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function save() {
|
|
|
|
if (!$this->getVerificationHash()) {
|
|
|
|
$hash = PhabricatorHash::digestForIndex($this->getVerificationCode());
|
|
|
|
$this->setVerificationHash($hash);
|
|
|
|
}
|
|
|
|
|
|
|
|
return parent::save();
|
|
|
|
}
|
|
|
|
|
2015-02-11 15:05:53 +01:00
|
|
|
public function setViewerHasVerificationCode($loaded) {
|
|
|
|
$this->viewerHasVerificationCode = $loaded;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* -( PhabricatorPolicyInterface )----------------------------------------- */
|
|
|
|
|
|
|
|
|
|
|
|
public function getCapabilities() {
|
|
|
|
return array(
|
|
|
|
PhabricatorPolicyCapability::CAN_VIEW,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getPolicy($capability) {
|
|
|
|
switch ($capability) {
|
|
|
|
case PhabricatorPolicyCapability::CAN_VIEW:
|
|
|
|
return PhabricatorPolicies::POLICY_ADMIN;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public function hasAutomaticCapability($capability, PhabricatorUser $viewer) {
|
|
|
|
if ($this->viewerHasVerificationCode) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($viewer->getPHID()) {
|
|
|
|
if ($viewer->getPHID() == $this->getAuthorPHID()) {
|
|
|
|
// You can see invites you sent.
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($viewer->getPHID() == $this->getAcceptedByPHID()) {
|
|
|
|
// You can see invites you have accepted.
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function describeAutomaticCapability($capability) {
|
|
|
|
return pht(
|
|
|
|
'Invites are visible to administrators, the inviting user, users with '.
|
|
|
|
'an invite code, and the user who accepts the invite.');
|
|
|
|
}
|
|
|
|
|
Add email invites to Phabricator (logic only)
Summary:
Ref T7152. This builds the core of email invites and implements all the hard logic for them, covering it with a pile of tests.
There's no UI to create these yet, so users can't actually get invites (and administrators can't send them).
This stuff is a complicated mess because there are so many interactions between accounts, email addresses, email verification, email primary-ness, and user verification. However, I think I got it right and got test coverage everwhere.
The degree to which this is exception-driven is a little icky, but I think it's a reasonable way to get the testability we want while still making it hard for callers to get the flow wrong. In particular, I expect there to be at least two callers (one invite flow in the upstream, and one derived invite flow in Instances) so I believe there is merit in burying as much of this logic inside the Engine as is reasonably possible.
Test Plan: Unit tests only.
Reviewers: btrahan
Reviewed By: btrahan
Subscribers: epriestley
Maniphest Tasks: T7152
Differential Revision: https://secure.phabricator.com/D11723
2015-02-10 01:12:36 +01:00
|
|
|
}
|