Passed
Push — develop ( 7c0cd9...49abac )
by Felipe
04:38
created

RoleTrait::setRole()   F

Complexity

Conditions 16
Paths 4096

Size

Total Lines 84
Code Lines 40

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 84
rs 2
c 0
b 0
f 0
cc 16
eloc 40
nc 4096
nop 15

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