Any authenticated user can invite an e-mail address; the mailed single-use token lets exactly one signup through even while registration is closed. Open (pending, unexpired) invitations count against the new instance setting invitations.maxOpenPerUser (default 5, 0 disables inviting) — plus a 20/day per-user rate limit so a revoke-and-recreate loop cannot become a mail cannon. Only the SHA-256 token hash is stored (auth-tokens pattern); a failed signup (taken username) un-redeems the token so the invitee can retry. Surfaces: invitations section in the user settings (list, invite, revoke, quota line; wide table in a focusable .table-scroll region), signup page reads ?invitation=<token> (preview banner, e-mail prefill, closed-mode gate opens only for a previewed-valid token), admin general card gets the quota field (flat RHF name per #322; VS-NfD marked and hideable). Governance: audit actions invitation.created/revoked/accepted (catalogue 1.10), VS-NfD profile entry (compliant: 0) + hardening-guide row, i18n de+en including the invitation mail template. Tests: api e2e-db (mail link, closed-mode single-use signup with un-redeem on failure, quota + revoke frees slot, quota 0 = 403, auth matrix), new web e2e pack invitations.spec.ts (full UI loop through Mailpit, wired into ci.yml with its own rate-limit reset), a11y scan waits for the new section. Full api suite (107 files / 607 tests), auth/admin-settings/a11y packs green against a fresh local stack. Closes #332
71 lines
3.8 KiB
JSON
71 lines
3.8 KiB
JSON
{
|
|
"common": {
|
|
"greeting": "Hallo {{displayName}},",
|
|
"signoff": "Dein Dorfteich",
|
|
"ignoreHint": "Falls du diese E-Mail nicht angefordert hast, kannst du sie einfach ignorieren."
|
|
},
|
|
"verifyEmail": {
|
|
"subject": "Bestätige deine E-Mail-Adresse",
|
|
"body": "willkommen im Dorfteich! Bitte bestätige deine E-Mail-Adresse, um dein Konto zu aktivieren:",
|
|
"action": "E-Mail-Adresse bestätigen",
|
|
"expiry": "Der Link ist 24 Stunden gültig."
|
|
},
|
|
"resetPassword": {
|
|
"subject": "Passwort zurücksetzen",
|
|
"body": "jemand (hoffentlich du) hat das Zurücksetzen des Passworts für dein Konto angefordert. Über diesen Link kannst du ein neues Passwort setzen:",
|
|
"action": "Neues Passwort setzen",
|
|
"expiry": "Der Link ist eine Stunde gültig. Dein aktuelles Passwort bleibt gültig, bis du ein neues gesetzt hast."
|
|
},
|
|
"invitation": {
|
|
"subject": "Du bist eingeladen: Dorfteich",
|
|
"body": "{{inviterName}} lädt dich zu einem Dorfteich ein — einem gemeinsamen Ort für Seiten und Notizen. Über diesen Link kannst du dir ein Konto anlegen:",
|
|
"action": "Einladung annehmen",
|
|
"expiry": "Der Link ist 14 Tage gültig und kann nur einmal verwendet werden."
|
|
},
|
|
"smtpTest": {
|
|
"subject": "SMTP-Testnachricht",
|
|
"body": "diese Testnachricht bestätigt, dass dein Dorfteich E-Mails über den konfigurierten SMTP-Server versenden kann. Deine Instanz erreichst du hier:",
|
|
"action": "Dorfteich öffnen",
|
|
"expiry": "Du kannst diese E-Mail einfach löschen."
|
|
},
|
|
"backupFailed": {
|
|
"subject": "[{{instance}}] Backup fehlgeschlagen ({{backupId}})",
|
|
"intro": "Der nächtliche Backup-Lauf auf {{instance}} ist fehlgeschlagen.",
|
|
"backupId": "Backup-ID: {{backupId}}",
|
|
"error": "Fehler: {{error}}",
|
|
"lastSuccess": "Letztes erfolgreiches Backup: {{finishedAt}}",
|
|
"lastSuccessNever": "Letztes erfolgreiches Backup: noch keines",
|
|
"hint": "Prüfe die Sidecar-Logs (docker compose logs backup) und die status.json auf dem Backups-Volume."
|
|
},
|
|
"backupUploadFailed": {
|
|
"subject": "[{{instance}}] Backup-Upload zu Nextcloud fehlgeschlagen ({{backupId}})",
|
|
"intro": "Das lokale Backup auf {{instance}} war erfolgreich, aber der Upload zum Nextcloud-Ziel ist fehlgeschlagen.",
|
|
"backupId": "Backup-ID: {{backupId}}",
|
|
"error": "Fehler: {{error}}",
|
|
"lastSuccess": "Letzter erfolgreicher Upload: {{finishedAt}}",
|
|
"lastSuccessNever": "Letzter erfolgreicher Upload: noch keiner",
|
|
"hint": "Prüfe die Nextcloud-Verbindungseinstellungen im Admin-Bereich (Verbindungstest) und die Sidecar-Logs (docker compose logs backup)."
|
|
},
|
|
"backupMirrorFailed": {
|
|
"subject": "[{{instance}}] Backup-Spiegelung zum privaten Host fehlgeschlagen",
|
|
"intro": "Das lokale Backup auf {{instance}} war erfolgreich, aber die Spiegelung der Sets per rsync ist fehlgeschlagen.",
|
|
"backupId": "Komponente: rsync-Mirror (Issue #84)",
|
|
"error": "Fehler: {{error}}",
|
|
"lastSuccess": "Letzte erfolgreiche Spiegelung: {{finishedAt}}",
|
|
"lastSuccessNever": "Letzte erfolgreiche Spiegelung: noch keine",
|
|
"hint": "Prüfe den Tunnel zum Mirror-Host, den SSH-Key im Secrets-Volume und die Sidecar-Logs (docker compose logs backup). Einrichtung: deploy/backup-basel.md."
|
|
},
|
|
"digest": {
|
|
"subject": "Dorfteich: {{count}} Neuigkeiten für dich",
|
|
"intro": "Das ist auf von dir beobachteten Seiten passiert ({{count}} Neuigkeiten):",
|
|
"changes_one": "{{count}} Änderung",
|
|
"changes_other": "{{count}} Änderungen",
|
|
"comments_one": "{{count}} Kommentar",
|
|
"comments_other": "{{count}} Kommentare",
|
|
"openApp": "Dorfteich öffnen: {{link}}",
|
|
"unsubscribe": "Diese Digest-Mails abbestellen: {{link}}",
|
|
"unsubscribedTitle": "Digest-Mails deaktiviert",
|
|
"unsubscribedBody": "Du erhältst keine Benachrichtigungs-Digests mehr. In den Konto-Einstellungen kannst du sie nach der Anmeldung jederzeit wieder aktivieren."
|
|
}
|
|
}
|