feat: use Laravel's built-in Manager class
- Use Laravel's built-in abstract Manager class instead of ModelLoaderFactory (#71)
This commit is contained in:
parent
259a389595
commit
fe5839fa0d
|
@ -7,10 +7,10 @@ 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 Lauthz\Contracts\ModelLoader;
|
|
||||||
use Lauthz\Models\Rule;
|
use Lauthz\Models\Rule;
|
||||||
use Illuminate\Support\Arr;
|
use Illuminate\Support\Arr;
|
||||||
use InvalidArgumentException;
|
use InvalidArgumentException;
|
||||||
|
use Lauthz\Loaders\ModelLoaderManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @mixin \Casbin\Enforcer
|
* @mixin \Casbin\Enforcer
|
||||||
|
@ -87,7 +87,8 @@ class EnforcerManager implements Factory
|
||||||
}
|
}
|
||||||
|
|
||||||
$model = new Model();
|
$model = new Model();
|
||||||
$loader = $this->app->make(ModelLoader::class, $config);
|
$loader = $this->app->make(ModelLoaderManager::class);
|
||||||
|
$loader->initFromConfig($config);
|
||||||
$loader->loadModel($model);
|
$loader->loadModel($model);
|
||||||
|
|
||||||
$adapter = Arr::get($config, 'adapter');
|
$adapter = Arr::get($config, 'adapter');
|
||||||
|
|
|
@ -3,8 +3,7 @@
|
||||||
namespace Lauthz;
|
namespace Lauthz;
|
||||||
|
|
||||||
use Illuminate\Support\ServiceProvider;
|
use Illuminate\Support\ServiceProvider;
|
||||||
use Lauthz\Contracts\ModelLoader;
|
use Lauthz\Loaders\ModelLoaderManager;
|
||||||
use Lauthz\Loaders\ModelLoaderFactory;
|
|
||||||
use Lauthz\Models\Rule;
|
use Lauthz\Models\Rule;
|
||||||
use Lauthz\Observers\RuleObserver;
|
use Lauthz\Observers\RuleObserver;
|
||||||
|
|
||||||
|
@ -53,8 +52,8 @@ class LauthzServiceProvider extends ServiceProvider
|
||||||
return new EnforcerManager($app);
|
return new EnforcerManager($app);
|
||||||
});
|
});
|
||||||
|
|
||||||
$this->app->bind(ModelLoader::class, function($app, $config) {
|
$this->app->singleton(ModelLoaderManager::class, function ($app) {
|
||||||
return ModelLoaderFactory::createFromConfig($config);
|
return new ModelLoaderManager($app);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,48 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Lauthz\Loaders;
|
|
||||||
|
|
||||||
use Illuminate\Support\Arr;
|
|
||||||
use Lauthz\Contracts\Factory;
|
|
||||||
use InvalidArgumentException;
|
|
||||||
|
|
||||||
class ModelLoaderFactory implements Factory
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Create a model loader from configuration.
|
|
||||||
*
|
|
||||||
* A model loader is responsible for a loading model from an arbitrary source.
|
|
||||||
* Developers can customize loading behavior by implementing
|
|
||||||
* the ModelLoader interface and specifying their custom class
|
|
||||||
* via 'model.config_loader_class' in the configuration.
|
|
||||||
*
|
|
||||||
* Built-in loader implementations include:
|
|
||||||
* - FileLoader: For loading model from file.
|
|
||||||
* - TextLoader: Suitable for model defined as a multi-line string.
|
|
||||||
* - UrlLoader: Handles model loading from URL.
|
|
||||||
*
|
|
||||||
* To utilize a built-in loader, set 'model.config_type' to match one of the above types.
|
|
||||||
*
|
|
||||||
* @param array $config
|
|
||||||
* @return \Lauthz\Contracts\ModelLoader
|
|
||||||
* @throws InvalidArgumentException
|
|
||||||
*/
|
|
||||||
public static function createFromConfig(array $config) {
|
|
||||||
$customLoader = Arr::get($config, 'model.config_loader_class', '');
|
|
||||||
if (class_exists($customLoader)) {
|
|
||||||
return new $customLoader($config);
|
|
||||||
}
|
|
||||||
|
|
||||||
$loaderType = Arr::get($config, 'model.config_type', '');
|
|
||||||
switch ($loaderType) {
|
|
||||||
case 'file':
|
|
||||||
return new FileLoader($config);
|
|
||||||
case 'text':
|
|
||||||
return new TextLoader($config);
|
|
||||||
case 'url':
|
|
||||||
return new UrlLoader($config);
|
|
||||||
default:
|
|
||||||
throw new InvalidArgumentException("Unsupported model loader type: {$loaderType}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,108 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Lauthz\Loaders;
|
||||||
|
|
||||||
|
use Illuminate\Support\Arr;
|
||||||
|
use Illuminate\Support\Str;
|
||||||
|
use Illuminate\Support\Manager;
|
||||||
|
use InvalidArgumentException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The model loader manager.
|
||||||
|
*
|
||||||
|
* A model loader is responsible for a loading model from an arbitrary source.
|
||||||
|
* Developers can customize loading behavior by implementing
|
||||||
|
* and register the custom loader in AppServiceProvider through `app(LoaderManager::class)->extend()`.
|
||||||
|
*
|
||||||
|
* Built-in loader implementations include:
|
||||||
|
* - FileLoader: For loading model from file.
|
||||||
|
* - TextLoader: Suitable for model defined as a multi-line string.
|
||||||
|
* - UrlLoader: Handles model loading from URL.
|
||||||
|
*
|
||||||
|
* To utilize a built-in or custom loader, set 'model.config_type' in the configuration to match one of the above types.
|
||||||
|
*/
|
||||||
|
class ModelLoaderManager extends Manager
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The array of the lauthz driver configuration.
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $config;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize configuration for the loader manager instance.
|
||||||
|
*
|
||||||
|
* @param array $config the lauthz driver configuration.
|
||||||
|
*/
|
||||||
|
public function initFromConfig(array $config)
|
||||||
|
{
|
||||||
|
$this->config = $config;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the default driver from the configuration.
|
||||||
|
*
|
||||||
|
* @return string The default driver name.
|
||||||
|
*/
|
||||||
|
public function getDefaultDriver()
|
||||||
|
{
|
||||||
|
return Arr::get($this->config, 'model.config_type', '');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new TextLoader instance.
|
||||||
|
*
|
||||||
|
* @return TextLoader
|
||||||
|
*/
|
||||||
|
public function createTextDriver()
|
||||||
|
{
|
||||||
|
return new TextLoader($this->config);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new UrlLoader instance.
|
||||||
|
*
|
||||||
|
* @return UrlLoader
|
||||||
|
*/
|
||||||
|
public function createUrlDriver()
|
||||||
|
{
|
||||||
|
return new UrlLoader($this->config);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new FileLoader instance.
|
||||||
|
*
|
||||||
|
* @return FileLoader
|
||||||
|
*/
|
||||||
|
public function createFileDriver()
|
||||||
|
{
|
||||||
|
return new FileLoader($this->config);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new driver instance.
|
||||||
|
*
|
||||||
|
* @param string $driver
|
||||||
|
* @return mixed
|
||||||
|
*
|
||||||
|
* @throws \InvalidArgumentException
|
||||||
|
*/
|
||||||
|
protected function createDriver($driver)
|
||||||
|
{
|
||||||
|
if(empty($driver)) {
|
||||||
|
throw new InvalidArgumentException('Unsupported empty model loader type.');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($this->customCreators[$driver])) {
|
||||||
|
return $this->callCustomCreator($driver);
|
||||||
|
}
|
||||||
|
$method = 'create' . Str::studly($driver) . 'Driver';
|
||||||
|
if (method_exists($this, $method)) {
|
||||||
|
return $this->$method();
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new InvalidArgumentException("Unsupported model loader type: {$driver}.");
|
||||||
|
}
|
||||||
|
}
|
|
@ -309,7 +309,7 @@ class DatabaseAdapterTest extends TestCase
|
||||||
$this->assertEquals([
|
$this->assertEquals([
|
||||||
['bob', 'data2', 'write']
|
['bob', 'data2', 'write']
|
||||||
], Enforcer::getPolicy());
|
], Enforcer::getPolicy());
|
||||||
|
|
||||||
// Filter
|
// Filter
|
||||||
$filter = new Filter(['v2'], ['read']);
|
$filter = new Filter(['v2'], ['read']);
|
||||||
Enforcer::loadFilteredPolicy($filter);
|
Enforcer::loadFilteredPolicy($filter);
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
namespace Lauthz\Tests;
|
namespace Lauthz\Tests;
|
||||||
|
|
||||||
use Lauthz\Facades\Enforcer;
|
use Lauthz\Facades\Enforcer;
|
||||||
|
use Lauthz\Loaders\ModelLoaderManager;
|
||||||
use InvalidArgumentException;
|
use InvalidArgumentException;
|
||||||
use RuntimeException;
|
use RuntimeException;
|
||||||
|
|
||||||
|
@ -67,7 +68,15 @@ class ModelLoaderTest extends TestCase
|
||||||
$this->assertFalse(Enforcer::enforce('alice', 'data', 'read'));
|
$this->assertFalse(Enforcer::enforce('alice', 'data', 'read'));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testBadUlrConnection(): void
|
public function testNotExistLoaderType(): void
|
||||||
|
{
|
||||||
|
$this->app['config']->set('lauthz.basic.model.config_type', 'not_exist');
|
||||||
|
$this->expectException(InvalidArgumentException::class);
|
||||||
|
|
||||||
|
$this->assertFalse(Enforcer::enforce('alice', 'data', 'read'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testBadUrlConnection(): void
|
||||||
{
|
{
|
||||||
$this->initUrlConfig();
|
$this->initUrlConfig();
|
||||||
$this->app['config']->set('lauthz.basic.model.config_url', 'http://filenoexists');
|
$this->app['config']->set('lauthz.basic.model.config_url', 'http://filenoexists');
|
||||||
|
@ -94,12 +103,20 @@ class ModelLoaderTest extends TestCase
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function initCustomConfig(): void {
|
protected function initCustomConfig(): void
|
||||||
$this->app['config']->set('lauthz.second.model.config_loader_class', '\Lauthz\Loaders\TextLoader');
|
{
|
||||||
|
$this->app['config']->set('lauthz.second.model.config_type', 'custom');
|
||||||
$this->app['config']->set(
|
$this->app['config']->set(
|
||||||
'lauthz.second.model.config_text',
|
'lauthz.second.model.config_text',
|
||||||
$this->getModelText()
|
$this->getModelText()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
$config = $this->app['config']->get('lauthz.second');
|
||||||
|
$loader = $this->app->make(ModelLoaderManager::class);
|
||||||
|
|
||||||
|
$loader->extend('custom', function () use ($config) {
|
||||||
|
return new \Lauthz\Loaders\TextLoader($config);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function getModelText(): string
|
protected function getModelText(): string
|
||||||
|
@ -118,4 +135,4 @@ e = some(where (p.eft == allow))
|
||||||
m = r.sub == p.sub && r.obj == p.obj && r.act == p.act
|
m = r.sub == p.sub && r.obj == p.obj && r.act == p.act
|
||||||
EOT;
|
EOT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ namespace Lauthz\Tests;
|
||||||
use Lauthz\Middlewares\RequestMiddleware;
|
use Lauthz\Middlewares\RequestMiddleware;
|
||||||
use Illuminate\Foundation\Testing\DatabaseMigrations;
|
use Illuminate\Foundation\Testing\DatabaseMigrations;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
|
use Lauthz\Facades\Enforcer;
|
||||||
use Lauthz\Models\Rule;
|
use Lauthz\Models\Rule;
|
||||||
|
|
||||||
class RequestMiddlewareTest extends TestCase
|
class RequestMiddlewareTest extends TestCase
|
||||||
|
@ -34,11 +35,19 @@ class RequestMiddlewareTest extends TestCase
|
||||||
$this->assertEquals($this->middleware(Request::create('/foo1/123', 'PUT')), 'Unauthorized Exception');
|
$this->assertEquals($this->middleware(Request::create('/foo1/123', 'PUT')), 'Unauthorized Exception');
|
||||||
|
|
||||||
$this->assertEquals($this->middleware(Request::create('/proxy', 'GET')), 'Unauthorized Exception');
|
$this->assertEquals($this->middleware(Request::create('/proxy', 'GET')), 'Unauthorized Exception');
|
||||||
|
|
||||||
|
Enforcer::guard('second')->addPolicy('alice', '/foo1/*', '(GET|POST)');
|
||||||
|
|
||||||
|
$this->assertEquals($this->middleware(Request::create('/foo1/123', 'GET'), 'second'), 200);
|
||||||
|
$this->assertEquals($this->middleware(Request::create('/foo1/123', 'POST'), 'second'), 200);
|
||||||
|
$this->assertEquals($this->middleware(Request::create('/foo1/123', 'PUT'), 'second'), 'Unauthorized Exception');
|
||||||
|
|
||||||
|
$this->assertEquals($this->middleware(Request::create('/proxy', 'GET'), 'second'), 'Unauthorized Exception');
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function middleware($request)
|
protected function middleware($request, ...$guards)
|
||||||
{
|
{
|
||||||
return parent::runMiddleware(RequestMiddleware::class, $request);
|
return parent::runMiddleware(RequestMiddleware::class, $request, ...$guards);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function initConfig()
|
protected function initConfig()
|
||||||
|
@ -62,6 +71,8 @@ e = some(where (p.eft == allow))
|
||||||
m = g(r.sub, p.sub) && r.sub == p.sub && keyMatch2(r.obj, p.obj) && regexMatch(r.act, p.act)
|
m = g(r.sub, p.sub) && r.sub == p.sub && keyMatch2(r.obj, p.obj) && regexMatch(r.act, p.act)
|
||||||
EOT;
|
EOT;
|
||||||
$this->app['config']->set('lauthz.basic.model.config_text', $text);
|
$this->app['config']->set('lauthz.basic.model.config_text', $text);
|
||||||
|
$this->app['config']->set('lauthz.second.model.config_type', 'text');
|
||||||
|
$this->app['config']->set('lauthz.second.model.config_text', $text);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function initTable()
|
protected function initTable()
|
||||||
|
|
Loading…
Reference in New Issue