mirror of
https://we.phorge.it/source/phorge.git
synced 2024-12-23 14:00:56 +01:00
Move admin promotions to modular transactions
Summary: Continue clean up of super-old code. I am pretty proud of "defrocked", but would also consider "dethroned", "ousted", "unseated", "unmade", or "disenfranchised". I feel like there's a word for being kicked out of Hogwarts and having your wizarding powers revoked, but it is not leaping to mind. Test Plan: Promoted/demoted users to/from admin, attempted to demote myself and observed preserved witty text, checked user timelines, checked feed, checked DB for sanity, including `user_logs`. I didn't test exposing this via Conduit to attempt promoting a user without having admin access. Reviewers: epriestley Reviewed By: epriestley Subscribers: Korvin Differential Revision: https://secure.phabricator.com/D19891
This commit is contained in:
parent
5e94343c7d
commit
b6999c7ef4
4 changed files with 115 additions and 52 deletions
|
@ -4622,6 +4622,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorUserEditorTestCase' => 'applications/people/editor/__tests__/PhabricatorUserEditorTestCase.php',
|
||||
'PhabricatorUserEmail' => 'applications/people/storage/PhabricatorUserEmail.php',
|
||||
'PhabricatorUserEmailTestCase' => 'applications/people/storage/__tests__/PhabricatorUserEmailTestCase.php',
|
||||
'PhabricatorUserEmpowerTransaction' => 'applications/people/xaction/PhabricatorUserEmpowerTransaction.php',
|
||||
'PhabricatorUserFerretEngine' => 'applications/people/search/PhabricatorUserFerretEngine.php',
|
||||
'PhabricatorUserFulltextEngine' => 'applications/people/search/PhabricatorUserFulltextEngine.php',
|
||||
'PhabricatorUserIconField' => 'applications/people/customfield/PhabricatorUserIconField.php',
|
||||
|
@ -10683,6 +10684,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorUserEditorTestCase' => 'PhabricatorTestCase',
|
||||
'PhabricatorUserEmail' => 'PhabricatorUserDAO',
|
||||
'PhabricatorUserEmailTestCase' => 'PhabricatorTestCase',
|
||||
'PhabricatorUserEmpowerTransaction' => 'PhabricatorUserTransactionType',
|
||||
'PhabricatorUserFerretEngine' => 'PhabricatorFerretEngine',
|
||||
'PhabricatorUserFulltextEngine' => 'PhabricatorFulltextEngine',
|
||||
'PhabricatorUserIconField' => 'PhabricatorUserCustomField',
|
||||
|
|
|
@ -22,22 +22,26 @@ final class PhabricatorPeopleEmpowerController
|
|||
$request,
|
||||
$done_uri);
|
||||
|
||||
if ($user->getPHID() == $viewer->getPHID()) {
|
||||
return $this->newDialog()
|
||||
->setTitle(pht('Your Way is Blocked'))
|
||||
->appendParagraph(
|
||||
pht(
|
||||
'After a time, your efforts fail. You can not adjust your own '.
|
||||
'status as an administrator.'))
|
||||
->addCancelButton($done_uri, pht('Accept Fate'));
|
||||
}
|
||||
$validation_exception = null;
|
||||
|
||||
if ($request->isFormPost()) {
|
||||
id(new PhabricatorUserEditor())
|
||||
->setActor($viewer)
|
||||
->makeAdminUser($user, !$user->getIsAdmin());
|
||||
$xactions = array();
|
||||
$xactions[] = id(new PhabricatorUserTransaction())
|
||||
->setTransactionType(
|
||||
PhabricatorUserEmpowerTransaction::TRANSACTIONTYPE)
|
||||
->setNewValue(!$user->getIsAdmin());
|
||||
|
||||
return id(new AphrontRedirectResponse())->setURI($done_uri);
|
||||
$editor = id(new PhabricatorUserTransactionEditor())
|
||||
->setActor($viewer)
|
||||
->setContentSourceFromRequest($request)
|
||||
->setContinueOnMissingFields(true);
|
||||
|
||||
try {
|
||||
$editor->applyTransactions($user, $xactions);
|
||||
return id(new AphrontRedirectResponse())->setURI($done_uri);
|
||||
} catch (PhabricatorApplicationTransactionValidationException $ex) {
|
||||
$validation_exception = $ex;
|
||||
}
|
||||
}
|
||||
|
||||
if ($user->getIsAdmin()) {
|
||||
|
@ -60,6 +64,7 @@ final class PhabricatorPeopleEmpowerController
|
|||
}
|
||||
|
||||
return $this->newDialog()
|
||||
->setValidationException($validation_exception)
|
||||
->setTitle($title)
|
||||
->setShortTitle($short)
|
||||
->appendParagraph($body)
|
||||
|
|
|
@ -131,45 +131,6 @@ final class PhabricatorUserEditor extends PhabricatorEditor {
|
|||
|
||||
/* -( Editing Roles )------------------------------------------------------ */
|
||||
|
||||
|
||||
/**
|
||||
* @task role
|
||||
*/
|
||||
public function makeAdminUser(PhabricatorUser $user, $admin) {
|
||||
$actor = $this->requireActor();
|
||||
|
||||
if (!$user->getID()) {
|
||||
throw new Exception(pht('User has not been created yet!'));
|
||||
}
|
||||
|
||||
$user->openTransaction();
|
||||
$user->beginWriteLocking();
|
||||
|
||||
$user->reload();
|
||||
if ($user->getIsAdmin() == $admin) {
|
||||
$user->endWriteLocking();
|
||||
$user->killTransaction();
|
||||
return $this;
|
||||
}
|
||||
|
||||
$log = PhabricatorUserLog::initializeNewLog(
|
||||
$actor,
|
||||
$user->getPHID(),
|
||||
PhabricatorUserLog::ACTION_ADMIN);
|
||||
$log->setOldValue($user->getIsAdmin());
|
||||
$log->setNewValue($admin);
|
||||
|
||||
$user->setIsAdmin((int)$admin);
|
||||
$user->save();
|
||||
|
||||
$log->save();
|
||||
|
||||
$user->endWriteLocking();
|
||||
$user->saveTransaction();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @task role
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorUserEmpowerTransaction
|
||||
extends PhabricatorUserTransactionType {
|
||||
|
||||
const TRANSACTIONTYPE = 'user.admin';
|
||||
|
||||
public function generateOldValue($object) {
|
||||
return (bool)$object->getIsAdmin();
|
||||
}
|
||||
|
||||
public function generateNewValue($object, $value) {
|
||||
return (bool)$value;
|
||||
}
|
||||
|
||||
public function applyInternalEffects($object, $value) {
|
||||
$object->setIsAdmin((int)$value);
|
||||
}
|
||||
|
||||
public function applyExternalEffects($object, $value) {
|
||||
$user = $object;
|
||||
|
||||
$this->newUserLog(PhabricatorUserLog::ACTION_ADMIN)
|
||||
->setOldValue($this->getOldValue())
|
||||
->setNewValue($value)
|
||||
->save();
|
||||
}
|
||||
|
||||
public function validateTransactions($object, array $xactions) {
|
||||
$user = $object;
|
||||
$actor = $this->getActor();
|
||||
|
||||
$errors = array();
|
||||
foreach ($xactions as $xaction) {
|
||||
$old = $xaction->getOldValue();
|
||||
$new = $xaction->getNewValue();
|
||||
|
||||
if ($old === $new) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($user->getPHID() === $actor->getPHID()) {
|
||||
$errors[] = $this->newInvalidError(
|
||||
pht('After a time, your efforts fail. You can not adjust your own '.
|
||||
'status as an administrator.'), $xaction);
|
||||
}
|
||||
|
||||
if (!$actor->getIsAdmin()) {
|
||||
$errors[] = $this->newInvalidError(
|
||||
pht('You must be an administrator to create administrators.'),
|
||||
$xaction);
|
||||
}
|
||||
}
|
||||
|
||||
return $errors;
|
||||
}
|
||||
|
||||
public function getTitle() {
|
||||
$new = $this->getNewValue();
|
||||
if ($new) {
|
||||
return pht(
|
||||
'%s empowered this user as an administrator.',
|
||||
$this->renderAuthor());
|
||||
} else {
|
||||
return pht(
|
||||
'%s defrocked this user.',
|
||||
$this->renderAuthor());
|
||||
}
|
||||
}
|
||||
|
||||
public function getTitleForFeed() {
|
||||
$new = $this->getNewValue();
|
||||
if ($new) {
|
||||
return pht(
|
||||
'%s empowered %s as an administrator.',
|
||||
$this->renderAuthor(),
|
||||
$this->renderObject());
|
||||
} else {
|
||||
return pht(
|
||||
'%s defrocked %s.',
|
||||
$this->renderAuthor(),
|
||||
$this->renderObject());
|
||||
}
|
||||
}
|
||||
|
||||
public function getRequiredCapabilities(
|
||||
$object,
|
||||
PhabricatorApplicationTransaction $xaction) {
|
||||
|
||||
// Unlike normal user edits, admin promotions require admin
|
||||
// permissions, which is enforced by validateTransactions().
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue