We are excited to share details about our recent integration with the Group module.
By default, Group module stores group memberships in the Drupal database. For a recent project, our Client required that group memberships are canonically stored in their existing LDAP directory. That way, memberships may be re-used to control access to 3rd party applications like real-time chat, file sharing, etc.
Group module provides a simple service, GroupMembershipLoader, that is responsible for loading all memberships for a group or all memberships for a user. We swapped that service for a custom one that queries LDAP instead of querying database. Further, we added a simple caching layer so that a user’s group memberships are cached in that user’s session.
// Cache a user’s own groups in their session for fast retrieval.
$duration = \Drupal::getContainer()->getParameter('ldap_directory.dgids_duration');
$this->getPrivateTempStore($account, $duration)->get('ldap_directory')->set('dgids', $dgids);
A group membership not only relates a user to a group but also assigns a role to that membership. In our implementation, a member can be a Reader, Contributor, or a Group Admin. We decided to model that by creating a DirectoryGroup content entity, and configuring Group module such that DirectoryGroups can become group content. So, when a new Group is created, an insert hook does the following:
- 3 LDAP groups are programmatically created
- 3 DirectoryGroup content entities are created+affiliated with the new Group.
- The group creator is added to the Group as an Admin member.
That last step hints at another part of the custom integration. The Group::addMember and Group::removeMember methods control what happens when memberships are created and removed. We overrode the default implementation in our Group bundle class and perform LDAP operations instead of DB operations. Then we clear that user’s Tempstore in order that they immediately see the new membership.
Judicious use of cache tags insures that this list is invalidated when the user is added or removed from Groups.
// Invalidate that user's group memberships
Cache::invalidateTags($account->getCacheTags());
Also, we are pulling user avatars and other profile info from LDAP. Avatars are cached locally at full resolution and we may then use Image Styles to scale them down as needed. Drupal’s re-use of LDAP data demonstrates that Drupal is a good enterprise citizen.
Kudos to kristiaanvandeneynde for the excellent architecture of group module that made this integration possible without any patches to Group.