Skip to content

Commit 70fd960

Browse files
author
epriestley
committedMay 25, 2012
Consolidate user editing code
Summary: - We currently have some bugs in account creation due to nontransactional user/email editing. - We save $user, then try to save $email. This may fail for various reasons, commonly because the email isn't unique. - This leaves us with a $user with no email. - Also, logging of edits is somewhat inconsistent across various edit mechanisms. - Move all editing to a `PhabricatorUserEditor` class. - Handle some broken-data cases more gracefully. Test Plan: - Created and edited a user with `accountadmin`. - Created a user with `add_user.php` - Created and edited a user with People editor. - Created a user with OAuth. - Edited user information via Settings. - Tried to create an OAuth user with a duplicate email address, got a proper error. - Tried to create a user via People with a duplicate email address, got a proper error. Reviewers: btrahan, vrana, jungejason Reviewed By: btrahan CC: tberman, aran Maniphest Tasks: T1184 Differential Revision: https://secure.phabricator.com/D2569
1 parent eb31088 commit 70fd960

16 files changed

+502
-87
lines changed
 

‎scripts/user/account_admin.php

+24-16
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,6 @@
121121
$set_admin = phutil_console_confirm(
122122
'Should this user be an administrator?',
123123
$default_no = !$is_admin);
124-
$user->setIsAdmin($set_admin);
125124

126125
echo "\n\nACCOUNT SUMMARY\n\n";
127126
$tpl = "%12s %-30s %-30s\n";
@@ -149,21 +148,30 @@
149148
exit(1);
150149
}
151150

152-
$user->save();
153-
if ($changed_pass !== false) {
154-
// This must happen after saving the user because we use their PHID as a
155-
// component of the password hash.
156-
$user->setPassword($changed_pass);
157-
$user->save();
158-
}
151+
$user->openTransaction();
159152

160-
if ($new_email) {
161-
id(new PhabricatorUserEmail())
162-
->setUserPHID($user->getPHID())
163-
->setAddress($new_email)
164-
->setIsVerified(1)
165-
->setIsPrimary(1)
166-
->save();
167-
}
153+
$editor = new PhabricatorUserEditor();
154+
155+
// TODO: This is wrong, but we have a chicken-and-egg problem when you use
156+
// this script to create the first user.
157+
$editor->setActor($user);
158+
159+
if ($new_email) {
160+
$email = id(new PhabricatorUserEmail())
161+
->setAddress($new_email)
162+
->setIsVerified(1);
163+
164+
$editor->createNewUser($user, $email);
165+
} else {
166+
$editor->updateUser($user);
167+
}
168+
169+
$editor->makeAdminUser($user, $set_admin);
170+
171+
if ($changed_pass !== false) {
172+
$editor->changePassword($user, $changed_pass);
173+
}
174+
175+
$user->saveTransaction();
168176

169177
echo "Saved changes.\n";

‎scripts/user/add_user.php

+5-5
Original file line numberDiff line numberDiff line change
@@ -61,14 +61,14 @@
6161
$user = new PhabricatorUser();
6262
$user->setUsername($username);
6363
$user->setRealname($realname);
64-
$user->save();
6564

6665
$email_object = id(new PhabricatorUserEmail())
67-
->setUserPHID($user->getPHID())
6866
->setAddress($email)
69-
->setIsVerified(1)
70-
->setIsPrimary(1)
71-
->save();
67+
->setIsVerified(1);
68+
69+
id(new PhabricatorUserEditor())
70+
->setActor($admin)
71+
->createNewUser($user, $email_object);
7272

7373
$user->sendWelcomeEmail($admin);
7474

‎src/__phutil_library_map__.php

