0

like it said in the title, I would like to add custom permissions on folders and subfolder in a document library on SharePoint online using PowerShell? I've tried this code but only works for the 1st level folder, not for subfolders.

Can anyone help me?

<#
The sample scripts are not supported under any Microsoft standard support 
program or service. The sample scripts are provided AS IS without warranty  
of any kind. Microsoft further disclaims all implied warranties including,  
without limitation, any implied warranties of merchantability or of fitness for 
a particular purpose. The entire risk arising out of the use or performance of  
the sample scripts and documentation remains with you. In no event shall 
Microsoft, its authors, or anyone else involved in the creation, production, or 
delivery of the scripts be liable for any damages whatsoever (including, 
without limitation, damages for loss of business profits, business interruption, 
loss of business information or other pecuniary loss) arising out of the use 
of or inability to use the sample scripts or documentation, even if Microsoft 
has been advised of the possibility of such damages.
#>


#requries -Version 2.0

<#
    .SYNOPSIS
        This script will Set Folder Permission in a library of SharePoint Online.
    .DESCRIPTION
        This script could be used to set a folder which could be only accessed by a security group. And this folder must have the same name of the security group. Otherwise, the script will create a new folder
    .PARAMETER  userName
        This parameter specified the username to login into SharePoint Online
    .PARAMETER  Password
        This parameter specifies the password to login into SharePoint Online 
    .PARAMETER  siteURL
        This parameter specifies the URL of the SharePoint site
    .PARAMETER  ListName
        This parameter specifies library/list name of the site
    .PARAMETER  FolderName
        This parameter specifies the parenet folder name/url. 
    .PARAMETER  PrincipalName
        This parameter specifies the security group or user who will be assigned the permission
    .PARAMETER  RoleType
        This parameter specifies the permission level to be assigned             
    .EXAMPLE
    SPOSetFolderPermissioninLibrary.ps1 –userName admin@tenant.onmicrosoft.com –siteURL https://tenant.sharepoint.com/sites/wroking -PrincipalName SecuirtyA -Roletype Editor
    The folder SecurityA in library ‘Demofile’ of site https://tenant.sharepoint.com/sites/working can only be edited by security group “SecuirtyA”
#>


Param
(
    [Parameter(Mandatory=$true)]
    [string] $userName,
    [Parameter(Mandatory=$True)]
    [Security.SecureString]$Password,
    [Parameter(Mandatory=$true)]
    [string] $siteURL,
    [Parameter(Mandatory=$true)]
    [string] $ListName,
    [Parameter(Mandatory=$false)]
    [string] $FolderName,
    [Parameter(Mandatory=$true)]
    [string] $PrincipalName,
    [Parameter(Mandatory=$true)][ValidateSet('None','Guest','Reader','Contributor','WebDesigner','Administrator','Editor')]
    [string] $RoleType


)

Begin
{
    $SPClientDirRegKey = Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\SharePoint Client Components\15.0" -PSProperty "Location" -ErrorAction:SilentlyContinue
    if ($SPClientDirRegKey -ne $null) 
    {
        $moduleFilePath1 = $SPClientDirRegKey.'Location' + 'ISAPI\Microsoft.SharePoint.Client.dll'
        $moduleFilePath2 = $SPClientDirRegKey.'Location' + 'ISAPI\Microsoft.SharePoint.Client.Runtime.dll'
        Import-Module $moduleFilePath1
        Import-Module $moduleFilePath2
    }
    else 
    {
        $errorMsg = "Please install SharePoint Server 2013 Client Components SDK"
        throw $errorMsg
        Exit
    }
    $credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($username, $Password)
    $context = New-Object Microsoft.SharePoint.Client.ClientContext($siteURL)
    $context.Credentials = $credentials
    $web = $context.Web
    $site = $context.Site
    $context.Load($web)
    $context.Load($site)
    try
    {
        $context.ExecuteQuery()
    }
    Catch
    {
        Write-Error $Error[0]
        Exit
    }
    Write-host "Conntect To Sharepoint Site $siteURL"
}

