Issues (217)

src/controllers/PrivilegesController.php (1 issue)

Labels
Severity
1
<?php
2
3
/**
4
 * PHPPgAdmin 6.1.3
5
 */
6
7
namespace PHPPgAdmin\Controller;
8
9
/**
10
 * PrivilegesController controller class.
11
 */
12
class PrivilegesController extends BaseController
13
{
14
    public $table_place = 'privileges-privileges';
15
16
    public $controller_title = 'strprivileges';
17
18
    /**
19
     * Default method to render the controller according to the action parameter.
20
     */
21
    public function render(): void
22
    {
23
        $this->printHeader();
24
        $this->printBody();
25
26
        switch ($this->action) {
27
            case 'save':
28
                if (isset($_REQUEST['cancel'])) {
29
                    $this->doDefault();
30
                } else {
31
                    $this->doAlter($_REQUEST['mode']);
32
                }
33
34
                break;
35
            case 'alter':
36
                $this->formAlter($_REQUEST['mode']);
37
38
                break;
39
40
            default:
41
                $this->doDefault();
42
43
                break;
44
        }
45
46
        $this->printFooter();
47
    }
48
49
    /**
50
     * Show permissions on a database, namespace, relation, language or function.
51
     *
52
     * @param mixed $msg
53
     */
54
    public function doDefault($msg = ''): void
55
    {
56
        $data = $this->misc->getDatabaseAccessor();
57
        $subject = $_REQUEST['subject'];
58
59
        $this->printTrail($subject);
60
61
        // @@@FIXME: This switch is just a temporary solution,
62
        // need a better way, maybe every type of object should
63
        // have a tab bar???
64
65
        if (\in_array($subject, [
66
            'server',
67
            'database',
68
            'schema',
69
            'table',
70
            'column',
71
            'view',
72
            'function',
73
        ], true)) {
74
            $this->printTabs($subject, 'privileges');
75
        } else {
76
            $this->printTitle($this->lang['strprivileges'], 'pg.privilege');
77
        }
78
79
        $this->printMsg($msg);
80
81
        if (!isset($data->privlist[$subject])) {
82
            $this->container->halt('No privileges defined for subject ' . $subject);
83
84
            return;
85
        }
86
87
        // Determine whether object should be ref'd by name or oid.
88
        if (isset($_REQUEST[$subject . '_oid'])) {
89
            $object = $_REQUEST[$subject . '_oid'];
90
        } else {
91
            $object = $_REQUEST[$subject];
92
        }
93
94
        // Get the privileges on the object, given its type
95
        if ('column' === $subject) {
96
            $privileges = $data->getPrivileges($object, 'column', $_REQUEST['table']);
97
        } else {
98
            $privileges = $data->getPrivileges($object, $subject);
99
        }
100
101
        if (0 < \count($privileges)) {
0 ignored issues
show
It seems like $privileges can also be of type integer; however, parameter $var of count() does only seem to accept Countable|array, maybe add an additional type check? ( Ignorable by Annotation )

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

101
        if (0 < \count(/** @scrutinizer ignore-type */ $privileges)) {
Loading history...
102
            echo '<table>' . \PHP_EOL;
103
104
            if ($data->hasRoles()) {
105
                echo "<tr><th class=\"data\">{$this->lang['strrole']}</th>";
106
            } else {
107
                echo "<tr><th class=\"data\">{$this->lang['strtype']}</th><th class=\"data\">{$this->lang['struser']}/{$this->lang['strgroup']}</th>";
108
            }
109
110
            foreach ($data->privlist[$subject] as $v2) {
111
                // Skip over ALL PRIVILEGES
112
                if ('ALL PRIVILEGES' === $v2) {
113
                    continue;
114
                }
115
116
                echo "<th class=\"data\">{$v2}</th>" . \PHP_EOL;
117
            }
118
119
            if ($data->hasGrantOption()) {
120
                echo "<th class=\"data\">{$this->lang['strgrantor']}</th>";
121
            }
122
            echo '</tr>' . \PHP_EOL;
123
124
            // Loop over privileges, outputting them
125
            $i = 0;
126
127
            foreach ($privileges as $v) {
128
                $id = (0 === ($i % 2) ? '1' : '2');
129
                echo "<tr class=\"data{$id}\">" . \PHP_EOL;
130
131
                if (!$data->hasRoles()) {
132
                    echo '<td>', $this->misc->printVal($v[0]), '</td>' . \PHP_EOL;
133
                }
134
135
                echo '<td>', $this->misc->printVal($v[1]), '</td>' . \PHP_EOL;
136
137
                foreach ($data->privlist[$subject] as $v2) {
138
                    // Skip over ALL PRIVILEGES
139
                    if ('ALL PRIVILEGES' === $v2) {
140
                        continue;
141
                    }
142
143
                    echo '<td>';
144
145
                    if (\in_array($v2, $v[2], true)) {
146
                        echo $this->lang['stryes'];
147
                    } else {
148
                        echo $this->lang['strno'];
149
                    }
150
151
                    // If we have grant option for this, end mark
152
                    if ($data->hasGrantOption() && \in_array($v2, $v[4], true)) {
153
                        echo $this->lang['strasterisk'];
154
                    }
155
156
                    echo '</td>' . \PHP_EOL;
157
                }
158
159
                if ($data->hasGrantOption()) {
160
                    echo '<td>', $this->misc->printVal($v[3]), '</td>' . \PHP_EOL;
161
                }
162
                echo '</tr>' . \PHP_EOL;
163
                ++$i;
164
            }
165
166
            echo '</table>';
167
        } else {
168
            echo "<p>{$this->lang['strnoprivileges']}</p>" . \PHP_EOL;
169
        }
170
        $this->printGrantLinks();
171
    }
172
173
    public function printGrantLinks(): void
174
    {
175
        $data = $this->misc->getDatabaseAccessor();
176
        $subject = $_REQUEST['subject'];
177
        $alllabel = '';
178
        $alltxt = '';
179
        // Links for granting to a user or group
180
        switch ($subject) {
181
            case 'table':
182
            case 'view':
183
            case 'sequence':
184
            case 'function':
185
            case 'tablespace':
186
                $alllabel = "showall{$subject}s";
187
                $allurl = "{$subject}s";
188
                $alltxt = $this->lang["strshowall{$subject}s"];
189
190
                break;
191
            case 'schema':
192
                $alllabel = 'showallschemas';
193
                $allurl = 'schemas';
194
                $alltxt = $this->lang['strshowallschemas'];
195
196
                break;
197
            case 'database':
198
                $alllabel = 'showalldatabases';
199
                $allurl = 'alldb';
200
                $alltxt = $this->lang['strshowalldatabases'];
201
202
                break;
203
        }
204
205
        $object = $_REQUEST[$subject];
206
207
        if ('function' === $subject) {
208
            $objectoid = $_REQUEST[$subject . '_oid'];
209
            $urlvars = [
210
                'action' => 'alter',
211
                'server' => $_REQUEST['server'],
212
                'database' => $_REQUEST['database'],
213
                'schema' => $_REQUEST['schema'],
214
                $subject => $object,
215
                "{$subject}_oid" => $objectoid,
216
                'subject' => $subject,
217
            ];
218
        } elseif ('column' === $subject) {
219
            $urlvars = [
220
                'action' => 'alter',
221
                'server' => $_REQUEST['server'],
222
                'database' => $_REQUEST['database'],
223
                'schema' => $_REQUEST['schema'],
224
                $subject => $object,
225
                'subject' => $subject,
226
            ];
227
228
            if (isset($_REQUEST['table'])) {
229
                $urlvars['table'] = $_REQUEST['table'];
230
            } elseif (isset($_REQUEST['view'])) {
231
                $urlvars['view'] = $_REQUEST['view'];
232
            } else {
233
                $urlvars['matview'] = $_REQUEST['matview'];
234
            }
235
        } else {
236
            $urlvars = [
237
                'action' => 'alter',
238
                'server' => $_REQUEST['server'],
239
                'database' => $_REQUEST['database'],
240
                $subject => $object,
241
                'subject' => $subject,
242
            ];
243
244
            if (isset($_REQUEST['schema'])) {
245
                $urlvars['schema'] = $_REQUEST['schema'];
246
            }
247
        }
248
249
        $navlinks = [
250
            'grant' => [
251
                'attr' => [
252
                    'href' => [
253
                        'url' => 'privileges',
254
                        'urlvars' => \array_merge($urlvars, ['mode' => 'grant']),
255
                    ],
256
                ],
257
                'content' => $this->lang['strgrant'],
258
            ],
259
            'revoke' => [
260
                'attr' => [
261
                    'href' => [
262
                        'url' => 'privileges',
263
                        'urlvars' => \array_merge($urlvars, ['mode' => 'revoke']),
264
                    ],
265
                ],
266
                'content' => $this->lang['strrevoke'],
267
            ],
268
        ];
269
270
        if (isset($allurl)) {
271
            $navlinks[$alllabel] = [
272
                'attr' => [
273
                    'href' => [
274
                        'url' => $allurl,
275
                        'urlvars' => [
276
                            'server' => $_REQUEST['server'],
277
                            'database' => $_REQUEST['database'],
278
                        ],
279
                    ],
280
                ],
281
                'content' => $alltxt,
282
            ];
283
284
            if (isset($_REQUEST['schema'])) {
285
                $navlinks[$alllabel]['attr']['href']['urlvars']['schema'] = $_REQUEST['schema'];
286
            }
287
        }
288
289
        $this->printNavLinks($navlinks, $this->table_place, \get_defined_vars());
290
    }
291
292
    /**
293
     * Prints the form to grants permision on an object to a user.
294
     *
295
     * @param string $mode either grant or revoke
296
     * @param string $msg  The message
297
     */
298
    public function formAlter($mode, $msg = ''): void
299
    {
300
        $data = $this->misc->getDatabaseAccessor();
301
302
        $this->coalesceArr($_REQUEST, 'username', []);
303
304
        $this->coalesceArr($_REQUEST, 'groupname', []);
305
306
        $this->coalesceArr($_REQUEST, 'privilege', []);
307
308
        // Get users from the database
309
        $users = $data->getUsers();
310
        // Get groups from the database
311
        $groups = $data->getGroups();
312
313
        $this->printTrail($_REQUEST['subject']);
314
315
        $this->printTitle($this->lang['str' . $mode], 'pg.privilege.' . $mode);
316
317
        $this->printMsg($msg);
318
319
        echo '<form action="' . \containerInstance()->subFolder . '/src/views/privileges" method="post">' . \PHP_EOL;
320
        echo '<table>' . \PHP_EOL;
321
        echo "<tr><th class=\"data left\">{$this->lang['strusers']}</th>" . \PHP_EOL;
322
        echo '<td class="data1"><select name="username[]" multiple="multiple" size="', \min(6, $users->recordCount()), '">' . \PHP_EOL;
323
324
        while (!$users->EOF) {
325
            $uname = \htmlspecialchars($users->fields['usename']);
326
            echo "<option value=\"{$uname}\"",
327
            \in_array($users->fields['usename'], $_REQUEST['username'], true) ? ' selected="selected"' : '', ">{$uname}</option>" . \PHP_EOL;
328
            $users->moveNext();
329
        }
330
        echo '</select></td></tr>' . \PHP_EOL;
331
        echo "<tr><th class=\"data left\">{$this->lang['strgroups']}</th>" . \PHP_EOL;
332
        echo '<td class="data1">' . \PHP_EOL;
333
        echo '<input type="checkbox" id="public" name="public"', (isset($_REQUEST['public']) ? ' checked="checked"' : ''), ' /><label for="public">PUBLIC</label>' . \PHP_EOL;
334
        // Only show groups if there are groups!
335
        if (0 < $groups->recordCount()) {
336
            echo '<br /><select name="groupname[]" multiple="multiple" size="', \min(6, $groups->recordCount()), '">' . \PHP_EOL;
337
338
            while (!$groups->EOF) {
339
                $gname = \htmlspecialchars($groups->fields['groname']);
340
                echo "<option value=\"{$gname}\"",
341
                \in_array($groups->fields['groname'], $_REQUEST['groupname'], true) ? ' selected="selected"' : '', ">{$gname}</option>" . \PHP_EOL;
342
                $groups->moveNext();
343
            }
344
            echo '</select>' . \PHP_EOL;
345
        }
346
        echo '</td></tr>' . \PHP_EOL;
347
        echo "<tr><th class=\"data left required\">{$this->lang['strprivileges']}</th>" . \PHP_EOL;
348
        echo '<td class="data1">' . \PHP_EOL;
349
350
        foreach ($data->privlist[$_REQUEST['subject']] as $v) {
351
            $v = \htmlspecialchars($v);
352
            echo "<input type=\"checkbox\" id=\"privilege[{$v}]\" name=\"privilege[{$v}]\"",
353
            isset($_REQUEST['privilege'][$v]) ? ' checked="checked"' : '', " /><label for=\"privilege[{$v}]\">{$v}</label><br />" . \PHP_EOL;
354
        }
355
        echo '</td></tr>' . \PHP_EOL;
356
        // Grant option
357
        if ($data->hasGrantOption()) {
358
            echo "<tr><th class=\"data left\">{$this->lang['stroptions']}</th>" . \PHP_EOL;
359
            echo '<td class="data1">' . \PHP_EOL;
360
361
            if ('grant' === $mode) {
362
                echo '<input type="checkbox" id="grantoption" name="grantoption"',
363
                isset($_REQUEST['grantoption']) ? ' checked="checked"' : '', ' /><label for="grantoption">GRANT OPTION</label>' . \PHP_EOL;
364
            } elseif ('revoke' === $mode) {
365
                echo '<input type="checkbox" id="grantoption" name="grantoption"',
366
                isset($_REQUEST['grantoption']) ? ' checked="checked"' : '', ' /><label for="grantoption">GRANT OPTION FOR</label><br />' . \PHP_EOL;
367
                echo '<input type="checkbox" id="cascade" name="cascade"',
368
                isset($_REQUEST['cascade']) ? ' checked="checked"' : '', ' /><label for="cascade">CASCADE</label><br />' . \PHP_EOL;
369
            }
370
            echo '</td></tr>' . \PHP_EOL;
371
        }
372
        echo '</table>' . \PHP_EOL;
373
374
        echo '<p><input type="hidden" name="action" value="save" />' . \PHP_EOL;
375
        echo '<input type="hidden" name="mode" value="', \htmlspecialchars($mode), '" />' . \PHP_EOL;
376
        echo '<input type="hidden" name="subject" value="', \htmlspecialchars($_REQUEST['subject']), '" />' . \PHP_EOL;
377
378
        if (isset($_REQUEST[$_REQUEST['subject'] . '_oid'])) {
379
            echo '<input type="hidden" name="', \htmlspecialchars($_REQUEST['subject'] . '_oid'),
380
            '" value="', \htmlspecialchars($_REQUEST[$_REQUEST['subject'] . '_oid']), '" />' . \PHP_EOL;
381
        }
382
383
        echo '<input type="hidden" name="', \htmlspecialchars($_REQUEST['subject']),
384
        '" value="', \htmlspecialchars($_REQUEST[$_REQUEST['subject']]), '" />' . \PHP_EOL;
385
386
        if ('column' === $_REQUEST['subject']) {
387
            echo '<input type="hidden" name="table" value="',
388
            \htmlspecialchars($_REQUEST['table']), '" />' . \PHP_EOL;
389
        }
390
391
        echo $this->view->form;
392
        echo \sprintf('<input type="submit" name="%s" value="%s" />%s', $mode, $this->lang['str' . $mode], \PHP_EOL);
393
394
        echo "<input type=\"submit\" name=\"cancel\" value=\"{$this->lang['strcancel']}\" /></p>";
395
        echo '</form>' . \PHP_EOL;
396
    }
397
398
    /**
399
     * Grant permissions on an object to a user.
400
     *
401
     * @param string $mode 'grant' or 'revoke'
402
     */
403
    public function doAlter($mode): void
404
    {
405
        $data = $this->misc->getDatabaseAccessor();
406
407
        $this->coalesceArr($_REQUEST, 'username', []);
408
409
        $this->coalesceArr($_REQUEST, 'groupname', []);
410
411
        $this->coalesceArr($_REQUEST, 'privilege', []);
412
413
        // Determine whether object should be ref'd by name or oid.
414
        if (isset($_REQUEST[$_REQUEST['subject'] . '_oid'])) {
415
            $object = $_REQUEST[$_REQUEST['subject'] . '_oid'];
416
        } else {
417
            $object = $_REQUEST[$_REQUEST['subject']];
418
        }
419
420
        if (isset($_REQUEST['table'])) {
421
            $table = $_REQUEST['table'];
422
        } else {
423
            $table = null;
424
        }
425
426
        $status = $data->setPrivileges(
427
            ('grant' === $mode) ? 'GRANT' : 'REVOKE',
428
            $_REQUEST['subject'],
429
            $object,
430
            isset($_REQUEST['public']),
431
            $_REQUEST['username'],
432
            $_REQUEST['groupname'],
433
            \array_keys($_REQUEST['privilege']),
434
            isset($_REQUEST['grantoption']),
435
            isset($_REQUEST['cascade']),
436
            $table
437
        );
438
439
        if (0 === $status) {
440
            $this->doDefault($this->lang['strgranted']);
441
        } elseif (-3 === $status || -4 === $status) {
442
            $this->formAlter($_REQUEST['mode'], $this->lang['strgrantbad']);
443
        } else {
444
            $this->formAlter($_REQUEST['mode'], $this->lang['strgrantfailed']);
445
        }
446
    }
447
}
448