• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

php-casbin / laravel-authz / 11578530306

29 Oct 2024 04:42PM UTC coverage: 99.275% (-0.4%) from 99.681%
11578530306

push

github

leeqvip
BREAKING CHANGE: upgrade to PHP 8.0 and PHP-Casbin 4.0 (#75)

BREAKING CHANGE: upgrade to PHP 8.0 and PHP-Casbin 4.0 (#75)

3 of 3 new or added lines in 1 file covered. (100.0%)

1 existing line in 1 file now uncovered.

274 of 276 relevant lines covered (99.28%)

69.95 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

97.94
/src/Adapters/DatabaseAdapter.php
1
<?php
2

3
declare(strict_types=1);
4

5
namespace Lauthz\Adapters;
6

7
use Lauthz\Models\Rule;
8
use Lauthz\Contracts\DatabaseAdapter as DatabaseAdapterContract;
9
use Lauthz\Contracts\BatchDatabaseAdapter as BatchDatabaseAdapterContract;
10
use Lauthz\Contracts\UpdatableDatabaseAdapter as UpdatableDatabaseAdapterContract;
11
use Lauthz\Contracts\FilteredDatabaseAdapter as FilteredDatabaseAdapterContract;
12
use Casbin\Persist\Adapters\Filter;
13
use Casbin\Model\Model;
14
use Casbin\Persist\AdapterHelper;
15
use DateTime;
16
use Casbin\Exceptions\InvalidFilterTypeException;
17
use Illuminate\Support\Facades\DB;
18

19
/**
20
 * DatabaseAdapter.
21
 *
22
 * @author techlee@qq.com
23
 */
24
class DatabaseAdapter implements DatabaseAdapterContract, BatchDatabaseAdapterContract, UpdatableDatabaseAdapterContract, FilteredDatabaseAdapterContract
25
{
26
    use AdapterHelper;
27

28
    /**
29
     * @var bool
30
     */
31
    private $filtered = false;
32

33
    /**
34
     * Rules eloquent model.
35
     *
36
     * @var Rule
37
     */
38
    protected $eloquent;
39

40
    /**
41
     * the DatabaseAdapter constructor.
42
     *
43
     * @param Rule $eloquent
44
     */
45
    public function __construct(Rule $eloquent)
46
    {
47
        $this->eloquent = $eloquent;
150✔
48
    }
49

50
    /**
51
     * Filter the rule.
52
     *
53
     * @param array $rule
54
     * @return array
55
     */
56
    public function filterRule(array $rule): array
57
    {
58
        $rule = array_values($rule);
150✔
59

60
        $i = count($rule) - 1;
150✔
61
        for (; $i >= 0; $i--) {
150✔
62
            if ($rule[$i] != '' && !is_null($rule[$i])) {
150✔
63
                break;
150✔
64
            }
65
        }
66

67
        return array_slice($rule, 0, $i + 1);
150✔
68
    }
69

70
    /**
71
     * savePolicyLine function.
72
     *
73
     * @param string $ptype
74
     * @param array  $rule
75
     */
76
    public function savePolicyLine(string $ptype, array $rule): void
77
    {
78
        $col['ptype'] = $ptype;
65✔
79
        foreach ($rule as $key => $value) {
65✔
80
            $col['v'.strval($key)] = $value;
65✔
81
        }
82

83
        $this->eloquent->create($col);
65✔
84
    }
85

86
    /**
87
     * loads all policy rules from the storage.
88
     *
89
     * @param Model $model
90
     */
91
    public function loadPolicy(Model $model): void
92
    {
93
        $rows = $this->eloquent->getAllFromCache();
150✔
94

95
        foreach ($rows as $row) {
150✔
96
            $this->loadPolicyArray($this->filterRule($row), $model);
150✔
97
        }
98
    }
99

100
    /**
101
     * saves all policy rules to the storage.
102
     *
103
     * @param Model $model
104
     */
105
    public function savePolicy(Model $model): void
106
    {
107
        foreach ($model['p'] as $ptype => $ast) {
10✔
108
            foreach ($ast->policy as $rule) {
10✔
109
                $this->savePolicyLine($ptype, $rule);
10✔
110
            }
111
        }
112

113
        foreach ($model['g'] as $ptype => $ast) {
10✔
114
            foreach ($ast->policy as $rule) {
10✔
UNCOV
115
                $this->savePolicyLine($ptype, $rule);
×
116
            }
117
        }
118
    }
119

120
    /**
121
     * adds a policy rule to the storage.
122
     * This is part of the Auto-Save feature.
123
     *
124
     * @param string $sec
125
     * @param string $ptype
126
     * @param array  $rule
127
     */
128
    public function addPolicy(string $sec, string $ptype, array $rule): void
129
    {
130
        $this->savePolicyLine($ptype, $rule);
55✔
131
    }
132

133
     /**
134
     * Adds a policy rules to the storage.
135
     * This is part of the Auto-Save feature.
136
     *
137
     * @param string $sec
138
     * @param string $ptype
139
     * @param string[][] $rules
140
     */
141
    public function addPolicies(string $sec, string $ptype, array $rules): void
142
    {
143
        $cols = [];
15✔
144
        $i = 0;
15✔
145

146
        foreach($rules as $rule) {
15✔
147
            $temp['ptype'] = $ptype;
15✔
148
            $temp['created_at'] = new DateTime();
15✔
149
            $temp['updated_at'] = $temp['created_at'];
15✔
150
            foreach ($rule as $key => $value) {
15✔
151
                $temp['v'.strval($key)] = $value;
15✔
152
            }
153
            $cols[$i++] = $temp ?? [];
15✔
154
            $temp = [];
15✔
155
        }
156
        $this->eloquent->insert($cols);
15✔
157
        Rule::fireModelEvent('saved');
15✔
158
    }
159

160
    /**
161
     * This is part of the Auto-Save feature.
162
     *
163
     * @param string $sec
164
     * @param string $ptype
165
     * @param array  $rule
166
     */
167
    public function removePolicy(string $sec, string $ptype, array $rule): void
168
    {
169
        $instance = $this->eloquent->where('ptype', $ptype);
20✔
170

171
        foreach ($rule as $key => $value) {
20✔
172
            $instance->where('v'.strval($key), $value);
20✔
173
        }
174

175
        $instance->delete();
20✔
176
        Rule::fireModelEvent('deleted');
20✔
177
    }
178

179
    /**
180
     * Removes policy rules from the storage.
181
     * This is part of the Auto-Save feature.
182
     *
183
     * @param string $sec
184
     * @param string $ptype
185
     * @param string[][] $rules
186
     */
187
    public function removePolicies(string $sec, string $ptype, array $rules): void
188
    {
189
        $this->eloquent->getConnection()->transaction(function () use ($sec, $rules, $ptype) {
10✔
190
            foreach ($rules as $rule) {
10✔
191
                $this->removePolicy($sec, $ptype, $rule);
10✔
192
            }
193
        });
10✔
194
    }
195

196
    /**
197
     * @param string      $sec
198
     * @param string      $ptype
199
     * @param int         $fieldIndex
200
     * @param string|null ...$fieldValues
201
     * @return array
202
     * @throws Throwable
203
     */
204
    public function _removeFilteredPolicy(string $sec, string $ptype, int $fieldIndex, ?string ...$fieldValues): array
205
    {
206
        $removedRules = [];
15✔
207
        $instance = $this->eloquent->where('ptype', $ptype);
15✔
208
        
209
        foreach (range(0, 5) as $value) {
15✔
210
            if ($fieldIndex <= $value && $value < $fieldIndex + count($fieldValues)) {
15✔
211
                if ('' != $fieldValues[$value - $fieldIndex]) {
15✔
212
                    $instance->where('v' . strval($value), $fieldValues[$value - $fieldIndex]);
15✔
213
                }
214
            }
215
        }
216

217
        $oldP = $instance->get()->makeHidden(['created_at','updated_at', 'id', 'ptype'])->toArray();
15✔
218
        foreach ($oldP as &$item) {
15✔
219
            $item = $this->filterRule($item);
15✔
220
            $removedRules[] = $item;
15✔
221
        }
222

223
        $instance->delete();
15✔
224
        Rule::fireModelEvent('deleted');
15✔
225

226
        return $removedRules;
15✔
227
    }
228

229
    /**
230
     * RemoveFilteredPolicy removes policy rules that match the filter from the storage.
231
     * This is part of the Auto-Save feature.
232
     *
233
     * @param string      $sec
234
     * @param string      $ptype
235
     * @param int         $fieldIndex
236
     * @param string|null ...$fieldValues
237
     * @return void
238
     */
239
    public function removeFilteredPolicy(string $sec, string $ptype, int $fieldIndex, ?string ...$fieldValues): void
240
    {
241
        $this->_removeFilteredPolicy($sec, $ptype, $fieldIndex, ...$fieldValues);
10✔
242
    }
243

244
    /**
245
     * Updates a policy rule from storage.
246
     * This is part of the Auto-Save feature.
247
     *
248
     * @param string $sec
249
     * @param string $ptype
250
     * @param string[] $oldRule
251
     * @param string[] $newPolicy
252
     */
253
    public function updatePolicy(string $sec, string $ptype, array $oldRule, array $newPolicy): void
254
    {
255
        $instance = $this->eloquent->where('ptype', $ptype);
15✔
256
        foreach($oldRule as $k => $v) {
15✔
257
            $instance->where('v' . $k, $v);
15✔
258
        }
259
        $instance = $instance->first();
15✔
260
        if (!$instance) {
15✔
261
            return;
×
262
        }
263

264
        $update = [];
15✔
265
        foreach($newPolicy as $k => $v) {
15✔
266
            $update['v' . $k] = $v;
15✔
267
        }
268
        $instance->update($update);
15✔
269
        Rule::fireModelEvent('saved');
15✔
270
    }
271

272
    /**
273
     * UpdatePolicies updates some policy rules to storage, like db, redis.
274
     *
275
     * @param string $sec
276
     * @param string $ptype
277
     * @param string[][] $oldRules
278
     * @param string[][] $newRules
279
     * @return void
280
     */
281
    public function updatePolicies(string $sec, string $ptype, array $oldRules, array $newRules): void
282
    {
283
        $this->eloquent->getConnection()->transaction(function () use ($sec, $ptype, $oldRules, $newRules) {
5✔
284
            foreach ($oldRules as $i => $oldRule) {
5✔
285
                $this->updatePolicy($sec, $ptype, $oldRule, $newRules[$i]);
5✔
286
            }
287
        });
5✔
288
    }
289

290
    /**
291
     * UpdateFilteredPolicies deletes old rules and adds new rules.
292
     *
293
     * @param string $sec
294
     * @param string $ptype
295
     * @param array $newPolicies
296
     * @param integer $fieldIndex
297
     * @param string ...$fieldValues
298
     * @return array
299
     */
300
    public function updateFilteredPolicies(string $sec, string $ptype, array $newPolicies, int $fieldIndex, string ...$fieldValues): array
301
    {
302
        $oldRules = [];
5✔
303
        $this->eloquent->getConnection()->transaction(function () use ($sec, $ptype, $fieldIndex, $fieldValues, $newPolicies, &$oldRules) {
5✔
304
            $oldRules = $this->_removeFilteredPolicy($sec, $ptype, $fieldIndex, ...$fieldValues);
5✔
305
            $this->addPolicies($sec, $ptype, $newPolicies);
5✔
306
        });
5✔
307
        return $oldRules;
5✔
308
    }
309

310
    /**
311
     * Loads only policy rules that match the filter.
312
     *
313
     * @param Model $model
314
     * @param mixed $filter
315
     */
316
    public function loadFilteredPolicy(Model $model, $filter): void
317
    {
318
        $instance = $this->eloquent;
5✔
319

320
        if (is_string($filter)) {
5✔
321
            $instance = $instance->whereRaw($filter);
5✔
322
        } else if ($filter instanceof Filter) {
5✔
323
            foreach($filter->p as $k => $v) {
5✔
324
                $where[$v] = $filter->g[$k];
5✔
325
                $instance = $instance->where($v, $filter->g[$k]);
5✔
326
            }
327
        } else if ($filter instanceof \Closure) {
5✔
328
            $instance = $instance->where($filter);
5✔
329
        } else {
330
            throw new InvalidFilterTypeException('invalid filter type');
5✔
331
        }
332
        $rows = $instance->get()->makeHidden(['created_at','updated_at', 'id'])->toArray();
5✔
333
        foreach ($rows as $row) {
5✔
334
            $row = array_filter($row, function($value) { return !is_null($value) && $value !== ''; });
5✔
335
            $line = implode(', ', array_filter($row, function ($val) {
5✔
336
                return '' != $val && !is_null($val);
5✔
337
            }));
5✔
338
            $this->loadPolicyLine(trim($line), $model);
5✔
339
        }
340
        $this->setFiltered(true);
5✔
341
    }
342

343
    /**
344
     * Returns true if the loaded policy has been filtered.
345
     *
346
     * @return bool
347
     */
348
    public function isFiltered(): bool
349
    {
350
        return $this->filtered;
150✔
351
    }
352

353
    /**
354
     * Sets filtered parameter.
355
     *
356
     * @param bool $filtered
357
     */
358
    public function setFiltered(bool $filtered): void
359
    {
360
        $this->filtered = $filtered;
5✔
361
    }
362
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc