feat(nextcloud-files): Modul Dateien mit Nextcloud-Adresse, Verbindungsprüfung und gesicherter Verbindungsschicht

- Migration 20261008180000: NextcloudFilesConfig (Organisation) und NextcloudFilesAccount
  (Mandant UND Benutzer per Zeilenschutz, nur verschlüsseltes App-Passwort)
- Transportschicht ncRequest: feste Pfadanfänge, Segmentcodierung, keine Weiterleitungen,
  keine Cookies, Zeitgrenzen; Aufrufsperre pausiert den Ursprung nach jedem 429 und
  sperrt Zugangsschlüssel nach dem ersten 401
- Einstellungen: Adresse speichern/prüfen, Adresswechsel läuft alle Konten ab (mit Bestätigung)
- Controller mit Verwalten nur auf Einstellungen, Seed, Modul, Registrierung in Web
  (Ladefunktion, Symbol folder, Navigation, Layout) und Reiter Einstellungen
- RLS-Inventar fortgeschrieben, Testaufbau (tessera-nc-test) und E2E-Skripte

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-08 17:41:46 +02:00
parent 83b842b72c
commit 960696745f
35 changed files with 3282 additions and 2 deletions
+46
View File
@@ -58,6 +58,7 @@ model User {
moduleGrants ModuleGrant[]
customModules CustomModule[]
reminders Reminder[]
nextcloudFilesAccounts NextcloudFilesAccount[]
nextcloudAlertSubscriptions NextcloudAlertSubscription[]
@@index([tenantId])
@@ -942,6 +943,51 @@ model DomainsOrder {
@@index([tenantId])
}
// quick-261008-mzu: Modul "Nextcloud-Dateien". Eine Nextcloud je Organisation
// (NextcloudFilesConfig, Singleton), ein eigenes Konto je Benutzer
// (NextcloudFilesAccount). Gespeichert wird nur das App-Passwort, AES-verschluesselt
// (CryptoService); das echte Passwort wird nie abgelegt. `baseUrl` im Konto ist die
// Adresse, fuer die das App-Passwort ausgestellt wurde: es geht nie an einen anderen
// Host, und ein Adresswechsel laesst alle Konten ablaufen. Zeilenschutz wie Reminder
// (Mandant UND Benutzer), keine Systemleserregel.
enum NextcloudFilesAccountStatus {
ACTIVE
EXPIRED
}
enum NextcloudFilesConnectMethod {
PASSWORD
LOGIN_FLOW
}
model NextcloudFilesConfig {
id String @id @default(uuid())
tenantId String @unique
baseUrl String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@index([tenantId])
}
model NextcloudFilesAccount {
id String @id @default(uuid())
tenantId String
userId String
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
baseUrl String
ncUserId String
ncDisplayName String?
encryptedAppPassword String
status NextcloudFilesAccountStatus @default(ACTIVE)
connectedVia NextcloudFilesConnectMethod
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@unique([tenantId, userId])
@@index([tenantId])
}
// Eigene Module (quick-260929-9wc): vom Administrator angelegte Seitenleisten-
// Eintraege, die eine externe https-Seite im Rahmen zeigen. Sichtbar fuer alle
// Benutzer des Mandanten. Zeilenschutz nach Muster ProxmoxServer (tenantId,