Passed
Push — master ( 5397c5...a7725b )
by Felipe
05:40
created

RoleTrait::_alterRole()   F

Complexity

Conditions 9
Paths 256

Size

Total Lines 30
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 9
eloc 21
nc 256
nop 9
dl 0
loc 30
rs 3
c 0
b 0
f 0

How to fix   Many Parameters   

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