Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F13179958
D19933.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
37 KB
Referenced Files
None
Subscribers
None
D19933.diff
View Options
diff --git a/resources/sql/autopatches/20181222.banish.01.user.sql b/resources/sql/autopatches/20181222.banish.01.user.sql
new file mode 100644
--- /dev/null
+++ b/resources/sql/autopatches/20181222.banish.01.user.sql
@@ -0,0 +1,2 @@
+ALTER TABLE {$NAMESPACE}_user.user
+ ADD isBanished BOOL NOT NULL;
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
@@ -4608,6 +4608,7 @@
'PhabricatorUser' => 'applications/people/storage/PhabricatorUser.php',
'PhabricatorUserApproveTransaction' => 'applications/people/xaction/PhabricatorUserApproveTransaction.php',
'PhabricatorUserBadgesCacheType' => 'applications/people/cache/PhabricatorUserBadgesCacheType.php',
+ 'PhabricatorUserBanishTransaction' => 'applications/people/xaction/PhabricatorUserBanishTransaction.php',
'PhabricatorUserBlurbField' => 'applications/people/customfield/PhabricatorUserBlurbField.php',
'PhabricatorUserCache' => 'applications/people/storage/PhabricatorUserCache.php',
'PhabricatorUserCachePurger' => 'applications/cache/purger/PhabricatorUserCachePurger.php',
@@ -10673,6 +10674,7 @@
),
'PhabricatorUserApproveTransaction' => 'PhabricatorUserTransactionType',
'PhabricatorUserBadgesCacheType' => 'PhabricatorUserCacheType',
+ 'PhabricatorUserBanishTransaction' => 'PhabricatorUserTransactionType',
'PhabricatorUserBlurbField' => 'PhabricatorUserCustomField',
'PhabricatorUserCache' => 'PhabricatorUserDAO',
'PhabricatorUserCachePurger' => 'PhabricatorCachePurger',
diff --git a/src/applications/auth/controller/PhabricatorDisabledUserController.php b/src/applications/auth/controller/PhabricatorDisabledUserController.php
--- a/src/applications/auth/controller/PhabricatorDisabledUserController.php
+++ b/src/applications/auth/controller/PhabricatorDisabledUserController.php
@@ -15,10 +15,18 @@
return new Aphront404Response();
}
+ if ($viewer->getIsBanished()) {
+ $title = pht('Account Banished');
+ $body = pht('Your account has been banished.');
+ } else {
+ $title = pht('Account Disabled');
+ $body = pht('Your account has been disabled.');
+ }
+
return $this->newDialog()
- ->setTitle(pht('Account Disabled'))
- ->addCancelButton('/logout/', pht('Okay'))
- ->appendParagraph(pht('Your account has been disabled.'));
+ ->setTitle($title)
+ ->appendParagraph($body)
+ ->addCancelButton('/logout/', pht('Okay'));
}
}
diff --git a/src/applications/people/application/PhabricatorPeopleApplication.php b/src/applications/people/application/PhabricatorPeopleApplication.php
--- a/src/applications/people/application/PhabricatorPeopleApplication.php
+++ b/src/applications/people/application/PhabricatorPeopleApplication.php
@@ -52,9 +52,7 @@
=> 'PhabricatorPeopleInviteSendController',
),
'approve/(?P<id>[1-9]\d*)/' => 'PhabricatorPeopleApproveController',
- '(?P<via>disapprove)/(?P<id>[1-9]\d*)/'
- => 'PhabricatorPeopleDisableController',
- '(?P<via>disable)/(?P<id>[1-9]\d*)/'
+ '(?P<via>disapprove|disable|banish)/(?P<id>[1-9]\d*)/'
=> 'PhabricatorPeopleDisableController',
'empower/(?P<id>[1-9]\d*)/' => 'PhabricatorPeopleEmpowerController',
'delete/(?P<id>[1-9]\d*)/' => 'PhabricatorPeopleDeleteController',
diff --git a/src/applications/people/controller/PhabricatorPeopleDisableController.php b/src/applications/people/controller/PhabricatorPeopleDisableController.php
--- a/src/applications/people/controller/PhabricatorPeopleDisableController.php
+++ b/src/applications/people/controller/PhabricatorPeopleDisableController.php
@@ -29,6 +29,8 @@
// Disabling via "Disable" requires the permission only.
$is_disapprove = ($via == 'disapprove');
+ $is_banish = ($via == 'banish');
+
if ($is_disapprove) {
$done_uri = $this->getApplicationURI('query/approval/');
@@ -63,15 +65,28 @@
->setTitle(pht('Something Stays Your Hand'))
->appendParagraph(
pht(
- 'Try as you might, you find you can not disable your own account.'))
+ 'Try as you might, you find you can not disable or banish '.
+ 'your own account.'))
->addCancelButton($done_uri, pht('Curses!'));
}
+ // Make the "undisable/unbanish" action always apply the appropriate
+ // type of change, regardless of how the controller was invoked.
+ if (!$should_disable) {
+ $is_banish = $user->getIsBanished();
+ }
+
if ($request->isFormPost()) {
$xactions = array();
+ if ($is_banish) {
+ $xaction_type = PhabricatorUserBanishTransaction::TRANSACTIONTYPE;
+ } else {
+ $xaction_type = PhabricatorUserDisableTransaction::TRANSACTIONTYPE;
+ }
+
$xactions[] = id(new PhabricatorUserTransaction())
- ->setTransactionType(PhabricatorUserDisableTransaction::TRANSACTIONTYPE)
+ ->setTransactionType($xaction_type)
->setNewValue($should_disable);
id(new PhabricatorUserTransactionEditor())
@@ -85,26 +100,52 @@
return id(new AphrontRedirectResponse())->setURI($done_uri);
}
- if ($should_disable) {
- $title = pht('Disable User?');
- $short_title = pht('Disable User');
-
- $body = pht(
- 'Disable %s? They will no longer be able to access Phabricator or '.
- 'receive email.',
- phutil_tag('strong', array(), $user->getUsername()));
+ $display_username = phutil_tag('strong', array(), $user->getUsername());
- $submit = pht('Disable User');
+ if ($should_disable) {
+ if ($is_banish) {
+ $title = pht('Banish User?');
+ $short_title = pht('Banish User');
+
+ $body = pht(
+ 'Banish %s? They will no longer be able to access Phabricator or '.
+ 'receive email, and their profile and comments will be hidden.',
+ $display_username);
+
+ $submit = pht('Banish User');
+ } else {
+ $title = pht('Disable User?');
+ $short_title = pht('Disable User');
+
+ $body = pht(
+ 'Disable %s? They will no longer be able to access Phabricator or '.
+ 'receive email.',
+ $display_username);
+
+ $submit = pht('Disable User');
+ }
} else {
- $title = pht('Enable User?');
- $short_title = pht('Enable User');
-
- $body = pht(
- 'Enable %s? They will be able to access Phabricator and receive '.
- 'email again.',
- phutil_tag('strong', array(), $user->getUsername()));
-
- $submit = pht('Enable User');
+ if ($is_banish) {
+ $title = pht('Unbanish User?');
+ $short_title = pht('Unbanish User');
+
+ $body = pht(
+ 'Unbanish %s? They will be able to access Phabricator and receive '.
+ 'email again, and their profile and comments will become visible.',
+ $display_username);
+
+ $submit = pht('Unbanish User');
+ } else {
+ $title = pht('Enable User?');
+ $short_title = pht('Enable User');
+
+ $body = pht(
+ 'Enable %s? They will be able to access Phabricator and receive '.
+ 'email again.',
+ $display_username);
+
+ $submit = pht('Enable User');
+ }
}
return $this->newDialog()
diff --git a/src/applications/people/controller/PhabricatorPeopleProfileBadgesController.php b/src/applications/people/controller/PhabricatorPeopleProfileBadgesController.php
--- a/src/applications/people/controller/PhabricatorPeopleProfileBadgesController.php
+++ b/src/applications/people/controller/PhabricatorPeopleProfileBadgesController.php
@@ -16,6 +16,11 @@
return new Aphront404Response();
}
+ $response = $this->newProfileAccessResponse($user);
+ if ($response) {
+ return $response;
+ }
+
$class = 'PhabricatorBadgesApplication';
if (!PhabricatorApplication::isClassInstalledForViewer($class, $viewer)) {
return new Aphront404Response();
diff --git a/src/applications/people/controller/PhabricatorPeopleProfileCommitsController.php b/src/applications/people/controller/PhabricatorPeopleProfileCommitsController.php
--- a/src/applications/people/controller/PhabricatorPeopleProfileCommitsController.php
+++ b/src/applications/people/controller/PhabricatorPeopleProfileCommitsController.php
@@ -18,6 +18,11 @@
return new Aphront404Response();
}
+ $response = $this->newProfileAccessResponse($user);
+ if ($response) {
+ return $response;
+ }
+
$class = 'PhabricatorDiffusionApplication';
if (!PhabricatorApplication::isClassInstalledForViewer($class, $viewer)) {
return new Aphront404Response();
diff --git a/src/applications/people/controller/PhabricatorPeopleProfileController.php b/src/applications/people/controller/PhabricatorPeopleProfileController.php
--- a/src/applications/people/controller/PhabricatorPeopleProfileController.php
+++ b/src/applications/people/controller/PhabricatorPeopleProfileController.php
@@ -74,6 +74,9 @@
if ($user->getIsAdmin()) {
$roles[] = pht('Administrator');
}
+ if ($user->getIsBanished()) {
+ $roles[] = pht('Banished');
+ }
if ($user->getIsDisabled()) {
$roles[] = pht('Disabled');
}
@@ -106,7 +109,9 @@
require_celerity_resource('project-view-css');
- if ($user->getIsDisabled()) {
+ if ($user->getIsBanished()) {
+ $header->setStatus('fa-gavel', 'red', pht('Banished'));
+ } else if ($user->getIsDisabled()) {
$header->setStatus('fa-ban', 'red', pht('Disabled'));
} else {
$header->setStatus($profile_icon, 'bluegrey', $profile_title);
@@ -125,4 +130,23 @@
return $header;
}
+ protected function newProfileAccessResponse(PhabricatorUser $user) {
+ if ($user->getIsBanished()) {
+ $has_disable = $this->hasApplicationCapability(
+ PeopleDisableUsersCapability::CAPABILITY);
+
+ if (!$has_disable) {
+ return $this->newDialog()
+ ->setTitle(pht('User Banished'))
+ ->appendParagraph(
+ pht(
+ 'This user has been banished. You must have the '.
+ '"Can Disable Users" permission to view their profile.'))
+ ->addCancelButton('/', pht('Done'));
+ }
+ }
+
+ return null;
+ }
+
}
diff --git a/src/applications/people/controller/PhabricatorPeopleProfileManageController.php b/src/applications/people/controller/PhabricatorPeopleProfileManageController.php
--- a/src/applications/people/controller/PhabricatorPeopleProfileManageController.php
+++ b/src/applications/people/controller/PhabricatorPeopleProfileManageController.php
@@ -22,6 +22,11 @@
return new Aphront404Response();
}
+ $response = $this->newProfileAccessResponse($user);
+ if ($response) {
+ return $response;
+ }
+
$this->setUser($user);
$header = $this->buildProfileHeader();
@@ -144,12 +149,29 @@
->setWorkflow(true)
->setHref($this->getApplicationURI('rename/'.$user->getID().'/')));
- if ($user->getIsDisabled()) {
+ $curtain->addAction(
+ id(new PhabricatorActionView())
+ ->setIcon('fa-envelope')
+ ->setName(pht('Send Welcome Email'))
+ ->setWorkflow(true)
+ ->setDisabled(!$can_welcome)
+ ->setHref($this->getApplicationURI('welcome/'.$user->getID().'/')));
+
+ $curtain->addAction(
+ id(new PhabricatorActionView())
+ ->setType(PhabricatorActionView::TYPE_DIVIDER));
+
+ $show_banish = false;
+ if ($user->getIsBanished()) {
+ $disable_icon = 'fa-check-circle-o';
+ $disable_name = pht('Unbanish User');
+ } else if ($user->getIsDisabled()) {
$disable_icon = 'fa-check-circle-o';
$disable_name = pht('Enable User');
} else {
$disable_icon = 'fa-ban';
$disable_name = pht('Disable User');
+ $show_banish = true;
}
$curtain->addAction(
@@ -160,6 +182,16 @@
->setWorkflow(true)
->setHref($this->getApplicationURI('disable/'.$user->getID().'/')));
+ if ($show_banish) {
+ $curtain->addAction(
+ id(new PhabricatorActionView())
+ ->setIcon('fa-gavel')
+ ->setName(pht('Banish User'))
+ ->setDisabled(!$can_disable)
+ ->setWorkflow(true)
+ ->setHref($this->getApplicationURI('banish/'.$user->getID().'/')));
+ }
+
$curtain->addAction(
id(new PhabricatorActionView())
->setIcon('fa-times')
@@ -170,11 +202,7 @@
$curtain->addAction(
id(new PhabricatorActionView())
- ->setIcon('fa-envelope')
- ->setName(pht('Send Welcome Email'))
- ->setWorkflow(true)
- ->setDisabled(!$can_welcome)
- ->setHref($this->getApplicationURI('welcome/'.$user->getID().'/')));
+ ->setType(PhabricatorActionView::TYPE_DIVIDER));
return $curtain;
}
diff --git a/src/applications/people/controller/PhabricatorPeopleProfileRevisionsController.php b/src/applications/people/controller/PhabricatorPeopleProfileRevisionsController.php
--- a/src/applications/people/controller/PhabricatorPeopleProfileRevisionsController.php
+++ b/src/applications/people/controller/PhabricatorPeopleProfileRevisionsController.php
@@ -18,6 +18,11 @@
return new Aphront404Response();
}
+ $response = $this->newProfileAccessResponse($user);
+ if ($response) {
+ return $response;
+ }
+
$class = 'PhabricatorDifferentialApplication';
if (!PhabricatorApplication::isClassInstalledForViewer($class, $viewer)) {
return new Aphront404Response();
diff --git a/src/applications/people/controller/PhabricatorPeopleProfileTasksController.php b/src/applications/people/controller/PhabricatorPeopleProfileTasksController.php
--- a/src/applications/people/controller/PhabricatorPeopleProfileTasksController.php
+++ b/src/applications/people/controller/PhabricatorPeopleProfileTasksController.php
@@ -18,6 +18,11 @@
return new Aphront404Response();
}
+ $response = $this->newProfileAccessResponse($user);
+ if ($response) {
+ return $response;
+ }
+
$class = 'PhabricatorManiphestApplication';
if (!PhabricatorApplication::isClassInstalledForViewer($class, $viewer)) {
return new Aphront404Response();
diff --git a/src/applications/people/controller/PhabricatorPeopleProfileViewController.php b/src/applications/people/controller/PhabricatorPeopleProfileViewController.php
--- a/src/applications/people/controller/PhabricatorPeopleProfileViewController.php
+++ b/src/applications/people/controller/PhabricatorPeopleProfileViewController.php
@@ -21,6 +21,11 @@
return new Aphront404Response();
}
+ $response = $this->newProfileAccessResponse($user);
+ if ($response) {
+ return $response;
+ }
+
$this->setUser($user);
$header = $this->buildProfileHeader();
diff --git a/src/applications/people/phid/PhabricatorPeopleUserPHIDType.php b/src/applications/people/phid/PhabricatorPeopleUserPHIDType.php
--- a/src/applications/people/phid/PhabricatorPeopleUserPHIDType.php
+++ b/src/applications/people/phid/PhabricatorPeopleUserPHIDType.php
@@ -38,14 +38,21 @@
foreach ($handles as $phid => $handle) {
$user = $objects[$phid];
- $realname = $user->getRealName();
$username = $user->getUsername();
+ if ($user->getIsBanished()) {
+ $profile_image = celerity_get_resource_uri('/rsrc/image/avatar.png');
+ $full_name = $username;
+ } else {
+ $profile_image = $user->getProfileImageURI();
+ $full_name = $user->getFullName();
+ }
+
$handle
->setName($username)
->setURI('/p/'.$username.'/')
- ->setFullName($user->getFullName())
- ->setImageURI($user->getProfileImageURI())
+ ->setFullName($full_name)
+ ->setImageURI($profile_image)
->setMailStampName('@'.$username);
if ($user->getIsMailingList()) {
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
@@ -19,6 +19,7 @@
private $nameTokens;
private $namePrefixes;
private $isEnrolledInMultiFactor;
+ private $isBanished;
private $needPrimaryEmail;
private $needProfile;
@@ -87,6 +88,11 @@
return $this;
}
+ public function withIsBanished($banished) {
+ $this->isBanished = $banished;
+ return $this;
+ }
+
public function withNameLike($like) {
$this->nameLike = $like;
return $this;
@@ -356,6 +362,13 @@
(int)$this->isEnrolledInMultiFactor);
}
+ if ($this->isBanished !== null) {
+ $where[] = qsprintf(
+ $conn,
+ 'user.isBanished = %d',
+ (int)$this->isBanished);
+ }
+
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
@@ -84,6 +84,17 @@
pht(
'Pass true to find only users awaiting administrative approval, '.
'or false to omit these users.')),
+ id(new PhabricatorSearchThreeStateField())
+ ->setLabel(pht('Banished'))
+ ->setKey('banished')
+ ->setOptions(
+ pht('(Show All)'),
+ pht('Show Only Banished Users'),
+ pht('Hide Banished Users'))
+ ->setDescription(
+ pht(
+ 'Pass true to find only users who have been banished, '.
+ 'or false to omit these users.')),
);
$viewer = $this->requireViewer();
@@ -169,6 +180,10 @@
$query->withIsApproved(!$map['needsApproval']);
}
+ if ($map['banished'] !== null) {
+ $query->withIsBanished($map['banished']);
+ }
+
if (idx($map, 'mfa') !== null) {
$viewer = $this->requireViewer();
if (!$viewer->getIsAdmin()) {
@@ -263,7 +278,10 @@
$item->addAttribute($primary_email->getAddress());
}
- if ($user->getIsDisabled()) {
+ if ($user->getIsBanished()) {
+ $item->addIcon('fa-gavel', pht('Banished'));
+ $item->setDisabled(true);
+ } else if ($user->getIsDisabled()) {
$item->addIcon('fa-ban', pht('Disabled'));
$item->setDisabled(true);
}
@@ -336,9 +354,15 @@
$export = array();
foreach ($users as $user) {
+ if ($user->getIsBanished()) {
+ $real_name = null;
+ } else {
+ $real_name = $user->getRealName();
+ }
+
$export[] = array(
'username' => $user->getUsername(),
- 'realName' => $user->getRealName(),
+ 'realName' => $real_name,
);
}
diff --git a/src/applications/people/storage/PhabricatorUser.php b/src/applications/people/storage/PhabricatorUser.php
--- a/src/applications/people/storage/PhabricatorUser.php
+++ b/src/applications/people/storage/PhabricatorUser.php
@@ -44,6 +44,7 @@
protected $isEmailVerified = 0;
protected $isApproved = 0;
protected $isEnrolledInMultiFactor = 0;
+ protected $isBanished = 0;
protected $accountSecret;
@@ -113,6 +114,10 @@
return false;
}
+ if ($this->getIsBanished()) {
+ return false;
+ }
+
if (PhabricatorUserEmail::isEmailVerificationRequired()) {
if (!$this->getIsEmailVerified()) {
return false;
@@ -229,6 +234,7 @@
'availabilityCacheTTL' => 'uint32?',
'defaultProfileImagePHID' => 'phid?',
'defaultProfileImageVersion' => 'text64?',
+ 'isBanished' => 'bool',
),
self::CONFIG_KEY_SCHEMA => array(
'key_phid' => null,
@@ -246,6 +252,9 @@
'key_approved' => array(
'columns' => array('isApproved'),
),
+ 'key_banished' => array(
+ 'columns' => array('isBanished'),
+ ),
),
self::CONFIG_NO_MUTATE => array(
'availabilityCache' => true,
@@ -1443,9 +1452,19 @@
$roles[] = 'activated';
}
+ if ($this->getIsBanished()) {
+ $roles[] = 'banished';
+ }
+
+ if ($this->getIsBanished()) {
+ $real_name = null;
+ } else {
+ $real_name = $this->getRealName();
+ }
+
return array(
'username' => $this->getUsername(),
- 'realName' => $this->getRealName(),
+ 'realName' => $real_name,
'roles' => $roles,
);
}
diff --git a/src/applications/people/storage/PhabricatorUserLog.php b/src/applications/people/storage/PhabricatorUserLog.php
--- a/src/applications/people/storage/PhabricatorUserLog.php
+++ b/src/applications/people/storage/PhabricatorUserLog.php
@@ -18,6 +18,7 @@
const ACTION_SYSTEM_AGENT = 'system-agent';
const ACTION_MAILING_LIST = 'mailing-list';
const ACTION_DISABLE = 'disable';
+ const ACTION_BANISH = 'banish';
const ACTION_APPROVE = 'approve';
const ACTION_DELETE = 'delete';
@@ -83,6 +84,7 @@
self::ACTION_FAIL_HISEC => pht('Hisec: Failed Attempt'),
self::ACTION_MULTI_ADD => pht('Multi-Factor: Add Factor'),
self::ACTION_MULTI_REMOVE => pht('Multi-Factor: Remove Factor'),
+ self::ACTION_BANISH => pht('Banish'),
);
}
diff --git a/src/applications/people/xaction/PhabricatorUserDisableTransaction.php b/src/applications/people/xaction/PhabricatorUserBanishTransaction.php
copy from src/applications/people/xaction/PhabricatorUserDisableTransaction.php
copy to src/applications/people/xaction/PhabricatorUserBanishTransaction.php
--- a/src/applications/people/xaction/PhabricatorUserDisableTransaction.php
+++ b/src/applications/people/xaction/PhabricatorUserBanishTransaction.php
@@ -1,12 +1,12 @@
<?php
-final class PhabricatorUserDisableTransaction
+final class PhabricatorUserBanishTransaction
extends PhabricatorUserTransactionType {
- const TRANSACTIONTYPE = 'user.disable';
+ const TRANSACTIONTYPE = 'user.banish';
public function generateOldValue($object) {
- return (bool)$object->getIsDisabled();
+ return (bool)$object->getIsBanished();
}
public function generateNewValue($object, $value) {
@@ -14,12 +14,14 @@
}
public function applyInternalEffects($object, $value) {
- $object->setIsDisabled((int)$value);
+ $object
+ ->setIsDisabled((int)$value)
+ ->setIsBanished((int)$value);
}
public function applyExternalEffects($object, $value) {
$this->newUserLog(PhabricatorUserLog::ACTION_DISABLE)
- ->setOldValue((bool)$object->getIsDisabled())
+ ->setOldValue((bool)$object->getIsBanished())
->setNewValue((bool)$value)
->save();
}
@@ -28,18 +30,16 @@
$new = $this->getNewValue();
if ($new) {
return pht(
- '%s disabled this user.',
+ '%s banished this user to the shadow realm.',
$this->renderAuthor());
} else {
return pht(
- '%s enabled this user.',
+ '%s unbanished this user.',
$this->renderAuthor());
}
}
public function shouldHideForFeed() {
- // Don't publish feed stories about disabling users, since this can be
- // a sensitive action.
return true;
}
@@ -47,19 +47,19 @@
$errors = array();
foreach ($xactions as $xaction) {
- $is_disabled = (bool)$object->getIsDisabled();
+ $is_banished = (bool)$object->getIsBanished();
- if ((bool)$xaction->getNewValue() === $is_disabled) {
+ if ((bool)$xaction->getNewValue() === $is_banished) {
continue;
}
- // You must have the "Can Disable Users" permission to disable a user.
+ // You must have the "Can Disable Users" permission to banish a user.
$this->requireApplicationCapability(
PeopleDisableUsersCapability::CAPABILITY);
if ($this->getActingAsPHID() === $object->getPHID()) {
$errors[] = $this->newInvalidError(
- pht('You can not enable or disable your own account.'));
+ pht('You can not banish or unbanish your own account.'));
}
}
@@ -69,11 +69,6 @@
public function getRequiredCapabilities(
$object,
PhabricatorApplicationTransaction $xaction) {
-
- // You do not need to be able to edit users to disable them. Instead, this
- // requirement is replaced with a requirement that you have the "Can
- // Disable Users" permission.
-
return null;
}
}
diff --git a/src/applications/people/xaction/PhabricatorUserDisableTransaction.php b/src/applications/people/xaction/PhabricatorUserDisableTransaction.php
--- a/src/applications/people/xaction/PhabricatorUserDisableTransaction.php
+++ b/src/applications/people/xaction/PhabricatorUserDisableTransaction.php
@@ -53,13 +53,23 @@
continue;
}
+ if ($object->getIsBanished()) {
+ $errors[] = $this->newInvalidError(
+ pht(
+ 'This user has been banished. To restore their account, you '.
+ 'must unbanish them.'),
+ $xaction);
+ continue;
+ }
+
// You must have the "Can Disable Users" permission to disable a user.
$this->requireApplicationCapability(
PeopleDisableUsersCapability::CAPABILITY);
if ($this->getActingAsPHID() === $object->getPHID()) {
$errors[] = $this->newInvalidError(
- pht('You can not enable or disable your own account.'));
+ pht('You can not enable or disable your own account.'),
+ $xaction);
}
}
diff --git a/src/applications/transactions/conduit/TransactionSearchConduitAPIMethod.php b/src/applications/transactions/conduit/TransactionSearchConduitAPIMethod.php
--- a/src/applications/transactions/conduit/TransactionSearchConduitAPIMethod.php
+++ b/src/applications/transactions/conduit/TransactionSearchConduitAPIMethod.php
@@ -104,6 +104,7 @@
->setViewer($viewer)
->setTemplate($template)
->withTransactionPHIDs(mpull($xactions, 'getPHID'))
+ ->needBanishments(true)
->execute();
$comment_map = msort($comment_map, 'getCommentVersion');
@@ -160,9 +161,16 @@
$comment_data = array();
if ($comments) {
$removed = head($comments)->getIsDeleted();
+ $banishment = head($comments)->getBanishment();
foreach ($comments as $comment) {
- if ($removed) {
+ if ($banishment) {
+ // For consistency with the web UI, don't show any of the text if
+ // the author has been banished.
+ $content = array(
+ 'raw' => '',
+ );
+ } else if ($removed) {
// If the most recent version of the comment has been removed,
// don't show the history. This is for consistency with the web
// UI, which also prevents users from retrieving the content of
diff --git a/src/applications/transactions/controller/PhabricatorApplicationTransactionCommentEditController.php b/src/applications/transactions/controller/PhabricatorApplicationTransactionCommentEditController.php
--- a/src/applications/transactions/controller/PhabricatorApplicationTransactionCommentEditController.php
+++ b/src/applications/transactions/controller/PhabricatorApplicationTransactionCommentEditController.php
@@ -9,6 +9,11 @@
$xaction = id(new PhabricatorObjectQuery())
->setViewer($viewer)
->withPHIDs(array($request->getURIData('phid')))
+ ->requireCapabilities(
+ array(
+ PhabricatorPolicyCapability::CAN_VIEW,
+ PhabricatorPolicyCapability::CAN_EDIT,
+ ))
->executeOne();
if (!$xaction) {
return new Aphront404Response();
diff --git a/src/applications/transactions/controller/PhabricatorApplicationTransactionCommentHistoryController.php b/src/applications/transactions/controller/PhabricatorApplicationTransactionCommentHistoryController.php
--- a/src/applications/transactions/controller/PhabricatorApplicationTransactionCommentHistoryController.php
+++ b/src/applications/transactions/controller/PhabricatorApplicationTransactionCommentHistoryController.php
@@ -15,25 +15,20 @@
->withPHIDs(array($phid))
->setViewer($viewer)
->executeOne();
-
if (!$xaction) {
return new Aphront404Response();
}
- if (!$xaction->getComment()) {
- // You can't view history of a transaction with no comments.
- return new Aphront404Response();
- }
-
- if ($xaction->getComment()->getIsRemoved()) {
- // You can't view history of a transaction with a removed comment.
- return new Aphront400Response();
+ $response = $this->newAccessResponse($xaction);
+ if ($response) {
+ return $response;
}
$comments = id(new PhabricatorApplicationTransactionTemplatedCommentQuery())
->setViewer($viewer)
->setTemplate($xaction->getApplicationTransactionCommentObject())
->withTransactionPHIDs(array($xaction->getPHID()))
+ ->needBanishments(true)
->execute();
if (!$comments) {
diff --git a/src/applications/transactions/controller/PhabricatorApplicationTransactionCommentQuoteController.php b/src/applications/transactions/controller/PhabricatorApplicationTransactionCommentQuoteController.php
--- a/src/applications/transactions/controller/PhabricatorApplicationTransactionCommentQuoteController.php
+++ b/src/applications/transactions/controller/PhabricatorApplicationTransactionCommentQuoteController.php
@@ -15,16 +15,9 @@
return new Aphront404Response();
}
- if (!$xaction->getComment()) {
- return new Aphront404Response();
- }
-
- if ($xaction->getComment()->getIsRemoved()) {
- return new Aphront400Response();
- }
-
- if (!$xaction->hasComment()) {
- return new Aphront404Response();
+ $response = $this->newAccessResponse($xaction);
+ if ($response) {
+ return $response;
}
$content = $xaction->getComment()->getContent();
diff --git a/src/applications/transactions/controller/PhabricatorApplicationTransactionCommentRawController.php b/src/applications/transactions/controller/PhabricatorApplicationTransactionCommentRawController.php
--- a/src/applications/transactions/controller/PhabricatorApplicationTransactionCommentRawController.php
+++ b/src/applications/transactions/controller/PhabricatorApplicationTransactionCommentRawController.php
@@ -3,6 +3,10 @@
final class PhabricatorApplicationTransactionCommentRawController
extends PhabricatorApplicationTransactionController {
+ public function shouldAllowPublic() {
+ return true;
+ }
+
public function handleRequest(AphrontRequest $request) {
$viewer = $this->getViewer();
$phid = $request->getURIData('phid');
@@ -11,19 +15,13 @@
->withPHIDs(array($phid))
->setViewer($viewer)
->executeOne();
-
if (!$xaction) {
return new Aphront404Response();
}
- if (!$xaction->getComment()) {
- // You can't view a raw comment if there is no comment.
- return new Aphront404Response();
- }
-
- if ($xaction->getComment()->getIsRemoved()) {
- // You can't view a raw comment if the comment is deleted.
- return new Aphront400Response();
+ $response = $this->newAccessResponse($xaction);
+ if ($response) {
+ return $response;
}
$obj_phid = $xaction->getObjectPHID();
@@ -32,6 +30,8 @@
->withPHIDs(array($obj_phid))
->executeOne();
+ $done_uri = $obj_handle->getURI();
+
$title = pht('Raw Comment');
$body = $xaction->getComment()->getContent();
$addendum = null;
@@ -55,9 +55,8 @@
}
}
}
- $dialog = id(new AphrontDialogView())
- ->setUser($viewer)
- ->addCancelButton($obj_handle->getURI())
+ $dialog = $this->newDialog()
+ ->addCancelButton($done_uri)
->setTitle($title);
$dialog
@@ -73,11 +72,7 @@
$dialog->appendParagraph($addendum);
}
- return id(new AphrontDialogResponse())->setDialog($dialog);
- }
-
- public function shouldAllowPublic() {
- return true;
+ return $dialog;
}
}
diff --git a/src/applications/transactions/controller/PhabricatorApplicationTransactionController.php b/src/applications/transactions/controller/PhabricatorApplicationTransactionController.php
--- a/src/applications/transactions/controller/PhabricatorApplicationTransactionController.php
+++ b/src/applications/transactions/controller/PhabricatorApplicationTransactionController.php
@@ -24,4 +24,49 @@
return $cancel_uri;
}
+ protected function newAccessResponse(
+ PhabricatorApplicationTransaction $xaction) {
+ $viewer = $this->getViewer();
+
+ $comment = $xaction->getComment();
+ if (!$comment) {
+ return new Aphront404Response();
+ }
+
+ $obj_phid = $xaction->getObjectPHID();
+ $obj_handle = id(new PhabricatorHandleQuery())
+ ->setViewer($viewer)
+ ->withPHIDs(array($obj_phid))
+ ->executeOne();
+
+ $done_uri = $obj_handle->getURI();
+
+ if ($comment->getIsRemoved()) {
+ return $this->newDialog()
+ ->setTitle(pht('Comment Removed'))
+ ->appendParagraph(
+ pht('This comment has been removed.'))
+ ->addCancelButton($done_uri);
+ }
+
+ if ($comment->getIsDeleted()) {
+ return $this->newDialog()
+ ->setTitle(pht('Comment Deleted'))
+ ->appendParagraph(
+ pht('This comment has been deleted.'))
+ ->addCancelButton($done_uri);
+ }
+
+ if ($comment->getBanishment()) {
+ return $this->newDialog()
+ ->setTitle(pht('Author Banished'))
+ ->appendParagraph(
+ pht('The user who made this comment has been banished.'))
+ ->addCancelButton($done_uri);
+ }
+
+ return null;
+ }
+
+
}
diff --git a/src/applications/transactions/query/PhabricatorApplicationTransactionCommentQuery.php b/src/applications/transactions/query/PhabricatorApplicationTransactionCommentQuery.php
--- a/src/applications/transactions/query/PhabricatorApplicationTransactionCommentQuery.php
+++ b/src/applications/transactions/query/PhabricatorApplicationTransactionCommentQuery.php
@@ -9,6 +9,7 @@
private $transactionPHIDs;
private $isDeleted;
private $hasTransaction;
+ private $needBanishments;
abstract protected function getTemplate();
@@ -42,6 +43,11 @@
return $this;
}
+ public function needBanishments($banishments) {
+ $this->needBanishments = $banishments;
+ return $this;
+ }
+
protected function loadPage() {
$table = $this->getTemplate();
$conn_r = $table->establishConnection('r');
@@ -118,6 +124,44 @@
return $where;
}
+ protected function didFilterPage(array $comments) {
+ if ($this->needBanishments) {
+ $type_user = PhabricatorPeopleUserPHIDType::TYPECONST;
+
+ $author_phids = array();
+ foreach ($comments as $comment) {
+ $author_phid = $comment->getAuthorPHID();
+ if (!$author_phid) {
+ continue;
+ }
+
+ if (phid_get_type($author_phid) !== $type_user) {
+ continue;
+ }
+
+ $author_phids[$author_phid] = $author_phid;
+ }
+
+ if ($author_phids) {
+ $authors = id(new PhabricatorPeopleQuery())
+ ->setViewer($this->getViewer())
+ ->withPHIDs($author_phids)
+ ->withIsBanished(true)
+ ->execute();
+ $authors = mpull($authors, null, 'getPHID');
+ } else {
+ $authors = array();
+ }
+
+ foreach ($comments as $comment) {
+ $author_phid = $comment->getAuthorPHID();
+ $comment->attachBanishment((bool)idx($authors, $author_phid));
+ }
+ }
+
+ return $comments;
+ }
+
public function getQueryApplicationClass() {
// TODO: Figure out the app via the template?
return null;
diff --git a/src/applications/transactions/query/PhabricatorApplicationTransactionQuery.php b/src/applications/transactions/query/PhabricatorApplicationTransactionQuery.php
--- a/src/applications/transactions/query/PhabricatorApplicationTransactionQuery.php
+++ b/src/applications/transactions/query/PhabricatorApplicationTransactionQuery.php
@@ -89,6 +89,7 @@
->setTemplate($table->getApplicationTransactionCommentObject())
->setViewer($this->getViewer())
->withPHIDs($comment_phids)
+ ->needBanishments(true)
->execute();
$comments = mpull($comments, null, 'getPHID');
}
diff --git a/src/applications/transactions/storage/PhabricatorApplicationTransactionComment.php b/src/applications/transactions/storage/PhabricatorApplicationTransactionComment.php
--- a/src/applications/transactions/storage/PhabricatorApplicationTransactionComment.php
+++ b/src/applications/transactions/storage/PhabricatorApplicationTransactionComment.php
@@ -19,6 +19,7 @@
protected $isDeleted = 0;
private $oldComment = self::ATTACHABLE;
+ private $banishment = self::ATTACHABLE;
abstract public function getApplicationTransactionObject();
@@ -101,6 +102,15 @@
return ($this->oldComment !== self::ATTACHABLE);
}
+ public function attachBanishment($banishment) {
+ $this->banishment = $banishment;
+ return $this;
+ }
+
+ public function getBanishment() {
+ return $this->assertAttached($this->banishment);
+ }
+
/* -( PhabricatorMarkupInterface )----------------------------------------- */
diff --git a/src/applications/transactions/view/PhabricatorApplicationTransactionView.php b/src/applications/transactions/view/PhabricatorApplicationTransactionView.php
--- a/src/applications/transactions/view/PhabricatorApplicationTransactionView.php
+++ b/src/applications/transactions/view/PhabricatorApplicationTransactionView.php
@@ -294,7 +294,10 @@
$comment = $xaction->getComment();
if ($comment) {
- if ($comment->getIsRemoved()) {
+ if ($comment->getBanishment()) {
+ // If the comment author has been banished, don't render anything.
+ return null;
+ } else if ($comment->getIsRemoved()) {
return javelin_tag(
'span',
array(
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Thu, May 9, 9:33 PM (3 w, 3 d ago)
Storage Engine
amazon-s3
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
phabricator/secure/k2/jb/pmkoi4piqe7edynb
Default Alt Text
D19933.diff (37 KB)
Attached To
Mode
D19933: Allow users to be "Banished", hiding their profiles and comments
Attached
Detach File
Event Timeline
Log In to Comment