Process
{ 
    $web = $context.web
    $folderurl = $Web.ServerRelativeUrl + "/" + $ListName + "/" + $FolderName
    $folder = $web.GetFolderByServerRelativeUrl($folderurl)
    $context.Load($folder)

    $folderExist = $false

    try
    {
        $Context.ExecuteQuery();

        if ($folder.Path)
        {
            $folderExist = $true;
        }
    }
    catch { }

    if(!$folderExist)
    {
        $parentFolderUrl = $folderUrl.Replace('/' + $folderName,'')

        $newItemInfo = new-object Microsoft.SharePoint.Client.ListItemCreationInformation
        $newItemInfo.UnderlyingObjectType = [Microsoft.SharePoint.Client.FileSystemObjectType]::Folder
        $newItemInfo.LeafName = $folderName
        $newItemInfo.FolderUrl = $parentFolderUrl

        $listurl = $context.web.ServerRelativeUrl + "/" + "demofile"

        write-host $listurl

        $method = [Microsoft.SharePoint.Client.ClientContext].GetMethod("Load")
        $loadMethod = $method.MakeGenericMethod([Microsoft.SharePoint.Client.List])

        $parameter = [System.Linq.Expressions.Expression]::Parameter(([Microsoft.SharePoint.Client.List]), "list")
        $expression = [System.Linq.Expressions.Expression]::Lambda([System.Linq.Expressions.Expression]::Convert(
                        [System.Linq.Expressions.Expression]::PropertyOrField(
                            [System.Linq.Expressions.Expression]::PropertyOrField($parameter, "RootFolder"),
                            "ServerRelativeUrl"
                            ),
                        [System.Object]),
                    $($parameter)
                    )
        $expressionArray = [System.Array]::CreateInstance($expression.GetType(), 1)
        $expressionArray.SetValue($expression, 0)

        $lists = $web.Lists

        $Context.Load($lists)
        $Context.ExecuteQuery()

        $list = $null

        foreach ($listfinder in $lists) 
        {
            $loadMethod.Invoke($Context, @($listfinder, $expressionArray))
            $Context.ExecuteQuery()

            if ($listfinder.RootFolder.ServerRelativeUrl -eq $listUrl)
            {
                $list = $listfinder
            }
        }

        $newListItem = $list.AddItem($newItemInfo)

        $newListItem.Update()
        $context.load($list)
        $context.ExecuteQuery()
    }


    $roleTypeObject = [Microsoft.SharePoint.Client.RoleType]$roleType
    $roledefs = $web.RoleDefinitions
    $context.Load($roledefs)
    $Context.ExecuteQuery()
    $role = $roleDefs | where {$_.RoleTypeKind -eq $roleTypeObject}

    $principal = $context.Web.EnsureUser($PrincipalName)

    $Context.Load($principal)
    Try
    {
        $Context.ExecuteQuery()
    }
    Catch
    {
        Write-Error $Error[0]
        Exit
    }

    $list = $web.Lists.GetByTitle($listname)

    $camlQuery = new-object Microsoft.SharePoint.Client.CamlQuery
    $camlQuery.ViewXml = "<View><Query><Where><Eq><FieldRef Name='FileLeafRef' /><Value Type='Text'>$FolderName</Value></Eq></Where></Query></View>"

    $listItems = $list.GetItems($camlQuery)

    $Context.Load($listItems)
    $Context.ExecuteQuery()

    $listitem = $listItems[0]

    $method = [Microsoft.Sharepoint.Client.ClientContext].GetMethod("Load")
    $loadMethod = $method.MakeGenericMethod([Microsoft.Sharepoint.Client.ListItem])

    $parameter = [System.Linq.Expressions.Expression]::Parameter(([Microsoft.SharePoint.Client.ListItem]), "x")
    $expression = [System.Linq.Expressions.Expression]::Lambda([System.Linq.Expressions.Expression]::Convert(
                    [System.Linq.Expressions.Expression]::Property(
                    $parameter, ([Microsoft.SharePoint.Client.ListItem]).GetProperty("HasUniqueRoleAssignments")), 
                    ([System.Object])), $($parameter))
    $expressionArray = [System.Array]::CreateInstance($expression.GetType(), 1)
    $expressionArray.SetValue($expression, 0)

    $loadMethod.Invoke( $Context, @( $listItem, $expressionArray ) )

    $Context.ExecuteQuery()
    if (-not $listItem.HasUniqueRoleAssignments)
    {
        $listItem.BreakRoleInheritance($false, $true)
    }

    $rdb = New-Object Microsoft.SharePoint.Client.RoleDefinitionBindingCollection($Context)

    $rdb.Add($role)

    $ra = $listItem.RoleAssignments.Add($principal, $rdb)

    $Context.ExecuteQuery()
}

