v0.1.24 — App Report, CSV Import, Read-Only Mode, Group Management

- App Report: Installationszähler pro App via Graph $batch (deviceStatuses)
- Geräte-Export: CSV mit Maschinennamen pro App (GET /api/apps/devicestatus)
- CSV-Import: Massenimport von Benutzern in Gruppen mit Header-Erkennung
- Read-Only-Modus: Schreib-Tabs/Buttons automatisch ausblenden
- Ergebnis-Banner nach CSV-Import (hinzugefügt/bereits Mitglied/Fehler/nicht gefunden)
- Dokumentation aktualisiert (README, help.md, CHANGELOG)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-07-03 07:12:49 +02:00
co-authored by Claude Sonnet 4.6
commit 34811ff583
24 changed files with 17052 additions and 0 deletions
+217
View File
@@ -0,0 +1,217 @@
# Intune Manager – Web Edition
Modernes Web-Frontend fuer den Intune Manager.
PowerShell startet einen lokalen HTTP-Server, der das Frontend ausliefert
und die Microsoft Graph-Aufrufe ausfuehrt.
## Voraussetzungen
- Windows mit PowerShell 5.1 oder PowerShell 7+
- Modul `Microsoft.Graph.Authentication` (wird beim ersten Connect benoetigt):
```powershell
Install-Module Microsoft.Graph.Authentication -Scope CurrentUser -Force
```
- Browser (Edge, Chrome, Firefox)
## Start
```powershell
.\Start.ps1
```
Optionen:
| Parameter | Standard | Beschreibung |
|---------------|----------|-----------------------------------------------------------|
| `-Port` | `8077` | Port des lokalen HTTP-Servers |
| `-TenantId` | — | Ueberschreibt Tenant-ID aus Settings (nur dieser Start) |
| `-ClientId` | — | Ueberschreibt Client-ID aus Settings (nur dieser Start) |
| `-NoBrowser` | aus | Browser nicht automatisch oeffnen |
Beispiele:
```powershell
.\Start.ps1 -Port 8088
.\Start.ps1 -NoBrowser
```
Beenden: `Ctrl+C` im Terminal.
---
## Verbindungsmodus (Read/Write vs. Read-Only)
Der Server probiert beim Verbinden **zuerst die Read/Write-App-ID** (`clientId`).
Schlaegt diese fehl, wird automatisch auf die **Read-Only-App-ID** (`clientIdRo`) zurueckgefallen.
| Modus | Anmelde-Ergebnis | Verhalten im Frontend |
|-------------|------------------------------------------|------------------------------------------------|
| Read/Write | Normale Verbindung | Alle Funktionen verfuegbar |
| Read-Only | Fallback auf `clientIdRo` | Schreib-Buttons/Tabs werden ausgeblendet |
### Was wird im Read-Only-Modus ausgeblendet?
- App-Zuweisung (Required / Available hinzufuegen und entfernen)
- Gruppen erstellen und loeschen
- Tab „Benutzer hinzufuegen" im Group Management
- Tab „CSV-Import" im Group Management
- Session-Ausfuehren-Button
- Alle Rename-/Delete-Buttons
### Konfiguration in den Einstellungen
```
Settings → Verbindung
Client-ID (Read/Write): <Azure App-Registration mit Schreibrechten>
Client-ID (Read-Only): <Azure App-Registration nur mit Leserechten> (optional)
Scopes RW: DeviceManagementApps.ReadWrite.All ...
Scopes RO: DeviceManagementApps.Read.All ...
```
### Benoetigt Graph-Berechtigungen
| Funktion | Benoetigt |
|----------------------------------|----------------------------------------------|
| Apps anzeigen | `DeviceManagementApps.Read.All` |
| Gruppen anzeigen / Mitglieder | `GroupMember.Read.All` |
| User suchen | `User.Read.All` |
| Zuweisungen aendern | `DeviceManagementApps.ReadWrite.All` |
| Gruppen-Mitglieder aendern | `GroupMember.ReadWrite.All` |
| App-Installationszaehler (Report)| `DeviceManagementManagedDevices.Read.All` ⚠ |
| Geraete-Exportliste pro App | `DeviceManagementManagedDevices.Read.All` ⚠ |
> ⚠ Ohne `DeviceManagementManagedDevices.Read.All` zeigt der App-Report nur
> Zaehler = 0 und der Geraete-Export liefert keine Eintraege.
---
## Navigation (Tabs)
| Tab | Beschreibung |
|--------------------|-------------------------------------------------------------|
| App Management | Haupt-Ansicht: Apps laden, Gruppen zuweisen / entfernen |
| Group Management | Mitglieder anzeigen, exportieren, Benutzer hinzufuegen, CSV-Import |
| App Report | Installationszaehler pro App, Geraete-Export als CSV |
---
## Group Management
### Mitglieder & Export
- Gruppe links suchen und auswaehlen
- Mitgliederliste (inkl. verschachtelte Gruppen) wird geladen
- Filter zum Einschraenken der Anzeige
- **Als CSV exportieren** laedt alle Mitglieder als `members-<Gruppe>-<Datum>.csv`
### Benutzer hinzufuegen *(nur Read/Write)*
- Benutzer per Name, UPN oder E-Mail suchen
- Mehrere Benutzer auswaehlen und gemeinsam hinzufuegen
### CSV-Import *(nur Read/Write)*
Massenhaftes Hinzufuegen von Benutzern zu einer Gruppe per CSV-Datei.
**Ablauf:**
1. Gruppe links auswaehlen
2. CSV hochladen **oder** UPNs/E-Mails direkt einfuegen (eine pro Zeile)
3. **„Benutzer aufloesen"** – Graph-Lookup via UPN/Mail → Vorschau mit ✓/✗
4. **„Gefundene importieren"** – fuegt alle gefundenen Benutzer zur Gruppe hinzu
**CSV-Format:**
Die erste Zeile wird als optionaler Header erkannt.
Spalte mit dem Namen `UserPrincipalName`, `Mail` oder `Email` wird automatisch
ausgewaehlt. Ohne Header: erste Spalte mit `@` wird verwendet.
```csv
DisplayName,UserPrincipalName,Mail
Max Mustermann,max.mustermann@firma.de,max.mustermann@firma.de
Erika Muster,erika.muster@firma.de,
```
Oder einfach eine UPN pro Zeile:
```
max.mustermann@firma.de
erika.muster@firma.de
```
**Ergebnis-Anzeige nach Import:**
| Chip / Status | Bedeutung |
|--------------------|------------------------------------------------|
| ✔ Gruen | Erfolgreich hinzugefuegt |
| ≈ Gelb | Bereits Mitglied (kein Fehler) |
| ✗ Rot | Fehler (Meldung in der Tabelle) |
| Grau | UPN nicht in Graph gefunden (nicht importiert) |
---
## App Report
- **Neu laden**: laedt Installationszaehler fuer alle Apps (kann 1–2 Min. dauern)
- Tabelle sortierbar per Klick auf Spaltenheader
- Suche filtert nach App-Name, Publisher, Typ
- **Als CSV exportieren**: exportiert die gefilterte Tabelle
- **Geraete-Export** (pro Zeile): laedt alle Geraete mit Installationsstatus fuer diese App
---
## Architektur
```
Intune Manager/
├── Start.ps1 Entry Point, Config, State
├── README.md diese Datei
├── src/
│ ├── Models.ps1 Settings-Schema und Defaults
│ ├── Graph.ps1 Microsoft Graph API Helpers
│ ├── Server.ps1 HTTP-Server (HttpListener)
│ ├── Router.ps1 Request-Routing
│ └── Api.ps1 REST-API-Endpoints
└── www/
├── index.html SPA-Shell
├── styles.css Dark Theme, Read-Only-Regeln
└── app.js Frontend-Logik (Vanilla JS)
```
---
## REST-API (intern)
| Methode | Pfad | Rechte | Zweck |
|---------|-------------------------------------------|-----------|------------------------------------------|
| GET | `/api/status` | — | Verbindungsstatus + ReadOnly-Flag |
| POST | `/api/connect` | — | Microsoft Graph verbinden |
| POST | `/api/disconnect` | — | Trennen |
| GET | `/api/groups` | Read | Abteilungs-Gruppen (`abt-hm-*`) |
| GET | `/api/groups/rpa` | Read | 3 vordefinierte RPA-Gruppen |
| GET | `/api/groups/search?q=` | Read | Gruppen suchen |
| POST | `/api/groups` | **Write** | Neue Required-Gruppe erstellen |
| POST | `/api/groups/check` | Read | Gruppen-Name pruefen |
| POST | `/api/groups/resolve-upns` | Read | UPN-Liste → UserId + DisplayName |
| GET | `/api/groups/{id}/members` | Read | Mitglieder einer Gruppe |
| GET | `/api/groups/{id}/members/export` | Read | Mitglieder als CSV |
| POST | `/api/groups/{id}/members` | **Write** | Benutzer zur Gruppe hinzufuegen |
| DELETE | `/api/groups/{id}/members/{uid}` | **Write** | Benutzer aus Gruppe entfernen |
| GET | `/api/users?q=` | Read | Benutzer suchen |
| GET | `/api/apps` | Read | Apps laden (cached) |
| POST | `/api/apps/refresh` | Read | Apps neu laden |
| GET | `/api/apps/report` | Read+MDM | Installationszaehler alle Apps |
| GET | `/api/apps/devicestatus?appId=` | Read+MDM | Geraete-Installationsstatus einer App |
| GET | `/api/membership?targets=&groupId=` | Read | Mitgliedschafts-Status pruefen |
| POST | `/api/membership/bulk` | Read | Mehrere Mitgliedschaften pruefen |
| POST | `/api/assignments/apply` | **Write** | Geplante Zuweisungen ausfuehren |
> **Read+MDM** = benoetigt zusaetzlich `DeviceManagementManagedDevices.Read.All`
---
## Hinweise
- **Single-User-App** – der lokale HTTP-Server ist fuer einen Benutzer ausgelegt.
- **Auth lebt im PowerShell-Prozess** – Disconnect oder Schliessen des Terminals beendet die Session.
- **Cache** – Apps werden im Serverprozess gecacht. Refresh-Knopf laedt neu.
- **Port-Konflikt** – laeuft bereits eine Instanz, beendet `Start.ps1` sie automatisch (per CommandLine-Matching). Bei PID-4-Konflikt (http.sys) anderen Port waehlen: `.\Start.ps1 -Port 8088`.