The question appears when a site owner is playing withe the permission set and remove his group from the object (list or site). The same question is existing when you are loading the content from an On Premise SharePoint farm (in which the site collection admin could be given to the site owner) to SharePoint Online, and you need to reset the Permission set for that Site Owner group.
This PowerShell script is using CSOM Object to loop into all the site collection (in all the subsites) and apply the Full Control permission into any list and Subsite (it's not going deeper in the List content level).
In the same script, the Site Access request is configured with the given email address to delegate the permission management to the defined Site Onwer.
[string]$username = "LoginAccount@tenant.onmicrosoft.com"
[string]$PwdTXTPath = "C:\\SECUREDPWD\ExportedPWD-$($username).txt"
[string]$SPOSiteCollectionURLToSet = “https://tenant.sharepoint.com/sites/MySiteCollection”
[string]$RootSiteOwnerGroupToSet = "MySiteCollection Owners"
[string]$SiteOwnerEmailAdress = "SiteOnwerEmail@mycompany.com"
[boolean]$ChangeRequestAccessEmail = $false
[string]$RoleTypeToApply = "Administrator"
function Load-DLLandAssemblies
{
[string]$defaultDLLPath = ""
# Load assemblies to PowerShell session
$defaultDLLPath = "C:\Program Files\SharePoint Online Management Shell\Microsoft.Online.SharePoint.PowerShell\Microsoft.SharePoint.Client.dll"
[System.Reflection.Assembly]::LoadFile($defaultDLLPath)
$defaultDLLPath = "C:\Program Files\SharePoint Online Management Shell\Microsoft.Online.SharePoint.PowerShell\Microsoft.SharePoint.Client.Runtime.dll"
[System.Reflection.Assembly]::LoadFile($defaultDLLPath)
$defaultDLLPath = "C:\Program Files\SharePoint Online Management Shell\Microsoft.Online.SharePoint.PowerShell\Microsoft.Online.SharePoint.Client.Tenant.dll"
[System.Reflection.Assembly]::LoadFile($defaultDLLPath)
}
Function Invoke-LoadMethod() {
param(
[Microsoft.SharePoint.Client.ClientObject]$Object = $(throw "Please provide a Client Object"),
[string]$PropertyName
)
$ctx = $Object.Context
$load = [Microsoft.SharePoint.Client.ClientContext].GetMethod("Load")
$type = $Object.GetType()
$clientLoad = $load.MakeGenericMethod($type)
$Parameter = [System.Linq.Expressions.Expression]::Parameter(($type), $type.Name)
$Expression = [System.Linq.Expressions.Expression]::Lambda(
[System.Linq.Expressions.Expression]::Convert(
[System.Linq.Expressions.Expression]::PropertyOrField($Parameter,$PropertyName),
[System.Object]
),
$($Parameter)
)
$ExpressionArray = [System.Array]::CreateInstance($Expression.GetType(), 1)
$ExpressionArray.SetValue($Expression, 0)
$clientLoad.Invoke($ctx,@($Object,$ExpressionArray))
}
Function Add-Group-As-FullPermission-InSPWeb()
{
Param(
[Microsoft.SharePoint.Client.ClientContext]$Context,
[string]$SPGroupName,
[Microsoft.SharePoint.Client.Web]$SPWeb,
[string]$RoleType
)
Write-Host " ---------------------------------------------------------"
# get group/principal
$Mygroups = $SPWeb.SiteGroups
$MyRootWeb = $Context.Site.RootWeb
$context.Load($MyRootWeb)
$Context.Load($Mygroups)
$Context.ExecuteQuery()
<#
foreach($MyTempGroup in $Mygroups)
{ Write-Host " --->>> Group In Group List: ", $MyTempGroup.Title }
#>
$Mygroup = $Mygroups | where {$_.Title -eq $SPGroupName}
#$MyRoleType = [Microsoft.SharePoint.Client.RoleType]$Roletype
$roleDefs = $SPWeb.RoleDefinitions
$Context.Load($roleDefs)
$Context.ExecuteQuery()
$roleDef = $roleDefs | where {$_.RoleTypeKind -eq $Roletype}
Write-Host " --- Role Definition: ", $roleDef.Name
Write-Host " --- Group Name: ", $Mygroup.Title, " - Original Name:", $SPGroupName
try{
$collRdb = new-object Microsoft.SharePoint.Client.RoleDefinitionBindingCollection($Context)
$collRdb.Add($roleDef)
$collRoleAssign = $SPWeb.RoleAssignments
$rollAssign = $collRoleAssign.Add($Mygroup, $collRdb)
$Context.ExecuteQuery()
Write-Host " >>>>> Permissions assigned successfully." -ForegroundColor Green
}
catch{
write-host " !!!!!!! info: $($_.Exception.Message)" -foregroundcolor red
}
Write-Host " ---------------------------------------------------------"
}
Function Add-Group-As-FullPermission-InSPList()
{
Param(
[Microsoft.SharePoint.Client.ClientContext]$Context,
[string]$SPGroupName,
[Microsoft.SharePoint.Client.Web]$SPWeb,
[Microsoft.SharePoint.Client.List]$SPList,
[string]$RoleType
)
Write-Host " ---------------------------------------------------------"
# get group/principal
$Mygroups = $SPWeb.SiteGroups
$MyRootWeb = $Context.Site.RootWeb
$context.Load($MyRootWeb)
$Context.Load($Mygroups)
$context.Load($SPList)
$Context.ExecuteQuery()
<#
foreach($MyTempGroup in $Mygroups)
{ Write-Host " --->>> Group In Group List: ", $MyTempGroup.Title }
#>
$Mygroup = $Mygroups | where {$_.Title -eq $SPGroupName}
#$MyRoleType = [Microsoft.SharePoint.Client.RoleType]$Roletype
# get role definition
$roleDefs = $SPWeb.RoleDefinitions
$Context.Load($roleDefs)
$Context.ExecuteQuery()
$roleDef = $roleDefs | where {$_.RoleTypeKind -eq $Roletype}
Write-Host " --- Role Definition: ", $roleDef.Name
Write-Host " --- Group Name: ", $Mygroup.Title, " - Original Name:", $SPGroupName
try{
$collRdb = new-object Microsoft.SharePoint.Client.RoleDefinitionBindingCollection($Context)
$collRdb.Add($roleDef)
$collRoleAssign = $SPList.RoleAssignments
$rollAssign = $collRoleAssign.Add($Mygroup, $collRdb)
$Context.ExecuteQuery()
Write-Host " >>>>> Permissions assigned successfully." -ForegroundColor Green
}
catch{
write-host " !!!!!!! info: $($_.Exception.Message)" -foregroundcolor red
}
Write-Host " ---------------------------------------------------------"
}
function Check-Permission-InLists
{
Param(
[Microsoft.SharePoint.Client.ClientContext]$Context,
[Microsoft.SharePoint.Client.Web]$SPWeb
)
$Mylists = $SPWeb.Lists;
$Context.Load($Mylists)
#you can use one execute per multiple loads
$Context.ExecuteQuery();
Write-host " ---- CHECK IN LISTS --- "
foreach($myList in $MyLists)
{
Write-host " ==== List Name:", $mylist.Title
if($mylist.hidden -eq $false)
{
Write-host " ====> List Name not hidden:", $mylist.Title -ForegroundColor Yellow
Invoke-LoadMethod -Object $myList -PropertyName "HasUniqueRoleAssignments"
$context.ExecuteQuery()
if($myList.HasUniqueRoleAssignments)
{
Write-Host " -->> List in the SPWeb:", $myList.Title -ForegroundColor Yellow
Write-Host " -->> Has Unique Permissions:", $myList.HasUniqueRoleAssignments
Add-Group-As-FullPermission-InSPList -Context $Context -SPGroupName $RootSiteOwnerGroupToSet -SPWeb $SPWeb -SPList $myList -RoleType $RoleTypeToApply
}
}
}
}
function Get-SPOSubWebs
{
Param(
[Microsoft.SharePoint.Client.ClientContext]$Context,
[Microsoft.SharePoint.Client.Web]$RootWeb
)
$Webs = $RootWeb.Webs
$Context.Load($Webs)
$Context.ExecuteQuery()
ForEach ($sWeb in $Webs)
{
Write-host " -------------------------------------------------------- "
Write-host " -->> SubSite:", $sWeb.URL -ForegroundColor green
Invoke-LoadMethod -Object $sWeb -PropertyName "HasUniqueRoleAssignments"
$context.ExecuteQuery()
Write-Host " -->> Has Unique Permissions:", $sWeb.HasUniqueRoleAssignments
if($sWeb.HasUniqueRoleAssignments)
{
Invoke-LoadMethod -Object $sWeb -PropertyName "RequestAccessEmail"
$context.ExecuteQuery()
Write-Host " -->> Request Access Email Before change:", $sWeb.RequestAccessEmail
if(($ChangeRequestAccessEmail) -and ($sWeb.RequestAccessEmail -ne $SiteOwnerEmailAdress))
{
Write-Host " ===->> Request Access Email to change"
$sWeb.RequestAccessEmail = $SiteOwnerEmailAdress
$sWeb.Update()
$context.ExecuteQuery()
Invoke-LoadMethod -Object $sWeb -PropertyName "RequestAccessEmail"
$context.ExecuteQuery()
Write-Host " -->> Request Access Email After change:", $sWeb.RequestAccessEmail
}
Add-Group-As-FullPermission-InSPWeb -Context $Context -SPGroupName $RootSiteOwnerGroupToSet -SPWeb $sWeb -RoleType $RoleTypeToApply
}
Check-Permission-InLists -Context $Myctx -SPWeb $sWeb
Get-SPOSubWebs -Context $Context -RootWeb $sWeb
}
}
function Reset-Group-OwnerShip
{
Param(
[Microsoft.SharePoint.Client.ClientContext]$Context,
# [Microsoft.SharePoint.Client.Web]$SPWeb,
[string]$GroupOwnerName
)
$MyRootWeb = $Context.Site.RootWeb
$Mygroups = $MyRootWeb.SiteGroups
$context.Load($MyRootWeb)
$Context.Load($Mygroups)
$Context.ExecuteQuery()
foreach($MyTempGroup in $Mygroups)
{
Write-Host " --->>> Group Name: ", $MyTempGroup.Title
$ThegroupOwner = $Context.Web.SiteGroups.GetByName($GroupOwnerName);
$MyTempGroup.Owner = $ThegroupOwner
$MyTempGroup.Update()
$Context.ExecuteQuery()
}
}
function SetGroupAsFullOwner([string]$MyRootWebURL)
{
[bool]$CreateSGSDocLibList = $false
$Myctx = New-Object Microsoft.SharePoint.Client.ClientContext($MyRootWebURL)
$secureStringPwd = ConvertTo-SecureString -string (Get-Content $PwdTXTPath)
$creds = New-Object System.Management.Automation.PSCredential -ArgumentList $username, $secureStringPwd
$Myctx.Credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($creds.UserName,$creds.Password)
$Myctx.RequestTimeout = 1000000 # milliseconds
$MyspoRootweb = $Myctx.Web
$Myctx.Load($MyspoRootweb)
$Myctx.ExecuteQuery()
Write-Host " "
Write-Host " ---------------------------------------------------------"
Write-Host " >>>> # Server Version:" $Myctx.ServerVersion " # <<<<<<" -ForegroundColor Green
Write-Host " ---------------------------------------------------------"
Write-Host " "
Write-host " -------------------------------------------------------- "
Write-host " -->> RootSite:", $MyspoRootweb.URL -ForegroundColor green
Reset-Group-OwnerShip -Context $Myctx -GroupOwnerName $RootSiteOwnerGroupToSet
Invoke-LoadMethod -Object $MyspoRootweb -PropertyName "RequestAccessEmail"
$Myctx.ExecuteQuery()
Write-Host " -->> Request Access Email Before change:", $MyspoRootweb.RequestAccessEmail
if($MyspoRootweb.RequestAccessEmail -ne $SiteOwnerEmailAdress)
{
Write-Host " ===->> Request Access Email to change"
$MyspoRootweb.RequestAccessEmail = $SiteOwnerEmailAdress
$MyspoRootweb.Update()
$Myctx.ExecuteQuery()
Invoke-LoadMethod -Object $MyspoRootweb -PropertyName "RequestAccessEmail"
$Myctx.ExecuteQuery()
Write-Host " -->> Request Access Email After change:", $MyspoRootweb.RequestAccessEmail
}
Check-Permission-InLists -Context $Myctx -SPWeb $MyspoRootweb
Get-SPOSubWebs -Context $Myctx -RootWeb $MyspoRootweb
}
cls
Load-DLLandAssemblies
SetGroupAsFullOwner $SPOSiteCollectionURLToSetI'm using that script since many months to reapply the permission set after site content migration from SharePoint 2007 to SharePoint Online, the maximum test validation was done with one site collection having more than 2900 Subsites.
Original Post message:
Fabrice Romelard [MBA Risk Management]
Sites Sources:
- https://gist.github.com/star-crossed/0062ec1e5ef622a4c8e8
- http://sharepoint.stackexchange.com/questions/126221/spo-retrieve-hasuniqueroleassignements-property-using-powershell
- https://social.technet.microsoft.com/wiki/contents/articles/31157.manage-sharepoint-online-access-requests-using-powershell.aspx
- https://blogs.msdn.microsoft.com/chandru/2015/12/31/sharepoint-onlinecsom-change-access-requests-settings/
- http://www.sharepointdiary.com/2014/12/delete-unique-permissions-reset-broken-inheritance-using-powershell.html
- https://gist.github.com/asadrefai/b854cf8ca1719a3fcc73
- https://gallery.technet.microsoft.com/office/Script-to-get-All-Webs-in-c2c1cdaf