1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-22 23:02:42 +01:00

Implement an approval queue

Summary:
  - Add an option for the queue.
  - By default, enable it.
  - Dump new users into the queue.
  - Send admins an email to approve them.

Test Plan:
  - Registered new accounts with queue on and off.
  - As an admin, approved accounts and disabled the queue from email.

Reviewers: btrahan

Reviewed By: btrahan

CC: aran

Differential Revision: https://secure.phabricator.com/D7576
This commit is contained in:
epriestley 2013-11-13 11:24:56 -08:00
parent 0fa411083f
commit c0e1a63a63
8 changed files with 101 additions and 16 deletions

View file

@ -181,6 +181,7 @@ $user->openTransaction();
$editor->createNewUser($user, $email); $editor->createNewUser($user, $email);
} else { } else {
if ($verify_email) { if ($verify_email) {
$user->setIsEmailVerified(1);
$verify_email->setIsVerified($set_verified ? 1 : 0); $verify_email->setIsVerified($set_verified ? 1 : 0);
} }
$editor->updateUser($user, $verify_email); $editor->updateUser($user, $verify_email);

View file

@ -42,6 +42,7 @@ if ($existing_email) {
$user = new PhabricatorUser(); $user = new PhabricatorUser();
$user->setUsername($username); $user->setUsername($username);
$user->setRealname($realname); $user->setRealname($realname);
$user->setIsApproved(1);
$email_object = id(new PhabricatorUserEmail()) $email_object = id(new PhabricatorUserEmail())
->setAddress($email) ->setAddress($email)

View file

@ -232,6 +232,19 @@ final class PhabricatorAuthRegisterController
$user->setUsername($value_username); $user->setUsername($value_username);
$user->setRealname($value_realname); $user->setRealname($value_realname);
if ($is_setup) {
$must_approve = false;
} else {
$must_approve = PhabricatorEnv::getEnvConfig(
'auth.require-approval');
}
if ($must_approve) {
$user->setIsApproved(0);
} else {
$user->setIsApproved(1);
}
$user->openTransaction(); $user->openTransaction();
$editor = id(new PhabricatorUserEditor()) $editor = id(new PhabricatorUserEditor())
@ -257,6 +270,10 @@ final class PhabricatorAuthRegisterController
$email_obj->sendVerificationEmail($user); $email_obj->sendVerificationEmail($user);
} }
if ($must_approve) {
$this->sendWaitingForApprovalEmail($user);
}
return $this->loginUser($user); return $this->loginUser($user);
} catch (AphrontQueryDuplicateKeyException $exception) { } catch (AphrontQueryDuplicateKeyException $exception) {
$same_username = id(new PhabricatorUser())->loadOneWhere( $same_username = id(new PhabricatorUser())->loadOneWhere(
@ -506,4 +523,43 @@ final class PhabricatorAuthRegisterController
array($message)); array($message));
} }
private function sendWaitingForApprovalEmail(PhabricatorUser $user) {
$title = '[Phabricator] '.pht(
'New User "%s" Awaiting Approval',
$user->getUsername());
$body = new PhabricatorMetaMTAMailBody();
$body->addRawSection(
pht(
'Newly registered user "%s" is awaiting account approval by an '.
'administrator.',
$user->getUsername()));
$body->addTextSection(
pht('APPROVAL QUEUE'),
PhabricatorEnv::getProductionURI(
'/people/query/approval/'));
$body->addTextSection(
pht('DISABLE APPROVAL QUEUE'),
PhabricatorEnv::getProductionURI(
'/config/edit/auth.require-approval/'));
$admins = id(new PhabricatorPeopleQuery())
->setViewer(PhabricatorUser::getOmnipotentUser())
->withIsAdmin(true)
->execute();
if (!$admins) {
return;
}
$mail = id(new PhabricatorMetaMTAMail())
->addTos(mpull($admins, 'getPHID'))
->setSubject($title)
->setBody($body->render())
->saveAndSend();
}
} }

View file

@ -490,7 +490,7 @@ final class PhabricatorConfigEditController
$table[] = phutil_tag('tr', array(), array( $table[] = phutil_tag('tr', array(), array(
phutil_tag('th', array(), $description), phutil_tag('th', array(), $description),
phutil_tag('th', array(), $value), phutil_tag('td', array(), $value),
)); ));
} }

View file

