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

php-casbin / think-authz / 6544700676

17 Oct 2023 08:40AM UTC coverage: 93.902% (+1.2%) from 92.683%
6544700676

push

github

web-flow
Merge pull request #44 from php-casbin/develop

Develop

154 of 164 relevant lines covered (93.9%)

16.69 hits per line

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

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

3
namespace tauthz\adapter;
4

5
use tauthz\model\Rule;
6
use Casbin\Model\Model;
7
use Casbin\Persist\Adapter;
8
use Casbin\Persist\AdapterHelper;
9
use Casbin\Persist\UpdatableAdapter;
10
use Casbin\Persist\BatchAdapter;
11
use Casbin\Persist\FilteredAdapter;
12
use Casbin\Persist\Adapters\Filter;
13
use Casbin\Exceptions\InvalidFilterTypeException;
14
use think\facade\Db;
15

16
/**
17
 * DatabaseAdapter.
18
 *
19
 * @author techlee@qq.com
20
 */
21
class DatabaseAdapter implements Adapter, UpdatableAdapter, BatchAdapter, FilteredAdapter
22
{
23
    use AdapterHelper;
24

25
    /**
26
     * @var bool
27
     */
28
    private $filtered = false;
29

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

37
    /**
38
     * the DatabaseAdapter constructor.
39
     *
40
     * @param Rule $model
41
     */
42
    public function __construct(Rule $model)
43
    {
44
        $this->model = $model;
44✔
45
    }
11✔
46

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

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

64
        return array_slice($rule, 0, $i + 1);
44✔
65
    }
66

67
    /**
68
     * savePolicyLine function.
69
     *
70
     * @param string $ptype
71
     * @param array  $rule
72
     *
73
     * @return void
74
     */
75
    public function savePolicyLine($ptype, array $rule)
76
    {
77
        $col['ptype'] = $ptype;
12✔
78
        foreach ($rule as $key => $value) {
12✔
79
            $col['v'.strval($key).''] = $value;
12✔
80
        }
81
        $this->model->cache('tauthz')->insert($col);
12✔
82
    }
3✔
83

84
    /**
85
     * loads all policy rules from the storage.
86
     *
87
     * @param Model $model
88
     */
89
    public function loadPolicy(Model $model): void
90
    {
91
        $rows = $this->model->cache('tauthz')->field(['ptype', 'v0', 'v1', 'v2', 'v3', 'v4', 'v5'])->select()->toArray();
44✔
92
        foreach ($rows as $row) {
44✔
93
            $this->loadPolicyArray($this->filterRule($row), $model);
44✔
94
        }
95
    }
11✔
96

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

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

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

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

143
        foreach ($rules as $rule) {
8✔
144
            $temp['ptype'] = $ptype;
8✔
145
            foreach ($rule as $key => $value) {
8✔
146
                $temp['v' . strval($key)] = $value;
8✔
147
            }
148
            $cols[$i++] = $temp;
8✔
149
            $temp = [];
8✔
150
        }
151
        $this->model->cache('tauthz')->insertAll($cols);
8✔
152
    }
2✔
153

154
    /**
155
     * This is part of the Auto-Save feature.
156
     *
157
     * @param string $sec
158
     * @param string $ptype
159
     * @param array  $rule
160
     */
161
    public function removePolicy(string $sec, string $ptype, array $rule): void
162
    {
163
        $count = 0;
8✔
164

165
        $instance = $this->model->where('ptype', $ptype);
8✔
166

167
        foreach ($rule as $key => $value) {
8✔
168
            $instance->where('v'.strval($key), $value);
8✔
169
        }
170

171
        foreach ($instance->select() as $model) {
8✔
172
            if ($model->cache('tauthz')->delete()) {
8✔
173
                ++$count;
8✔
174
            }
175
        }
176
    }
2✔
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
        Db::transaction(function () use ($sec, $ptype, $rules) {
3✔
189
            foreach ($rules as $rule) {
4✔
190
                $this->removePolicy($sec, $ptype, $rule);
4✔
191
            }
192
        });
