Release / verify (push) Canceled after 0s
CI / checks (push) Canceled after 0s
CI / frontend (push) Canceled after 0s
CI / backend (push) Canceled after 0s
Release / test (push) Canceled after 0s
Release / publish (backend) (push) Canceled after 0s
Release / publish (frontend) (push) Canceled after 0s
Release / publish (proxy) (push) Canceled after 0s
Release / publish (updater) (push) Canceled after 0s
Erste Schritte nach der Installation. Ende-zu-Ende gegen einen isolierten Stack getestet, siehe Handbuch „Einrichtungsassistent und Passwort-Reset“: - **Einrichtungsassistent** (`/setup`, System › Einrichtung): vier Schritte mit Erklärungen — Willkommen und Sprache, Konto (eigenes Passwort, Zwei-Faktor-Anmeldung), erste Firewall verbinden (inklusive Anleitung für den API-Key in OPNsense, Zertifikat festsetzen, Verbindungsstatus) und eine Übersicht, was als Nächstes sinnvoll ist. Auf einer frischen Installation ohne Hosts öffnet er sich nach der ersten Anmeldung von selbst; „Assistent überspringen“ merkt sich das pro Benutzer, erneut öffnen geht jederzeit über System › Einrichtung oder die Einstellungen. Nur für Admins. Neue Spalte `user_preferences.setup_done` (Migration `0005`). - **`opnexus password [NAME]`** setzt ein neues Zufallspasswort für den Admin und zeigt es an (`--yes` ohne Rückfrage; Rückfrage nur, wenn sich schon jemand angemeldet hat). Ersetzt das Suchen im Backend-Log nach dem beim ersten Start erzeugten Passwort und taugt zugleich für ein vergessenes Admin-Passwort. Alle Sitzungen des Kontos enden. Dahinter steht `python -m app.reset_password`. Die Meldung beim ersten Start verweist darauf.
40 lines
2.1 KiB
Python
40 lines
2.1 KiB
Python
from typing import Literal
|
|
from fastapi import APIRouter, Depends
|
|
from pydantic import BaseModel
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
from sqlalchemy.dialects.postgresql import insert
|
|
from app.config import settings
|
|
from app.database import get_db
|
|
from app.models.preferences import UserPreferences
|
|
from app.models.user import AdminUser
|
|
from app.routers.auth import current_user
|
|
|
|
router=APIRouter(prefix='/settings',tags=['settings'])
|
|
|
|
class Preferences(BaseModel):
|
|
theme: Literal['light','dark','system'] | None = None
|
|
language: Literal['de','en'] | None = None
|
|
setup_done: bool | None = None
|
|
|
|
@router.get('')
|
|
async def read(user: AdminUser=Depends(current_user),db:AsyncSession=Depends(get_db)):
|
|
preferences=await db.get(UserPreferences,user.id)
|
|
return {'username':user.username,'theme':preferences.theme if preferences else 'system',
|
|
'language':preferences.language if preferences else 'de',
|
|
'setup_done':preferences.setup_done if preferences else False,
|
|
'deploy_confirm_window_seconds':settings.deploy_confirm_window_seconds,
|
|
'session_lifetime_seconds':settings.session_lifetime}
|
|
|
|
@router.put('')
|
|
async def update(payload:Preferences,user:AdminUser=Depends(current_user),db:AsyncSession=Depends(get_db)):
|
|
username = user.username
|
|
current = await db.get(UserPreferences, user.id)
|
|
theme = payload.theme or (current.theme if current else 'system')
|
|
language = payload.language or (current.language if current else 'de')
|
|
setup_done = payload.setup_done if payload.setup_done is not None else bool(current.setup_done if current else False)
|
|
await db.execute(insert(UserPreferences).values(user_id=user.id,theme=theme,language=language,setup_done=setup_done).on_conflict_do_update(index_elements=['user_id'],set_={'theme':theme,'language':language,'setup_done':setup_done}))
|
|
await db.commit()
|
|
return {'username':username,'theme':theme,'language':language,'setup_done':setup_done,
|
|
'deploy_confirm_window_seconds':settings.deploy_confirm_window_seconds,
|
|
'session_lifetime_seconds':settings.session_lifetime}
|