users migrace má nové sloupce gitea_user_id, gitea_sync_status, gitea_sync_error, gitea_synced_at.
Přidal jsem gitea_provisioning.py, který přes Gitea API vytváří, aktivuje, deaktivuje a synchronizuje účty.
Role viewer Gitea účet nemá; developer a admin účet mají.
Změny role a enable/disable v administraci spouští sync do Gitea.
Admin UI v routes/users.py zobrazuje stav Gitea synchronizace a má ruční Sync Gitea.
Google login po přihlášení dorovnává Gitea stav podle portálového uživatele.
Gitea OAuth login je v portálu vypnutý; endpointy zůstaly, ale vrací hlášku, že se má použít Google.
Lokální login se zobrazuje/povolí jen při explicitním AUTH_MODE=local.
Gitea API token se čte z GITEA_ADMIN_TOKEN, případně fallback GITEA_API_TOKEN nebo GITEA_TOKEN. Podřízené Gitea username je deterministicky portal-{user_id}, portálová tabulka zůstává zdroj pravdy.
Ověření: python -m py_compile prošel pro všechny upravené Python soubory.
Přidal jsem AUTH_MODE=google|mixed|local:
google: jen Google login, lokální/Gitea nejdou ani přes přímý endpoint
mixed: Google + lokální/Gitea fallback
local: jen lokální login
Správa uživatelů zůstává admin-only, guard posledního admina platí pro odebrání role i deaktivaci. Přidal jsem do ní i přehled oprávnění rolí a zobrazení provider/avatar metadat.
DB migrace teď přes PRAGMA table_info(users) doplňuje chybějící sloupce bez mazání/recreate existující tabulky; pokud users vůbec neexistuje, bezpečně ji vytvoří. Podporované sloupce zahrnují email, display_name, role, is_enabled, created_at, updated_at, last_login_at, auth_provider, provider_subject, plus kompatibilní sloupce pro lokální login.
tlačítko Přihlásit přes Gitea na login stránku
zachovaný lokální login jako nouzový admin fallback
GET /portal/auth/gitea/login
GET /portal/auth/gitea/callback
OAuth state přes session a ověření přes secrets.compare_digest
výměna code za token a načtení /api/v1/user
mapování Gitea uživatele do users bez ORM
nové Gitea účty dostanou role = developer, existující role se zachová
disabled user is_active = 0 se nepřihlásí
audit eventy auth.gitea.login.started, auth.gitea.login.success, auth.gitea.login.failed
bezpečné chybové hlášky bez detailů a bez zobrazení client secretu