SharePoint - How to Reset Inheritance Permission set into an SP DocLib folder or file

Steel Contributor

When we are importing File Server content into SharePoint using dedicated tools for, we can import permission set configured at the sub levels (subfolders or documents). That import can create some issues due to incorrect configuration in place on original File Server.

 

But how can we check one user complaining to not see or access the content as it was into the File Server ?

That need to be reviewed at any SharePoint Content Level with Permission Management with "Administrator Permission" with the link "Manage Access".

You have to select the link (at the bottom) "Advanced" to have the exact permission set configured at this level 

DocLibFolderPermission-01.png

 

DocLibFolderPermission-02.png

 

DocLibFolderPermission-03.png

 

Based on that situation, you can decide what to apply at this folder or file level. You can:

  • add a colleague or a group with appropriate permission (Read, Write or full control)
  • Remove the specific permission of that level clicking on "Delete unique permissions"

 

But this config could concern many other sublevels and wait the user complains is probably not the best option.

How to track folders or files with unique permissions ?

You can do that using the Document Library Permission Settings from:

  • Library Settings > "Permissions for this Document Library"

You will have the permission configuration in place at this root Document library level.

But the first line will explain (if that is the case into your document library) the status of sublevel:

  • Some items of this list may have unique permissions which are not controlled from this page.  Show these items.

When you are clicking on that link it will show you a part of customized levels.

You can change the permission set for each of those level clicking on "Manage Permissions" to have the same details we look in the first part of this message. 

DocLibFolderPermission-04.png

 

DocLibFolderPermission-05.png

 

DocLibFolderPermission-06.png

 

DocLibFolderPermission-07.png

 

Now as you can imagine with a document library could contains thousands of folders, this manual action is really huge.

How reset all customized permissions configured at sublevel ?

That is the best option you can select as site admin, using PowerShell and an interesting PS Module named:

This following script will help IT Team to reconfigure all content customized into the document library and cancel this and reconfigure permission inheritance instead.

 

#install-module SharePointPnPPowerShellOnline -Force #to install that module the first time only
Write-Host " ---------------------------------------------- "
Import-Module SharePointPnPPowerShellOnline
Write-Host " ---------------------------------------------- "

#Config Variables
$SiteURL = "https://yourtenant.sharepoint.com/sites/YourSiteCollection/"
$ListTitle = "Document Library Name"

$foldertoscope = "/sites/YourSiteCollection/YourDocumentLibrary/"

#Connect to PnP Online
Connect-PnPOnline -Url $SiteURL -UseWebLogin

$ctx = Get-PnPContext

  $ctx.Load($ctx.Web.Lists)
  $ctx.Load($ctx.Web)
  $ctx.Load($ctx.Web.Webs)
  $ctx.ExecuteQuery()
  $ll=$ctx.Web.Lists.GetByTitle($ListTitle)
  $ctx.Load($ll)
  $ctx.ExecuteQuery()

  ## View XML
$qCommand = @"
<View Scope="RecursiveAll">
    <Query>
        <OrderBy><FieldRef Name='ID' Ascending='TRUE'/></OrderBy>
    </Query>
    <RowLimit Paged="TRUE">5000</RowLimit>
</View>
"@
## Page Position
$position = $null
 
## All Items
$allItems = @()
Do{
    $camlQuery = New-Object Microsoft.SharePoint.Client.CamlQuery
    $camlQuery.ListItemCollectionPosition = $position
    $camlQuery.ViewXml = $qCommand
 ## Executing the query
    $currentCollection = $ll.GetItems($camlQuery)
    $ctx.Load($currentCollection)
    $ctx.ExecuteQuery()
 
 ## Getting the position of the previous page
    $position = $currentCollection.ListItemCollectionPosition
 
 # Adding current collection to the allItems collection
    $allItems += $currentCollection

     Write-Host "Collecting items. Current number of items: " $allItems.Count
}
while($position -ne $null)

Write-Host "Total number of items: " $allItems.Count

for($j=0;$j -lt $allItems.Count ;$j++)
{
    if($allItems[$j]["FileRef"].StartsWith($foldertoscope))
    {
        Write-Host "Resetting permissions for " $allItems[$j]["Title"] ".." $allItems[$j]["FileRef"]
        $allItems[$j].ResetRoleInheritance()
        $ctx.ExecuteQuery()
    }
}

 

DocLibFolderPermission-08.png

 

Now you can adapt the permissions as much as you need to

Fabrice Romelard

17 Replies

@Fabrice RomelardYou sir are a genetleman and a scholar. Saved me a lot of time and effort. 10/10 works a treat.

This is working wonders for me, thanks, I just wonder if you are able to look at just folders within a Document Library?

Thanks

@aprietoYes, you can apply this just to a subfolder within a library. I found this site looking to do just that. You just need to set the "$foldertoscope =" parameter to the relative URL of the folder. The final loop of the script compares the path of every object to that string, and if it starts with that string, it resets the permissions.

