Going through groups and their subgroups using recursive Flow
This time, we will make a flow that goes through the group hierarchy and sends a message to all its members. We have the following organizational hierarchy.
- Unit A
- Department A
- Team 1
- Team 2
- Team 3
- Department B
- Team 4
- Team 5
- Department A
The hierarchy is modeled in Entra ID as nested groups. Organization-level members are always members of the corresponding group.
Next we use a flow to send a message to each organization member.
Flow – Group members
Let’s make a flow that receives the group identifier (groupid) as a parameter.
After this, we list all the members of that group (List group members).
As a result, we get the users and groups that are members of the group.
Let’s filter the result to show only users.
Filter Query = @equals(item()?['@odata.type'], '#microsoft.graph.user')
Now we can send all group members a message, for example, an email.
Next, filter the result to show only groups.
Filter Query = @equals(item()?['@odata.type'], '#microsoft.graph.group')
Flow – Handling nested groups (with recursion)
We now only send the email to direct members of one group (Unit A), not to users in subgroups of the group. To top it all off, these subgroups can be nested in several levels.
However, the solution is simple. It’s called recursion (a function that calls itself). We’ve already done a flow that
- Sends a message to all group members
- List all groups within a group
Now, for every group we find, we call this same flow again! A new flow run sends a message to the members of that group, lists the groups within it, and calls himself again.
Clear?
Let’s start the flow again (Run a Child Flow) for each group using the group’s identifier (GroupId) as a parameter. For flow to be used as a child flow, we need to add Respond to a Power App or flow action on it.
Similarly, all flow connections should be defined to use a fixed connection.
However, after doing all this, saving the flow fails.
Request to XRM API failed with error: 'Message: Flow client error returned with status code "BadRequest" and details "{"error":{"code":"FlowCannotInvokeItself","message":"The Flow could not be saved because Flows cannot invoke themselves as Child Flows."}}". Code: 0x80060467 InnerError: '.
Flow cannot trigger itself.
A silly limitation that has two easy workarounds.
The first is to trigger the flow with an http trigger. This was discussed in the previous article about recursion.
The second is the use of a simple intermediary flow. Let’s make another flow (List Group Members – Helper), which receives the group id as a parameter and forwards it to the original flow.
So the flow we create does not start itself, but the intermediary flow. Which does nothing but start the original flow.
Finally, the main flow looks like this.
Let’s start the flow using the identifier of the Unit A group as a parameter. There are eight groups in our hierarchy. The startup generates a total of 8 executions. Each group in the hierarchy is reviewed.
Optimization
Now flow first sends a message to all members of the group and then calls itself for each subgroup. As the last step, the flow returns a return message to its caller.
If the hierarchy is really extensive, it can take time to go through the entire chain. Especially if something more complicated is done for the user than just sending a message.
Let’s change the flow so that users and groups are processed side by side. A return message to the calling flow is also sent at the same time.
Let’s add error handling so that we can get information on which group the error occurred in processing.
Notes
The first point about the solution is that there are more efficient solutions for sending e-mail messages to members of the organization. But what if we want to send them a personal Teams message with flow? In practice, there are situations where it is necessary to go through the nested groups using flow.
If there are many members in the groups, pagination should be set to List Group Members action.
If there are many members in the groups, the search result has to be processed in flow one page at a time.
Problems may be caused by a situation where a user is a member of several groups. In this case, flow handles him/her several times. In this case, the original flow can only store the user’s identifier in, for example, a SharePoint list. Only if the user cannot be found there yet.
After this, the second flow goes through the users in the SharePoint list and takes the desired action per user.