Privileges and Access Rights in CRM 2013

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.

Privileges

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):

AccessTeam

Access Rights provided using Sharing:

Share

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 &amp; 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;

}