Tech Spec - Group Mentions(LDAP)
Status: 99%
OVERVIEW
This document describes the main design and implementation decisions behind the "Group Mentions” feature. This feature provides ways for a MM user to mention groups and notify their members (and invite the ones that are not in the channel to the channel).
GOALS
describe the changes and additions to the backend architecture (API and Storage)
describe the UX changes (webapp and redux)
describe the mobile changes.
SCOPE
In:
ability to mention group(s) in a channel
ability to notify the members of the group(s) that are being mentioned
ability to enable/disable the referencing (mention) of a group in the System Console
display a warning if the group mention will trigger notifications to more than X number of users
ability to enable or disable notifications per group
Out:
TBD
BACKGROUND READING
TERMINOLOGY
“Group-constrained” - when a group is linked to a channel or team and the syncing of its group members is turned on.
SPECIFICATIONS
High-level Architecture
Group Mentions
We can split the group mentioning flow into two phases: Build Suggestions and Notify Members. In the Build Suggestions phase we build the suggestions list that is displayed in the channel UI when the user enters the “@*” text in the channel textbox. In the Notify Members phase we sedn the notifications to the members of the groups being selected in the previous phase. We will detail the design and the API, storage and client supporting changes for both of them.
Phase 1: Build Suggestions
Design
The flow of actions for this phase will be:
we fetch the group(s) objects from the server and use them to populate the client state
we filter the client state if the current channel or team is group-constrained or not and select the groups that fulfill the right conditions (see below)
we populate the mentions suggestion list with the names of the groups obtained in the previous step.
Group-Constrained Channel/Team Status
A channel or a team can be in one of two states :
constrained to the group(s)
not constrained by any group.
Depending if the current channel and/or the containing team is group constrained , we can have the following group-mentioning cases:
If the current channel is constrained by the group(s), the user in the channel can only mention one of these groups.
Otherwise, if the current team is constrained by one or more groups, the user can only mention one or more of these groups.
If neither the current channel is constrained, nor the current team, then the user can mention any group constrained to any channel/group in the system. (currently all groups in MM are linked groups).
While we currently do not have a good estimate of how many groups we can have in an org, we made the assumption that the number is small enough where we could fetch them from the server more than once during a user session (we somewhat optimize this action by retrieving only the mentionable ones). The group mention flow is initiated from a channel's textbox; it is an expensive operation to repeatedly fetch the group(s) from the server as the user types - we will fetch the groups and populate the client state (depending if the channel/team is group-constrained or not) once per team initialization (which means that if we switch teams in the work session we will fetch the teams from the server again).
Future Work: We are exploring way to ensure the groups will need to be fetched only once, at server start, not at every team change (and then only updated based on group-related System Console actions). Later this set is updated based on user’s actions (groups removed, etc.)
Duplicate group names
When we enable group mentioning on a group in the System Console, we are also generating the actual “group name” property from the group’s “display name” (e.g. display name: “software developers” ; group name: “@software-developers”). This happens at the server-side and since we enforce the uniqueness of the name
column in the UserGroups table, there is a potential of error and throwing a SQL exception if there is already a group with the same name already stored. We address the duplicate group name case by surfacing the duplicate error in the UI and allowing the user to specify a different (custom) group name if the current one is a duplicate of another. Ticket: MM-23816: Enable the editing of the group name in the Group Configuration panel. Closed
UI/X (Webapp)
Group Mention Settings Toggle Panel
we will add a new “Group Mention Settings” widget containing a toggle component in the Group Configuration details panel in the System Console. We will not commit the update of the group object at the server until the user clicks on the Save button in the panel - until then, the group is in a draft state. We will validate and warn the user for the following conditions:
group name is empty
group name contains invalid characters (TBD the exact set of characters allowed).
Channel Textbox Suggestions List
when displaying the group mention in the suggestion list, we will include the group’s name and display name. “@software-developers Software Developers”.
UI/X (Redux)
Selectors:
searchAssociatedGroupsForReferenceLocal
- allows for searching of mentionable groups based on the user entered text
getAssociatedGroupsForReference
- returns the full list of groups that constrain a channel and/or team (or not), base don the criteria mentioned above. If the current user’s role does not have USE_GROUP_MENTIONS permission, it will return an empty list.
getGroupsAssociatedToTeamForReference
- returns the list of groups that constrain a team
getGroupsAssociatedToChannelForReference
- returns the list of groups that constrain a channel
getAllAssociatedGroupsForReference
- returns the list of groups that constrain a channel or team in the system
Actions:
getGroups
- returns the list of groups from the server filtered byfilter_allow_reference
flag
patchGroup
- patches a group with an newname
orallow_reference
property
getAllGroupsAssociatedToChannelsInTeam
- for every channel that is constrained by one or more groups, returns the corresponding list of groups, indexed by the channel’s id.
REST API
we will add the following new endpoints:
Team : …/ groups_by_channels
getGroupsAssociatedToChannelsByTeam
(GET) - returns for a team, a map of channels constrained by groups and the corresponding groups.
we will augment the following
getGroups*
API endpoints with the additionalfilter_allow_reference
filter (default isfalse
), to be able to retrieve from the server only the groups that are enabled for mentions.
getGroupsByChannel, getGroupsByTeam, getGroupsAssociatedToChannelsByTeam, getGroups
Storage
we will add a new SQL stored-procedure:
getGroupsAssociatedToChannelsByTeam
- for every channel that is constrained by one or more groups, retrieves the corresponding list of groups, indexed by the channel’s id.
Tickets
Display group mentions in suggestions list in the main channel textbox
MM-23016: Display group mentions in suggestions list in the main channel textboxClosed
Enable or Disable group mentions
MM-23015: Enable or Disable group mentionsClosed
WebApp - Highlight Group Names in chat window
MM-23159: WebApp - Highlight Group Names in chat windowClosed
Phase 2: Notify Members
After the groups have been selected from the suggestion list in the channel textbox, we need to notify their members about the mention.
Design
The flow of notifying group members will use the existing SendNotifications
function and insert checks for groups where needed.
The first step added will be to check if the user creating the post and has access to
PERMISSION_USE_GROUP_MENTIONS
, if not then the behavior ofSendNotifications
will be unchangedIf group mentions are enabled then all groups that have
AllowReference = 1
will be added to memoryThe
ExplicitMentions
struct will have a new attributeGroupMentions
to store the groups mentioned by thePost.Message
.Once all groups are added to the
GroupMentions
map, group members that exist in the channel will be added to theMentions
map as confirmed mentions in the channel.Group members that exist in the
team
but not in thechannel
will be added toOtherPotentialMentions
and will have an invite message generated for them using the existing logic.If there are no group members in the team that the message is sent to, a system message will be sent, letting the user know that the group mentioned has no members in the current team.
Warning Modal
in the notification phase, when the aggregated number of group members to mention is above a certain threshold N(=5), we are displaying a warning modal (see wireframe), the text message in the modal specifies the user count from the largest group in the set of groups selected in the first phase. This is a compromise solution, due to performance constraints -see below.
For example, if we mention
@developers
and@board
, where@developers
has 10 users within the channel while@board
only has 2 members in the channel, the warning modal will warn the user that she is about to notify@developers
with 10 members in the channel.
If two groups have common users the total count to be displayed by the dialog would have to be the union of members for each group within the channel. This can be done but at a significant performance cost (groups can have a large number of members).
Future work: Investigate a better solution?
UI/X(Webapp)
The
markdown
component will be modified to usegetAllUserMentionKeys
which contains the union of `getCurrentUserMentionKeys
andgetCurrentUserGroupMentionKeys.
This will ensure that group names will be highlighted for the user as expected.The existing admin setting
enableConfirmNotificationsToChannel
will be used to determine if the warning modal should show up if a group has more than N members in the channel.Upon visiting a channel all the groups that have members within that channel can be retrieved by using the
channelMemberCountsByGroup
selector.A utility function
groupsMentionedInText
will be added to get all the groups mentioned in a message before sending.All the groups being mentioned will be retrieved from the Redux state and then the one with the largest number channel members will be selected and its member count be used to display the number of users being notified. However, if groups are being mentioned alongside @all or @channel, then the total number of channel members - 1 will be used instead.
UI/X(Redux)
A new selector will be added to get the list of groups that the current user can be mentioned by:
getCurrentUserGroupMentionKeys
- it will be used to determine which @group mentions should be highlighted in the chat facing UI. This selector will be used inside ofgetAllUserMentionKeys
where we merge its set with the result of callinggetCurrentUserMentionKeys
(which contains regular mentions such as first name / user name etc).New actions and selectors for
getChannelMemberCountsByGroup
have been added, which take achannelID
and a booleanincludeTimezones
flag as arguments and returns a list of all groups with members within the channel and number of members in that channel. IfincludeTimezones
is true the function also returns the number of unique timezones for the users in that group.
REST API
we will add the following new endpoints:
channel: “.../ member_counts_by_group/" channelMemberCountsByGroup`
(GET)
since we extend the range of calls to the GetGroups* methods from the SystemConsole to the chat-facing area we will remove the existing permission check from the following API calls: getGroups, getGroupsByTeam
The USE_GROUP_MENTIONS
permission check is being done now in Redux, where we check the current user’s permission to fetch the mentionable groups.
Storage:
we will add the following new stored procedures:
GetMemberCountsByGroup
- returns a slice of ChannelMemberCountByGroup
for a given channel which contains the number of channel members for each group and optionally the number of unique timezones present for each group in the channel
GetMemberUsersInTeam
- returns a slice of users that are members of a group and exist in a team. The intersection of (users in team) & (users in group)
GetMemberUsersNotInChannel
- returns a slice of users that are members of a group that exist in the team that the channel belongs to but do not exist in the channel. The intersection of (users in team) & (users in group) & (users not in channel)
Tickets
Group Mentions - Show a confirmation dialog when mentioning a group with too many users
Send notifications to the @-mentioned group members
MM-23017: Group Mentions & Invites - Send notifications to the @-mentioned group membersClosed
Supporting Work
Storage
we will add a new column to the UserGroups table to tag the groups that are enabled for mentioning:
AllowReference
: boolean
Permissions
we will add a new permission
USE_GROUP_MENTIONS
- this allows us to
Tickets
Create use_group_mentions permission
MM-23019: Group Mentions & Invites - Create use_group_mentions permissionClosed
Websockets updates: Ensure websockets are updating the referenceable groups (et al) in Redux for group-mentions
CLI
Out of scope.
Configuration
None.
Plugins
Out of scope.
CREDITS
Thanks to Martin, Hossein, Farhan and Scott for great suggestions and brainstorming.