rupadana / filament-shield
为 `spatie/laravel-permission` 提供的丝材支持。
Requires
- php: ^8.1
- filament/filament: ^3.0
- spatie/laravel-package-tools: ^1.9
- spatie/laravel-permission: ^5.0
Requires (Dev)
- laravel/pint: ^1.0
- nunomaduro/collision: ^7.0
- nunomaduro/larastan: ^2.1
- orchestra/testbench: ^8.0
- pestphp/pest: ^2.10
- phpstan/extension-installer: ^1.3
- phpstan/phpstan-deprecation-rules: ^1.1
- phpstan/phpstan-phpunit: ^1.3
- phpunit/phpunit: ^10.1
README

盾牌
为您的 Filament Admin 添加访问管理最容易且最直观的方式
- 🔥 资源
- 🔥 页面
- 🔥 小部件
- 🔥 自定义权限
注意
对于 Filament 2.x 请使用 2.x 分支
重要
在 v3.1.0
之前,Shield 支持 spatie/laravel-permission:^5.0
,现在它支持版本 ^6.0
。这涉及到一些关于迁移的破坏性更改。如果您是从 v3.1.0
之前的版本升级,请确保删除旧迁移文件并重新发布新的迁移文件。
安装
- 通过 composer 安装此包
composer require bezhansalleh/filament-shield
- 将
Spatie\Permission\Traits\HasRoles
特性添加到您的用户模型中
use Illuminate\Foundation\Auth\User as Authenticatable; use Spatie\Permission\Traits\HasRoles; class User extends Authenticatable { use HasRoles; // ... }
- 发布
config
文件,然后设置您的配置
php artisan vendor:publish --tag=filament-shield-config
- 为所需的 Filament 面板注册插件
public function panel(Panel $panel): Panel { return $panel ->plugins([ \BezhanSalleh\FilamentShield\FilamentShieldPlugin::make() ]); }
- 现在运行以下命令安装 shield
php artisan shield:install
按照提示操作,并享受使用体验!
Filament 面板
如果您想为多个面板启用 Shield
,则需要像上面提到的那样为每个面板注册插件。
面板访问
Shield 包含 HasPanelShield
特性,该特性提供了一种简单的方法来将 Shield 的约定与 Filament 的面板访问系统集成。
HasPanelShield
特性为 canAccessPanel
方法提供了一种实现,它根据用户是否具有 super_admin
角色或 panel_user
角色来确定访问权限。它还在创建用户时分配 panel_user
角色并在删除时移除它。当然,角色名称可以从插件的配置文件中更改。
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; // ... }
资源
一般来说,Shield 处理了两种情况下您的 Filament
资源的权限。
默认
默认情况下,Shield 处理 Filament
资源预定义的权限。所以如果您只需要这些,您就设置好了。如果您需要添加单个权限(例如 lock
),并且希望它在所有资源中都可用,只需将其追加到以下 config
键
permission_prefixes' => [ 'resource' => [ 'view', 'view_any', 'create', 'update', 'restore', 'restore_any', 'replicate', 'reorder', 'delete', 'delete_any', 'force_delete', 'force_delete_any', 'lock' ], ... ],
💡 现在您可能在想 如果我只需要一个权限仅适用于一个资源怎么办?
没关系,这正是 自定义权限 发挥作用的地方。
自定义权限
为了为每个 Resource
定义自定义权限,您的 Resource
必须实现 HasShieldPermissions
合约。此合约有一个 getPermissionPrefixes()
方法,该方法返回一个包含您的 Resource
权限前缀的数组。
假设您有一个 PostResource
,并且您想要几个预定义的权限以及一个名为 publish_posts
的新权限,这些权限仅适用于 PostResource
。
<?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' ]; } ... }
在上面的示例中,getPermissionPrefixes()
方法返回 Shield 需要生成的权限前缀。
✅ 现在要强制执行 publish_post
权限,请转到您的 PostPolicy
并添加一个 publish()
方法
/** * 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'); }
🅰️/🈯️ 要使前缀可翻译,发布 Shield
的翻译,并在 resource_permission_prefixes_labels
中将前缀作为键,将翻译作为值附加到您需要的语言。
//lang/en/filament-shield.php 'resource_permission_prefixes_labels' => [ 'publish' => 'Publish' ], //lang/es/filament-shield.php 'resource_permission_prefixes_labels' => [ 'publish' => 'Publicar' ],
配置权限标识符
默认情况下,权限标识符的生成方式如下
Str::of($resource) ->afterLast('Resources\\') ->before('Resource') ->replace('\\', '') ->snake() ->replace('_', '::');
例如,如果您有一个如 App\Filament\Resources\Shop\CategoryResource
的资源,则权限标识符将是 shop::category
,然后它会带有您定义的前缀或默认的 Shield 前缀。
如果您想更改默认行为,则可以在服务提供者的 boot()
方法中调用静态 configurePermissionIdentifierUsing()
方法,并向其传递一个闭包以修改逻辑。闭包接收资源的完全限定类名作为 $resource
,这使得您能够访问资源中定义的任何属性或方法。
例如,如果您想使用模型名称作为权限标识符,可以这样做
use BezhanSalleh\FilamentShield\Facades\FilamentShield; FilamentShield::configurePermissionIdentifierUsing( fn($resource) => str($resource::getModel()) ->afterLast('\\') ->lower() ->toString() );
警告 请记住,确保权限标识符的唯一性现在取决于您。
自定义导航组
默认情况下,英文翻译将角色和权限显示为 'Filament Shield' 下的内容。如果您想更改这一点,首先发布 翻译文件 并更改相关区域设置为您的选择组,例如
'nav.group' => 'Filament Shield',
改为
'nav.group' => 'User Management',
将此应用到您有组的每种语言中。
页面
如果您为 Pages
生成权限,您可以切换侧边栏中的页面导航和页面的受限访问。您可以手动设置此操作,但此包附带了一个 HasPageShield
特性来加快此过程。您只需在您的页面中使用此特性即可。
<?php namespace App\Filament\Pages; use ...; use BezhanSalleh\FilamentShield\Traits\HasPageShield; class MyPage extends Page { use HasPageShield; ... }
📕 HasPageShield
使用 booted
方法检查用户的权限,并确保在父页存在的情况下执行 booted
页面方法。
页面钩子
但是,如果您需要在 booted
方法前后执行某些方法,您可以在您的 Filament 页面中声明下一个钩子方法。
<?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() { ... } }
页面重定向路径
HasPageShield
默认使用 config('filament.path')
值进行 Shield 重定向。如果您需要覆盖重定向路径,只需将下一个方法添加到您的页面即可。
<?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
生成权限,您可以根据用户是否有权限切换它们的状态。您可以手动设置此操作,但此包附带了一个 HasWidgetShield
特性来加快此过程。您只需在您的部件中使用此特性即可。
<?php namespace App\Filament\Widgets; use ...; use BezhanSalleh\FilamentShield\Traits\HasWidgetShield; class IncomeWidget extends LineChartWidget { use HasWidgetShield; ... }
策略
角色策略
为了确保通过 RolePolicy
访问 RoleResource
,您需要在您的 AuthServiceProvider
中添加以下内容
//AuthServiceProvider.php ... protected $policies = [ 'Spatie\Permission\Models\Role' => 'App\Policies\RolePolicy', ]; ...
如果您已在 config
中启用它,则可以跳过此步骤。
// config/filament-shield.php ... 'register_role_policy' => [ 'enabled' => true, ], ...
策略路径
如果您的策略不在 app_path()
中的默认 Policies
目录中,您可以在配置文件中更改目录名称。
... 'generator' => [ 'option' => 'policies_and_permissions', 'policy_directory' => 'Policies', ], ...
为模型或第三方插件自定义文件夹结构
Shield 还为具有自定义文件夹结构的第三方插件和 Models
生成策略和权限,为了强制执行生成的策略,您需要在应用程序的 AuthServiceProvider
中注册它们。
...
class AuthServiceProvider extends ServiceProvider
{
...
protected $policies = [
...,
'App\Models\Blog\Author' => 'App\Policies\Blog\AuthorPolicy',
'Ramnzys\FilamentEmailLog\Models\Email' => 'App\Policies\EmailPolicy'
];
用户(将角色分配给用户)
Shield 默认不提供将角色分配给用户的方式,但是您可以使用 Filament Forms
的 Select
或 CheckboxList
组件轻松地将角色分配给用户。在您的用户 Resource
的表单中添加这些组件之一,并按需配置它们。
// 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()
您可以在 Filament 文档 中了解更多关于这些组件的信息。
布局自定义
您可以在不发布资源的情况下轻松自定义 Grid
、Section
和 CheckboxList
的 columns()
和 columnSpan()
。
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, ]), ]); }

翻译
使用以下方法发布翻译:
php artisan vendor:publish --tag="filament-shield-translations"
可用的 Filament Shield 命令
shield:doctor
- 显示有关 Filament Shield 的有用信息。
shield:install
设置核心包要求并安装 Shield。接受以下标志:
--fresh
重新运行迁移--only
仅设置 shield,不生成权限和创建超级管理员
shield:generate
为 Filament 实体生成权限和/或策略。接受以下标志:
--all
为所有实体生成权限/策略--option[=OPTION]
覆盖配置生成器选项(policies_and_permissions
、policies
、permissions
)--resource[=RESOURCE]
一个或多个资源,用逗号(,)分隔--page[=PAGE]
一个或多个页面,用逗号(,)分隔--widget[=WIDGET]
一个或多个小部件,用逗号(,)分隔--exclude
生成时排除指定的实体--ignore-config-exclude
生成时忽略配置exclude
选项--ignore-existing-policies
不覆盖现有策略。
shield:super-admin
创建一个具有超级管理员角色的用户。
- 接受一个
--user=
参数,该参数将使用提供的 ID 查找要成为超级管理员的用户。
shield:publish
- 发布 Shield
RoleResource
并按需进行自定义
shield:seeder
- 通过设置您的角色和权限或添加您自己的种子来轻松部署
测试
composer test
变更日志
有关最近更改的更多信息,请参阅 变更日志。
贡献
有关详细信息,请参阅 贡献指南。
安全漏洞
请查看 我们的安全策略 了解如何报告安全漏洞。
鸣谢
许可协议
MIT 许可协议(MIT)。有关更多信息,请参阅 许可文件。