From 4d49aef1abe7b8b135b600ed64486971fe11e71c Mon Sep 17 00:00:00 2001 From: Dobando <33273950+Dobmod@users.noreply.github.com> Date: Fri, 5 Jul 2024 19:16:47 +0800 Subject: [PATCH] feat: use Laravel's built-in Manager class (#72) - Use Laravel's built-in abstract Manager class instead of ModelLoaderFactory (#71) --- src/EnforcerManager.php | 5 +- src/LauthzServiceProvider.php | 7 +- src/Loaders/ModelLoaderFactory.php | 48 ------------- src/Loaders/ModelLoaderManager.php | 108 +++++++++++++++++++++++++++++ tests/DatabaseAdapterTest.php | 2 +- tests/ModelLoaderTest.php | 25 +++++-- tests/RequestMiddlewareTest.php | 15 +++- 7 files changed, 149 insertions(+), 61 deletions(-) delete mode 100644 src/Loaders/ModelLoaderFactory.php create mode 100644 src/Loaders/ModelLoaderManager.php diff --git a/src/EnforcerManager.php b/src/EnforcerManager.php index dc5da35..0c08164 100755 --- a/src/EnforcerManager.php +++ b/src/EnforcerManager.php @@ -7,10 +7,10 @@ use Casbin\Model\Model; use Casbin\Log\Log; use Lauthz\Contracts\Factory; -use Lauthz\Contracts\ModelLoader; use Lauthz\Models\Rule; use Illuminate\Support\Arr; use InvalidArgumentException; +use Lauthz\Loaders\ModelLoaderManager; /** * @mixin \Casbin\Enforcer @@ -87,7 +87,8 @@ protected function resolve($name) } $model = new Model(); - $loader = $this->app->make(ModelLoader::class, $config); + $loader = $this->app->make(ModelLoaderManager::class); + $loader->initFromConfig($config); $loader->loadModel($model); $adapter = Arr::get($config, 'adapter'); diff --git a/src/LauthzServiceProvider.php b/src/LauthzServiceProvider.php index 273f42b..84f0fb9 100644 --- a/src/LauthzServiceProvider.php +++ b/src/LauthzServiceProvider.php @@ -3,8 +3,7 @@ namespace Lauthz; use Illuminate\Support\ServiceProvider; -use Lauthz\Contracts\ModelLoader; -use Lauthz\Loaders\ModelLoaderFactory; +use Lauthz\Loaders\ModelLoaderManager; use Lauthz\Models\Rule; use Lauthz\Observers\RuleObserver; @@ -53,8 +52,8 @@ public function register() return new EnforcerManager($app); }); - $this->app->bind(ModelLoader::class, function($app, $config) { - return ModelLoaderFactory::createFromConfig($config); + $this->app->singleton(ModelLoaderManager::class, function ($app) { + return new ModelLoaderManager($app); }); } } diff --git a/src/Loaders/ModelLoaderFactory.php b/src/Loaders/ModelLoaderFactory.php deleted file mode 100644 index 8a7ef9f..0000000 --- a/src/Loaders/ModelLoaderFactory.php +++ /dev/null @@ -1,48 +0,0 @@ -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}."); + } +} diff --git a/tests/DatabaseAdapterTest.php b/tests/DatabaseAdapterTest.php index 195c35b..21b13c7 100644 --- a/tests/DatabaseAdapterTest.php +++ b/tests/DatabaseAdapterTest.php @@ -309,7 +309,7 @@ public function testLoadFilteredPolicy() $this->assertEquals([ ['bob', 'data2', 'write'] ], Enforcer::getPolicy()); - + // Filter $filter = new Filter(['v2'], ['read']); Enforcer::loadFilteredPolicy($filter); diff --git a/tests/ModelLoaderTest.php b/tests/ModelLoaderTest.php index 75a93f3..4d673d5 100644 --- a/tests/ModelLoaderTest.php +++ b/tests/ModelLoaderTest.php @@ -3,6 +3,7 @@ namespace Lauthz\Tests; use Lauthz\Facades\Enforcer; +use Lauthz\Loaders\ModelLoaderManager; use InvalidArgumentException; use RuntimeException; @@ -67,7 +68,15 @@ public function testEmptyLoaderType(): void $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->app['config']->set('lauthz.basic.model.config_url', 'http://filenoexists'); @@ -94,12 +103,20 @@ protected function initTextConfig(): void ); } - protected function initCustomConfig(): void { - $this->app['config']->set('lauthz.second.model.config_loader_class', '\Lauthz\Loaders\TextLoader'); + protected function initCustomConfig(): void + { + $this->app['config']->set('lauthz.second.model.config_type', 'custom'); $this->app['config']->set( 'lauthz.second.model.config_text', $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 @@ -118,4 +135,4 @@ protected function getModelText(): string m = r.sub == p.sub && r.obj == p.obj && r.act == p.act EOT; } -} \ No newline at end of file +} diff --git a/tests/RequestMiddlewareTest.php b/tests/RequestMiddlewareTest.php index b4e6088..0805952 100644 --- a/tests/RequestMiddlewareTest.php +++ b/tests/RequestMiddlewareTest.php @@ -5,6 +5,7 @@ use Lauthz\Middlewares\RequestMiddleware; use Illuminate\Foundation\Testing\DatabaseMigrations; use Illuminate\Http\Request; +use Lauthz\Facades\Enforcer; use Lauthz\Models\Rule; class RequestMiddlewareTest extends TestCase @@ -34,11 +35,19 @@ public function testAfterLogin() $this->assertEquals($this->middleware(Request::create('/foo1/123', 'PUT')), '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() @@ -62,6 +71,8 @@ protected function initConfig() m = g(r.sub, p.sub) && r.sub == p.sub && keyMatch2(r.obj, p.obj) && regexMatch(r.act, p.act) EOT; $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()