Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 86
0.00% covered (danger)
0.00%
0 / 9
CRAP
0.00% covered (danger)
0.00%
0 / 1
PermissionQueryBuilder
0.00% covered (danger)
0.00%
0 / 86
0.00% covered (danger)
0.00%
0 / 9
870
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 groups
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 account
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 units
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 apps
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 categories
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 modules
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 permission
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 query
0.00% covered (danger)
0.00%
0 / 71
0.00% covered (danger)
0.00%
0 / 1
462
1<?php
2/**
3 * Jingga
4 *
5 * PHP Version 8.1
6 *
7 * @package   Modules\Admin\Models
8 * @copyright Dennis Eichhorn
9 * @license   OMS License 2.0
10 * @version   1.0.0
11 * @link      https://jingga.app
12 */
13declare(strict_types=1);
14
15namespace Modules\Admin\Models;
16
17use phpOMS\Account\PermissionType;
18use phpOMS\DataStorage\Database\Connection\ConnectionAbstract;
19use phpOMS\DataStorage\Database\Query\Builder;
20use phpOMS\DataStorage\Database\Query\Where;
21
22/**
23 * Query builder for selects which immediately check if a user/group has the appropriate permissions
24 *
25 * @package Modules\Admin\Models
26 * @license OMS License 2.0
27 * @link    https://jingga.app
28 * @since   1.0.0
29 */
30final class PermissionQueryBuilder
31{
32    /**
33     * Database connection
34     *
35     * @var ConnectionAbstract
36     * @since 1.0.0
37     */
38    private ConnectionAbstract $connection;
39
40    /**
41     * Group ids.
42     *
43     * @var array
44     * @since 1.0.0
45     */
46    private array $groups = [];
47
48    /**
49     * Account id.
50     *
51     * @var int
52     */
53    public int $account = 0;
54
55    /**
56     * Unit ids.
57     *
58     * @var array
59     * @since 1.0.0
60     */
61    private array $units = [null];
62
63    /**
64     * Ap ids.
65     *
66     * @var array
67     * @since 1.0.0
68     */
69    private array $apps = [null];
70
71    /**
72     * Module names.
73     *
74     * @var array
75     * @since 1.0.0
76     */
77    private array $modules = [null];
78
79    /**
80     * Category ids.
81     *
82     * @var array
83     * @since 1.0.0
84     */
85    private array $categories = [null];
86
87    /**
88     * Permission flag
89     *
90     * @var int
91     * @since 1.0.0
92     */
93    private int $permission = 0;
94
95    /**
96     * Constructor.
97     *
98     * @param ConnectionAbstract $connection Database connection
99     *
100     * @since 1.0.0
101     */
102    public function __construct(ConnectionAbstract $connection)
103    {
104        $this->connection = $connection;
105    }
106
107    /**
108     * Set group ids
109     *
110     * @param array $groups Group ids
111     *
112     * @return self
113     *
114     * @since 1.0.0
115     */
116    public function groups(array $groups) : self
117    {
118        $this->groups = $groups;
119
120        return $this;
121    }
122
123    /**
124     * Set account id
125     *
126     * @param int $account Account id
127     *
128     * @return self
129     *
130     * @since 1.0.0
131     */
132    public function account(int $account) : self
133    {
134        $this->account = $account;
135
136        return $this;
137    }
138
139    /**
140     * Set unit ids
141     *
142     * @param array $units Unit ids
143     *
144     * @return self
145     *
146     * @since 1.0.0
147     */
148    public function units(array $units) : self
149    {
150        $this->units = $units;
151
152        return $this;
153    }
154
155    /**
156     * Set app ids
157     *
158     * @param array $apps App ids
159     *
160     * @return self
161     *
162     * @since 1.0.0
163     */
164    public function apps(array $apps) : self
165    {
166        $this->apps = $apps;
167
168        return $this;
169    }
170
171    /**
172     * Set category ids
173     *
174     * @param array $categories Category ids
175     *
176     * @return self
177     *
178     * @since 1.0.0
179     */
180    public function categories(array $categories) : self
181    {
182        $this->categories = $categories;
183
184        return $this;
185    }
186
187    /**
188     * Set module ids
189     *
190     * @param array $modules Module ids
191     *
192     * @return self
193     *
194     * @since 1.0.0
195     */
196    public function modules(array $modules) : self
197    {
198        $this->modules = $modules;
199
200        return $this;
201    }
202
203    /**
204     * Set permission flags
205     *
206     * @param int $permission Permission flags
207     *
208     * @return self
209     *
210     * @since 1.0.0
211     */
212    public function permission(int $permission) : self
213    {
214        $this->permission = $permission;
215
216        return $this;
217    }
218
219    /**
220     * Create permission sub query for
221     *
222     * The sub query checks permissons only for specific models/db entries.
223     * More general permissions for an entier module etc. are handled differently.
224     * The reason individual models/db entries are handled this way is because this process is very slow and therefore the general check should be done first and only if that doesn't give results this very specifc solution should be used.
225     *
226     * @param string $idField Table column which contains the primary id (this is the field the permission is associated with)
227     *
228     * @return Builder
229     *
230     * @since 1.0.0
231     */
232    public function query(string $idField) : Builder
233    {
234        $where = new Where($this->connection);
235
236        $hasRead       = ($this->permission & PermissionType::READ) === PermissionType::READ;
237        $hasCreate     = ($this->permission & PermissionType::CREATE) === PermissionType::CREATE;
238        $hasModify     = ($this->permission & PermissionType::MODIFY) === PermissionType::MODIFY;
239        $hasDelete     = ($this->permission & PermissionType::DELETE) === PermissionType::DELETE;
240        $hasPermission = ($this->permission & PermissionType::PERMISSION) === PermissionType::PERMISSION;
241
242        // Handle account permissions
243        if (!empty($this->account)) {
244            $accountPermission = new Builder($this->connection);
245            $accountPermission->select('account_permission_element')
246                ->from('account_permission')
247                ->where('account_permission_account', '=', $this->account);
248
249            $subWhere = new Where($this->connection);
250            foreach ($this->units as $unit) {
251                $subWhere->orWhere('account_permission_unit', '=', $unit);
252            }
253
254            $accountPermission->where($subWhere);
255
256            $subWhere = new Where($this->connection);
257            foreach ($this->apps as $app) {
258                $subWhere->orWhere('account_permission_app', '=', $app);
259            }
260
261            $accountPermission->where($subWhere);
262
263            $subWhere = new Where($this->connection);
264            foreach ($this->modules as $module) {
265                $subWhere->orWhere('account_permission_module', '=', $module);
266            }
267
268            $accountPermission->where($subWhere);
269
270            $subWhere = new Where($this->connection);
271            foreach ($this->categories as $category) {
272                $subWhere->orWhere('account_permission_category', '=', $category);
273            }
274
275            $accountPermission->where($subWhere);
276
277            if ($hasRead) {
278                $accountPermission->where('account_permission_hasread', '=', $hasRead);
279            }
280
281            if ($hasCreate) {
282                $accountPermission->where('account_permission_hascreate', '=', $hasCreate);
283            }
284
285            if ($hasModify) {
286                $accountPermission->where('account_permission_hasmodify', '=', $hasModify);
287            }
288
289            if ($hasDelete) {
290                $accountPermission->where('account_permission_hasdelete', '=', $hasDelete);
291            }
292
293            if ($hasPermission) {
294                $accountPermission->where('account_permission_haspermission', '=', $hasPermission);
295            }
296
297            $where->where($idField, 'in', $accountPermission);
298        }
299
300        // Handle group permissions
301        if (!empty($this->groups)) {
302            $groupPermission = new Builder($this->connection);
303            $groupPermission->select('group_permission_element')
304                ->from('group_permission')
305                ->where('group_permission_group', 'IN', $this->groups);
306
307            $subWhere = new Where($this->connection);
308            foreach ($this->units as $unit) {
309                $subWhere->orWhere('group_permission_unit', '=', $unit);
310            }
311
312            $groupPermission->where($subWhere);
313
314            $subWhere = new Where($this->connection);
315            foreach ($this->apps as $app) {
316                $subWhere->orWhere('group_permission_app', '=', $app);
317            }
318
319            $groupPermission->where($subWhere);
320
321            $subWhere = new Where($this->connection);
322            foreach ($this->modules as $module) {
323                $subWhere->orWhere('group_permission_module', '=', $module);
324            }
325
326            $groupPermission->where($subWhere);
327
328            $subWhere = new Where($this->connection);
329            foreach ($this->categories as $category) {
330                $subWhere->orWhere('group_permission_category', '=', $category);
331            }
332
333            $groupPermission->where($subWhere);
334
335            if ($hasRead) {
336                $groupPermission->where('group_permission_hasread', '=', $hasRead);
337            }
338
339            if ($hasCreate) {
340                $groupPermission->where('group_permission_hascreate', '=', $hasCreate);
341            }
342
343            if ($hasModify) {
344                $groupPermission->where('group_permission_hasmodify', '=', $hasModify);
345            }
346
347            if ($hasDelete) {
348                $groupPermission->where('group_permission_hasdelete', '=', $hasDelete);
349            }
350
351            if ($hasPermission) {
352                $groupPermission->where('group_permission_haspermission', '=', $hasPermission);
353            }
354
355            $where->orWhere($idField, 'in', $groupPermission);
356        }
357
358        return $where;
359    }
360}