This morning, when I saw the requirement – “Check if the user has XYZ security role … bla bla bla…”, Quite frankly, I thought it’s pretty straightforward. Join systemuserroles, roles and user, use RetrieveMultipleRequest – done!! But, when I started working on the task that’s when I realised there is this big gap (at least in my understanding) in terms of Teams…
“SystemUserRoles” will not hold the roles inherited by the user via teams.
Afterall SystemUserRoles is simple N:N relation b/w roles and users, this is not a special entity which does some “magic” and brings all user roles under one roof. It’s making sense to me now after gone through the entity metadata.
Another surprise to me is – there is no much chatter about it on google (I’m sure, I’m not a bad googler 🙂 ). Except for this one blog from Debajit, I didn’t find much useful information and henceforth this quick blog post.
Just to make sure, everyone is on the same page, here is the problem statement
User A –
Security Roles Associated – “Sales Lead”, “Regional Manager”
Teams Associated – “America Sales Team”
American Sales Team-
Security Roles Associated – “Custom Security Role”
The task on the hand is, check if User A has “Custom Security Role” or “Regional Manager” role.
The following method helps in finding out the same. It will return “True”, if the given user has any of the given security roles.
public bool UserHasRole(IOrganizationService service, Guid userId, Guid businessUnitId, List rolesToCheck) { var query = new QueryExpression("role"); query.ColumnSet.AddColumn("name"); query.ColumnSet.AddColumn("businessunitid"); query.AddLink("systemuserroles", "roleid", "roleid", JoinOperator.LeftOuter); var teamRolesLink = query.AddLink("teamroles", "roleid", "roleid", JoinOperator.LeftOuter); var teamMemberLink = teamRolesLink.AddLink("teammembership", "teamid", "teamid", JoinOperator.LeftOuter); var teamLink = teamMemberLink.AddLink("team", "teamid", "teamid", JoinOperator.LeftOuter); teamLink.Columns.AddColumn("businessunitid"); query.Criteria = new FilterExpression(LogicalOperator.And) { Filters = { new FilterExpression(LogicalOperator.Or) { Conditions = { new ConditionExpression("systemuserroles", "systemuserid", ConditionOperator.Equal, userId), }, Filters = { new FilterExpression(LogicalOperator.And) { Conditions = { new ConditionExpression("teammembership", "systemuserid", ConditionOperator.Equal, userId), new ConditionExpression("team", "businessunitid",ConditionOperator.Equal, businessUnitId) } } } } } }; var filter = new FilterExpression(LogicalOperator.Or); foreach (var askedRole in rolesToCheck) { filter.AddCondition("name", ConditionOperator.Equal, askedRole); } query.Criteria.Filters.Add(filter); var data = service.RetrieveMultiple(query); return data.Entities?.Count > 0; }
The usage –
UserHasRole(_client.OrganizationServiceProxy, new Guid("C2BF68B5-7253-E811-80E4-00155D34085B"), new Guid("4E62A061-3437-E811-80E1-00155D340540"), list);
Note: I have tested it with multiple scenarios and found it is working fine. But I would recommend thorough testing from your end as well 😊
Hope this helps, Happy coding !!