OroCRM 实体创建后修改访问控制列表(ACL)权限
2025-02-27 00:44:12
OROCRM 中创建实体后修改访问控制列表 (ACL)
我碰到了一个问题, 就是在 OROCRM 里创建完实体之后,想修改它的权限,折腾了半天,现在把我的处理经过总结一下。
一、 问题的产生
一开始,我创建实体的时候,权限配置是这样的:
/**
* @ORM\Entity
* @ORM\Table(name="my_table")
* @ORM\HasLifecycleCallbacks()
* @Config(
* routeView="my_route_view",
* defaultValues={
* "security"={
* "type"="ACL",
* "group_name"="",
* "permissions"="VIEW"
* },
* "entity"={
* "icon"="fa-briefcase"
* },
* "dataaudit"={
* "auditable"=false
* }
* }
* )
*
*/
看到了吧,permissions
那里,我只给了 VIEW
,也就是查看的权限。 结果,系统就只给我生成了查看权限的 ACL。
后来我需要给这个实体加上创建、更新、删除的权限。 我试了两种方法:
- 把
permissions
属性去掉:
/**
* @ORM\Entity
* @ORM\Table(name="pb_inventory_synchronization_queue")
* @ORM\HasLifecycleCallbacks()
* @Config(
* routeView="pb_inventory_synchronization_queue_view",
* defaultValues={
* "security"={
* "type"="ACL",
* "group_name"=""
* },
* "entity"={
* "icon"="fa-briefcase"
* },
* "dataaudit"={
* "auditable"=false
* }
* }
* )
*
*/
- 把所有权限都明确写出来:
/**
* @ORM\Entity
* @ORM\Table(name="pb_inventory_synchronization_queue")
* @ORM\HasLifecycleCallbacks()
* @Config(
* routeView="pb_inventory_synchronization_queue_view",
* defaultValues={
* "security"={
* "type"="ACL",
* "group_name"="",
* "permissions"="VIEW;EDIT;DELETE;CREATED;"
* },
* "entity"={
* "icon"="fa-briefcase"
* },
* "dataaudit"={
* "auditable"=false
* }
* }
* )
*
*/
可惜,这两种办法都不好使。 在角色管理界面,还是只能看到查看权限。 通过 API 创建、编辑、删除的时候,直接报 403 错误,提示:
No access to this type of entities.
二、问题的原因
OROCRM 在创建实体的时候,会根据 @Config
注解里的 security
部分生成 ACL。 如果 permissions
属性只指定了部分权限, 它就只生成这些权限的 ACL, 后面再想改, 直接在注解里改是不行的。 OROCRM 不会因为你改了注解,就自动更新 ACL。
三、 解决方案
要解决这个问题,得用 OROCRM 提供的命令行工具,或者直接操作数据库。
1. 使用 oro:acl:update
命令
这是最推荐的方法。
-
原理:
oro:acl:update
命令会重新扫描所有实体类的@Config
注解,并更新 ACL。 -
操作步骤:
-
修改实体类的
@Config
注解,把permissions
设置成你想要的权限,比如"permissions"="VIEW;CREATE;UPDATE;DELETE"
,或者直接把 "permission" 属性去掉. 让 OROCRM 使用默认权限. -
在命令行里,进入到你的 OROCRM 项目根目录。
-
执行以下命令:
php bin/console oro:acl:update --env=prod
--env=prod
表示在生产环境下执行。如果是开发环境,改成--env=dev
。 -
清理缓存:
php bin/console cache:clear --env=prod
-
登录 OROCRM 后台管理检查权限设置。
-
-
进阶技巧:
-
如果只想更新某个特定实体的 ACL, 可以用
--class
参数指定实体类名:php bin/console oro:acl:update --class="Acme\\Bundle\\Entity\\MyEntity" --env=prod
把
Acme\\Bundle\\Entity\\MyEntity
换成你自己的实体类名。 -
oro:acl:update
只会更新现有的 ACL, 不会删除多余的。如果有需要, 可以配合--flush
选项,强制刷新.
-
2. 使用 oro:entity-config:update
命令
这个命令用来更新实体配置,包括 ACL。
-
原理:
oro:entity-config:update
会重新读取实体配置,并更新数据库里的相关记录。 -
操作步骤:
-
修改实体类的
@Config
注解,配置好permissions
。 -
运行命令:
php bin/console oro:entity-config:update <entity-class-name> --env=prod
<entity-class-name>
换成你的实体类名。 -
清理缓存:
php bin/console cache:clear --env=prod
-
3.直接修改数据库 (不推荐, 仅供参考)
这种方法比较危险,容易出错,不到万不得已,别用.
-
原理: OROCRM 的 ACL 信息存储在几个表里,主要是
acl_classes
、acl_entries
、acl_object_identities
、acl_security_identities
。 可以直接修改这些表里的数据。 -
操作步骤(非常粗略,可能有遗漏):
- 找到你的实体对应的
acl_classes
表里的记录, 记录下id
。 - 在
acl_entries
表里, 找到class_id
等于上面那个id
的记录, 这里就是你的实体的各项权限。 - 根据需要, 添加、修改或删除
acl_entries
表里的记录。比如, 要添加创建权限, 就插入一条新记录,permission
字段设置为CREATE
。 - 可能还需要修改
acl_object_identities
和acl_security_identities
表,具体怎么改, 取决于你的权限设置。 - 改完之后,一定要清理缓存!
- 找到你的实体对应的
4. 使用Migration
-
原理: 使用数据库迁移脚本修改ACL定义。
-
操作步骤:
- 创建一个 Migration:
随便起一个名字。php bin/console make:migration
- 在新生成的 Migration 文件(
src/Migrations/Version<版本号>.php
)中的up()
函数下加入代码:
<?php declare(strict_types=1); namespace DoctrineMigrations; use Doctrine\DBAL\Schema\Schema; use Doctrine\Migrations\AbstractMigration; use Oro\Bundle\SecurityBundle\Acl\Extension\EntityAclExtension; use Oro\Bundle\SecurityBundle\Acl\Persistence\AclManager; use Symfony\Component\DependencyInjection\ContainerAwareInterface; use Symfony\Component\DependencyInjection\ContainerAwareTrait; final class Version20231117171005 extends AbstractMigration implements ContainerAwareInterface { use ContainerAwareTrait; public function getDescription(): string { return 'Modify ACL'; } public function up(Schema $schema): void { /** @var AclManager $aclManager */ $aclManager = $this->container->get('oro_security.acl.manager'); if ($aclManager->isAclEnabled()) { $sid = $aclManager->getSid('IS_AUTHENTICATED_FULLY'); // Replace 'IS_AUTHENTICATED_FULLY' by you actual user. $oid = $aclManager->getOid('entity:Your\Entity\Namespace'); // Replace "Your\Entity\Namespace" to your current entity $this->extendEntityAcl( $aclManager, $sid, $oid, [ 'CREATE' => 1, // Enable Create permission at organization level. Replace by bit mask you want. 'DELETE' => 1, // Enable Delete. 'VIEW' => 2, 'EDIT' => 8 ] ); $aclManager->flush(); } } private function extendEntityAcl(AclManager $aclManager, $sid, $oid, array $permissions, int $mask = 0): void { $extension = $aclManager->getExtensionSelector()->selectByObjectIdentity($oid); if (!$extension instanceof EntityAclExtension) { // we can extend only entity ACLs return; } $rootOid = $extension->getRootObjectIdentity($oid); $acl = $aclManager->getAcl($rootOid, [$sid]); $aces = $acl->getClassAces(); //get all ACE for class. It work also for getObjectAces. if(empty($aces)) { $acl = $extension->addPermission($acl, $sid, key($permissions) , $mask,0,false); // Insert new ACE permission } else{ foreach ($permissions as $permission => $permissionMask) { $extension->setPermission($aces[0], $sid, $permission,$permissionMask ,0); } } } public function down(Schema $schema): void { // $this->addSql('ALTER TABLE your_entity_ DROP new_field'); } } ``` 3. 修改`oid`: Replace "Your\Entity\Namespace" to your entity class namespace. 4. 修改`sid`: 获得用户的 Security identity (SID)。如果是针对 Role 设置权限,代码类似 `$aclManager->getSid( new RoleSecurityIdentity($role))` ,其中 `$role` 是 `Oro\Bundle\UserBundle\Entity\Role` 对象。更简单的方法是用 `$aclManager->getSid('IS_AUTHENTICATED_FULLY');`. 保证对应实体有用户访问过,才会生成对应的 SID。如果遇到 "SID does not exist." 错误, 先随便用个有权限的用户登录,访问下相关页面,让系统创建这个 SID。 5. 在 extendEntityAcl 里面的 $permission 里面的数组配置修改权限,以及权限的范围 (Organization, Business Unit, User). 参考:`Oro\Bundle\SecurityBundle\Model\AclPermission` 和 `Oro\Bundle\SecurityBundle\Acl\AccessLevel` 。 3. 执行迁移: ```bash php bin/console doctrine:migrations:migrate ``` 刷新缓存。 ```bash php bin/console cache:clear ```
- 创建一个 Migration:
四、 总结
- 修改已创建实体的 ACL,直接改注解不行,要用命令行工具或者直接操作数据库,使用Migration也是不错的选择。
oro:acl:update
命令最方便。- Migration 方式更为推荐.
- 改完之后,一定要清理缓存。
做 OROCRM 开发,遇到权限问题是家常便饭。希望我的这点总结对大家有点帮助。