Passed
Push — develop ( d51928...4c214f )
by Felipe
31:34 queued 23:49
created

RoleTrait   D

Complexity

Total Complexity 101

Size/Duplication

Total Lines 857
Duplicated Lines 16.1 %

Coupling/Cohesion

Components 1
Dependencies 0

Importance

Changes 0
Metric Value
dl 138
loc 857
rs 4.4444
c 0
b 0
f 0
wmc 101
lcom 1
cbo 0

41 Methods

Rating   Name   Duplication   Size   Complexity  
A getRoles() 0 14 2
A getRole() 0 11 1
A getUsers() 0 8 1
A getUser() 0 10 1
F createRole() 0 59 15
A _encryptPassword() 0 4 1
B setRenameRole() 0 58 5
A renameRole() 0 9 1
C _dealWithOldParentRoles() 27 27 7
C _dealWithOriginalMembers() 25 25 8
C _dealWithOriginalAdmins() 23 23 7
F _alterRole() 0 31 9
B setRole() 0 54 8
A grantRole() 12 12 2
A revokeRole() 14 14 2
A dropRole() 0 8 1
C createUser() 27 27 7
B setRenameUser() 0 26 5
A renameUser() 0 9 1
B setUser() 0 22 5
A dropUser() 0 8 1
A changePassword() 10 10 1
A addGroupMember() 0 9 1
A getMemberOf() 0 14 1
A getMembers() 0 13 1
A dropGroupMember() 0 9 1
A getGroup() 0 11 1
A getGroups() 0 6 1
A createGroup() 0 13 3
A dropGroup() 0 8 1
fieldClean() 0 1 ?
beginTransaction() 0 1 ?
rollbackTransaction() 0 1 ?
endTransaction() 0 1 ?
execute() 0 1 ?
setComment() 0 1 ?
selectSet() 0 1 ?
clean() 0 1 ?
hasGrantOption() 0 1 ?
getFunction() 0 1 ?
fieldArrayClean() 0 1 ?

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like RoleTrait often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use RoleTrait, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
/**
4
 * PHPPgAdmin v6.0.0-beta.48
5
 */
6
7
namespace PHPPgAdmin\Database\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(
0 ignored issues
show
Coding Style Naming introduced by
The parameter $new_roles_to_add is not named in camelCase.

This check marks parameter names that have not been written in camelCase.

In camelCase names are written without any punctuation, the start of each new word being marked by a capital letter. Thus the name database connection string becomes databaseConnectionString.

Loading history...
Coding Style Naming introduced by
The parameter $new_members_of_role is not named in camelCase.

This check marks parameter names that have not been written in camelCase.

In camelCase names are written without any punctuation, the start of each new word being marked by a capital letter. Thus the name database connection string becomes databaseConnectionString.

Loading history...
Coding Style Naming introduced by
The parameter $new_admins_of_role is not named in camelCase.

This check marks parameter names that have not been written in camelCase.

In camelCase names are written without any punctuation, the start of each new word being marked by a capital letter. Thus the name database connection string becomes databaseConnectionString.

Loading history...
106
        $rolename,
107
        $password,
108
        $superuser,
109
        $createdb,
110
        $createrole,
111
        $inherits,
112
        $login,
113
        $connlimit,
114
        $expiry,
115
        $new_roles_to_add,
116
        $new_members_of_role,
117
        $new_admins_of_role
118
    ) {
119
        $enc = $this->_encryptPassword($rolename, $password);
120
        $this->fieldClean($rolename);
121
        $this->clean($enc);
122
        $this->clean($connlimit);
123
        $this->clean($expiry);
124
        $this->fieldArrayClean($new_roles_to_add);
125
        $this->fieldArrayClean($new_members_of_role);
126
        $this->fieldArrayClean($new_admins_of_role);
127
128
        $sql = "CREATE ROLE \"{$rolename}\"";
129
        if ($password != '') {
130
            $sql .= " WITH ENCRYPTED PASSWORD '{$enc}'";
131
        }
132
133
        $sql .= $superuser ? ' SUPERUSER' : ' NOSUPERUSER';
134
        $sql .= $createdb ? ' CREATEDB' : ' NOCREATEDB';
135
        $sql .= $createrole ? ' CREATEROLE' : ' NOCREATEROLE';
136
        $sql .= $inherits ? ' INHERIT' : ' NOINHERIT';
137
        $sql .= $login ? ' LOGIN' : ' NOLOGIN';
138
        if ($connlimit != '') {
139
            $sql .= " CONNECTION LIMIT {$connlimit}";
140
        } else {
141
            $sql .= ' CONNECTION LIMIT -1';
142
        }
143
144
        if ($expiry != '') {
145
            $sql .= " VALID UNTIL '{$expiry}'";
146
        } else {
147
            $sql .= " VALID UNTIL 'infinity'";
148
        }
149
150
        if (is_array($new_roles_to_add) && sizeof($new_roles_to_add) > 0) {
151
            $sql .= ' IN ROLE "'.join('", "', $new_roles_to_add).'"';
152
        }
153
154
        if (is_array($new_members_of_role) && sizeof($new_members_of_role) > 0) {
155
            $sql .= ' ROLE "'.join('", "', $new_members_of_role).'"';
156
        }
157
158
        if (is_array($new_admins_of_role) && sizeof($new_admins_of_role) > 0) {
159
            $sql .= ' ADMIN "'.join('", "', $new_admins_of_role).'"';
160
        }
161
162
        return $this->execute($sql);
163
    }