Mr @Rajiv

I have now this script, it works for users but i changed it for groups but i have an error, any help ?

Here is the error: Impossible d’appeler une méthode dans une expression Null. in line 86

### Get the user credentials
$credential = Get-Credential
$username = $credential.UserName
$password = $credential.GetNetworkCredential().Password
$securePassword = ConvertTo-SecureString $password -AsPlainText -Force


### Input Parameters
$url = 'https://xxx.sharepoint.com/sites/Demo-
test/Interne/'
$ListName = 'Infrastructure'
$GroupName = 'TestPemissions'
$RootFolder = 'TestPermissions'

### References
# Specified the paths where the dll's are located.
Add-Type -Path 'c:\Program Files\Common Files\microsoft shared\Web Server 
Extensions\15\ISAPI\Microsoft.SharePoint.Client.dll'
Add-Type -Path 'c:\Program Files\Common Files\microsoft shared\Web Server 
Extensions\15\ISAPI\Microsoft.SharePoint.Client.Runtime.dll'


### AddPermission Function
function AddPermission()
{

# Connect to SharePoint Online and get ClientContext object.
$clientContext = New-Object Microsoft.SharePoint.Client.ClientContext($url)
$credentials = New-Object 
Microsoft.SharePoint.Client.SharePointOnlineCredentials($username, 
$securePassword)
$clientContext.Credentials = $credentials



# Get the SharePoint web
$web = $clientContext.Web
$clientcontext.Load($web)
$groups = $web.SiteGroups
$clientcontext.Load($groups)
$clientcontext.ExecuteQuery()  
$folderurl = $web.ServerRelativeUrl + "/" + $ListName + "/" + $RootFolder
Write-Host "group : " $group
Write-Host "relative url : " $web.ServerRelativeUrl
Write-Host "folderurl : " $folderurl
$root = $web.GetFolderByServerRelativeUrl($folderurl)
$clientcontext.Load($root.Folders)
$clientcontext.ExecuteQuery()
Write-Host "folders : " $root

$group=$GroupName

Function GetRole
    {
        [CmdletBinding()]
        param
        (
            [Parameter(Mandatory = $true, Position = 1)]
            [Microsoft.SharePoint.Client.RoleType]$rType
        )

        $web = $clientContext.Web
        if ($web -ne $null)
        {
            $roleDefs = $web.RoleDefinitions
            $clientContext.Load($roleDefs)
            $clientContext.ExecuteQuery()
            $roleDef = $roleDefs | Where-Object { $_.RoleTypeKind -eq $rType  }
           return $roleDef
       }
       return $null
   }

foreach($folder in $root.Folders){

       #Break inheritance and remove existing permissions
       $folder.ListItemAllFields.BreakRoleInheritance($false, $true)

       #Get the role required and load it 
       write-host "folder : " $folder
       $roleType = Read-Host "None, Guest, Reader, Contributor, WebDesigner, 
Administrator, Editor"
       $roleTypeObject = [Microsoft.SharePoint.Client.RoleType]$roleType
       $roleObj = GetRole $roleTypeObject

       $gpRDBC = New-Object 
Microsoft.SharePoint.Client.RoleDefinitionBindingCollection($clientContext)
       $gpRDBC.Add($roleObj)

       $gpRoleAssign = $folder.RoleAssignement

line 86           $RoleAssign = $gpRoleAssign.Add($group,$gpRDBC)
       $clientcontext.ExecuteQuery()
              Write-Host $gpRDBC.Description

              # Display the folder name and URL
              Write-Host -ForegroundColor Green 'Folder Name: ' $folder.Name 
' URL: '$folder1.ServerRelativeUrl;
       }

}
#Execute the function
AddPermission
0

