注意修改命名空间
<?php
declare(strict_types=1);
namespace Eason\Casbin\Adapter;
use Casbin\Model\Model;
use Casbin\Persist\Adapter;
use Casbin\Persist\AdapterHelper;
use Casbin\Persist\UpdatableAdapter;
use Casbin\Persist\BatchAdapter;
use Casbin\Persist\FilteredAdapter;
use Casbin\Persist\Adapters\Filter;
use Casbin\Exceptions\InvalidFilterTypeException;
use Illuminate\Support\Facades\DB;
use Eason\Casbin\Model\RuleModel as Rule;
/**
* DatabaseAdapter.
*
* @author techlee@qq.com
*/
class DatabaseAdapter implements Adapter, UpdatableAdapter, BatchAdapter, FilteredAdapter
{
use AdapterHelper;
/**
* @var bool
*/
private $filtered = false;
/**
* RuleModel model.
*
* @var RuleModel
*/
protected $model;
/**
* the DatabaseAdapter constructor.
*
* @param RuleModel $model
*/
public function __construct(RuleModel $model)
{
$this->model = $model;
}
/**
* savePolicyLine function.
*
* @param string $ptype
* @param array $rule
*
* @return void
*/
public function savePolicyLine($ptype, array $rule)
{
$col['ptype'] = $ptype;
foreach ($rule as $key => $value) {
$col['v' . strval($key) . ''] = $value;
}
$this->model->create($col);
}
/**
* loads all policy rules from the storage.
*
* @param Model $model
*/
public function loadPolicy(Model $model): void
{
$rows = $this->model->getAllFromCache();
foreach ($rows as $row) {
$line = implode(', ', array_filter(array_slice($row, 1), function ($val) {
return '' != $val && !is_null($val);
}));
$this->loadPolicyLine(trim($line), $model);
}
}
/**
* saves all policy rules to the storage.
*
* @param Model $model
*/
public function savePolicy(Model $model): void
{
foreach ($model['p'] as $ptype => $ast) {
foreach ($ast->policy as $rule) {
$this->savePolicyLine($ptype, $rule);
}
}
foreach ($model['g'] as $ptype => $ast) {
foreach ($ast->policy as $rule) {
$this->savePolicyLine($ptype, $rule);
}
}
}
/**
* adds a policy rule to the storage.
* This is part of the Auto-Save feature.
*
* @param string $sec
* @param string $ptype
* @param array $rule
*/
public function addPolicy(string $sec, string $ptype, array $rule): void
{
$this->savePolicyLine($ptype, $rule);
}
/**
* Adds a policy rules to the storage.
* This is part of the Auto-Save feature.
*
* @param string $sec
* @param string $ptype
* @param string[][] $rules
*/
public function addPolicies(string $sec, string $ptype, array $rules): void
{
$cols = [];
$i = 0;
foreach ($rules as $rule) {
$temp['ptype'] = $ptype;
$temp['created_at'] = date("Y-m-d h:m:i");
$temp['updated_at'] = $temp['created_at'];
foreach ($rule as $key => $value) {
$temp['v' . strval($key)] = $value;
}
$cols[$i++] = $temp ?? [];
$temp = [];
}
$this->model->insert($cols);
Rule::fireModelEvent('saved');
}
/**
* This is part of the Auto-Save feature.
*
* @param string $sec
* @param string $ptype
* @param array $rule
*/
public function removePolicy(string $sec, string $ptype, array $rule): void
{
$count = 0;
$instance = $this->model->where('ptype', $ptype);
foreach ($rule as $key => $value) {
$instance->where('v' . strval($key), $value);
}
$instance->delete();
Rule::fireModelEvent('deleted');
// foreach ($instance->select() as $model) {
// if ($model->delete()) {
// ++$count;
// }
// }
}
/**
* Removes policy rules from the storage.
* This is part of the Auto-Save feature.
*
* @param string $sec
* @param string $ptype
* @param string[][] $rules
*/
public function removePolicies(string $sec, string $ptype, array $rules): void
{
DB::transaction(function () use ($sec, $ptype, $rules) {
foreach ($rules as $rule) {
$this->removePolicy($sec, $ptype, $rule);
}
});
}
/**
* RemoveFilteredPolicy removes policy rules that match the filter from the storage.
* This is part of the Auto-Save feature.
*
* @param string $sec
* @param string $ptype
* @param int $fieldIndex
* @param string ...$fieldValues
*/
public function removeFilteredPolicy(string $sec, string $ptype, int $fieldIndex, string ...$fieldValues): void
{
$count = 0;
$instance = $this->model->where('ptype', $ptype);
foreach (range(0, 5) as $value) {
if ($fieldIndex <= $value && $value < $fieldIndex + count($fieldValues)) {
if ('' != $fieldValues[$value - $fieldIndex]) {
$instance->where('v' . strval($value), $fieldValues[$value - $fieldIndex]);
}
}
}
$oldP = $instance->get()->makeHidden(['created_at','updated_at', 'id', 'ptype'])->toArray();
foreach ($oldP as &$item) {
$item = $this->filterRule($item);
$removedRules[] = $item;
}
$instance->delete();
Rule::fireModelEvent('deleted');
// foreach ($instance->select() as $model) {
// if ($model->delete()) {
// ++$count;
// }
// }
}
/**
* Updates a policy rule from storage.
* This is part of the Auto-Save feature.
*
* @param string $sec
* @param string $ptype
* @param string[] $oldRule
* @param string[] $newPolicy
*/
public function updatePolicy(string $sec, string $ptype, array $oldRule, array $newPolicy): void
{
$instance = $this->model->where('ptype', $ptype);
foreach ($oldRule as $key => $value) {
$instance->where('v' . strval($key), $value);
}
$instance = $instance->first();
$update = [];
foreach ($newPolicy as $key => $value) {
$update['v' . $key] = $value;
}
$instance->update($update);
Rule::fireModelEvent('saved');
}
/**
* UpdatePolicies updates some policy rules to storage, like DB, redis.
*
* @param string $sec
* @param string $ptype
* @param string[][] $oldRules
* @param string[][] $newRules
* @return void
*/
public function updatePolicies(string $sec, string $ptype, array $oldRules, array $newRules): void
{
DB::transaction(function () use ($sec, $ptype, $oldRules, $newRules) {
foreach ($oldRules as $i => $oldRule) {
$this->updatePolicy($sec, $ptype, $oldRule, $newRules[$i]);
}
});
}
/**
* UpdateFilteredPolicies deletes old rules and adds new rules.
*
* @param string $sec
* @param string $ptype
* @param array $newPolicies
* @param integer $fieldIndex
* @param string ...$fieldValues
* @return array
*/
public function updateFilteredPolicies(string $sec, string $ptype, array $newPolicies, int $fieldIndex, string ...$fieldValues): array
{
$oldRules = [];
\Illuminate\Support\Facades\DB::transaction(function () use ($sec, $ptype, $fieldIndex, $fieldValues, $newPolicies, &$oldRules) {
$oldRules = $this->_removeFilteredPolicy($sec, $ptype, $fieldIndex, ...$fieldValues);
$this->addPolicies($sec, $ptype, $newPolicies);
});
return $oldRules;
}
/**
* Returns true if the loaded policy has been filtered.
*
* @return bool
*/
public function isFiltered(): bool
{
return $this->filtered;
}
/**
* Sets filtered parameter.
*
* @param bool $filtered
*/
public function setFiltered(bool $filtered): void
{
$this->filtered = $filtered;
}
/**
* Loads only policy rules that match the filter.
*
* @param Model $model
* @param mixed $filter
*/
public function loadFilteredPolicy(Model $model, $filter): void
{
$instance = $this->model;
if (is_string($filter)) {
$instance = $instance->whereRaw($filter);
} elseif ($filter instanceof Filter) {
foreach ($filter->p as $k => $v) {
$where[$v] = $filter->g[$k];
$instance = $instance->where($v, $filter->g[$k]);
}
} elseif ($filter instanceof \Closure) {
$instance = $instance->where($filter);
} else {
throw new InvalidFilterTypeException('invalid filter type');
}
$rows = $instance->get()->makeHidden(['created_at','updated_at', 'id'])->toArray();
foreach ($rows as $row) {
// $row = array_filter($row, function ($value) {
// return !is_null($value) && $value !== '';
// });
// $line = implode(', ', array_filter($row, function ($val) {
// return '' != $val && !is_null($val);
// }));
$row = array_filter($row, function($value) { return !is_null($value) && $value !== ''; });
$line = implode(', ', array_filter($row, function ($val) {
return '' != $val && !is_null($val);
}));
$this->loadPolicyLine(trim($line), $model);
}
$this->setFiltered(true);
}
}
<?php
declare(strict_types=1);
namespace Eason\Casbin\Model;
use Illuminate\Database\Eloquent\Model;
/**
* RuleModel Model
*/
class RuleModel extends Model
{
/**
* a cache store.
*
* @var \Illuminate\Cache\Repository
*/
protected $store;
/**
* Fillable.
*
* @var array
*/
protected $fillable = ['ptype', 'v0', 'v1', 'v2', 'v3', 'v4', 'v5'];
/**
* the guard for lauthz.
*
* @var string
*/
protected $guard;
/**
* 架构函数
* @access public
* @param array $data 数据
*/
public function __construct($data = [])
{
$connection = $this->config('database.connection') ?: config('database.default');
$this->setConnection($connection);
$this->setTable($this->config('database.rules_table'));
parent::__construct($data);
}
/**
* Gets config value by key.
*
* @param string $key
* @param string $default
*
* @return mixed
*/
protected function config(string $key = null, $default = null)
{
$driver = config('plugin.eason.casbin.permission.default');
return config('plugin.eason.casbin.permission.' . $driver . '.' . $key, $default);
}
/**
* Gets rules from caches.
*
* @return mixed
*/
public function getAllFromCache()
{
$get = function () {
return $this->select('ptype', 'v0', 'v1', 'v2', 'v3', 'v4', 'v5')->get()->toArray();
};
if (!$this->config('cache.enabled', false)) {
return $get();
}
return $this->store->remember($this->config('cache.key'), $this->config('cache.ttl'), $get);
}
}
赞
RuleModel模型里可以加上 public $timestamps = false; 要不然就要在数据库添加两个时间字段
已添加