Skip to content

Commit c7acd66

Browse files
committed
illuminate/database
1 parent 07fe86b commit c7acd66

File tree

4 files changed

+416
-1
lines changed

4 files changed

+416
-1
lines changed

composer.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@
4040
"require-dev": {
4141
"phpunit/phpunit": "~7.0|~8.0|~9.0",
4242
"php-coveralls/php-coveralls": "^2.1",
43-
"workerman/webman": "^1.0"
43+
"workerman/webman": "^1.0",
44+
"illuminate/database": "^8.83",
45+
"illuminate/cache": "^8.83"
4446
}
4547
}
Lines changed: 327 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,327 @@
1+
<?php
2+
3+
/**
4+
* @desc Policy Adapter
5+
* @author Tinywan(ShaoBo Wan)
6+
* @date 2022/01/12 10:37
7+
*/
8+
9+
declare(strict_types=1);
10+
11+
namespace Casbin\WebmanPermission\Adapter;
12+
13+
use Casbin\Model\Model;
14+
use Casbin\Persist\Adapter;
15+
use Casbin\Persist\AdapterHelper;
16+
use Casbin\Persist\UpdatableAdapter;
17+
use Casbin\Persist\BatchAdapter;
18+
use Casbin\Persist\FilteredAdapter;
19+
use Casbin\Persist\Adapters\Filter;
20+
use Casbin\Exceptions\InvalidFilterTypeException;
21+
use Casbin\WebmanPermission\Model\LaravelRuleModel;
22+
use Casbin\WebmanPermission\Model\RuleModel;
23+
use Illuminate\Support\Facades\DB;
24+
25+
/**
26+
* DatabaseAdapter.
27+
*
28+
29+
*/
30+
class LaravelDatabaseAdapter implements Adapter, UpdatableAdapter, BatchAdapter, FilteredAdapter
31+
{
32+
use AdapterHelper;
33+
34+
/**
35+
* @var bool
36+
*/
37+
private bool $filtered = false;
38+
39+
/**
40+
* RuleModel model.
41+
*
42+
* @var LaravelRuleModel
43+
*/
44+
protected $model;
45+
46+
/**
47+
* the DatabaseAdapter constructor.
48+
*
49+
* @param RuleModel $model
50+
*/
51+
public function __construct(RuleModel $model)
52+
{
53+
$this->model = $model;
54+
}
55+
56+
/**
57+
* savePolicyLine function.
58+
*
59+
* @param string $ptype
60+
* @param array $rule
61+
*
62+
* @return void
63+
*/
64+
public function savePolicyLine(string $ptype, array $rule)
65+
{
66+
$col['ptype'] = $ptype;
67+
foreach ($rule as $key => $value) {
68+
$col['v' . strval($key) . ''] = $value;
69+
}
70+
$this->model->create($col);
71+
}
72+
73+
/**
74+
* loads all policy rules from the storage.
75+
*
76+
* @param Model $model
77+
*/
78+
public function loadPolicy(Model $model): void
79+
{
80+
$rows = $this->model->getAllFromCache();
81+
foreach ($rows as $row) {
82+
$line = implode(', ', array_filter(array_slice($row, 1), function ($val) {
83+
return '' != $val && !is_null($val);
84+
}));
85+
$this->loadPolicyLine(trim($line), $model);
86+
}
87+
}
88+
89+
/**
90+
* saves all policy rules to the storage.
91+
*
92+
* @param Model $model
93+
*/
94+
public function savePolicy(Model $model): void
95+
{
96+
foreach ($model['p'] as $ptype => $ast) {
97+
foreach ($ast->policy as $rule) {
98+
$this->savePolicyLine($ptype, $rule);
99+
}
100+
}
101+
102+
foreach ($model['g'] as $ptype => $ast) {
103+
foreach ($ast->policy as $rule) {
104+
$this->savePolicyLine($ptype, $rule);
105+
}
106+
}
107+
}
108+
109+
/**
110+
* adds a policy rule to the storage.
111+
* This is part of the Auto-Save feature.
112+
*
113+
* @param string $sec
114+
* @param string $ptype
115+
* @param array $rule
116+
*/
117+
public function addPolicy(string $sec, string $ptype, array $rule): void
118+
{
119+
$this->savePolicyLine($ptype, $rule);
120+
}
121+
122+
/**
123+
* Adds a policy rules to the storage.
124+
* This is part of the Auto-Save feature.
125+
*
126+
* @param string $sec
127+
* @param string $ptype
128+
* @param string[][] $rules
129+
*/
130+
public function addPolicies(string $sec, string $ptype, array $rules): void
131+
{
132+
$cols = [];
133+
$i = 0;
134+
135+
foreach ($rules as $rule) {
136+
$temp['ptype'] = $ptype;
137+
$temp['created_at'] = date("Y-m-d h:m:i");
138+
$temp['updated_at'] = $temp['created_at'];
139+
foreach ($rule as $key => $value) {
140+
$temp['v' . strval($key)] = $value;
141+
}
142+
$cols[$i++] = $temp ?? [];
143+
$temp = [];
144+
}
145+
$this->model->insert($cols);
146+
LaravelRuleModel::fireModelEvent('saved');
147+
}
148+
149+
/**
150+
* This is part of the Auto-Save feature.
151+
*
152+
* @param string $sec
153+
* @param string $ptype
154+
* @param array $rule
155+
*/
156+
public function removePolicy(string $sec, string $ptype, array $rule): void
157+
{
158+
$instance = $this->model->where('ptype', $ptype);
159+
foreach ($rule as $key => $value) {
160+
$instance->where('v' . strval($key), $value);
161+
}
162+
$instance->delete();
163+
LaravelRuleModel::fireModelEvent('deleted');
164+
}
165+
166+
/**
167+
* Removes policy rules from the storage.
168+
* This is part of the Auto-Save feature.
169+
*
170+
* @param string $sec
171+
* @param string $ptype
172+
* @param string[][] $rules
173+
*/
174+
public function removePolicies(string $sec, string $ptype, array $rules): void
175+
{
176+
DB::transaction(function () use ($sec, $ptype, $rules) {
177+
foreach ($rules as $rule) {
178+
$this->removePolicy($sec, $ptype, $rule);
179+
}
180+
});
181+
}
182+
183+
/**
184+
* RemoveFilteredPolicy removes policy rules that match the filter from the storage.
185+
* This is part of the Auto-Save feature.
186+
*
187+
* @param string $sec
188+
* @param string $ptype
189+
* @param int $fieldIndex
190+
* @param string ...$fieldValues
191+
*/
192+
public function removeFilteredPolicy(string $sec, string $ptype, int $fieldIndex, string ...$fieldValues): void
193+
{
194+
$instance = $this->model->where('ptype', $ptype);
195+
foreach (range(0, 5) as $value) {
196+
if ($fieldIndex <= $value && $value < $fieldIndex + count($fieldValues)) {
197+
if ('' != $fieldValues[$value - $fieldIndex]) {
198+
$instance->where('v' . strval($value), $fieldValues[$value - $fieldIndex]);
199+
}
200+
}
201+
}
202+
203+
$oldP = $instance->get()->makeHidden(['created_at','updated_at', 'id', 'ptype'])->toArray();
204+
foreach ($oldP as &$item) {
205+
$item = $this->filterRule($item);
206+
$removedRules[] = $item;
207+
}
208+
$instance->delete();
209+
LaravelRuleModel::fireModelEvent('deleted');
210+
}
211+
212+
/**
213+
* Updates a policy rule from storage.
214+
* This is part of the Auto-Save feature.
215+
*
216+
* @param string $sec
217+
* @param string $ptype
218+
* @param string[] $oldRule
219+
* @param string[] $newPolicy
220+
*/
221+
public function updatePolicy(string $sec, string $ptype, array $oldRule, array $newPolicy): void
222+
{
223+
$instance = $this->model->where('ptype', $ptype);
224+
foreach ($oldRule as $key => $value) {
225+
$instance->where('v' . strval($key), $value);
226+
}
227+
$instance = $instance->first();
228+
229+
$update = [];
230+
foreach ($newPolicy as $key => $value) {
231+
$update['v' . $key] = $value;
232+
}
233+
234+
$instance->update($update);
235+
LaravelRuleModel::fireModelEvent('saved');
236+
}
237+
238+
/**
239+
* UpdatePolicies updates some policy rules to storage, like DB, redis.
240+
*
241+
* @param string $sec
242+
* @param string $ptype
243+
* @param string[][] $oldRules
244+
* @param string[][] $newRules
245+
* @return void
246+
*/
247+
public function updatePolicies(string $sec, string $ptype, array $oldRules, array $newRules): void
248+
{
249+
DB::transaction(function () use ($sec, $ptype, $oldRules, $newRules) {
250+
foreach ($oldRules as $i => $oldRule) {
251+
$this->updatePolicy($sec, $ptype, $oldRule, $newRules[$i]);
252+
}
253+
});
254+
}
255+
256+
/**
257+
* UpdateFilteredPolicies deletes old rules and adds new rules.
258+
*
259+
* @param string $sec
260+
* @param string $ptype
261+
* @param array $newPolicies
262+
* @param integer $fieldIndex
263+
* @param string ...$fieldValues
264+
* @return array
265+
*/
266+
public function updateFilteredPolicies(string $sec, string $ptype, array $newPolicies, int $fieldIndex, string ...$fieldValues): array
267+
{
268+
$oldRules = [];
269+
\Illuminate\Support\Facades\DB::transaction(function () use ($sec, $ptype, $fieldIndex, $fieldValues, $newPolicies, &$oldRules) {
270+
$oldRules = $this->_removeFilteredPolicy($sec, $ptype, $fieldIndex, ...$fieldValues);
271+
$this->addPolicies($sec, $ptype, $newPolicies);
272+
});
273+
return $oldRules;
274+
}
275+
276+
/**
277+
* Returns true if the loaded policy has been filtered.
278+
*
279+
* @return bool
280+
*/
281+
public function isFiltered(): bool
282+
{
283+
return $this->filtered;
284+
}
285+
286+
/**
287+
* Sets filtered parameter.
288+
*
289+
* @param bool $filtered
290+
*/
291+
public function setFiltered(bool $filtered): void
292+
{
293+
$this->filtered = $filtered;
294+
}
295+
296+
/**
297+
* Loads only policy rules that match the filter.
298+
*
299+
* @param Model $model
300+
* @param mixed $filter
301+
*/
302+
public function loadFilteredPolicy(Model $model, $filter): void
303+
{
304+
$instance = $this->model;
305+
if (is_string($filter)) {
306+
$instance = $instance->whereRaw($filter);
307+
} elseif ($filter instanceof Filter) {
308+
foreach ($filter->p as $k => $v) {
309+
$where[$v] = $filter->g[$k];
310+
$instance = $instance->where($v, $filter->g[$k]);
311+
}
312+
} elseif ($filter instanceof \Closure) {
313+
$instance = $instance->where($filter);
314+
} else {
315+
throw new InvalidFilterTypeException('invalid filter type');
316+
}
317+
$rows = $instance->get()->makeHidden(['created_at','updated_at', 'id'])->toArray();
318+
foreach ($rows as $row) {
319+
$row = array_filter($row, function($value) { return !is_null($value) && $value !== ''; });
320+
$line = implode(', ', array_filter($row, function ($val) {
321+
return '' != $val && !is_null($val);
322+
}));
323+
$this->loadPolicyLine(trim($line), $model);
324+
}
325+
$this->setFiltered(true);
326+
}
327+
}

0 commit comments

Comments
 (0)