Giter Site home page Giter Site logo

bezhansalleh / filament-shield Goto Github PK

View Code? Open in Web Editor NEW
1.1K 17.0 148.0 735 KB

The easiest and most intuitive way to add access management to your Filament Admin Resources, Pages & Widgets through `spatie/laravel-permission`

License: MIT License

PHP 95.58% Blade 4.42%
permissions roles filament filamentplugin laravel php livewire secure easy-access-management acl

filament-shield's Introduction

filament-shield-art

FILAMENT 8.x Packagist Tests Passing Code Style Passing Downloads

Shield

The easiest and most intuitive way to add access management to your Filament Admin:

  • πŸ”₯ Resources
  • πŸ”₯ Pages
  • πŸ”₯ Widgets
  • πŸ”₯ Custom Permissions

Note

For Filament 2.x use 2.x branch

Important

Prior to v3.1.0 Shield supported spatie/laravel-permission:^5.0 and now it supports version ^6.0. Which has some breaking changes around migrations. If you are upgrading from a version prior to v3.1.0 please make sure to remove the old migration file and republish the new one.

Installation

  1. Install the package via composer:
composer require bezhansalleh/filament-shield
  1. Add the Spatie\Permission\Traits\HasRoles trait to your User model(s):
use Illuminate\Foundation\Auth\User as Authenticatable;
use Spatie\Permission\Traits\HasRoles;

class User extends Authenticatable
{
    use HasRoles;

    // ...
}
  1. Publish the config file then setup your configuration:
php artisan vendor:publish --tag=filament-shield-config
  1. Register the plugin for the Filament Panels you want
public function panel(Panel $panel): Panel
{
    return $panel
        ->plugins([
            \BezhanSalleh\FilamentShield\FilamentShieldPlugin::make()
        ]);
}
  1. Now run the following command to install shield:
php artisan shield:install

Follow the prompts and enjoy!

Filament Panels

If you want to enable Shield for more than one panel then you need to register the plugin for each panel as mentioned above.

Panel Access

Shield comes with the HasPanelShield trait which provides an easy way to integrate Shield's conventions with the Filament's panel access system.

The HasPanelShield trait provides an implementation for the canAccessPanel method, determining access based on whether the user possesses the super_admin role or the panel_user role. It also assigns the panel_user role to the user upon creation and removes it upon deletion. Ofcourse the role names can be changed from the plugin's configuration file.

use BezhanSalleh\FilamentShield\Traits\HasPanelShield;
use Filament\Models\Contracts\FilamentUser;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Spatie\Permission\Traits\HasRoles;

class User extends Authenticatable implements FilamentUser
{
    use HasRoles;
    use HasPanelShield;
    // ...
}

Resources

Generally there are two scenarios that shield handles permissions for your Filament resources.

Default

Out of the box Shield handles the predefined permissions for Filament resources. So if that's all that you need you are all set. If you need to add a single permission (for instance lock) and have it available for all your resources just append it to the following config key:

    permission_prefixes' => [
        'resource' => [
            'view',
            'view_any',
            'create',
            'update',
            'restore',
            'restore_any',
            'replicate',
            'reorder',
            'delete',
            'delete_any',
            'force_delete',
            'force_delete_any',
            'lock'
        ],
        ...
    ],

πŸ’‘ Now you are thinking what if I need a permission to be only available for just one resource? No worries, that's where Custom Permissions come to play.

Custom Permissions

To define custom permissions per Resource your Resource must implement the HasShieldPermissions contract. This contract has a getPermissionPrefixes() method which returns an array of permission prefixes for your Resource.

Consider you have a PostResource and you want a couple of the predefined permissions plus a new permission called publish_posts to be only available for PostResource only.

<?php

namespace BezhanSalleh\FilamentShield\Resources;

use BezhanSalleh\FilamentShield\Contracts\HasShieldPermissions;
...

class PostResource extends Resource implements HasShieldPermissions
{
    ...

    public static function getPermissionPrefixes(): array
    {
        return [
            'view',
            'view_any',
            'create',
            'update',
            'delete',
            'delete_any',
            'publish'
        ];
    }

    ...
}

In the above example the getPermissionPrefixes() method returns the permission prefixes Shield needs to generate the permissions.

βœ… Now to enforce publish_post permission headover to your PostPolicy and add a publish() method:

    /**
     * Determine whether the user can publish posts.
     *
     * @param  \App\Models\User  $admin
     * @return \Illuminate\Auth\Access\Response|bool
     */
    public function publish(User $user)
    {
        return $user->can('publish_post');
    } 

πŸ…°οΈ/🈯️ To make the prefix translatable, publish Shield's translations and append the prefix inside resource_permission_prefixes_labels as key and it's translation as value for the languages you need.

//lang/en/filament-shield.php
'resource_permission_prefixes_labels' => [
    'publish' => 'Publish'    
],
//lang/es/filament-shield.php
'resource_permission_prefixes_labels' => [
    'publish' => 'Publicar'    
],
Configure Permission Identifier

By default the permission identifier is generated as follow:

Str::of($resource)
    ->afterLast('Resources\\')
    ->before('Resource')
    ->replace('\\', '')
    ->snake()
    ->replace('_', '::');

So for instance if you have a resource like App\Filament\Resources\Shop\CategoryResource then the permission identifier would be shop::category and then it would be prefixed with your defined prefixes or what comes default with shield.

If you wish to change the default behaviour, then you can call the static configurePermissionIdentifierUsing() method inside a service provider's boot() method, to which you pass a Closure to modify the logic. The Closure receives the fully qualified class name of the resource as $resource which gives you the ability to access any property or method defined within the resource.

For example, if you wish to use the model name as the permission identifier, you can do it like so:

use BezhanSalleh\FilamentShield\Facades\FilamentShield;

FilamentShield::configurePermissionIdentifierUsing(
    fn($resource) => str($resource::getModel())
        ->afterLast('\\')
        ->lower()
        ->toString()
);

Warning Keep in mind that ensuring the uniqueness of the permission identifier is now up to you.

Custom Navigation Group

By default the english translation renders Roles and Permissions under 'Filament Shield' if you wish to change this, first publish the translations files and change the relative locale to the group of your choosing for example:

'nav.group' => 'Filament Shield',

to

'nav.group' => 'User Management',

apply this to each language you have groups in.

Pages

If you have generated permissions for Pages you can toggle the page's navigation from sidebar and restricted access to the page. You can set this up manually but this package comes with a HasPageShield trait to speed up this process. All you have to do is use the trait in you pages:

<?php

namespace App\Filament\Pages;

use ...;
use BezhanSalleh\FilamentShield\Traits\HasPageShield;

class MyPage extends Page
{
    use HasPageShield;
    ...
}

πŸ“• HasPageShield uses the booted method to check the user's permissions and makes sure to execute the booted page method in the parent page if exists.

Pages Hooks

However if you need to perform some methods before and after the booted method you can declare the next hooks methods in your filament page.

<?php

namespace App\Filament\Pages;

use ...;
use BezhanSalleh\FilamentShield\Traits\HasPageShield;

class MyPage extends Page
{
    use HasPageShield;
    ...

    protected function beforeBooted : void() {
        ...
    }

    protected function afterBooted : void() {
        ...
    }

    /**
     * Hook to perform an action before redirect if the user
     * doesn't have access to the page.  
     * */
    protected function beforeShieldRedirects : void() {
        ...
    }
}
Pages Redirect Path

HasPageShield uses the config('filament.path') value by default to perform the shield redirection. If you need to overwrite the rediretion path, just add the next method to your page:

<?php

namespace App\Filament\Pages;

use ...;
use BezhanSalleh\FilamentShield\Traits\HasPageShield;

class MyPage extends Page
{
    use HasPageShield;
    ...

    protected function getShieldRedirectPath(): string {
        return '/'; // redirect to the root index...
    }
}

Widgets

if you have generated permissions for Widgets you can toggle their state based on whether a user have permission or not. You can set this up manually but this package comes with a HasWidgetShield trait to speed up this process. All you have to do is use the trait in you widgets:

<?php

namespace App\Filament\Widgets;

use ...;
use BezhanSalleh\FilamentShield\Traits\HasWidgetShield;

class IncomeWidget extends LineChartWidget
{
    use HasWidgetShield;
    ...
}

Policies

Role Policy

To ensure RoleResource access via RolePolicy you would need to add the following to your AuthServiceProvider:

//AuthServiceProvider.php
...
protected $policies = [
    'Spatie\Permission\Models\Role' => 'App\Policies\RolePolicy',
];
...

You can skip it if you have enabled it from the config:

// config/filament-shield.php
...

'register_role_policy' => [
    'enabled' => true,
],
...

Policy Path

If your policies are not in the default Policies directory in the app_path() you can change the directory name in the config file:

...
'generator' => [
    'option' => 'policies_and_permissions',
    'policy_directory' => 'Policies',
],
...

Custom folder structure for Models or Third-Party Plugins

Shield also generates policies and permissions for third-party plugins and Models with custom folder structure and to enforce the generated policies you will need to register them in your application's AuthServiceProvider:

...
class AuthServiceProvider extends ServiceProvider
{
    ...
    protected $policies = [
        ...,
        'App\Models\Blog\Author' => 'App\Policies\Blog\AuthorPolicy',
        'Ramnzys\FilamentEmailLog\Models\Email' => 'App\Policies\EmailPolicy'

    ];

Users (Assigning Roles to Users)

Shield does not come with a way to assign roles to your users out of the box, however you can easily assign roles to your users using Filament Forms's Select or CheckboxList component. Inside your users Resource's form add one of these components and configure them as you need:

// Using Select Component
Forms\Components\Select::make('roles')
    ->relationship('roles', 'name')
    ->multiple()
    ->preload()
    ->searchable()
                    
// Using CheckboxList Component
Forms\Components\CheckboxList::make('roles')
    ->relationship('roles', 'name')
    ->searchable()

You can find out more about these components in the Filament Docs

Layout Customization

You can easily customize the Grid, Section and CheckboxList's columns() and columnSpan() without publishing the resource.

use BezhanSalleh\FilamentShield\FilamentShieldPlugin;

public function panel(Panel $panel): Panel
{
        return $panel
            ...
            ...
            ->plugins([
                FilamentShieldPlugin::make()
                    ->gridColumns([
                        'default' => 1,
                        'sm' => 2,
                        'lg' => 3
                    ])
                    ->sectionColumnSpan(1)
                    ->checkboxListColumns([
                        'default' => 1,
                        'sm' => 2,
                        'lg' => 4,
                    ])
                    ->resourceCheckboxListColumns([
                        'default' => 1,
                        'sm' => 2,
                    ]),
            ]);
}
Screenshot 2023-09-24 at 10 34 31 PM

Translations

Publish the translations using:

php artisan vendor:publish --tag="filament-shield-translations"

Available Filament Shield Commands

shield:doctor

  • Show useful info about Filament Shield.

shield:install

Setup Core Package requirements and Install Shield. Accepts the following flags:

  • --fresh re-run the migrations
  • --only Only setups shield without generating permissions and creating super-admin

shield:generate

Generate Permissions and/or Policies for Filament entities. Accepts the following flags:

  • --all Generate permissions/policies for all entities
  • --option[=OPTION] Override the config generator option(policies_and_permissions,policies,permissions)
  • --resource[=RESOURCE] One or many resources separated by comma (,)
  • --page[=PAGE] One or many pages separated by comma (,)
  • --widget[=WIDGET] One or many widgets separated by comma (,)
  • --exclude Exclude the given entities during generation
  • --ignore-config-exclude Ignore config exclude option during generation
  • --ignore-existing-policies Do not overwrite the existing policies.

shield:super-admin

Create a user with super_admin role.

  • Accepts an --user= argument that will use the provided ID to find the user to be made super admin.

shield:publish

  • Publish the Shield RoleResource and customize it however you like

shield:seeder

  • Deploy easily by setting up your roles and permissions or add your custom seeds

Testing

composer test

Changelog

Please see CHANGELOG for more information on what has changed recently.

Contributing

Please see CONTRIBUTING for details.

Security Vulnerabilities

Please review our security policy on how to report security vulnerabilities.

Credits

License

The MIT License (MIT). Please see License File for more information.

filament-shield's People

Contributors

aalmakzumi-merge avatar atmonshi avatar bezhansalleh avatar corvisier avatar datlechin avatar dependabot[bot] avatar felipe-balloni avatar furkangm avatar gergo85 avatar github-actions[bot] avatar hadyfayed avatar homaeee avatar igwen6w avatar intrepidws avatar jvkassi avatar lhilton avatar majdghithan avatar modrictin avatar mohamedsabil83 avatar noxoua avatar oyepez003 avatar pathros avatar pxlrbt avatar rupadana avatar sayasuhendra avatar shibomb avatar simonbuehler avatar thijmenkort avatar torosegon avatar webmasterlv avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

filament-shield's Issues

In roles page (for each role) takes too much time to modify permissions

Hi thanks for the good package you provide to community.
When i have many models like more than 10, In roles page (for each role) takes too much time to modify permissions. As i see in network request, the response for each modification takes a lot of resources and heavy in size (+600kb).
I'm not sure how to make it faster.

Error when saving Shield Settings

Hi,

I've installed the package in a local filament project running under Xampp / PHP 8 / Laravel 8.82.0 / Windows 11 and received the following error when both trying to save and save & generate the shield settings.

mkdir(): File exists

This is returned out of C:\xampp8\htdocs\filament_eval\vendor\laravel\framework\src\Illuminate\Filesystem\Filesystem
.php : 603

The path that's being passed into the makeDirectory function is (on my local environment):

C:\xampp8\htdocs\filament_eval\config\filament-shield.php

(IDEA) Greater freedom to generate permissions

I think that more than once we have collided with the possibility that not all our resources share the same ones, many times some have less and others more permissions than those we have already defined.

We could give developers a little more freedom, if we define a function through an interface so that the permissions that the resource will have are written there.

I'm currently working on it, since most of my projects need them and I don't really like the idea of ​​having custom permissions. Not when view_role, view_any_role and more are inside the same segment but disable_role will be outside the Role segment just because it is different.

I don't know if you'd be interested in me opening a PR when I'm done setting this up in my project.

Default roles

Hi the default roles base on config must can not be modified, since this is attach in some code base, like super_admin and filament_user, just want to try to override the resource, but it is tedious to manually override

Question: specify resource permission set

For example, I have two resources: Post and Category. User can (or not) set status "published" for Post, but for Category this is not usefull. Can I specify resource permission for Post (add "publish" permission), but for Category set own?

Cannot Change Page and Widget Permission Prefixes

I have tried changing the widget and page permission prefixes to several different things (access_page, view_page, page_view, etc). Changing to anything at all results in a Class "" not found error when trying to access a role view or update page.

Possible issue involving permissions of models with composite name

I'm facing an issue involving a mismatch with the name of permissions for models with composite name.

My model is named as IpAddress. After ran install command the permissions were created in the database as:

  • create_ipaddress
  • delete_any_ipaddress
  • delete_ipaddress
  • export_ipaddress
  • update_ipaddress
  • view_any_ipaddress
  • view_ipaddress

Also in the IpAddressPolicy class, the permissions are exactly the same and it is working for super admin at this point.

The problem starts after create a new role with low access and try add permissions for this resource. When we need change the role, the form of the card in edit page has the wrong name in the fields.

Screen Shot 2022-07-20 at 10 07 12

After enable the toogle and save it, I'm able to see permissions duplicated in the database (table permissions): there are two records for each permission, one with ipaddress and other with ip_address. The permissions in DB are like this list:

