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 @@ -4622,6 +4622,7 @@ '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 @@ 'PhabricatorUserEditorTestCase' => 'PhabricatorTestCase', 'PhabricatorUserEmail' => 'PhabricatorUserDAO', 'PhabricatorUserEmailTestCase' => 'PhabricatorTestCase', + 'PhabricatorUserEmpowerTransaction' => 'PhabricatorUserTransactionType', 'PhabricatorUserFerretEngine' => 'PhabricatorFerretEngine', 'PhabricatorUserFulltextEngine' => 'PhabricatorFulltextEngine', 'PhabricatorUserIconField' => 'PhabricatorUserCustomField', diff --git a/src/applications/people/controller/PhabricatorPeopleEmpowerController.php b/src/applications/people/controller/PhabricatorPeopleEmpowerController.php --- a/src/applications/people/controller/PhabricatorPeopleEmpowerController.php +++ b/src/applications/people/controller/PhabricatorPeopleEmpowerController.php @@ -22,22 +22,26 @@ $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()) + $xactions = array(); + $xactions[] = id(new PhabricatorUserTransaction()) + ->setTransactionType( + PhabricatorUserEmpowerTransaction::TRANSACTIONTYPE) + ->setNewValue(!$user->getIsAdmin()); + + $editor = id(new PhabricatorUserTransactionEditor()) ->setActor($viewer) - ->makeAdminUser($user, !$user->getIsAdmin()); + ->setContentSourceFromRequest($request) + ->setContinueOnMissingFields(true); - return id(new AphrontRedirectResponse())->setURI($done_uri); + 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 @@ } return $this->newDialog() + ->setValidationException($validation_exception) ->setTitle($title) ->setShortTitle($short) ->appendParagraph($body) diff --git a/src/applications/people/editor/PhabricatorUserEditor.php b/src/applications/people/editor/PhabricatorUserEditor.php --- a/src/applications/people/editor/PhabricatorUserEditor.php +++ b/src/applications/people/editor/PhabricatorUserEditor.php @@ -131,45 +131,6 @@ /* -( 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 */ diff --git a/src/applications/people/xaction/PhabricatorUserEmpowerTransaction.php b/src/applications/people/xaction/PhabricatorUserEmpowerTransaction.php new file mode 100644 --- /dev/null +++ b/src/applications/people/xaction/PhabricatorUserEmpowerTransaction.php @@ -0,0 +1,95 @@ +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; + } +}