2012-05-07 19:29:33 +02:00
|
|
|
<?php
|
|
|
|
|
|
|
|
/**
|
Allow restriction of permitted email domains
Summary:
Allow allowed email addresses to be restricted to certain domains. This implies email must be verified.
This probably isn't QUITE ready for prime-time without a few other tweaks (better administrative tools, notably) but we're nearly there.
Test Plan:
- With no restrictions:
- Registered with OAuth
- Created an account with accountadmin
- Added an email
- With restrictions:
- Tried to OAuth register with a restricted address, was prompted to provide a valid one.
- Tried to OAuth register with a valid address, worked fine.
- Tried to accountadmin a restricted address, got blocked.
- Tried to accountadmin a valid address, worked fine.
- Tried to add a restricted address, blocked.
- Tried to add a valid address, worked fine.
- Created a user with People with an invalid address, got blocked.
- Created a user with People with a valid address, worked fine.
Reviewers: btrahan, csilvers
Reviewed By: csilvers
CC: aran, joe, csilvers
Maniphest Tasks: T1184
Differential Revision: https://secure.phabricator.com/D2581
2012-05-26 15:04:35 +02:00
|
|
|
* @task restrictions Domain Restrictions
|
|
|
|
* @task email Email About Email
|
2012-05-07 19:29:33 +02:00
|
|
|
*/
|
|
|
|
final class PhabricatorUserEmail extends PhabricatorUserDAO {
|
|
|
|
|
|
|
|
protected $userPHID;
|
|
|
|
protected $address;
|
|
|
|
protected $isVerified;
|
|
|
|
protected $isPrimary;
|
|
|
|
protected $verificationCode;
|
|
|
|
|
2014-02-23 19:19:35 +01:00
|
|
|
const MAX_ADDRESS_LENGTH = 128;
|
|
|
|
|
2012-05-07 19:29:33 +02:00
|
|
|
public function getVerificationURI() {
|
|
|
|
return '/emailverify/'.$this->getVerificationCode().'/';
|
|
|
|
}
|
|
|
|
|
|
|
|
public function save() {
|
|
|
|
if (!$this->verificationCode) {
|
|
|
|
$this->setVerificationCode(Filesystem::readRandomCharacters(24));
|
|
|
|
}
|
|
|
|
return parent::save();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
Allow restriction of permitted email domains
Summary:
Allow allowed email addresses to be restricted to certain domains. This implies email must be verified.
This probably isn't QUITE ready for prime-time without a few other tweaks (better administrative tools, notably) but we're nearly there.
Test Plan:
- With no restrictions:
- Registered with OAuth
- Created an account with accountadmin
- Added an email
- With restrictions:
- Tried to OAuth register with a restricted address, was prompted to provide a valid one.
- Tried to OAuth register with a valid address, worked fine.
- Tried to accountadmin a restricted address, got blocked.
- Tried to accountadmin a valid address, worked fine.
- Tried to add a restricted address, blocked.
- Tried to add a valid address, worked fine.
- Created a user with People with an invalid address, got blocked.
- Created a user with People with a valid address, worked fine.
Reviewers: btrahan, csilvers
Reviewed By: csilvers
CC: aran, joe, csilvers
Maniphest Tasks: T1184
Differential Revision: https://secure.phabricator.com/D2581
2012-05-26 15:04:35 +02:00
|
|
|
/* -( Domain Restrictions )------------------------------------------------ */
|
|
|
|
|
|
|
|
|
2014-02-23 19:19:35 +01:00
|
|
|
/**
|
|
|
|
* @task restrictions
|
|
|
|
*/
|
|
|
|
public static function isValidAddress($address) {
|
|
|
|
if (strlen($address) > self::MAX_ADDRESS_LENGTH) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2014-02-24 02:31:46 +01:00
|
|
|
// Very roughly validate that this address isn't so mangled that a
|
|
|
|
// reasonable piece of code might completely misparse it. In particular,
|
|
|
|
// the major risks are:
|
|
|
|
//
|
|
|
|
// - `PhutilEmailAddress` needs to be able to extract the domain portion
|
|
|
|
// from it.
|
|
|
|
// - Reasonable mail adapters should be hard-pressed to interpret one
|
|
|
|
// address as several addresses.
|
|
|
|
//
|
|
|
|
// To this end, we're roughly verifying that there's some normal text, an
|
|
|
|
// "@" symbol, and then some more normal text.
|
|
|
|
|
2014-03-13 20:42:41 +01:00
|
|
|
$email_regex = '(^[a-z0-9_+.!-]+@[a-z0-9_+:.-]+\z)i';
|
2014-02-24 02:31:46 +01:00
|
|
|
if (!preg_match($email_regex, $address)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2014-02-23 19:19:35 +01:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @task restrictions
|
|
|
|
*/
|
|
|
|
public static function describeValidAddresses() {
|
|
|
|
return pht(
|
2014-02-24 02:31:46 +01:00
|
|
|
"Email addresses should be in the form 'user@domain.com'. The maximum ".
|
|
|
|
"length of an email address is %d character(s).",
|
2014-02-23 19:19:35 +01:00
|
|
|
new PhutilNumber(self::MAX_ADDRESS_LENGTH));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
Allow restriction of permitted email domains
Summary:
Allow allowed email addresses to be restricted to certain domains. This implies email must be verified.
This probably isn't QUITE ready for prime-time without a few other tweaks (better administrative tools, notably) but we're nearly there.
Test Plan:
- With no restrictions:
- Registered with OAuth
- Created an account with accountadmin
- Added an email
- With restrictions:
- Tried to OAuth register with a restricted address, was prompted to provide a valid one.
- Tried to OAuth register with a valid address, worked fine.
- Tried to accountadmin a restricted address, got blocked.
- Tried to accountadmin a valid address, worked fine.
- Tried to add a restricted address, blocked.
- Tried to add a valid address, worked fine.
- Created a user with People with an invalid address, got blocked.
- Created a user with People with a valid address, worked fine.
Reviewers: btrahan, csilvers
Reviewed By: csilvers
CC: aran, joe, csilvers
Maniphest Tasks: T1184
Differential Revision: https://secure.phabricator.com/D2581
2012-05-26 15:04:35 +02:00
|
|
|
/**
|
|
|
|
* @task restrictions
|
|
|
|
*/
|
|
|
|
public static function isAllowedAddress($address) {
|
2014-02-23 19:19:35 +01:00
|
|
|
if (!self::isValidAddress($address)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
Allow restriction of permitted email domains
Summary:
Allow allowed email addresses to be restricted to certain domains. This implies email must be verified.
This probably isn't QUITE ready for prime-time without a few other tweaks (better administrative tools, notably) but we're nearly there.
Test Plan:
- With no restrictions:
- Registered with OAuth
- Created an account with accountadmin
- Added an email
- With restrictions:
- Tried to OAuth register with a restricted address, was prompted to provide a valid one.
- Tried to OAuth register with a valid address, worked fine.
- Tried to accountadmin a restricted address, got blocked.
- Tried to accountadmin a valid address, worked fine.
- Tried to add a restricted address, blocked.
- Tried to add a valid address, worked fine.
- Created a user with People with an invalid address, got blocked.
- Created a user with People with a valid address, worked fine.
Reviewers: btrahan, csilvers
Reviewed By: csilvers
CC: aran, joe, csilvers
Maniphest Tasks: T1184
Differential Revision: https://secure.phabricator.com/D2581
2012-05-26 15:04:35 +02:00
|
|
|
$allowed_domains = PhabricatorEnv::getEnvConfig('auth.email-domains');
|
|
|
|
if (!$allowed_domains) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
$addr_obj = new PhutilEmailAddress($address);
|
|
|
|
|
|
|
|
$domain = $addr_obj->getDomainName();
|
|
|
|
if (!$domain) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return in_array($domain, $allowed_domains);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @task restrictions
|
|
|
|
*/
|
|
|
|
public static function describeAllowedAddresses() {
|
|
|
|
$domains = PhabricatorEnv::getEnvConfig('auth.email-domains');
|
|
|
|
if (!$domains) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (count($domains) == 1) {
|
|
|
|
return 'Email address must be @'.head($domains);
|
|
|
|
} else {
|
|
|
|
return 'Email address must be at one of: '.
|
|
|
|
implode(', ', $domains);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Check if this install requires email verification.
|
|
|
|
*
|
|
|
|
* @return bool True if email addresses must be verified.
|
|
|
|
*
|
|
|
|
* @task restrictions
|
|
|
|
*/
|
|
|
|
public static function isEmailVerificationRequired() {
|
|
|
|
// NOTE: Configuring required email domains implies required verification.
|
|
|
|
return PhabricatorEnv::getEnvConfig('auth.require-email-verification') ||
|
|
|
|
PhabricatorEnv::getEnvConfig('auth.email-domains');
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-05-07 19:29:33 +02:00
|
|
|
/* -( Email About Email )-------------------------------------------------- */
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Send a verification email from $user to this address.
|
|
|
|
*
|
|
|
|
* @param PhabricatorUser The user sending the verification.
|
|
|
|
* @return this
|
|
|
|
* @task email
|
|
|
|
*/
|
|
|
|
public function sendVerificationEmail(PhabricatorUser $user) {
|
|
|
|
$username = $user->getUsername();
|
|
|
|
|
|
|
|
$address = $this->getAddress();
|
|
|
|
$link = PhabricatorEnv::getProductionURI($this->getVerificationURI());
|
|
|
|
|
|
|
|
|
|
|
|
$is_serious = PhabricatorEnv::getEnvConfig('phabricator.serious-business');
|
|
|
|
|
|
|
|
$signature = null;
|
|
|
|
if (!$is_serious) {
|
|
|
|
$signature = <<<EOSIGNATURE
|
|
|
|
Get Well Soon,
|
|
|
|
Phabricator
|
|
|
|
EOSIGNATURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
$body = <<<EOBODY
|
|
|
|
Hi {$username},
|
|
|
|
|
|
|
|
Please verify that you own this email address ({$address}) by clicking this
|
|
|
|
link:
|
|
|
|
|
|
|
|
{$link}
|
|
|
|
|
|
|
|
{$signature}
|
|
|
|
EOBODY;
|
|
|
|
|
|
|
|
id(new PhabricatorMetaMTAMail())
|
|
|
|
->addRawTos(array($address))
|
|
|
|
->setSubject('[Phabricator] Email Verification')
|
|
|
|
->setBody($body)
|
|
|
|
->setRelatedPHID($user->getPHID())
|
|
|
|
->saveAndSend();
|
|
|
|
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Send a notification email from $user to this address, informing the
|
|
|
|
* recipient that this is no longer their account's primary address.
|
|
|
|
*
|
|
|
|
* @param PhabricatorUser The user sending the notification.
|
|
|
|
* @param PhabricatorUserEmail New primary email address.
|
|
|
|
* @return this
|
|
|
|
* @task email
|
|
|
|
*/
|
|
|
|
public function sendOldPrimaryEmail(
|
|
|
|
PhabricatorUser $user,
|
|
|
|
PhabricatorUserEmail $new) {
|
|
|
|
$username = $user->getUsername();
|
|
|
|
|
|
|
|
$old_address = $this->getAddress();
|
|
|
|
$new_address = $new->getAddress();
|
|
|
|
|
|
|
|
$body = <<<EOBODY
|
|
|
|
Hi {$username},
|
|
|
|
|
|
|
|
This email address ({$old_address}) is no longer your primary email address.
|
|
|
|
Going forward, Phabricator will send all email to your new primary email
|
|
|
|
address ({$new_address}).
|
|
|
|
|
|
|
|
EOBODY;
|
|
|
|
|
|
|
|
id(new PhabricatorMetaMTAMail())
|
|
|
|
->addRawTos(array($old_address))
|
|
|
|
->setSubject('[Phabricator] Primary Address Changed')
|
|
|
|
->setBody($body)
|
|
|
|
->setFrom($user->getPHID())
|
|
|
|
->setRelatedPHID($user->getPHID())
|
|
|
|
->saveAndSend();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Send a notification email from $user to this address, informing the
|
|
|
|
* recipient that this is now their account's new primary email address.
|
|
|
|
*
|
|
|
|
* @param PhabricatorUser The user sending the verification.
|
|
|
|
* @return this
|
|
|
|
* @task email
|
|
|
|
*/
|
|
|
|
public function sendNewPrimaryEmail(PhabricatorUser $user) {
|
|
|
|
$username = $user->getUsername();
|
|
|
|
|
|
|
|
$new_address = $this->getAddress();
|
|
|
|
|
|
|
|
$body = <<<EOBODY
|
|
|
|
Hi {$username},
|
|
|
|
|
|
|
|
This is now your primary email address ({$new_address}). Going forward,
|
|
|
|
Phabricator will send all email here.
|
|
|
|
|
|
|
|
EOBODY;
|
|
|
|
|
|
|
|
id(new PhabricatorMetaMTAMail())
|
|
|
|
->addRawTos(array($new_address))
|
|
|
|
->setSubject('[Phabricator] Primary Address Changed')
|
|
|
|
->setBody($body)
|
|
|
|
->setFrom($user->getPHID())
|
|
|
|
->setRelatedPHID($user->getPHID())
|
|
|
|
->saveAndSend();
|
|
|
|
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|