+1
Original file line numberDiff line numberDiff line change
@@ -956,6 +956,7 @@
956956
'PhabricatorUserAccountSettingsPanelController' => 'applications/people/controller/settings/panels/account',
957957
'PhabricatorUserConduitSettingsPanelController' => 'applications/people/controller/settings/panels/conduit',
958958
'PhabricatorUserDAO' => 'applications/people/storage/base',
959+
'PhabricatorUserEditor' => 'applications/people/editor',
959960
'PhabricatorUserEmail' => 'applications/people/storage/email',
960961
'PhabricatorUserEmailPreferenceSettingsPanelController' => 'applications/people/controller/settings/panels/emailpref',
961962
'PhabricatorUserEmailSettingsPanelController' => 'applications/people/controller/settings/panels/email',

‎src/applications/auth/controller/oauthregistration/default/PhabricatorOAuthDefaultRegistrationController.php

+8-7
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,6 @@ public function processRequest() {
8383
}
8484

8585
try {
86-
$user->save();
8786

8887
// NOTE: We don't verify OAuth email addresses by default because
8988
// OAuth providers might associate email addresses with accounts that
@@ -92,12 +91,14 @@ public function processRequest() {
9291
// verifying an email address are high because having a corporate
9392
// address at a company is sometimes the key to the castle.
9493

95-
$new_email = id(new PhabricatorUserEmail())
96-
->setUserPHID($user->getPHID())
94+
95+
$email_obj = id(new PhabricatorUserEmail())
9796
->setAddress($new_email)
98-
->setIsPrimary(1)
99-
->setIsVerified(0)
100-
->save();
97+
->setIsVerified(0);
98+
99+
id(new PhabricatorUserEditor())
100+
->setActor($user)
101+
->createNewUser($user, $email_obj);
101102

102103
$oauth_info->setUserID($user->getID());
103104
$oauth_info->save();
@@ -106,7 +107,7 @@ public function processRequest() {
106107
$request->setCookie('phusr', $user->getUsername());
107108
$request->setCookie('phsid', $session_key);
108109

109-
$new_email->sendVerificationEmail($user);
110+
$email_obj->sendVerificationEmail($user);
110111

111112
return id(new AphrontRedirectResponse())->setURI('/');
112113
} catch (AphrontQueryDuplicateKeyException $exception) {

‎src/applications/auth/controller/oauthregistration/default/__init__.php

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
phutil_require_module('phabricator', 'aphront/response/redirect');
1010
phutil_require_module('phabricator', 'applications/auth/controller/oauthregistration/base');
1111
phutil_require_module('phabricator', 'applications/files/storage/file');
12+
phutil_require_module('phabricator', 'applications/people/editor');
1213
phutil_require_module('phabricator', 'applications/people/storage/email');
1314
phutil_require_module('phabricator', 'applications/people/storage/user');
1415
phutil_require_module('phabricator', 'view/form/base');

‎src/applications/conduit/method/user/disable/ConduitAPI_user_disable_Method.php

+5-3
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,8 @@ public function defineErrorTypes() {
4444
}
4545

4646
protected function execute(ConduitAPIRequest $request) {
47-
if (!$request->getUser()->getIsAdmin()) {
47+
$actor = $request->getUser();
48+
if (!$actor->getIsAdmin()) {
4849
throw new ConduitException('ERR-PERMISSIONS');
4950
}
5051

@@ -59,8 +60,9 @@ protected function execute(ConduitAPIRequest $request) {
5960
}
6061

6162
foreach ($users as $user) {
62-
$user->setIsDisabled(true);
63-
$user->save();
63+
id(new PhabricatorUserEditor())
64+
->setActor($actor)
65+
->disableUser($user, true);
6466
}
6567
}
6668

‎src/applications/conduit/method/user/disable/__init__.php

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
phutil_require_module('phabricator', 'applications/conduit/method/user/base');
1010
phutil_require_module('phabricator', 'applications/conduit/protocol/exception');
11+
phutil_require_module('phabricator', 'applications/people/editor');
1112
phutil_require_module('phabricator', 'applications/people/storage/user');
1213

1314
phutil_require_module('phutil', 'utils');

‎src/applications/people/controller/edit/PhabricatorPeopleEditController.php

+23-33
Original file line numberDiff line numberDiff line change
@@ -165,22 +165,18 @@ private function processBasicRequest(PhabricatorUser $user) {
165165
try {
166166
$is_new = !$user->getID();
167167

168-
$user->save();
169-
170-
if ($is_new) {
171-
168+
if (!$is_new) {
169+
id(new PhabricatorUserEditor())
170+
->setActor($admin)
171+
->updateUser($user);
172+
} else {
172173
$email = id(new PhabricatorUserEmail())
173-
->setUserPHID($user->getPHID())
174174
->setAddress($new_email)
175-
->setIsPrimary(1)
176-
->setIsVerified(0)
177-
->save();
175+
->setIsVerified(0);
178176

179-
$log = PhabricatorUserLog::newLog(
180-
$admin,
181-
$user,
182-
PhabricatorUserLog::ACTION_CREATE);
183-
$log->save();
177+
id(new PhabricatorUserEditor())
178+
->setActor($admin)
179+
->createNewUser($user, $email);
184180

185181
if ($welcome_checked) {
186182
$user->sendWelcomeEmail($admin);
@@ -255,13 +251,17 @@ private function processBasicRequest(PhabricatorUser $user) {
255251
->setValue($new_email)
256252
->setError($e_email));
257253
} else {
254+
$email = $user->loadPrimaryEmail();
255+
if ($email) {
256+
$status = $email->getIsVerified() ? 'Verified' : 'Unverified';
257+
} else {
258+
$status = 'No Email Address';
259+
}
260+
258261
$form->appendChild(
259262
id(new AphrontFormStaticControl())
260263
->setLabel('Email')
261-
->setValue(
262-
$user->loadPrimaryEmail()->getIsVerified()
263-
? 'Verified'
264-
: 'Unverified'));
264+
->setValue($status));
265265
}
266266

267267
$form->appendChild($this->getRoleInstructions());
@@ -354,31 +354,21 @@ private function processRoleRequest(PhabricatorUser $user) {
354354
$new_admin = (bool)$request->getBool('is_admin');
355355
$old_admin = (bool)$user->getIsAdmin();
356356
if ($new_admin != $old_admin) {
357-
$log = clone $log_template;
358-
$log->setAction(PhabricatorUserLog::ACTION_ADMIN);
359-
$log->setOldValue($old_admin);
360-
$log->setNewValue($new_admin);
361-
$user->setIsAdmin($new_admin);
362-
$logs[] = $log;
357+
id(new PhabricatorUserEditor())
358+
->setActor($admin)
359+
->makeAdminUser($user, $new_admin);
363360
}
364361

365362
$new_disabled = (bool)$request->getBool('is_disabled');
366363
$old_disabled = (bool)$user->getIsDisabled();
367364
if ($new_disabled != $old_disabled) {
368-
$log = clone $log_template;
369-
$log->setAction(PhabricatorUserLog::ACTION_DISABLE);
370-
$log->setOldValue($old_disabled);
371-
$log->setNewValue($new_disabled);
372-
$user->setIsDisabled($new_disabled);
373-
$logs[] = $log;
365+
id(new PhabricatorUserEditor())
366+
->setActor($admin)
367+
->disableUser($user, $new_disabled);
374368
}
375369
}
376370

377371
if (!$errors) {
378-
$user->save();
379-
foreach ($logs as $log) {
380-
$log->save();
381-
}
382372
return id(new AphrontRedirectResponse())
383373
->setURI($request->getRequestURI()->alter('saved', 'true'));
384374
}

‎src/applications/people/controller/edit/__init__.php

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
phutil_require_module('phabricator', 'aphront/response/404');
1010
phutil_require_module('phabricator', 'aphront/response/redirect');
1111
phutil_require_module('phabricator', 'applications/people/controller/base');
12+
phutil_require_module('phabricator', 'applications/people/editor');
1213
phutil_require_module('phabricator', 'applications/people/storage/email');
1314
phutil_require_module('phabricator', 'applications/people/storage/log');
1415
phutil_require_module('phabricator', 'applications/people/storage/user');

‎src/applications/people/controller/settings/panels/email/PhabricatorUserEmailSettingsPanelController.php

+13-20
Original file line numberDiff line numberDiff line change
@@ -175,13 +175,14 @@ private function returnNewAddressResponse(PhutilURI $uri, $new) {
175175

176176
if (!$errors) {
177177
$object = id(new PhabricatorUserEmail())
178-
->setUserPHID($user->getPHID())
179178
->setAddress($email)
180-
->setIsVerified(0)
181-
->setIsPrimary(0);
179+
->setIsVerified(0);
182180

183181
try {
184-
$object->save();
182+
183+
id(new PhabricatorUserEditor())
184+
->setActor($user)
185+
->addEmail($user, $object);
185186

186187
$object->sendVerificationEmail($user);
187188

@@ -245,7 +246,11 @@ private function returnDeleteAddressResponse(PhutilURI $uri, $email_id) {
245246
}
246247

247248
if ($request->isFormPost()) {
248-
$email->delete();
249+
250+
id(new PhabricatorUserEditor())
251+
->setActor($user)
252+
->removeEmail($user, $email);
253+
249254
return id(new AphrontRedirectResponse())->setURI($uri);
250255
}
251256

@@ -314,21 +319,9 @@ private function returnPrimaryAddressResponse(PhutilURI $uri, $email_id) {
314319

315320
if ($request->isFormPost()) {
316321

317-
// TODO: Transactions!
318-
319-
$email->setIsPrimary(1);
320-
321-
$old_primary = $user->loadPrimaryEmail();
322-
if ($old_primary) {
323-
$old_primary->setIsPrimary(0);
324-
$old_primary->save();
325-
}
326-
$email->save();
327-
328-
if ($old_primary) {
329-
$old_primary->sendOldPrimaryEmail($user, $email);
330-
}
331-
$email->sendNewPrimaryEmail($user);
322+
id(new PhabricatorUserEditor())
323+
->setActor($user)
324+
->changePrimaryEmail($user, $email);
332325

333326
return id(new AphrontRedirectResponse())->setURI($uri);
334327
}

‎src/applications/people/controller/settings/panels/email/__init__.php

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
phutil_require_module('phabricator', 'aphront/response/redirect');
1212
phutil_require_module('phabricator', 'aphront/response/reload');
1313
phutil_require_module('phabricator', 'applications/people/controller/settings/panels/base');
14+
phutil_require_module('phabricator', 'applications/people/editor');
1415
phutil_require_module('phabricator', 'applications/people/storage/email');
1516
phutil_require_module('phabricator', 'infrastructure/javelin/markup');
1617
phutil_require_module('phabricator', 'view/control/table');

‎src/applications/people/controller/settings/panels/password/PhabricatorUserPasswordSettingsPanelController.php

+5-2
Original file line numberDiff line numberDiff line change
@@ -79,13 +79,16 @@ public function processRequest() {
7979
}
8080

8181
if (!$errors) {
82-
$user->setPassword($pass);
8382
// This write is unguarded because the CSRF token has already
8483
// been checked in the call to $request->isFormPost() and
8584
// the CSRF token depends on the password hash, so when it
8685
// is changed here the CSRF token check will fail.
8786
$unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
88-
$user->save();
87+
88+
id(new PhabricatorUserEditor())
89+
->setActor($user)
90+
->changePassword($user, $pass);
91+
8992
unset($unguarded);
9093

9194
if ($valid_token) {

‎src/applications/people/controller/settings/panels/password/__init__.php

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
phutil_require_module('phabricator', 'aphront/response/redirect');
1111
phutil_require_module('phabricator', 'aphront/writeguard');
1212
phutil_require_module('phabricator', 'applications/people/controller/settings/panels/base');
13+
phutil_require_module('phabricator', 'applications/people/editor');
1314
phutil_require_module('phabricator', 'applications/people/storage/email');
1415
phutil_require_module('phabricator', 'infrastructure/env');
1516
phutil_require_module('phabricator', 'view/form/base');

0 commit comments

Comments
 (0)
Failed to load comments.