Page MenuHomePhabricator

D17500.diff
No OneTemporary

D17500.diff

diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -3763,6 +3763,7 @@
'PhabricatorSearchBaseController' => 'applications/search/controller/PhabricatorSearchBaseController.php',
'PhabricatorSearchCheckboxesField' => 'applications/search/field/PhabricatorSearchCheckboxesField.php',
'PhabricatorSearchConfigOptions' => 'applications/search/config/PhabricatorSearchConfigOptions.php',
+ 'PhabricatorSearchConstraintException' => 'applications/search/exception/PhabricatorSearchConstraintException.php',
'PhabricatorSearchController' => 'applications/search/controller/PhabricatorSearchController.php',
'PhabricatorSearchCustomFieldProxyField' => 'applications/search/field/PhabricatorSearchCustomFieldProxyField.php',
'PhabricatorSearchDAO' => 'applications/search/storage/PhabricatorSearchDAO.php',
@@ -9072,6 +9073,7 @@
'PhabricatorSearchBaseController' => 'PhabricatorController',
'PhabricatorSearchCheckboxesField' => 'PhabricatorSearchField',
'PhabricatorSearchConfigOptions' => 'PhabricatorApplicationConfigOptions',
+ 'PhabricatorSearchConstraintException' => 'Exception',
'PhabricatorSearchController' => 'PhabricatorSearchBaseController',
'PhabricatorSearchCustomFieldProxyField' => 'PhabricatorSearchField',
'PhabricatorSearchDAO' => 'PhabricatorLiskDAO',
diff --git a/src/applications/config/option/PhabricatorSecurityConfigOptions.php b/src/applications/config/option/PhabricatorSecurityConfigOptions.php
--- a/src/applications/config/option/PhabricatorSecurityConfigOptions.php
+++ b/src/applications/config/option/PhabricatorSecurityConfigOptions.php
@@ -66,6 +66,21 @@
,
PhabricatorEnv::getDoclink('Configuring Encryption')));
+ $require_mfa_description = $this->deformat(pht(<<<EOTEXT
+By default, Phabricator allows users to add multi-factor authentication to
+their accounts, but does not require it. By enabling this option, you can
+force all users to add at least one authentication factor before they can use
+their accounts.
+
+Administrators can query a list of users who do not have MFA configured in
+{nav People}:
+
+ - **[[ %s | %s ]]**
+EOTEXT
+ ,
+ '/people/?mfa=false',
+ pht('List of Users Without MFA')));
+
return array(
$this->newOption('security.alternate-file-domain', 'string', null)
->setLocked(true)
@@ -132,13 +147,7 @@
->setLocked(true)
->setSummary(
pht('Require all users to configure multi-factor authentication.'))
- ->setDescription(
- pht(
- 'By default, Phabricator allows users to add multi-factor '.
- 'authentication to their accounts, but does not require it. '.
- 'By enabling this option, you can force all users to add '.
- 'at least one authentication factor before they can use their '.
- 'accounts.'))
+ ->setDescription($require_mfa_description)
->setBoolOptions(
array(
pht('Multi-Factor Required'),
diff --git a/src/applications/people/query/PhabricatorPeopleQuery.php b/src/applications/people/query/PhabricatorPeopleQuery.php
--- a/src/applications/people/query/PhabricatorPeopleQuery.php
+++ b/src/applications/people/query/PhabricatorPeopleQuery.php
@@ -18,6 +18,7 @@
private $nameLike;
private $nameTokens;
private $namePrefixes;
+ private $isEnrolledInMultiFactor;
private $needPrimaryEmail;
private $needProfile;
@@ -100,6 +101,11 @@
return $this;
}
+ public function withIsEnrolledInMultiFactor($enrolled) {
+ $this->isEnrolledInMultiFactor = $enrolled;
+ return $this;
+ }
+
public function needPrimaryEmail($need) {
$this->needPrimaryEmail = $need;
return $this;
@@ -337,6 +343,13 @@
$this->nameLike);
}
+ if ($this->isEnrolledInMultiFactor !== null) {
+ $where[] = qsprintf(
+ $conn,
+ 'user.isEnrolledInMultiFactor = %d',
+ (int)$this->isEnrolledInMultiFactor);
+ }
+
return $where;
}
diff --git a/src/applications/people/query/PhabricatorPeopleSearchEngine.php b/src/applications/people/query/PhabricatorPeopleSearchEngine.php
--- a/src/applications/people/query/PhabricatorPeopleSearchEngine.php
+++ b/src/applications/people/query/PhabricatorPeopleSearchEngine.php
@@ -18,7 +18,7 @@
}
protected function buildCustomSearchFields() {
- return array(
+ $fields = array(
id(new PhabricatorSearchStringListField())
->setLabel(pht('Usernames'))
->setKey('usernames')
@@ -84,18 +84,36 @@
pht(
'Pass true to find only users awaiting administrative approval, '.
'or false to omit these users.')),
- id(new PhabricatorSearchDateField())
- ->setKey('createdStart')
- ->setLabel(pht('Joined After'))
- ->setDescription(
- pht('Find user accounts created after a given time.')),
- id(new PhabricatorSearchDateField())
- ->setKey('createdEnd')
- ->setLabel(pht('Joined Before'))
+ );
+
+ $viewer = $this->requireViewer();
+ if ($viewer->getIsAdmin()) {
+ $fields[] = id(new PhabricatorSearchThreeStateField())
+ ->setLabel(pht('Has MFA'))
+ ->setKey('mfa')
+ ->setOptions(
+ pht('(Show All)'),
+ pht('Show Only Users With MFA'),
+ pht('Hide Users With MFA'))
->setDescription(
- pht('Find user accounts created before a given time.')),
+ pht(
+ 'Pass true to find only users who are enrolled in MFA, or false '.
+ 'to omit these users.'));
+ }
- );
+ $fields[] = id(new PhabricatorSearchDateField())
+ ->setKey('createdStart')
+ ->setLabel(pht('Joined After'))
+ ->setDescription(
+ pht('Find user accounts created after a given time.'));
+
+ $fields[] = id(new PhabricatorSearchDateField())
+ ->setKey('createdEnd')
+ ->setLabel(pht('Joined Before'))
+ ->setDescription(
+ pht('Find user accounts created before a given time.'));
+
+ return $fields;
}
protected function getDefaultFieldOrder() {
@@ -151,6 +169,19 @@
$query->withIsApproved(!$map['needsApproval']);
}
+ if (idx($map, 'mfa') !== null) {
+ $viewer = $this->requireViewer();
+ if (!$viewer->getIsAdmin()) {
+ throw new PhabricatorSearchConstraintException(
+ pht(
+ 'The "Has MFA" query constraint may only be used by '.
+ 'administrators, to prevent attackers from using it to target '.
+ 'weak accounts.'));
+ }
+
+ $query->withIsEnrolledInMultiFactor($map['mfa']);
+ }
+
if ($map['createdStart']) {
$query->withDateCreatedAfter($map['createdStart']);
}
@@ -255,6 +286,12 @@
}
if ($viewer->getIsAdmin()) {
+ if ($user->getIsEnrolledInMultiFactor()) {
+ $item->addIcon('fa-lock', pht('Has MFA'));
+ }
+ }
+
+ if ($viewer->getIsAdmin()) {
$user_id = $user->getID();
if ($is_approval) {
$item->addAction(
diff --git a/src/applications/search/controller/PhabricatorApplicationSearchController.php b/src/applications/search/controller/PhabricatorApplicationSearchController.php
--- a/src/applications/search/controller/PhabricatorApplicationSearchController.php
+++ b/src/applications/search/controller/PhabricatorApplicationSearchController.php
@@ -331,6 +331,8 @@
'query parameters and correct errors.');
} catch (PhutilSearchQueryCompilerSyntaxException $ex) {
$exec_errors[] = $ex->getMessage();
+ } catch (PhabricatorSearchConstraintException $ex) {
+ $exec_errors[] = $ex->getMessage();
}
// The engine may have encountered additional errors during rendering;
diff --git a/src/applications/search/exception/PhabricatorSearchConstraintException.php b/src/applications/search/exception/PhabricatorSearchConstraintException.php
new file mode 100644
--- /dev/null
+++ b/src/applications/search/exception/PhabricatorSearchConstraintException.php
@@ -0,0 +1,4 @@
+<?php
+
+final class PhabricatorSearchConstraintException
+ extends Exception {}

File Metadata

Mime Type
text/plain
Expires
Mon, Mar 31, 8:58 AM (3 w, 2 d ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7223533
Default Alt Text
D17500.diff (8 KB)

Event Timeline