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:
@@ -7,6 +7,8 @@ import { SettingsSection } from '@/components/control-center/settings-section';
|
||||
import { PageHeader } from '@/components/layout/page-header';
|
||||
import { getNextcloudFilesStatus, type NextcloudFilesStatus } from '@/lib/nextcloud-files-api';
|
||||
import { useCanManageModule } from '@/lib/use-module-capability';
|
||||
import { AccountBar } from './components/AccountBar';
|
||||
import { ConnectPanel } from './components/ConnectPanel';
|
||||
import { SettingsTab } from './components/SettingsTab';
|
||||
|
||||
type TabId = 'files' | 'settings';
|
||||
@@ -15,9 +17,10 @@ type TabId = 'files' | 'settings';
|
||||
* Dateien (quick-261008-mzu): die Nextcloud-Dateien jedes Benutzers in Tessera.
|
||||
* Die Adresse der Nextcloud stellen Administratoren und Benutzer mit der
|
||||
* Freigabestufe Verwalten im Reiter "Einstellungen" ein; alle anderen sehen nur
|
||||
* den Reiter "Dateien" ohne Reiterleiste — bindend ist allein die API. Der
|
||||
* Abschnitt `nextcloud-files-main` ist die Stelle, an der das Verbinden des
|
||||
* eigenen Kontos und der Dateibrowser eingehaengt werden.
|
||||
* den Reiter "Dateien" ohne Reiterleiste — bindend ist allein die API. Im
|
||||
* Abschnitt `nextcloud-files-main` verbindet jeder Benutzer sein eigenes Konto
|
||||
* (ConnectPanel); ist es verbunden, steht dort der Dateibereich
|
||||
* (`nextcloud-files-browser`, den die Dateiansicht fuellt).
|
||||
*/
|
||||
export default function NextcloudFilesPage() {
|
||||
const t = useTranslations('nextcloudFiles');
|
||||
@@ -40,13 +43,25 @@ export default function NextcloudFilesPage() {
|
||||
void reloadStatus();
|
||||
}, [reloadStatus]);
|
||||
|
||||
const account = status?.account ?? null;
|
||||
const connected = account?.connected === true;
|
||||
|
||||
const tabs: { id: TabId; label: string }[] = [{ id: 'files', label: t('tabs.files') }];
|
||||
if (canManage) tabs.push({ id: 'settings', label: t('tabs.settings') });
|
||||
const activeTab: TabId = tabs.some((x) => x.id === tab) ? tab : 'files';
|
||||
|
||||
return (
|
||||
<div className="mx-auto max-w-6xl space-y-6 p-3 sm:p-6">
|
||||
<PageHeader moduleSlug="nextcloud-files" title={t('title')} description={t('description')} />
|
||||
<PageHeader
|
||||
moduleSlug="nextcloud-files"
|
||||
title={t('title')}
|
||||
description={t('description')}
|
||||
actions={
|
||||
activeTab === 'files' && status?.configured && account && connected ? (
|
||||
<AccountBar account={account} host={status.host} onDisconnected={reloadStatus} />
|
||||
) : undefined
|
||||
}
|
||||
/>
|
||||
{statusError && (
|
||||
<p role="alert" className="text-sm text-destructive">
|
||||
{t('errors.loadStatus')}
|
||||
@@ -71,9 +86,19 @@ export default function NextcloudFilesPage() {
|
||||
)}
|
||||
{activeTab === 'files' && status?.configured && (
|
||||
<section data-testid="nextcloud-files-main" className="space-y-4">
|
||||
<p className="text-sm text-muted-foreground">
|
||||
{t('main.server', { host: status.host ?? '' })}
|
||||
</p>
|
||||
{connected ? (
|
||||
<div data-testid="nextcloud-files-browser">
|
||||
<p className="text-sm text-muted-foreground">
|
||||
{t('main.server', { host: status.host ?? '' })}
|
||||
</p>
|
||||
</div>
|
||||
) : (
|
||||
<ConnectPanel
|
||||
host={status.host}
|
||||
expired={account?.expired === true}
|
||||
onConnected={reloadStatus}
|
||||
/>
|
||||
)}
|
||||
</section>
|
||||
)}
|
||||
{activeTab === 'settings' && canManage && (
|
||||
|
||||
Reference in New Issue
Block a user