Dataverse: Share Record Access

I have experienced the scenario where the Organization wants to implement strict record management where the requirement was to limit access based on the team. For example, if the owner of the record is Team A, the other Teams can’t interact with it unless one of the members of Team A shares it with those teams. By default, Dataverse can control it by defining User/Team access that you can more in this link. Today we will learn how we can implement this requirement in two ways. Using GrantAccessRequest and also AddUserToRecordTeamRequest!

Security role

GrantAccessRequest

If you need sharing the access anytime + dynamics, you can use this OOB (out-of-the-box) feature. When you open a record from Model-Driven-Apps, you can click Share > Add/remove the User/Team > select the permission that you want to add:

Share the record

You can select multiple permissions per User/Team and press the Share button:

Select the permission

Below is the code to do the same operation:

using System;
using System.Web.Configuration;
using Entities;
using Microsoft.Crm.Sdk.Messages;
using Microsoft.Xrm.Tooling.Connector;

namespace CrmCheck
{
    class Program
    {
        static void Main(string[] args)
        {
            var connectionString = WebConfigurationManager.AppSettings["connectionString"];
            var client = new CrmServiceClient(connectionString);
            var contact = new Contact { Id = new Guid("f3310bfd-b5a1-ec11-b400-002248576bd2") };

            var teamA = new Team { Id = new Guid("b15b756c-c5a1-ec11-b400-002248576bd2") };
            var accessRequest = new GrantAccessRequest
            {
                Target = contact.ToEntityReference(),
                PrincipalAccess = new PrincipalAccess
                {
                    AccessMask = AccessRights.ReadAccess | AccessRights.WriteAccess | AccessRights.DeleteAccess,
                    Principal = teamA.ToEntityReference()
                }
            };
            client.Execute(accessRequest);

            var retrieveRequest = new RetrieveSharedPrincipalsAndAccessRequest
            {
                Target = contact.ToEntityReference()
            };
            var retrieveResponse = (RetrieveSharedPrincipalsAndAccessResponse)client.Execute(retrieveRequest);
            foreach (var item in retrieveResponse.PrincipalAccesses)
            {
                var modifyRequest = new ModifyAccessRequest
                {
                    Target = contact.ToEntityReference(),
                    PrincipalAccess = new PrincipalAccess
                    {
                        AccessMask = AccessRights.WriteAccess,
                        Principal = item.Principal
                    }
                };
                client.Execute(modifyRequest);

                var revokeRequest = new RevokeAccessRequest
                {
                    Target = contact.ToEntityReference(),
                    Revokee = item.Principal
                };
                client.Execute(revokeRequest);
            }
            Console.ReadKey();
        }
    }
}

In the above code, to give access, we can use the GrantAccessRequest operation and pass the Target record that you want to share. Also, you need to pass PrincipleAccess with AccessRights that you want to set + Principal (The User/Team) that you selected.

If you want to retrieve all the share history, you can use RetrieveSharedPrincipalsAndAccessRequest. To modify the shared access you can use ModifyAccessRequest. And the last for revoking you can use RevokeAccessRequest.

AddUserToRecordTeamRequest

If your organization already has a predefined pattern for sharing the record, you might consider AddUserToRecordTeamRequest! To enable Access Team you must go to the Customization > Entities > your Entity that you want to enable > Check the Access Teams checkbox:

Set Entity Access Teams

Don’t forget to hit the Save and Publish button!

Then you need to create Team Templates:

Create Team Template

For adding/removing the user (only can by user), you need to invoke the below code:

using System;
using System.Web.Configuration;
using Entities;
using Microsoft.Crm.Sdk.Messages;
using Microsoft.Xrm.Tooling.Connector;

namespace CrmCheck
{
    class Program
    {
        static void Main(string[] args)
        {
            var connectionString = WebConfigurationManager.AppSettings["connectionString"];
            var client = new CrmServiceClient(connectionString);
            var contact = new Contact { Id = new Guid("f3310bfd-b5a1-ec11-b400-002248576bd2") };

            var user = new SystemUser { Id = new Guid("07C7FE54-F968-EC11-8941-002248583842") };
            var teamTemplate = new TeamTemplate { Id = new Guid("bea177ef-d7a1-ec11-b400-002248576bd2") };
            var addUserToTeamRequest = new AddUserToRecordTeamRequest
            {
                Record = contact.ToEntityReference(),
                SystemUserId = user.Id,
                TeamTemplateId = teamTemplate.Id
            };

            client.Execute(addUserToTeamRequest);

            var deleteTeamRequest = new RemoveUserFromRecordTeamRequest
            {
                Record = contact.ToEntityReference(),
                SystemUserId = user.Id,
                TeamTemplateId = teamTemplate.Id
            };
            client.Execute(deleteTeamRequest);
            Console.ReadKey();
        }
    }
}

The drawn back using this method, System will automatically create Team with Type = Access. And in my experience, the more the record grows, the more you will have a performance problem. That is why you need to manage the Team with Type=Access (to delete).

Access Type Team created

Hopefully you learn something and happy CRM-ing!

3 thoughts on “Dataverse: Share Record Access

    1. Yessss Sir! My first project refactored (CRM 2015 on premise) also related with this one. The principal object access data keeps growing + make the system slow. In the end we changed it to Organization+using JavaScript to to redirect if the user don’t have access (based on attributes). 🙂

      Liked by 1 person

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.