Opportunity Product Permissions

When an assumption is made that something very basic, can be easily configured using OOB functionalities, that is when I find myself stuck occasionally and having to rethink on how to implement a feature. I recently had one such experience. The requirement was to allow users in certain security role, to delete opportunity products, but not opportunities.My first thought was to use security role, to modify the permissions for opportunity products. To my surprise, I was unable to find opportunity products in Security Role.

It turns out Opportunity Product, Invoice Product, Quote Product and Order Product share a unique trait: they don’t have separate permissions and use the permission of their parent. Such being the limitation, I could implement this using ribbons or plugins. I implemented this using ribbon. Here are the steps

  1. Grant Delete permission on the Opportunity entity for the appropriate security role
  2.  Use Ribbon Workbench to edit the ribbon for opportunity entity
  3. Add a new Enable Rule of type Custom Javascript Rule. I am calling a function in the Javascript webresource
  4.  Add the Enable Rule to the following commands:  
    • Mscrm.DeletePrimaryRecord
    • Mscrm.DeleteSelectedRecord
    • Mscrm.HomePageGrid.DeleteSplitButtonCommand

This change should be done on HomePage, Form and Subgrid ribbons. The code for the getOppDeletePermissionByRole itself is quite simple, as I am using XrmServiceToolkit.

var CVN = window.CVN || {};

CVN.getOppDeletePermissionByRole = function() {
 return !XrmServiceToolkit.Soap.IsCurrentUserRole('1.1 CRM - Base User Role');

window.CVN = CVN;

I did this on a CRM2011 organisation, but the process in same for a CRM2015 organisation. You’ll just be editing the command bar instead of the ribbon. Here are the relevant buttons in CRM2015, whose command you’ll need to edit.

Deployment Manager exception after installing UR17 in CRM 2011

I recently encountered an issue with an existing CRM 2011 environment after installing Rollup 17. The deployment manager would crash with this following error.

Type is not resolved for member ‘Microsoft.Crm.CrmSecurityException,Microsoft.Crm.Core, Version=, Culture=neutral, PublicKeyToken=31bf3856ad364e35’.
I turned on CRM tracing and this seems to be the underlying error.

CrmException..ctor(String message, Exception innerException, Int32 errorCode, Boolean isFlowControlException)  ilOffset = 0x0
at CrmException..ctor(String message, Exception innerException, Int32 errorCode)  ilOffset = 0x0
at SecurityUtils.GetActiveDirectoryEntry(String searchItem, String searchFilter, String searchItemLogInfo, Boolean throwIfNotFound, String domainName)  ilOffset = 0x44
at SystemUserService.GetCaseSafeName(String domain, String accountName)  ilOffset = 0x188
at SystemUserService.GetCaseSafeName(String name)  ilOffset = 0x50
at SystemUserService.GetIdsFromName(String userName)  ilOffset = 0xB
at SecurityRoleService.TryVerifyUser(String userName, SecurityRole role)  ilOffset = 0xC
at SystemUserController.TryVerifyUser()  ilOffset = 0xD
at DMSnapInHelper.DisplayMessageBoxIfCurrentUserIsNotSystemUser(Console console)  ilOffset = 0x0
at DMSnapIn.OnInitialize()  ilOffset = 0x27
at SnapInBase.Initialized()  ilOffset = 0x41
at SnapInClient.Microsoft.ManagementConsole.Internal.ISnapInClient.Initialize(ISnapInPlatform snapInPlatform)  ilOffset = 0x14
at UnsafeNativeMethods.DispatchMessageW(MSG& msg)  ilOffset = 0xFFFFFFFF
at ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)  ilOffset = 0x18E
at ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)  ilOffset = 0x1F7
at ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)  ilOffset = 0x13
at SnapInMessagePumpProxy.Microsoft.ManagementConsole.Internal.ISnapInMessagePumpProxy.Run()  ilOffset = 0x34
>Crm Exception: Message: Could not find AD entry for : 09283477 with SearchFilter: samAccountName, ErrorCode: -2147214038, InnerException: System.DirectoryServices.ActiveDirectory.ActiveDirectoryObjectNotFoundException: The specified domain does not exist or cannot be contacted.
at System.DirectoryServices.ActiveDirectory.Domain.GetDomain(DirectoryContext context)
at Microsoft.Crm.SecurityUtils.GetActiveDirectoryEntry(String searchItem, String searchFilter, String searchItemLogInfo, Boolean throwIfNotFound, String domainName)

After much troubleshooting with CRM tracing, Netmon, LDAP Tracing and Wireshark I was able to ascertain that this exception is thrown right after Deployment Manager sends a NbtNs packet before crashing.

 I wrote a small console application to see if this could be a Domain Controller issue. There was no NbtNs packet sent out in my console application and it was successfully able to query the user details.
I posted this in CRM forums and it seems that others also are having the same issue, after moving to Rollup 17. This seems to be a bug in UR17, which cannot handle more than 15 characters in Domain Name (according to the poster). Here is the forum post https://community.dynamics.com/crm/f/117/t/128100.aspx

There was also an additional issue I encountered when I tried to uninstall UR17. The uninstall process would crash with a owner_importlogs key violation on ImportLogBase table. It seems the uninstall process wants to insert two rows with Owner Id = Guid.Empty in the ImportLogBase table.

I had to disable this constraint, allow the uninstall process to finish and later delete these two rows.

So if are having similar issues with Deployment Manager after installing UR17, downgrade to UR16 or wait for UR18.