Friday, October 21, 2011

BDCM: How to set permissions through the code?

[What you have]:
You have a BDCM file.


[What you want]:
You want to set permissions on the model and External Content Types (ECT) through the code.


[What you want to know]: 
You need to make sure that you have at least one access control entity with enough permission to avoid an error:
 At least one user/group in the Access Control List must have the SetPermissions right to avoid creating a non-manageable object.

There are 3 options how you can populate permissions through the code.

[What you want to do]:


1. PowerShell:


 $userAccountAdministrator = "{Domain}\{AdminUser}"; 
 $allUsers = "NT AUTHORITY\Authenticated Users";

 $userAdministrator=[Microsoft.SharePoint.BusinessData.Infrastructure.BdcAccessControlList]::TranslateFriendlyStringToEncodedClaim($userAccountAdministrator);
 $allUsers=[Microsoft.SharePoint.BusinessData.Infrastructure.BdcAccessControlList]::TranslateFriendlyStringToEncodedClaim($allUsers);

 $bdcRightsAdministrator= @([Microsoft.BusinessData.Infrastructure.BdcRights]::Execute, [Microsoft.BusinessData.Infrastructure.BdcRights]::Edit,[Microsoft.BusinessData.Infrastructure.BdcRights]::SetPermissions,[Microsoft.BusinessData.Infrastructure.BdcRights]::UseInBusinessDataInLists,[Microsoft.BusinessData.Infrastructure.BdcRights]::SelectableInClients); 
 $bdcRightsAllUsers= [Microsoft.BusinessData.Infrastructure.BdcRights]::Execute; 


 $aceAdministrator = New-Object "Microsoft.SharePoint.BusinessData.Infrastructure.IndividualAccessControlEntry" -arg $userAdministrator,$bdcRightsAdministrator ;
 $aceAllUsers=New-Object "Microsoft.SharePoint.BusinessData.Infrastructure.IndividualAccessControlEntry" -arg $allUsers,$bdcRightsAllUsers ;

$models=@(
"{Your model1}",
"{Your model2}",
"{Your model3}"
);


foreach ($modelName in $models)
{
$Model = Get-SPBusinessDataCatalogMetadataObject -BdcObjectType "Model" -name $modelName -ServiceContext {web app url}


$lbsAcl=$Model.GetAccessControlList();                                                                                                                                                                                                                           
$lbsAcl.Add($aceAdministrator);                                                                                                                                                                                                                                                        
$Model.SetAccessControlList($lbsAcl);                                                                                                                                                                                                                           


$entities=$Model.AllEntities;


foreach ($entity in $entities)
    {
      Write-Host $entity.DefaultDisplayName 


      $acl= $entity.GetAccessControlList(); 
      $acl.Add($aceAdministrator);
      $acl.Add($aceAllUsers);                                                                                                                                                                                                                                                           
      $entity.SetAccessControlList($acl);                                                                                                                                                                                                                                         
      $entity.CopyAclAcrossChildren();                                                                                                                                                                                                                                               
    }
}




2.  Feature receiver
Code Snippet: Add an Access Control Entry to a MetadataObject Using the Administration Object Model
  You can copy paste the code into your custom feature receiver.

3. Declaratively in a BDC Model:

  <AccessControlList>
    <AccessControlEntry Principal="{domain}\{AdminUser}">
      <Right BdcRight="Edit" />
      <Right BdcRight="Execute" />
      <Right BdcRight="SetPermissions" />
      <Right BdcRight="SelectableInClients" />
    </AccessControlEntry>
  </AccessControlList>


The BDC Model has a element <AccessControlList> in several places:
1. Permissions on the Model: inside <Model> tag
2. Permissions on External Content Type: inside <Entity> tag
3. Permissions on the method of ECT (in UI if the options is selected "Propagate permissions to all methods of this external content type. Doing so will overwrite existing permissions"): inside <Method> and <MethodInstance>