UserFacade::getUserPrivileges()   A
last analyzed

Complexity

Conditions 5
Paths 9

Size

Total Lines 44
Code Lines 29

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 29
nc 9
nop 3
dl 0
loc 44
rs 9.1448
c 0
b 0
f 0
1
<?php
2
3
namespace Lagdo\DbAdmin\Db\Facades;
4
5
use function explode;
6
use function in_array;
7
use function array_keys;
8
use function strtoupper;
9
10
/**
11
 * Facade to user functions
12
 */
13
class UserFacade extends AbstractFacade
14
{
15
    /**
16
     * Get the privilege list
17
     * This feature is available only for MySQL
18
     *
19
     * @param string $database  The database name
20
     *
21
     * @return array
22
     */
23
    public function getPrivileges(string $database = ''): array
24
    {
25
        $headers = [
26
            $this->utils->trans->lang('Username'),
27
            $this->utils->trans->lang('Server'),
28
            '',
29
            '',
30
        ];
31
32
        $details = [];
33
        foreach ($this->driver->getUsers($database) as $user) {
34
            // Fetch user grants
35
            $userEntity = $this->driver->getUserGrants($user["User"], $user["Host"]);
36
            $details[] = [
37
                'user' => $this->utils->str->html($userEntity->name),
38
                'host' => $this->utils->str->html($userEntity->host),
39
                'grants' => \array_keys($userEntity->grants),
40
            ];
41
        }
42
43
        return \compact('headers', 'details');
44
    }
45
46
    /**
47
     * @param array $features
48
     * @param array $row
49
     *
50
     * @return void
51
     */
52
    private function makeFeatures(array &$features, array $row)
53
    {
54
        $contexts = explode(',', $row['Context']);
55
        foreach ($contexts as $context) {
56
            // Don't take 'Grant option' privileges.
57
            if ($row['Privilege'] === 'Grant option') {
58
                continue;
59
            }
60
            // Privileges of 'Server Admin' and 'File access on server' are merged
61
            if ($context === 'File access on server') {
62
                $context = 'Server Admin';
63
            }
64
            $privilege = $row['Privilege'];
65
            // Comment for this is 'No privileges - allow connect only'
66
            if ($context === 'Server Admin' && $privilege === 'Usage') {
67
                continue;
68
            }
69
            // MySQL bug #30305
70
            if ($context === 'Procedures' && $privilege === 'Create routine') {
71
                $context = 'Databases';
72
            }
73
            if (!isset($features[$context])) {
74
                $features[$context] = [];
75
            }
76
            $features[$context][$privilege] = $row['Comment'];
77
            if ($context === 'Tables' &&
78
                in_array($privilege, ['Select', 'Insert', 'Update', 'References'])) {
79
                $features['Columns'][$privilege] = $row['Comment'];
80
            }
81
        }
82
    }
83
84
    /**
85
     * @param string $privilege
86
     * @param string $desc
87
     * @param string $context
88
     * @param array $grants
89
     *
90
     * @return array
91
     */
92
    private function getPrivilegeInput(string $privilege, string $desc, string $context, array $grants): array
93
    {
94
        $detail = [$desc, $this->utils->str->html($privilege)];
95
        // echo '<tr><td' . ($desc ? ">$desc<td" : " colspan='2'") .
96
        //     ' lang="en" title="' . $this->utils->str->html($comment) . '">' . $this->utils->str->html($privilege);
97
        $i = 0;
98
        foreach ($grants as $object => $grant) {
99
            $name = "'grants[$i][" . $this->utils->str->html(strtoupper($privilege)) . "]'";
100
            $value = $grant[strtoupper($privilege)] ?? false;
101
            if ($context == 'Server Admin' && $object != (isset($grants['*.*']) ? '*.*' : '.*')) {
102
                $detail[] = '';
103
            }
104
            // elseif(isset($values['grant']))
105
            // {
106
            //     $detail[] = "<select name=$name><option><option value='1'" .
107
            //         ($value ? ' selected' : '') . '>' . $this->utils->trans->lang('Grant') .
108
            //         "<option value='0'" . ($value == '0' ? ' selected' : '') . '>' .
109
            //         $this->utils->trans->lang('Revoke') . '</select>';
110
            // }
111
            else {
112
                $detail[] = "<input type='checkbox' name=$name" . ($value ? ' checked />' : ' />');
113
            }
114
            $i++;
115
        }
116
        return $detail;
117
    }
118
119
    /**
120
     * Get the user privileges
121
     *
122
     * @param array $grants     The user grants
123
     *
124
     * @return array
125
     */
126
    private function _getUserPrivileges(array $grants): array
127
    {
128
        // From user.inc.php
129
        $features = [
130
            '' => [
131
                'All privileges' => '',
132
            ],
133
            'Columns' => [],
134
        ];
135
        $rows = $this->driver->rows('SHOW PRIVILEGES');
136
        foreach ($rows as $row) {
137
            $this->makeFeatures($features, $row);
138
        }
139
140
        foreach (array_keys($features['Tables']) as $privilege) {
141
            unset($features['Databases'][$privilege]);
142
        }
143
144
        $privileges = [];
145
        $contexts = [
146
            '' => '',
147
            'Server Admin' => $this->utils->trans->lang('Server'),
148
            'Databases' => $this->utils->trans->lang('Database'),
149
            'Tables' => $this->utils->trans->lang('Table'),
150
            'Columns' => $this->utils->trans->lang('Column'),
151
            'Procedures' => $this->utils->trans->lang('Routine'),
152
        ];
153
        foreach ($contexts as $context => $desc) {
154
            foreach ($features[$context] as $privilege => $comment) {
155
                $privileges[] = $this->getPrivilegeInput($privilege, $desc, $context, $grants);
156
            }
157
        }
158
159
        return $privileges;
160
    }
161
162
    /**
163
     * Get the grants of a user on a given host
164
     *
165
     * @return array
166
     */
167
    public function newUserPrivileges(): array
168
    {
169
        $grants = [".*" => []];
170
171
        $headers = [
172
            $this->utils->trans->lang('Contexts'),
173
            $this->utils->trans->lang('Privileges'),
174
        ];
175
        $i = 0;
176
        foreach ($grants as $object => $grant) {
177
            //! separate db, table, columns, PROCEDURE|FUNCTION, routine
178
            $headers[] = $object === '*.*' ?
179
                '<input type="hidden" name="objects[' . $i . ']" value="*.*" />*.*' :
180
                '<input name="objects[' . $i . ']" value="' . $this->utils->str->html($object) . '" autocapitalize="off" />';
181
            $i++;
182
        }
183
184
        $user = [
185
            'host' => [
186
                'label' => $this->utils->trans->lang('Server'),
187
                'value' => '',
188
            ],
189
            'name' => [
190
                'label' => $this->utils->trans->lang('Username'),
191
                'value' => '',
192
            ],
193
            'pass' => [
194
                'label' => $this->utils->trans->lang('Password'),
195
                'value' => '',
196
            ],
197
            'hashed' => [
198
                'label' => $this->utils->trans->lang('Hashed'),
199
                'value' => false,
200
            ],
201
        ];
202
203
        $details = $this->_getUserPrivileges($grants);
204
205
        return \compact('user', 'headers', 'details');
206
    }
207
208
    /**
209
     * Get the grants of a user on a given host
210
     *
211
     * @param string $user      The username
212
     * @param string $host      The host name
213
     * @param string $database  The database name
214
     *
215
     * @return array
216
     */
217
    public function getUserPrivileges(string $user, string $host, string $database): array
218
    {
219
        $userEntity = $this->driver->getUserGrants($user, $host);
220
        if ($database !== '') {
221
            $userEntity->grants = isset($userEntity->grants[$database]) ?
222
                [$database => $userEntity->grants[$database]] : [];
223
        }
224
225
        $headers = [
226
            $this->utils->trans->lang('Contexts'),
227
            $this->utils->trans->lang('Privileges'),
228
        ];
229
        $i = 0;
230
        foreach ($userEntity->grants as $object => $grant) {
231
            //! separate db, table, columns, PROCEDURE|FUNCTION, routine
232
            $headers[] = $object === '*.*' ?
233
                '<input type="hidden" name="objects[' . $i . ']" value="*.*" />*.*' :
234
                '<input name="objects[' . $i . ']" value="' .
235
                    $this->utils->str->html($object) . '" autocapitalize="off" />';
236
            $i++;
237
        }
238
239
        $user = [
240
            'host' => [
241
                'label' => $this->utils->trans->lang('Server'),
242
                'value' => $host,
243
            ],
244
            'name' => [
245
                'label' => $this->utils->trans->lang('Username'),
246
                'value' => $user,
247
            ],
248
            'pass' => [
249
                'label' => $this->utils->trans->lang('Password'),
250
                'value' => $userEntity->password ,
251
            ],
252
            'hashed' => [
253
                'label' => $this->utils->trans->lang('Hashed'),
254
                'value' => ($userEntity->password  !== ''),
255
            ],
256
        ];
257
258
        $details = $this->_getUserPrivileges($userEntity->grants);
259
260
        return \compact('user', 'headers', 'details');
261
    }
262
}
263