4✔
193
    }
1✔
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
        $count = 0;
8✔
206
        $removedRules = [];
8✔
207

208
        $instance = $this->model->where('ptype', $ptype);
8✔
209
        foreach (range(0, 5) as $value) {
8✔
210
            if ($fieldIndex <= $value && $value < $fieldIndex + count($fieldValues)) {
8✔
211
                if ('' != $fieldValues[$value - $fieldIndex]) {
8✔
212
                    $instance->where('v' . strval($value), $fieldValues[$value - $fieldIndex]);
8✔
213
                }
214
            }
215
        }
216

217
        foreach ($instance->select() as $model) {
8✔
218
            $item = $model->hidden(['id', 'ptype'])->toArray();
8✔
219
            $item = $this->filterRule($item);
8✔
220
            $removedRules[] = $item;
8✔
221
            if ($model->cache('tauthz')->delete()) {
8✔
222
                ++$count;
8✔
223
            }
224
        }
225
        
226
        return $removedRules;
8✔
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
     */
238
    public function removeFilteredPolicy(string $sec, string $ptype, int $fieldIndex, ?string ...$fieldValues): void
239
    {
240
        $this->_removeFilteredPolicy($sec, $ptype, $fieldIndex, ...$fieldValues);
4✔
241
    }
1✔
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->model->where('ptype', $ptype);
8✔
255
        foreach ($oldRule as $key => $value) {
8✔
256
            $instance->where('v' . strval($key), $value);
8✔
257
        }
258
        $instance = $instance->find();
8✔
259

260
        foreach ($newPolicy as $key => $value) {
8✔
261
            $column = 'v' . strval($key);
8✔
262
            $instance->$column = $value;
8✔
263
        }
264

265
        $instance->save();
8✔
266
    }
2✔
267

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

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

304
        return $oldRules;
4✔
305
    }
306

307
    /**
308
     * Returns true if the loaded policy has been filtered.
309
     *
310
     * @return bool
311
     */
312
    public function isFiltered(): bool
313
    {
314
        return $this->filtered;
44✔
315
    }
316

317
    /**
318
     * Sets filtered parameter.
319
     *
320
     * @param bool $filtered
321
     */
322
    public function setFiltered(bool $filtered): void
323
    {
324
        $this->filtered = $filtered;
4✔
325
    }
1✔
326

327
    /**
328
     * Loads only policy rules that match the filter.
329
     *
330
     * @param Model $model
331
     * @param mixed $filter
332
     */
333
    public function loadFilteredPolicy(Model $model, $filter): void
334
    {
335
        $instance = $this->model;
4✔
336

337
        if (is_string($filter)) {
4✔
338
            $instance = $instance->whereRaw($filter);
4✔
339
        } elseif ($filter instanceof Filter) {
4✔
340
            foreach ($filter->p as $k => $v) {
4✔
341
                $where[$v] = $filter->g[$k];
4✔
342
                $instance = $instance->where($v, $filter->g[$k]);
4✔
343
            }
344
        } elseif ($filter instanceof \Closure) {
4✔
345
            $instance = $instance->where($filter);
4✔
346
        } else {
347
            throw new InvalidFilterTypeException('invalid filter type');
4✔
348
        }
349
        $rows = $instance->select()->hidden(['id'])->toArray();
4✔
350
        foreach ($rows as $row) {
4✔
351
            $row = array_filter($row, function ($value) {
3✔
352
                return !is_null($value) && $value !== '';
4✔
353
            });
4✔
354
            $line = implode(', ', array_filter($row, function ($val) {
3✔
355
                return '' != $val && !is_null($val);
4✔
356
            }));
4✔
357
            $this->loadPolicyLine(trim($line), $model);
4✔
358
        }
359
        $this->setFiltered(true);
4✔
360
    }
1✔
361
}
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