@ -21,7 +21,7 @@ final class PhabricatorAuthenticationConfigOptions
"Maximum number of simultaneous web sessions each user is ". "Maximum number of simultaneous web sessions each user is ".
"permitted to have. Setting this to '1' will prevent a user from ". "permitted to have. Setting this to '1' will prevent a user from ".
"logging in on more than one browser at the same time.")), "logging in on more than one browser at the same time.")),
$this->newOption('auth.sessions.conduit', 'int', 5) $this->newOption('auth.sessions.conduit', 'int', 5)
->setSummary( ->setSummary(
pht( pht(
"Number of simultaneous Conduit sessions each user is permitted.")) "Number of simultaneous Conduit sessions each user is permitted."))
@ -29,7 +29,7 @@ final class PhabricatorAuthenticationConfigOptions
pht( pht(
"Maximum number of simultaneous Conduit sessions each user is ". "Maximum number of simultaneous Conduit sessions each user is ".
"permitted to have.")), "permitted to have.")),
$this->newOption('auth.require-email-verification', 'bool', false) $this->newOption('auth.require-email-verification', 'bool', false)
->setBoolOptions( ->setBoolOptions(
array( array(
pht("Require email verification"), pht("Require email verification"),
@ -41,24 +41,47 @@ final class PhabricatorAuthenticationConfigOptions
pht( pht(
"If true, email addresses must be verified (by clicking a link ". "If true, email addresses must be verified (by clicking a link ".
"in an email) before a user can login. By default, verification ". "in an email) before a user can login. By default, verification ".
"is optional unless 'auth.email-domains' is nonempty.")), "is optional unless {{auth.email-domains}} is nonempty.")),
$this->newOption('auth.email-domains', 'list<string>', array()) $this->newOption('auth.require-approval', 'bool', true)
->setBoolOptions(
array(
pht("Require Administrators to Approve Accounts"),
pht("Don't Require Manual Approval"),
))
->setSummary(
pht("Require administrators to approve new accounts."))
->setDescription(
pht(
"Newly registered Phabricator accounts can either be placed ".
"into a manual approval queue for administrative review, or ".
"automatically activated immediately. The approval queue is ".
"enabled by default because it gives you greater control over ".
"who can register an account and access Phabricator.\n\n".
"If your install is completely public, or on a VPN, or users can ".
"only register with a trusted provider like LDAP, or you've ".
"otherwise configured Phabricator to prevent unauthorized ".
"registration, you can disable the queue to reduce administrative ".
"overhead.\n\n".
"NOTE: Before you disable the queue, make sure ".
"{{auth.email-domains}} is configured correctly for your ".
"install!")),
$this->newOption('auth.email-domains', 'list<string>', array())
->setSummary(pht("Only allow registration from particular domains.")) ->setSummary(pht("Only allow registration from particular domains."))
->setDescription( ->setDescription(
pht( pht(
"You can restrict allowed email addresses to certain domains ". "You can restrict allowed email addresses to certain domains ".
"(like 'yourcompany.com') by setting a list of allowed domains ". "(like `yourcompany.com`) by setting a list of allowed domains ".
"here. Users will only be allowed to register using email ". "here.\n\nUsers will only be allowed to register using email ".
"addresses at one of the domains, and will only be able to add ". "addresses at one of the domains, and will only be able to add ".
"new email addresses for these domains. If you configure this, ". "new email addresses for these domains. If you configure this, ".
"it implies 'auth.require-email-verification'.\n\n". "it implies {{auth.require-email-verification}}.\n\n".
"You should omit the '@' from domains. Note that the domain must ". "You should omit the `@` from domains. Note that the domain must ".
"match exactly. If you allow 'yourcompany.com', that permits ". "match exactly. If you allow `yourcompany.com`, that permits ".
"'joe@yourcompany.com' but rejects 'joe@mail.yourcompany.com'.")) "`joe@yourcompany.com` but rejects `joe@mail.yourcompany.com`."))
->addExample( ->addExample(
"yourcompany.com\nmail.yourcompany.com", "yourcompany.com\nmail.yourcompany.com",
pht('Valid Setting')), pht('Valid Setting')),
$this->newOption('auth.login-message', 'string', null) $this->newOption('auth.login-message', 'string', null)
->setLocked(true) ->setLocked(true)
->setSummary(pht("A block of HTML displayed on the login screen.")) ->setSummary(pht("A block of HTML displayed on the login screen."))
->setDescription( ->setDescription(
@ -66,7 +89,7 @@ final class PhabricatorAuthenticationConfigOptions
"You can provide an arbitrary block of HTML here, which will ". "You can provide an arbitrary block of HTML here, which will ".
"appear on the login screen. Normally, you'd use this to provide ". "appear on the login screen. Normally, you'd use this to provide ".
"login or registration instructions to users.")), "login or registration instructions to users.")),
$this->newOption('account.editable', 'bool', true) $this->newOption('account.editable', 'bool', true)
->setBoolOptions( ->setBoolOptions(
array( array(
pht("Allow editing"), pht("Allow editing"),
@ -83,7 +106,7 @@ final class PhabricatorAuthenticationConfigOptions
"synchronize account information from some other authoritative ". "synchronize account information from some other authoritative ".
"system, you can disable this to ensure information remains ". "system, you can disable this to ensure information remains ".
"consistent across both systems.")), "consistent across both systems.")),
$this->newOption('account.minimum-password-length', 'int', 8) $this->newOption('account.minimum-password-length', 'int', 8)
->setSummary(pht("Minimum password length.")) ->setSummary(pht("Minimum password length."))
->setDescription( ->setDescription(
pht( pht(

View file

@ -182,6 +182,9 @@ final class PhabricatorPeopleEditController
->setAddress($new_email) ->setAddress($new_email)
->setIsVerified(0); ->setIsVerified(0);
// Automatically approve the user, since an admin is creating them.
$user->setIsApproved(1);
id(new PhabricatorUserEditor()) id(new PhabricatorUserEditor())
->setActor($admin) ->setActor($admin)
->createNewUser($user, $email); ->createNewUser($user, $email);

View file

@ -30,7 +30,7 @@ final class PhabricatorUser
protected $isAdmin = 0; protected $isAdmin = 0;
protected $isDisabled = 0; protected $isDisabled = 0;
protected $isEmailVerified = 0; protected $isEmailVerified = 0;
protected $isApproved = 1; protected $isApproved = 0;
private $profileImage = null; private $profileImage = null;
private $profile = null; private $profile = null;

View file

@ -181,7 +181,8 @@ abstract class PhabricatorTestCase extends ArcanistPhutilTestCase {
$user = id(new PhabricatorUser()) $user = id(new PhabricatorUser())
->setRealName("Test User {$seed}}") ->setRealName("Test User {$seed}}")
->setUserName("test{$seed}"); ->setUserName("test{$seed}")
->setIsApproved(1);
$email = id(new PhabricatorUserEmail()) $email = id(new PhabricatorUserEmail())
->setAddress("testuser{$seed}@example.com") ->setAddress("testuser{$seed}@example.com")