Programmatically and Selectively Revoke SharePoint Item-Level Permissions Using PowerShell
I’ve been using PowerShell more and more lately, and liking it more and more as I use it.
Here’s another one you might find useful – programmatically and selectively revoking item-level permissions. For this scenario, the SharePoint list already has inheritance broken. Now we have to loop through the versions of SharePoint list items, and check a people/group column called Participant. A participant would have had read/contribute permissions before, but after the list item has been verified, we don’t want the participants changing any of the values anymore.
We will start with the typical loading of the DLL, and creating a handle to our SharePoint site:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | #Load the SharePoint DLL [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint") | Out-Null $SiteURL = $server; #make sure we're using the system account token $TmpSite = New-Object Microsoft.SharePoint.SPSite($SiteURL); $SysToken = $TmpSite.SystemAccount.UserToken; $SPSite = New-Object Microsoft.SharePoint.SPSite($SiteURL,$SysToken); #if we want to get additional info about SPSite, code is below #$SPSite.AllWebs | Format-Table Url, ID, Name, AllUsers $SPWeb = $SPSite.OpenWeb(); $SPWeb.AllowUnsafeUpdates = $true; $MyList = $SPWeb.Lists["My Sample List"]; |
Now let’s get only verified items from our list:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | #note your ending herestring must NOT have a space before it. #also, this "Project Audited" field is really a boolean, #but using the Integer works $CAML = @" <Where> <Eq> <FieldRef Name='Project_x0020_Verified' /> <Value Type='Integer'>1</Value> </Eq> </Where> "@ $SPQuery = New-Object Microsoft.SharePoint.SPQuery; $SPQuery.Query = $CAML; $itemCollection = $null; $itemCollection = $MyList.GetItems($SPQuery); $listItem = $null; |
Now the bulk of the work is as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | if($ItemCollection.Count -gt 0) { foreach($listItem in $itemCollection) { $ID = [string]$listItem["ID"] $ProjectVerified = [string]$listItem["Project Verified"] #now I want to display the roles before I revoke, #so I can verify the changes visually #assume in here you already created a new file for #this process, and gave it a handle $logfile "Roles BEFORE revoke : " | Out-File -FilePath $logfile -Append foreach ($role in $roles) { $msg = "Role : ID " + $role.Member.ID.ToString() + " : Name " + $role.Member.Name $msg | Out-File -FilePath $logfile -Append } #get the item versions (SPListItemVersionCollection) $itemVersionCollection = $listItem.Versions; #need to check current permissions #we'll store all Participants in an array first and evaluate later $Participants = @(); foreach($currentVersion in $itemVersionCollection) { $SPFieldUserValue = New-Object Microsoft.SharePoint.SPFieldUserValue($SPWeb, [string]$currentVersion["Participant"]); $Participants += $SPFieldUserValue.User.LoginName } #now, we just want to get the unique people from the version, #so we don't unnecessarily revoke $Participants = $Participants | SELECT -Unique #let's now revoke permissions for every participant #that has ever been involved in any version of this item foreach($Participant in $Participants) { $user = $SPWeb.AllUsers[$Participant]; $listItem.RoleAssignments.Remove([Microsoft.SharePoint.SPUser]$user); } #confirm "Roles AFTER revoke : " | Out-File -FilePath $logfile -Append foreach ($role in $roles) { $msg = "Role : ID " + $role.Member.ID.ToString() + " : Name " + $role.Member.Name $msg | Out-File -FilePath $logfile -Append } } } |
And very very important, do not forget to dispose the SPWeb and SPSite objects you created. It’s VERY bad to not dispose it, as it will definitely slow down your site, one way or another. Believe me, you don’t want to learn this the hard way.
1 2 3 | $SPWeb.Dispose(); $SPSite.Dispose(); $TmpSite.Dispose(); |
Done. Happy times.