@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Move user renames to modular transactions

Summary: Cleaning up more super-old code from `PhabricatorUserEditor`. Also fix user logging in approve transactions. I'm not sure how it worked at all previously.

Test Plan: Created new users, renamed them, checked DB for sanity. Entered invalid names, duplicate names, and empty names, got appropriate error messages.

Reviewers: epriestley

Reviewed By: epriestley

Subscribers: Korvin

Differential Revision: https://secure.phabricator.com/D19887

+115 -80
+2
src/__phutil_library_map__.php
··· 4646 4646 'PhabricatorUserTransaction' => 'applications/people/storage/PhabricatorUserTransaction.php', 4647 4647 'PhabricatorUserTransactionEditor' => 'applications/people/editor/PhabricatorUserTransactionEditor.php', 4648 4648 'PhabricatorUserTransactionType' => 'applications/people/xaction/PhabricatorUserTransactionType.php', 4649 + 'PhabricatorUserUsernameTransaction' => 'applications/people/xaction/PhabricatorUserUsernameTransaction.php', 4649 4650 'PhabricatorUsersEditField' => 'applications/transactions/editfield/PhabricatorUsersEditField.php', 4650 4651 'PhabricatorUsersPolicyRule' => 'applications/people/policyrule/PhabricatorUsersPolicyRule.php', 4651 4652 'PhabricatorUsersSearchField' => 'applications/people/searchfield/PhabricatorUsersSearchField.php', ··· 10706 10707 'PhabricatorUserTransaction' => 'PhabricatorModularTransaction', 10707 10708 'PhabricatorUserTransactionEditor' => 'PhabricatorApplicationTransactionEditor', 10708 10709 'PhabricatorUserTransactionType' => 'PhabricatorModularTransactionType', 10710 + 'PhabricatorUserUsernameTransaction' => 'PhabricatorUserTransactionType', 10709 10711 'PhabricatorUsersEditField' => 'PhabricatorTokenizerEditField', 10710 10712 'PhabricatorUsersPolicyRule' => 'PhabricatorPolicyRule', 10711 10713 'PhabricatorUsersSearchField' => 'PhabricatorSearchTokenizerField',
+21 -33
src/applications/people/controller/PhabricatorPeopleRenameController.php
··· 22 22 $request, 23 23 $done_uri); 24 24 25 - $errors = array(); 26 - 27 - $v_username = $user->getUsername(); 28 - $e_username = true; 25 + $validation_exception = null; 26 + $username = $user->getUsername(); 29 27 if ($request->isFormPost()) { 30 - $v_username = $request->getStr('username'); 28 + $username = $request->getStr('username'); 29 + $xactions = array(); 31 30 32 - if (!strlen($v_username)) { 33 - $e_username = pht('Required'); 34 - $errors[] = pht('New username is required.'); 35 - } else if ($v_username == $user->getUsername()) { 36 - $e_username = pht('Invalid'); 37 - $errors[] = pht('New username must be different from old username.'); 38 - } else if (!PhabricatorUser::validateUsername($v_username)) { 39 - $e_username = pht('Invalid'); 40 - $errors[] = PhabricatorUser::describeValidUsername(); 41 - } 31 + $xactions[] = id(new PhabricatorUserTransaction()) 32 + ->setTransactionType( 33 + PhabricatorUserUsernameTransaction::TRANSACTIONTYPE) 34 + ->setNewValue($username); 42 35 43 - if (!$errors) { 44 - try { 45 - id(new PhabricatorUserEditor()) 46 - ->setActor($viewer) 47 - ->changeUsername($user, $v_username); 36 + $editor = id(new PhabricatorUserTransactionEditor()) 37 + ->setActor($viewer) 38 + ->setContentSourceFromRequest($request) 39 + ->setContinueOnMissingFields(true); 48 40 49 - return id(new AphrontRedirectResponse())->setURI($done_uri); 50 - } catch (AphrontDuplicateKeyQueryException $ex) { 51 - $e_username = pht('Not Unique'); 52 - $errors[] = pht('Another user already has that username.'); 53 - } 41 + try { 42 + $editor->applyTransactions($user, $xactions); 43 + return id(new AphrontRedirectResponse())->setURI($done_uri); 44 + } catch (PhabricatorApplicationTransactionValidationException $ex) { 45 + $validation_exception = $ex; 54 46 } 47 + 55 48 } 56 49 57 50 $inst1 = pht( ··· 87 80 ->appendChild( 88 81 id(new AphrontFormTextControl()) 89 82 ->setLabel(pht('New Username')) 90 - ->setValue($v_username) 91 - ->setName('username') 92 - ->setError($e_username)); 93 - 94 - if ($errors) { 95 - $errors = id(new PHUIInfoView())->setErrors($errors); 96 - } 83 + ->setValue($username) 84 + ->setName('username')); 97 85 98 86 return $this->newDialog() 99 87 ->setWidth(AphrontDialogView::WIDTH_FORM) 100 88 ->setTitle(pht('Change Username')) 101 - ->appendChild($errors) 89 + ->setValidationException($validation_exception) 102 90 ->appendParagraph($inst1) 103 91 ->appendParagraph($inst2) 104 92 ->appendParagraph($inst3)
-47
src/applications/people/editor/PhabricatorUserEditor.php
··· 129 129 } 130 130 131 131 132 - /** 133 - * @task edit 134 - */ 135 - public function changeUsername(PhabricatorUser $user, $username) { 136 - $actor = $this->requireActor(); 137 - 138 - if (!$user->getID()) { 139 - throw new Exception(pht('User has not been created yet!')); 140 - } 141 - 142 - if (!PhabricatorUser::validateUsername($username)) { 143 - $valid = PhabricatorUser::describeValidUsername(); 144 - throw new Exception(pht('Username is invalid! %s', $valid)); 145 - } 146 - 147 - $old_username = $user->getUsername(); 148 - 149 - $user->openTransaction(); 150 - $user->reload(); 151 - $user->setUsername($username); 152 - 153 - try { 154 - $user->save(); 155 - } catch (AphrontDuplicateKeyQueryException $ex) { 156 - $user->setUsername($old_username); 157 - $user->killTransaction(); 158 - throw $ex; 159 - } 160 - 161 - $log = PhabricatorUserLog::initializeNewLog( 162 - $actor, 163 - $user->getPHID(), 164 - PhabricatorUserLog::ACTION_CHANGE_USERNAME); 165 - $log->setOldValue($old_username); 166 - $log->setNewValue($username); 167 - $log->save(); 168 - 169 - $user->saveTransaction(); 170 - 171 - // The SSH key cache currently includes usernames, so dirty it. See T12554 172 - // for discussion. 173 - PhabricatorAuthSSHKeyQuery::deleteSSHKeyCache(); 174 - 175 - $user->sendUsernameChangeEmail($actor, $old_username); 176 - } 177 - 178 - 179 132 /* -( Editing Roles )------------------------------------------------------ */ 180 133 181 134
+92
src/applications/people/xaction/PhabricatorUserUsernameTransaction.php
··· 1 + <?php 2 + 3 + final class PhabricatorUserUsernameTransaction 4 + extends PhabricatorUserTransactionType { 5 + 6 + const TRANSACTIONTYPE = 'user.rename'; 7 + 8 + public function generateOldValue($object) { 9 + return $object->getUsername(); 10 + } 11 + 12 + public function generateNewValue($object, $value) { 13 + return $value; 14 + } 15 + 16 + public function applyInternalEffects($object, $value) { 17 + $object->setUsername($value); 18 + } 19 + 20 + public function applyExternalEffects($object, $value) { 21 + $user = $object; 22 + 23 + $this->newUserLog(PhabricatorUserLog::ACTION_CHANGE_USERNAME) 24 + ->setOldValue($this->getOldValue()) 25 + ->setNewValue($value) 26 + ->save(); 27 + 28 + // The SSH key cache currently includes usernames, so dirty it. See T12554 29 + // for discussion. 30 + PhabricatorAuthSSHKeyQuery::deleteSSHKeyCache(); 31 + 32 + $user->sendUsernameChangeEmail($this->getActor(), $this->getOldValue()); 33 + } 34 + 35 + public function getTitle() { 36 + return pht( 37 + '%s renamed this user from %s to %s.', 38 + $this->renderAuthor(), 39 + $this->renderOldValue(), 40 + $this->renderNewValue()); 41 + } 42 + 43 + public function validateTransactions($object, array $xactions) { 44 + $actor = $this->getActor(); 45 + $errors = array(); 46 + 47 + foreach ($xactions as $xaction) { 48 + $new = $xaction->getNewValue(); 49 + $old = $xaction->getOldValue(); 50 + 51 + if ($old === $new) { 52 + continue; 53 + } 54 + 55 + if (!$actor->getIsAdmin()) { 56 + $errors[] = $this->newInvalidError( 57 + pht('You must be an administrator to rename users.')); 58 + } 59 + 60 + if (!strlen($new)) { 61 + $errors[] = $this->newRequiredError( 62 + pht('New username is required.'), $xaction); 63 + } else if (!PhabricatorUser::validateUsername($new)) { 64 + $errors[] = $this->newInvalidError( 65 + PhabricatorUser::describeValidUsername(), $xaction); 66 + } 67 + 68 + $user = id(new PhabricatorPeopleQuery()) 69 + ->setViewer(PhabricatorUser::getOmnipotentUser()) 70 + ->withUsernames(array($new)) 71 + ->executeOne(); 72 + 73 + if ($user) { 74 + $errors[] = $this->newInvalidError( 75 + pht('Another user already has that username.'), $xaction); 76 + } 77 + 78 + } 79 + 80 + return $errors; 81 + } 82 + 83 + public function getRequiredCapabilities( 84 + $object, 85 + PhabricatorApplicationTransaction $xaction) { 86 + 87 + // Unlike normal user edits, renames require admin permissions, which 88 + // is enforced by validateTransactions(). 89 + 90 + return null; 91 + } 92 + }