Support for multiple enforcers.
This commit is contained in:
parent
4e53d87672
commit
6e69d2b8dd
|
@ -1,171 +1,169 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Lauthz\Adapters;
|
namespace Lauthz\Adapters;
|
||||||
|
|
||||||
use Lauthz\Models\Rule;
|
use Lauthz\Models\Rule;
|
||||||
use Lauthz\Contracts\DatabaseAdapter as DatabaseAdapterContract;
|
use Lauthz\Contracts\DatabaseAdapter as DatabaseAdapterContract;
|
||||||
use Casbin\Persist\AdapterHelper;
|
use Casbin\Persist\AdapterHelper;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DatabaseAdapter.
|
* DatabaseAdapter.
|
||||||
*
|
*
|
||||||
* @author techlee@qq.com
|
* @author techlee@qq.com
|
||||||
*/
|
*/
|
||||||
class DatabaseAdapter implements DatabaseAdapterContract
|
class DatabaseAdapter implements DatabaseAdapterContract
|
||||||
{
|
{
|
||||||
use AdapterHelper;
|
use AdapterHelper;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rules eloquent model.
|
* Rules eloquent model.
|
||||||
*
|
*
|
||||||
* @var Rule
|
* @var Rule
|
||||||
*/
|
*/
|
||||||
protected $eloquent;
|
protected $eloquent;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* the DatabaseAdapter constructor.
|
* the DatabaseAdapter constructor.
|
||||||
*
|
*
|
||||||
* @param Rule $eloquent
|
* @param Rule $eloquent
|
||||||
*/
|
*/
|
||||||
public function __construct(Rule $eloquent)
|
public function __construct(Rule $eloquent)
|
||||||
{
|
{
|
||||||
$this->eloquent = $eloquent;
|
$this->eloquent = $eloquent;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* savePolicyLine function.
|
* savePolicyLine function.
|
||||||
*
|
*
|
||||||
* @param string $ptype
|
* @param string $ptype
|
||||||
* @param array $rule
|
* @param array $rule
|
||||||
*
|
*/
|
||||||
* @return void
|
public function savePolicyLine($ptype, array $rule)
|
||||||
*/
|
{
|
||||||
public function savePolicyLine($ptype, array $rule)
|
$col['ptype'] = $ptype;
|
||||||
{
|
foreach ($rule as $key => $value) {
|
||||||
$col['ptype'] = $ptype;
|
$col['v'.strval($key)] = $value;
|
||||||
foreach ($rule as $key => $value) {
|
}
|
||||||
$col['v'.strval($key)] = $value;
|
|
||||||
}
|
$this->eloquent->create($col);
|
||||||
|
}
|
||||||
$this->eloquent->create($col);
|
|
||||||
}
|
/**
|
||||||
|
* loads all policy rules from the storage.
|
||||||
/**
|
*
|
||||||
* loads all policy rules from the storage.
|
* @param Model $model
|
||||||
*
|
*
|
||||||
* @param Model $model
|
* @return mixed
|
||||||
*
|
*/
|
||||||
* @return mixed
|
public function loadPolicy($model)
|
||||||
*/
|
{
|
||||||
public function loadPolicy($model)
|
$rows = $this->eloquent->getAllFromCache();
|
||||||
{
|
|
||||||
$rows = $this->eloquent->getAllFromCache();
|
foreach ($rows as $row) {
|
||||||
|
$line = implode(', ', array_filter($row, function ($val) {
|
||||||
foreach ($rows as $row) {
|
return '' != $val && !is_null($val);
|
||||||
$line = implode(', ', array_filter($row, function ($val) {
|
}));
|
||||||
return '' != $val && !is_null($val);
|
$this->loadPolicyLine(trim($line), $model);
|
||||||
}));
|
}
|
||||||
$this->loadPolicyLine(trim($line), $model);
|
}
|
||||||
}
|
|
||||||
}
|
/**
|
||||||
|
* saves all policy rules to the storage.
|
||||||
/**
|
*
|
||||||
* saves all policy rules to the storage.
|
* @param Model $model
|
||||||
*
|
*
|
||||||
* @param Model $model
|
* @return bool
|
||||||
*
|
*/
|
||||||
* @return bool
|
public function savePolicy($model)
|
||||||
*/
|
{
|
||||||
public function savePolicy($model)
|
foreach ($model->model['p'] as $ptype => $ast) {
|
||||||
{
|
foreach ($ast->policy as $rule) {
|
||||||
foreach ($model->model['p'] as $ptype => $ast) {
|
$this->savePolicyLine($ptype, $rule);
|
||||||
foreach ($ast->policy as $rule) {
|
}
|
||||||
$this->savePolicyLine($ptype, $rule);
|
}
|
||||||
}
|
|
||||||
}
|
foreach ($model->model['g'] as $ptype => $ast) {
|
||||||
|
foreach ($ast->policy as $rule) {
|
||||||
foreach ($model->model['g'] as $ptype => $ast) {
|
$this->savePolicyLine($ptype, $rule);
|
||||||
foreach ($ast->policy as $rule) {
|
}
|
||||||
$this->savePolicyLine($ptype, $rule);
|
}
|
||||||
}
|
|
||||||
}
|
return true;
|
||||||
|
}
|
||||||
return true;
|
|
||||||
}
|
/**
|
||||||
|
* Adds a policy rule to the storage.
|
||||||
/**
|
* This is part of the Auto-Save feature.
|
||||||
* Adds a policy rule to the storage.
|
*
|
||||||
* This is part of the Auto-Save feature.
|
* @param string $sec
|
||||||
*
|
* @param string $ptype
|
||||||
* @param string $sec
|
* @param array $rule
|
||||||
* @param string $ptype
|
*
|
||||||
* @param array $rule
|
* @return mixed
|
||||||
*
|
*/
|
||||||
* @return mixed
|
public function addPolicy($sec, $ptype, $rule)
|
||||||
*/
|
{
|
||||||
public function addPolicy($sec, $ptype, $rule)
|
return $this->savePolicyLine($ptype, $rule);
|
||||||
{
|
}
|
||||||
return $this->savePolicyLine($ptype, $rule);
|
|
||||||
}
|
/**
|
||||||
|
* This is part of the Auto-Save feature.
|
||||||
/**
|
*
|
||||||
* This is part of the Auto-Save feature.
|
* @param string $sec
|
||||||
*
|
* @param string $ptype
|
||||||
* @param string $sec
|
* @param array $rule
|
||||||
* @param string $ptype
|
*
|
||||||
* @param array $rule
|
* @return mixed
|
||||||
*
|
*/
|
||||||
* @return mixed
|
public function removePolicy($sec, $ptype, $rule)
|
||||||
*/
|
{
|
||||||
public function removePolicy($sec, $ptype, $rule)
|
$count = 0;
|
||||||
{
|
|
||||||
$count = 0;
|
$instance = $this->eloquent->where('ptype', $ptype);
|
||||||
|
|
||||||
$instance = $this->eloquent->where('ptype', $ptype);
|
foreach ($rule as $key => $value) {
|
||||||
|
$instance->where('v'.strval($key), $value);
|
||||||
foreach ($rule as $key => $value) {
|
}
|
||||||
$instance->where('v'.strval($key), $value);
|
|
||||||
}
|
foreach ($instance->get() as $model) {
|
||||||
|
if ($model->delete()) {
|
||||||
foreach ($instance->get() as $model) {
|
++$count;
|
||||||
if ($model->delete()) {
|
}
|
||||||
++$count;
|
}
|
||||||
}
|
|
||||||
}
|
return $count;
|
||||||
|
}
|
||||||
return $count;
|
|
||||||
}
|
/**
|
||||||
|
* RemoveFilteredPolicy removes policy rules that match the filter from the storage.
|
||||||
/**
|
* This is part of the Auto-Save feature.
|
||||||
* 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 string $sec
|
* @param int $fieldIndex
|
||||||
* @param string $ptype
|
* @param mixed ...$fieldValues
|
||||||
* @param int $fieldIndex
|
*
|
||||||
* @param mixed ...$fieldValues
|
* @return mixed
|
||||||
*
|
*/
|
||||||
* @return mixed
|
public function removeFilteredPolicy($sec, $ptype, $fieldIndex, ...$fieldValues)
|
||||||
*/
|
{
|
||||||
public function removeFilteredPolicy($sec, $ptype, $fieldIndex, ...$fieldValues)
|
$count = 0;
|
||||||
{
|
|
||||||
$count = 0;
|
$instance = $this->eloquent->where('ptype', $ptype);
|
||||||
|
foreach (range(0, 5) as $value) {
|
||||||
$instance = $this->eloquent->where('ptype', $ptype);
|
if ($fieldIndex <= $value && $value < $fieldIndex + count($fieldValues)) {
|
||||||
foreach (range(0, 5) as $value) {
|
if ('' != $fieldValues[$value - $fieldIndex]) {
|
||||||
if ($fieldIndex <= $value && $value < $fieldIndex + count($fieldValues)) {
|
$instance->where('v'.strval($value), $fieldValues[$value - $fieldIndex]);
|
||||||
if ('' != $fieldValues[$value - $fieldIndex]) {
|
}
|
||||||
$instance->where('v'.strval($value), $fieldValues[$value - $fieldIndex]);
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
foreach ($instance->get() as $model) {
|
||||||
|
if ($model->delete()) {
|
||||||
foreach ($instance->get() as $model) {
|
++$count;
|
||||||
if ($model->delete()) {
|
}
|
||||||
++$count;
|
}
|
||||||
}
|
|
||||||
}
|
return $count;
|
||||||
|
}
|
||||||
return $count;
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -6,34 +6,75 @@ use Casbin\Enforcer;
|
||||||
use Casbin\Model\Model;
|
use Casbin\Model\Model;
|
||||||
use Casbin\Log\Log;
|
use Casbin\Log\Log;
|
||||||
use Lauthz\Contracts\Factory;
|
use Lauthz\Contracts\Factory;
|
||||||
use Illuminate\Support\Manager;
|
use Lauthz\Models\Rule;
|
||||||
use Illuminate\Support\Arr;
|
use Illuminate\Support\Arr;
|
||||||
|
use InvalidArgumentException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @mixin \Casbin\Enforcer
|
* @mixin \Casbin\Enforcer
|
||||||
*/
|
*/
|
||||||
class EnforcerManager extends Manager implements Factory
|
class EnforcerManager implements Factory
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Get the default driver name.
|
* The application instance.
|
||||||
*
|
*
|
||||||
* @return string
|
* @var \Illuminate\Foundation\Application
|
||||||
*/
|
*/
|
||||||
public function getDefaultDriver()
|
protected $app;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The array of created "guards".
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $guards = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new manager instance.
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Foundation\Application $app
|
||||||
|
*/
|
||||||
|
public function __construct($app)
|
||||||
{
|
{
|
||||||
return $this->app['config']['lauthz.default'];
|
$this->app = $app;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create an instance of the Basic Enforcer driver.
|
* Attempt to get the enforcer from the local cache.
|
||||||
*
|
*
|
||||||
* @param array $config
|
* @param string $name
|
||||||
*
|
*
|
||||||
* @return \Casbin\Enforcer
|
* @return \Casbin\Enforcer
|
||||||
|
*
|
||||||
|
* @throws \InvalidArgumentException
|
||||||
*/
|
*/
|
||||||
public function createBasicDriver()
|
public function guard($name = null)
|
||||||
{
|
{
|
||||||
$config = $this->getConfig('basic');
|
$name = $name ?: $this->getDefaultGuard();
|
||||||
|
|
||||||
|
if (!isset($this->guards[$name])) {
|
||||||
|
$this->guards[$name] = $this->resolve($name);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->guards[$name];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolve the given guard.
|
||||||
|
*
|
||||||
|
* @param string $name
|
||||||
|
*
|
||||||
|
* @return \Casbin\Enforcer
|
||||||
|
*
|
||||||
|
* @throws \InvalidArgumentException
|
||||||
|
*/
|
||||||
|
protected function resolve($name)
|
||||||
|
{
|
||||||
|
$config = $this->getConfig($name);
|
||||||
|
|
||||||
|
if (is_null($config)) {
|
||||||
|
throw new InvalidArgumentException("Enforcer [{$name}] is not defined.");
|
||||||
|
}
|
||||||
|
|
||||||
if ($logger = Arr::get($config, 'log.logger')) {
|
if ($logger = Arr::get($config, 'log.logger')) {
|
||||||
Log::setLogger(new $logger($this->app['log']));
|
Log::setLogger(new $logger($this->app['log']));
|
||||||
|
@ -48,7 +89,9 @@ class EnforcerManager extends Manager implements Factory
|
||||||
}
|
}
|
||||||
$adapter = Arr::get($config, 'adapter');
|
$adapter = Arr::get($config, 'adapter');
|
||||||
if (!is_null($adapter)) {
|
if (!is_null($adapter)) {
|
||||||
$adapter = $this->app->make($adapter);
|
$adapter = $this->app->make($adapter, [
|
||||||
|
'eloquent' => new Rule([], $name),
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Enforcer($model, $adapter, Arr::get($config, 'log.enabled', false));
|
return new Enforcer($model, $adapter, Arr::get($config, 'log.enabled', false));
|
||||||
|
@ -65,4 +108,49 @@ class EnforcerManager extends Manager implements Factory
|
||||||
{
|
{
|
||||||
return $this->app['config']["lauthz.{$name}"];
|
return $this->app['config']["lauthz.{$name}"];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the default enforcer guard name.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getDefaultGuard()
|
||||||
|
{
|
||||||
|
return $this->app['config']['lauthz.default'];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the default guard driver the factory should serve.
|
||||||
|
*
|
||||||
|
* @param string $name
|
||||||
|
*/
|
||||||
|
public function shouldUse($name)
|
||||||
|
{
|
||||||
|
$name = $name ?: $this->getDefaultGuard();
|
||||||
|
|
||||||
|
$this->setDefaultGuard($name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the default authorization guard name.
|
||||||
|
*
|
||||||
|
* @param string $name
|
||||||
|
*/
|
||||||
|
public function setDefaultGuard($name)
|
||||||
|
{
|
||||||
|
$this->app['config']['lauthz.default'] = $name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dynamically call the default driver instance.
|
||||||
|
*
|
||||||
|
* @param string $method
|
||||||
|
* @param array $parameters
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function __call($method, $parameters)
|
||||||
|
{
|
||||||
|
return $this->guard()->{$method}(...$parameters);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,61 +1,66 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Lauthz\Middlewares;
|
namespace Lauthz\Middlewares;
|
||||||
|
|
||||||
use Closure;
|
use Closure;
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
use Lauthz\Exceptions\UnauthorizedException;
|
use Illuminate\Http\Request;
|
||||||
use Lauthz\Facades\Enforcer;
|
use Lauthz\Exceptions\UnauthorizedException;
|
||||||
|
use Lauthz\Facades\Enforcer;
|
||||||
/**
|
|
||||||
* A HTTP Request Middleware.
|
/**
|
||||||
*/
|
* A HTTP Request Middleware.
|
||||||
class RequestMiddleware
|
*/
|
||||||
{
|
class RequestMiddleware
|
||||||
/**
|
{
|
||||||
* The authentication factory instance.
|
/**
|
||||||
*
|
* Handle an incoming request.
|
||||||
* @var \Illuminate\Contracts\Auth\Factory
|
*
|
||||||
*/
|
* @param \Illuminate\Http\Request $request
|
||||||
protected $auth;
|
* @param \Closure $next
|
||||||
|
* @param mixed ...$guards
|
||||||
/**
|
*
|
||||||
* Create a new middleware instance.
|
* @return mixed
|
||||||
*
|
*/
|
||||||
* @param \Illuminate\Contracts\Auth\Factory $auth
|
public function handle($request, Closure $next, ...$guards)
|
||||||
*
|
{
|
||||||
* @return void
|
if (Auth::guest()) {
|
||||||
*/
|
throw new UnauthorizedException();
|
||||||
public function __construct(Auth $auth)
|
}
|
||||||
{
|
|
||||||
$this->auth = $auth;
|
$this->authorize($request, $guards);
|
||||||
}
|
|
||||||
|
return $next($request);
|
||||||
/**
|
}
|
||||||
* Handle an incoming request.
|
|
||||||
*
|
/**
|
||||||
* @param \Illuminate\Http\Request $request
|
* Determine if the user is authorized in to any of the given guards.
|
||||||
* @param \Closure $next
|
*
|
||||||
* @param mixed ...$args
|
* @param \Illuminate\Http\Request $request
|
||||||
*
|
* @param array $guards
|
||||||
* @return mixed
|
*
|
||||||
*/
|
* @throws \Lauthz\Exceptions\UnauthorizedException
|
||||||
public function handle($request, Closure $next)
|
*/
|
||||||
{
|
protected function authorize(Request $request, array $guards)
|
||||||
if (Auth::guest()) {
|
{
|
||||||
throw new UnauthorizedException();
|
$user = Auth::user();
|
||||||
}
|
$identifier = $user->getAuthIdentifier();
|
||||||
|
if (method_exists($user, 'getAuthzIdentifier')) {
|
||||||
$user = Auth::user();
|
$identifier = $user->getAuthzIdentifier();
|
||||||
$identifier = $user->getAuthIdentifier();
|
}
|
||||||
if (method_exists($user, 'getAuthzIdentifier')) {
|
|
||||||
$identifier = $user->getAuthzIdentifier();
|
if (empty($guards)) {
|
||||||
}
|
if (Enforcer::enforce($identifier, $request->getPathInfo(), $request->method())) {
|
||||||
|
return;
|
||||||
if (!Enforcer::enforce($identifier, $request->getPathInfo(), $request->method())) {
|
}
|
||||||
throw new UnauthorizedException();
|
}
|
||||||
}
|
|
||||||
|
foreach ($guards as $guard) {
|
||||||
return $next($request);
|
if (Enforcer::guard($guard)->enforce($identifier, $request->getPathInfo(), $request->method())) {
|
||||||
}
|
return Enforcer::shouldUse($guard);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new UnauthorizedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -17,6 +17,13 @@ class Rule extends Model
|
||||||
*/
|
*/
|
||||||
protected $store;
|
protected $store;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* the guard for lauthz.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $guard;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fillable.
|
* Fillable.
|
||||||
*
|
*
|
||||||
|
@ -27,10 +34,16 @@ class Rule extends Model
|
||||||
/**
|
/**
|
||||||
* Create a new Eloquent model instance.
|
* Create a new Eloquent model instance.
|
||||||
*
|
*
|
||||||
* @param array $attributes
|
* @param array $attributes
|
||||||
|
* @param string $guard
|
||||||
*/
|
*/
|
||||||
public function __construct(array $attributes = [])
|
public function __construct(array $attributes = [], $guard = '')
|
||||||
{
|
{
|
||||||
|
$this->guard = $guard;
|
||||||
|
if (!$guard) {
|
||||||
|
$this->guard = config('lauthz.default');
|
||||||
|
}
|
||||||
|
|
||||||
$connection = $this->config('database.connection') ?: config('database.default');
|
$connection = $this->config('database.connection') ?: config('database.default');
|
||||||
|
|
||||||
$this->setConnection($connection);
|
$this->setConnection($connection);
|
||||||
|
@ -84,7 +97,6 @@ class Rule extends Model
|
||||||
*/
|
*/
|
||||||
protected function initCache()
|
protected function initCache()
|
||||||
{
|
{
|
||||||
$driver = config('lauthz.default');
|
|
||||||
$store = $this->config('cache.store', 'default');
|
$store = $this->config('cache.store', 'default');
|
||||||
$store = 'default' == $store ? null : $store;
|
$store = 'default' == $store ? null : $store;
|
||||||
$this->store = Cache::store($store);
|
$this->store = Cache::store($store);
|
||||||
|
@ -100,8 +112,6 @@ class Rule extends Model
|
||||||
*/
|
*/
|
||||||
protected function config($key = null, $default = null)
|
protected function config($key = null, $default = null)
|
||||||
{
|
{
|
||||||
$driver = config('lauthz.default');
|
return config('lauthz.'.$this->guard.'.'.$key, $default);
|
||||||
|
|
||||||
return config('lauthz.'.$driver.'.'.$key, $default);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue