web
You’re offline. This is a read only version of the page.
close
Skip to main content

Announcements

Community site session details

Community site session details

Session Id :

Restrict Advanced Find entity record based on Security Role using Retrieve Multiple Plugin.

gdas Profile Picture gdas 50,091 Moderator

You may have seen in the community many people have asked how to hide entities from Advanced find. Yes, we can hide the entity using Security Role removing Read access or control record implementing business unit.

There are also possibilities to restrict fields read permission using Field Level Security. But the problem is the user may need the entity to read access to show some of the data in various place saying SubGrid and main entity gird with predefined filter only, but you don’t want to show all the fields and records using Advanced Find for some security role.

In this situation you may go for retrieve multiple plugin where you can check the user security role the column they are accessing.

Requirement:

If the use having security role is “Salesperson” and you want to restrict user to view some columns apart from some predefined fields.

Here are the steps which I followed:

Step 1:  Restrict user to create own saved view in the Organization by going to settings –> Security role-> under Core Records –> deselect Saved View access.

2018-12-24_14-54-55_SavedView

Step 2: Create a pre-operation plugin which fires when any retrieve multiple operation will trigger, so I selected the message name “RetrieveMultiple” here and write your plugin looks like below –

using System;

using Microsoft.Xrm.Sdk;

using Microsoft.Xrm.Sdk.Query;

namespace Sample.Plugins

{

public class SubscriptionRetrieveMultipleFilter : IPlugin

{

/// <summary>

// Execute method will be trigger automatically when any retrieve multiple event trigger for subscription entity.

/// </summary>

/// <param name="serviceProvider"></param>

public void Execute(IServiceProvider serviceProvider)

{

try

{

IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));

IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));

IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);

ITracingService tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));

if ((context.Mode == 0) && (context.MessageName.Equals("RetrieveMultiple")) && (context.InputParameters.Contains("Query")) && (context.InputParameters["Query"] is QueryExpression) )

{

if (UserHasRole(context.InitiatingUserId, service))

{

// Get the QueryExpression from the property

QueryExpression objQueryExpression = (QueryExpression)context.InputParameters["Query"];

// Check any additional columns user wants to view

bool hasAdditionalColumn = ChecQueryHasAnyAdditionalColumn(objQueryExpression);

if (hasAdditionalColumn == true)

{

// If the query contains additional column then add some invalid filter condition 

// so that there will be no data to retrieve let say created on 20 years back for an example

ConditionExpression condition1 = new ConditionExpression();

FilterExpression filter1 = new FilterExpression();

filter1.FilterOperator = LogicalOperator.And;

condition1.AttributeName = "new_subscriptionname";

condition1.Operator = ConditionOperator.Equal;

condition1.Values.Add("SomeInValidName"); // Assigin some invalid value so that no data will match

filter1.Conditions.Add(condition1);

objQueryExpression.Criteria.AddFilter(filter1);

}

}

}

}

catch (Exception ex)

{

throw new InvalidPluginExecutionException("An error occurred in MyPlug-in.", ex);

}

}

/// <summary>

/// This function will check role if user having "Salesperson" security roles or not. If the user assigned "Salesperson" security role then function return true. 

/// </summary>

/// <param name="userid"></param>

/// <param name="_service"></param>

/// <returns></returns>

private bool UserHasRole(Guid userid, IOrganizationService _service)

{

bool hasRole = false;

QueryExpression qe = new QueryExpression("systemuserroles");

qe.Criteria.AddCondition("systemuserid", ConditionOperator.Equal, userid);

LinkEntity link = qe.AddLink("role", "roleid", "roleid", JoinOperator.Inner);

// Check whether user having "Salesperson" role

link.LinkCriteria.AddCondition("name", ConditionOperator.Equal, "Salesperson");

EntityCollection results = _service.RetrieveMultiple(qe);

hasRole = results.Entities.Count > 0;

return hasRole;

}

/// <summary>

/// This function will check any additional selected columns on top of predefined columns and return true when its found additional column

/// </summary>

/// <param name="columnName"></param>

/// <returns></returns>

private bool ChecQueryHasAnyAdditionalColumn(QueryExpression objQueryExpression)

{

bool hasAdditionalColumn = false;

// Here you can define your attributes list which user can access

string UserPerdefinedAccesssColumn = "new_subscriptionid,new_name,createdon";

foreach (string columnNmae in objQueryExpression.ColumnSet.Columns)

{

if (hasAdditionalColumn == false)

{

if (UserPerdefinedAccesssColumn.Contains(columnNmae))

hasAdditionalColumn = false;

else

hasAdditionalColumn = true;

}

}

return hasAdditionalColumn;

}

}

}

Here is the plugin steps –

2018-12-24_14-54-55_RetrieveMultipleStage

Hope this helps


This was originally posted here.

Comments

*This post is locked for comments