Passed
Push — develop ( 2d5edd...a33225 )
by Felipe
05:40
created

RoleTrait::setPrivileges()   F

Complexity

Conditions 36
Paths 13839

Size

Total Lines 129
Code Lines 77

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 129
rs 2
c 0
b 0
f 0
cc 36
eloc 77
nc 13839
nop 10

How to fix   Long Method    Complexity    Many Parameters   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

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