164
165
    /**
166
     * Helper function that computes encypted PostgreSQL passwords.
167
     *
168
     * @param string $username The username
169
     * @param string $password The password
170
     *
171
     * @return string
172
     */
173
    public function _encryptPassword($username, $password)
174
    {
175
        return 'md5'.md5($password.$username);
176
    }
177
178
    /**
179
     * Adjusts a role's info and renames it.
180
     *
181
     * @param string $rolename              The name of the role to adjust
182
     * @param string $password              A password for the role
183
     * @param bool   $superuser             Boolean whether or not the role is a superuser
184
     * @param bool   $createdb              Boolean whether or not the role can create databases
185
     * @param bool   $createrole            Boolean whether or not the role can create other roles
186
     * @param bool   $inherits              Boolean whether or not the role inherits the privileges from parent roles
187
     * @param bool   $login                 Boolean whether or not the role will be allowed to login
188
     * @param number $connlimit             Number of concurrent connections the role can make
189
     * @param string $expiry                string Format 'YYYY-MM-DD HH:MM:SS'.  '' means never expire
190
     * @param array  $new_roles_to_add      (array) Roles to which the role will be immediately added as a new member
191
     * @param array  $new_members_of_role   (array) Roles which are automatically added as members of the role
192
     * @param array  $new_admins_of_role    (array) Roles which are automatically added as admin members of the role
193
     * @param string $original_parent_roles Original roles whose the role belongs to, comma separated
194
     * @param string $original_members      Original roles that are members of the role, comma separated
195
     * @param string $original_admins       Original roles that are admin members of the role, comma separated
196
     * @param string $newrolename           The new name of the role
197
     *
198
     * @return bool|int 0 success
199
     */
200
    public function setRenameRole(
0 ignored issues
show
Coding Style Naming introduced by
The parameter $new_roles_to_add is not named in camelCase.

This check marks parameter names that have not been written in camelCase.

In camelCase names are written without any punctuation, the start of each new word being marked by a capital letter. Thus the name database connection string becomes databaseConnectionString.

Loading history...
Coding Style Naming introduced by
The parameter $new_members_of_role is not named in camelCase.

This check marks parameter names that have not been written in camelCase.

In camelCase names are written without any punctuation, the start of each new word being marked by a capital letter. Thus the name database connection string becomes databaseConnectionString.

Loading history...
Coding Style Naming introduced by
The parameter $new_admins_of_role is not named in camelCase.

This check marks parameter names that have not been written in camelCase.

In camelCase names are written without any punctuation, the start of each new word being marked by a capital letter. Thus the name database connection string becomes databaseConnectionString.

Loading history...
Coding Style Naming introduced by
The parameter $original_parent_roles is not named in camelCase.

This check marks parameter names that have not been written in camelCase.

In camelCase names are written without any punctuation, the start of each new word being marked by a capital letter. Thus the name database connection string becomes databaseConnectionString.

Loading history...
Coding Style Naming introduced by
The parameter $original_members is not named in camelCase.

This check marks parameter names that have not been written in camelCase.

In camelCase names are written without any punctuation, the start of each new word being marked by a capital letter. Thus the name database connection string becomes databaseConnectionString.

Loading history...
Coding Style Naming introduced by
The parameter $original_admins is not named in camelCase.

This check marks parameter names that have not been written in camelCase.

In camelCase names are written without any punctuation, the start of each new word being marked by a capital letter. Thus the name database connection string becomes databaseConnectionString.

Loading history...
201
        $rolename,
202
        $password,
203
        $superuser,
204
        $createdb,
205
        $createrole,
206
        $inherits,
207
        $login,
208
        $connlimit,
209
        $expiry,
210
        $new_roles_to_add,
211
        $new_members_of_role,
212
        $new_admins_of_role,
213
        $original_parent_roles,
214
        $original_members,
215
        $original_admins,
216
        $newrolename
217
    ) {
218
        $status = $this->beginTransaction();
219
        if ($status != 0) {
220
            return -1;
221
        }
222
223
        if ($rolename != $newrolename) {
224
            $status = $this->renameRole($rolename, $newrolename);
225
            if ($status != 0) {
226
                $this->rollbackTransaction();
227
228
                return -3;
229
            }
230
            $rolename = $newrolename;
231
        }
232
233
        $status = $this->setRole(
234
            $rolename,
235
            $password,
236
            $superuser,
237
            $createdb,
238
            $createrole,
239
            $inherits,
240
            $login,
241
            $connlimit,
242
            $expiry,
243
            $new_roles_to_add,
244
            $new_members_of_role,
245
            $new_admins_of_role,
246
            $original_parent_roles,
247
            $original_members,
248
            $original_admins
249
        );
250
        if ($status != 0) {
251
            $this->rollbackTransaction();
252
253
            return -2;
254
        }
255
256
        return $this->endTransaction();
257
    }