2 Answers 2

0

Use (edit as per your requirement ) the following powershell script:

Add-PSSnapin Microsoft.SharePoint.PowerShell -erroraction SilentlyContinue
 $site = new-object Microsoft.SharePoint.SPSite("http://yourserver/")
 $web = $site.OpenWeb()
 function GrantGroupPermission($groupName)
 {
  [Microsoft.SharePoint.SPGroupCollection]$spgroups = $web.SiteGroups
  [Microsoft.SharePoint.SPGroup]$spgroup = $spgroups[$groupName]
  $sproleass=new-object Microsoft.SharePoint.SPRoleAssignment([Microsoft.SharePoint.SPPrincipal]$spgroup)
  $folder.BreakRoleInheritance("true")
  $sproleass.RoleDefinitionBindings.Add($web.RoleDefinitions["Contribute"])
  $folder.RoleAssignments.Add($sproleass);
  Write-Host "Permission given to the group ", $groupName
 }
 function GrantUserpermission($userName)
 {
  [Microsoft.SharePoint.SPUserCollection]$spusers=[Microsoft.SharePoint.SPUserCollection]$web.SiteUsers
  [Microsoft.SharePoint.SPUser]$spuser=$spusers[$userName]
  $sproleass=new-object Microsoft.SharePoint.SPRoleAssignment([Microsoft.SharePoint.SPPrincipal]$spuser)
  $folder.BreakRoleInheritance("true")
  $sproleass.RoleDefinitionBindings.Add($web.RoleDefinitions["Contribute"])
  $folder.RoleAssignments.Add($sproleass);
  Write-Host "Permission given to  user ", $userName
 }
 $doclib=[Microsoft.SharePoint.SPDocumentLibrary]$web.Lists["Shared Documents"]
 $foldercoll=$doclib.Folders;
 foreach($folder in $foldercoll)
 {
  Write-Host $folder.Name
  if($folder.Name.Equals("office"))
  {
   GrantUserPermission("rajiv")
  }

 }
 Write-Host "Done!"
 $web.Close()
 $site.Dispose()
5
  • Thanks for the answer but i get this when i execute: new-object : Le type [Microsoft.SharePoint.Client.ClientContext] est introuvable : vérifiez que l’assembly dans lequel il se trouve est chargé. Au caractère Ligne:3 : 9.... Its like Add-PSSnapin Microsoft.SharePoint.PowerShell doesnt work
    – Moda Niang
    May 31, 2017 at 9:47
  • What I can understand from the french message is : {Microsoft.SharePoint.Client.ClientContext] can not be found: verify that the assembly in which it is located is loaded. It seems you have not added the assembly in your solution.Try to search and add the desired dll file for {Microsoft.SharePoint.Client.ClientContext]. Righ click Solution > Add assebly > Locate "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\ISAPI" > Add Microsoft.SharePoint.Client.Runtime.dll and Microsoft.SharePoint.Client.dll
    – Rajiv
    May 31, 2017 at 10:05
  • Ok thanks its ok for the client dll, now i have another error "[Microsoft.SharePoint.SPSite] est introuvable : vérifiez que l’assembly dans lequel il se trouve est chargé." Can we have add-pssnapin for SP online ?
    – Moda Niang
    Jun 1, 2017 at 7:58
  • The code that you were using earlier was of CSOM which requires client.dll, however, the one that I shared was of SSOM and not specific to the SharePoint Online. If you want to run the powershell script for SharePoint Online, then you need to edit it with the new commands of SPOnline. Please refer the link below for the command sets of SharePoint Onlinel: technet.microsoft.com/en-us/library/fp161388.aspx I will meanwhile try to find out the exact script for your problem, but I think if you try to replace the commands in above script with the commands of SPOnline it should work.
    – Rajiv
    Jun 1, 2017 at 8:17
  • That's good! Please kindly post your solution here which will help others in future. Regards!
    – Rajiv
    Jun 9, 2017 at 3:19
