Wednesday, January 16, 2013

Custom CRM user admin role unable to assign roles to other users in MS CRM 2011


Recently our project was migrated from MS CRM 4.0 to MS CRM 2011. The migration went quite smooth without much issue. We are using the backward compatible web services provided by the 2011 system in our plugins. So we didn't have to change much in the plugin area.

One of the functionality in our system is that there is a separate team who deals with creation of users and then assigning roles and teams to them. We cannot assign System Administrator role to this users as they will be able to see the entire system and can perform the CRUD operation on any records they want. So in CRM 4.0, we just defined the required privileges in the business management tab for the role to create a user, assign roles and assign teams. So the users cannot see the data in the system other than the users.

Once we migrated to MS CRM 2011, we found that this is not working as the way it was working in MS CRM 4.0. The system was throwing an error message while trying to assign a role to the user. While searching on Google regarding this issue, I came across the below blog:


In CRM 2011 for security reasons a user must have same or higher privileges than the role they are assigning to other user. This is the reason why the user admin role is not able to assign roles to the user.

Microsoft has released a fix in UR 10. By applying this fix, we can make this work but with few restrictions.
·     The users should have a role equivalent to System Administrator ( Role Copied from System Administrator).
·     The User access mode and license type should be administrative so that the user can only see the administrative section and not the data. This means a full user will not be able to manage the user or the other way, the administrative user will not able to work on data records.


But in our case we were not able to go with this solution as there were some users who have the user admin role and other data entry roles in the system. So those users cannot be of administrative license type.

Currently we tried an unsupported implementation by modifying 2 files: dlg_role.aspx and dlg_removeroles.aspx. In the window.onload of dlg_role.aspx, we captured the roles to add/remove in 2 separate arrays. Then we retrieved the system user id of the user having System Administrator CRM role. Using the system administrator user context, we added the roles in the addroles array and removed roles in the removeroles array to/from the CRM user using AssociateEntityrequest and DisAssociateEntityRequest XmlHttp calls.

//Getting the Admin User Id
var AdminUserResponse = RetrieveAdminUserId();
if(AdminUserResponse!=null && AdminUserResponse.text!=null)
adminUserId = AdminUserResponse.text;

//Xmlhttp Associate Request
function AssociateEntities(relationshipSchemaName, entity1Name, entity1Id, entity2Name, entity2Id) {
var xmlReq = "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
+ "<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\""
+ " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">"
+ "<soap:Header><CrmAuthenticationToken xmlns=\"http://schemas.microsoft.com/crm/2007/WebServices\"><AuthenticationType xmlns=\"http://schemas.microsoft.com/crm/2007/CoreTypes\">0</AuthenticationType><OrganizationName xmlns=\"http://schemas.microsoft.com/crm/2007/CoreTypes\">" + Xrm.Page.context.getOrgUniqueName() +"</OrganizationName><CallerId xmlns=\"http://schemas.microsoft.com/crm/2007/CoreTypes\">" + adminUserId + "</CallerId></CrmAuthenticationToken></soap:Header>"
+ " <soap:Body>"
+ "<Execute xmlns=\"http://schemas.microsoft.com/crm/2007/WebServices\">"
+ "<Request xsi:type=\"AssociateEntitiesRequest\">"
+ "<Moniker1>"
+ "<Name xmlns=\"http://schemas.microsoft.com/crm/2006/CoreTypes\">" + entity1Name + "</Name>"
+ "<Id xmlns=\"http://schemas.microsoft.com/crm/2006/CoreTypes\">" + entity1Id + "</Id>"
+ "</Moniker1>"
+ "<Moniker2>"
+ "<Name xmlns=\"http://schemas.microsoft.com/crm/2006/CoreTypes\">" + entity2Name + "</Name>"
+ "<Id xmlns=\"http://schemas.microsoft.com/crm/2006/CoreTypes\">" + entity2Id + "</Id>"
+ "</Moniker2>"
+ "<RelationshipName>" + relationshipSchemaName + "</RelationshipName>"
+ "</Request>"
+ "</Execute>"
+ "</soap:Body>"
+ "</soap:Envelope>";
ExecuteSOAP("/MSCRMServices/2007/CrmService.asmx", xmlReq, http://schemas.microsoft.com/crm/2007/WebServices/Execute);
}

//Xmlhttp DisAssociate Request
function DisAssociateEntities(relationshipSchemaName, entity1Name, entity1Id, entity2Name, entity2Id) {
var xmlReq = "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
+ "<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\""
+ " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">"
+ "<soap:Header><CrmAuthenticationToken xmlns=\"http://schemas.microsoft.com/crm/2007/WebServices\"><AuthenticationType xmlns=\"http://schemas.microsoft.com/crm/2007/CoreTypes\">0</AuthenticationType><OrganizationName xmlns=\"http://schemas.microsoft.com/crm/2007/CoreTypes\">" + Xrm.Page.context.getOrgUniqueName() +"</OrganizationName><CallerId xmlns=\"http://schemas.microsoft.com/crm/2007/CoreTypes\">" + adminUserId + "</CallerId></CrmAuthenticationToken></soap:Header>"
+ " <soap:Body>"
+ "<Execute xmlns=\"http://schemas.microsoft.com/crm/2007/WebServices\">"
+ "<Request xsi:type=\"DisassociateEntitiesRequest\">"
+ "<Moniker1>"
+ "<Name xmlns=\"http://schemas.microsoft.com/crm/2006/CoreTypes\">" + entity1Name + "</Name>"
+ "<Id xmlns=\"http://schemas.microsoft.com/crm/2006/CoreTypes\">" + entity1Id + "</Id>"
+ "</Moniker1>"
+ "<Moniker2>"
+ "<Name xmlns=\"http://schemas.microsoft.com/crm/2006/CoreTypes\">" + entity2Name + "</Name>"
+ "<Id xmlns=\"http://schemas.microsoft.com/crm/2006/CoreTypes\">" + entity2Id + "</Id>"
+ "</Moniker2>"
+ "<RelationshipName>" + relationshipSchemaName + "</RelationshipName>"
+ "</Request>"
+ "</Execute>"
+ "</soap:Body>"
+ "</soap:Envelope>";
ExecuteSOAP("/MSCRMServices/2007/CrmService.asmx", xmlReq, http://schemas.microsoft.com/crm/2007/WebServices/Execute);
}

//Looping through the roles to Add
for (var i=0; i<addRoleCount; i++)
{
AssociateEntities("systemuserroles_association", "systemuser", _a[0], "role", rolesAdded[i]);
}

//Looping through the roles to remove.
for (var i=0; i<removeRoleCount; i++)
{
DisAssociateEntities("systemuserroles_association", "systemuser", _a[0], "role", rolesRemoved[i]);
}

As this is an unsupported way of doing, Please suggest us if anybody have any suggestions doing it in a supported way. Thank you so much for reading my blog and hearty welcome for all your suggestions and comments.

1 comment:

  1. Hi, Thanks for sharing this. We are in a process of migrating from CRM4 to 2011. I havent yet come across such problem yet but will keep this in mind for future. in the meawhile i can work out something to overcome this issue and i will keep you posted!!!

    ReplyDelete