Privileges
Privileges define the action that a user can perform on a CRM System and at what level.
Privileges are added by system. Privileges can be modified but can’t be deleted. Privileges are assigned to users or teams using Security Roles. For security roles, privileges are assigned with different access levels i.e. User Level (basic), Business Unit (local), Parent (deep), and Organizational level.
There are 5 levels of access:
None – No Privileges
User (basic) – Privileges given at user level on records owned by/Shared with user or team.
Business Unit (local) – Privileges given on all the records in the Business Unit.
Parent: Child Business Unit (deep) – Privileges given on all the records in the user’s Business Unit and the Business Units subordinate to that Business Unit.
Organization (global): Privileges on all the records in the Organization.
How to Check Privileges Programmatically using C# and JavaScript:
In the below code it’s checked if the given user has user(basic) level privileges on Account entity.
Using C#:
bool userHasCreatePrivilege = false; QueryExpression query = new QueryExpression("privilege"); query.ColumnSet = new ColumnSet(new[] { "name", "canbebasic" }); //canbebasi == user level LinkEntity lnkEnty1 = new LinkEntity("privilege", "roleprivileges", "privilegeid", "privilegeid", JoinOperator.Inner); LinkEntity lnkEnty2 = new LinkEntity("roleprivileges", "role", "roleid", "roleid", JoinOperator.Inner); LinkEntity lnkEnty3 = new LinkEntity("role", "systemuserroles", "roleid", "roleid", JoinOperator.Inner); LinkEntity lnkEnty4 = new LinkEntity("systemuserroles", "systemuser", "systemuserid", "systemuserid", JoinOperator.Inner); ConditionExpression condition = new ConditionExpression("systemuserid", ConditionOperator.Equal, userId); lnkEnty4.LinkCriteria.AddCondition(condition); FilterExpression filter = new FilterExpression(LogicalOperator.Or); filter.AddCondition("name", ConditionOperator.Equal, "prvCreateAccount”); query.Criteria = filter; lnkEnty3.LinkEntities.Add(lnkEnty4); lnkEnty2.LinkEntities.Add(lnkEnty3); lnkEnty1.LinkEntities.Add(lnkEnty2); query.LinkEntities.Add(lnkEnty1); EntityCollection entities= service.RetrieveMultiple(query); if (entities.Entities.Count > 0) { Entity entity = entities.Entities[0]; if (entity.Contains("canbebasic") && entity["canbebasic"] != null && (bool)entity["canbebasic"] == true) userHasCreatePrivilege = true; }
Using JavaScript:
Privileges can also be checked using SOAP request and Fetch Xml:
function checkUserPrivileges() { var fetchXml = generateFetchXml("prvCreatAccount", Xrm.Page.context.getUserId()); var request = generateFetchBasedSOAPRequest(fetchXml); var xmlhttp = new XMLHttpRequest(); xmlhttp.open("POST", getClientUrl() + "XRMServices/2011/Organization.svc/web", true); xmlhttp.setRequestHeader("Accept", "application/xml, text/xml, */*"); xmlhttp.setRequestHeader("Content-Type", "text/xml; charset=utf-8"); xmlhttp.setRequestHeader("SOAPAction", "http://schemas.microsoft.com/xrm/2011/Contracts/Services/IOrganizationService/Execute"); xmlhttp.onreadystatechange = function () { if (this.readyState == 4) { xmlhttp.onreadystatechange = null; parseSoapResponse(this); } }; xmlhttp.send(request); } function generateFetchXml(privilageName, userId) { var fetchXml = "<fetch mapping='logical' version='1.0'>" + "<entity name='privilege'>" + "<attribute name='accessright' />" + "<attribute name='name' />" + "<filter>" + "<condition attribute='name' operator='eq' value='" + privilageName + "' />" + "</filter>" + "<link-entity name='roleprivileges' from='privilegeid' to='privilegeid'>" + "<link-entity name='role' from='parentrootroleid' to='roleid'>" + "<link-entity name='systemuserroles' from='roleid' to='roleid'>" + "<filter>" + "<condition attribute='systemuserid' operator='eq' value='" + userId + "' />" + "</filter>" + "</link-entity>" + "</link-entity>" + "</link-entity>" + "</entity>" + "</fetch>"; return fetchXml; } function generateFetchBasedSOAPRequest(fetchXml) { var request = "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\">"; request += "<s:Body>"; request += '<Execute xmlns="http://schemas.microsoft.com/xrm/2011/Contracts/Services">' + '<request i:type="b:RetrieveMultipleRequest" ' + ' xmlns:b="http://schemas.microsoft.com/xrm/2011/Contracts" ' + ' xmlns:i="http://www.w3.org/2001/XMLSchema-instance">' + '<b:Parameters xmlns:c="http://schemas.datacontract.org/2004/07/System.Collections.Generic">' + '<b:KeyValuePairOfstringanyType>' + '<c:key>Query</c:key>' + '<c:value i:type="b:FetchExpression">' + '<b:Query>'; request += CrmEncodeDecode.CrmXmlEncode(fetchXml); request += '</b:Query>' + '</c:value>' + '</b:KeyValuePairOfstringanyType>' + '</b:Parameters>' + '<b:RequestId i:nil="true"/>' + '<b:RequestName>RetrieveMultiple</b:RequestName>' + '</request>' + '</Execute>'; request += '</s:Body></s:Envelope>'; return request; }
Access Rights
Access rights is basically record based security that applies to individual records. It’s provided by using Access Rights. Access rights are bit different than privileges. Privileges can be assigned through security roles while access rights can be given using Access Teams or Sharing. A user/team can you access rights on record level even without having privileges. Access rights apply after privileges have taken effect.
Access Rights Provided through Access Team (Access Team Template):
Access Rights provided using Sharing:
Create Access – In the above tables you’ll notice that there is no Create Access listed. The reason is Create is handled as a Privilege instead of an Access Right.
Retrieve Access Rights Programmatically using C# and JavaScript:
C# Code to retrieve Access Rights:
bool userHasAccessRight = false; var principalAccessRequest = new RetrievePrincipalAccessRequest{ Principal = new EntityReference("systemuser", new Guid(".....")), Target = new EntityReference("account", new Guid(".....")) }; var principalAccessResponse = (RetrievePrincipalAccessResponse)service.Execute(principalAccessRequest); if ((principalAccessResponse.AccessRights & AccessRights.ReadAccess) != AccessRights.None) { userHasAccessRight = true; }
Using JavaScript:
Using RetrievePrincialAccess Request, it can be accessed Access Rights to a user on a particular record.
function checkUserAccessRights() { var request= generateSoapRetrievePrincipalAccessRequest(); var xmlhttp = new XMLHttpRequest(); xmlhttp.open("POST", getClientUrl() + "XRMServices/2011/Organization.svc/web", true); xmlhttp.setRequestHeader("Accept", "application/xml, text/xml, */*"); xmlhttp.setRequestHeader("Content-Type", "text/xml; charset=utf-8"); xmlhttp.setRequestHeader("SOAPAction", "http://schemas.microsoft.com/xrm/2011/Contracts/Services/IOrganizationService/Execute"); xmlhttp.onreadystatechange = function () { if (this.readyState == 4) { xmlhttp.onreadystatechange = null; parseResponse(this); } }; xmlhttp.send(request); } function generateSoapRetrievePrincipalAccessRequest() { var userId = Xrm.Page.context.getUserId(); var accountId= Xrm.Page.data.entity.getId(); var accountLogicalName = "account"; var requestName = "RetrievePrincipalAccess"; var systemUserLogicalName = "systemuser"; var requestMain = ""; requestMain += "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\">"; requestMain += " <s:Body>"; requestMain += " <Execute xmlns=\"http://schemas.microsoft.com/xrm/2011/Contracts/Services\" xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\">"; requestMain += " <request i:type=\"b:RetrievePrincipalAccessRequest\" xmlns:a=\"http://schemas.microsoft.com/xrm/2011/Contracts\" xmlns:b=\"http://schemas.microsoft.com/crm/2011/Contracts\">"; requestMain += " <a:Parameters xmlns:c=\"http://schemas.datacontract.org/2004/07/System.Collections.Generic\">"; requestMain += " <a:KeyValuePairOfstringanyType>"; requestMain += " <c:key>Target</c:key>"; requestMain += " <c:value i:type=\"a:EntityReference\">"; requestMain += " <a:Id>" + accountId+ "</a:Id>"; requestMain += " <a:LogicalName>" + accountLogicalName+ "</a:LogicalName>"; requestMain += " <a:Name i:nil=\"true\" />"; requestMain += " </c:value>"; requestMain += " </a:KeyValuePairOfstringanyType>"; requestMain += " <a:KeyValuePairOfstringanyType>"; requestMain += " <c:key>Principal</c:key>"; requestMain += " <c:value i:type=\"a:EntityReference\">"; requestMain += " <a:Id>" + userId + "</a:Id>"; requestMain += " <a:LogicalName>" + systemUserLogicalName + "</a:LogicalName>"; requestMain += " <a:Name i:nil=\"true\" />"; requestMain += " </c:value>"; requestMain += " </a:KeyValuePairOfstringanyType>"; requestMain += " </a:Parameters>"; requestMain += " <a:RequestId i:nil=\"true\" />"; requestMain += " <a:RequestName>" + requestName + "</a:RequestName>"; requestMain += " </request>"; requestMain += " </Execute>"; requestMain += " </s:Body>"; requestMain += "</s:Envelope>"; return requestMain; }