feat(nextcloud-files): Anmeldung per Passwort und im Browser (Zwei-Faktor), Abmelden mit Widerruf
- Anmelde-Client (getapppassword, cloud/user, Widerruf, Login Flow v2 mit fester Abfrageadresse, Link aus Basis und Token neu gebaut), Anmeldebremse 3/15 min je Benutzer und 8/30 min je Server, Ablaufspeicher für Browser-Anmeldungen (20 min, höchstens 200, eine je Benutzer) - Kontodienst: Verbinden, Trennen mit Widerruf, Sitzung mit Zugangsschlüssel-Sperre, frisch ausgestellte oder ersetzte App-Passwörter bleiben nie verwaist; jeder Kontozugriff über forTenant mit Mandant UND Benutzer aus dem Token - Migration 20261008183000: Spalte ncLoginName (App-Passwort gilt nur für den Anmeldenamen der Ausstellung, gemessen mit E-Mail-Anmeldung gegen Nextcloud 34) - Verbindungsbildschirm und Kontoleiste, Texte de/en, RLS-Inventar fortgeschrieben, E2E-Skript e2e-connect.sh Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -12,11 +12,25 @@ const BASE = '/modules/nextcloud-files';
|
||||
export interface NextcloudFilesAccount {
|
||||
connected: boolean;
|
||||
expired: boolean;
|
||||
status: 'ACTIVE' | 'EXPIRED';
|
||||
ncUserId: string | null;
|
||||
displayName: string | null;
|
||||
connectedVia: 'PASSWORD' | 'LOGIN_FLOW' | null;
|
||||
connectedAt: string | null;
|
||||
}
|
||||
|
||||
export interface NextcloudFilesFlowStart {
|
||||
flowId: string;
|
||||
/** Link zur Anmeldeseite der Nextcloud; der Benutzer oeffnet ihn mit eigenem Klick. */
|
||||
loginUrl: string;
|
||||
expiresAt: string;
|
||||
}
|
||||
|
||||
export type NextcloudFilesFlowPoll =
|
||||
| { state: 'pending' }
|
||||
| { state: 'connected' }
|
||||
| { state: 'failed'; code: string; message: string };
|
||||
|
||||
export interface NextcloudFilesStatus {
|
||||
configured: boolean;
|
||||
serverUrl: string | null;
|
||||
@@ -118,3 +132,34 @@ export function saveNextcloudFilesSettings(input: {
|
||||
export function testNextcloudFilesSettings(baseUrl: string): Promise<NextcloudFilesCheck> {
|
||||
return request<NextcloudFilesCheck>('/settings/test', { method: 'POST', json: { baseUrl } });
|
||||
}
|
||||
|
||||
/**
|
||||
* Verbinden mit Benutzername und Passwort. Das Passwort geht genau einmal an die
|
||||
* API und wird nirgends zwischengespeichert; die Antwort enthaelt kein Geheimnis.
|
||||
*/
|
||||
export function connectWithPassword(input: {
|
||||
loginName: string;
|
||||
password: string;
|
||||
}): Promise<NextcloudFilesStatus> {
|
||||
return request<NextcloudFilesStatus>('/connect/password', { method: 'POST', json: input });
|
||||
}
|
||||
|
||||
/** Startet die Browser-Anmeldung (Login Flow v2) fuer Konten mit Zwei-Faktor-Anmeldung. */
|
||||
export function startLoginFlow(): Promise<NextcloudFilesFlowStart> {
|
||||
return request<NextcloudFilesFlowStart>('/connect/flow', { method: 'POST' });
|
||||
}
|
||||
|
||||
export function pollLoginFlow(flowId: string): Promise<NextcloudFilesFlowPoll> {
|
||||
return request<NextcloudFilesFlowPoll>(`/connect/flow/${encodeURIComponent(flowId)}`);
|
||||
}
|
||||
|
||||
export function cancelLoginFlow(flowId: string): Promise<{ cancelled: true }> {
|
||||
return request<{ cancelled: true }>(`/connect/flow/${encodeURIComponent(flowId)}`, {
|
||||
method: 'DELETE',
|
||||
});
|
||||
}
|
||||
|
||||
/** Trennt die Verbindung; die API widerruft den Zugang bei Nextcloud. */
|
||||
export function disconnectNextcloud(): Promise<{ disconnected: true }> {
|
||||
return request<{ disconnected: true }>('/connect', { method: 'DELETE' });
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user