Revoke All Permissions on Item activity (here's the code)

Jun 30, 2011 at 4:35 PM

I think there was a request in here somewhere for an activity which could revoke all access on an item (without needing to know in your WF who had access). Since this project has been a big help to me, I'll add in my code here which I used for this activity, although my approach differs slightly from the style used in the rest of the project. Unclepaul84, feel free to include this or a modified version of this in your project if you'd like, just toss some sort of attribution in for me if you do so.

I've identified this action as both "Revoke All Access" and "Destroy Permissions", depending on context and how clearly I wanted to distinguish it from the "Revoke Access" action. Its behavior is to break inheritance (if needed), and then remove permissions for all users/groups on the specified listItem unless the user/group has been given "Full Control" (I never want to remove admin access).

In PermissionsService.cs , you'll need to make 3 changes:

  1. Add a new item to the PermissionActionType enum (I think this enum might normally be in Common.cs , I moved it to make integration into my solution more logical)

    internal enum PermissionActionType {
            Grant = 1,
            Revoke = 2,
            Reset = 3,
            Destroy = 4
        }
    
  2. In the "PermissionRequest processing methods" region, add a new method to handle this PermissionActionType:

    private void ProcessDestroyRequest(PermissionRequest pr) {
                int retryCount = 0;
    
                SPSecurity.RunWithElevatedPrivileges(delegate() {
    
                    using (SPSite site = new SPSite(pr.SiteID)) {
                        using (SPWeb web = site.AllWebs[pr.WebID]) {
                            SPList list = web.Lists[pr.ListID];
    
                            SPListItem listItem = list.Items.GetItemById(pr.ItemId);
                            ArrayList roleAssesToRemove = new ArrayList();
                            foreach (SPRoleAssignment ra in listItem.RoleAssignments) {
                                bool notAnAdmin = true;
                                foreach (SPRoleDefinition rd in ra.RoleDefinitionBindings) {
                                    if (rd.Type == SPRoleType.Administrator)
                                        notAnAdmin = false;
                                }
                                if (notAnAdmin)
                                    roleAssesToRemove.Add(ra);
                            }
    
                            bool finished = false;
                            while (!finished) {
                                listItem = list.Items.GetItemById(pr.ItemId);
    
                                try {
                                    if (roleAssesToRemove.Count != 0) {
                                        // Can be removed if calling Common.RemoveListItemPermi... :
                                        if (!listItem.HasUniqueRoleAssignments)
                                            listItem.BreakRoleInheritance(true);
    
                                        foreach (SPRoleAssignment ra in roleAssesToRemove) {
                                            listItem.RoleAssignments.Remove(ra.Member);
                                            //Common.RemoveListItemPermissionEntry(listItem, ra.Member.Name, true);
                                        }
                                    }
                                    finished = true;
                                } catch {
                                    retryCount++;
                                    finished = (retryCount > 3) ? true : false;
                                }
                            }
                        }
                    }
                });
            }
    
  3. In Commit(), add another switch case to call the method defined above

 

Then create a new activity class for this. I won't bore you with the DependencyProperties or class definition (base it off the Reset Permissions class & properties if you're confused), but the Execute method should be:

 

protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext) {
            
            try {
                PermissionRequest myDestroyRequest = new PermissionRequest();

                myDestroyRequest.RequestType = PermissionActionType.Destroy;
                myDestroyRequest.ItemId = this.listItem;
                myDestroyRequest.ListID = new Guid(this.listID);
                myDestroyRequest.SiteID = this.__Context.Site.ID;
                myDestroyRequest.WebID = this.__Context.Web.ID;

                WorkflowEnvironment.WorkBatch.Add(PermissionsService.Instance, myDestroyRequest);
            } catch {             
                return ActivityExecutionStatus.Faulting;
            }
            return ActivityExecutionStatus.Closed;
        }

And finally, add a new Action element to your custom .ACTIONS file (if you're using the code for this solution, look in the Install/12/Template... dir):

<Action
                Name="Revoke All Permissions on Object"
                ClassName="NAMESPACE.PermissionsRevokeAllActivity"
                Assembly="NAMESPACE, Version=YOURVERSION, Culture=neutral, PublicKeyToken=YOURPUBLICKEY"
                AppliesTo="all"
                Category="Custom: Item-Level Permissions">
            <RuleDesigner Sentence="Revoke all permissions on %1 for all users/groups (except those with Full Control)">
                <FieldBind Id="1" Field="listID,listItem"  DesignerType="ChooseListItem"   Text="List Item" />
            </RuleDesigner>
            <Parameters>
                <Parameter Name="__Context"     Type="Microsoft.SharePoint.WorkflowActions.WorkflowContext"     Direction="In" />
                <Parameter Name="__ListId"      Type="System.String, mscorlib"  Direction="In" />
                <Parameter Name="__ListItem"    Type="System.Int32, mscorlib"   Direction="In" />
                <Parameter Name="__ActivationProperties"    Type="Microsoft.SharePoint.Workflow.SPWorkflowActivationProperties, Microsoft.SharePoint"   Direction="In" />
                <Parameter Name="listID"        Type="System.String"            Direction="In" />
                <Parameter Name="listItem"      Type="System.Int32"             Direction="In" />
            </Parameters>
        </Action>

Hope it helps someone