|
1
|
|
|
<?php |
|
2
|
|
|
/****************************************************************************** |
|
3
|
|
|
* Wikipedia Account Creation Assistance tool * |
|
4
|
|
|
* * |
|
5
|
|
|
* All code in this file is released into the public domain by the ACC * |
|
6
|
|
|
* Development Team. Please see team.json for a list of contributors. * |
|
7
|
|
|
******************************************************************************/ |
|
8
|
|
|
|
|
9
|
|
|
namespace Waca\Pages; |
|
10
|
|
|
|
|
11
|
|
|
use Waca\DataObjects\User; |
|
12
|
|
|
use Waca\DataObjects\UserRole; |
|
13
|
|
|
use Waca\Exceptions\ApplicationLogicException; |
|
14
|
|
|
use Waca\Helpers\Logger; |
|
15
|
|
|
use Waca\Helpers\SearchHelpers\UserSearchHelper; |
|
16
|
|
|
use Waca\SessionAlert; |
|
17
|
|
|
use Waca\Tasks\InternalPageBase; |
|
18
|
|
|
use Waca\WebRequest; |
|
19
|
|
|
|
|
20
|
|
|
/** |
|
21
|
|
|
* Class PageUserManagement |
|
22
|
|
|
* @package Waca\Pages |
|
23
|
|
|
*/ |
|
24
|
|
|
class PageUserManagement extends InternalPageBase |
|
25
|
|
|
{ |
|
26
|
|
|
/** @var string */ |
|
27
|
|
|
private $adminMailingList = '[email protected]'; |
|
28
|
|
|
|
|
29
|
|
|
/** |
|
30
|
|
|
* Main function for this page, when no specific actions are called. |
|
31
|
|
|
*/ |
|
32
|
|
|
protected function main() |
|
33
|
|
|
{ |
|
34
|
|
|
$this->setHtmlTitle('User Management'); |
|
35
|
|
|
|
|
36
|
|
|
$database = $this->getDatabase(); |
|
37
|
|
|
$currentUser = User::getCurrent($database); |
|
38
|
|
|
|
|
39
|
|
|
if (WebRequest::getBoolean("showAll")) { |
|
|
|
|
|
|
40
|
|
|
$this->assign("showAll", true); |
|
|
|
|
|
|
41
|
|
|
|
|
42
|
|
|
$this->assign("suspendedUsers", |
|
|
|
|
|
|
43
|
|
|
UserSearchHelper::get($database)->byStatus(User::STATUS_SUSPENDED)->fetch()); |
|
44
|
|
|
$this->assign("declinedUsers", UserSearchHelper::get($database)->byStatus(User::STATUS_DECLINED)->fetch()); |
|
|
|
|
|
|
45
|
|
|
|
|
46
|
|
|
UserSearchHelper::get($database)->getRoleMap($roleMap); |
|
47
|
|
|
} |
|
48
|
|
|
else { |
|
49
|
|
|
$this->assign("showAll", false); |
|
|
|
|
|
|
50
|
|
|
$this->assign("suspendedUsers", array()); |
|
|
|
|
|
|
51
|
|
|
$this->assign("declinedUsers", array()); |
|
|
|
|
|
|
52
|
|
|
|
|
53
|
|
|
UserSearchHelper::get($database)->statusIn(array('New', 'Active'))->getRoleMap($roleMap); |
|
54
|
|
|
} |
|
55
|
|
|
|
|
56
|
|
|
$this->assign('newUsers', UserSearchHelper::get($database)->byStatus(User::STATUS_NEW)->fetch()); |
|
57
|
|
|
$this->assign('normalUsers', |
|
58
|
|
|
UserSearchHelper::get($database)->byStatus(User::STATUS_ACTIVE)->byRole('user')->fetch()); |
|
59
|
|
|
$this->assign('adminUsers', |
|
60
|
|
|
UserSearchHelper::get($database)->byStatus(User::STATUS_ACTIVE)->byRole('admin')->fetch()); |
|
61
|
|
|
$this->assign('checkUsers', |
|
62
|
|
|
UserSearchHelper::get($database)->byStatus(User::STATUS_ACTIVE)->byRole('checkuser')->fetch()); |
|
63
|
|
|
$this->assign('toolRoots', |
|
64
|
|
|
UserSearchHelper::get($database)->byStatus(User::STATUS_ACTIVE)->byRole('toolRoot')->fetch()); |
|
65
|
|
|
|
|
66
|
|
|
$this->assign('roles', $roleMap); |
|
67
|
|
|
|
|
68
|
|
|
$this->getTypeAheadHelper()->defineTypeAheadSource('username-typeahead', function() use ($database) { |
|
|
|
|
|
|
69
|
|
|
return UserSearchHelper::get($database)->fetchColumn('username'); |
|
70
|
|
|
}); |
|
71
|
|
|
|
|
72
|
|
|
$this->assign('canApprove', $this->barrierTest('approve', $currentUser)); |
|
73
|
|
|
$this->assign('canDecline', $this->barrierTest('decline', $currentUser)); |
|
74
|
|
|
$this->assign('canRename', $this->barrierTest('rename', $currentUser)); |
|
75
|
|
|
$this->assign('canEditUser', $this->barrierTest('editUser', $currentUser)); |
|
76
|
|
|
$this->assign('canSuspend', $this->barrierTest('suspend', $currentUser)); |
|
77
|
|
|
$this->assign('canEditRoles', $this->barrierTest('editRoles', $currentUser)); |
|
78
|
|
|
|
|
79
|
|
|
$this->setTemplate("usermanagement/main.tpl"); |
|
|
|
|
|
|
80
|
|
|
} |
|
|
|
|
|
|
81
|
|
|
|
|
82
|
|
|
#region Access control |
|
83
|
|
|
|
|
84
|
|
|
/** |
|
85
|
|
|
* Action target for editing the roles assigned to a user |
|
86
|
|
|
*/ |
|
|
|
|
|
|
87
|
|
|
protected function editRoles() |
|
88
|
|
|
{ |
|
89
|
|
|
$this->setHtmlTitle('User Management'); |
|
90
|
|
|
$database = $this->getDatabase(); |
|
91
|
|
|
$userId = WebRequest::getInt('user'); |
|
92
|
|
|
|
|
93
|
|
|
/** @var User $user */ |
|
94
|
|
|
$user = User::getById($userId, $database); |
|
95
|
|
|
|
|
96
|
|
|
if ($user === false) { |
|
|
|
|
|
|
97
|
|
|
throw new ApplicationLogicException('Sorry, the user you are trying to edit could not be found.'); |
|
98
|
|
|
} |
|
99
|
|
|
|
|
100
|
|
|
$roleData = $this->getRoleData(UserRole::getForUser($user->getId(), $database)); |
|
101
|
|
|
|
|
102
|
|
|
// Dual-mode action |
|
103
|
|
|
if (WebRequest::wasPosted()) { |
|
104
|
|
|
$this->validateCSRFToken(); |
|
105
|
|
|
|
|
106
|
|
|
$reason = WebRequest::postString('reason'); |
|
107
|
|
|
if ($reason === false || trim($reason) === '') { |
|
108
|
|
|
throw new ApplicationLogicException('No reason specified for roles change'); |
|
109
|
|
|
} |
|
110
|
|
|
|
|
111
|
|
|
/** @var UserRole[] $delete */ |
|
112
|
|
|
$delete = array(); |
|
113
|
|
|
/** @var string[] $delete */ |
|
114
|
|
|
$add = array(); |
|
115
|
|
|
|
|
116
|
|
|
foreach ($roleData as $name => $r) { |
|
117
|
|
|
if ($r['allowEdit'] !== 1) { |
|
118
|
|
|
// not allowed, to touch this, so ignore it |
|
119
|
|
|
continue; |
|
120
|
|
|
} |
|
121
|
|
|
|
|
122
|
|
|
$newValue = WebRequest::postBoolean('role-' . $name) ? 1 : 0; |
|
123
|
|
|
if ($newValue !== $r['active']) { |
|
124
|
|
|
if ($newValue === 0) { |
|
125
|
|
|
$delete[] = $r['object']; |
|
126
|
|
|
} |
|
127
|
|
|
|
|
128
|
|
|
if ($newValue === 1) { |
|
129
|
|
|
$add[] = $name; |
|
130
|
|
|
} |
|
131
|
|
|
} |
|
132
|
|
|
} |
|
133
|
|
|
|
|
134
|
|
|
// Check there's something to do |
|
135
|
|
|
if ((count($add) + count($delete)) === 0) { |
|
136
|
|
|
$this->redirect('statistics/users', 'detail', array('user' => $user->getId())); |
|
137
|
|
|
SessionAlert::warning('No changes made to roles.'); |
|
138
|
|
|
|
|
139
|
|
|
return; |
|
140
|
|
|
} |
|
141
|
|
|
|
|
142
|
|
|
$removed = array(); |
|
143
|
|
|
|
|
144
|
|
|
/** @var UserRole $d */ |
|
145
|
|
|
foreach ($delete as $d) { |
|
146
|
|
|
$removed[] = $d->getRole(); |
|
147
|
|
|
$d->delete(); |
|
148
|
|
|
} |
|
149
|
|
|
|
|
150
|
|
|
foreach ($add as $x) { |
|
151
|
|
|
$a = new UserRole(); |
|
152
|
|
|
$a->setUser($user->getId()); |
|
153
|
|
|
$a->setRole($x); |
|
154
|
|
|
$a->setDatabase($database); |
|
155
|
|
|
$a->save(); |
|
156
|
|
|
} |
|
157
|
|
|
|
|
158
|
|
|
Logger::userRolesEdited($database, $user, $reason, $add, $removed); |
|
159
|
|
|
|
|
160
|
|
|
// dummy save for optimistic locking. If this fails, the entire txn will roll back. |
|
161
|
|
|
$user->setUpdateVersion(WebRequest::postInt('updateversion')); |
|
162
|
|
|
$user->save(); |
|
163
|
|
|
|
|
164
|
|
|
$this->getNotificationHelper()->userRolesEdited($user, $reason); |
|
165
|
|
|
SessionAlert::quick('Roles changed for user ' . htmlentities($user->getUsername(), ENT_COMPAT, 'UTF-8')); |
|
166
|
|
|
|
|
167
|
|
|
$this->redirect('statistics/users', 'detail', array('user' => $user->getId())); |
|
168
|
|
|
return; |
|
169
|
|
|
} |
|
170
|
|
|
else { |
|
171
|
|
|
$this->assignCSRFToken(); |
|
172
|
|
|
$this->setTemplate('usermanagement/roleedit.tpl'); |
|
173
|
|
|
$this->assign('user', $user); |
|
174
|
|
|
$this->assign('roleData', $roleData); |
|
175
|
|
|
} |
|
176
|
|
|
} |
|
|
|
|
|
|
177
|
|
|
|
|
178
|
|
|
/** |
|
179
|
|
|
* Action target for suspending users |
|
180
|
|
|
* |
|
181
|
|
|
* @throws ApplicationLogicException |
|
182
|
|
|
*/ |
|
183
|
|
|
protected function suspend() |
|
184
|
|
|
{ |
|
185
|
|
|
$this->setHtmlTitle('User Management'); |
|
186
|
|
|
|
|
187
|
|
|
$database = $this->getDatabase(); |
|
188
|
|
|
|
|
189
|
|
|
$userId = WebRequest::getInt('user'); |
|
190
|
|
|
|
|
191
|
|
|
/** @var User $user */ |
|
192
|
|
|
$user = User::getById($userId, $database); |
|
193
|
|
|
|
|
194
|
|
|
if ($user === false) { |
|
|
|
|
|
|
195
|
|
|
throw new ApplicationLogicException('Sorry, the user you are trying to suspend could not be found.'); |
|
196
|
|
|
} |
|
197
|
|
|
|
|
198
|
|
|
if ($user->isSuspended()) { |
|
199
|
|
|
throw new ApplicationLogicException('Sorry, the user you are trying to suspend is already suspended.'); |
|
200
|
|
|
} |
|
201
|
|
|
|
|
202
|
|
|
// Dual-mode action |
|
203
|
|
|
if (WebRequest::wasPosted()) { |
|
204
|
|
|
$this->validateCSRFToken(); |
|
205
|
|
|
$reason = WebRequest::postString('reason'); |
|
206
|
|
|
|
|
207
|
|
|
if ($reason === null || trim($reason) === "") { |
|
|
|
|
|
|
208
|
|
|
throw new ApplicationLogicException('No reason provided'); |
|
209
|
|
|
} |
|
210
|
|
|
|
|
211
|
|
|
$user->setStatus(User::STATUS_SUSPENDED); |
|
212
|
|
|
$user->setUpdateVersion(WebRequest::postInt('updateversion')); |
|
213
|
|
|
$user->save(); |
|
214
|
|
|
Logger::suspendedUser($database, $user, $reason); |
|
215
|
|
|
|
|
216
|
|
|
$this->getNotificationHelper()->userSuspended($user, $reason); |
|
217
|
|
|
SessionAlert::quick('Suspended user ' . htmlentities($user->getUsername(), ENT_COMPAT, 'UTF-8')); |
|
218
|
|
|
|
|
219
|
|
|
// send email |
|
220
|
|
|
$this->sendStatusChangeEmail( |
|
221
|
|
|
'Your WP:ACC account has been suspended', |
|
222
|
|
|
'usermanagement/emails/suspended.tpl', |
|
223
|
|
|
$reason, |
|
224
|
|
|
$user, |
|
225
|
|
|
User::getCurrent($database)->getUsername() |
|
226
|
|
|
); |
|
227
|
|
|
|
|
228
|
|
|
$this->redirect('userManagement'); |
|
229
|
|
|
|
|
230
|
|
|
return; |
|
231
|
|
|
} |
|
232
|
|
|
else { |
|
233
|
|
|
$this->assignCSRFToken(); |
|
234
|
|
|
$this->setTemplate('usermanagement/changelevel-reason.tpl'); |
|
235
|
|
|
$this->assign('user', $user); |
|
236
|
|
|
$this->assign('status', 'Suspended'); |
|
237
|
|
|
$this->assign("showReason", true); |
|
|
|
|
|
|
238
|
|
|
} |
|
239
|
|
|
} |
|
|
|
|
|
|
240
|
|
|
|
|
241
|
|
|
/** |
|
242
|
|
|
* Entry point for the decline action |
|
243
|
|
|
* |
|
244
|
|
|
* @throws ApplicationLogicException |
|
245
|
|
|
*/ |
|
246
|
|
|
protected function decline() |
|
247
|
|
|
{ |
|
248
|
|
|
$this->setHtmlTitle('User Management'); |
|
249
|
|
|
|
|
250
|
|
|
$database = $this->getDatabase(); |
|
251
|
|
|
|
|
252
|
|
|
$userId = WebRequest::getInt('user'); |
|
253
|
|
|
$user = User::getById($userId, $database); |
|
254
|
|
|
|
|
255
|
|
|
if ($user === false) { |
|
|
|
|
|
|
256
|
|
|
throw new ApplicationLogicException('Sorry, the user you are trying to decline could not be found.'); |
|
257
|
|
|
} |
|
258
|
|
|
|
|
259
|
|
|
if (!$user->isNewUser()) { |
|
260
|
|
|
throw new ApplicationLogicException('Sorry, the user you are trying to decline is not new.'); |
|
261
|
|
|
} |
|
262
|
|
|
|
|
263
|
|
|
// Dual-mode action |
|
264
|
|
|
if (WebRequest::wasPosted()) { |
|
265
|
|
|
$this->validateCSRFToken(); |
|
266
|
|
|
$reason = WebRequest::postString('reason'); |
|
267
|
|
|
|
|
268
|
|
|
if ($reason === null || trim($reason) === "") { |
|
|
|
|
|
|
269
|
|
|
throw new ApplicationLogicException('No reason provided'); |
|
270
|
|
|
} |
|
271
|
|
|
|
|
272
|
|
|
$user->setStatus(User::STATUS_DECLINED); |
|
273
|
|
|
$user->setUpdateVersion(WebRequest::postInt('updateversion')); |
|
274
|
|
|
$user->save(); |
|
275
|
|
|
Logger::declinedUser($database, $user, $reason); |
|
276
|
|
|
|
|
277
|
|
|
$this->getNotificationHelper()->userDeclined($user, $reason); |
|
278
|
|
|
SessionAlert::quick('Declined user ' . htmlentities($user->getUsername(), ENT_COMPAT, 'UTF-8')); |
|
279
|
|
|
|
|
280
|
|
|
// send email |
|
281
|
|
|
$this->sendStatusChangeEmail( |
|
282
|
|
|
'Your WP:ACC account has been declined', |
|
283
|
|
|
'usermanagement/emails/declined.tpl', |
|
284
|
|
|
$reason, |
|
285
|
|
|
$user, |
|
286
|
|
|
User::getCurrent($database)->getUsername() |
|
287
|
|
|
); |
|
288
|
|
|
|
|
289
|
|
|
$this->redirect('userManagement'); |
|
290
|
|
|
|
|
291
|
|
|
return; |
|
292
|
|
|
} |
|
293
|
|
|
else { |
|
294
|
|
|
$this->assignCSRFToken(); |
|
295
|
|
|
$this->setTemplate('usermanagement/changelevel-reason.tpl'); |
|
296
|
|
|
$this->assign('user', $user); |
|
297
|
|
|
$this->assign('status', 'Declined'); |
|
298
|
|
|
$this->assign("showReason", true); |
|
|
|
|
|
|
299
|
|
|
} |
|
300
|
|
|
} |
|
|
|
|
|
|
301
|
|
|
|
|
302
|
|
|
/** |
|
303
|
|
|
* Entry point for the approve action |
|
304
|
|
|
* |
|
305
|
|
|
* @throws ApplicationLogicException |
|
306
|
|
|
*/ |
|
307
|
|
|
protected function approve() |
|
308
|
|
|
{ |
|
309
|
|
|
$this->setHtmlTitle('User Management'); |
|
310
|
|
|
|
|
311
|
|
|
$database = $this->getDatabase(); |
|
312
|
|
|
|
|
313
|
|
|
$userId = WebRequest::getInt('user'); |
|
314
|
|
|
$user = User::getById($userId, $database); |
|
315
|
|
|
|
|
316
|
|
|
if ($user === false) { |
|
|
|
|
|
|
317
|
|
|
throw new ApplicationLogicException('Sorry, the user you are trying to approve could not be found.'); |
|
318
|
|
|
} |
|
319
|
|
|
|
|
320
|
|
|
if ($user->isActive()) { |
|
321
|
|
|
throw new ApplicationLogicException('Sorry, the user you are trying to approve is already an active user.'); |
|
322
|
|
|
} |
|
323
|
|
|
|
|
324
|
|
|
// Dual-mode action |
|
325
|
|
|
if (WebRequest::wasPosted()) { |
|
326
|
|
|
$this->validateCSRFToken(); |
|
327
|
|
|
$user->setStatus(User::STATUS_ACTIVE); |
|
328
|
|
|
$user->setUpdateVersion(WebRequest::postInt('updateversion')); |
|
329
|
|
|
$user->save(); |
|
330
|
|
|
Logger::approvedUser($database, $user); |
|
331
|
|
|
|
|
332
|
|
|
$this->getNotificationHelper()->userApproved($user); |
|
333
|
|
|
SessionAlert::quick('Approved user ' . htmlentities($user->getUsername(), ENT_COMPAT, 'UTF-8')); |
|
334
|
|
|
|
|
335
|
|
|
// send email |
|
336
|
|
|
$this->sendStatusChangeEmail( |
|
337
|
|
|
'Your WP:ACC account has been approved', |
|
338
|
|
|
'usermanagement/emails/approved.tpl', |
|
339
|
|
|
null, |
|
340
|
|
|
$user, |
|
341
|
|
|
User::getCurrent($database)->getUsername() |
|
342
|
|
|
); |
|
343
|
|
|
|
|
344
|
|
|
$this->redirect("userManagement"); |
|
|
|
|
|
|
345
|
|
|
|
|
346
|
|
|
return; |
|
347
|
|
|
} |
|
348
|
|
|
else { |
|
349
|
|
|
$this->assignCSRFToken(); |
|
350
|
|
|
$this->setTemplate("usermanagement/changelevel-reason.tpl"); |
|
|
|
|
|
|
351
|
|
|
$this->assign("user", $user); |
|
|
|
|
|
|
352
|
|
|
$this->assign("status", "User"); |
|
|
|
|
|
|
353
|
|
|
$this->assign("showReason", false); |
|
|
|
|
|
|
354
|
|
|
} |
|
355
|
|
|
} |
|
|
|
|
|
|
356
|
|
|
|
|
357
|
|
|
#endregion |
|
358
|
|
|
|
|
359
|
|
|
#region Renaming / Editing |
|
360
|
|
|
|
|
361
|
|
|
/** |
|
362
|
|
|
* Entry point for the rename action |
|
363
|
|
|
* |
|
364
|
|
|
* @throws ApplicationLogicException |
|
365
|
|
|
*/ |
|
366
|
|
|
protected function rename() |
|
367
|
|
|
{ |
|
368
|
|
|
$this->setHtmlTitle('User Management'); |
|
369
|
|
|
|
|
370
|
|
|
$database = $this->getDatabase(); |
|
371
|
|
|
|
|
372
|
|
|
$userId = WebRequest::getInt('user'); |
|
373
|
|
|
$user = User::getById($userId, $database); |
|
374
|
|
|
|
|
375
|
|
|
if ($user === false) { |
|
|
|
|
|
|
376
|
|
|
throw new ApplicationLogicException('Sorry, the user you are trying to rename could not be found.'); |
|
377
|
|
|
} |
|
378
|
|
|
|
|
379
|
|
|
// Dual-mode action |
|
380
|
|
|
if (WebRequest::wasPosted()) { |
|
381
|
|
|
$this->validateCSRFToken(); |
|
382
|
|
|
$newUsername = WebRequest::postString('newname'); |
|
383
|
|
|
|
|
384
|
|
|
if ($newUsername === null || trim($newUsername) === "") { |
|
|
|
|
|
|
385
|
|
|
throw new ApplicationLogicException('The new username cannot be empty'); |
|
386
|
|
|
} |
|
387
|
|
|
|
|
388
|
|
|
if (User::getByUsername($newUsername, $database) != false) { |
|
389
|
|
|
throw new ApplicationLogicException('The new username already exists'); |
|
390
|
|
|
} |
|
391
|
|
|
|
|
392
|
|
|
$oldUsername = $user->getUsername(); |
|
393
|
|
|
$user->setUsername($newUsername); |
|
394
|
|
|
$user->setUpdateVersion(WebRequest::postInt('updateversion')); |
|
395
|
|
|
|
|
396
|
|
|
$user->save(); |
|
397
|
|
|
|
|
398
|
|
|
$logEntryData = serialize(array( |
|
399
|
|
|
'old' => $oldUsername, |
|
400
|
|
|
'new' => $newUsername, |
|
401
|
|
|
)); |
|
402
|
|
|
|
|
403
|
|
|
Logger::renamedUser($database, $user, $logEntryData); |
|
404
|
|
|
|
|
405
|
|
|
SessionAlert::quick("Changed User " |
|
|
|
|
|
|
406
|
|
|
. htmlentities($oldUsername, ENT_COMPAT, 'UTF-8') |
|
407
|
|
|
. " name to " |
|
|
|
|
|
|
408
|
|
|
. htmlentities($newUsername, ENT_COMPAT, 'UTF-8')); |
|
409
|
|
|
|
|
410
|
|
|
$this->getNotificationHelper()->userRenamed($user, $oldUsername); |
|
411
|
|
|
|
|
412
|
|
|
// send an email to the user. |
|
413
|
|
|
$this->assign('targetUsername', $user->getUsername()); |
|
414
|
|
|
$this->assign('toolAdmin', User::getCurrent($database)->getUsername()); |
|
415
|
|
|
$this->assign('oldUsername', $oldUsername); |
|
416
|
|
|
$this->assign('mailingList', $this->adminMailingList); |
|
417
|
|
|
|
|
418
|
|
|
$this->getEmailHelper()->sendMail( |
|
419
|
|
|
$user->getEmail(), |
|
420
|
|
|
'Your username on WP:ACC has been changed', |
|
421
|
|
|
$this->fetchTemplate('usermanagement/emails/renamed.tpl'), |
|
422
|
|
|
array('Reply-To' => $this->adminMailingList) |
|
423
|
|
|
); |
|
424
|
|
|
|
|
425
|
|
|
$this->redirect("userManagement"); |
|
|
|
|
|
|
426
|
|
|
|
|
427
|
|
|
return; |
|
428
|
|
|
} |
|
429
|
|
|
else { |
|
430
|
|
|
$this->assignCSRFToken(); |
|
431
|
|
|
$this->setTemplate('usermanagement/renameuser.tpl'); |
|
432
|
|
|
$this->assign('user', $user); |
|
433
|
|
|
} |
|
434
|
|
|
} |
|
|
|
|
|
|
435
|
|
|
|
|
436
|
|
|
/** |
|
437
|
|
|
* Entry point for the edit action |
|
438
|
|
|
* |
|
439
|
|
|
* @throws ApplicationLogicException |
|
440
|
|
|
*/ |
|
441
|
|
|
protected function editUser() |
|
442
|
|
|
{ |
|
443
|
|
|
$this->setHtmlTitle('User Management'); |
|
444
|
|
|
|
|
445
|
|
|
$database = $this->getDatabase(); |
|
446
|
|
|
|
|
447
|
|
|
$userId = WebRequest::getInt('user'); |
|
448
|
|
|
$user = User::getById($userId, $database); |
|
449
|
|
|
|
|
450
|
|
|
if ($user === false) { |
|
|
|
|
|
|
451
|
|
|
throw new ApplicationLogicException('Sorry, the user you are trying to edit could not be found.'); |
|
452
|
|
|
} |
|
453
|
|
|
|
|
454
|
|
|
// Dual-mode action |
|
455
|
|
|
if (WebRequest::wasPosted()) { |
|
456
|
|
|
$this->validateCSRFToken(); |
|
457
|
|
|
$newEmail = WebRequest::postEmail('user_email'); |
|
458
|
|
|
$newOnWikiName = WebRequest::postString('user_onwikiname'); |
|
459
|
|
|
|
|
460
|
|
|
if ($newEmail === null) { |
|
461
|
|
|
throw new ApplicationLogicException('Invalid email address'); |
|
462
|
|
|
} |
|
463
|
|
|
|
|
464
|
|
|
if (!$user->isOAuthLinked()) { |
|
465
|
|
|
if (trim($newOnWikiName) == "") { |
|
|
|
|
|
|
466
|
|
|
throw new ApplicationLogicException('New on-wiki username cannot be blank'); |
|
467
|
|
|
} |
|
468
|
|
|
|
|
469
|
|
|
$user->setOnWikiName($newOnWikiName); |
|
470
|
|
|
} |
|
471
|
|
|
|
|
472
|
|
|
$user->setEmail($newEmail); |
|
473
|
|
|
|
|
474
|
|
|
$user->setUpdateVersion(WebRequest::postInt('updateversion')); |
|
475
|
|
|
|
|
476
|
|
|
$user->save(); |
|
477
|
|
|
|
|
478
|
|
|
Logger::userPreferencesChange($database, $user); |
|
479
|
|
|
$this->getNotificationHelper()->userPrefChange($user); |
|
480
|
|
|
SessionAlert::quick('Changes to user\'s preferences have been saved'); |
|
481
|
|
|
|
|
482
|
|
|
$this->redirect("userManagement"); |
|
|
|
|
|
|
483
|
|
|
|
|
484
|
|
|
return; |
|
485
|
|
|
} |
|
486
|
|
|
else { |
|
487
|
|
|
$this->assignCSRFToken(); |
|
488
|
|
|
$this->setTemplate('usermanagement/edituser.tpl'); |
|
489
|
|
|
$this->assign('user', $user); |
|
490
|
|
|
} |
|
491
|
|
|
} |
|
|
|
|
|
|
492
|
|
|
|
|
493
|
|
|
#endregion |
|
494
|
|
|
|
|
495
|
|
|
/** |
|
496
|
|
|
* Sends a status change email to the user. |
|
497
|
|
|
* |
|
498
|
|
|
* @param string $subject The subject of the email |
|
499
|
|
|
* @param string $template The smarty template to use |
|
500
|
|
|
* @param string|null $reason The reason for performing the status change |
|
501
|
|
|
* @param User $user The user affected |
|
502
|
|
|
* @param string $toolAdminUsername The tool admin's username who is making the edit |
|
503
|
|
|
*/ |
|
504
|
|
|
private function sendStatusChangeEmail($subject, $template, $reason, $user, $toolAdminUsername) |
|
505
|
|
|
{ |
|
506
|
|
|
$this->assign('targetUsername', $user->getUsername()); |
|
507
|
|
|
$this->assign('toolAdmin', $toolAdminUsername); |
|
508
|
|
|
$this->assign('actionReason', $reason); |
|
509
|
|
|
$this->assign('mailingList', $this->adminMailingList); |
|
510
|
|
|
|
|
511
|
|
|
$this->getEmailHelper()->sendMail( |
|
512
|
|
|
$user->getEmail(), |
|
513
|
|
|
$subject, |
|
514
|
|
|
$this->fetchTemplate($template), |
|
515
|
|
|
array('Reply-To' => $this->adminMailingList) |
|
516
|
|
|
); |
|
517
|
|
|
} |
|
|
|
|
|
|
518
|
|
|
|
|
519
|
|
|
/** |
|
520
|
|
|
* @param UserRole[] $activeRoles |
|
521
|
|
|
* |
|
522
|
|
|
* @return array |
|
523
|
|
|
*/ |
|
524
|
|
|
private function getRoleData($activeRoles) |
|
525
|
|
|
{ |
|
526
|
|
|
$availableRoles = $this->getSecurityManager()->getRoleConfiguration()->getAvailableRoles(); |
|
527
|
|
|
|
|
528
|
|
|
$currentUser = User::getCurrent($this->getDatabase()); |
|
529
|
|
|
$this->getSecurityManager()->getActiveRoles($currentUser, $userRoles, $inactiveRoles); |
|
530
|
|
|
|
|
531
|
|
|
$initialValue = array('active' => 0, 'allowEdit' => 0, 'description' => '???', 'object' => null); |
|
532
|
|
|
|
|
533
|
|
|
$roleData = array(); |
|
534
|
|
|
foreach ($availableRoles as $role => $data) { |
|
535
|
|
|
$intersection = array_intersect($data['editableBy'], $userRoles); |
|
536
|
|
|
|
|
537
|
|
|
$roleData[$role] = $initialValue; |
|
538
|
|
|
$roleData[$role]['allowEdit'] = count($intersection) > 0 ? 1 : 0; |
|
539
|
|
|
$roleData[$role]['description'] = $data['description']; |
|
540
|
|
|
} |
|
541
|
|
|
|
|
542
|
|
|
foreach ($activeRoles as $role) { |
|
543
|
|
|
if (!isset($roleData[$role->getRole()])) { |
|
544
|
|
|
// This value is no longer available in the configuration, allow changing (aka removing) it. |
|
545
|
|
|
$roleData[$role->getRole()] = $initialValue; |
|
546
|
|
|
$roleData[$role->getRole()]['allowEdit'] = 1; |
|
547
|
|
|
} |
|
548
|
|
|
|
|
549
|
|
|
$roleData[$role->getRole()]['object'] = $role; |
|
550
|
|
|
$roleData[$role->getRole()]['active'] = 1; |
|
551
|
|
|
} |
|
552
|
|
|
|
|
553
|
|
|
return $roleData; |
|
554
|
|
|
} |
|
|
|
|
|
|
555
|
|
|
} |
|
|
|
|
|
|
556
|
|
|
|
PHP provides two ways to mark string literals. Either with single quotes
'literal'or with double quotes"literal". The difference between these is that string literals in double quotes may contain variables with are evaluated at run-time as well as escape sequences.String literals in single quotes on the other hand are evaluated very literally and the only two characters that needs escaping in the literal are the single quote itself (
\') and the backslash (\\). Every other character is displayed as is.Double quoted string literals may contain other variables or more complex escape sequences.
will print an indented:
Single is ValueIf your string literal does not contain variables or escape sequences, it should be defined using single quotes to make that fact clear.
For more information on PHP string literals and available escape sequences see the PHP core documentation.