Public/New-SPPermissionReport.ps1
|
function New-SPPermissionReport { <# .SYNOPSIS Renders a scan JSON (from Invoke-SPPermissionScan) into a self-contained, interactive HTML report. .DESCRIPTION The report needs no server and can be sent by mail: matrix per site (hierarchy as a collapsible tree, principals as columns, V/B/M/L abbreviations in the cells), inherited permissions dimmed, unique permissions highlighted, group members shown on click (including nested groups), search/filter (including "where does person X have access?"), sharing links flagged and filterable, overview page for tenant scans. .PARAMETER InputPath Path to the scan JSON file. .PARAMETER ScanData Scan object (from Invoke-SPPermissionScan -PassThru) or scan JSON FileInfo - pipeline capable. .PARAMETER OutputPath Path of the HTML output file. Default: input path with .html extension. .PARAMETER Title Report title. Default: SharePoint-Berechtigungsmatrix .PARAMETER Open Opens the report in the default browser afterwards. .EXAMPLE New-SPPermissionReport -InputPath .\scan.json -Open .EXAMPLE Invoke-SPPermissionScan -SiteUrl $url -Depth 2 -Interactive -ClientId $appId | New-SPPermissionReport -Open #> [CmdletBinding(SupportsShouldProcess, DefaultParameterSetName = 'Path')] [OutputType([System.IO.FileInfo])] param( [Parameter(Mandatory, ParameterSetName = 'Path', Position = 0)] [string]$InputPath, [Parameter(Mandatory, ParameterSetName = 'Data', ValueFromPipeline)] [psobject]$ScanData, [string]$OutputPath, [string]$Title = 'SharePoint-Berechtigungsmatrix', [switch]$Open ) process { $sourcePath = $null if ($PSCmdlet.ParameterSetName -eq 'Path') { $sourcePath = $InputPath } elseif ($ScanData -is [System.IO.FileInfo]) { $sourcePath = $ScanData.FullName } if ($sourcePath) { if (-not (Test-Path -Path $sourcePath)) { throw "Scan-Datei nicht gefunden: $sourcePath" } $json = Get-Content -Path $sourcePath -Raw -Encoding utf8 $null = $json | ConvertFrom-Json # validate early } else { $json = $ScanData | ConvertTo-Json -Depth 64 } if (-not $OutputPath) { if ($sourcePath) { $OutputPath = [System.IO.Path]::ChangeExtension((Resolve-Path -Path $sourcePath).Path, '.html') } else { $OutputPath = Join-Path (Get-Location) ('SPPermissionReport_{0:yyyyMMdd_HHmmss}.html' -f (Get-Date)) } } # "</" would end the inline <script> block early - escape it (valid JSON escape). $safeJson = $json -replace '</', '<\/' $html = (Get-SPMHtmlTemplate). Replace('__REPORT_TITLE__', [System.Net.WebUtility]::HtmlEncode($Title)). Replace('__GENERATED__', (Get-Date -Format 'dd.MM.yyyy HH:mm')). Replace('"__SCAN_DATA__"', $safeJson) if ($PSCmdlet.ShouldProcess($OutputPath, 'HTML-Report erstellen')) { Set-Content -Path $OutputPath -Value $html -Encoding utf8 Write-Verbose "Report gespeichert: $OutputPath" if ($Open) { Invoke-Item -Path $OutputPath } return (Get-Item -Path $OutputPath) } } } |