The og_subgroups module provides user inheritance functionality. This allows to automatically add users to parent/child OG. The 1.x version offered 2-way inheritance: you could automatically add user to the parent group(s) or to the child groups. However, this version only works with OG 1.x. The 2.x version, which works with OG 2.x, only has parent to child inheritance. So, I implemented child to parent inheritance as well.

The UI changed a little bit. Instead of a radio button that just toggles user inheritance, there are now two checkboxes, one to toggle parent-to-child inheritance and another to toggle child-to-parent inheritance:

UI

There is a concept of propagation. So, imagine that I have a group Grandfather which is parent of Father which is parent of Son. If I add a user to Father, he will have access to both Grandfather and Son groups, if 2-way inheritance is enabled for the Father group. But if Father has no inheritance and Son has "upwards" inheritance, if I add a user to Son, the Father group will inherit the user but the Grandfather won't. However, if the Father also has the "upwards" inheritance, the user created in Son will also become a user of Grandfather. The example below shows a more complex scenario of how it works. On this image, the two arrows mean 2-way inheritance, and the user is the user added to the group.

Example

The expected results from user point-of-view are:

  • grandfather-user: should see groups Grandfather, Great Grandfather and Father
  • son-user: should see groups Son, Father and Grandson

And from the group point-of-view:

  • Great Grandfather: should inherit user grandfather-user
  • Grandfather: should inherit no user
  • Father: should inherit both users grandfather-user and son-user
  • Son: should inherit no user
  • Grandson: should inherit son-user

The patch is attached: https://drupal.org/files/0001-Implementing-optional-two-way-inheritance-....

