szopen / simple-access-control
基于描述标签定义的操作的权限检查系统
Requires
- php: ^8.0|^8.1|^8.2
- webmozart/assert: ^1.11
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.20
- phpunit/phpunit: ^10.2
- vimeo/psalm: ^5.13
This package is auto-updated.
Last update: 2024-09-10 17:26:38 UTC
README
本项目是一个简单的系统,用于检查关于文本标签操作权限。
基本概念是,您可以定义一个描述可能过程的操作,然后可以定义一个权限,允许或拒绝该操作。
<?php // Defines the action with a label identifier $productDetailViewAction = new Action('product.detail.view'); // Defines the permission that allow to view the product detail $canViewProductDetailPermission = new Permission($productDetailViewAction, true);
层次权限
您可以以这样的方式定义操作标签,使其表现得像一个层次结构。基本思想是使用一系列名词,用任意字符串分隔,以创建父子关系。这样,就可以为整个操作家族定义权限。
操作名称解析策略
前面章节中提到的是使用ActionNameParserStrategy实现的,该策略定义了如何解析Action标签并将其分割成一组单独的元素,其序列定义了父子关系的路径。已经定义了两种策略
- NullActionNameParserStrategy:不执行任何操作,将标签视为单个字符串,不将其拆分;
- DotSeparatedActionNameParserStrategy:使用点
.字符作为分隔符解析操作标签;
// Defines the parser strategy $dotSeparatedParser = new DotSeparatedActionNameParserStrategy(); // Defines two action that are related $productAction = new Action('product', $dotSeparatedParser); // `product` is the root // `detail` is the child of product // `view` child of detail and nephew of product $productDetailViewAction = new Action('product.detail.view', $dotSeparatedParser);
这样,可以定义例如,一个授予根product权限的权限,这样拥有此权限的人也将被授予product(例如,product.detail.view)的“子”操作的所有权限,基于决策策略。
权限检查策略
使用PermissionCheckerStrategy,可以检查给定的Action是否允许与PermissionsCollection进行比较。已经定义了两种类型的策略
- Affirmative:只要有权限授予访问权限,就授予访问权限;
- Unanimous:只有在没有权限拒绝访问的情况下才授予访问权限。
<?php $permissions = [ new Permission(new Action('product.detail.view'), true), new Permission(new Action('product.detail.edit'), false), ]; $strategy = new AffirmativePermissionCheckerStrategy(); // This returns `true` $isAllowed = $strategy->canPerformAction( new Action('product.detail.view'), new PermissionsCollection($permissions) );
使用层次功能,如果父操作的权限被授予,则使用AffirmativePermissionCheckerStrategy授予子操作
<?php // Defines the parser strategy $dotSeparatedParser = new DotSeparatedActionNameParserStrategy(); $permissions = [ new Permission(new Action('product', $dotSeparatedParser), true), new Permission(new Action('product.detail.edit', $dotSeparatedParser), false), ]; $strategy = new AffirmativePermissionCheckerStrategy(); // This returns `true` $isAllowed = $strategy->canPerformAction( new Action('product.detail.edit', $dotSeparatedParser), new PermissionsCollection($permissions) );
如果未定义针对操作的权限,则策略将始终拒绝操作。
<?php $permissions = [ new Permission(new Action('product.detail.view'), true), new Permission(new Action('product.detail.edit'), false), ]; $strategy = new AffirmativePermissionCheckerStrategy(); // This returns `false` $isAllowed = $strategy->canPerformAction( // This action is not associated to any permission in the collection new Action('product.add'), new PermissionsCollection($permissions) );
服务
作为常见用例,该包提供了一个UserAuthorizationService,该服务给定一个UserWithPermission和一个Action,能够检查用户是否有权执行该操作。UserWithPermission是辅助接口,您必须实现它以利用此服务。
<?php final class MyDomainUser implements UserWithPermission { // some code... public function getPermissions(): PermissionsCollection { return new PermissionsCollection([ new Permission(new Action('product.detail.view'), true), new Permission(new Action('product.detail.edit'), false), ]); } }
然后是服务。
<?php $user = new MyDomainUser(); $service = new UserAuthorizationService( new AffirmativePermissionCheckerStrategy() ); // This returns `false` $isAllowed = $service->canUserPerformAction($user, new Action('product.detail.edit'));
测试
要运行所有测试,请执行composer test