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

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

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

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

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

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

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

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

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