Geräte-Tab: Suche, Detail-Panel und Aktionen

Neuer Haupttab "Geräte" mit Geräteliste (filterbar nach OS/Compliance),
Detail-Panel mit vollständigen Gerätedaten und Aktions-Buttons:
Sync, Neustart, Sperren, Diagnose, BitLocker-Rotation, Retire.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-08-12 14:26:46 +02:00
co-authored by Claude Sonnet 4.6
parent ec130031cb
commit 78dc8d5c01
4 changed files with 566 additions and 1 deletions
+113
View File
@@ -70,6 +70,18 @@ function Invoke-ApiHandler {
return Get-UserMemberOfEndpoint -UserId $matches[1]
}
if ($Method -eq "GET" -and $Path -eq "/api/devices") {
return Search-DevicesEndpoint -Query $Query
}
if ($Method -eq "GET" -and $Path -match "^/api/devices/([^/]+)$") {
return Get-DeviceEndpoint -DeviceId $matches[1]
}
if ($Method -eq "POST" -and $Path -match "^/api/devices/([^/]+)/action$") {
return Invoke-DeviceActionEndpoint -DeviceId $matches[1] -Body $Body
}
if ($Method -eq "GET" -and $Path -match "^/api/apps/([^/]+)/details$") {
return Get-AppDetailsEndpoint -AppId $matches[1]
}
@@ -1520,6 +1532,107 @@ function Get-UserMemberOfEndpoint {
return @{ groups = $groups; count = $groups.Count }
}
# ============================================================
# Devices
# ============================================================
function Search-DevicesEndpoint {
param($Query)
$err = Test-Connected
if ($err) { return $err }
$q = [string]$Query.q
$os = [string]$Query.os
$compliance = [string]$Query.compliance
$top = 100
$filters = @()
if ($q -and $q.Length -ge 2) {
$qEnc = [uri]::EscapeDataString($q)
$filters += "(startswith(deviceName,'$q') or startswith(userDisplayName,'$q') or startswith(serialNumber,'$q'))"
}
if ($os) { $filters += "operatingSystem eq '$os'" }
if ($compliance) { $filters += "complianceState eq '$compliance'" }
$filterStr = if ($filters.Count -gt 0) { '$filter=' + [uri]::EscapeDataString(($filters -join ' and ')) + '&' } else { '' }
$select = 'id,deviceName,userDisplayName,userPrincipalName,operatingSystem,osVersion,complianceState,lastSyncDateTime,managementState,serialNumber,model,manufacturer,enrolledDateTime'
$uri = "https://graph.microsoft.com/v1.0/deviceManagement/managedDevices?${filterStr}`$select=$select&`$top=$top&`$orderby=deviceName"
$items = @()
$resp = Invoke-MgGraphRequestRetry -Uri $uri -Method GET
foreach ($d in $resp.value) {
$items += [pscustomobject]@{
Id = $d.id
DeviceName = $d.deviceName
UserDisplayName = $d.userDisplayName
UserPrincipalName= $d.userPrincipalName
OS = $d.operatingSystem
OSVersion = $d.osVersion
ComplianceState = $d.complianceState
LastSync = $d.lastSyncDateTime
ManagementState = $d.managementState
SerialNumber = $d.serialNumber
Model = $d.model
Manufacturer = $d.manufacturer
EnrolledDateTime = $d.enrolledDateTime
}
}
return @{ items = $items; count = $items.Count }
}
function Get-DeviceEndpoint {
param($DeviceId)
$err = Test-Connected
if ($err) { return $err }
$select = 'id,deviceName,userDisplayName,userPrincipalName,operatingSystem,osVersion,complianceState,lastSyncDateTime,managementState,serialNumber,model,manufacturer,enrolledDateTime,imei,wiFiMacAddress,azureADDeviceId,joinType,deviceEnrollmentType,managedDeviceOwnerType,totalStorageSpaceInBytes,freeStorageSpaceInBytes'
$d = Invoke-MgGraphRequestRetry -Uri "https://graph.microsoft.com/v1.0/deviceManagement/managedDevices/$DeviceId`?`$select=$select" -Method GET
$totalGB = if ($d.totalStorageSpaceInBytes) { [math]::Round($d.totalStorageSpaceInBytes / 1GB, 1) } else { $null }
$freeGB = if ($d.freeStorageSpaceInBytes) { [math]::Round($d.freeStorageSpaceInBytes / 1GB, 1) } else { $null }
return @{
Id = $d.id
DeviceName = $d.deviceName
UserDisplayName = $d.userDisplayName
UserPrincipalName= $d.userPrincipalName
OS = $d.operatingSystem
OSVersion = $d.osVersion
ComplianceState = $d.complianceState
LastSync = $d.lastSyncDateTime
ManagementState = $d.managementState
SerialNumber = $d.serialNumber
Model = $d.model
Manufacturer = $d.manufacturer
EnrolledDateTime = $d.enrolledDateTime
Imei = $d.imei
WiFiMac = $d.wiFiMacAddress
AzureADDeviceId = $d.azureADDeviceId
JoinType = $d.joinType
EnrollmentType = $d.deviceEnrollmentType
OwnerType = $d.managedDeviceOwnerType
TotalStorageGB = $totalGB
FreeStorageGB = $freeGB
}
}
function Invoke-DeviceActionEndpoint {
param($DeviceId, $Body)
$err = Test-Connected
if ($err) { return $err }
$action = [string]$Body.action
$allowed = @('syncDevice','rebootNow','remoteLock','collectDiagnostics','rotateBitLockerKeys','retire')
if ($action -notin $allowed) {
return @{ statusCode = 400; error = "Unbekannte Aktion: $action" }
}
$uri = "https://graph.microsoft.com/v1.0/deviceManagement/managedDevices/$DeviceId/$action"
$bodyJson = '{}'
Invoke-MgGraphRequestRetry -Uri $uri -Method POST -Body $bodyJson -ContentType 'application/json' | Out-Null
return @{ success = $true; action = $action }
}
# ============================================================
# Apps
# ============================================================