feat(auth): admin Users page + allow_registration toggle (5a frontend)

New admin-only Users page (sidebar): Users & roles (list + promote/demote with
confirm; self/demo/last-admin guarded server-side), plus the Access requests
(Invite whitelist) and Demo whitelist+reset migrated out of Settings → Account
(same data/tables — UI relocated only). Settings → Account now holds personal
content only. ConfigPanel learns a boolean field type (toggle) for the new
allow_registration setting. api methods, new 'users' page/route/nav/header, and
EN/HU/DE strings (new users namespace + access group).
This commit is contained in:
npeter83 2026-06-19 14:16:48 +02:00
parent 8f5e26d2ee
commit a2f61a827e
17 changed files with 528 additions and 281 deletions

View file

@ -2,6 +2,7 @@
"intro": "In der Datenbank gespeicherte Betriebseinstellungen — sie überschreiben die Datei-/Env-Standardwerte und wirken ohne erneutes Deployment. Lass ein Feld leer (oder setze es zurück), um auf den Standard zurückzufallen.",
"loading": "Konfiguration wird geladen…",
"groups": {
"access": "Zugang",
"email": "E-Mail / SMTP",
"youtube": "YouTube-API",
"quota": "Kontingent",
@ -23,7 +24,8 @@
"shorts_probe_batch": { "label": "Shorts-Prüfung — Stapelgröße", "hint": "Wie viele Videos pro Lauf klassifiziert werden." },
"enrich_batch_size": { "label": "Anreicherungs-Stapelgröße", "hint": "videos.list-IDs pro Aufruf (YouTube begrenzt auf 50)." },
"autotag_title_sample": { "label": "Auto-Tag-Titelstichprobe", "hint": "Pro Kanal abgetastete aktuelle Videotitel zur Spracherkennung." },
"youtube_api_key": { "label": "YouTube-API-Schlüssel", "hint": "Optional. Für öffentliche Lesezugriffe (Kanäle/Videos), damit gemeinsames Nachladen nicht vom OAuth eines Nutzers abhängt. Verschlüsselt gespeichert; nur schreibbar." }
"youtube_api_key": { "label": "YouTube-API-Schlüssel", "hint": "Optional. Für öffentliche Lesezugriffe (Kanäle/Videos), damit gemeinsames Nachladen nicht vom OAuth eines Nutzers abhängt. Verschlüsselt gespeichert; nur schreibbar." },
"allow_registration": { "label": "Registrierung erlauben", "hint": "Wenn aktiviert, kann jeder eine E-Mail+Passwort-Registrierung einreichen. Für die Anmeldung sind weiterhin E-Mail-Bestätigung und Admin-Freigabe nötig." }
},
"save": "Speichern",
"saving": "Speichern…",

View file