0

Here is the solution, but you need to adapt it. ;)

<#
Ce sript permet d'ajouter les droits à un groupe sur un dossier.
#>


$Username = "email address"
$Site = "https://yousite.sharepoint.com/sites/x/"
$Password = Read-Host -Prompt "Entrez votre mot de passe" -AsSecureString

$ListName = 'Your library'
$RootFolder = 'Your folder'


#Add references to SharePoint client assemblies and authenticate to Office 365 site
Add-Type -Path 'c:\Program Files\Common Files\microsoft shared\Web Server Extensions\15\ISAPI\Microsoft.SharePoint.Client.dll'
Add-Type -Path 'c:\Program Files\Common Files\microsoft shared\Web Server Extensions\15\ISAPI\Microsoft.SharePoint.Client.Runtime.dll'

# Connect to SharePoint Online and get Context object.
$Context = New-Object Microsoft.SharePoint.Client.ClientContext($Site)
$Creds = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($Username,$Password)
$Context.Credentials = $Creds
$Web = $Context.Web
$Context.Load($web)

#Retrieve Groups
$group = $Context.Web.SiteGroups.getByName("Group name");
$Context.Load($group)
$Context.ExecuteQuery()

#Retrieve Folder
$folderurl = $web.ServerRelativeUrl + "/" + $ListName + "/" + $RootFolder
$root = $web.GetFolderByServerRelativeUrl($folderurl)
$Context.Load($root.Folders)
$Context.ExecuteQuery()

Function GetRole
    {
        [CmdletBinding()]
        param
        (
            [Parameter(Mandatory = $true, Position = 1)]
            [Microsoft.SharePoint.Client.RoleType]$rType
        )

        $web = $Context.Web
        if ($web -ne $null)
        {
            $roleDefs = $web.RoleDefinitions
            $Context.Load($roleDefs)
            $Context.ExecuteQuery()
            $roleDef = $roleDefs | Where-Object { $_.RoleTypeKind -eq $rType }
            return $roleDef
        }
        return $null
    }


foreach($folder in $root.Folders){

    #Break inheritance and remove existing permissions
    $folder.ListItemAllFields.BreakRoleInheritance($false, $true)

    #Get the role required and load it 
    $roleType = "Editor"
    write-host  -ForegroundColor Green "Ajout des droits " $roleType "sur le dossier " $folder.Name "Pour le groupe " $group.LoginName
    $roleTypeObject = [Microsoft.SharePoint.Client.RoleType]$roleType
    $roleObj = GetRole $roleTypeObject

    #Bind Permission Level to Group
    $RoleDefBind = New-Object Microsoft.SharePoint.Client.RoleDefinitionBindingCollection($Context)
    $RoleDefBind.Add($roleObj)
    $Assignments = $Context.Web.RoleAssignments

    #Apply the permission roles to the list.
       $Context.Load($folder.ListItemAllFields.RoleAssignments.Add($group, $RoleDefBind))
       $folder.Update()
       $Context.ExecuteQuery()

} 

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.