Closed (fixed)
Project:
Subgroup (Graph)
Version:
1.0.0-alpha3
Component:
Code
Priority:
Normal
Category:
Task
Assigned:
Issue tags:
Reporter:
Created:
27 Sep 2019 at 07:16 UTC
Updated:
7 Jul 2023 at 15:44 UTC
Jump to comment: Most recent, Most recent file
Comments
Comment #2
lobsterr commentedComment #3
catchEither here or in a different issue, we should also add or modify gnode_node_grants() to take into account the same inheritance mappings.
Comment #4
lobsterr commented@catch it is not required. "gnode_node_grants" calls
It will call the permission calculators check
Which will call InheritGroupPermissionCalculator.
Comment #5
catchUnfortunately it doesn't work like that, because the permissions check only happens against groups that the user is actually a direct member of:
Within that loop, we'd need to find the relevant parent/child groups of the current membership group and add them, or we'd have to just load every group on the site instead.
Comment #6
lobsterr commented@catch Yes, It is exactly what we do in InheritGroupPermissionCalculator::calculateAnonymousPermissions and InheritGroupPermissionCalculator::calculateOutsiderPermissions we load not membership we load all group and check mapping of the roles, if we have the mapping we apply permission from the mapped roles. This was the initial idea.
Comment #7
catchOK loading all groups has some scaling issues, but will be a lot simpler than trying to figure out the parent/child group relationships in that foreach so probably a good option.
Comment #8
kkasson commentedI used the following in gnode_node_grants. There's a bit of extra overhead because it will check subgroups that the user may not have inherited roles in, but it's much less than checking every group.
Comment #9
catchThere's a performance issue here though in that rather than doing a single multiple load of groups, we're individually loading the subgroups. So while there are less permission checks, there's more individual database (or cache) queries. The trade-off is going to depend on the specific site, but I think I'd lean towards just loading and checking all the groups, and maybe adding an extra cache layer on top of it.
Comment #10
lobsterr commented@catch Yes, the fetch process of groups is heavy, but it is done ones then it is cached. ChainGroupPermissionCalculator::doCacheableCalculation
Comment #11
catchOne other question here, sort of related to the above. It's quite common to want to get 'all groups the current user is a member of' (using the group membership loader), but the usual methods don't work once you're using subgroups. Should we add new methods for this?
Comment #12
floydm commentedThank you for all of your work separating this module out.
I'm working on a project that has been using the subgroups patches from parent ticket #2736233. We have three levels of groups -- parent, child, grandchild -- with members being added to the child group in order to have access to content in the parent group. Members of the child group also form and join the grandchild groups, and the child group administrators inherit the ability to add and remove members from the grandchild group without actually needing to be added as members to the grandchild groups. We have a couple dozen behat functional tests that we've been running to verify this functionality is working.
We've been pinned to the patch from #244 because some time between that patch and the final patch (#261) on the parent ticket, role inheritance stopped working for us.
Attached is an updated ggroup_role_mapper patch that incorporate a few of the suggestions on this ticket since comment #2 as well as the suggestions on comment #263 on the parent ticket. At least in our case, with these changes in role mapping works now using ggroup and ggroup_role_mapper. All of our tests are passing again. :)
Again, thank you much for all the work you've been doing on this! I hope breaking up the patch into smaller pieces, as you've done, does lead to subgroups and subgroup role mapping making it into the group module before too long.
Comment #13
catchJust to say I'm using this patch on a project (development only at the moment) and #12 seems to be working well (and fixes a bug in #2 with groups inheriting roles from subgroups).
Comment #14
sayco commentedHi, I was using a patch #12 and it truly seems to work fine, however, I have faced some issues when working on main user (uid: 1) and get few notcies:
Notice: Undefined offset: 1 in Drupal\ggroup_role_mapper\Access\InheritGroupPermissionCalculator->getInheritedGroupRoleIdsByMembership() (line 276 of modules/contrib/group/modules/ggroup_role_mapper/src/Access/InheritGroupPermissionCalculator.php).Warning: Invalid argument supplied for foreach() in Drupal\ggroup_role_mapper\Access\InheritGroupPermissionCalculator->calculateMemberPermissions() (line 122 of modules/contrib/group/modules/ggroup_role_mapper/src/Access/InheritGroupPermissionCalculator.php).As a simple workaround, I replaced in the line 276
return $this->mappedRoles[$account_id];with
return $this->mappedRoles[$account_id] ?? [];but I'm not certain if this won't have any implications, also I don't consider that fix as a "clean" solution, I think there might be a problem laying somewhere deep down.
Comment #15
sayco commentedI need to solve the issue that I've mentioned on #14 for the project that I'm currently working on, so here I provide a patch. I introduced a new method
getMappedRolesand additional checkerhasMappedRolesto unify how we handle mapped roles eg. to always return an array - which was the main issue in my case.Comment #16
heddn#11 is a pretty important point. There is a getter for membership on the group entity. But no "isMember" method. And the users are not members of the direct parent group in a sub group situation. In some of my site's custom code we have a lot of
getMember()calls to find if a user is a member, then do something about it. Some type of fixed API for isMember would be nice. Or maybe "give me the roles" would be better and offer greater flexibility.Comment #17
dwkitchen commentedThese functions are a performance issue and need re-thinking.
Might be OK on a site with 10 groups, but testing with my project with 38k it breaks.
I'm wondering why anon and outsider permissions should be included in this.
Comment #18
catchFound a bug/performance issue - some calculated permissions items are being created with SCOPE_GROUP_TYPE instead of SCOPE_GROUP. This means that when SCOPE_GROUP items are retrieved in gnode_node_grants, it's calculating for all a lot of groups mis-labeled as group types.
Updated patch for that.
Comment #19
heddnDid a quick review and the changes here make sense. Reviewing the patch in #15 vs #18, there's an obvious issue w/ using CalculatedGroupPermissionsItemInterface::SCOPE_GROUP_TYPE. The latest patch fixes that.
Comment #20
gorkagr commentedHi!
I have a weird issue with this patch (in theory the subgroup patch in #3084140 works fine), but the moment I enable this submodule, the issue starts.
I will try to explain the steps and the issue (maybe there is smth i am missing to configure):
- I have a group type created
- I have a content type created. Inside the content type, one of the fields is an 'entity_reference' to the group type created (cardinality infinite)
- That field formatter is autocomplete_deluxe (also tested with normal autocomplete)
Users belongs to one or multiple groups.
Before the patch, each time any user create new content of that content type, in the autocomplete field, they get any of the groups that are created in the platform, based on what they type (ok, desired behaviour)
Now, the moment I enable this module and clear the cache, if the user do the same (create new content type), the moment the user types in the autocomplete field, he only get results if the typed matches any of the groups he is member in (and excluding almost all the groups, not good)
If I disable the module and clear the cache, normal behaviour is back (and all the groups can be listed)
It does not matter if I have any relation created between groups or not, the autocomplete works fine with the submodule core enabled.
Any idea?
Comment #21
gorkagr commentedHi again!
The issue i was commenting in 20, it is fixed if I apply the patch in https://www.drupal.org/project/group/issues/3125427
Best,
Comment #22
gorkagr commentedHi (me again)
Either I am doing smth wrong or there is an issue with some of the permissions once this module is enabled, making the logged user not seeing all the content, just the one that belongs to its groups. I explain what i have done, adding the question at the end.
Patches I am using:
- "Support for subgroups": "https://www.drupal.org/files/issues/2019-10-23/subgroup_core-3084140-6.p...",
- "Subgroups role mapper": "https://www.drupal.org/files/issues/2020-03-23/3084153-18.patch"
What i have done in a clean installation, to double check the issue:
- Created new site, applied both mentioned patches.
- Enabled subgroup module only
- Created new content type (CT), created new group and enabled the CT in the group as plugin
- Add some groups and some content to the CT created
- Create a view that list the content of the CT created
- Create 2 users
- Create a view that list all the content CT, with 'unrestricted' access (i have edited frontpage).
- In the permissions of the created group, set "Entity: View content entities" for all (anonymous, outsider, member)
So let's say that I have:
- Group 1, Group2 and Group 3.
- Node 1, node 2, node 3, node 4 and node orphan.
- U1 and U2 as users
Assign Node 1 and node 2 to Group 1; node 3 to group 2; node 4 to group 3.
U1 is member of group 1 and U2 of group 2
So far, all good. If any user (anonymous or logged) visits the page, the front page shows everything.
Now: we enable the subgroup role mapper and do a cache rebuild
- If an anonymous user visits the page, frontpage shows all the nodes
- U1 logs: frontpage shows only Node 1, Node 2 and Node orphan (N1 and N2 because they belong to group 1, and orphan as it doesnt have any group relation)
- U2 logs: frontpage shows Node 3, Node orphan.
If I assign Group 3 as subgroup of group 1 (and map the permissions):
- U1 see also now Node 4 once it logs.
- U2 see the same.
Assigning Node orphan to a G1 or G3 makes it visible only to U1.
Assigning Node orphan to G2 makes it visible only to U2.
My question is:
As the view is 'unrestricted', and all the nodes are visible by all the anonymous, should it be the same if a user is logged in, and see all the nodes in the view, independently if they are assigned or not to a group?
Or I am missing though any settings to be configured?
Thnks!
Comment #23
dbielke1986 commentedHello,
As described in the following note "Programatically add a subgroup to a group", I assign the SubGroup via "$parentGroup->addContent($mySubGroup, 'subgroup:' . $mySubGroup->bundle());". The attached error occurs when I try to assign several groups in a loop.
All of the mentioned (sub)groups definitely exist (at the time of the error message) in the system and are also assigned to the group, but the permissions are only correct after a cache refresh.
Something goes wrong here...
If I make the assignment via the UI (and thus individually), it works.
PS:
my_module is the log of "function getSubgroupRelationConfig($group_id, $subgroup_id)"
\Drupal::logger('my_module')->notice('<pre><code>' . print_r($group_id . ', ' . $subgroup_id, TRUE) . '');
$type = $this->subgroupRelations[$group_id][$subgroup_id];
The whole error:
Comment #24
dbielke1986 commentedAnybody got a good idea?
We are planning a GoLive in July and would like to use this module. Currently, the only way to solve the problem is to clear the cache after the mapping (and the errors mentioned above) or to flush the cache after every assignment:
Comment #25
dwkitchen commentedI have created a repo where I am working on a re-write of this sub-module
https://github.com/committeehq/drupal-ggroup_role_mapper
The first action was to remove the Anon and Outsider permission mapping.
Next, I think there is a better way to add to the configuration form than using
ggroup_role_mapper_form_group_content_type_add_form_alter().I will then put up an improved patch here.
Comment #26
dbielke1986 commentedGreat! Thank you! I am ready to test your patch 😃
Comment #27
dbielke1986 commented@dwkitchen
I have tested the modified code in your git repro and I can tell you that the error from #23 did not occure anymore! This is really great! Thank you so much!
I will do some other tests the next days.
Comment #28
dbielke1986 commentedComment #29
dbielke1986 commentedDo we need to update this module because of the changes which were made to the groupe 1.0/1.1 release?
I mean the following:
and
Comment #30
dbielke1986 commentedAnother question:
Shouldn´t we use the official contrib modul instead of using this group modul modification?
https://www.drupal.org/project/subgroup
Comment #31
catchYes I think this needs to be marked postponed, or probably duplicate (but will let kristiaanvandeneynde do that) of the new contrib module. https://www.drupal.org/project/subgroup
Comment #32
dbielke1986 commentedbtw:
Within the contrib module there are a few things missing:
:-(
Comment #33
dbielke1986 commentedOk, as we found out in the discussion with the maintainer of the subgroup module, it is not a duplicate, but takes a different approach.
The difference, for me, is that the subgroup module only allows one "one child group can only belong to one parent group".
This implementation here allows a "one child group can belong to several parent groups".
Maybe this variant, though not in the core of the group module, will make it into a separate Contrib module. I would be very pleased!
Comment #34
dwkitchen commentedAs with #3084140: Subgroups core module, because of the creation of
subgroupthis will move to its own projectggroupComment #35
kristiaanvandeneyndeComment #36
catchFound a new issue with the patch..
When permissions are calculated, ggroup_role_mapper is calculating permissions for every single group, regardless of membership, in case there is group role mapping set up. This much is fine, however when there is actually no mapping at all, and a user isn't a member of a group directly or via a subgroup, we need to discard those permissions so that the group_type permissions kick in. Otherwise groups module itself uses the group permissions (which may be none) and discards the group type permissions.
For steps to reproduce, I found this with the 'request group access' permission and https://www.drupal.org/project/grequest
Comment #37
catchWithout the debug.
Comment #38
heddnWhy do we cast to string for the first, but not the second?
Comment #40
akalam commentedTested on D8.9 and works as expected. I'm creating a new MR and hiding the patches to focus the collaboration in the MR. Feel free to show the patches again if somebody disagrees.
The MR is based on #37 and I added the following changes in new commits:
MR: https://git.drupalcode.org/issue/ggroup-3084153/-/merge_requests/1
Comment #41
akalam commentedComment #43
dwkitchen commentedI have created the MR against the project now so it shows up on the issue page here.
@akalam thanks fo getting the set up on the new GitLab MR system - much easier to work on than before.
Comment #44
akalam commentedI detected a bug on the ggroup_role_mapper module. The module works good with 1 level of deep withing the user membership and the tested group. Let me explain myself with an example.
- Create 3 groups (the arrows represent hierarchy):
group 1 - > group 2
group 3
So both "group 1" and "group 3" have no parent group. Now add a user to group 1 as a member. He/she will get the roles for group 1 and group 2, but if you then add the existing group 3 as a child of group 2..
group 1 - > group 2 -> group 3
Then the user won't get the permissions on group 3 until you clean the cache.
The permissions rebuild is done on group_content creation or deletion. This is something that happen in the first scenario but not in the second scenario for group 3.
I added a commit with a fix based on cache tags. We are using the group_content_list:{$bundle} cache tag. After adding it, the permissions rebuild looks unnecessary, so I removed it. Feel free to discuss or to add it again if you find a more efficient way to solve the issue.
Comment #45
dwkitchen commented@akalam I was just noticing the same issue as I was moving a child group i.e.
Group X > Group Y > Group Z
and then
Group 1 > Group 2 > Group Z
Group X still have access to Group z and Group 1 didn't; I will test with your updates.
Comment #46
brad.bulger commentedIs there no UI associated with this yet? I thought I had seen it before but I must have been thinking of the subgroup module.
update: My mistake, it was because I'd patched the plugin ID from 'subgroup' to 'ggroup' #3209627: Change GroupRelationship id for compatibility with subgroup module.
Comment #47
catchI found several issues with the role mapping/permission calculation - for example permissions for one group could potentially be overwritten by a different group, and permissions when a user is a member of a subgroup but not the actual group being checked were being discarded. See various changes in the MR.
This could really use some automated test coverage, for example calculating permissions when the user is a member of:
1. Only a subgroup
2. Only a supergroup
3. Both a subgroup and the group being checked
4. Both a supergroup and the group being checked
5. Only the group being checked
6. Outsider permissions
7. Anonymous permissions
Comment #48
catchUploading an interdiff vs. the changes prior to around #44, will leave some notes on the interdiff in the next comment to explain some of the changes.
Comment #49
catchBy getting the inherited group roles by membership, this ends up missing some inherited roles.
Let's say group A is a subgroup of group B. And user 10 is a member only of group A.
When we're checking permissions of group B, we can't base the permissions on membership of group B, but only whether the user is a member of group B, or any subgroups, or any supergroups of group B. This means we need to get all the memberships of the current user, then build the list of group roles for any sub/supergroups they're also in.
The bulk of the bugfix then is here, instead of checking inherited roles based on a group membership, which implies direct membership of the group being checked, we just get all the inherited roles for the user and then the parent checks against the group once those are built:
The original thing that got me here was a more straightforward logic error:
As you can see the $group_id variable was getting overwritten in the foreach, this meant the mapped roles were getting completely wiped out depending on particular combinations of group memberships/group relationships.
Comment #50
brad.bulger commentedWe need this functionality for the 3.x branch, I imagine it will be complicated to do. If we could sponsor work on the issue to help make it happen, we'd definitely look at that.
Comment #51
lobsterr commented@brad.bulger - Yes, it would be a quite complex, taking into account that Group 3.0 have been reworked. Contact me on the slack we can discuss it.
Comment #52
lobsterr commentedI have a question to developers who are using this patch?
Outsider and Anonymous roles were dropped #42 and I don't see any complains about it. So, I assume nobody uses anonymous and outsider roles for mapping ?
If it is a true and we don't need it, then I will clean up the code.
if we still need it, we can make it optional to avoid performance issue on some websites.
Please, share your opinion.
Comment #53
brad.bulger commentedI am not sure how much this applies to the Group 3+ way of doing things. Each change in the combination of factors results in a distinct single group role. So maybe it is simpler, in that you can map any source group role to any target group role. Or maybe it has to echo the same scopes as Drupal site roles: one mapping for source group role + member of target group, one for source group role + non-member of target group.
Comment #54
lobsterr commentedAfter checking the status of the current code, I found the next issues, which I want to improve to reach a stable version
1) Role mapped only to the direct ancestors. I think we want to apply permission to all subgroups. Should we add it as an option ?
2) We load group entities, but we don't need them, we just need group ids.
3) We have removed outsiders / anonymous mapping, I believe, it is still useful feature I propose to make it optional
4) Should move this patch to a contrib module or should I add already to ggroup module? For me it would easier to handle the bugs and feature requests
5) We do a lot of useless operations. I see some ways to optimize the code
Please share your opinions
Comment #55
catch#1 and #3 both seem like they'd add complexity to the current patch, which is already complex enough, so for me I'd prefer not to do this - or at least, to do it in a follow-up once there's a working version in a module somewhere.
Comment #56
brad.bulger commentedIf it still works as it did before, where it is a module that has to be enabled separately in addition to ggroup, then whatever is easier to maintain would be the way to go, I think - standalone or component of ggroup.
Being able to optionally have mapping apply to descendants would be nice.
Comment #58
lobsterr commentedFrom this moment ggroup role mapper is part of ggroup.
Please share your thoughts and ideas here #3369117: Ggroup role mapper module new features and suggestions
All comments here will be ignored, create a separate tickets and choose "Ggroup role mapper".