Forum Discussion

Fromelard's avatar
Fromelard
Steel Contributor
Oct 14, 2020

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

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 

 

 

 

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. 

 

 

 

 

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()
    }
}

 

 

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

Fabrice Romelard

  • bobito's avatar
    bobito
    Copper Contributor
    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/.
    • sir_action's avatar
      sir_action
      Copper Contributor

      bobito 
      Two notes:

      Running the script from Visual Studio code does not work.
      I managed to get to the reset permissions phase: the content of the $foldertoscope is case sensitive. I recommend to check (print) the value of ($allItems[$j]["FileRef"] and use that to set the value of $foldertoscope

  • DeclanTyndall's avatar
    DeclanTyndall
    Copper Contributor
    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"
    }
  • MetsCaniac's avatar
    MetsCaniac
    Copper Contributor
    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?
    • Osmundo's avatar
      Osmundo
      Copper Contributor
      I have the same issue with this script, it stops at item collection and never runs the actual resetting. Anybody found the solution?
      • AdamDodds's avatar
        AdamDodds
        Copper Contributor

        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/"

  • roymaalouf's avatar
    roymaalouf
    Copper Contributor
    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:
    • NickV2114's avatar
      NickV2114
      Copper Contributor
      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?
  • Fromelard 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. 

  • aprieto's avatar
    aprieto
    Copper Contributor
    This is working wonders for me, thanks, I just wonder if you are able to look at just folders within a Document Library?

    Thanks
    • CFox-Merit's avatar
      CFox-Merit
      Copper Contributor

      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.

      • aprieto's avatar
        aprieto
        Copper Contributor
        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
  • DrehUK's avatar
    DrehUK
    Copper Contributor

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

Resources