That was sponsored by The Jibe (http://thejibe.com).

Comments

fp’s picture

Status: Needs review » Reviewed & tested by the community

Looks good and work as expected.

fp’s picture

Status: Reviewed & tested by the community » Needs review
StatusFileSize
new12.79 KB

Getting :

Notice: Undefined variable: group_id in og_subgroups_og_user_access_alter() (line 104 of /path/to/og_subgroups/og_subgroups.module).

This is the diff of the patch attached here:

--- og_subgroups-2051597-optional-two-way-inheritance.patch	2013-08-18 10:41:18.466235001 -0700
+++ og_subgroups-2051597-2-optional-two-way-inheritance.patch	2013-08-18 11:00:37.266235001 -0700
@@ -311,7 +311,7 @@ index 4d57056..bc26ac7 100644
 -  $parent_groups = _og_subgroups_get_unique_parents($group_type, $id);
 -  if (!empty($parent_groups)) {
 -    foreach ($parent_groups as $parent_group) {
-+  $groups = _og_subgroups_get_unique_parents($group_type, $group_id) + _og_subgroups_get_unique_children($group_type, $group_id);
++  $groups = _og_subgroups_get_unique_parents($group_type, $id) + _og_subgroups_get_unique_children($group_type, $id);
 +  if (!empty($groups)) {
 +    foreach ($groups as $group) {
caiosba’s picture

Please consider only this patch instead of the two previous ones. This one includes the two previous ones and also implements support to filling accessible inherited groups on audience field for non-admin users.

I implemented a new selection handler for the audience field, which inherits from the default OG selection handler. The default OG selection handler gets the memberships and returns the group ids. So, in this new handler implemented in og_subgroups module, I get the inherited groups from the user and return their ids.

caiosba’s picture

Please consider this new patch only, instead of the previous one. That's because I added a new feature: two blocks that list the users of a group. The first block shows all the users (including the inherited ones) as a single list. The other shows the users and the groups where they are inherited from. Both blocks were implemented as displays of the og_members view, provided by OG module. This way, both blocks share the same settings that the og_members block has (pagination, header, footer, whatever). The blocks were implemented using views hooks. The hooks iterate through the inherited groups of the current displayed group and call the view of each one recursively, which keeps all views settings and consistency. Loop is avoided since they are called with the display "block_1" provided by OG module. The image below shows how the blocks look like. The number 1 lists users separated by groups, while the number 2 lists the users as a single list.

OG Subgroups Blocks

I also forked the original module code: https://github.com/caiosba/drupal-og-subgroups.

mpotter’s picture

I'll try to get some time to review this within Open Atrium 2 after the first release. I've agreed to do some work on this module since the original maintainers have gotten busy. There are a couple of issues related to the bidirectional inheritance and I need to get up to speed on which patch(s) we should commit.

In particular, I want to compare this with #1956426: Content Inheritance, so comments are welcome.

mpotter’s picture

Issue summary: View changes

Fixing typo.

ceepeebee’s picture

In particular, I want to compare this with #1956426: Content Inheritance , so comments are welcome.

Maybe, I am wrong, but I think you have to distinguish between "cloning" group-membership, and proper "sub"-groups**. If the child-group inherits its members from the parent, you actually get a clone (in reference to the members).
IMO, for "sub"-groups** the user inheritance has to go up the line (from children to parents). I'll try to explain, what I mean:

Let's have the following structure as a reference:
- parent-group (P)
-- child-group (A)
-- child-group (B)

1. user-inheritance:
1.1. bottom-up: in set theory the parent group would be a union of the child-groups (="sub"-groups**). Members(P) = Members(A) U Members(B)
Everybody, who is a member of A, a member of B or a member of (A and B) should be a member of the parent; on the other hand, not every member of the parent-group has to be a member of a "sub"-group**.
Use case:
- organisation
-- dep1
-- dep2

1.2. top-down:"group-cloning" (= user-inheritance from parent to children); Members(P) = Members(A) = Members(B); major difference to 1.1.: there is no difference in the sets of members of A resp. B.
(I only refer to the automatically inherited members; of course, a child-group inheriting the members of its parent could have its own extra members)
Use case:
- group
-- public
-- private

2. content-inheritance: here on the other hand, both directions apply equally.
2.1. bottom-up: Content(P) = Content(A) U Content(B); typical content-aggregation on a higher level, like feed-aggregation.

2.2. top-down: Content(P) = Content(A) = Content(B).
(as above, I only refer to the automatically inherited content; of course, a child-group inheriting the content of its parent could have its own extra content)
Use case: (learned from [1956426])
- school
-- grade 1
-- grade 2
e.g. the all-school-calender should merge with the different grade-calenders on grade-level

3. Combinations:
A typical combination of both user and content inheritance would be 1.1. along with 2.2., therefore inheritance in opposite directions: user upwards, content downwards
Use cases:
- all kinds of organisations, especially when members(A) XOR members(B) like in school grades;
- or if: A/B are proper subsets of P;
- Biological_classification

Another typical combination could be 1.1. with 2.1., aka user/content-aggregation on higher levels.

So long and thanks for all the fish.

** "sub"-groups in the meaning of subsets of the (parent) set

mpotter’s picture

Will be looking at this during January since I definitely see use cases for all of the above-mentioned inheritance.

I think something else that makes this issue complicated is the difference between inherited "membership" and inherited "access".

For example, "membership" typically involves permissions around creating/editing content. For example, "members" of a discussion group can add posts, reply to posts, etc. But there is also simple "read access" of groups.

In the 1.1 case above, you might want to give "read access" for the child members to view the parent space. But you might not want them to be true "members" of the parent space with create/edit access.

In other words, when working with Private groups, the "view access" of that private group might be determined from the children or parent groups.

I think this patch addresses the "membership" inheritance, but maybe not the "read access". Maybe that should be a separate issue, but it seems related and I'm trying to figure out how to present this complexity to the users without it being a mess of different options.

Further discussion is welcome!

mpotter’s picture

Also, I am looking for other testers to see how this works with the latest version of OG and og_subgroups. The recent patch to OG did some security updates on the group audience selector that might impact this patch (and other inheritance patches).

ergophobe’s picture

RE #7, if membership and role is inherited, isn't it then up to the site admin to manage how permissions propogate?

For example let's say I have this hierarchy

- national
-- regional
--- local

Then I can create roles like
- default
- local admin
- regional admin
- national admin

These then work sort of like bitwise operators. I set up my permissions so the default member has permission to add content on a local group, but can only read content on the regional group.

I'm just now trying subgroups for the first time, so I may be missing something basic here, but I think that would work in my case.

And though content inheritance and user inheritance are related in many ways, to me these are very separate issues. I could certainly imagine use cases that would use one but not the other.

ergophobe’s picture

Also, I am looking for other testers

I'd love to test, but this is my first flirtation with this module and given the changes in http://drupalcode.org/project/og_subgroups.git/commitdiff/4db2260b1d1f90... related to #2029123: Finer control of permission inhertence, I wouldn't be able to reroll the existing patch without getting to know og_subgroups a LOT better (which I hope I eventually will).

brightbold’s picture

I think something else that makes this issue complicated is the difference between inherited "membership" and inherited "access"... I think this patch addresses the "membership" inheritance, but maybe not the "read access". Maybe that should be a separate issue, but it seems related...

I've taken the liberty of reopening #824016: Subgroup visibility and access inheritance (which was originally posted to the OG queue) to cover the access issue. @mpotter if you feel it's better to discuss both issues in one, we can close that one. But this issue seemed membership-inheritance heavy so I thought maybe access inheritance needed its own space.

I can test this patch because I do need child-to-parent inheritance (if you're a member of a class, then by default you should also be a member of the school) so I have a good use case for trying out upwards member inheritance.

Let us know what else we can do to help your efforts, @mpotter. I will be delighted if this module gets a lot of attention this month!

solesum’s picture

I have the same scenario as BrightBold, needing child-to-parent inheritance of group membership for classes and courses (using Opigno LMS).

I am off to test the patch in #4 now!

ergophobe’s picture

As I mentioned, patch 4 is not going to apply to current code. There have been huge changes in the commit I referenced, so if you want to test patch 4, you'll need to checkout the code from before that commit.

But since that commit makes fundamental changes to the way permissions are inherited, I'm not sure testing against the code from before the fix makes any sense.

We need to reroll the patch against the existing code to get any sort of meaningful test.

solesum’s picture

Ergophobe, thanks so much for clarifying. I noticed right away when I was manually trying to apply the patch, and I really appreciate your setting me straight. I wish I was skilled enough to re-write the patch for current code, but I will definitely be around to help test.

brightbold’s picture

Can anyone reroll so we can test? I want to help move this issue along (selfishly, because I desperately need access inheritance) and I want to give mpotter any help I can in making this module awesomely useful. (But I'm not a module developer, so I can't reroll, sorry.)

ergophobe’s picture

BrightBold

It's not a simple matter of rerolling. The module has totally changed since the patch was created. Many new and different functions, as well as many functions missing. Rerolling is almost like starting from scratch.

If you need it in a hurry, I would try caiosba's fork on github mentioned in #4. It works fine in my tests (I only tested user inheritance, not permissions).

https://github.com/caiosba/drupal-og-subgroups.

solesum’s picture

Hey all, just wanted to post the solution we used to achieve backwards inheritance of roles -- we did not end up using OG Subgroups for now, instead we used OG and Rules, plus Conditional Rules. Our solution is fairly specific to our usage, but maybe it will give some folks who are looking for an immediate solution an idea.

We have an OG group content type called Courses (this is the "parent") which is linked to another OG group content type called Sessions (child). To achieve the parent/child relationship between the group types, we created an og_group_ref field (Group audience) in the Session group type which refers to the course.

Each Session (child group) has an Entity Registration form that is attached to it, so authenticated users can register for Sessions. Registrations have states, and when a new one is submitted by a user its default state is "Pending review". When a group manager goes through a registration, they change the state to "Reviewed/Approved" and save.

We configured a rule to react on event "After updating an existing registration". We have two conditions, the first does a text comparison to "[registration:state:label], Matching text of Reviewed / Approved. The second is an Entity is type: User, to pull in the user data.

Using rules actions, we fetch the Session ID, Subscribe user to group, and Grant OG Role of learner to user. Then we have a conditional which checks for the field og_group_ref on the Session. If the group ref is present, we use it to fetch the Course ID (parent group). We can then subscribe our registering user to the parent Course, and assign them the role of Learner.

In this way, we have allowed members to automatically be added to the "parent" group referred to via og_group_ref.

brightbold’s picture

Thanks ergophobe. I did see your earlier comment that it was complicated but didn't realize that that meant the term "reroll" no longer applied. At any rate, user inheritance isn't my primary concern — I really want access inheritance (which I don't think is covered by the fork in #4). But mpotter had asked for testers and I figured that was a way I could help move this module forward. I'll keep my eye on this and if there's something I can help test I will try to do it.

brightbold’s picture

If anyone who's following this issue is interested in the access inheritance mpotter mentions in #7 (e.g., a public subgroup of a private group should be public only to members of its private parent group, not public to the whole world), an organization I work with may have some funding to sponsor work on that issue. See [#8633899-30] for more details and contact me.

Edit: Not sure why issue link didn't work, but it's here: https://drupal.org/comment/8633899#comment-8633899

WorldFallz’s picture

@solesum I'm trying to do something similar (simply subscribe a user to the parent group automatically via the 'User has become a group member' event), and I'm having a devil of a time trying to get og_group_ref for the parent. Could you possible post an export of your rule?

sk2013’s picture

+1 any update?

caiosba’s picture

FYI, I started implementing 2-way inheritance for the new module version: https://github.com/caiosba/drupal-og-subgroups/tree/7.x-2.0-beta2.

My previous patch at #4 was completely useless and I had to restart from scratch.

caiosba’s picture

Ok, I re-implemented 2-way inheritance on OG Subgroups, against 7.x-2.0-beta2. Patch is attached. The original description is still valid.

et.cetera’s picture

@caiosba

I am using an old version of your tree

og_subgroups.module	2014-04-17 06:40:45.000000000 +0200

and since my growing site gets more and more performance problems related to og_subgroups I decided to try the master-branch (since the beta2 branch doesn't have the plugins folder - why?).
Therefore I disabled (not uninstalled!) the old version, enabled the new one, ran update.php (just to be sure) and reset node permissions.
The first thing I got was an error

 EntityFieldQueryException: Unknown field: og_user_permission_inheritance in EntityFieldQuery->addFieldCondition()

Can I solve this without uninstalling the old version and loosing my hole configuration?
--
Edit:
OK this problem seems to be beta2 specific
https://www.drupal.org/node/2568551
Would be nice to have the beta4 branch, since it seems to solve this problem.
Still the question is if there are any implications on upgrading the module.

Something that is different now is that if you use "Parents of this group will inherit its users" and assign a node to a tree of parents is that if you change that node to become a child of an other tree (and remove the old reference), the old assignment partially persists, so that in the old tree the node is still there and is listed as inherited.
This wasn't the case in the older alpha relase, where the footprint of the inheritance within the old tree of parents was removed, after you have assigned a new tree of parents.

Anything else seems to work as before (until now). I will still test the new version in a development environment, since it became a fundamental part of my system...

joshuautley’s picture

@caiosba

I applied patch #23 against 7.x-2.0-beta5 and it worked! (=

In my use case I have a content type as a Group and then a separate content type as a Sub-group with the field Group user inheritance set to "Parents of this group will inherit its users."

Note that at first I did not think it worked because I use OG Extras for displaying group members and the new member (of the subgroup) was not visible in this view but after visiting /group/node/xyz/admin/people I do see the Inherited From table with the member.

This is very cool. As an aside I've been using OG for about a year now and have found it to be extremely easy to get lost in all that it can do. However, it and its sub-module maintainers and community are very active and supportive. I will be able to assist with testing patches and thinking out use case as they arise. I have to disclose that I do not have much time to put into actual development as I'm primarily a front end guy and I see my role as that of someone willing to evaluate the front end experience of configuring modules. And, I do have nearly ten years of PHP experience with a smidgen of Drupal development experience.

Anyhow, cheers! Great work!! Let's keep it going.

caiosba’s picture

I'm so glad it worked! Thanks for testing that! :)

et.cetera’s picture

StatusFileSize
new420.56 KB
new468.48 KB

Ok I tried now beta5. The patch applied (except one line in the .info file) cleanly. But I still have the problem, that after changing the entity reference and switching to another tree of parents, the old group inheritances are not deleted immediately. To illustrate my problem I have appended two pictures.

Solution:
Clearing all caches did solve the problem (I am using entitycache)!! With the old alpha version this does not happen.

So at some point clearing the entitycache of the old parents is missing.

Did no one encounter this problem???

joshuautley’s picture

@caiosba - Any thoughts on how to create a user list of all members of two groups (Parent group and Child group)?

mpotter’s picture

Status: Needs review » Needs work

Ok, now that I finally got the 2.0 stable version released, I think we can start working on this issue again. We need to re-roll this against the 2.0 release and then start adding some tests for all of this. We need to ensure that existing sites are not broken by this and also that the patch adds the desired 2-way functionality.

I wanted to get 2.0 released so we can get proper security team coverage for this important module (since it's main purpose is access control). But now that it's released we need to get serious about writing automated tests so we don't break stuff in the future.

Since I only have minimal time to support this module as part of Open Atrium, any help on writing tests for this would be much appreciated.