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

php-casbin / laravel-authz / 12480906032

24 Dec 2024 11:09AM UTC coverage: 99.248% (-0.03%) from 99.275%
12480906032

push

github

leeqvip
docs: add gate usage

264 of 266 relevant lines covered (99.25%)

80.35 hits per line

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

97.89
/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

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

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

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

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

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

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

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

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

82
        $this->eloquent->create($col);
78✔
83
    }
84

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

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

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

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

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

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

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

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

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

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

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

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

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

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

225
        return $removedRules;
18✔
226
    }
227

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

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

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

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

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

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

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

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

350
    /**
351
     * Sets filtered parameter.
352
     *
353
     * @param bool $filtered
354
     */
355
    public function setFiltered(bool $filtered): void
356
    {
357
        $this->filtered = $filtered;
6✔
358
    }
359
}
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