Test Failed
Push — master ( 34dd7c...325a03 )
by Felipe
11:17 queued 06:14
created

RoleTrait::getMembers()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 12
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 12
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 5
nc 1
nop 2
1
<?php
2
3
/**
4
 * PHPPgAdmin v6.0.0-beta.43
5
 */
6
7
namespace PHPPgAdmin\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 \PHPPgAdmin\ADORecordSet Either one or All roles
20
     */
21
    public function getRoles($rolename = '')
22
    {
23
        $sql = '
24
			SELECT rolname, rolsuper, rolcreatedb, rolcreaterole, rolinherit,
25
				rolcanlogin, rolconnlimit, rolvaliduntil, rolconfig
26
			FROM pg_catalog.pg_roles';
27
        if ($rolename) {
28
            $sql .= " WHERE rolname!='{$rolename}'";
29
        }
30
31
        $sql .= ' ORDER BY rolname';
32
33
        return $this->selectSet($sql);
34
    }
35
36
    /**
37
     * Returns information about a single role.
38
     *
39
     * @param string $rolename The name of the role to retrieve
40
     *
41
     * @return \PHPPgAdmin\ADORecordSet The role's data
42
     */
43
    public function getRole($rolename)
44
    {
45
        $this->clean($rolename);
46
47
        $sql = "
48
			SELECT rolname, rolsuper, rolcreatedb, rolcreaterole, rolinherit,
49
				rolcanlogin, rolconnlimit, rolvaliduntil, rolconfig
50
			FROM pg_catalog.pg_roles WHERE rolname='{$rolename}'";
51
52
        return $this->selectSet($sql);
53
    }
54
55
    /**
56
     * Returns all users in the database cluster.
57
     *
58
     * @return \PHPPgAdmin\ADORecordSet All users
59
     */
60
    public function getUsers()
61
    {
62
        $sql = 'SELECT usename, usesuper, usecreatedb, valuntil AS useexpires, useconfig
63
			FROM pg_user
64
			ORDER BY usename';
65
66
        return $this->selectSet($sql);
67
    }
68
69
    /**
70
     * Returns information about a single user.
71
     *
72
     * @param string $username The username of the user to retrieve
73
     *
74
     * @return \PHPPgAdmin\ADORecordSet The user's data
75
     */
76
    public function getUser($username)
77
    {
78
        $this->clean($username);
79
80
        $sql = "SELECT usename, usesuper, usecreatedb, valuntil AS useexpires, useconfig
81
			FROM pg_user
82
			WHERE usename='{$username}'";
83
84
        return $this->selectSet($sql);
85
    }
86
87
    /**
88
     * Creates a new role.
89
     *
90
     * @param string $rolename     The name of the role to create
91
     * @param string $password     A password for the role
92
     * @param bool   $superuser    Boolean whether or not the role is a superuser
93
     * @param bool   $createdb     Boolean whether or not the role can create databases
94
     * @param bool   $createrole   Boolean whether or not the role can create other roles
95
     * @param bool   $inherits     Boolean whether or not the role inherits the privileges from parent roles
96
     * @param bool   $login        Boolean whether or not the role will be allowed to login
97
     * @param number $connlimit    Number of concurrent connections the role can make
98
     * @param string $expiry       String Format 'YYYY-MM-DD HH:MM:SS'.  '' means never expire
99
     * @param array  $memberof     (array) Roles to which the new role will be immediately added as a new member
100
     * @param array  $members      (array) Roles which are automatically added as members of the new role
101
     * @param array  $adminmembers (array) Roles which are automatically added as admin members of the new role
102
     *
103
     * @return int 0 if operation was successful
104
     */
105
    public function createRole(
106
        $rolename,
107
        $password,
108
        $superuser,
109
        $createdb,
110
        $createrole,
111
        $inherits,
112
        $login,
113
        $connlimit,
114
        $expiry,
115
        $memberof,
116
        $members,
117
        $adminmembers
118
    ) {
119
        $enc = $this->_encryptPassword($rolename, $password);
120
        $this->fieldClean($rolename);
121
        $this->clean($enc);
122
        $this->clean($connlimit);
123
        $this->clean($expiry);
124
        $this->fieldArrayClean($memberof);
0 ignored issues
show
Bug introduced by
It seems like fieldArrayClean() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

124
        $this->/** @scrutinizer ignore-call */ 
125
               fieldArrayClean($memberof);
Loading history...
125
        $this->fieldArrayClean($members);
126
        $this->fieldArrayClean($adminmembers);
127
128
        $sql = "CREATE ROLE \"{$rolename}\"";
129
        if ($password != '') {
130
            $sql .= " WITH ENCRYPTED PASSWORD '{$enc}'";
131
        }
132
133
        $sql .= $superuser ? ' SUPERUSER' : ' NOSUPERUSER';
134
        $sql .= $createdb ? ' CREATEDB' : ' NOCREATEDB';
135
        $sql .= $createrole ? ' CREATEROLE' : ' NOCREATEROLE';
136
        $sql .= $inherits ? ' INHERIT' : ' NOINHERIT';
137
        $sql .= $login ? ' LOGIN' : ' NOLOGIN';
138
        if ($connlimit != '') {
139
            $sql .= " CONNECTION LIMIT {$connlimit}";
140
        } else {
141
            $sql .= ' CONNECTION LIMIT -1';
142
        }
143
144
        if ($expiry != '') {
145
            $sql .= " VALID UNTIL '{$expiry}'";
146
        } else {
147
            $sql .= " VALID UNTIL 'infinity'";
148
        }
149
150
        if (is_array($memberof) && sizeof($memberof) > 0) {
151
            $sql .= ' IN ROLE "' . join('", "', $memberof) . '"';
152
        }
153
154
        if (is_array($members) && sizeof($members) > 0) {
155
            $sql .= ' ROLE "' . join('", "', $members) . '"';
156
        }
157
158
        if (is_array($adminmembers) && sizeof($adminmembers) > 0) {
159
            $sql .= ' ADMIN "' . join('", "', $adminmembers) . '"';
160
        }
161
162
        return $this->execute($sql);
163
    }
164
165
    /**
166
     * Helper function that computes encypted PostgreSQL passwords.
167
     *
168
     * @param string $username The username
169
     * @param string $password The password
170
     *
171
     * @return string
172
     */
173
    public function _encryptPassword($username, $password)
1 ignored issue
show
Coding Style introduced by
Public method name "RoleTrait::_encryptPassword" must not be prefixed with an underscore
Loading history...
174
    {
175
        return 'md5' . md5($password . $username);
176
    }
177
178
    /**
179
     * Adjusts a role's info and renames it.
180
     *
181
     * @param string $rolename        The name of the role to adjust
182
     * @param string $password        A password for the role
183
     * @param bool   $superuser       Boolean whether or not the role is a superuser
184
     * @param bool   $createdb        Boolean whether or not the role can create databases
185
     * @param bool   $createrole      Boolean whether or not the role can create other roles
186
     * @param bool   $inherits        Boolean whether or not the role inherits the privileges from parent roles
187
     * @param bool   $login           Boolean whether or not the role will be allowed to login
188
     * @param number $connlimit       Number of concurrent connections the role can make
189
     * @param string $expiry          string Format 'YYYY-MM-DD HH:MM:SS'.  '' means never expire
190
     * @param array  $memberof        (array) Roles to which the role will be immediately added as a new member
191
     * @param array  $members         (array) Roles which are automatically added as members of the role
192
     * @param array  $adminmembers    (array) Roles which are automatically added as admin members of the role
193
     * @param array  $memberofold     (array) Original roles whose the role belongs to
194
     * @param array  $membersold      (array) Original roles that are members of the role
195
     * @param array  $adminmembersold (array) Original roles that are admin members of the role
196
     * @param string $newrolename     The new name of the role
197
     *
198
     * @return bool|int 0 success
199
     */
