Is access handler class meant to be working this way?
idimopoulos opened this issue · comments
Hello, this is possibly a question rather than an issue.
What happens with group content?
When I have a group content entity, e.g. $child
, and I have defined a GroupContentOperationPermission
e.g. do some stuff
in my subscriber, I can properly call $child->access('do some stuff)
, and this will call the access handler, which will call the og_entity_access
hook, which will call eventually \Drupal\og\OgAccess::userAccessEntityOperation
and that will call \Drupal\og\OgAccess::userAccessGroupContentEntityOperation
which will normally check all operations created, including the do some stuff
What happens in groups?
On the other side - this is where my problem lies - when it comes to groups, I have created a \Drupal\og\GroupPermission
through a subscriber. For the $group
group, I expect that calling $group->access('do some stuff')
should have the same effect. However, it does not. After going through the og_entity_access
and into the \Drupal\og\OgAccess::userAccessEntityOperation
where the following check takes place:
if ($this->groupTypeManager->isGroup($entity_type_id, $bundle)) {
// We are performing an entity operation on a group entity. Map the
// operation to the corresponding group level permission.
if (array_key_exists($operation, self::OPERATION_GROUP_PERMISSION_MAPPING)) {
$permission = self::OPERATION_GROUP_PERMISSION_MAPPING[$operation];
// An entity can be a group and group content in the same time. If the
// group returns a neutral result the user still might have access to
// the permission in group content context. So if we get a neutral result
// we will continue with the group content access check below.
$result = $this->userAccess($entity, $permission, $user);
In that part, the operation is indeed do some stuff
but the self::OPERATION_GROUP_PERMISSION_MAPPING
only contains the delete and update mappings and thus never reaches the ::userAccess
method so it never succeeds.
Is that normal? am i missing something here? It is very easy to reproduce this using a test I guess but I wanted to make sure that I am not doing something wrong first.
Changing the above to
if ($this->groupTypeManager->isGroup($entity_type_id, $bundle)) {
// We are performing an entity operation on a group entity. Map the
// operation to the corresponding group level permission.
$permission = array_key_exists($operation, self::OPERATION_GROUP_PERMISSION_MAPPING)
? self::OPERATION_GROUP_PERMISSION_MAPPING[$operation]
: $operation;
// An entity can be a group and group content in the same time. If the
// group returns a neutral result the user still might have access to
// the permission in group content context. So if we get a neutral result
// we will continue with the group content access check below.
$result = $this->userAccess($entity, $permission, $user);
if (!$result->isNeutral()) {
return $result;
}
}
actually fixed my issue and it seems to me like it is normal since the mapping mainly creates a translation from the CRUD operations update
and delete
to update group
and delete group
respectively.
It seems you are mixing up permissions and CRUD operation access checks, it doesn't make sense to call $group->access('do some stuff')
, the only operations that are supported by OG are update
and delete
. We don't consider view access (also not in the D7 version of OG if I am not mistaken), and create access is handled differently in core (through hook_entity_create_access()
).
It looks to me that do some stuff
is the name of a permission. If you want to check if a user has a certain group permission, then use OgAccess::userAccess()
which allows to pass in a permission name.
It is still a bit weird to me however I created a test and managed to get it a bit straight. In my case, I had some very specific cases so the operation was the same as the permission name.
The test proved that it is indeed working fine. The ::userAccessEntity
is the correct way to go. I have discussed this with @pfrenssen in chat as well and it seems that indeed, custom operations with custom permissions should have custom handling in code, either access hook or handler.
Maybe it should be mentioned somewhere though.