  • create_ipaddress
  • delete_any_ipaddress
  • delete_ipaddress
  • export_ipaddress
  • update_ipaddress
  • view_any_ipaddress
  • view_ipaddress
  • create_ip_address
  • delete_any_ip_address
  • delete_ip_address
  • export_ip_address
  • update_ip_address
  • view_any_ip_address
  • view_ip_address

After this point all the users (even super_admin) are not able to access the resource, no matter what you try in the settings or in role configuration.

The others resource for Models with regular names, like the model Banner from the screenshot, are still working perfectly.

Filament Shield Menu Label

ow can I change the name and location of the Filament Shield that is displayed in the left navbar? it's possible?

Reorder Policy issue

I've enabled table reordering records using spatie/eloquent-sortable, so I'm getting this issue on reorder ability :

public function reorder(User $user, Lesson $lesson)
   {
       return $user->can('reorder_lesson');
   }

The issue :
Too few arguments to function App\Policies\LessonPolicy::reorder(), 1 passed in .../vendor/laravel/framework/src/Illuminate/Auth/Access/Gate.php on line 798 and exactly 2 expected

Thanks

Policy is not enforced for plugin resources

When using plugins for filament like 3x1io/filament-translations or stephenjude/filament-blog the policy is not enforced:
I've created a limited role with no permissions for Post (part of blog plugin). When I login with this user I can still see the posts menu and can do everything inside.
This is a problem only with the plugins...

I can access role page and edit role without permission

Hello,

I have configure a new role without "Role" permission and if i'm log in the account which don't have role permission i view the page and if i edit role and i'm delete "disabled" variable with source i can edit the role.

Screenshots:

Role (super admin account):
image

Role page (new account without permission):
image

Edit role (new account without permission):
image

Paginate Roles / permissions

Hi,

Awesome work again πŸš€

I would like to suggest adding pagination to the roles' tabs considering the fact that it may be heavy to load hundreds of permissions at once in the case of a high number of resources for example.

Thank you again

Getting 500 error on all shield pages except index page

Hi, I am using this package for roles and permissions. It was working absolutely fine but now it is throwing 500 error on all pages of the shield except the index page. I am able to see a list of roles and nothing else.

Also, I am unable to debug it as well. It is not showing any error even after enabling the debug mode.

Screenshot 2022-07-21 at 6 12 01 PM

Cannot restrict user from editing another user's entries

Hi,
Not sure if this is a problem on my end, or not, so hoping someone can help.

I've got the roles for a Timer resource set up as follows:

image

I think this means that the user can create/edit/delete/view their own Timers, but not someone else's.

User 3 has the following Timer currently set up:
image

However, if I log in as user 3 then go to the edit page for a Timer for user 1, I get the form to edit the Timer, and the changes are saved:
image

Shouldn't the form reject User 3 when they try to edit user 1's entry?

Regards,
Andy

Unnecessary Snake Case?

In the ViewShieldSettings.php file, the following code exists:

Forms\Components\TextInput::make('super_admin.name')
    ->label(__('filament-shield::filament-shield.labels.super_admin.text_input'))
    ->afterStateHydrated(function ($set, $state) {
        $set('super_admin.name', Str::of($state)->snake()->toString());
    })
    ->visible(fn ($get) => $get('super_admin.enabled'))
    ->required(fn ($get) => $get('super_admin.enabled')),

The afterStateHydrated() portion of that code does not exist for this similar block of code:

Forms\Components\TextInput::make('filament_user.name')
    ->label(__('filament-shield::filament-shield.labels.filament_user.text_input'))
    ->visible(fn ($get) => $get('filament_user.enabled'))
    ->required(fn ($get) => $get('filament_user.enabled'))

It doesn't seem to make that it's necessary to convert super_admin.name to snake case. Regardless, it would seem that either both super_admin.name and filament_user.name should be converted to snake case or both should not be. Happy to submit a PR if you can tell me which you'd prefer (and if there is a reason to convert to snake case or not).

For what it's worth, I think it would be nice if the name variables did not need to be snake case, as I prefer naming something Super Admin versus super_admin- especially when that is what users will see when assigning roles via the admin.

It generates policies without using guard

I have two guards web for frontend for User model and admin guard for filament for Admin model.

So in filament.php config file I have:

'auth'   => [
        'guard' => env('FILAMENT_AUTH_GUARD',  'admin'),
        'pages' => [
            'login' => \Filament\Http\Livewire\Auth\Login::class,
        ],
    ],

when I use php artisan shield:install or generate from the admin panel it generates the policies for the default gaurd not for the filament guard

Problem with custom permissions

Hello, I'm trying to add a custom permission import only to a specific entity project.

The problem is when I add this permission to prefixes > resource array, the permission is added to all entities.

'prefixes' => [
        'resource' => [
            'view',
            'view_any',
            'create',
            'delete',
            'delete_any',
            'update',
            'import'  //custom permission
        ],
        'page'  =>  'view',
        'widget' => 'view'
    ],

How can I add this import permission to only project entity? Is that possible?

There is a problem creating the user

There is a problem creating the user. The user in my database does not have a name column. How can I create a super_admin when it asks "Creating Super Admin ..."?

public function up()
{
    Schema::create('users', function (Blueprint $table) {
        $table->id();
        $table->string('first_name');
        $table->string('last_name');
        $table->string('phone')->nullable();
        $table->string('avatar')->nullable();
        $table->string('email')->unique();
        $table->timestamp('email_verified_at')->nullable();
        $table->string('password');
        $table->rememberToken();
        $table->timestamps();
        $table->softDeletes();
    });
}

How to protect the "Roles" resource?

I create a new user with a new role and gave it no permissions, but I am still able to list/create/edit roles with that user? How to prevent that? I can't find a way.

Thanks.

Empty permision list for resources

Hello
I just updated from v1 to v2 but I have a problem.
In Edit page of a Role, there is no permissions to be selected for resources:
image

what did I wrong?

How attribute a role on a user ?

Hi all

I installed the filament shield plugin after following the instructions on https://github.com/bezhanSalleh/filament-shield
The role management is well integrated but i don't know how i can attribute a role on users.
There is no explanation on how associate a role on user except

Add the Spatie\Permission\Traits\HasRoles trait to your User model(s):
use Illuminate\Foundation\Auth\User as Authenticatable;
use Spatie\Permission\Traits\HasRoles;

class User extends Authenticatable
{
use HasRoles;
//.....
}
roles
users

Custom Navigation Group

Hi there, I can't seem to place this plugin into a custom nav group - I want to place access to this plugin, so it can sit with the rest of my nav items under 'System' nav group.

These seem to be the only 3 nav options we have:

