1
0
Fork 0
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:
Austin McKinley 2018-12-14 15:19:56 -08:00
parent 5e94343c7d
commit b6999c7ef4
4 changed files with 115 additions and 52 deletions

View file

@ -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',

View file

@ -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)

View file

@ -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
*/

View file

@ -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;
}
}