mirror of
https://we.phorge.it/source/phorge.git
synced 2025-04-01 23:18:15 +02: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',
|
'PhabricatorUserEditorTestCase' => 'applications/people/editor/__tests__/PhabricatorUserEditorTestCase.php',
|
||||||
'PhabricatorUserEmail' => 'applications/people/storage/PhabricatorUserEmail.php',
|
'PhabricatorUserEmail' => 'applications/people/storage/PhabricatorUserEmail.php',
|
||||||
'PhabricatorUserEmailTestCase' => 'applications/people/storage/__tests__/PhabricatorUserEmailTestCase.php',
|
'PhabricatorUserEmailTestCase' => 'applications/people/storage/__tests__/PhabricatorUserEmailTestCase.php',
|
||||||
|
'PhabricatorUserEmpowerTransaction' => 'applications/people/xaction/PhabricatorUserEmpowerTransaction.php',
|
||||||
'PhabricatorUserFerretEngine' => 'applications/people/search/PhabricatorUserFerretEngine.php',
|
'PhabricatorUserFerretEngine' => 'applications/people/search/PhabricatorUserFerretEngine.php',
|
||||||
'PhabricatorUserFulltextEngine' => 'applications/people/search/PhabricatorUserFulltextEngine.php',
|
'PhabricatorUserFulltextEngine' => 'applications/people/search/PhabricatorUserFulltextEngine.php',
|
||||||
'PhabricatorUserIconField' => 'applications/people/customfield/PhabricatorUserIconField.php',
|
'PhabricatorUserIconField' => 'applications/people/customfield/PhabricatorUserIconField.php',
|
||||||
|
@ -10683,6 +10684,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorUserEditorTestCase' => 'PhabricatorTestCase',
|
'PhabricatorUserEditorTestCase' => 'PhabricatorTestCase',
|
||||||
'PhabricatorUserEmail' => 'PhabricatorUserDAO',
|
'PhabricatorUserEmail' => 'PhabricatorUserDAO',
|
||||||
'PhabricatorUserEmailTestCase' => 'PhabricatorTestCase',
|
'PhabricatorUserEmailTestCase' => 'PhabricatorTestCase',
|
||||||
|
'PhabricatorUserEmpowerTransaction' => 'PhabricatorUserTransactionType',
|
||||||
'PhabricatorUserFerretEngine' => 'PhabricatorFerretEngine',
|
'PhabricatorUserFerretEngine' => 'PhabricatorFerretEngine',
|
||||||
'PhabricatorUserFulltextEngine' => 'PhabricatorFulltextEngine',
|
'PhabricatorUserFulltextEngine' => 'PhabricatorFulltextEngine',
|
||||||
'PhabricatorUserIconField' => 'PhabricatorUserCustomField',
|
'PhabricatorUserIconField' => 'PhabricatorUserCustomField',
|
||||||
|
|
|
@ -22,22 +22,26 @@ final class PhabricatorPeopleEmpowerController
|
||||||
$request,
|
$request,
|
||||||
$done_uri);
|
$done_uri);
|
||||||
|
|
||||||
if ($user->getPHID() == $viewer->getPHID()) {
|
$validation_exception = null;
|
||||||
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'));
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($request->isFormPost()) {
|
if ($request->isFormPost()) {
|
||||||
id(new PhabricatorUserEditor())
|
$xactions = array();
|
||||||
->setActor($viewer)
|
$xactions[] = id(new PhabricatorUserTransaction())
|
||||||
->makeAdminUser($user, !$user->getIsAdmin());
|
->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()) {
|
if ($user->getIsAdmin()) {
|
||||||
|
@ -60,6 +64,7 @@ final class PhabricatorPeopleEmpowerController
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->newDialog()
|
return $this->newDialog()
|
||||||
|
->setValidationException($validation_exception)
|
||||||
->setTitle($title)
|
->setTitle($title)
|
||||||
->setShortTitle($short)
|
->setShortTitle($short)
|
||||||
->appendParagraph($body)
|
->appendParagraph($body)
|
||||||
|
|
|
@ -131,45 +131,6 @@ final class PhabricatorUserEditor extends PhabricatorEditor {
|
||||||
|
|
||||||
/* -( Editing Roles )------------------------------------------------------ */
|
/* -( 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
|
* @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…
Add table
Reference in a new issue