258
259
    /**
260
     * Renames a role.
261
     *
262
     * @param string $rolename    The name of the role to rename
263
     * @param string $newrolename The new name of the role
264
     *
265
     * @return int 0 if operation was successful
266
     */
267
    public function renameRole($rolename, $newrolename)
268
    {
269
        $this->fieldClean($rolename);
270
        $this->fieldClean($newrolename);
271
272
        $sql = "ALTER ROLE \"{$rolename}\" RENAME TO \"{$newrolename}\"";
273
274
        return $this->execute($sql);
275
    }
276
277 View Code Duplication
    private function _dealWithOldParentRoles($original_parent_roles, $new_roles_to_add, $rolename)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
Coding Style Naming introduced by
The parameter $original_parent_roles is not named in camelCase.

This check marks parameter names that have not been written in camelCase.

In camelCase names are written without any punctuation, the start of each new word being marked by a capital letter. Thus the name database connection string becomes databaseConnectionString.

Loading history...
Coding Style Naming introduced by
The parameter $new_roles_to_add is not named in camelCase.

This check marks parameter names that have not been written in camelCase.

In camelCase names are written without any punctuation, the start of each new word being marked by a capital letter. Thus the name database connection string becomes databaseConnectionString.

Loading history...
278
    {
279
        $old = explode(',', $original_parent_roles);
280
281
        // Grant the roles of the old role owners to the new owner
282
        foreach ($new_roles_to_add as $m) {
283
            if (!in_array($m, $old, true)) {
284
                $status = $this->grantRole($m, $rolename);
285
                if ($status != 0) {
286
                    return -1;
287
                }
288
            }
289
        }
290
291
        // Revoke the new role to the old members if they don't have the requested role name
292
293
        foreach ($old as $o) {
294
            if (!in_array($o, $new_roles_to_add, true)) {
295
                $status = $this->revokeRole($o, $rolename, 0, 'CASCADE');
296
                if ($status != 0) {
297
                    return -1;
298
                }
299
            }
300
        }
301
302
        return 0;
303
    }
304
305 View Code Duplication
    private function _dealWithOriginalMembers($original_members, $new_members_of_role, $rolename)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
Coding Style Naming introduced by
The parameter $original_members is not named in camelCase.

This check marks parameter names that have not been written in camelCase.

In camelCase names are written without any punctuation, the start of each new word being marked by a capital letter. Thus the name database connection string becomes databaseConnectionString.

Loading history...
Coding Style Naming introduced by
The parameter $new_members_of_role is not named in camelCase.

This check marks parameter names that have not been written in camelCase.

In camelCase names are written without any punctuation, the start of each new word being marked by a capital letter. Thus the name database connection string becomes databaseConnectionString.

Loading history...
306
    {
307
        //members
308
        $old = explode(',', $original_members);
309
        foreach ($new_members_of_role as $m) {
310
            if (!in_array($m, $old, true)) {
311
                $status = $this->grantRole($rolename, $m);
312
                if ($status != 0) {
313
                    return -1;
314
                }
315
            }
316
        }
317
        if ($original_members) {
318
            foreach ($old as $o) {
319
                if (!in_array($o, $new_members_of_role, true)) {
320
                    $status = $this->revokeRole($rolename, $o, 0, 'CASCADE');
321
                    if ($status != 0) {
322
                        return -1;
323
                    }
324
                }
325
            }
326
        }
327
328
        return 0;
329
    }
