Private/Resolve-SPMPrincipal.ps1
|
function Resolve-SPMGroupMemberEntry { <# .SYNOPSIS Converts a member of a SharePoint group into a member-tree entry (nested groups resolved via Graph). #> [CmdletBinding()] param( [Parameter(Mandatory)] $User, [Parameter(Mandatory)] [hashtable]$GroupCache ) $login = [string]$User.LoginName switch ([string]$User.PrincipalType) { 'User' { if ($login -eq 'c:0(.s|true') { return [pscustomobject]@{ name = 'Jeder'; type = 'Everyone' } } $upn = $null if ($User.Email) { $upn = [string]$User.Email } elseif ($login -match '\|membership\|(.+)$') { $upn = $Matches[1] } return [pscustomobject]@{ name = [string]$User.Title; type = 'User'; upn = $upn } } 'SecurityGroup' { $claim = Get-SPMClaimClassification -LoginName $login switch ($claim.Type) { 'Everyone' { return [pscustomobject]@{ name = 'Jeder'; type = 'Everyone' } } 'EveryoneExceptExternal' { return [pscustomobject]@{ name = 'Jeder ausser externen Benutzern'; type = 'EveryoneExceptExternal' } } default { $relation = if ($claim.OwnersClaim) { 'owners' } else { 'members' } $label = if ($claim.OwnersClaim) { [string]$User.Title + ' (nur Besitzer der M365-Gruppe)' } else { [string]$User.Title } $entry = [pscustomobject]@{ name = $label; type = $claim.Type; members = $null } if ($claim.GroupId) { $entry.members = @(Resolve-SPMEntraGroup -GroupId $claim.GroupId -GroupCache $GroupCache -Relation $relation) } return $entry } } } default { return [pscustomobject]@{ name = [string]$User.Title; type = 'Other' } } } } function Resolve-SPMPrincipal { <# .SYNOPSIS Registers a role-assignment member as a principal in the per-site principal index and returns its id. .DESCRIPTION SharePoint groups get their members enumerated (including nested Entra ID groups, resolved transitively). Sharing-link groups are detected and typed separately. Each principal is resolved only once per site. #> [CmdletBinding()] param( [Parameter(Mandatory)] $Member, [Parameter(Mandatory)] [System.Collections.Specialized.OrderedDictionary]$PrincipalIndex, [Parameter(Mandatory)] [hashtable]$GroupCache ) $login = [string]$Member.LoginName if ($PrincipalIndex.Contains($login)) { return $PrincipalIndex[$login].id } $name = [string]$Member.Title $type = 'Other' $upn = $null $membersTree = $null switch ([string]$Member.PrincipalType) { 'SharePointGroup' { $type = if ($name -like 'SharingLinks.*' -or $login -like '*SharingLinks.*') { 'SharingLink' } else { 'SharePointGroup' } $list = [System.Collections.Generic.List[object]]::new() try { $spMembers = @(Invoke-SPMWithRetry { Get-PnPGroupMember -Group $Member.Id }) foreach ($u in $spMembers) { $entry = Resolve-SPMGroupMemberEntry -User $u -GroupCache $GroupCache if ($entry) { $list.Add($entry) } } } catch { Write-Warning "Mitglieder der Gruppe '$name' konnten nicht abgerufen werden: $($_.Exception.Message)" $list.Add([pscustomobject]@{ name = '(Mitglieder nicht abrufbar)'; type = 'Note' }) } $membersTree = $list.ToArray() } 'SecurityGroup' { $claim = Get-SPMClaimClassification -LoginName $login $type = $claim.Type if ($type -eq 'EveryoneExceptExternal') { $name = 'Jeder ausser externen Benutzern' } if ($claim.OwnersClaim) { $name = $name + ' (nur Besitzer der M365-Gruppe)' } if ($claim.GroupId) { $relation = if ($claim.OwnersClaim) { 'owners' } else { 'members' } $membersTree = @(Resolve-SPMEntraGroup -GroupId $claim.GroupId -GroupCache $GroupCache -Relation $relation) } } 'User' { if ($login -eq 'c:0(.s|true') { $type = 'Everyone' $name = 'Jeder' } else { $type = 'User' if ($Member.Email) { $upn = [string]$Member.Email } elseif ($login -match '\|membership\|(.+)$') { $upn = $Matches[1] } } } } $record = [pscustomobject]@{ id = 'p{0}' -f $PrincipalIndex.Count name = $name type = $type loginName = $login upn = $upn members = $membersTree } $PrincipalIndex[$login] = $record return $record.id } |