@ -5,6 +5,7 @@
"usageStats": "Nutzung & Statistik",
"scheduler": "Planer",
"configuration": "Konfiguration",
"users": "Benutzer",
"scope": {
"label": "Feed-Quelle",
"my": "Meine",
@ -20,6 +21,7 @@
"stats": "Statistik",
"scheduler": "Planer",
"config": "Konfiguration",
"users": "Benutzer",
"settings": "Einstellungen",
"about": "Über",
"signOut": "Abmelden",

View file

@ -0,0 +1,21 @@
{
"roles": {
"title": "Benutzer & Rollen",
"intro": "Alle, die sich anmelden können. Mache einen Benutzer zum Admin oder wieder zum normalen Benutzer.",
"empty": "Noch keine Benutzer.",
"you": "du",
"admin": "Admin",
"demo": "Demo",
"pending": "Wartet auf Freigabe",
"unverified": "E-Mail nicht bestätigt",
"demoLocked": "Die Rolle des Demo-Kontos kann nicht geändert werden.",
"selfLocked": "Du kannst deine eigene Rolle nicht ändern.",
"makeAdmin": "Zum Admin machen",
"makeUser": "Zum Benutzer machen",
"updated": "Rolle aktualisiert",
"promoteTitle": "Zum Admin machen?",
"demoteTitle": "Admin entfernen?",
"promoteConfirm": "{{email}} vollen Admin-Zugriff geben (Einstellungen, Planer, Benutzerverwaltung)?",
"demoteConfirm": "{{email}} den Admin-Zugriff entziehen? Wird zum normalen Benutzer."
}
}

View file

@ -2,6 +2,7 @@
"intro": "Operational settings stored in the database — these override the file/env defaults and take effect without a redeploy. Leave a field empty (or reset it) to fall back to the default.",
"loading": "Loading configuration…",
"groups": {
"access": "Access",
"email": "Email / SMTP",
"youtube": "YouTube API",
"quota": "Quota",
@ -23,7 +24,8 @@
"shorts_probe_batch": { "label": "Shorts probe — batch size", "hint": "How many videos to classify per run." },
"enrich_batch_size": { "label": "Enrichment batch size", "hint": "videos.list ids per call (YouTube caps this at 50)." },
"autotag_title_sample": { "label": "Auto-tag title sample", "hint": "Recent video titles sampled per channel for language detection." },
"youtube_api_key": { "label": "YouTube API key", "hint": "Optional. Used for public reads (channels/videos) so shared backfill doesn't depend on a user's OAuth. Stored encrypted; write-only." }
"youtube_api_key": { "label": "YouTube API key", "hint": "Optional. Used for public reads (channels/videos) so shared backfill doesn't depend on a user's OAuth. Stored encrypted; write-only." },
"allow_registration": { "label": "Allow registration", "hint": "When on, anyone can submit an email+password registration. They still need to verify their email and be approved by an admin before they can sign in." }
},
"save": "Save",
"saving": "Saving…",

View file

@ -5,6 +5,7 @@
"usageStats": "Usage & stats",
"scheduler": "Scheduler",
"configuration": "Configuration",
"users": "Users",
"scope": {
"label": "Feed source",
"my": "Mine",
@ -20,6 +21,7 @@
"stats": "Stats",
"scheduler": "Scheduler",
"config": "Configuration",
"users": "Users",
"settings": "Settings",
"about": "About",
"signOut": "Sign out",

View file

@ -0,0 +1,21 @@
{
"roles": {
"title": "Users & roles",
"intro": "Everyone who can sign in. Promote a user to admin, or back to a regular user.",
"empty": "No users yet.",
"you": "you",
"admin": "Admin",
"demo": "Demo",
"pending": "Pending approval",
"unverified": "Unverified email",
"demoLocked": "The demo account's role can't be changed.",
"selfLocked": "You can't change your own role.",
"makeAdmin": "Make admin",
"makeUser": "Make user",
"updated": "Role updated",
"promoteTitle": "Make admin?",
"demoteTitle": "Remove admin?",
"promoteConfirm": "Give {{email}} full admin access (settings, scheduler, user management)?",
"demoteConfirm": "Remove admin access from {{email}}? They'll become a regular user."
}
}

View file

@ -2,6 +2,7 @@
"intro": "Az adatbázisban tárolt működési beállítások — felülírják a fájl/env alapértékeket, és újratelepítés nélkül lépnek életbe. Hagyd üresen (vagy állítsd vissza) a mezőt az alapértékhez való visszatéréshez.",
"loading": "Konfiguráció betöltése…",
"groups": {
"access": "Hozzáférés",
"email": "E-mail / SMTP",
"youtube": "YouTube API",
"quota": "Kvóta",
@ -23,7 +24,8 @@
"shorts_probe_batch": { "label": "Shorts-vizsgálat — kötegméret", "hint": "Futásonként ennyi videót osztályozunk." },
"enrich_batch_size": { "label": "Gazdagítási kötegméret", "hint": "videos.list azonosítók hívásonként (a YouTube 50-ben maximálja)." },
"autotag_title_sample": { "label": "Auto-címke címmintavétel", "hint": "Csatornánként ennyi friss videócímet mintázunk a nyelvfelismeréshez." },
"youtube_api_key": { "label": "YouTube API-kulcs", "hint": "Opcionális. Publikus olvasásokhoz (csatornák/videók), hogy a megosztott letöltés ne függjön egy felhasználó OAuth-jától. Titkosítva tárolva; csak írható." }
"youtube_api_key": { "label": "YouTube API-kulcs", "hint": "Opcionális. Publikus olvasásokhoz (csatornák/videók), hogy a megosztott letöltés ne függjön egy felhasználó OAuth-jától. Titkosítva tárolva; csak írható." },
"allow_registration": { "label": "Regisztráció engedélyezése", "hint": "Bekapcsolva bárki beküldhet email+jelszó regisztrációt. Belépéshez továbbra is email-igazolás és admin-jóváhagyás szükséges." }
},
"save": "Mentés",
"saving": "Mentés…",

View file

@ -5,6 +5,7 @@
"usageStats": "Használat és statisztika",
"scheduler": "Ütemező",
"configuration": "Konfiguráció",
"users": "Felhasználók",
"scope": {
"label": "Hírfolyam forrása",
"my": "Sajátom",
@ -20,6 +21,7 @@
"stats": "Statisztika",
"scheduler": "Ütemező",
"config": "Konfiguráció",
"users": "Felhasználók",
"settings": "Beállítások",
"about": "Névjegy",
"signOut": "Kijelentkezés",

View file

@ -0,0 +1,21 @@
{
"roles": {
"title": "Felhasználók és szerepek",
"intro": "Mindenki, aki be tud lépni. Léptess egy felhasználót adminná, vagy vissza sima felhasználóvá.",
"empty": "Még nincs felhasználó.",
"you": "te",
"admin": "Admin",
"demo": "Demo",
"pending": "Jóváhagyásra vár",
"unverified": "Nem igazolt e-mail",
"demoLocked": "A demo fiók szerepe nem módosítható.",
"selfLocked": "A saját szerepedet nem módosíthatod.",
"makeAdmin": "Adminná tesz",
"makeUser": "Felhasználóvá tesz",
"updated": "Szerep frissítve",
"promoteTitle": "Adminná teszed?",
"demoteTitle": "Elveszed az admin jogot?",
"promoteConfirm": "Teljes admin hozzáférést adsz neki: {{email}} (beállítások, ütemező, felhasználókezelés)?",
"demoteConfirm": "Elveszed az admin jogot tőle: {{email}}? Sima felhasználó lesz."
}
}