Recently we had to archive a few document libraries on our SharePoint farm. The document libraries may have they own permission setting on the library level, and / or at the folder, and / or the document levels either. We do not have any custom permission level defined in our sites.
We defined “archive” as this: all users that have read / write permission to an item, should keep the access on the item, but it has to be restricted to read permission in the future. The users having permission to the documents should be able to download them, and work on them locally (if they wish) but are not allowed to save them back to the library.
I wrote a PowerShell script that processes the permissions, and replaces write permissions with read permissions on demand.
Note: the solution implemented in this post is a one-way street. It’s not a read-only switch you can turn on or off as you can do for example in the case of a site collection (like Set-SPSite http://YourSharePointSite -LockState ReadOnly). You won’t be able to reproduce the original permissions once you run the script.
- $url = "http://YourSharePointSite/SubSite"
- $docLibName = "Documents"
- $web = Get-SPWeb $url
- $docLib = $web.Lists[$docLibName]
- $limitedAccess = $web.RoleDefinitions.GetByType([Microsoft.SharePoint.SPRoleType]::Guest)
- $readAccess = $web.RoleDefinitions.GetByType([Microsoft.SharePoint.SPRoleType]::Reader)
- $allowedAccess = $limitedAccess.Name, $readAccess.Name
- function Replace-Permissions($securable)
- {
- $securable.RoleAssignments | ? { $_.RoleDefinitionBindings | ? { $allowedAccess -notcontains $_.Name }} | % {
- $_.RoleDefinitionBindings.RemoveAll()
- $_.RoleDefinitionBindings.Add($readAccess)
- $_.Update()
- }
- }
- # if the doc. lib. inherits the permissions and if there is any role assignments that contains an access level beyond read only
- # we should break the inheritance first, to be able to change the permissions on the library level
- If (($doclib.HasUniqueRoleAssignments) -and (($docLib.RoleAssignments | ? { $_.RoleDefinitionBindings | ? { $allowedAccess -notcontains $_.Name }}).Count -gt 0))
- {
- $doclib.BreakRoleInheritance($true);
- }
- # set permissions on the doc. lib level
- Replace-Permissions($docLib)
- # set permissions on all folders having its own role assignment
- $doclib.Folders | ? { $_.HasUniqueRoleAssignments } | % { Replace-Permissions $_ }
- # set permissions on all documents having its own role assignment
- $doclib.Items | ? { $_.HasUniqueRoleAssignments } | % { Replace-Permissions $_ }
In the Replace-Permissions function I replace any permissions on a securable object other than Read or Limited Access (Guest) permissions with Read permissions.
Note: If you remove a Limited Access permission using the web UI, or the corresponding role assignment from code, you will loose the permissions set explicitly for that user anywhere in the hierarchy below that level. As described here, you can call the RemoveAll method on the RoleDefinitionBindings without such side effects. Then we can add the read permissions in place of the removed permissions.
I invoke the Replace-Permissions function once for the document library, then once for each folder and document having its own unique role assignments.