Feature Request: Modular support
WebKenth opened this issue · comments
Greetings!
We love your package, however it falls short whenever there's a third party model which happens to have the same name as ours
This might be an "us" issue, and not something relevant for this package, however i thought i would contribute if anyone else had the same issues:
Context:
We use a Laravel Module package which allows us to seperate our code into modules and keep logic more tightly locked up. a benefit of this is that when it becomes nessecary we can simply turn the entire module into a package and share it to external partners and such. ( Package in question is: https://github.com/InterNACHI/modular )
Problem:
We have 3 Models all names Product
Each are namespaced into their own module
Example:
- app/Models/Product
- app-modules/Shopify/Models/Product
- app-modules/Struct/Models/Product
when using this package it is only possible for us to register / generate a policy for one module as they are all put into the same directory.
So a "ShopifyProduct" would turn into ProductPolicy with the model pointing to the module's model
In the AuthServiceProvider
we added each custom model with a corresponding policy
ie:
'Module\Vendor\Models\Shopify\Product' => 'Module\Vendor\Policies\ProductPolicy',
with the thought that Shield would edit the policy in the module folder, and while we understand why not it was still not possible for Shield to add a sub folder to the app/Policies
folder
ideally we wanted something like
- app/Policies/Shopify/ProductPolicy
- app/Policies/Struct/ProductPolicy
- app/Policies/ProductPolicy
however the generate command simple overwrote the same ProductPolicy 3 times and the last one registered won :(
The patch below solves the issue by looking for a folder and then using Sub Folder logic to separate each policy into their own folder
--- src/Commands/Concerns/CanGeneratePolicy.php
+++ src/Commands/Concerns/CanGeneratePolicy.php
@@ -25,6 +25,19 @@
$policyPath = Str::of(config('filament-shield.generator.policy_directory', 'Policies'))
->replace('\\', DIRECTORY_SEPARATOR);
+ if (Str::of($path)->contains('app-modules')) {
+ $sub_path = explode('app-modules/', $path);
+ $module_name = explode('/', $sub_path[1])[0];
+ $module_name = Str::studly($module_name);
+ $basePolicyPath = app_path(
+ (string) Str::of($entity['model'])
+ ->prepend($policyPath->append('\\'))
+ ->replace('\\', DIRECTORY_SEPARATOR),
+ );
+ $policyPath = str_replace('app/Policies',"app/Policies/{$module_name}","{$basePolicyPath}Policy.php");
+ return $policyPath;
+ }
+
if (Str::of($path)->contains(['vendor', 'src'])) {
$basePolicyPath = app_path(
(string) Str::of($entity['model'])
@@ -64,6 +77,14 @@
$stubVariables['namespace'] = Str::of($path)->contains(['vendor', 'src'])
? 'App\Policies'
: Str::of($namespace)->replace('Models', 'Policies'); /** @phpstan-ignore-line */
+
+ if(Str::of($path)->contains('app-modules')) {
+ $sub_path = explode('app-modules/', $path);
+ $module_name = explode('/', $sub_path[1])[0];
+ $module_name = Str::studly($module_name);
+ $stubVariables['namespace'] = "App\\Policies\\{$module_name}";
+ }
+
$stubVariables['model_name'] = $entity['model'];
$stubVariables['model_fqcn'] = $namespace . '\\' . $entity['model'];
$stubVariables['model_variable'] = Str::of($entity['model'])->camel();
--- src/FilamentShield.php
+++ src/FilamentShield.php
@@ -41,10 +41,14 @@
if (Str::contains($identifier, '_')) {
throw new \InvalidArgumentException("Permission identifier `$identifier` for `$resource` cannot contain underscores.");
}
-
return $identifier;
}
-
+ if (Str::contains($resource, '{{ YOUR MODULE NAMESPACE }}')) {
+ $package = explode('\\', $resource);
+ $vendor = Str::lower($package[0]);
+ $module = Str::lower($package[1]);
+ return "$vendor:$module::{$this->getDefaultPermissionIdentifier($resource)}";
+ }
return $this->getDefaultPermissionIdentifier($resource);
}
An idea could be to make it an option in the plugin to allow subfolder logic
not planned at the moment but maybe once i get some free time