    'shield_resource' => [
        'navigation_sort' => -1,
        'navigation_badge' => true,
        'navigation_group' => false,

Would like something like:

    'shield_resource' => [
        'navigation_custom_group' => 'System',

Missing Permissions

Currently, the DefaultPolicy stub has methods for the following:

  • viewAny
  • view
  • create
  • update
  • delete
  • deleteAny

By default, when using the --model flag, Laravel policies also contain methods for:

  • restore
  • forceDelete

Additionally, Filament also looks for the following policy methods:

  • forceDeleteAny
  • replicate
  • restore
  • restoreAny

I'd love to PR the addition of these other six methods by default, along with default model permissions for each. Would you be open to this?

Widgets defined in sub folder cause exception to the package

I have a sub folder on my widgets directory to organize widgets. Then i realized bcoz of that, your package can not do its job which i will explain why:

My widgets are something like:
image

in
\BezhanSalleh\FilamentShield\Resources\RoleResource::getWidgetEntityPermissionSchema()
you call
FilamentShield::getLocalizedWidgetLabel($widget)
then bcoz of sub folder, value of $widget would be something like _my_sub_folder_surveys_report_overview
then in transformClassString() function you can not find class name and return empty string, then in this call
$parent = get_parent_class($class);
$class would be empty and cause this nice exception:
get_parent_class(): Argument 1 ($object_or_class) must be an object or a valid class name, string given

I think you should consider such situations.
Thanks

Trouble upgrading from 1.1.12 to 2.1.0

When launching the php artisan shield:upgrade command I get an error related to migrations
I'm using postgres as database

$ php artisan shield:upgrade
shield upgraded.
***************************************************
*     Following operations will be performed:     *
***************************************************

-  Publishes core package config
-  Publishes core package migration
   - On fresh applications database will be migrated
   - You can also force this behavior by supplying the --fresh option
-  Creates a filament user
   - Assigns Super Admin role if enabled in config
   - And/Or Assigns Filament User role if enabled in config
-  Discovers filament resources and generates Permissions and Policies accordingly
   - Will override any existing policies if available

 Do you wish to continue? (yes/no) [yes]:
 > yes

   INFO  Publishing assets.  

  File [config/permission.php] already exists .............................................................................................. SKIPPED  
  File [database/migrations/2022_06_06_164730_create_permission_tables.php] already exists ................................................. SKIPPED  

Core Package config published.
   INFO  Publishing [filament-shield-config] assets.  

  Copying file [vendor/bezhansalleh/filament-shield/config/filament-shield.php] to [config/filament-shield.php] ............................... DONE

PDOException: SQLSTATE[2BP01]: Dependent objects still exist: 7 ERROR:  cannot drop table permissions because other objects depend on it
DETAIL:  constraint model_has_permissions_permission_id_foreign on table model_has_permissions depends on table permissions
constraint role_has_permissions_permission_id_foreign on table role_has_permissions depends on table permissions
HINT:  Use DROP ... CASCADE to drop the dependent objects too. in /code/vendor/laravel/framework/src/Illuminate/Database/Connection.php:544
Stack trace:
#0 /code/vendor/laravel/framework/src/Illuminate/Database/Connection.php(544): PDOStatement->execute()
#1 /code/vendor/laravel/framework/src/Illuminate/Database/Connection.php(752): Illuminate\Database\Connection->Illuminate\Database\{closure}('DROP TABLE IF E...', Array)
#2 /code/vendor/laravel/framework/src/Illuminate/Database/Connection.php(719): Illuminate\Database\Connection->runQueryCallback('DROP TABLE IF E...', Array, Object(Closure))
#3 /code/vendor/laravel/framework/src/Illuminate/Database/Connection.php(545): Illuminate\Database\Connection->run('DROP TABLE IF E...', Array, Object(Closure))
#4 /code/vendor/laravel/framework/src/Illuminate/Database/DatabaseManager.php(462): Illuminate\Database\Connection->statement('DROP TABLE IF E...')
#5 /code/vendor/laravel/framework/src/Illuminate/Support/Facades/Facade.php(338): Illuminate\Database\DatabaseManager->__call('statement', Array)
#6 /code/vendor/bezhansalleh/filament-shield/src/Commands/MakeShieldInstallCommand.php(110): Illuminate\Support\Facades\Facade::__callStatic('statement', Array)
#7 /code/vendor/laravel/framework/src/Illuminate/Collections/Traits/EnumeratesValues.php(264): BezhanSalleh\FilamentShield\Commands\MakeShieldInstallCommand->BezhanSalleh\FilamentShield\Commands\{closure}('permissions', 0)
#8 /code/vendor/bezhansalleh/filament-shield/src/Commands/MakeShieldInstallCommand.php(110): Illuminate\Support\Collection->each(Object(Closure))
#9 /code/vendor/bezhansalleh/filament-shield/src/Commands/MakeShieldInstallCommand.php(53): BezhanSalleh\FilamentShield\Commands\MakeShieldInstallCommand->install(true)
#10 /code/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(36): BezhanSalleh\FilamentShield\Commands\MakeShieldInstallCommand->handle()
#11 /code/vendor/laravel/framework/src/Illuminate/Container/Util.php(41): Illuminate\Container\BoundMethod::Illuminate\Container\{closure}()
#12 /code/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(93): Illuminate\Container\Util::unwrapIfClosure(Object(Closure))
#13 /code/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(37): Illuminate\Container\BoundMethod::callBoundMethod(Object(Illuminate\Foundation\Application), Array, Object(Closure))
#14 /code/vendor/laravel/framework/src/Illuminate/Container/Container.php(651): Illuminate\Container\BoundMethod::call(Object(Illuminate\Foundation\Application), Array, Array, NULL)
#15 /code/vendor/laravel/framework/src/Illuminate/Console/Command.php(139): Illuminate\Container\Container->call(Array)
#16 /code/vendor/symfony/console/Command/Command.php(308): Illuminate\Console\Command->execute(Object(Symfony\Component\Console\Input\ArrayInput), Object(Illuminate\Console\OutputStyle))
#17 /code/vendor/laravel/framework/src/Illuminate/Console/Command.php(124): Symfony\Component\Console\Command\Command->run(Object(Symfony\Component\Console\Input\ArrayInput), Object(Illuminate\Console\OutputStyle))
#18 /code/vendor/laravel/framework/src/Illuminate/Console/Concerns/CallsCommands.php(68): Illuminate\Console\Command->run(Object(Symfony\Component\Console\Input\ArrayInput), Object(Illuminate\Console\OutputStyle))
#19 /code/vendor/laravel/framework/src/Illuminate/Console/Concerns/CallsCommands.php(28): Illuminate\Console\Command->runCommand('shield:install', Array, Object(Illuminate\Console\OutputStyle))
#20 /code/vendor/bezhansalleh/filament-shield/src/Commands/MakeShieldUpgradeCommand.php(44): Illuminate\Console\Command->call('shield:install', Array)
#21 /code/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(36): BezhanSalleh\FilamentShield\Commands\MakeShieldUpgradeCommand->handle()
#22 /code/vendor/laravel/framework/src/Illuminate/Container/Util.php(41): Illuminate\Container\BoundMethod::Illuminate\Container\{closure}()
#23 /code/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(93): Illuminate\Container\Util::unwrapIfClosure(Object(Closure))
#24 /code/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(37): Illuminate\Container\BoundMethod::callBoundMethod(Object(Illuminate\Foundation\Application), Array, Object(Closure))
#25 /code/vendor/laravel/framework/src/Illuminate/Container/Container.php(651): Illuminate\Container\BoundMethod::call(Object(Illuminate\Foundation\Application), Array, Array, NULL)
#26 /code/vendor/laravel/framework/src/Illuminate/Console/Command.php(139): Illuminate\Container\Container->call(Array)
#27 /code/vendor/symfony/console/Command/Command.php(308): Illuminate\Console\Command->execute(Object(Symfony\Component\Console\Input\ArgvInput), Object(Illuminate\Console\OutputStyle))
#28 /code/vendor/laravel/framework/src/Illuminate/Console/Command.php(124): Symfony\Component\Console\Command\Command->run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Illuminate\Console\OutputStyle))
#29 /code/vendor/symfony/console/Application.php(998): Illuminate\Console\Command->run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#30 /code/vendor/symfony/console/Application.php(299): Symfony\Component\Console\Application->doRunCommand(Object(BezhanSalleh\FilamentShield\Commands\MakeShieldUpgradeCommand), Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#31 /code/vendor/symfony/console/Application.php(171): Symfony\Component\Console\Application->doRun(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#32 /code/vendor/laravel/framework/src/Illuminate/Console/Application.php(102): Symfony\Component\Console\Application->run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#33 /code/vendor/laravel/framework/src/Illuminate/Foundation/Console/Kernel.php(129): Illuminate\Console\Application->run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#34 /code/artisan(37): Illuminate\Foundation\Console\Kernel->handle(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#35 {main}

Next Illuminate\Database\QueryException: SQLSTATE[2BP01]: Dependent objects still exist: 7 ERROR:  cannot drop table permissions because other objects depend on it
DETAIL:  constraint model_has_permissions_permission_id_foreign on table model_has_permissions depends on table permissions
constraint role_has_permissions_permission_id_foreign on table role_has_permissions depends on table permissions
HINT:  Use DROP ... CASCADE to drop the dependent objects too. (SQL: DROP TABLE IF EXISTS permissions) in /code/vendor/laravel/framework/src/Illuminate/Database/Connection.php:759
Stack trace:
#0 /code/vendor/laravel/framework/src/Illuminate/Database/Connection.php(719): Illuminate\Database\Connection->runQueryCallback('DROP TABLE IF E...', Array, Object(Closure))
#1 /code/vendor/laravel/framework/src/Illuminate/Database/Connection.php(545): Illuminate\Database\Connection->run('DROP TABLE IF E...', Array, Object(Closure))
#2 /code/vendor/laravel/framework/src/Illuminate/Database/DatabaseManager.php(462): Illuminate\Database\Connection->statement('DROP TABLE IF E...')
#3 /code/vendor/laravel/framework/src/Illuminate/Support/Facades/Facade.php(338): Illuminate\Database\DatabaseManager->__call('statement', Array)
#4 /code/vendor/bezhansalleh/filament-shield/src/Commands/MakeShieldInstallCommand.php(110): Illuminate\Support\Facades\Facade::__callStatic('statement', Array)
#5 /code/vendor/laravel/framework/src/Illuminate/Collections/Traits/EnumeratesValues.php(264): BezhanSalleh\FilamentShield\Commands\MakeShieldInstallCommand->BezhanSalleh\FilamentShield\Commands\{closure}('permissions', 0)
#6 /code/vendor/bezhansalleh/filament-shield/src/Commands/MakeShieldInstallCommand.php(110): Illuminate\Support\Collection->each(Object(Closure))
#7 /code/vendor/bezhansalleh/filament-shield/src/Commands/MakeShieldInstallCommand.php(53): BezhanSalleh\FilamentShield\Commands\MakeShieldInstallCommand->install(true)
#8 /code/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(36): BezhanSalleh\FilamentShield\Commands\MakeShieldInstallCommand->handle()
#9 /code/vendor/laravel/framework/src/Illuminate/Container/Util.php(41): Illuminate\Container\BoundMethod::Illuminate\Container\{closure}()
#10 /code/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(93): Illuminate\Container\Util::unwrapIfClosure(Object(Closure))
#11 /code/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(37): Illuminate\Container\BoundMethod::callBoundMethod(Object(Illuminate\Foundation\Application), Array, Object(Closure))
#12 /code/vendor/laravel/framework/src/Illuminate/Container/Container.php(651): Illuminate\Container\BoundMethod::call(Object(Illuminate\Foundation\Application), Array, Array, NULL)
#13 /code/vendor/laravel/framework/src/Illuminate/Console/Command.php(139): Illuminate\Container\Container->call(Array)
#14 /code/vendor/symfony/console/Command/Command.php(308): Illuminate\Console\Command->execute(Object(Symfony\Component\Console\Input\ArrayInput), Object(Illuminate\Console\OutputStyle))
#15 /code/vendor/laravel/framework/src/Illuminate/Console/Command.php(124): Symfony\Component\Console\Command\Command->run(Object(Symfony\Component\Console\Input\ArrayInput), Object(Illuminate\Console\OutputStyle))
#16 /code/vendor/laravel/framework/src/Illuminate/Console/Concerns/CallsCommands.php(68): Illuminate\Console\Command->run(Object(Symfony\Component\Console\Input\ArrayInput), Object(Illuminate\Console\OutputStyle))
#17 /code/vendor/laravel/framework/src/Illuminate/Console/Concerns/CallsCommands.php(28): Illuminate\Console\Command->runCommand('shield:install', Array, Object(Illuminate\Console\OutputStyle))
#18 /code/vendor/bezhansalleh/filament-shield/src/Commands/MakeShieldUpgradeCommand.php(44): Illuminate\Console\Command->call('shield:install', Array)
#19 /code/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(36): BezhanSalleh\FilamentShield\Commands\MakeShieldUpgradeCommand->handle()
#20 /code/vendor/laravel/framework/src/Illuminate/Container/Util.php(41): Illuminate\Container\BoundMethod::Illuminate\Container\{closure}()
#21 /code/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(93): Illuminate\Container\Util::unwrapIfClosure(Object(Closure))
#22 /code/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(37): Illuminate\Container\BoundMethod::callBoundMethod(Object(Illuminate\Foundation\Application), Array, Object(Closure))
#23 /code/vendor/laravel/framework/src/Illuminate/Container/Container.php(651): Illuminate\Container\BoundMethod::call(Object(Illuminate\Foundation\Application), Array, Array, NULL)
#24 /code/vendor/laravel/framework/src/Illuminate/Console/Command.php(139): Illuminate\Container\Container->call(Array)
#25 /code/vendor/symfony/console/Command/Command.php(308): Illuminate\Console\Command->execute(Object(Symfony\Component\Console\Input\ArgvInput), Object(Illuminate\Console\OutputStyle))
#26 /code/vendor/laravel/framework/src/Illuminate/Console/Command.php(124): Symfony\Component\Console\Command\Command->run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Illuminate\Console\OutputStyle))
#27 /code/vendor/symfony/console/Application.php(998): Illuminate\Console\Command->run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#28 /code/vendor/symfony/console/Application.php(299): Symfony\Component\Console\Application->doRunCommand(Object(BezhanSalleh\FilamentShield\Commands\MakeShieldUpgradeCommand), Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#29 /code/vendor/symfony/console/Application.php(171): Symfony\Component\Console\Application->doRun(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#30 /code/vendor/laravel/framework/src/Illuminate/Console/Application.php(102): Symfony\Component\Console\Application->run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#31 /code/vendor/laravel/framework/src/Illuminate/Foundation/Console/Kernel.php(129): Illuminate\Console\Application->run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#32 /code/artisan(37): Illuminate\Foundation\Console\Kernel->handle(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#33 {main}
Freshening up shield migrations.
   INFO  Running migrations.  

  2022_06_06_164730_create_permission_tables .............................................................................................. 7ms FAIL

   Illuminate\Database\QueryException 

  SQLSTATE[42P07]: Duplicate table: 7 ERROR:  relation "permissions" already exists (SQL: create table "permissions" ("id" bigserial primary key not null, "name" varchar(255) not null, "guard_name" varchar(255) not null, "created_at" timestamp(0) without time zone null, "updated_at" timestamp(0) without time zone null))

  at vendor/laravel/framework/src/Illuminate/Database/Connection.php:759
    755β–•         // If an exception occurs when attempting to run a query, we'll format the error
    756β–•         // message to include the bindings with SQL, which will make this exception a
    757β–•         // lot more helpful to the developer instead of just the database's errors.
    758β–•         catch (Exception $e) {
  ➜ 759β–•             throw new QueryException(
    760β–•                 $query, $this->prepareBindings($bindings), $e
    761β–•             );
    762β–•         }
    763β–•     }

      +9 vendor frames 
  10  database/migrations/2022_06_06_164730_create_permission_tables.php:35
      Illuminate\Support\Facades\Facade::__callStatic("create")

      +49 vendor frames 
  60  artisan:37
      Illuminate\Foundation\Console\Kernel::handle(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))

Can I set custom labels?

Hi and thanks for the awesome package!
Q: Can some titles be translated? See picture. 1 - display the resource's $label property. 2 - redefine title in another language. 3 - specify an arbitrary title more understandable to managers. At the same time, do not change the values ​​themselves.
111

How to associate a role to a user?

I installed shield and created few roles with permissions, I don't see any visual way to assign a role to a user? How can we do that?

the permission 'view' not work alone

I need to give the user only the permission 'view' to show a specific Post on the view page but this does not work it shows a 403 error, to make it work I need to add the permission 'view any'

and I don't want to give the user the permission 'view any' to show all the posts

laravel => v9.11
filament => v2.11.10
filament-shield => v1.1

Method Illuminate\Support\Stringable::toString does not exist.

It seems toString is not a function in this set of packages:

bezhansalleh/filament-shield      v2.0.4
filament/filament                 v2.14.4
laravel/framework                 v8.83.21
spatie/laravel-permission         5.5.5

route:
/shield/roles/settings

file:
\BezhanSalleh\FilamentShield\Resources\RoleResource\Pages\ViewShieldSettings::getFormSchema():54
and also here:
\BezhanSalleh\FilamentShield\FilamentShield::getResources():104

I dont know about this toString() function but it seems there is no such function in my Stringable class

roles and permission

Hii, When I install filament-shield(roles and permissions) my resources on the dashboard are hidden automatically. <-how do I resolve this issue?

Install filamet-shield

After following your instructions, i have this error message πŸ‘
Unable to locate a class or view for component [filament-shield::filament-shield.nav.role.icon]

What's wrong ?

Filament Shield permissions are not applying on some pages

I've installed laravel 9.x version with filament, filament-shield, spatie laravel-permission, filament blog, and some other packages. Everything is working fine but the filament shield permissions are not working correctly.

This is my normal user role settings and I have disabled all permissions to the normal user role except the dashboard page, but the user can still see all the pages in his account except the "Roles" and "Users" pages. the permissions are just implemented on these two pages, the rest of the pages are still showing in the user account.

https://www.linkpicture.com/q/filament.png

What can be the issue, I've installed all the packages with the documentation given on the packages documentation page?

Compatibiltiy with filament/spatie-laravel-settings-plugin

Thank you for the package. I wanted to restrict access to my Settings Pages generated with spatie-laravel-settings-plugin. I tried to use the HasPageSheild trait however this came back with:

Declaration of BezhanSalleh\FilamentShield\Traits\HasPageShield::mount() must be compatible with Filament\Pages\SettingsPage::mount(): void

because of the redirect in the mount method in the trait.

Any suggestions of a workaround/potential guidance for a PR?

Dashboard Permission Not Working

only admin users have permission to see the dashboard but all users can see the dashboard even if they do have not any role. the widget was also having the same issue then I solved it with the manual assignment of permissions but I'm not able to find the way for the dashboard is there any way to manually assign the permission to the dashboard? because auto assignment is not working.

shield:generate - Enable "exclude" by default

Hi,

First of all, thank you for this amazing plugin.

I suggest enabling exclude by default (or at least display a warning + prompt for existing Policies) because it may override custom rules.

Keep up the great work πŸŽ‰

Filament Global Search enabled when this plugin is installed

Hi there

I require the Filament Global Search to be disabled while using this plugin. It's disabled on all my resources, but I need this added to the RoleResource.php file:

protected static bool $isGloballySearchable = false;

The only way I can override this is by duplicating the RoleResource.php file into my resources and adding the above line. Any chance we can get this added to Filament Shield package as a config/flag ?

Please see this discussion on disabling the Global Search: filamentphp/filament#3420

Do not write changes made by UI to config file.

In terms of version control and automated deployments I thinks it's not the best practice that this packages writes/modifies the config/filament-shield.php file.

Any changes written there would be gone after a new code deployments. I think it's good to have config values as defaults from this file but not to store any changes made by UI in there.

Anyway, this package is great!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.