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

php-casbin / think-authz / 15025178114

14 May 2025 03:45PM UTC coverage: 92.667%. Remained the same
15025178114

push

github

web-flow
fix: delete without condition if cache disabled (#52)

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

139 of 150 relevant lines covered (92.67%)

48.54 hits per line

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

98.95
/src/adapter/DatabaseAdapter.php
1
<?php
2

3
namespace tauthz\adapter;
4

5
use tauthz\model\Rule;
6
use tauthz\cache\CacheHandlerContract;
7
use Casbin\Model\Model;
8
use Casbin\Persist\{Adapter, AdapterHelper, UpdatableAdapter, BatchAdapter, FilteredAdapter};
9
use Casbin\Persist\Adapters\Filter;
10
use Casbin\Exceptions\InvalidFilterTypeException;
11
use tauthz\traits\Configurable;
12
use think\facade\Db;
13

14
/**
15
 * DatabaseAdapter.
16
 *
17
 * @author leeqvip@gmail.com
18
 */
19
class DatabaseAdapter implements Adapter, UpdatableAdapter, BatchAdapter, FilteredAdapter
20
{
21
    use AdapterHelper, Configurable;
22

23
    /**
24
     * @var bool
25
     */
26
    private bool $filtered = false;
27

28
    /**
29
     * Rules model.
30
     *
31
     * @var Rule
32
     */
33
    protected Rule $model;
34

35
    /**
36
     * Cache Handler.
37
     * 
38
     * @var CacheHandlerContract
39
     */
40
    protected CacheHandlerContract $cacheHandler;
41

42
    /**
43
     * the DatabaseAdapter constructor.
44
     *
45
     * @param Rule $model
46
     */
47
    public function __construct(Rule $model)
48
    {
49
        $this->model = $model;
108✔
50

51
        $cacheHandlerClass = $this->config('cache.handler', \tauthz\cache\CacheHandler::class);
108✔
52
        $this->cacheHandler = new $cacheHandlerClass();
108✔
53
    }
54

55
    /**
56
     * Filter the rule.
57
     *
58
     * @param array $rule
59
     * @return array
60
     */
61
    public function filterRule(array $rule): array
62
    {
63
        $rule = array_values($rule);
108✔
64

65
        $i = count($rule) - 1;
108✔
66
        for (; $i >= 0; $i--) {
108✔
67
            if ($rule[$i] != '' && !is_null($rule[$i])) {
108✔
68
                break;
108✔
69
            }
70
        }
71

72
        return array_slice($rule, 0, $i + 1);
108✔
73
    }
74

75
    /**
76
     * savePolicyLine function.
77
     *
78
     * @param string $ptype
79
     * @param array  $rule
80
     *
81
     * @return void
82
     */
83
    public function savePolicyLine(string $ptype, array $rule): void
84
    {
85
        $col['ptype'] = $ptype;
27✔
86
        foreach ($rule as $key => $value) {
27✔
87
            $col['v' . strval($key) . ''] = $value;
27✔
88
        }
89

90
        $this->cacheHandler->cachePolicies($this->model)->insert($col);
27✔
91
    }
92

93
    /**
94
     * loads all policy rules from the storage.
95
     *
96
     * @param Model $model
97
     */
98
    public function loadPolicy(Model $model): void
99
    {
100
        $rows = $this->cacheHandler->cachePolicies($this->model)->field(['ptype', 'v0', 'v1', 'v2', 'v3', 'v4', 'v5'])
108✔
101
            ->select()->toArray();
108✔
102
        foreach ($rows as $row) {
108✔
103
            $this->loadPolicyArray($this->filterRule($row), $model);
108✔
104
        }
105
    }
106

107
    /**
108
     * saves all policy rules to the storage.
109
     *
110
     * @param Model $model
111
     */
112
    public function savePolicy(Model $model): void
113
    {
114
        foreach ($model['p'] as $ptype => $ast) {
9✔
115
            foreach ($ast->policy as $rule) {
9✔
116
                $this->savePolicyLine($ptype, $rule);
9✔
117
            }
118
        }
119

120
        foreach ($model['g'] as $ptype => $ast) {
9✔
121
            foreach ($ast->policy as $rule) {
9✔
122
                $this->savePolicyLine($ptype, $rule);
×
123
            }
124
        }
125
    }
126

127
    /**
128
     * adds a policy rule to the storage.
129
     * This is part of the Auto-Save feature.
130
     *
131
     * @param string $sec
132
     * @param string $ptype
133
     * @param array  $rule
134
     */
135
    public function addPolicy(string $sec, string $ptype, array $rule): void
136
    {
137
        $this->savePolicyLine($ptype, $rule);
18✔
138
    }
139

140
    /**
141
     * Adds a policy rules to the storage.
142
     * This is part of the Auto-Save feature.
143
     *
144
     * @param string $sec
145
     * @param string $ptype
146
     * @param string[][] $rules
147
     */
148
    public function addPolicies(string $sec, string $ptype, array $rules): void
149
    {
150
        $cols = [];
18✔
151
        $i = 0;
18✔
152

153
        foreach ($rules as $rule) {
18✔
154
            $temp['ptype'] = $ptype;
18✔
155
            foreach ($rule as $key => $value) {
18✔
156
                $temp['v' . strval($key)] = $value;
18✔
157
            }
158
            $cols[$i++] = $temp;
18✔
159
            $temp = [];
18✔
160
        }
161

162
        $this->cacheHandler->cachePolicies($this->model)->insertAll($cols);
18✔
163
    }
164

165
    /**
166
     * This is part of the Auto-Save feature.
167
     *
168
     * @param string $sec
169
     * @param string $ptype
170
     * @param array  $rule
171
     */
172
    public function removePolicy(string $sec, string $ptype, array $rule): void
173
    {
174
        $count = 0;
18✔
175

176
        $instance = $this->model->where('ptype', $ptype);
18✔
177

178
        foreach ($rule as $key => $value) {
18✔
179
            $instance->where('v' . strval($key), $value);
18✔
180
        }
181

182
        foreach ($instance->select() as $model) {
18✔
183
            if ($this->cacheHandler->cachePolicies($model)->delete()) {
18✔
184
                ++$count;
18✔
185
            }
186
        }
187
    }
188

189
    /**
190
     * Removes policy rules from the storage.
191
     * This is part of the Auto-Save feature.
192
     *
193
     * @param string $sec
194
     * @param string $ptype
195
     * @param string[][] $rules
196
     */
197
    public function removePolicies(string $sec, string $ptype, array $rules): void
198
    {
199
        Db::transaction(function () use ($sec, $ptype, $rules) {
9✔
200
            foreach ($rules as $rule) {
9✔
201
                $this->removePolicy($sec, $ptype, $rule);
9✔
202
            }
203
        });
9✔
204
    }
205

206
    /**
207
     * @param string      $sec
208
     * @param string      $ptype
209
     * @param int         $fieldIndex
210
     * @param string|null ...$fieldValues
211
     * @return array
212
     * @throws Throwable
213
     */
214
    public function _removeFilteredPolicy(string $sec, string $ptype, int $fieldIndex, ?string ...$fieldValues): array
215
    {
216
        $count = 0;
18✔
217
        $removedRules = [];
18✔
218

219
        $instance = $this->model->where('ptype', $ptype);
18✔
220
        foreach (range(0, 5) as $value) {
18✔
221
            if ($fieldIndex <= $value && $value < $fieldIndex + count($fieldValues)) {
18✔
222
                if ('' != $fieldValues[$value - $fieldIndex]) {
18✔
223
                    $instance->where('v' . strval($value), $fieldValues[$value - $fieldIndex]);
18✔
224
                }
225
            }
226
        }
227

228
        foreach ($instance->select() as $model) {
18✔
229
            $item = $model->hidden(['id', 'ptype'])->toArray();
18✔
230
            $item = $this->filterRule($item);
18✔
231
            $removedRules[] = $item;
18✔
232
            if ($this->cacheHandler->cachePolicies($model)->delete()) {
18✔
233
                ++$count;
18✔
234
            }
235
        }
236

237
        return $removedRules;
18✔
238
    }
239

240
    /**
241
     * RemoveFilteredPolicy removes policy rules that match the filter from the storage.
242
     * This is part of the Auto-Save feature.
243
     *
244
     * @param string      $sec
245
     * @param string      $ptype
246
     * @param int         $fieldIndex
247
     * @param string|null ...$fieldValues
248
     */
249
    public function removeFilteredPolicy(string $sec, string $ptype, int $fieldIndex, ?string ...$fieldValues): void
250
    {
251
        $this->_removeFilteredPolicy($sec, $ptype, $fieldIndex, ...$fieldValues);
9✔
252
    }
253

254
    /**
255
     * Updates a policy rule from storage.
256
     * This is part of the Auto-Save feature.
257
     *
258
     * @param string $sec
259
     * @param string $ptype
260
     * @param string[] $oldRule
261
     * @param string[] $newPolicy
262
     */
263
    public function updatePolicy(string $sec, string $ptype, array $oldRule, array $newPolicy): void
264
    {
265
        $instance = $this->model->where('ptype', $ptype);
18✔
266
        foreach ($oldRule as $key => $value) {
18✔
267
            $instance->where('v' . strval($key), $value);
18✔
268
        }
269
        $instance = $instance->find();
18✔
270

271
        foreach ($newPolicy as $key => $value) {
18✔
272
            $column = 'v' . strval($key);
18✔
273
            $instance->{$column} = $value;
18✔
274
        }
275

276
        $instance->save();
18✔
277
    }
278

279
    /**
280
     * UpdatePolicies updates some policy rules to storage, like db, redis.
281
     *
282
     * @param string $sec
283
     * @param string $ptype
284
     * @param string[][] $oldRules
285
     * @param string[][] $newRules
286
     * @return void
287
     */
288
    public function updatePolicies(string $sec, string $ptype, array $oldRules, array $newRules): void
289
    {
290
        Db::transaction(function () use ($sec, $ptype, $oldRules, $newRules) {
9✔
291
            foreach ($oldRules as $i => $oldRule) {
9✔
292
                $this->updatePolicy($sec, $ptype, $oldRule, $newRules[$i]);
9✔
293
            }
294
        });
9✔
295
    }
296

297
    /**
298
     * UpdateFilteredPolicies deletes old rules and adds new rules.
299
     *
300
     * @param string $sec
301
     * @param string $ptype
302
     * @param array $newPolicies
303
     * @param integer $fieldIndex
304
     * @param string ...$fieldValues
305
     * @return array
306
     */
307
    public function updateFilteredPolicies(string $sec, string $ptype, array $newPolicies, int $fieldIndex, string ...$fieldValues): array
308
    {
309
        $oldRules = [];
9✔
310
        DB::transaction(function () use ($sec, $ptype, $fieldIndex, $fieldValues, $newPolicies, &$oldRules) {
9✔
311
            $oldRules = $this->_removeFilteredPolicy($sec, $ptype, $fieldIndex, ...$fieldValues);
9✔
312
            $this->addPolicies($sec, $ptype, $newPolicies);
9✔
313
        });
9✔
314

315
        return $oldRules;
9✔
316
    }
317

318
    /**
319
     * Returns true if the loaded policy has been filtered.
320
     *
321
     * @return bool
322
     */
323
    public function isFiltered(): bool
324
    {
325
        return $this->filtered;
108✔
326
    }
327

328
    /**
329
     * Sets filtered parameter.
330
     *
331
     * @param bool $filtered
332
     */
333
    public function setFiltered(bool $filtered): void
334
    {
335
        $this->filtered = $filtered;
9✔
336
    }
337

338
    /**
339
     * Loads only policy rules that match the filter.
340
     *
341
     * @param Model $model
342
     * @param mixed $filter
343
     */
344
    public function loadFilteredPolicy(Model $model, $filter): void
345
    {
346
        $instance = $this->model;
9✔
347

348
        if (is_string($filter)) {
9✔
349
            $instance = $instance->whereRaw($filter);
9✔
350
        } elseif ($filter instanceof Filter) {
9✔
351
            foreach ($filter->p as $k => $v) {
9✔
352
                $where[$v] = $filter->g[$k];
9✔
353
                $instance = $instance->where($v, $filter->g[$k]);
9✔
354
            }
355
        } elseif ($filter instanceof \Closure) {
9✔
356
            $instance = $instance->where($filter);
9✔
357
        } else {
358
            throw new InvalidFilterTypeException('invalid filter type');
9✔
359
        }
360
        $rows = $instance->select()->hidden(['id'])->toArray();
9✔
361
        foreach ($rows as $row) {
9✔
362
            $row = array_filter($row, fn ($value) => !is_null($value) && $value !== '');
9✔
363
            $line = implode(', ', array_filter($row, fn ($val) => '' != $val && !is_null($val)));
9✔
364

365
            $this->loadPolicyLine(trim($line), $model);
9✔
366
        }
367

368
        $this->setFiltered(true);
9✔
369
    }
370
}
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

© 2026 Coveralls, Inc