add group export

This commit is contained in:
2026-06-17 08:14:10 +02:00
parent 2f271265e9
commit e98660134a
8 changed files with 558 additions and 0 deletions
+87
View File
@@ -29,6 +29,7 @@ function Invoke-ApiHandler {
"GET /api/groups" { return Get-GroupsEndpoint -Query $Query }
"GET /api/groups/rpa" { return Get-RpaGroupsEndpoint }
"GET /api/groups/search" { return Search-GroupsEndpoint -Query $Query }
"POST /api/groups" { return New-GroupEndpoint -Body $Body }
"POST /api/groups/check" { return Test-GroupNameEndpoint -Body $Body }
@@ -45,6 +46,11 @@ function Invoke-ApiHandler {
}
# 2-segment fallbacks (z.B. /api/groups/<id>/members)
# Export-Route VOR der generischen /members-Route pruefen
if ($Method -eq "GET" -and $Path -match "^/api/groups/([^/]+)/members/export$") {
return Get-GroupMembersExportEndpoint -GroupId $matches[1]
}
if ($Method -eq "GET" -and $Path -match "^/api/groups/([^/]+)/members$") {
return Get-GroupMembersEndpoint -GroupId $matches[1]
}
@@ -1185,6 +1191,87 @@ function Get-GroupMembersEndpoint {
return @{ items = $items; count = $items.Count }
}
function Search-GroupsEndpoint {
param($Query)
$err = Test-Connected
if ($err) { return $err }
$term = [string]$Query.q
if ([string]::IsNullOrWhiteSpace($term) -or $term.Length -lt 2) {
return @{ items = @(); count = 0 }
}
$sw = [System.Diagnostics.Stopwatch]::StartNew()
$raw = @(Search-GraphGroups -SearchTerm $term -Top 50)
$sw.Stop()
Write-Host " [GSEARCH] '$term': $($raw.Count) Treffer in $($sw.ElapsedMilliseconds)ms" -ForegroundColor DarkGray
$items = @()
foreach ($g in $raw) {
$id = if ($g.id) { $g.id } else { $g.Id }
$name = if ($g.displayName) { $g.displayName } else { $g.displayname }
if ($id) {
$items += [pscustomobject]@{
Id = [string]$id
DisplayName = [string]$name
Description = [string]$g.description
}
}
}
return @{ items = $items; count = $items.Count }
}
function Get-GroupMembersExportEndpoint {
# Loest alle Benutzer einer Gruppe auf, einschliesslich Mitglieder aus
# verschachtelten Unter-Gruppen. Gibt die flache, deduplizierte Benutzer-
# liste mit SourcePath-Angabe zurueck — das Frontend erzeugt daraus den CSV.
param([string]$GroupId)
$err = Test-Connected
if ($err) { return $err }
if ([string]::IsNullOrWhiteSpace($GroupId)) {
return @{ __status = 400; error = "GroupId fehlt" }
}
$groupName = $GroupId
try {
$g = Get-GraphGroupById -Id $GroupId -Property @("id","displayName")
if ($g.displayName) { $groupName = [string]$g.displayName }
} catch {
return @{ __status = 404; error = "Gruppe nicht gefunden: $($_.Exception.Message)" }
}
Write-Host "[EXPORT] Starte Aufloesung: '$groupName' ($GroupId)" -ForegroundColor Cyan
$sw = [System.Diagnostics.Stopwatch]::StartNew()
$allUsers = @(Resolve-GroupMembersWithNesting -GroupId $GroupId -GroupName $groupName)
# Deduplizieren: erster Treffer (= direktes Mitglied) gewinnt
$seen = @{}
$unique = [System.Collections.Generic.List[object]]::new()
$dups = 0
foreach ($u in $allUsers) {
if (-not $seen.ContainsKey($u.Id)) {
$seen[$u.Id] = $true
$unique.Add($u)
} else {
$dups++
}
}
$sw.Stop()
Write-Host " -> $($unique.Count) eindeutige Benutzer, $dups Duplikate, $($sw.ElapsedMilliseconds)ms" -ForegroundColor Green
return @{
groupId = $GroupId
groupName = $groupName
users = $unique.ToArray()
count = $unique.Count
duplicates = $dups
resolvedMs = [int]$sw.ElapsedMilliseconds
}
}
# ============================================================
# Users
# ============================================================