Passed
Push — develop ( c6c0b1...90e9a5 )
by Felipe
10:30 queued 02:43
created

UsersController   B

Complexity

Total Complexity 52

Size/Duplication

Total Lines 472
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 52
dl 0
loc 472
rs 7.9487
c 0
b 0
f 0

9 Methods

Rating   Name   Duplication   Size   Complexity  
B doDefault() 0 86 2
C render() 0 65 14
B doAccount() 0 42 4
B doSaveCreate() 0 22 4
B doChangePassword() 0 47 5
B doSaveEdit() 0 20 6
C doEdit() 0 58 11
A doDrop() 0 23 3
B doCreate() 0 38 3

How to fix   Complexity   

Complex Class

Complex classes like UsersController 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.

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 UsersController, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
/**
4
 * PHPPgAdmin v6.0.0-beta.45
5
 */
6
7
namespace PHPPgAdmin\Controller;
8
9
use PHPPgAdmin\Decorators\Decorator;
10
11
/**
12
 * Base controller class.
13
 *
14
 * @package PHPPgAdmin
15
 */
16
class UsersController extends BaseController
17
{
18
    public $controller_title = 'strusers';
19
20
    /**
21
     * Default method to render the controller according to the action parameter.
22
     */
23
    public function render()
24
    {
25
        $this->printHeader();
26
        $this->printBody();
27
28
        switch ($this->action) {
29
            case 'changepassword':
30
                if (isset($_REQUEST['ok'])) {
31
                    $this->doChangePassword(false);
32
                } else {
33
                    $this->doAccount();
34
                }
35
36
                break;
37
            case 'confchangepassword':
38
                $this->doChangePassword(true);
39
40
                break;
41
            case 'account':
42
                $this->doAccount();
43
44
                break;
45
            case 'save_create':
46
                if (isset($_REQUEST['cancel'])) {
47
                    $this->doDefault();
48
                } else {
49
                    $this->doSaveCreate();
50
                }
51
52
                break;
53
            case 'create':
54
                $this->doCreate();
55
56
                break;
57
            case 'drop':
58
                if (isset($_REQUEST['cancel'])) {
59
                    $this->doDefault();
60
                } else {
61
                    $this->doDrop(false);
62
                }
63
64
                break;
65
            case 'confirm_drop':
66
                $this->doDrop(true);
67
68
                break;
69
            case 'save_edit':
70
                if (isset($_REQUEST['cancel'])) {
71
                    $this->doDefault();
72
                } else {
73
                    $this->doSaveEdit();
74
                }
75
76
                break;
77
            case 'edit':
78
                $this->doEdit();
79
80
                break;
81
            default:
82
                $this->doDefault();
83
84
                break;
85
        }
86
87
        $this->printFooter();
88
    }
89
90
    /**
91
     * Show default list of users in the database.
92
     *
93
     * @param mixed $msg
94
     */
95
    public function doDefault($msg = '')
96
    {
97
        $data = $this->misc->getDatabaseAccessor();
98
99
        $lang             = $this->lang;
100
        $renderUseExpires = function ($val) use ($lang) {
101
            return 'infinity' == $val ? $lang['strnever'] : htmlspecialchars($val);
102
        };
103
104
        $this->printTrail('server');
105
        $this->printTabs('server', 'users');
106
        $this->printMsg($msg);
107
108
        $users = $data->getUsers();
109
110
        $columns = [
111
            'user'      => [
112
                'title' => $this->lang['strusername'],
113
                'field' => Decorator::field('usename'),
114
            ],
115
            'superuser' => [
116
                'title' => $this->lang['strsuper'],
117
                'field' => Decorator::field('usesuper'),
118
                'type'  => 'yesno',
119
            ],
120
            'createdb'  => [
121
                'title' => $this->lang['strcreatedb'],
122
                'field' => Decorator::field('usecreatedb'),
123
                'type'  => 'yesno',
124
            ],
125
            'expires'   => [
126
                'title'  => $this->lang['strexpires'],
127
                'field'  => Decorator::field('useexpires'),
128
                'type'   => 'callback',
129
                'params' => ['function' => $renderUseExpires, 'null' => $this->lang['strnever']],
130
            ],
131
            'defaults'  => [
132
                'title' => $this->lang['strsessiondefaults'],
133
                'field' => Decorator::field('useconfig'),
134
            ],
135
            'actions'   => [
136
                'title' => $this->lang['stractions'],
137
            ],
138
        ];
139
140
        $actions = [
141
            'alter' => [
142
                'content' => $this->lang['stralter'],
143
                'attr'    => [
144
                    'href' => [
145
                        'url'     => 'users',
146
                        'urlvars' => [
147
                            'action'   => 'edit',
148
                            'username' => Decorator::field('usename'),
149
                        ],
150
                    ],
151
                ],
152
            ],
153
            'drop'  => [
154
                'content' => $this->lang['strdrop'],
155
                'attr'    => [
156
                    'href' => [
157
                        'url'     => 'users',
158
                        'urlvars' => [
159
                            'action'   => 'confirm_drop',
160
                            'username' => Decorator::field('usename'),
161
                        ],
162
                    ],
163
                ],
164
            ],
165
        ];
166
167
        echo $this->printTable($users, $columns, $actions, 'users-users', $this->lang['strnousers']);
168
169
        $this->printNavLinks(['create' => [
170
            'attr'    => [
171
                'href' => [
172
                    'url'     => 'users',
173
                    'urlvars' => [
174
                        'action' => 'create',
175
                        'server' => $_REQUEST['server'],
176
                    ],
177
                ],
178
            ],
179
            'content' => $this->lang['strcreateuser'],
180
        ]], 'users-users', get_defined_vars());
181
    }
182
183
    /**
184
     * If a user is not a superuser, then we have an 'account management' page
185
     * where they can change their password, etc.  We don't prevent them from
186
     * messing with the URL to gain access to other user admin stuff, because
187
     * the PostgreSQL permissions will prevent them changing anything anyway.
188
     *
189
     * @param mixed $msg
190
     */
191
    public function doAccount($msg = '')
192
    {
193
        $data = $this->misc->getDatabaseAccessor();
194
195
        $server_info = $this->misc->getServerInfo();
196
197
        $userdata         = $data->getUser($server_info['username']);
198
        $_REQUEST['user'] = $server_info['username'];
199
200
        $this->printTrail('user');
201
        $this->printTabs('server', 'account');
202
        $this->printMsg($msg);
203
204
        if ($userdata->recordCount() > 0) {
205
            $userdata->fields['usesuper']    = $data->phpBool($userdata->fields['usesuper']);
206
            $userdata->fields['usecreatedb'] = $data->phpBool($userdata->fields['usecreatedb']);
207
            echo "<table>\n";
208
            echo "<tr><th class=\"data\">{$this->lang['strusername']}</th><th class=\"data\">{$this->lang['strsuper']}</th><th class=\"data\">{$this->lang['strcreatedb']}</th><th class=\"data\">{$this->lang['strexpires']}</th>";
209
            echo "<th class=\"data\">{$this->lang['strsessiondefaults']}</th>";
210
            echo "</tr>\n";
211
            echo "<tr>\n\t<td class=\"data1\">", $this->misc->printVal($userdata->fields['usename']), "</td>\n";
212
            echo "\t<td class=\"data1\">", $this->misc->printVal($userdata->fields['usesuper'], 'yesno'), "</td>\n";
213
            echo "\t<td class=\"data1\">", $this->misc->printVal($userdata->fields['usecreatedb'], 'yesno'), "</td>\n";
214
            echo "\t<td class=\"data1\">", ('infinity' == $userdata->fields['useexpires'] || is_null($userdata->fields['useexpires']) ? $this->lang['strnever'] : $this->misc->printVal($userdata->fields['useexpires'])), "</td>\n";
215
            echo "\t<td class=\"data1\">", $this->misc->printVal($userdata->fields['useconfig']), "</td>\n";
216
            echo "</tr>\n</table>\n";
217
        } else {
218
            echo "<p>{$this->lang['strnodata']}</p>\n";
219
        }
220
221
        $this->printNavLinks(['changepassword' => [
222
            'attr'    => [
223
                'href' => [
224
                    'url'     => 'users',
225
                    'urlvars' => [
226
                        'action' => 'confchangepassword',
227
                        'server' => $_REQUEST['server'],
228
                    ],
229
                ],
230
            ],
231
            'content' => $this->lang['strchangepassword'],
232
        ]], 'users-account', get_defined_vars());
233
    }
234
235
    /**
236
     * Show confirmation of change password and actually change password.
237
     *
238
     * @param mixed $confirm
239
     * @param mixed $msg
240
     */
241
    public function doChangePassword($confirm, $msg = '')
242
    {
243
        $data = $this->misc->getDatabaseAccessor();
244
245
        $server_info = $this->misc->getServerInfo();
246
247
        if ($confirm) {
248
            $_REQUEST['user'] = $server_info['username'];
249
            $this->printTrail('user');
250
            $this->printTitle($this->lang['strchangepassword'], 'pg.user.alter');
251
            $this->printMsg($msg);
252
253
            $this->coalesceArr($_POST, 'password', '');
254
255
            $this->coalesceArr($_POST, 'confirm', '');
256
257
            echo '<form action="' . \SUBFOLDER . "/src/views/users\" method=\"post\">\n";
258
            echo "<table>\n";
259
            echo "\t<tr>\n\t\t<th class=\"data left required\">{$this->lang['strpassword']}</th>\n";
260
            echo "\t\t<td><input type=\"password\" name=\"password\" size=\"32\" value=\"",
261
            htmlspecialchars($_POST['password']), "\" /></td>\n\t</tr>\n";
262
            echo "\t<tr>\n\t\t<th class=\"data left required\">{$this->lang['strconfirm']}</th>\n";
263
            echo "\t\t<td><input type=\"password\" name=\"confirm\" size=\"32\" value=\"\" /></td>\n\t</tr>\n";
264
            echo "</table>\n";
265
            echo "<p><input type=\"hidden\" name=\"action\" value=\"changepassword\" />\n";
266
            echo $this->misc->form;
267
            echo "<input type=\"submit\" name=\"ok\" value=\"{$this->lang['strok']}\" />\n";
268
            echo "<input type=\"submit\" name=\"cancel\" value=\"{$this->lang['strcancel']}\" />\n";
269
            echo "</p></form>\n";
270
        } else {
271
            // Check that password is minimum length
272
            if (strlen($_POST['password']) < $this->conf['min_password_length']) {
273
                $this->doChangePassword(true, $this->lang['strpasswordshort']);
274
            }
275
276
            // Check that password matches confirmation password
277
            elseif ($_POST['password'] != $_POST['confirm']) {
0 ignored issues
show
Coding Style introduced by
Expected "} elseif (...) \n"; found "\n\n // Check that password matches confirmation password\n elseif (...) {\n"
Loading history...
278
                $this->doChangePassword(true, $this->lang['strpasswordconfirm']);
279
            } else {
280
                $status = $data->changePassword(
281
                    $server_info['username'],
282
                    $_POST['password']
283
                );
284
                if (0 == $status) {
285
                    $this->doAccount($this->lang['strpasswordchanged']);
286
                } else {
287
                    $this->doAccount($this->lang['strpasswordchangedbad']);
288
                }
289
            }
290
        }
291
    }
292
293
    /**
294
     * Function to allow editing of a user.
295
     *
296
     * @param mixed $msg
297
     */
298
    public function doEdit($msg = '')
299
    {
300
        $data = $this->misc->getDatabaseAccessor();
301
302
        $this->printTrail('user');
303
        $this->printTitle($this->lang['stralter'], 'pg.user.alter');
304
        $this->printMsg($msg);
305
306
        $userdata = $data->getUser($_REQUEST['username']);
307
308
        if ($userdata->recordCount() > 0) {
309
            $server_info                     = $this->misc->getServerInfo();
310
            $canRename                       = $data->hasUserRename() && ($_REQUEST['username'] != $server_info['username']);
311
            $userdata->fields['usesuper']    = $data->phpBool($userdata->fields['usesuper']);
312
            $userdata->fields['usecreatedb'] = $data->phpBool($userdata->fields['usecreatedb']);
313
314
            if (!isset($_POST['formExpires'])) {
315
                if ($canRename) {
316
                    $_POST['newname'] = $userdata->fields['usename'];
317
                }
318
319
                if ($userdata->fields['usesuper']) {
320
                    $_POST['formSuper'] = '';
321
                }
322
323
                if ($userdata->fields['usecreatedb']) {
324
                    $_POST['formCreateDB'] = '';
325
                }
326
327
                $_POST['formExpires']  = 'infinity' == $userdata->fields['useexpires'] ? '' : $userdata->fields['useexpires'];
328
                $_POST['formPassword'] = '';
329
            }
330
331
            echo '<form action="' . \SUBFOLDER . "/src/views/users\" method=\"post\">\n";
332
            echo "<table>\n";
333
            echo "\t<tr>\n\t\t<th class=\"data left\">{$this->lang['strusername']}</th>\n";
334
            echo "\t\t<td class=\"data1\">", ($canRename ? "<input name=\"newname\" size=\"15\" maxlength=\"{$data->_maxNameLen}\" value=\"" . htmlspecialchars($_POST['newname']) . '" />' : $this->misc->printVal($userdata->fields['usename'])), "</td>\n\t</tr>\n";
335
            echo "\t<tr>\n\t\t<th class=\"data left\"><label for=\"formSuper\">{$this->lang['strsuper']}</label></th>\n";
336
            echo "\t\t<td class=\"data1\"><input type=\"checkbox\" id=\"formSuper\" name=\"formSuper\"",
337
            (isset($_POST['formSuper'])) ? ' checked="checked"' : '', " /></td>\n\t</tr>\n";
338
            echo "\t<tr>\n\t\t<th class=\"data left\"><label for=\"formCreateDB\">{$this->lang['strcreatedb']}</label></th>\n";
339
            echo "\t\t<td class=\"data1\"><input type=\"checkbox\" id=\"formCreateDB\" name=\"formCreateDB\"",
340
            (isset($_POST['formCreateDB'])) ? ' checked="checked"' : '', " /></td>\n\t</tr>\n";
341
            echo "\t<tr>\n\t\t<th class=\"data left\">{$this->lang['strexpires']}</th>\n";
342
            echo "\t\t<td class=\"data1\"><input size=\"16\" name=\"formExpires\" value=\"", htmlspecialchars($_POST['formExpires']), "\" /></td>\n\t</tr>\n";
343
            echo "\t<tr>\n\t\t<th class=\"data left\">{$this->lang['strpassword']}</th>\n";
344
            echo "\t\t<td class=\"data1\"><input type=\"password\" size=\"16\" name=\"formPassword\" value=\"", htmlspecialchars($_POST['formPassword']), "\" /></td>\n\t</tr>\n";
345
            echo "\t<tr>\n\t\t<th class=\"data left\">{$this->lang['strconfirm']}</th>\n";
346
            echo "\t\t<td class=\"data1\"><input type=\"password\" size=\"16\" name=\"formConfirm\" value=\"\" /></td>\n\t</tr>\n";
347
            echo "</table>\n";
348
            echo "<p><input type=\"hidden\" name=\"action\" value=\"save_edit\" />\n";
349
            echo '<input type="hidden" name="username" value="', htmlspecialchars($_REQUEST['username']), "\" />\n";
350
            echo $this->misc->form;
351
            echo "<input type=\"submit\" name=\"alter\" value=\"{$this->lang['stralter']}\" />\n";
352
            echo "<input type=\"submit\" name=\"cancel\" value=\"{$this->lang['strcancel']}\" /></p>\n";
353
            echo "</form>\n";
354
        } else {
355
            echo "<p>{$this->lang['strnodata']}</p>\n";
356
        }
357
    }
358
359
    /**
360
     * Function to save after editing a user.
361
     */
362
    public function doSaveEdit()
363
    {
364
        $data = $this->misc->getDatabaseAccessor();
365
366
        // Check name and password
367
        if (isset($_POST['newname']) && '' == $_POST['newname']) {
368
            $this->doEdit($this->lang['struserneedsname']);
369
        } elseif ($_POST['formPassword'] != $_POST['formConfirm']) {
370
            $this->doEdit($this->lang['strpasswordconfirm']);
371
        } else {
372
            if (isset($_POST['newname'])) {
373
                $status = $data->setRenameUser($_POST['username'], $_POST['formPassword'], isset($_POST['formCreateDB']), isset($_POST['formSuper']), $_POST['formExpires'], $_POST['newname']);
374
            } else {
375
                $status = $data->setUser($_POST['username'], $_POST['formPassword'], isset($_POST['formCreateDB']), isset($_POST['formSuper']), $_POST['formExpires']);
376
            }
377
378
            if (0 == $status) {
379
                $this->doDefault($this->lang['struserupdated']);
380
            } else {
381
                $this->doEdit($this->lang['struserupdatedbad']);
382
            }
383
        }
384
    }
385
386
    /**
387
     * Show confirmation of drop and perform actual drop.
388
     *
389
     * @param mixed $confirm
390
     */
391
    public function doDrop($confirm)
392
    {
393
        $data = $this->misc->getDatabaseAccessor();
394
395
        if ($confirm) {
396
            $this->printTrail('user');
397
            $this->printTitle($this->lang['strdrop'], 'pg.user.drop');
398
399
            echo '<p>', sprintf($this->lang['strconfdropuser'], $this->misc->printVal($_REQUEST['username'])), "</p>\n";
400
401
            echo '<form action="' . \SUBFOLDER . "/src/views/users\" method=\"post\">\n";
402
            echo "<p><input type=\"hidden\" name=\"action\" value=\"drop\" />\n";
403
            echo '<input type="hidden" name="username" value="', htmlspecialchars($_REQUEST['username']), "\" />\n";
404
            echo $this->misc->form;
405
            echo "<input type=\"submit\" name=\"drop\" value=\"{$this->lang['strdrop']}\" />\n";
406
            echo "<input type=\"submit\" name=\"cancel\" value=\"{$this->lang['strcancel']}\" /></p>\n";
407
            echo "</form>\n";
408
        } else {
409
            $status = $data->dropUser($_REQUEST['username']);
410
            if (0 == $status) {
411
                $this->doDefault($this->lang['struserdropped']);
412
            } else {
413
                $this->doDefault($this->lang['struserdroppedbad']);
414
            }
415
        }
416
    }
417
418
    /**
419
     * Displays a screen where they can enter a new user.
420
     *
421
     * @param mixed $msg
422
     */
423
    public function doCreate($msg = '')
424
    {
425
        $data = $this->misc->getDatabaseAccessor();
426
427
        $this->coalesceArr($_POST, 'formUsername', '');
428
429
        $this->coalesceArr($_POST, 'formPassword', '');
430
431
        $this->coalesceArr($_POST, 'formConfirm', '');
432
433
        $this->coalesceArr($_POST, 'formExpires', '');
434
435
        $this->printTrail('server');
436
        $this->printTitle($this->lang['strcreateuser'], 'pg.user.create');
437
        $this->printMsg($msg);
438
439
        echo '<form action="' . \SUBFOLDER . "/src/views/users\" method=\"post\">\n";
440
        echo "<table>\n";
441
        echo "\t<tr>\n\t\t<th class=\"data left required\">{$this->lang['strusername']}</th>\n";
442
        echo "\t\t<td class=\"data1\"><input size=\"15\" maxlength=\"{$data->_maxNameLen}\" name=\"formUsername\" value=\"", htmlspecialchars($_POST['formUsername']), "\" /></td>\n\t</tr>\n";
443
        echo "\t<tr>\n\t\t<th class=\"data left\">{$this->lang['strpassword']}</th>\n";
444
        echo "\t\t<td class=\"data1\"><input size=\"15\" type=\"password\" name=\"formPassword\" value=\"", htmlspecialchars($_POST['formPassword']), "\" /></td>\n\t</tr>\n";
445
        echo "\t<tr>\n\t\t<th class=\"data left\">{$this->lang['strconfirm']}</th>\n";
446
        echo "\t\t<td class=\"data1\"><input size=\"15\" type=\"password\" name=\"formConfirm\" value=\"", htmlspecialchars($_POST['formConfirm']), "\" /></td>\n\t</tr>\n";
447
        echo "\t<tr>\n\t\t<th class=\"data left\"><label for=\"formSuper\">{$this->lang['strsuper']}</label></th>\n";
448
        echo "\t\t<td class=\"data1\"><input type=\"checkbox\" id=\"formSuper\" name=\"formSuper\"",
449
        (isset($_POST['formSuper'])) ? ' checked="checked"' : '', " /></td>\n\t</tr>\n";
450
        echo "\t<tr>\n\t\t<th class=\"data left\"><label for=\"formCreateDB\">{$this->lang['strcreatedb']}</label></th>\n";
451
        echo "\t\t<td class=\"data1\"><input type=\"checkbox\" id=\"formCreateDB\" name=\"formCreateDB\"",
452
        (isset($_POST['formCreateDB'])) ? ' checked="checked"' : '', " /></td>\n\t</tr>\n";
453
        echo "\t<tr>\n\t\t<th class=\"data left\">{$this->lang['strexpires']}</th>\n";
454
        echo "\t\t<td class=\"data1\"><input size=\"30\" name=\"formExpires\" value=\"", htmlspecialchars($_POST['formExpires']), "\" /></td>\n\t</tr>\n";
455
        echo "</table>\n";
456
        echo "<p><input type=\"hidden\" name=\"action\" value=\"save_create\" />\n";
457
        echo $this->misc->form;
458
        echo "<input type=\"submit\" name=\"create\" value=\"{$this->lang['strcreate']}\" />\n";
459
        echo "<input type=\"submit\" name=\"cancel\" value=\"{$this->lang['strcancel']}\" /></p>\n";
460
        echo "</form>\n";
461
    }
462
463
    /**
464
     * Actually creates the new user in the database.
465
     */
466
    public function doSaveCreate()
467
    {
468
        $data = $this->misc->getDatabaseAccessor();
469
470
        // Check data
471
        if ('' == $_POST['formUsername']) {
472
            $this->doCreate($this->lang['struserneedsname']);
473
        } elseif ($_POST['formPassword'] != $_POST['formConfirm']) {
474
            $this->doCreate($this->lang['strpasswordconfirm']);
475
        } else {
476
            $status = $data->createUser(
477
                $_POST['formUsername'],
478
                $_POST['formPassword'],
479
                isset($_POST['formCreateDB']),
480
                isset($_POST['formSuper']),
481
                $_POST['formExpires'],
482
                []
483
            );
484
            if (0 == $status) {
485
                $this->doDefault($this->lang['strusercreated']);
486
            } else {
487
                $this->doCreate($this->lang['strusercreatedbad']);
488
            }
489
        }
490
    }
491
}
492