330
331 View Code Duplication
    private function _dealWithOriginalAdmins($original_admins, $new_admins_of_role, $rolename)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
Coding Style Naming introduced by
The parameter $original_admins is not named in camelCase.

This check marks parameter names that have not been written in camelCase.

In camelCase names are written without any punctuation, the start of each new word being marked by a capital letter. Thus the name database connection string becomes databaseConnectionString.

Loading history...
Coding Style Naming introduced by
The parameter $new_admins_of_role is not named in camelCase.

This check marks parameter names that have not been written in camelCase.

In camelCase names are written without any punctuation, the start of each new word being marked by a capital letter. Thus the name database connection string becomes databaseConnectionString.

Loading history...
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
        return 0;
353
    }
354
355
    private function _alterRole($rolename, $password, $connlimit, $expiry, $superuser, $createdb, $createrole, $inherits, $login)
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
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(
0 ignored issues
show
Coding Style Naming introduced by
The parameter $new_roles_to_add is not named in camelCase.

This check marks parameter names that have not been written in camelCase.

In camelCase names are written without any punctuation, the start of each new word being marked by a capital letter. Thus the name database connection string becomes databaseConnectionString.

Loading history...
Coding Style Naming introduced by
The parameter $new_members_of_role is not named in camelCase.

This check marks parameter names that have not been written in camelCase.

In camelCase names are written without any punctuation, the start of each new word being marked by a capital letter. Thus the name database connection string becomes databaseConnectionString.

Loading history...
Coding Style Naming introduced by
The parameter $new_admins_of_role is not named in camelCase.

This check marks parameter names that have not been written in camelCase.

In camelCase names are written without any punctuation, the start of each new word being marked by a capital letter. Thus the name database connection string becomes databaseConnectionString.

Loading history...
Coding Style Naming introduced by
The parameter $original_parent_roles is not named in camelCase.

This check marks parameter names that have not been written in camelCase.

In camelCase names are written without any punctuation, the start of each new word being marked by a capital letter. Thus the name database connection string becomes databaseConnectionString.

Loading history...
Coding Style Naming introduced by
The parameter $original_members is not named in camelCase.

This check marks parameter names that have not been written in camelCase.

In camelCase names are written without any punctuation, the start of each new word being marked by a capital letter. Thus the name database connection string becomes databaseConnectionString.

Loading history...
Coding Style Naming introduced by
The parameter $original_admins is not named in camelCase.

This check marks parameter names that have not been written in camelCase.

In camelCase names are written without any punctuation, the start of each new word being marked by a capital letter. Thus the name database connection string becomes databaseConnectionString.

Loading history...
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 View Code Duplication
    public function grantRole($role, $rolename, $admin = 0)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
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 View Code Duplication
    public function revokeRole($role, $rolename, $admin = 0, $type = 'RESTRICT')
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
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 View Code Duplication
    public function createUser($username, $password, $createdb, $createuser, $expiry, $groups)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
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 View Code Duplication
    public function changePassword($rolename, $password)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
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
    abstract public function fieldClean(&$str);
0 ignored issues
show
Documentation introduced by
For interfaces and abstract methods it is generally a good practice to add a @return annotation even if it is just @return void or @return null, so that implementors know what to do in the overridden method.

For interface and abstract methods, it is impossible to infer the return type from the immediate code. In these cases, it is generally advisible to explicitly annotate these methods with a @return doc comment to communicate to implementors of these methods what they are expected to return.

Loading history...
848
849
    abstract public function beginTransaction();
0 ignored issues
show
Documentation introduced by
For interfaces and abstract methods it is generally a good practice to add a @return annotation even if it is just @return void or @return null, so that implementors know what to do in the overridden method.

For interface and abstract methods, it is impossible to infer the return type from the immediate code. In these cases, it is generally advisible to explicitly annotate these methods with a @return doc comment to communicate to implementors of these methods what they are expected to return.

Loading history...
850
851
    abstract public function rollbackTransaction();
0 ignored issues
show
Documentation introduced by
For interfaces and abstract methods it is generally a good practice to add a @return annotation even if it is just @return void or @return null, so that implementors know what to do in the overridden method.

For interface and abstract methods, it is impossible to infer the return type from the immediate code. In these cases, it is generally advisible to explicitly annotate these methods with a @return doc comment to communicate to implementors of these methods what they are expected to return.

Loading history...
852
853
    abstract public function endTransaction();
0 ignored issues
show
Documentation introduced by
For interfaces and abstract methods it is generally a good practice to add a @return annotation even if it is just @return void or @return null, so that implementors know what to do in the overridden method.

For interface and abstract methods, it is impossible to infer the return type from the immediate code. In these cases, it is generally advisible to explicitly annotate these methods with a @return doc comment to communicate to implementors of these methods what they are expected to return.

Loading history...
854
855
    abstract public function execute($sql);
0 ignored issues
show
Documentation introduced by
For interfaces and abstract methods it is generally a good practice to add a @return annotation even if it is just @return void or @return null, so that implementors know what to do in the overridden method.

For interface and abstract methods, it is impossible to infer the return type from the immediate code. In these cases, it is generally advisible to explicitly annotate these methods with a @return doc comment to communicate to implementors of these methods what they are expected to return.

Loading history...
856
857
    abstract public function setComment($obj_type, $obj_name, $table, $comment, $basetype = null);
0 ignored issues
show
Documentation introduced by
For interfaces and abstract methods it is generally a good practice to add a @return annotation even if it is just @return void or @return null, so that implementors know what to do in the overridden method.

For interface and abstract methods, it is impossible to infer the return type from the immediate code. In these cases, it is generally advisible to explicitly annotate these methods with a @return doc comment to communicate to implementors of these methods what they are expected to return.

Loading history...
Coding Style Naming introduced by
The parameter $obj_type is not named in camelCase.

This check marks parameter names that have not been written in camelCase.

In camelCase names are written without any punctuation, the start of each new word being marked by a capital letter. Thus the name database connection string becomes databaseConnectionString.

Loading history...
Coding Style Naming introduced by
The parameter $obj_name is not named in camelCase.

This check marks parameter names that have not been written in camelCase.

In camelCase names are written without any punctuation, the start of each new word being marked by a capital letter. Thus the name database connection string becomes databaseConnectionString.

Loading history...
858
859
    abstract public function selectSet($sql);
0 ignored issues
show
Documentation introduced by
For interfaces and abstract methods it is generally a good practice to add a @return annotation even if it is just @return void or @return null, so that implementors know what to do in the overridden method.

For interface and abstract methods, it is impossible to infer the return type from the immediate code. In these cases, it is generally advisible to explicitly annotate these methods with a @return doc comment to communicate to implementors of these methods what they are expected to return.

Loading history...
860
861
    abstract public function clean(&$str);
0 ignored issues
show
Documentation introduced by
For interfaces and abstract methods it is generally a good practice to add a @return annotation even if it is just @return void or @return null, so that implementors know what to do in the overridden method.

For interface and abstract methods, it is impossible to infer the return type from the immediate code. In these cases, it is generally advisible to explicitly annotate these methods with a @return doc comment to communicate to implementors of these methods what they are expected to return.

Loading history...
862
863
    abstract public function hasGrantOption();
0 ignored issues
show
Documentation introduced by
For interfaces and abstract methods it is generally a good practice to add a @return annotation even if it is just @return void or @return null, so that implementors know what to do in the overridden method.

For interface and abstract methods, it is impossible to infer the return type from the immediate code. In these cases, it is generally advisible to explicitly annotate these methods with a @return doc comment to communicate to implementors of these methods what they are expected to return.

Loading history...
864
865
    abstract public function getFunction($function_oid);
0 ignored issues
show
Documentation introduced by
For interfaces and abstract methods it is generally a good practice to add a @return annotation even if it is just @return void or @return null, so that implementors know what to do in the overridden method.

For interface and abstract methods, it is impossible to infer the return type from the immediate code. In these cases, it is generally advisible to explicitly annotate these methods with a @return doc comment to communicate to implementors of these methods what they are expected to return.

Loading history...
Coding Style Naming introduced by
The parameter $function_oid is not named in camelCase.

This check marks parameter names that have not been written in camelCase.

In camelCase names are written without any punctuation, the start of each new word being marked by a capital letter. Thus the name database connection string becomes databaseConnectionString.

Loading history...
866
867
    abstract public function fieldArrayClean(&$arr);
0 ignored issues
show
Documentation introduced by
For interfaces and abstract methods it is generally a good practice to add a @return annotation even if it is just @return void or @return null, so that implementors know what to do in the overridden method.

For interface and abstract methods, it is impossible to infer the return type from the immediate code. In these cases, it is generally advisible to explicitly annotate these methods with a @return doc comment to communicate to implementors of these methods what they are expected to return.

Loading history...
868
}
869