Thursday, May 28, 2009

Share Records programmatically

Few days back our client placed a new requirement that he needs the newly created lead needs to to be shared by all the team mates of the businessunit, and that needs to be done automatically. I thought a workflow on lead creation will do the job. But when I sit on the system and to my surprise found that there is no option in the workflow manager for the same. I started scratching my head and at last decided to write a plugin for the same. Now instead of writing everything from scratch I asked the same to my good old friend (GOOGLE) :-) and i was really surprised to get this post by David Fronk of Dynamic Methods Inc. He explained everything in such detail that ...... it starts looking like a kid's play.

With all credit to his great job the excerpts of the post is :

Most implementations just open things up at the business unit level, or even the global level (depending on the size of the company) and don't even worry about sharing. However, there are times when certain information can be sensitive and necessary to restrict access to. Typically these things can be activities, opportunities, cases, services billed, hours worked, etc.


For instance, suppose sales reps aren't allowed to see support cases but are allowed to see the accounts that they manage. Any good account manager would want to know what support issues their account has been having before engaging on a new business proposal, so obviously the sales rep should get to see the cases related to the account.


All that is required is a couple of plugins at two main points and upon creation of a case and reassignment of an account. Whenever a case is created, get the account manager of the account on the case and share the case with that user. If the account gets reassigned, remove the share from the old account manager and add rights to the new account manager. Now with simple logic you can make data more accessible to those who should see the data without them having to do anything more than their regular job.


One side note, be aware that the more items there are under a parent record the longer the reassignments of records will take. For instance, if I reassign an account with 50 cases that's going to take a lot longer to complete the reassignment than it would if there were 5 cases, or even none. Just keep that in mind as you develop your sharing solution.


Pretty simple, and the SDK has some great examples on how to do this. Look up "AccessRights Enumeration", "GrantAccess Message", and "RevokeAccess Message" in the SDK and you should have everything you need.


Here's a quick example on how to share and give all rights to a user:





SecurityPrincipal principal = new
SecurityPrincipal();
principal.Type = SecurityPrincipalType.User;
principal.PrincipalId = new
Guid("7B222F98-F48A-4AED-9D09-77A19CB6EE82");
PrincipalAccess access = new
PrincipalAccess();
access.Principal = principal;
access.AccessMask = AccessRights.ReadAccess;

TargetOwnedDynamic target = new
TargetOwnedDynamic();
target.EntityId = new
Guid("6A92D3AE-A9C9-4E44-9FA6-F3D5643753C1");
target.EntityName = "incident";

GrantAccessRequest readGrant = new
GrantAccessRequest();
readGrant.PrincipalAccess = access;
readGrant.Target = target;
GrantAccessResponse readGranted = (GrantAccessResponse)crmService.Execute(readGrant);

access.AccessMask = AccessRights.WriteAccess;
readGrant.PrincipalAccess = access;
GrantAccessResponse writeGranted = (GrantAccessResponse)crmService.Execute(readGrant);

access.AccessMask = AccessRights.AppendAccess;
readGrant.PrincipalAccess = access;
GrantAccessResponse appendGranted = (GrantAccessResponse)crmService.Execute(readGrant);

access.AccessMask = AccessRights.AppendToAccess;
readGrant.PrincipalAccess = access;
GrantAccessResponse appendToGranted = (GrantAccessResponse)crmService.Execute(readGrant);

access.AccessMask = AccessRights.AssignAccess;
readGrant.PrincipalAccess = access;
GrantAccessResponse assignGranted = (GrantAccessResponse)crmService.Execute(readGrant);

access.AccessMask = AccessRights.DeleteAccess;
readGrant.PrincipalAccess = access;
GrantAccessResponse deleteGranted = (GrantAccessResponse)crmService.Execute(readGrant);



And here is an example on how to revoke access:





SecurityPrincipal principal = new
SecurityPrincipal();
principal.Type = SecurityPrincipalType.User;
principal.PrincipalId = new
Guid("7B222F98-F48A-4AED-9D09-77A19CB6EE82");
PrincipalAccess access = new
PrincipalAccess();
access.Principal = principal;
access.AccessMask = AccessRights.ReadAccess;

TargetOwnedDynamic target = new
TargetOwnedDynamic();
target.EntityId = new
Guid("6A92D3AE-A9C9-4E44-9FA6-F3D5643753C1");
target.EntityName = "incident";
GrantAccessRequest readGrant = new
GrantAccessRequest();
readGrant.PrincipalAccess = access;
readGrant.Target = target;
GrantAccessResponse readGranted = (GrantAccessResponse)crmService.Execute(readGrant);

No comments: