SharePoint: Auflisten aller Objekte mit eigener Berechtigungszuweisung

​Die Frage meines Kunden letztens: “Wie kann ich alle Elemente (Listen, Items, etc.) auflisten, bei denen eigene berechtigungszuweisungen erfolgt sind?”

Meine schnelle Antwort: “Nicht möglich, OOTB!”.

Mittlerweile weiß ich: In 2007 ging das – aber nur mit dem SharePoint Administrator Toolkit.

Ich habe – mit Inspiration von Mike Smith – ein Skript erstellt​, dass eben dies macht.

<#
.SYNOPSIS
List all items with broken inheritance
.DESCRIPTION
Lists all Webs, Lists, Folders and Items with broken inheritance.
This script was heavily inspired by http://techtrainingnotes.blogspot.de/2014/07/sharepoint-powershellfind-all-broken.html
.PARAMETER SiteCollectionUrl
Url to SiteCollection
.PARAMETER Site
Site. Can be Piped in.
.PARAMETER StopAtWeb
Stop the search at Web-Level. Do not search Lists/Folders/Items.
.PARAMETER StopAtList
Stop the search at List-Level. Do not search Folders/Items.
.PARAMETER StopAtFolder
Stop the search at Folder-Level. Do not search Items.
.INPUTS
Site
.OUTPUTS
Grid of Securable | Item | Url | Parent
where
Securable is one of "Web", "List", "Folder" or "Item"
Item is the Name or Title
Url is the url to the item
Parent is the url to the parent-item
.EXAMPLE
.\Get-SpBrokenInheritances.ps1 -SiteCollectionUrl http://my.lovely.site/
#>
[CmdletBinding()]
param (
[Parameter(ParameterSetName='SiteByUrl')]
[string]$SiteCollectionUrl,
[Parameter(ParameterSetName='SiteByObject', ValueFromPipeline=$true)]
[Microsoft.SharePoint.SPSite]$Site,
[Parameter()]
[switch]$StopAtWeb = $false,
[Parameter()]
[switch]$StopAtList = $false,
[Parameter()]
[switch]$StopAtFolder = $false
)
Set-StrictMode -Version Latest
$script:ErrorActionPreference = "Stop";
function Get-ParentUrl {
[CmdletBinding()]
param (
[Parameter(Mandatory=$true)]
[Microsoft.SharePoint.SPListItem]$Item
)
$List = $Item.ParentList;
if ($List.BaseType -eq [Microsoft.SharePoint.SPBaseType]::DocumentLibrary) {
return "$($_.ParentList.ParentWeb.ServerRelativeUrl)/$($_.File.ParentFolder.Url)";
} else {
# SPListItem.Url looks like /<listName>/<Folder1>/<folder2>/<ID>_.000 - I have no idea how to get the folder Url "correctly"
$FolderUrl = $Item.Url.Substring(0, $Item.Url.LastIndexOf("/"));
return "$($List.ParentWeb.ServerRelativeUrl)/$FolderUrl";
}
}
function Get-Url {
[CmdletBinding()]
param (
[Parameter(Mandatory=$true)]
[Microsoft.SharePoint.SPListItem]$Item
)
$List = $Item.ParentList;
if ($List.BaseType -eq [Microsoft.SharePoint.SPBaseType]::DocumentLibrary) {
return "$($List.ParentWeb.ServerRelativeUrl)/$($Item.Url)";
} else {
# e.g. /blubb/Lists/Test12/DispForm.aspx?ID=1
return "$($Item.ParentList.DefaultDisplayFormUrl)?ID=$($Item.Id)";
}
}
function Process-Lists {
[CmdletBinding()]
param (
[Parameter(Mandatory=$true)]
[Microsoft.SharePoint.SPList[]]$Lists
)
$Folders = $Lists | Select -ExpandProperty Folders;
$Folders | ? { $_.HasUniqueRoleAssignments } |
Select @{Label="Securable"; Expression={"Folder"}},
@{Label="Item"; Expression={$_.Title}},
@{Label="Url"; Expression={"$($_.ParentList.ParentWeb.ServerRelativeUrl)/$($_.Url)"}},
@{Label="Parent"; Expression={"$($_.ParentList.ParentWeb.ServerRelativeUrl)/$($_.ParentList.RootFolder.Url)"}} | Write-Output
if($StopAtFolder) {
return;
}
$Items = $Lists | Select -ExpandProperty Items;
$Items | ? { $_.HasUniqueRoleAssignments } |
Select @{Label="Securable"; Expression={"Item"}},
@{Label="Item"; Expression={$_.Name}},
@{Label="Url"; Expression={Get-Url -Item $_ }},
@{Label="Parent"; Expression={Get-ParentUrl -Item $_ }} | Write-Output
}
function Process-Webs {
[CmdletBinding()]
param (
[Parameter(Mandatory=$true)]
$Webs
)
$Lists = $Webs | Select -ExpandProperty Lists | ? { $_.EntityTypeName -ne "PublishedFeedList" -and -not $_.Hidden }
$Lists | ?{ $_.HasUniqueRoleAssignments } |
Select @{Label="Securable"; Expression={"List"}},
@{Label="Item"; Expression={$_.Title}},
@{Label="Url"; Expression={"$($_.ParentWeb.ServerRelativeUrl)/$($_.RootFolder.Url)"}},
@{Label="Parent"; Expression={$_.ParentWebUrl}} | Write-Output
if($StopAtList) {
return;
}
Process-Lists -Lists $Lists
}
function Process-Site {
[CmdletBinding()]
param (
[Parameter(Mandatory=$true)]
[Microsoft.SharePoint.SPSite]$Site
)
Write-Verbose "Process-Site $($Site.RootWeb.Title)";
$WebGc = Start-SPAssignment;
try {
$Webs = $Site | Get-SPWeb -AssignmentCollection $WebGc -Limit All;
$Webs | ?{ $_.HasUniqueRoleAssignments -and $_.ParentWeb -ne $Null } |
Select @{Label="Securable"; Expression={"Web"}},
@{Label="Item"; Expression={$_.Title}},
@{Label="Url"; Expression={$_.ServerRelativeUrl}},
@{Label="Parent"; Expression={$_.ParentWeb.ServerRelativeUrl}} | Write-Output
if($StopAtWeb) {
return;
}
Process-Webs -Webs $Webs
} finally {
Stop-SPAssignment $WebGc;
}
}
Add-PSSnapin "Microsoft.SharePoint.PowerShell" -ErrorAction Inquire
$gc = Start-SPAssignment;
try{
if(!$Site) {
Write-Verbose "Site was neither given, nor in Pipe. Fetching Site from Url:$SiteCollectionUrl";
if(!$SiteCollectionUrl) {
Write-Error "Neither -Site, nor -SiteCollectionUrl was given.";
Exit -1;
}
$Site = Get-SpSite -Identity $SiteCollectionUrl -AssignmentCollection $gc -ErrorAction SilentlyContinue;
if ($Site -eq $null)
{
Write-Error "No SiteCollection with Identity '$SiteCollectionUrl' found. Exiting...";
Exit -1;
}
}
Process-Site -Site $Site;
} finally {
Stop-SPAssignment $gc;
}