@CFox-Merit

Thanks for that Ive done that, but it still seems to be counting the whole Library, not sure what im doing wrong, im using "/sites/sitename/library/folder/ the one I'm testing on only had around 50 files and folders and this counts 5000 starting but goes up so cancel it, only because last time i ran at library it stated error because of the amount of requests

@Fabrice Romelard Thanks.  I am trying to reset permissions for a specific folder within a library.  I have gotten the script to run, but it just returns the amount of items it found in the whole document library not just that specific folder.  It also does not go into the next step of resetting the permissions. Any advice would be much appreciated. 

I am also experiencing the same thing as well as the script never gets to the part of resetting any of the permissions. It runs it tells me the total number of items in the entire library and then does nothing more than that. I have tried changing my foldertoscope variable but nothing I seem to do ever gets it to a point that it tries to reset the permissions. I am trying this on a test site for right now before actually doing it on our live document library.
I run the script as below:
install-module SharePointPnPPowerShellOnline -Force #to install that module the first time only
#install-module SharePointPnPPowerShellOnline -Force #to install that module the first time only
Write-Host " ---------------------------------------------- "
Import-Module SharePointPnPPowerShellOnline
Write-Host " ---------------------------------------------- "

#Config Variables
$SiteURL = " https://medair.sharepoint.com/sites/GlobalITS/"
$ListTitle = "Documents"

$foldertoscope = "/sites/GlobalITS/Shared%20Documents/"

#Connect to PnP Online
Connect-PnPOnline -Url $SiteURL -UseWebLogin

$ctx = Get-PnPContext

$ctx.Load($ctx.Web.Lists)
$ctx.Load($ctx.Web)
$ctx.Load($ctx.Web.Webs)
$ctx.ExecuteQuery()
$ll=$ctx.Web.Lists.GetByTitle($ListTitle)
$ctx.Load($ll)
$ctx.ExecuteQuery()

## View XML
$qCommand = @"
<View Scope="RecursiveAll">
<Query>
<OrderBy><FieldRef Name='ID' Ascending='TRUE'/></OrderBy>
</Query>
<RowLimit Paged="TRUE">5000</RowLimit>
</View>
"@
## Page Position
$position = $null

## All Items
$allItems = @()
Do{
$camlQuery = New-Object Microsoft.SharePoint.Client.CamlQuery
$camlQuery.ListItemCollectionPosition = $position
$camlQuery.ViewXml = $qCommand
## Executing the query
$currentCollection = $ll.GetItems($camlQuery)
$ctx.Load($currentCollection)
$ctx.ExecuteQuery()

## Getting the position of the previous page
$position = $currentCollection.ListItemCollectionPosition

# Adding current collection to the allItems collection
$allItems += $currentCollection

Write-Host "Collecting items. Current number of items: " $allItems.Count
}
while($position -ne $null)

Write-Host "Total number of items: " $allItems.Count

for($j=0;$j -lt $allItems.Count ;$j++)
{
if($allItems[$j]["FileRef"].StartsWith($foldertoscope))
{
Write-Host "Resetting permissions for " $allItems[$j]["Title"] ".." $allItems[$j]["FileRef"]
$allItems[$j].ResetRoleInheritance()
$ctx.ExecuteQuery()
}
}

----------------------------------------------
WARNING: The names of some imported commands from the module 'SharePointPnPPowerShellOnline' include unapproved verbs t
hat might make them less discoverable. To find the commands with unapproved verbs, run the Import-Module command again
with the Verbose parameter. For a list of approved verbs, type Get-Verb.
----------------------------------------------
WARNING:
You are running the legacy version of PnP PowerShell.

This version will be archived soon which means that while staying available, no updates or fixes will be released.
Consider installing the newer prereleased cross-platform version of PnP PowerShell.
This version has numerous improvements and many more cmdlets available.
To install the new version:

Uninstall-Module -Name SharePointPnPPowerShellOnline -AllVersions -Force
Install-Module -Name PnP.PowerShell

Read more about the new cross-platform version of PnP PowerShell at

https://pnp.github.io/powershell

To hide this message set the environment variable PNPLEGACYMESSAGE to "false"
In PowerShell add $env:PNPLEGACYMESSAGE='false' to your profile. Alternatively use 'Connect-PnPOnline -Url [yoururl] -W
arningAction Ignore'
Cannot convert argument "query", with value: "Microsoft.SharePoint.Client.CamlQuery", for "GetItems" to type
"Microsoft.SharePoint.Client.CamlQuery": "Cannot convert the "Microsoft.SharePoint.Client.CamlQuery" value of type
"Microsoft.SharePoint.Client.CamlQuery" to type "Microsoft.SharePoint.Client.CamlQuery"."
At line:45 char:5
+ $currentCollection = $ll.GetItems($camlQuery)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodException
+ FullyQualifiedErrorId : MethodArgumentConversionInvalidCastArgument

Cannot find an overload for "Load" and the argument count: "1".
At line:46 char:5
+ $ctx.Load($currentCollection)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodException
+ FullyQualifiedErrorId : MethodCountCouldNotFindBest

Collecting items. Current number of items: 1
Total number of items: 1
Cannot index into a null array.
At line:63 char:8
+ if($allItems[$j]["FileRef"].StartsWith($foldertoscope))
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : NullArray

I got the following result:
Exception calling "ExecuteQuery" with "0" argument(s): "The remote server returned an error: (400) Bad Request."
At line:66 char:9
+ $ctx.ExecuteQuery()
+ ~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : WebException

We get this error - is this Microsoft Throttling our connection?
I am having difficulty getting the script to finish. I need it to run on the this site which is the main team site created in a new M365 tenant.
https://<domain>.sharepoint.com/Shared%20Documents
however...when it runs, the collecting occurs but the resetting does not. I am guessing I do not have a variable correct. Do you have a suggestion?
I have the same issue with this script, it stops at item collection and never runs the actual resetting. Anybody found the solution?

Hello I have seen a couple comments that it is not resetting but only counting or doing "item collection"

I am not sure if it was just a formatting issue but I have gotten the current script to work. I have set the variables to a default non-usable value. Please edit them to fit your environment

#install-module SharePointPnPPowerShellOnline -Force #to install that module the first time only
Write-Host " ---------------------------------------------- "
Import-Module PnP.PowerShell
Write-Host " ---------------------------------------------- "

#Config Variables
$SiteURL = "https://domain.sharepoint.com/sites/SiteName"
$ListTitle = "Documents"

#For some libraries it will be Shared%20Documents. Be sure to retain the slash before /sites/SiteName/Documents
$foldertoscope = "/sites/SiteName/Documents"

#Connect to PnP Online
Connect-PnPOnline -Url $SiteURL -Interactive

$ctx = Get-PnPContext

$ctx.Load($ctx.Web.Lists)
$ctx.Load($ctx.Web)
$ctx.Load($ctx.Web.Webs)
$ctx.ExecuteQuery()
$ll=$ctx.Web.Lists.GetByTitle($ListTitle)
$ctx.Load($ll)
$ctx.ExecuteQuery()

## View XML
$qCommand = @"
<View Scope="RecursiveAll">
<Query>
<OrderBy><FieldRef Name='ID' Ascending='TRUE'/></OrderBy>
</Query>
<RowLimit Paged="TRUE">5000</RowLimit>
</View>
"@
## Page Position
$position = $null

## All Items
$allItems = @()
Do{
$camlQuery = New-Object Microsoft.SharePoint.Client.CamlQuery
$camlQuery.ListItemCollectionPosition = $position
$camlQuery.ViewXml = $qCommand
## Executing the query
$currentCollection = $ll.GetItems($camlQuery)
$ctx.Load($currentCollection)
$ctx.ExecuteQuery()

## Getting the position of the previous page
$position = $currentCollection.ListItemCollectionPosition

# Adding current collection to the allItems collection
$allItems += $currentCollection

Write-Host "Collecting items. Current number of items: " $allItems.Count
}
while($position -ne $null)

Write-Host "Total number of items: " $allItems.Count
for($j=0;$j -lt $allItems.Count ;$j++)
{
if($allItems[$j]["FileRef"].StartsWith($foldertoscope))
{
Write-Host "Resetting permissions for " $allItems[$j]["Title"] ".." $allItems[$j]["FileRef"]
$allItems[$j].ResetRoleInheritance()
$ctx.ExecuteQuery()
}
}

@Fabrice Romelard 

 

Thank you for this! This script was very helpful and using it saved myself tons of time!

@Osmundo 

 

I know you asked well over 6 months ago but if anyone else faces the same problem, here is how I fixed it

 

For a root SharePoint site it should be set out like this:

 

#Config Variables
$SiteURL = "https://company.sharepoint.com/"
$ListTitle = "Documents"

$foldertoscope = "/Shared Documents/"

Can you explain what exactly the "IF" portion of the script is doing, similarly to others i was having trouble getting it to run past the discovery phase, i added the below else statement and it would spit out "Failed" the for each item it discovered so the for Loop was working fine. I commented out the "IF" statement and it worked so i think, at least for me, thats where the issue is.

if($allItems[$j]["FileRef"].StartsWith($foldertoscope))
{
Write-Host "Resetting permissions for " $allItems[$j]["Title"] ".." $allItems[$j]["FileRef"]
$allItems[$j].ResetRoleInheritance()
$ctx.ExecuteQuery()
}
else
{
write-host "Failed"
}
If anyone has the issue where it returns the number of items found but doesn't reset the permissions, be sure you don't have any %20 in place of spaces. E.g. /sites/site%20name/shared%20documents/ should be entered as /sites/site name/shared documents/.