RoleTrait::_encryptPassword()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 3
rs 10
c 0
b 0
f 0
cc 1
eloc 1
nc 1
nop 2
1
<?php
2
3
/**
4
 * PHPPgAdmin 6.1.3
5
 */
6
7
namespace PHPPgAdmin\Database\Traits;
8
9
/**
10
 * Common trait for roles and users manipulation.
11
 */
12
trait RoleTrait
13
{
14
    /**
15
     * Returns all roles in the database cluster.
16
     *
17
     * @param string $rolename (optional) The role name to exclude from the select
18
     *
19
     * @return int|\PHPPgAdmin\ADORecordSet
20
     */
21
    public function getRoles($rolename = '')
22
    {
23
        $sql = '
24
			SELECT
25
                r.rolname,
26
                r1.rolname as group,
27
                r.rolsuper,
28
                r.rolcreatedb,
29
                r.rolcreaterole,
30
                r.rolinherit,
31
                r.rolcanlogin,
32
                r.rolconnlimit,
33
                r.rolvaliduntil,
34
                r.rolconfig
35
            FROM pg_catalog.pg_roles r
36
            LEFT JOIN pg_catalog.pg_auth_members m ON (m.member = r.oid)
37
            LEFT JOIN pg_roles r1 ON (m.roleid=r1.oid)
38
            ';
39
40
        if ($rolename) {
41
            $sql .= " WHERE r.rolname!='{$rolename}'";
42
        }
43
44
        $sql .= ' ORDER BY r.rolname';
45
46
        return $this->selectSet($sql);
47
    }
48
49
    /**
50
     * Returns information about a single role.
51
     *
52
     * @param string $rolename The name of the role to retrieve
53
     *
54
     * @return int|\PHPPgAdmin\ADORecordSet
55
     */
56
    public function getRole($rolename)
57
    {
58
        $this->clean($rolename);
59
60
        $sql = "
61
            SELECT
62
                r.rolname,
63
                r1.rolname as group,
64
                r.rolsuper,
65
                r.rolcreatedb,
66
                r.rolcreaterole,
67
                r.rolinherit,
68
                r.rolcanlogin,
69
                r.rolconnlimit,
70
                r.rolvaliduntil,
71
                r.rolconfig
72
            FROM pg_catalog.pg_roles r
73
            LEFT JOIN pg_catalog.pg_auth_members m ON (m.member = r.oid)
74
            LEFT JOIN pg_roles r1 ON (m.roleid=r1.oid)
75
            WHERE r.rolname='{$rolename}'";
76
77
        return $this->selectSet($sql);
78
    }
79
80
    /**
81
     * Returns all users in the database cluster.
82
     *
83
     * @return int|\PHPPgAdmin\ADORecordSet
84
     */
85
    public function getUsers()
86
    {
87
        $sql = 'SELECT
88
                r.usename,
89
                r1.rolname as group,
90
                r.usesuper,
91
                r.valuntil AS useexpires,
92
                r.useconfig
93
            FROM pg_catalog.pg_user r
94
            LEFT JOIN pg_catalog.pg_auth_members m ON (m.member = r.usesysid)
95
            LEFT JOIN pg_roles r1 ON (m.roleid=r1.oid)';
96
97
        return $this->selectSet($sql);
98
    }
99
100
    /**
101
     * Returns information about a single user.
102
     *
103
     * @param string $username The username of the user to retrieve
104
     *
105
     * @return int|\PHPPgAdmin\ADORecordSet
106
     */
107
    public function getUser($username)
108
    {
109
        $this->clean($username);
110
111
        $sql = "SELECT
112
                r.usename,
113
                r1.rolname as group,
114
                r.usesuper,
115
                r.valuntil AS useexpires,
116
                r.useconfig
117
            FROM pg_catalog.pg_user r
118
            LEFT JOIN pg_catalog.pg_auth_members m ON (m.member = r.usesysid)
119
            LEFT JOIN pg_roles r1 ON (m.roleid=r1.oid)
120
			WHERE r.usename='{$username}'";
121
122
        return $this->selectSet($sql);
123
    }
124
125
    /**
126
     * Creates a new role.
127
     *
128
     * @param string $rolename            The name of the role to create
129
     * @param string $password            A password for the role
130
     * @param bool   $superuser           Boolean whether or not the role is a superuser
131
     * @param bool   $createdb            Boolean whether or not the role can create databases
132
     * @param bool   $createrole          Boolean whether or not the role can create other roles
133
     * @param bool   $inherits            Boolean whether or not the role inherits the privileges from parent roles
134
     * @param bool   $login               Boolean whether or not the role will be allowed to login
135
     * @param int    $connlimit           Number of concurrent connections the role can make
136
     * @param string $expiry              String Format 'YYYY-MM-DD HH:MM:SS'.  '' means never expire
137
     * @param array  $new_roles_to_add    (array) Roles to which the new role will be immediately added as a new member
138
     * @param array  $new_members_of_role (array) Roles which are automatically added as members of the new role
139
     * @param array  $new_admins_of_role  (array) Roles which are automatically added as admin members of the new role
140
     *
141
     * @return int|\PHPPgAdmin\ADORecordSet
142
     */
143
    public function createRole(
144
        $rolename,
145
        $password,
146
        $superuser,
147
        $createdb,
148
        $createrole,
149
        $inherits,
150
        $login,
151
        $connlimit,
152
        $expiry,
153
        $new_roles_to_add,
154
        $new_members_of_role,
155
        $new_admins_of_role
156
    ) {
157
        $enc = $this->_encryptPassword($rolename, $password);
158
        $this->fieldClean($rolename);
159
        $this->clean($enc);
160
        $this->clean($connlimit);
161
        $this->clean($expiry);
162
        $this->fieldArrayClean($new_roles_to_add);
163
        $this->fieldArrayClean($new_members_of_role);
164
        $this->fieldArrayClean($new_admins_of_role);
165
166
        $sql = "CREATE ROLE \"{$rolename}\"";
167
168
        if ('' !== $password) {
169
            $sql .= " WITH ENCRYPTED PASSWORD '{$enc}'";
170
        }
171
172
        $sql .= $superuser ? ' SUPERUSER' : ' NOSUPERUSER';
173
        $sql .= $createdb ? ' CREATEDB' : ' NOCREATEDB';
174
        $sql .= $createrole ? ' CREATEROLE' : ' NOCREATEROLE';
175
        $sql .= $inherits ? ' INHERIT' : ' NOINHERIT';
176
        $sql .= $login ? ' LOGIN' : ' NOLOGIN';
177
178
        if ('' !== $connlimit) {
179
            $sql .= " CONNECTION LIMIT {$connlimit}";
180
        } else {
181
            $sql .= ' CONNECTION LIMIT -1';
182
        }
183
184
        if ('' !== $expiry) {
185
            $sql .= " VALID UNTIL '{$expiry}'";
186
        } else {
187
            $sql .= " VALID UNTIL 'infinity'";
188
        }
189
190
        if (\is_array($new_roles_to_add) && 0 < \count($new_roles_to_add)) {
191
            $sql .= ' IN ROLE "' . \implode('", "', $new_roles_to_add) . '"';
192
        }
193
194
        if (\is_array($new_members_of_role) && 0 < \count($new_members_of_role)) {
195
            $sql .= ' ROLE "' . \implode('", "', $new_members_of_role) . '"';
196
        }
197
198
        if (\is_array($new_admins_of_role) && 0 < \count($new_admins_of_role)) {
199
            $sql .= ' ADMIN "' . \implode('", "', $new_admins_of_role) . '"';
200
        }
201
202
        return $this->execute($sql);
203
    }
204
205
    /**
206
     * Helper function that computes encypted PostgreSQL passwords.
207
     *
208
     * @param string $username The username
209
     * @param string $password The password
210
     *
211
     * @return string
212
     */
213
    public function _encryptPassword($username, $password)
214
    {
215
        return 'md5' . \md5($password . $username);
216
    }
217
218
    /**
219
     * Adjusts a role's info and renames it.
220
     *
221
     * @param string $rolename              The name of the role to adjust
222
     * @param string $password              A password for the role
223
     * @param bool   $superuser             Boolean whether or not the role is a superuser
224
     * @param bool   $createdb              Boolean whether or not the role can create databases
225
     * @param bool   $createrole            Boolean whether or not the role can create other roles
226
     * @param bool   $inherits              Boolean whether or not the role inherits the privileges from parent roles
227
     * @param bool   $login                 Boolean whether or not the role will be allowed to login
228
     * @param int    $connlimit             Number of concurrent connections the role can make
229
     * @param string $expiry                string Format 'YYYY-MM-DD HH:MM:SS'.  '' means never expire
230
     * @param array  $new_roles_to_add      (array) Roles to which the role will be immediately added as a new member
231
     * @param array  $new_members_of_role   (array) Roles which are automatically added as members of the role
232
     * @param array  $new_admins_of_role    (array) Roles which are automatically added as admin members of the role
233
     * @param string $original_parent_roles Original roles whose the role belongs to, comma separated
234
     * @param string $original_members      Original roles that are members of the role, comma separated
235
     * @param string $original_admins       Original roles that are admin members of the role, comma separated
236
     * @param string $newrolename           The new name of the role
237
     *
238
     * @return bool|int 0 success
239
     */
240
    public function setRenameRole(
241
        $rolename,
242
        $password,
243
        $superuser,
244
        $createdb,
245
        $createrole,
246
        $inherits,
247
        $login,
248
        $connlimit,
249
        $expiry,
250
        $new_roles_to_add,
251
        $new_members_of_role,
252
        $new_admins_of_role,
253
        $original_parent_roles,
254
        $original_members,
255
        $original_admins,
256
        $newrolename
257
    ) {
258
        $status = $this->beginTransaction();
259
260
        if (0 !== $status) {
261
            return -1;
262
        }
263
264
        if ($rolename !== $newrolename) {
265
            $status = $this->renameRole($rolename, $newrolename);
266
267
            if (0 !== $status) {
268
                $this->rollbackTransaction();
269
270
                return -3;
271
            }
272
            $rolename = $newrolename;
273
        }
274
275
        $status = $this->setRole(
276
            $rolename,
277
            $password,
278
            $superuser,
279
            $createdb,
280
            $createrole,
281
            $inherits,
282
            $login,
283
            $connlimit,
284
            $expiry,
285
            $new_roles_to_add,
286
            $new_members_of_role,
287
            $new_admins_of_role,
288
            $original_parent_roles,
289
            $original_members,
290
            $original_admins
291
        );
292
293
        if (0 !== $status) {
294
            $this->rollbackTransaction();
295
296
            return -2;
297
        }
298
299
        return $this->endTransaction();
300
    }
301
302
    /**
303
     * Renames a role.
304
     *
305
     * @param string $rolename    The name of the role to rename
306
     * @param string $newrolename The new name of the role
307
     *
308
     * @return int|\PHPPgAdmin\ADORecordSet
309
     */
310
    public function renameRole($rolename, $newrolename)
311
    {
312
        $this->fieldClean($rolename);
313
        $this->fieldClean($newrolename);
314
315
        $sql = "ALTER ROLE \"{$rolename}\" RENAME TO \"{$newrolename}\"";
316
317
        return $this->execute($sql);
318
    }
319
320
    /**
321
     * Adjusts a role's info.
322
     *
323
     * @param string $rolename              The name of the role to adjust
324
     * @param string $password              A password for the role
325
     * @param bool   $superuser             Boolean whether or not the role is a superuser
326
     * @param bool   $createdb              Boolean whether or not the role can create databases
327
     * @param bool   $createrole            Boolean whether or not the role can create other roles
328
     * @param bool   $inherits              Boolean whether or not the role inherits the privileges from parent roles
329
     * @param bool   $login                 Boolean whether or not the role will be allowed to login
330
     * @param int    $connlimit             Number of concurrent connections the role can make
331
     * @param string $expiry                string Format 'YYYY-MM-DD HH:MM:SS'.  '' means never expire
332
     * @param array  $new_roles_to_add      (array) Roles to which the role will be immediately added as a new member
333
     * @param array  $new_members_of_role   (array) Roles which are automatically added as members of the role
334
     * @param array  $new_admins_of_role    (array) Roles which are automatically added as admin members of the role
335
     * @param string $original_parent_roles Original roles whose the role belongs to, comma separated
336
     * @param string $original_members      Original roles that are members of the role, comma separated
337
     * @param string $original_admins       Original roles that are admin members of the role, comma separated
338
     *
339
     * @return int 0 if operation was successful
340
     */
341
    public function setRole(
342
        $rolename,
343
        $password,
344
        $superuser,
345
        $createdb,
346
        $createrole,
347
        $inherits,
348
        $login,
349
        $connlimit,
350
        $expiry,
351
        $new_roles_to_add,
352
        $new_members_of_role,
353
        $new_admins_of_role,
354
        $original_parent_roles,
355
        $original_members,
356
        $original_admins
357
    ) {
358
        $this->fieldClean($rolename);
359
360
        $this->fieldArrayClean($new_roles_to_add);
361
        $this->fieldArrayClean($new_members_of_role);
362
        $this->fieldArrayClean($new_admins_of_role);
363
364
        $status = $this->_alterRole($rolename, $password, $connlimit, $expiry, $superuser, $createdb, $createrole, $inherits, $login);
365
366
        if (0 !== $status) {
367
            return -1;
368
        }
369
370
        // If there were existing users with the requested role,
371
        // assign their roles to the new user, and remove said
372
        // role from them if they are not among the new authorized members
373
        if ($original_parent_roles) {
374
            $status = $this->_dealWithOldParentRoles($original_parent_roles, $new_roles_to_add, $rolename);
375
376
            if (0 !== $status) {
377
                return -1;
378
            }
379
        }
380
381
        if ($original_members) {
382
            $status = $this->_dealWithOriginalMembers($original_members, $new_members_of_role, $rolename);
383
384
            if (0 !== $status) {
385
                return -1;
386
            }
387
        }
388
389
        if ($original_admins) {
390
            $status = $this->_dealWithOriginalAdmins($original_admins, $new_admins_of_role, $rolename);
391
392
            if (0 !== $status) {
393
                return -1;
394
            }
395
        }
396
397
        return $status;
398
    }
399
400
    /**
401
     * Grants membership in a role.
402
     *
403
     * @param string $role     The name of the target role
404
     * @param string $rolename The name of the role that will belong to the target role
405
     * @param int    $admin    (optional) Flag to grant the admin option
406
     *
407
     * @return int|\PHPPgAdmin\ADORecordSet
408
     */
409
    public function grantRole($role, $rolename, $admin = 0)
410
    {
411
        $this->fieldClean($role);
412
        $this->fieldClean($rolename);
413
414
        $sql = "GRANT \"{$role}\" TO \"{$rolename}\"";
415
416
        if (1 === $admin) {
417
            $sql .= ' WITH ADMIN OPTION';
418
        }
419
420
        return $this->execute($sql);
421
    }
422
423
    /**
424
     * Revokes membership in a role.
425
     *
426
     * @param string $role     The name of the target role
427
     * @param string $rolename The name of the role that will not belong to the target role
428
     * @param int    $admin    (optional) Flag to revoke only the admin option
429
     * @param string $type     (optional) Type of revoke: RESTRICT | CASCADE
430
     *
431
     * @return int|\PHPPgAdmin\ADORecordSet
432
     */
433
    public function revokeRole($role, $rolename, $admin = 0, $type = 'RESTRICT')
434
    {
435
        $this->fieldClean($role);
436
        $this->fieldClean($rolename);
437
438
        $sql = 'REVOKE ';
439
440
        if (1 === $admin) {
441
            $sql .= 'ADMIN OPTION FOR ';
442
        }
443
444
        $sql .= "\"{$role}\" FROM \"{$rolename}\" {$type}";
445
446
        return $this->execute($sql);
447
    }
448
449
    /**
450
     * Removes a role.
451
     *
452
     * @param string $rolename The name of the role to drop
453
     *
454
     * @return int|\PHPPgAdmin\ADORecordSet
455
     */
456
    public function dropRole($rolename)
457
    {
458
        $this->fieldClean($rolename);
459
460
        $sql = "DROP ROLE \"{$rolename}\"";
461
462
        return $this->execute($sql);
463
    }
464
465
    /**
466
     * Creates a new user.
467
     *
468
     * @param string $username   The username of the user to create
469
     * @param string $password   A password for the user
470
     * @param bool   $createdb   boolean Whether or not the user can create databases
471
     * @param bool   $createuser boolean Whether or not the user can create other users
472
     * @param string $expiry     string Format 'YYYY-MM-DD HH:MM:SS'.  '' means never expire
473
     * @param array  $groups     The groups to create the user in
474
     *
475
     * @return int|\PHPPgAdmin\ADORecordSet
476
     *
477
     * @internal param $group (array) The groups to create the user in
478
     */
479
    public function createUser($username, $password, $createdb, $createuser, $expiry, $groups)
480
    {
481
        $enc = $this->_encryptPassword($username, $password);
482
        $this->fieldClean($username);
483
        $this->clean($enc);
484
        $this->clean($expiry);
485
        $this->fieldArrayClean($groups);
486
487
        $sql = "CREATE USER \"{$username}\"";
488
489
        if ('' !== $password) {
490
            $sql .= " WITH ENCRYPTED PASSWORD '{$enc}'";
491
        }
492
493
        $sql .= $createdb ? ' CREATEDB' : ' NOCREATEDB';
494
        $sql .= $createuser ? ' CREATEUSER' : ' NOCREATEUSER';
495
496
        if (\is_array($groups) && 0 < \count($groups)) {
497
            $sql .= ' IN GROUP "' . \implode('", "', $groups) . '"';
498
        }
499
500
        if ('' !== $expiry) {
501
            $sql .= " VALID UNTIL '{$expiry}'";
502
        } else {
503
            $sql .= " VALID UNTIL 'infinity'";
504
        }
505
506
        return $this->execute($sql);
507
    }
508
509
    /**
510
     * Adjusts a user's info and renames the user.
511
     *
512
     * @param string $username   The username of the user to modify
513
     * @param string $password   A new password for the user
514
     * @param bool   $createdb   boolean Whether or not the user can create databases
515
     * @param bool   $createuser boolean Whether or not the user can create other users
516
     * @param string $expiry     string Format 'YYYY-MM-DD HH:MM:SS'.  '' means never expire.
517
     * @param string $newname    The new name of the user
518
     *
519
     * @return bool|int 0 success
520
     */
521
    public function setRenameUser($username, $password, $createdb, $createuser, $expiry, $newname)
522
    {
523
        $status = $this->beginTransaction();
524
525
        if (0 !== $status) {
526
            return -1;
527
        }
528
529
        if ($username !== $newname) {
530
            $status = $this->renameUser($username, $newname);
531
532
            if (0 !== $status) {
533
                $this->rollbackTransaction();
534
535
                return -3;
536
            }
537
            $username = $newname;
538
        }
539
540
        $status = $this->setUser($username, $password, $createdb, $createuser, $expiry);
541
542
        if (0 !== $status) {
543
            $this->rollbackTransaction();
544
545
            return -2;
546
        }
547
548
        return $this->endTransaction();
549
    }
550
551
    /**
552
     * Renames a user.
553
     *
554
     * @param string $username The username of the user to rename
555
     * @param string $newname  The new name of the user
556
     *
557
     * @return int|\PHPPgAdmin\ADORecordSet
558
     */
559
    public function renameUser($username, $newname)
560
    {
561
        $this->fieldClean($username);
562
        $this->fieldClean($newname);
563
564
        $sql = "ALTER USER \"{$username}\" RENAME TO \"{$newname}\"";
565
566
        return $this->execute($sql);
567
    }
568
569
    // Tablespace functions
570
571
    /**
572
     * Adjusts a user's info.
573
     *
574
     * @param string $username   The username of the user to modify
575
     * @param string $password   A new password for the user
576
     * @param bool   $createdb   boolean Whether or not the user can create databases
577
     * @param bool   $createuser boolean Whether or not the user can create other users
578
     * @param string $expiry     string Format 'YYYY-MM-DD HH:MM:SS'.  '' means never expire.
579
     *
580
     * @return int|\PHPPgAdmin\ADORecordSet
581
     */
582
    public function setUser($username, $password, $createdb, $createuser, $expiry)
583
    {
584
        $enc = $this->_encryptPassword($username, $password);
585
        $this->fieldClean($username);
586
        $this->clean($enc);
587
        $this->clean($expiry);
588
589
        $sql = "ALTER USER \"{$username}\"";
590
591
        if ('' !== $password) {
592
            $sql .= " WITH ENCRYPTED PASSWORD '{$enc}'";
593
        }
594
595
        $sql .= $createdb ? ' CREATEDB' : ' NOCREATEDB';
596
        $sql .= $createuser ? ' CREATEUSER' : ' NOCREATEUSER';
597
598
        if ('' !== $expiry) {
599
            $sql .= " VALID UNTIL '{$expiry}'";
600
        } else {
601
            $sql .= " VALID UNTIL 'infinity'";
602
        }
603
604
        return $this->execute($sql);
605
    }
606
607
    /**
608
     * Removes a user.
609
     *
610
     * @param string $username The username of the user to drop
611
     *
612
     * @return int|\PHPPgAdmin\ADORecordSet
613
     */
614
    public function dropUser($username)
615
    {
616
        $this->fieldClean($username);
617
618
        $sql = "DROP USER \"{$username}\"";
619
620
        return $this->execute($sql);
621
    }
622
623
    /**
624
     * Changes a role's password.
625
     *
626
     * @param string $rolename The role name
627
     * @param string $password The new password
628
     *
629
     * @return int|\PHPPgAdmin\ADORecordSet
630
     */
631
    public function changePassword($rolename, $password)
632
    {
633
        $enc = $this->_encryptPassword($rolename, $password);
634
        $this->fieldClean($rolename);
635
        $this->clean($enc);
636
637
        $sql = "ALTER ROLE \"{$rolename}\" WITH ENCRYPTED PASSWORD '{$enc}'";
638
639
        return $this->execute($sql);
640
    }
641
642
    /**
643
     * Adds a group member.
644
     *
645
     * @param string $groname The name of the group
646
     * @param string $user    The name of the user to add to the group
647
     *
648
     * @return int|\PHPPgAdmin\ADORecordSet
649
     */
650
    public function addGroupMember($groname, $user)
651
    {
652
        $this->fieldClean($groname);
653
        $this->fieldClean($user);
654
655
        $sql = "ALTER GROUP \"{$groname}\" ADD USER \"{$user}\"";
656
657
        return $this->execute($sql);
658
    }
659
660
    /**
661
     * Returns all role names which the role belongs to.
662
     *
663
     * @param string $rolename The role name
664
     *
665
     * @return int|\PHPPgAdmin\ADORecordSet
666
     */
667
    public function getMemberOf($rolename)
668
    {
669
        $this->clean($rolename);
670
671
        $sql = "
672
			SELECT rolname FROM pg_catalog.pg_roles R, pg_auth_members M
673
			WHERE R.oid=M.roleid
674
				AND member IN (
675
					SELECT oid FROM pg_catalog.pg_roles
676
					WHERE rolname='{$rolename}')
677
			ORDER BY rolname";
678
679
        return $this->selectSet($sql);
680
    }
681
682
    // Administration functions
683
684
    /**
685
     * Returns all role names that are members of a role.
686
     *
687
     * @param string $rolename The role name
688
     * @param string $admin    (optional) Find only admin members
689
     *
690
     * @return int|\PHPPgAdmin\ADORecordSet
691
     */
692
    public function getMembers($rolename, $admin = 'f')
693
    {
694
        $this->clean($rolename);
695
696
        $sql = "
697
			SELECT rolname FROM pg_catalog.pg_roles R, pg_auth_members M
698
			WHERE R.oid=M.member AND admin_option='{$admin}'
699
				AND roleid IN (SELECT oid FROM pg_catalog.pg_roles
700
					WHERE rolname='{$rolename}')
701
			ORDER BY rolname";
702
703
        return $this->selectSet($sql);
704
    }
705
706
    /**
707
     * Removes a group member.
708
     *
709
     * @param string $groname The name of the group
710
     * @param string $user    The name of the user to remove from the group
711
     *
712
     * @return int|\PHPPgAdmin\ADORecordSet
713
     */
714
    public function dropGroupMember($groname, $user)
715
    {
716
        $this->fieldClean($groname);
717
        $this->fieldClean($user);
718
719
        $sql = "ALTER GROUP \"{$groname}\" DROP USER \"{$user}\"";
720
721
        return $this->execute($sql);
722
    }
723
724
    /**
725
     * Return users in a specific group.
726
     *
727
     * @param string $groname The name of the group
728
     *
729
     * @return int|\PHPPgAdmin\ADORecordSet
730
     */
731
    public function getGroup($groname)
732
    {
733
        $this->clean($groname);
734
735
        $sql = "
736
			SELECT s.usename FROM pg_catalog.pg_user s, pg_catalog.pg_group g
737
			WHERE g.groname='{$groname}' AND s.usesysid = ANY (g.grolist)
738
			ORDER BY s.usename";
739
740
        return $this->selectSet($sql);
741
    }
742
743
    /**
744
     * Returns all groups in the database cluser.
745
     *
746
     * @return int|\PHPPgAdmin\ADORecordSet
747
     */
748
    public function getGroups()
749
    {
750
        $sql = 'SELECT groname FROM pg_group ORDER BY groname';
751
752
        return $this->selectSet($sql);
753
    }
754
755
    /**
756
     * Creates a new group.
757
     *
758
     * @param string $groname The name of the group
759
     * @param array  $users   An array of users to add to the group
760
     *
761
     * @return int|\PHPPgAdmin\ADORecordSet
762
     */
763
    public function createGroup($groname, $users)
764
    {
765
        $this->fieldClean($groname);
766
767
        $sql = "CREATE GROUP \"{$groname}\"";
768
769
        if (\is_array($users) && 0 < \count($users)) {
770
            $this->fieldArrayClean($users);
771
            $sql .= ' WITH USER "' . \implode('", "', $users) . '"';
772
        }
773
774
        return $this->execute($sql);
775
    }
776
777
    /**
778
     * Removes a group.
779
     *
780
     * @param string $groname The name of the group to drop
781
     *
782
     * @return int|\PHPPgAdmin\ADORecordSet
783
     */
784
    public function dropGroup($groname)
785
    {
786
        $this->fieldClean($groname);
787
788
        $sql = "DROP GROUP \"{$groname}\"";
789
790
        return $this->execute($sql);
791
    }
792
793
    abstract public function fieldClean(&$str);
794
795
    abstract public function beginTransaction();
796
797
    abstract public function rollbackTransaction();
798
799
    abstract public function endTransaction();
800
801
    abstract public function execute($sql);
802
803
    abstract public function setComment($obj_type, $obj_name, $table, $comment, $basetype = null);
804
805
    abstract public function selectSet($sql);
806
807
    abstract public function clean(&$str);
808
809
    abstract public function hasGrantOption();
810
811
    abstract public function getFunction($function_oid);
812
813
    abstract public function fieldArrayClean(&$arr);
814
815
    private function _dealWithOldParentRoles($original_parent_roles, $new_roles_to_add, $rolename)
816
    {
817
        $old = \explode(',', $original_parent_roles);
818
819
        // Grant the roles of the old role owners to the new owner
820
        foreach ($new_roles_to_add as $m) {
821
            if (!\in_array($m, $old, true)) {
822
                $status = $this->grantRole($m, $rolename);
823
824
                if (0 !== $status) {
825
                    return -1;
826
                }
827
            }
828
        }
829
830
        // Revoke the new role to the old members if they don't have the requested role name
831
832
        foreach ($old as $o) {
833
            if (!\in_array($o, $new_roles_to_add, true)) {
834
                $status = $this->revokeRole($o, $rolename, 0, 'CASCADE');
835
836
                if (0 !== $status) {
837
                    return -1;
838
                }
839
            }
840
        }
841
842
        return 0;
843
    }
844
845
    private function _dealWithOriginalMembers($original_members, $new_members_of_role, $rolename)
846
    {
847
        //members
848
        $old = \explode(',', $original_members);
849
850
        foreach ($new_members_of_role as $m) {
851
            if (!\in_array($m, $old, true)) {
852
                $status = $this->grantRole($rolename, $m);
853
854
                if (0 !== $status) {
855
                    return -1;
856
                }
857
            }
858
        }
859
860
        if ($original_members) {
861
            foreach ($old as $o) {
862
                if (!\in_array($o, $new_members_of_role, true)) {
863
                    $status = $this->revokeRole($rolename, $o, 0, 'CASCADE');
864
865
                    if (0 !== $status) {
866
                        return -1;
867
                    }
868
                }
869
            }
870
        }
871
872
        return 0;
873
    }
874
875
    private function _dealWithOriginalAdmins($original_admins, $new_admins_of_role, $rolename)
876
    {
877
        $old = \explode(',', $original_admins);
878
879
        foreach ($new_admins_of_role as $m) {
880
            if (!\in_array($m, $old, true)) {
881
                $status = $this->grantRole($rolename, $m, 1);
882
883
                if (0 !== $status) {
884
                    return -1;
885
                }
886
            }
887
        }
888
889
        foreach ($old as $o) {
890
            if (!\in_array($o, $new_admins_of_role, true)) {
891
                $status = $this->revokeRole($rolename, $o, 1, 'CASCADE');
892
893
                if (0 !== $status) {
894
                    return -1;
895
                }
896
            }
897
        }
898
899
        return 0;
900
    }
901
902
    private function _alterRole($rolename, $password, $connlimit, $expiry, $superuser, $createdb, $createrole, $inherits, $login)
903
    {
904
        $enc = $this->_encryptPassword($rolename, $password);
905
        $this->clean($enc);
906
        $this->clean($connlimit);
907
        $this->clean($expiry);
908
909
        $sql = "ALTER ROLE \"{$rolename}\"";
910
911
        if ('' !== $password) {
912
            $sql .= " WITH ENCRYPTED PASSWORD '{$enc}'";
913
        }
914
915
        $sql .= $superuser ? ' SUPERUSER' : ' NOSUPERUSER';
916
        $sql .= $createdb ? ' CREATEDB' : ' NOCREATEDB';
917
        $sql .= $createrole ? ' CREATEROLE' : ' NOCREATEROLE';
918
        $sql .= $inherits ? ' INHERIT' : ' NOINHERIT';
919
        $sql .= $login ? ' LOGIN' : ' NOLOGIN';
920
921
        if ('' !== $connlimit) {
922
            $sql .= " CONNECTION LIMIT {$connlimit}";
923
        } else {
924
            $sql .= ' CONNECTION LIMIT -1';
925
        }
926
927
        if ('' !== $expiry) {
928
            $sql .= " VALID UNTIL '{$expiry}'";
929
        } else {
930
            $sql .= " VALID UNTIL 'infinity'";
931
        }
932
933
        return $this->execute($sql);
934
    }
935
}
936