Migrate/reassign personal views from a user to another

This article is somehow linked to another one i wrote few times ago regarding the migration of views from OnPrem to Online.

The point here is not to explain one more time the concept behind but to introduce my latest XrmToolBox plugin :

Personal user views Migration :

This plugin will allow you to load all users and then for each one of them load it's views and have then the possibility to copy the selected views to another user OR reassign the views.

I know you can do it from the user interface but you have constraint :

  • You need to ask the owner of the views to do it
  • If the user is not in your azure active directory since more than 30 days (CRM Online), you are stuck since no actions can no longer be done on behalf of this user.

So i thought a quick tool to make your life easier regarding the migration or reassignement of views could help some of you.

Quick recap regarding the technical concept here :
  • Load the users from your organization either enabled or not
  • Load the views from the selected user
  • Copy/Reassign the view to the destination user

Seems to be really easy so far BUT as you might know to perform any action of behalf of other users, you need to have the permissions from the security roles.
With this permission, you can update the "CallerId" and impersonate yourself as the selected user.

But it's not enough, this works with enabled users. If a user is disabled (without a license), you won't be able to impersonate.
As a workaround here, i used the different "Access Mode" available on the systemuser side.
You have 4 access modes : Read/Write, Non Interactive and Administrative.
Here we are interested in the Non Interactive mode (limited to 5 per instance) which allow a user to access the WebApi but not the UI and this without consuming a license.

Here is the code i use to check if the user is disabled and then to switch from Read/Write (0) to NonInteractive mode (4) :

public void CheckIfUserEnabled(Guid userGuid, int accessmode = 4)  
{
    // By default i set it to the user
    Entity user = service.Retrieve("systemuser", userGuid, new Microsoft.Xrm.Sdk.Query.ColumnSet("isdisabled", "accessmode", "fullname"));

    // we check if the user exist in the crm                       
    if (user != null)
    {
        Trace.TraceInformation(String.Format("checking User : {0}, isdisabled : {1}, accessmode : {2}", user["fullname"], user["isdisabled"], ((OptionSetValue)user["accessmode"]).Value));
        // If the user is disabled or is in Non Interactive mode, we update it.
        if (Boolean.Parse(user["isdisabled"].ToString()) || ((OptionSetValue)user["accessmode"]).Value == 4)
        {
            user["accessmode"] = new OptionSetValue(accessmode);

            service.Update(user);
            Trace.TraceInformation(String.Format("updated User : {0} to accessmode : {1}", user["fullname"], accessmode));
        }
    }
}

So if I'm trying to execute any actions for a disabled user, i need first to switch his Access Mode to Non Interactive, then perform my request over the WebApi and switch the Access Mode back to Read/Write (to free the Non Interactive mode slot).

Knowing that, the number of Non Interactive mode enabled in parallel is limited to 5.

Hope this will help you out !
Happy CRM'in,
Clément

Clement

Dynamics 365 CRM & Power Platform addict.