200
    public function setRenameRole(
201
        $rolename,
202
        $password,
203
        $superuser,
204
        $createdb,
205
        $createrole,
206
        $inherits,
207
        $login,
208
        $connlimit,
209
        $expiry,
210
        $memberof,
211
        $members,
212
        $adminmembers,
213
        $memberofold,
214
        $membersold,
215
        $adminmembersold,
216
        $newrolename
217
    ) {
218
        $status = $this->beginTransaction();
219
        if ($status != 0) {
220
            return -1;
221
        }
222
223
        if ($rolename != $newrolename) {
224
            $status = $this->renameRole($rolename, $newrolename);
225
            if ($status != 0) {
226
                $this->rollbackTransaction();
227
228
                return -3;
229
            }
230
            $rolename = $newrolename;
231
        }
232
233
        $status =
0 ignored issues
show
Coding Style introduced by
Multi-line assignments must have the equal sign on the second line
Loading history...
234
        $this->setRole(
235
            $rolename,
236
            $password,
237
            $superuser,
238
            $createdb,
239
            $createrole,
240
            $inherits,
241
            $login,
242
            $connlimit,
243
            $expiry,
244
            $memberof,
245
            $members,
246
            $adminmembers,
247
            $memberofold,
0 ignored issues
show
Bug introduced by
$memberofold of type array is incompatible with the type string expected by parameter $memberofold of PHPPgAdmin\Traits\RoleTrait::setRole(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

247
            /** @scrutinizer ignore-type */ $memberofold,
Loading history...
248
            $membersold,
0 ignored issues
show
Bug introduced by
$membersold of type array is incompatible with the type string expected by parameter $membersold of PHPPgAdmin\Traits\RoleTrait::setRole(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

248
            /** @scrutinizer ignore-type */ $membersold,
Loading history...
249
            $adminmembersold
0 ignored issues
show
Bug introduced by
$adminmembersold of type array is incompatible with the type string expected by parameter $adminmembersold of PHPPgAdmin\Traits\RoleTrait::setRole(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

249
            /** @scrutinizer ignore-type */ $adminmembersold
Loading history...
250
        );
251
        if ($status != 0) {
252
            $this->rollbackTransaction();
253
254
            return -2;
255
        }
256
257
        return $this->endTransaction();
258
    }
259
260
    /**
261
     * Renames a role.
262
     *
263
     * @param string $rolename    The name of the role to rename
264
     * @param string $newrolename The new name of the role
265
     *
266
     * @return int 0 if operation was successful
267
     */
268
    public function renameRole($rolename, $newrolename)
269
    {
270
        $this->fieldClean($rolename);
271
        $this->fieldClean($newrolename);
272
273
        $sql = "ALTER ROLE \"{$rolename}\" RENAME TO \"{$newrolename}\"";
274
275
        return $this->execute($sql);
276
    }
277
278
    /**
279
     * Adjusts a role's info.
280
     *
281
     * @param string $rolename        The name of the role to adjust
282
     * @param string $password        A password for the role
283
     * @param bool   $superuser       Boolean whether or not the role is a superuser
284
     * @param bool   $createdb        Boolean whether or not the role can create databases
285
     * @param bool   $createrole      Boolean whether or not the role can create other roles
286
     * @param bool   $inherits        Boolean whether or not the role inherits the privileges from parent roles
287
     * @param bool   $login           Boolean whether or not the role will be allowed to login
288
     * @param number $connlimit       Number of concurrent connections the role can make
289
     * @param string $expiry          string Format 'YYYY-MM-DD HH:MM:SS'.  '' means never expire
290
     * @param array  $memberof        (array) Roles to which the role will be immediately added as a new member
291
     * @param array  $members         (array) Roles which are automatically added as members of the role
292
     * @param array  $adminmembers    (array) Roles which are automatically added as admin members of the role
293
     * @param string $memberofold     (array) Original roles whose the role belongs to
294
     * @param string $membersold      (array) Original roles that are members of the role
295
     * @param string $adminmembersold (array) Original roles that are admin members of the role
296
     *
297
     * @return int 0 if operation was successful
298
     */
299
    public function setRole(
300
        $rolename,
301
        $password,
302
        $superuser,
303
        $createdb,
304
        $createrole,
305
        $inherits,
306
        $login,
307
        $connlimit,
308
        $expiry,
309
        $memberof,
310
        $members,
311
        $adminmembers,
312
        $memberofold,
313
        $membersold,
314
        $adminmembersold
315
    ) {
316
        $enc = $this->_encryptPassword($rolename, $password);
317
        $this->fieldClean($rolename);
318
        $this->clean($enc);
319
        $this->clean($connlimit);
320
        $this->clean($expiry);
321
        $this->fieldArrayClean($memberof);
322
        $this->fieldArrayClean($members);
323
        $this->fieldArrayClean($adminmembers);
324
325
        $sql = "ALTER ROLE \"{$rolename}\"";
326
        if ($password != '') {
327
            $sql .= " WITH ENCRYPTED PASSWORD '{$enc}'";
328
        }
329
330
        $sql .= $superuser ? ' SUPERUSER' : ' NOSUPERUSER';
331
        $sql .= $createdb ? ' CREATEDB' : ' NOCREATEDB';
332
        $sql .= $createrole ? ' CREATEROLE' : ' NOCREATEROLE';
333
        $sql .= $inherits ? ' INHERIT' : ' NOINHERIT';
334
        $sql .= $login ? ' LOGIN' : ' NOLOGIN';
335
        if ($connlimit != '') {
336
            $sql .= " CONNECTION LIMIT {$connlimit}";
337
        } else {
338
            $sql .= ' CONNECTION LIMIT -1';
339
        }
340
341
        if ($expiry != '') {
342
            $sql .= " VALID UNTIL '{$expiry}'";
343
        } else {
344
            $sql .= " VALID UNTIL 'infinity'";
345
        }
346
347
        $status = $this->execute($sql);
348
349
        if ($status != 0) {
350
            return -1;
351
        }
352
353
        //memberof
354
        $old = explode(',', $memberofold);
355
        foreach ($memberof as $m) {
356
            if (!in_array($m, $old, true)) {
357
                $status = $this->grantRole($m, $rolename);
358
                if ($status != 0) {
359
                    return -1;
360
                }
361
            }
362
        }
363
        if ($memberofold) {
364
            foreach ($old as $o) {
365
                if (!in_array($o, $memberof, true)) {
366
                    $status = $this->revokeRole($o, $rolename, 0, 'CASCADE');
367
                    if ($status != 0) {
368
                        return -1;
369
                    }
370
                }
371
            }
372
        }
373
374
        //members
375
        $old = explode(',', $membersold);
376
        foreach ($members as $m) {
377
            if (!in_array($m, $old, true)) {
378
                $status = $this->grantRole($rolename, $m);
379
                if ($status != 0) {
380
                    return -1;
381
                }
382
            }
383
        }
384
        if ($membersold) {
385
            foreach ($old as $o) {
386
                if (!in_array($o, $members, true)) {
387
                    $status = $this->revokeRole($rolename, $o, 0, 'CASCADE');
388
                    if ($status != 0) {
389
                        return -1;
390
                    }
391
                }
392
            }
393
        }
394
395
        //adminmembers
396
        $old = explode(',', $adminmembersold);
397
        foreach ($adminmembers as $m) {
398
            if (!in_array($m, $old, true)) {
399
                $status = $this->grantRole($rolename, $m, 1);
400
                if ($status != 0) {
401
                    return -1;
402
                }
403
            }
404
        }
405
        if ($adminmembersold) {
406
            foreach ($old as $o) {
407
                if (!in_array($o, $adminmembers, true)) {
408
                    $status = $this->revokeRole($rolename, $o, 1, 'CASCADE');
409
                    if ($status != 0) {
410
                        return -1;
411
                    }
412
                }
413
            }
414
        }
415
416
        return $status;
417
    }
418
419
    /**
420
     * Grants membership in a role.
421
     *
422
     * @param string $role     The name of the target role
423
     * @param string $rolename The name of the role that will belong to the target role
424
     * @param int    $admin    (optional) Flag to grant the admin option
425
     *
426
     * @return int 0 if operation was successful
427
     */
428
    public function grantRole($role, $rolename, $admin = 0)
429
    {
430
        $this->fieldClean($role);
431
        $this->fieldClean($rolename);
432
433
        $sql = "GRANT \"{$role}\" TO \"{$rolename}\"";
434
        if ($admin == 1) {
435
            $sql .= ' WITH ADMIN OPTION';
436
        }
437
438
        return $this->execute($sql);
439
    }
440
441
    /**
442
     * Revokes membership in a role.
443
     *
444
     * @param string $role     The name of the target role
445
     * @param string $rolename The name of the role that will not belong to the target role
446
     * @param int    $admin    (optional) Flag to revoke only the admin option
447
     * @param string $type     (optional) Type of revoke: RESTRICT | CASCADE
448
     *
449
     * @return int 0 if operation was successful
450
     */
451
    public function revokeRole($role, $rolename, $admin = 0, $type = 'RESTRICT')
452
    {
453
        $this->fieldClean($role);
454
        $this->fieldClean($rolename);
455
456
        $sql = 'REVOKE ';
457
        if ($admin == 1) {
458
            $sql .= 'ADMIN OPTION FOR ';
459
        }
460
461
        $sql .= "\"{$role}\" FROM \"{$rolename}\" {$type}";
462
463
        return $this->execute($sql);
464
    }
465
466
    /**
467
     * Removes a role.
468
     *
469
     * @param string $rolename The name of the role to drop
470
     *
471
     * @return int 0 if operation was successful
472
     */
473
    public function dropRole($rolename)
474
    {
475
        $this->fieldClean($rolename);
476
477
        $sql = "DROP ROLE \"{$rolename}\"";
478
479
        return $this->execute($sql);
480
    }
481
482
    /**
483
     * Creates a new user.
484
     *
485
     * @param string $username   The username of the user to create
486
     * @param string $password   A password for the user
487
     * @param bool   $createdb   boolean Whether or not the user can create databases
488
     * @param bool   $createuser boolean Whether or not the user can create other users
489
     * @param string $expiry     string Format 'YYYY-MM-DD HH:MM:SS'.  '' means never expire
490
     * @param array  $groups     The groups to create the user in
491
     *
492
     * @return int 0 if operation was successful
493
     *
494
     * @internal param $group (array) The groups to create the user in
495
     */
496
    public function createUser($username, $password, $createdb, $createuser, $expiry, $groups)
497
    {
498
        $enc = $this->_encryptPassword($username, $password);
499
        $this->fieldClean($username);
500
        $this->clean($enc);
501
        $this->clean($expiry);
502
        $this->fieldArrayClean($groups);
503
504
        $sql = "CREATE USER \"{$username}\"";
505
        if ($password != '') {
506
            $sql .= " WITH ENCRYPTED PASSWORD '{$enc}'";
507
        }
508
509
        $sql .= $createdb ? ' CREATEDB' : ' NOCREATEDB';
510
        $sql .= $createuser ? ' CREATEUSER' : ' NOCREATEUSER';
511
        if (is_array($groups) && sizeof($groups) > 0) {
512
            $sql .= ' IN GROUP "' . join('", "', $groups) . '"';
513
        }
514
515
        if ($expiry != '') {
516
            $sql .= " VALID UNTIL '{$expiry}'";
517
        } else {
518
            $sql .= " VALID UNTIL 'infinity'";
519
        }
520
521
        return $this->execute($sql);
522
    }
523
524
    /**
525
     * Adjusts a user's info and renames the user.
526
     *
527
     * @param string $username   The username of the user to modify
528
     * @param string $password   A new password for the user
529
     * @param bool   $createdb   boolean Whether or not the user can create databases
530
     * @param bool   $createuser boolean Whether or not the user can create other users
531
     * @param string $expiry     string Format 'YYYY-MM-DD HH:MM:SS'.  '' means never expire.
532
     * @param string $newname    The new name of the user
533
     *
534
     * @return bool|int 0 success
535
     */
536
    public function setRenameUser($username, $password, $createdb, $createuser, $expiry, $newname)
537
    {
538
        $status = $this->beginTransaction();
539
        if ($status != 0) {
540
            return -1;
541
        }
542
543
        if ($username != $newname) {
544
            $status = $this->renameUser($username, $newname);
545
            if ($status != 0) {
546
                $this->rollbackTransaction();
547
548
                return -3;
549
            }
550
            $username = $newname;
551
        }
552
553
        $status = $this->setUser($username, $password, $createdb, $createuser, $expiry);
554
        if ($status != 0) {
555
            $this->rollbackTransaction();
556
557
            return -2;
558
        }
559
560
        return $this->endTransaction();
561
    }
562
563
    /**
564
     * Renames a user.
565
     *
566
     * @param string $username The username of the user to rename
567
     * @param string $newname  The new name of the user
568
     *
569
     * @return int 0 if operation was successful
570
     */
571
    public function renameUser($username, $newname)
572
    {
573
        $this->fieldClean($username);
574
        $this->fieldClean($newname);
575
576
        $sql = "ALTER USER \"{$username}\" RENAME TO \"{$newname}\"";
577
578
        return $this->execute($sql);
579
    }
580
581
    // Tablespace functions
582
583
    /**
584
     * Adjusts a user's info.
585
     *
586
     * @param string $username   The username of the user to modify
587
     * @param string $password   A new password for the user
588
     * @param bool   $createdb   boolean Whether or not the user can create databases
589
     * @param bool   $createuser boolean Whether or not the user can create other users
590
     * @param string $expiry     string Format 'YYYY-MM-DD HH:MM:SS'.  '' means never expire.
591
     *
592
     * @return int 0 if operation was successful
593
     */
594
    public function setUser($username, $password, $createdb, $createuser, $expiry)
595
    {
596
        $enc = $this->_encryptPassword($username, $password);
597
        $this->fieldClean($username);
598
        $this->clean($enc);
599
        $this->clean($expiry);
600
601
        $sql = "ALTER USER \"{$username}\"";
602
        if ($password != '') {
603
            $sql .= " WITH ENCRYPTED PASSWORD '{$enc}'";
604
        }
605
606
        $sql .= $createdb ? ' CREATEDB' : ' NOCREATEDB';
607
        $sql .= $createuser ? ' CREATEUSER' : ' NOCREATEUSER';
608
        if ($expiry != '') {
609
            $sql .= " VALID UNTIL '{$expiry}'";
610
        } else {
611
            $sql .= " VALID UNTIL 'infinity'";
612
        }
613
614
        return $this->execute($sql);
615
    }
616
617
    /**
618
     * Removes a user.
619
     *
620
     * @param string $username The username of the user to drop
621
     *
622
     * @return int 0 if operation was successful
623
     */
624
    public function dropUser($username)
625
    {
626
        $this->fieldClean($username);
627
628
        $sql = "DROP USER \"{$username}\"";
629
630
        return $this->execute($sql);
631
    }
632
633
    /**
634
     * Changes a role's password.
635
     *
636
     * @param string $rolename The role name
637
     * @param string $password The new password
638
     *
639
     * @return int 0 if operation was successful
640
     */
641
    public function changePassword($rolename, $password)
642
    {
643
        $enc = $this->_encryptPassword($rolename, $password);
644
        $this->fieldClean($rolename);
645
        $this->clean($enc);
646
647
        $sql = "ALTER ROLE \"{$rolename}\" WITH ENCRYPTED PASSWORD '{$enc}'";
648
649
        return $this->execute($sql);
650
    }
651
652
    /**
653
     * Adds a group member.
654
     *
655
     * @param string $groname The name of the group
656
     * @param string $user    The name of the user to add to the group
657
     *
658
     * @return int 0 if operation was successful
659
     */
660
    public function addGroupMember($groname, $user)
661
    {
662
        $this->fieldClean($groname);
663
        $this->fieldClean($user);
664
665
        $sql = "ALTER GROUP \"{$groname}\" ADD USER \"{$user}\"";
666
667
        return $this->execute($sql);
668
    }
669
670
    /**
671
     * Returns all role names which the role belongs to.
672
     *
673
     * @param string $rolename The role name
674
     *
675
     * @return \PHPPgAdmin\ADORecordSet All role names
676
     */
677
    public function getMemberOf($rolename)
678
    {
679
        $this->clean($rolename);
680
681
        $sql = "
682
			SELECT rolname FROM pg_catalog.pg_roles R, pg_auth_members M
683
			WHERE R.oid=M.roleid
684
				AND member IN (
685
					SELECT oid FROM pg_catalog.pg_roles
686
					WHERE rolname='{$rolename}')
687
			ORDER BY rolname";
688
689
        return $this->selectSet($sql);
690
    }
691
692
    // Administration functions
693
694
    /**
695
     * Returns all role names that are members of a role.
696
     *
697
     * @param string $rolename The role name
698
     * @param string $admin    (optional) Find only admin members
699
     *
700
     * @return \PHPPgAdmin\ADORecordSet All role names
701
     */
702
    public function getMembers($rolename, $admin = 'f')
703
    {
704
        $this->clean($rolename);
705
706
        $sql = "
707
			SELECT rolname FROM pg_catalog.pg_roles R, pg_auth_members M
708
			WHERE R.oid=M.member AND admin_option='{$admin}'
709
				AND roleid IN (SELECT oid FROM pg_catalog.pg_roles
710
					WHERE rolname='{$rolename}')
711
			ORDER BY rolname";
712
713
        return $this->selectSet($sql);
714
    }
715
716
    /**
717
     * Removes a group member.
718
     *
719
     * @param string $groname The name of the group
720
     * @param string $user    The name of the user to remove from the group
721
     *
722
     * @return int 0 if operation was successful
723
     */
724
    public function dropGroupMember($groname, $user)
725
    {
726
        $this->fieldClean($groname);
727
        $this->fieldClean($user);
728
729
        $sql = "ALTER GROUP \"{$groname}\" DROP USER \"{$user}\"";
730
731
        return $this->execute($sql);
732
    }
733
734
    /**
735
     * Return users in a specific group.
736
     *
737
     * @param string $groname The name of the group
738
     *
739
     * @return \PHPPgAdmin\ADORecordSet All users in the group
740
     */
741
    public function getGroup($groname)
742
    {
743
        $this->clean($groname);
744
745
        $sql = "
746
			SELECT s.usename FROM pg_catalog.pg_user s, pg_catalog.pg_group g
747
			WHERE g.groname='{$groname}' AND s.usesysid = ANY (g.grolist)
748
			ORDER BY s.usename";
749
750
        return $this->selectSet($sql);
751
    }
752
753
    /**
754
     * Returns all groups in the database cluser.
755
     *
756
     * @return \PHPPgAdmin\ADORecordSet All groups
757
     */
758
    public function getGroups()
759
    {
760
        $sql = 'SELECT groname FROM pg_group ORDER BY groname';
761
762
        return $this->selectSet($sql);
763
    }
764
765
    /**
766
     * Creates a new group.
767
     *
768
     * @param string $groname The name of the group
769
     * @param array  $users   An array of users to add to the group
770
     *
771
     * @return int 0 if operation was successful
772
     */
773
    public function createGroup($groname, $users)
774
    {
775
        $this->fieldClean($groname);
776
777
        $sql = "CREATE GROUP \"{$groname}\"";
778
779
        if (is_array($users) && sizeof($users) > 0) {
780
            $this->fieldArrayClean($users);
781
            $sql .= ' WITH USER "' . join('", "', $users) . '"';
782
        }
783
784
        return $this->execute($sql);
785
    }
786
787
    /**
788
     * Removes a group.
789
     *
790
     * @param string $groname The name of the group to drop
791
     *
792
     * @return int 0 if operation was successful
793
     */
794
    public function dropGroup($groname)
795
    {
796
        $this->fieldClean($groname);
797
798
        $sql = "DROP GROUP \"{$groname}\"";
799
800
        return $this->execute($sql);
801
    }
802
803
    /**
804
     * Grants a privilege to a user, group or public.
805
     *
806
     * @param string $mode        'GRANT' or 'REVOKE';
807
     * @param mixed  $type        The type of object
808
     * @param string $object      The name of the object
809
     * @param bool   $public      True to grant to public, false otherwise
810
     * @param mixed  $usernames   the array of usernames to grant privs to
811
     * @param mixed  $groupnames  the array of group names to grant privs to
812
     * @param mixed  $privileges  The array of privileges to grant (eg. ('SELECT', 'ALL PRIVILEGES', etc.) )
813
     * @param bool   $grantoption True if has grant option, false otherwise
814
     * @param bool   $cascade     True for cascade revoke, false otherwise
815
     * @param string $table       the column's table if type=column
816
     *
817
     * @return int 0 if operation was successful
818
     */
819
    public function setPrivileges(
820
        $mode,
821
        $type,
822
        $object,
823
        $public,
824
        $usernames,
825
        $groupnames,
826
        $privileges,
827
        $grantoption,
828
        $cascade,
829
        $table
830
    ) {
831
        $f_schema = $this->_schema;
832
        $this->fieldClean($f_schema);
833
        $this->fieldArrayClean($usernames);
834
        $this->fieldArrayClean($groupnames);
835
836
        // Input checking
837
        if (!is_array($privileges) || sizeof($privileges) == 0) {
838
            return -3;
839
        }
840
841
        if (!is_array($usernames) || !is_array($groupnames) ||
842
            (!$public && sizeof($usernames) == 0 && sizeof($groupnames) == 0)) {
1 ignored issue
show
Coding Style introduced by
Closing parenthesis of a multi-line IF statement must be on a new line
Loading history...
843
            return -4;
844
        }
845
846
        if ($mode != 'GRANT' && $mode != 'REVOKE') {
847
            return -5;
848
        }
849
850
        $sql = $mode;
851
852
        // Grant option
853
        if ($this->hasGrantOption() && $mode == 'REVOKE' && $grantoption) {
854
            $sql .= ' GRANT OPTION FOR';
855
        }
856
857
        if (in_array('ALL PRIVILEGES', $privileges, true)) {
858
            $sql .= ' ALL PRIVILEGES';
859
        } else {
860
            if ($type == 'column') {
861
                $this->fieldClean($object);
862
                $sql .= ' ' . join(" (\"{$object}\"), ", $privileges);
863
            } else {
864
                $sql .= ' ' . join(', ', $privileges);
865
            }
866
        }
867
868
        switch ($type) {
869
            case 'column':
870
                $sql .= " (\"{$object}\")";
871
                $object = $table;
872
            // no break
873
            case 'table':
874
            case 'view':
875
            case 'sequence':
876
                $this->fieldClean($object);
877
                $sql .= " ON \"{$f_schema}\".\"{$object}\"";
878
879
                break;
880
            case 'database':
881
                $this->fieldClean($object);
882
                $sql .= " ON DATABASE \"{$object}\"";
883
884
                break;
885
            case 'function':
886
                // Function comes in with $object as function OID
887
                $fn = $this->getFunction($object);
888
                $this->fieldClean($fn->fields['proname']);
889
                $sql .= " ON FUNCTION \"{$f_schema}\".\"{$fn->fields['proname']}\"({$fn->fields['proarguments']})";
890
891
                break;
892
            case 'language':
893
                $this->fieldClean($object);
894
                $sql .= " ON LANGUAGE \"{$object}\"";
895
896
                break;
897
            case 'schema':
898
                $this->fieldClean($object);
899
                $sql .= " ON SCHEMA \"{$object}\"";
900
901
                break;
902
            case 'tablespace':
903
                $this->fieldClean($object);
904
                $sql .= " ON TABLESPACE \"{$object}\"";
905
906
                break;
907
            default:
908
                return -1;
909
        }
910
911
        // Dump PUBLIC
912
        $first = true;
913
        $sql .= ($mode == 'GRANT') ? ' TO ' : ' FROM ';
914
        if ($public) {
915
            $sql .= 'PUBLIC';
916
            $first = false;
917
        }
918
        // Dump users
919
        foreach ($usernames as $v) {
920
            if ($first) {
921
                $sql .= "\"{$v}\"";
922
                $first = false;
923
            } else {
924
                $sql .= ", \"{$v}\"";
925
            }
926
        }
927
        // Dump groups
928
        foreach ($groupnames as $v) {
929
            if ($first) {
930
                $sql .= "GROUP \"{$v}\"";
931
                $first = false;
932
            } else {
933
                $sql .= ", GROUP \"{$v}\"";
934
            }
935
        }
936
937
        // Grant option
938
        if ($this->hasGrantOption() && $mode == 'GRANT' && $grantoption) {
939
            $sql .= ' WITH GRANT OPTION';
940
        }
941
942
        // Cascade revoke
943
        if ($this->hasGrantOption() && $mode == 'REVOKE' && $cascade) {
944
            $sql .= ' CASCADE';
945
        }
946
947
        return $this->execute($sql);
948
    }
949
950
    abstract public function fieldClean(&$str);
951
952
    abstract public function beginTransaction();
953
954
    abstract public function rollbackTransaction();
955
956
    abstract public function endTransaction();
957
958
    abstract public function execute($sql);
959
960
    abstract public function setComment($obj_type, $obj_name, $table, $comment, $basetype = null);
961
962
    abstract public function selectSet($sql);
963
964
    abstract public function clean(&$str);
965
966
    abstract public function hasGrantOption();
967
968
    abstract public function getFunction($function_oid);
969
}
970