Failed Conditions
Push — dependabot/composer/smarty/sma... ( 7af6bd )
by
unknown
21:22 queued 16:09
created

includes/Pages/PageUserManagement.php (1 issue)

Labels
Severity
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 Exception;
12
use SmartyException;
0 ignored issues
show
The type SmartyException was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
13
use Waca\DataObjects\Domain;
14
use Waca\DataObjects\User;
15
use Waca\DataObjects\UserRole;
16
use Waca\Exceptions\ApplicationLogicException;
17
use Waca\Exceptions\OptimisticLockFailedException;
18
use Waca\Helpers\Logger;
19
use Waca\Helpers\OAuthUserHelper;
20
use Waca\Helpers\PreferenceManager;
21
use Waca\Helpers\SearchHelpers\UserSearchHelper;
22
use Waca\SessionAlert;
23
use Waca\Tasks\InternalPageBase;
24
use Waca\WebRequest;
25
26
/**
27
 * Class PageUserManagement
28
 * @package Waca\Pages
29
 */
30
class PageUserManagement extends InternalPageBase
31
{
32
    // FIXME: domains
33
    /** @var string */
34
    private $adminMailingList = '[email protected]';
35
36
    /**
37
     * Main function for this page, when no specific actions are called.
38
     */
39
    protected function main()
40
    {
41
        $this->setHtmlTitle('User Management');
42
43
        $database = $this->getDatabase();
44
        $currentUser = User::getCurrent($database);
45
46
        $userSearchRequest = WebRequest::getString('usersearch');
47
        if ($userSearchRequest !== null) {
48
            $searchedUser = User::getByUsername($userSearchRequest, $database);
49
            if ($searchedUser !== false) {
50
                $this->redirect('statistics/users', 'detail', ['user' => $searchedUser->getId()]);
51
                return;
52
            }
53
        }
54
55
        // A bit hacky, but it's better than my last solution of creating an object for each user and passing that to
56
        // the template. I still don't have a particularly good way of handling this.
57
        OAuthUserHelper::prepareTokenCountStatement($database);
58
59
        if (WebRequest::getBoolean("showAll")) {
60
            $this->assign("showAll", true);
61
62
            $suspendedUsers = UserSearchHelper::get($database)->byStatus(User::STATUS_SUSPENDED)->fetch();
63
            $this->assign("suspendedUsers", $suspendedUsers);
64
65
            $declinedUsers = UserSearchHelper::get($database)->byStatus(User::STATUS_DECLINED)->fetch();
66
            $this->assign("declinedUsers", $declinedUsers);
67
68
            UserSearchHelper::get($database)->getRoleMap($roleMap);
69
        }
70
        else {
71
            $this->assign("showAll", false);
72
            $this->assign("suspendedUsers", array());
73
            $this->assign("declinedUsers", array());
74
75
            UserSearchHelper::get($database)->statusIn(array('New', 'Active'))->getRoleMap($roleMap);
76
        }
77
78
        $newUsers = UserSearchHelper::get($database)->byStatus(User::STATUS_NEW)->fetch();
79
        $normalUsers = UserSearchHelper::get($database)->byStatus(User::STATUS_ACTIVE)->byRole('user')->fetch();
80
        $adminUsers = UserSearchHelper::get($database)->byStatus(User::STATUS_ACTIVE)->byRole('admin')->fetch();
81
        $checkUsers = UserSearchHelper::get($database)->byStatus(User::STATUS_ACTIVE)->byRole('checkuser')->fetch();
82
        $stewards = UserSearchHelper::get($database)->byStatus(User::STATUS_ACTIVE)->byRole('steward')->fetch();
83
        $toolRoots = UserSearchHelper::get($database)->byStatus(User::STATUS_ACTIVE)->byRole('toolRoot')->fetch();
84
        $this->assign('newUsers', $newUsers);
85
        $this->assign('normalUsers', $normalUsers);
86
        $this->assign('adminUsers', $adminUsers);
87
        $this->assign('checkUsers', $checkUsers);
88
        $this->assign('stewards', $stewards);
89
        $this->assign('toolRoots', $toolRoots);
90
91
        $this->assign('roles', $roleMap);
92
93
        $this->addJs("/api.php?action=users&all=true&targetVariable=typeaheaddata");
94
95
        $this->assign('canApprove', $this->barrierTest('approve', $currentUser));
96
        $this->assign('canDecline', $this->barrierTest('decline', $currentUser));
97
        $this->assign('canRename', $this->barrierTest('rename', $currentUser));
98
        $this->assign('canEditUser', $this->barrierTest('editUser', $currentUser));
99
        $this->assign('canSuspend', $this->barrierTest('suspend', $currentUser));
100
        $this->assign('canEditRoles', $this->barrierTest('editRoles', $currentUser));
101
102
        // FIXME: domains!
103
        /** @var Domain $domain */
104
        $domain = Domain::getById(1, $this->getDatabase());
105
        $this->assign('mediawikiScriptPath', $domain->getWikiArticlePath());
106
107
        $this->setTemplate("usermanagement/main.tpl");
108
    }
109
110
    #region Access control
111
112
    /**
113
     * Action target for editing the roles assigned to a user
114
     *
115
     * @throws ApplicationLogicException
116
     * @throws SmartyException
117
     * @throws OptimisticLockFailedException
118
     * @throws Exception
119
     */
120
    protected function editRoles(): void
121
    {
122
        $this->setHtmlTitle('User Management');
123
        $database = $this->getDatabase();
124
        $domain = Domain::getCurrent($database);
125
        $userId = WebRequest::getInt('user');
126
127
        /** @var User|false $user */
128
        $user = User::getById($userId, $database);
129
130
        if ($user === false || $user->isCommunityUser()) {
131
            throw new ApplicationLogicException('Sorry, the user you are trying to edit could not be found.');
132
        }
133
134
        $roleData = $this->getRoleData(UserRole::getForUser($user->getId(), $database, $domain->getId()));
135
136
        // Dual-mode action
137
        if (WebRequest::wasPosted()) {
138
            $this->validateCSRFToken();
139
140
            $reason = WebRequest::postString('reason');
141
            if ($reason === false || trim($reason) === '') {
142
                throw new ApplicationLogicException('No reason specified for roles change');
143
            }
144
145
            /** @var UserRole[] $delete */
146
            $delete = array();
147
            /** @var string[] $add */
148
            $add = array();
149
150
            /** @var UserRole[] $globalDelete */
151
            $globalDelete = array();
152
            /** @var string[] $globalAdd */
153
            $globalAdd = array();
154
155
            foreach ($roleData as $name => $r) {
156
                if ($r['allowEdit'] !== 1) {
157
                    // not allowed, to touch this, so ignore it
158
                    continue;
159
                }
160
161
                $newValue = WebRequest::postBoolean('role-' . $name) ? 1 : 0;
162
                if ($newValue !== $r['active']) {
163
                    if ($newValue === 0) {
164
                        if ($r['globalOnly']) {
165
                            $globalDelete[] = $r['object'];
166
                        }
167
                        else {
168
                            $delete[] = $r['object'];
169
                        }
170
                    }
171
172
                    if ($newValue === 1) {
173
                        if ($r['globalOnly']) {
174
                            $globalAdd[] = $name;
175
                        }
176
                        else {
177
                            $add[] = $name;
178
                        }
179
                    }
180
                }
181
            }
182
183
            // Check there's something to do
184
            if ((count($add) + count($delete) + count($globalAdd) + count($globalDelete)) === 0) {
185
                $this->redirect('statistics/users', 'detail', array('user' => $user->getId()));
186
                SessionAlert::warning('No changes made to roles.');
187
188
                return;
189
            }
190
191
            $removed = array();
192
            $globalRemoved = array();
193
194
            foreach ($delete as $d) {
195
                $removed[] = $d->getRole();
196
                $d->delete();
197
            }
198
199
            foreach ($globalDelete as $d) {
200
                $globalRemoved[] = $d->getRole();
201
                $d->delete();
202
            }
203
204
            foreach ($add as $x) {
205
                $a = new UserRole();
206
                $a->setUser($user->getId());
207
                $a->setRole($x);
208
                $a->setDomain($domain->getId());
209
                $a->setDatabase($database);
210
                $a->save();
211
            }
212
213
            foreach ($globalAdd as $x) {
214
                $a = new UserRole();
215
                $a->setUser($user->getId());
216
                $a->setRole($x);
217
                $a->setDomain(null);
218
                $a->setDatabase($database);
219
                $a->save();
220
            }
221
222
            if ((count($add) + count($delete)) > 0) {
223
                Logger::userRolesEdited($database, $user, $reason, $add, $removed, $domain->getId());
224
            }
225
226
            if ((count($globalAdd) + count($globalDelete)) > 0) {
227
                Logger::userGlobalRolesEdited($database, $user, $reason, $globalAdd, $globalRemoved);
228
            }
229
230
            // dummy save for optimistic locking. If this fails, the entire txn will roll back.
231
            $user->setUpdateVersion(WebRequest::postInt('updateversion'));
232
            $user->save();
233
234
            $this->getNotificationHelper()->userRolesEdited($user, $reason);
235
            SessionAlert::quick('Roles changed for user ' . htmlentities($user->getUsername(), ENT_COMPAT, 'UTF-8'));
236
237
            $this->redirect('statistics/users', 'detail', array('user' => $user->getId()));
238
        }
239
        else {
240
            $this->assignCSRFToken();
241
            $this->setTemplate('usermanagement/roleedit.tpl');
242
            $this->assign('user', $user);
243
            $this->assign('roleData', $roleData);
244
        }
245
    }
246
247
    /**
248
     * Action target for suspending users
249
     *
250
     * @throws ApplicationLogicException
251
     */
252
    protected function suspend()
253
    {
254
        $this->setHtmlTitle('User Management');
255
256
        $database = $this->getDatabase();
257
258
        $userId = WebRequest::getInt('user');
259
260
        /** @var User $user */
261
        $user = User::getById($userId, $database);
262
263
        if ($user === false || $user->isCommunityUser()) {
264
            throw new ApplicationLogicException('Sorry, the user you are trying to suspend could not be found.');
265
        }
266
267
        if ($user->isSuspended()) {
268
            throw new ApplicationLogicException('Sorry, the user you are trying to suspend is already suspended.');
269
        }
270
271
        // Dual-mode action
272
        if (WebRequest::wasPosted()) {
273
            $this->validateCSRFToken();
274
            $reason = WebRequest::postString('reason');
275
276
            if ($reason === null || trim($reason) === "") {
277
                throw new ApplicationLogicException('No reason provided');
278
            }
279
280
            $user->setStatus(User::STATUS_SUSPENDED);
281
            $user->setUpdateVersion(WebRequest::postInt('updateversion'));
282
            $user->save();
283
            Logger::suspendedUser($database, $user, $reason);
284
285
            $this->getNotificationHelper()->userSuspended($user, $reason);
286
            SessionAlert::quick('Suspended user ' . htmlentities($user->getUsername(), ENT_COMPAT, 'UTF-8'));
287
288
            // send email
289
            $this->sendStatusChangeEmail(
290
                'Your WP:ACC account has been suspended',
291
                'usermanagement/emails/suspended.tpl',
292
                $reason,
293
                $user,
294
                User::getCurrent($database)->getUsername()
295
            );
296
297
            $this->redirect('userManagement');
298
299
            return;
300
        }
301
        else {
302
            $this->assignCSRFToken();
303
            $this->setTemplate('usermanagement/changelevel-reason.tpl');
304
            $this->assign('user', $user);
305
            $this->assign('status', 'Suspended');
306
            $this->assign("showReason", true);
307
308
            if (WebRequest::getString('preload')) {
309
                $this->assign('preload', WebRequest::getString('preload'));
310
            }
311
        }
312
    }
313
314
    /**
315
     * Entry point for the decline action
316
     *
317
     * @throws ApplicationLogicException
318
     */
319
    protected function decline()
320
    {
321
        $this->setHtmlTitle('User Management');
322
323
        $database = $this->getDatabase();
324
325
        $userId = WebRequest::getInt('user');
326
        $user = User::getById($userId, $database);
327
328
        if ($user === false || $user->isCommunityUser()) {
329
            throw new ApplicationLogicException('Sorry, the user you are trying to decline could not be found.');
330
        }
331
332
        if (!$user->isNewUser()) {
333
            throw new ApplicationLogicException('Sorry, the user you are trying to decline is not new.');
334
        }
335
336
        // Dual-mode action
337
        if (WebRequest::wasPosted()) {
338
            $this->validateCSRFToken();
339
            $reason = WebRequest::postString('reason');
340
341
            if ($reason === null || trim($reason) === "") {
342
                throw new ApplicationLogicException('No reason provided');
343
            }
344
345
            $user->setStatus(User::STATUS_DECLINED);
346
            $user->setUpdateVersion(WebRequest::postInt('updateversion'));
347
            $user->save();
348
            Logger::declinedUser($database, $user, $reason);
349
350
            $this->getNotificationHelper()->userDeclined($user, $reason);
351
            SessionAlert::quick('Declined user ' . htmlentities($user->getUsername(), ENT_COMPAT, 'UTF-8'));
352
353
            // send email
354
            $this->sendStatusChangeEmail(
355
                'Your WP:ACC account has been declined',
356
                'usermanagement/emails/declined.tpl',
357
                $reason,
358
                $user,
359
                User::getCurrent($database)->getUsername()
360
            );
361
362
            $this->redirect('userManagement');
363
364
            return;
365
        }
366
        else {
367
            $this->assignCSRFToken();
368
            $this->setTemplate('usermanagement/changelevel-reason.tpl');
369
            $this->assign('user', $user);
370
            $this->assign('status', 'Declined');
371
            $this->assign("showReason", true);
372
        }
373
    }
374
375
    /**
376
     * Entry point for the approve action
377
     *
378
     * @throws ApplicationLogicException
379
     */
380
    protected function approve()
381
    {
382
        $this->setHtmlTitle('User Management');
383
384
        $database = $this->getDatabase();
385
386
        $userId = WebRequest::getInt('user');
387
        $user = User::getById($userId, $database);
388
389
        if ($user === false || $user->isCommunityUser()) {
390
            throw new ApplicationLogicException('Sorry, the user you are trying to approve could not be found.');
391
        }
392
393
        if ($user->isActive()) {
394
            throw new ApplicationLogicException('Sorry, the user you are trying to approve is already an active user.');
395
        }
396
397
        // Dual-mode action
398
        if (WebRequest::wasPosted()) {
399
            $this->validateCSRFToken();
400
            $user->setStatus(User::STATUS_ACTIVE);
401
            $user->setUpdateVersion(WebRequest::postInt('updateversion'));
402
            $user->save();
403
            Logger::approvedUser($database, $user);
404
405
            $this->getNotificationHelper()->userApproved($user);
406
            SessionAlert::quick('Approved user ' . htmlentities($user->getUsername(), ENT_COMPAT, 'UTF-8'));
407
408
            // send email
409
            $this->sendStatusChangeEmail(
410
                'Your WP:ACC account has been approved',
411
                'usermanagement/emails/approved.tpl',
412
                null,
413
                $user,
414
                User::getCurrent($database)->getUsername()
415
            );
416
417
            $this->redirect("userManagement");
418
419
            return;
420
        }
421
        else {
422
            $this->assignCSRFToken();
423
            $this->setTemplate("usermanagement/changelevel-reason.tpl");
424
            $this->assign("user", $user);
425
            $this->assign("status", "Active");
426
            $this->assign("showReason", false);
427
        }
428
    }
429
430
    #endregion
431
432
    #region Renaming / Editing
433
434
    /**
435
     * Entry point for the rename action
436
     *
437
     * @throws ApplicationLogicException
438
     */
439
    protected function rename()
440
    {
441
        $this->setHtmlTitle('User Management');
442
443
        $database = $this->getDatabase();
444
445
        $userId = WebRequest::getInt('user');
446
        $user = User::getById($userId, $database);
447
448
        if ($user === false || $user->isCommunityUser()) {
449
            throw new ApplicationLogicException('Sorry, the user you are trying to rename could not be found.');
450
        }
451
452
        // Dual-mode action
453
        if (WebRequest::wasPosted()) {
454
            $this->validateCSRFToken();
455
            $newUsername = WebRequest::postString('newname');
456
457
            if ($newUsername === null || trim($newUsername) === "") {
458
                throw new ApplicationLogicException('The new username cannot be empty');
459
            }
460
461
            if (User::getByUsername($newUsername, $database) != false) {
462
                throw new ApplicationLogicException('The new username already exists');
463
            }
464
465
            $oldUsername = $user->getUsername();
466
            $user->setUsername($newUsername);
467
            $user->setUpdateVersion(WebRequest::postInt('updateversion'));
468
469
            $user->save();
470
471
            $logEntryData = serialize(array(
472
                'old' => $oldUsername,
473
                'new' => $newUsername,
474
            ));
475
476
            Logger::renamedUser($database, $user, $logEntryData);
477
478
            SessionAlert::quick("Changed User "
479
                . htmlentities($oldUsername, ENT_COMPAT, 'UTF-8')
480
                . " name to "
481
                . htmlentities($newUsername, ENT_COMPAT, 'UTF-8'));
482
483
            $this->getNotificationHelper()->userRenamed($user, $oldUsername);
484
485
            // send an email to the user.
486
            $this->assign('targetUsername', $user->getUsername());
487
            $this->assign('toolAdmin', User::getCurrent($database)->getUsername());
488
            $this->assign('oldUsername', $oldUsername);
489
            $this->assign('mailingList', $this->adminMailingList);
490
491
            // FIXME: domains!
492
            /** @var Domain $domain */
493
            $domain = Domain::getById(1, $database);
494
            $this->getEmailHelper()->sendMail(
495
                $this->adminMailingList,
496
                $user->getEmail(),
497
                'Your username on WP:ACC has been changed',
498
                $this->fetchTemplate('usermanagement/emails/renamed.tpl')
499
            );
500
501
            $this->redirect("userManagement");
502
503
            return;
504
        }
505
        else {
506
            $this->assignCSRFToken();
507
            $this->setTemplate('usermanagement/renameuser.tpl');
508
            $this->assign('user', $user);
509
        }
510
    }
511
512
    /**
513
     * Entry point for the edit action
514
     *
515
     * @throws ApplicationLogicException
516
     */
517
    protected function editUser()
518
    {
519
        $this->setHtmlTitle('User Management');
520
521
        $database = $this->getDatabase();
522
523
        $userId = WebRequest::getInt('user');
524
        $user = User::getById($userId, $database);
525
        $oauth = new OAuthUserHelper($user, $database, $this->getOAuthProtocolHelper(), $this->getSiteConfiguration());
526
527
        if ($user === false || $user->isCommunityUser()) {
528
            throw new ApplicationLogicException('Sorry, the user you are trying to edit could not be found.');
529
        }
530
531
        // FIXME: domains
532
        $prefs = new PreferenceManager($database, $user->getId(), 1);
533
534
        // Dual-mode action
535
        if (WebRequest::wasPosted()) {
536
            $this->validateCSRFToken();
537
            $newEmail = WebRequest::postEmail('user_email');
538
            $newOnWikiName = WebRequest::postString('user_onwikiname');
539
540
            if ($newEmail === null) {
541
                throw new ApplicationLogicException('Invalid email address');
542
            }
543
544
            if ($this->validateUnusedEmail($newEmail, $userId)) {
545
                throw new ApplicationLogicException('The specified email address is already in use.');
546
            }
547
548
            if (!($oauth->isFullyLinked() || $oauth->isPartiallyLinked())) {
549
                if (trim($newOnWikiName) == "") {
550
                    throw new ApplicationLogicException('New on-wiki username cannot be blank');
551
                }
552
553
                $user->setOnWikiName($newOnWikiName);
554
            }
555
556
            $user->setEmail($newEmail);
557
558
            $prefs->setLocalPreference(PreferenceManager::PREF_CREATION_MODE, WebRequest::postInt('creationmode'));
559
560
            $user->setUpdateVersion(WebRequest::postInt('updateversion'));
561
562
            $user->save();
563
564
            Logger::userPreferencesChange($database, $user);
565
            $this->getNotificationHelper()->userPrefChange($user);
566
            SessionAlert::quick('Changes to user\'s preferences have been saved');
567
568
            $this->redirect("userManagement");
569
570
            return;
571
        }
572
        else {
573
            $this->assignCSRFToken();
574
            $oauth = new OAuthUserHelper($user, $database, $this->getOAuthProtocolHelper(),
575
                $this->getSiteConfiguration());
576
            $this->setTemplate('usermanagement/edituser.tpl');
577
            $this->assign('user', $user);
578
            $this->assign('oauth', $oauth);
579
580
            $this->assign('preferredCreationMode', (int)$prefs->getPreference(PreferenceManager::PREF_CREATION_MODE));
581
            $this->assign('emailSignature', $prefs->getPreference(PreferenceManager::PREF_EMAIL_SIGNATURE));
582
583
            $this->assign('canManualCreate',
584
                $this->barrierTest(PreferenceManager::CREATION_MANUAL, $user, 'RequestCreation'));
585
            $this->assign('canOauthCreate',
586
                $this->barrierTest(PreferenceManager::CREATION_OAUTH, $user, 'RequestCreation'));
587
            $this->assign('canBotCreate',
588
                $this->barrierTest(PreferenceManager::CREATION_BOT, $user, 'RequestCreation'));
589
        }
590
    }
591
592
    #endregion
593
594
    private function validateUnusedEmail(string $email, int $userId) : bool {
595
        $query = 'SELECT COUNT(id) FROM user WHERE email = :email AND id <> :uid';
596
        $statement = $this->getDatabase()->prepare($query);
597
        $statement->execute(array(':email' => $email, ':uid' => $userId));
598
        $inUse = $statement->fetchColumn() > 0;
599
        $statement->closeCursor();
600
601
        return $inUse;
602
    }
603
604
    /**
605
     * Sends a status change email to the user.
606
     *
607
     * @param string      $subject           The subject of the email
608
     * @param string      $template          The smarty template to use
609
     * @param string|null $reason            The reason for performing the status change
610
     * @param User        $user              The user affected
611
     * @param string      $toolAdminUsername The tool admin's username who is making the edit
612
     */
613
    private function sendStatusChangeEmail($subject, $template, $reason, $user, $toolAdminUsername)
614
    {
615
        $this->assign('targetUsername', $user->getUsername());
616
        $this->assign('toolAdmin', $toolAdminUsername);
617
        $this->assign('actionReason', $reason);
618
        $this->assign('mailingList', $this->adminMailingList);
619
620
        // FIXME: domains!
621
        /** @var Domain $domain */
622
        $domain = Domain::getById(1, $this->getDatabase());
623
        $this->getEmailHelper()->sendMail(
624
            $this->adminMailingList,
625
            $user->getEmail(),
626
            $subject,
627
            $this->fetchTemplate($template)
628
        );
629
    }
630
631
    /**
632
     * @param UserRole[] $activeRoles
633
     *
634
     * @return array
635
     */
636
    private function getRoleData($activeRoles)
637
    {
638
        $availableRoles = $this->getSecurityManager()->getRoleConfiguration()->getAvailableRoles();
639
640
        $currentUser = User::getCurrent($this->getDatabase());
641
        $this->getSecurityManager()->getActiveRoles($currentUser, $userRoles, $inactiveRoles);
642
643
        $initialValue = array('active' => 0, 'allowEdit' => 0, 'description' => '???', 'object' => null);
644
645
        $roleData = array();
646
        foreach ($availableRoles as $role => $data) {
647
            $intersection = array_intersect($data['editableBy'], $userRoles);
648
649
            $roleData[$role] = $initialValue;
650
            $roleData[$role]['allowEdit'] = count($intersection) > 0 ? 1 : 0;
651
            $roleData[$role]['description'] = $data['description'];
652
            $roleData[$role]['globalOnly'] = $data['globalOnly'];
653
        }
654
655
        foreach ($activeRoles as $role) {
656
            if (!isset($roleData[$role->getRole()])) {
657
                // This value is no longer available in the configuration, allow changing (aka removing) it.
658
                $roleData[$role->getRole()] = $initialValue;
659
                $roleData[$role->getRole()]['allowEdit'] = 1;
660
            }
661
662
            $roleData[$role->getRole()]['object'] = $role;
663
            $roleData[$role->getRole()]['active'] = 1;
664
        }
665
666
        return $roleData;
667
    }
668
}
669