Commit Graph

62 Commits

Author SHA1 Message Date
JiriUhlir 40069c8969 env secrets and variables 2026-06-12 10:45:53 +02:00
JiriUhlir 428d9681e0 gitea sync update 2026-06-12 10:11:33 +02:00
JiriUhlir 5d12028a97 mazani uzivatelu 2026-06-12 09:58:52 +02:00
JiriUhlir ddc65322c5 gitea comm fix 2026-06-12 09:07:42 +02:00
JiriUhlir 061be18857 gitea push 2026-06-11 09:28:56 +02:00
JiriUhlir b1263edac6 Změny:
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.
2026-06-10 09:34:56 +02:00
JiriUhlir 38edf07ff3 Hotovo. V config.py (line 50) jsem upravil default fallbacky:
Google: APPFACTORY_PORTAL_PUBLIC_URL + PORTAL_PREFIX + /auth/google/callback
Gitea: APPFACTORY_PORTAL_PUBLIC_URL + PORTAL_PREFIX + /auth/gitea/callback
Explicitní env hodnoty GOOGLE_REDIRECT_URI a GITEA_OAUTH_REDIRECT_URI zůstávají respektované beze změny. Caddyfile ani login endpointy jsem neupravoval.
2026-06-10 08:55:59 +02:00
JiriUhlir 272b1eb883 Upravil jsem Google OAuth tak, že Google uživatel se hledá/vytváří přes email, ukládá auth_provider='google', provider_subject, display_name, avatar_url a po úspěšném loginu last_login_at. První Google uživatel v prázdné users tabulce dostane admin, další noví Google uživatelé viewer.
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.
2026-06-10 08:37:42 +02:00
JiriUhlir 9cec3d001f sprava uzivatelu 2026-06-10 07:56:02 +02:00
JiriUhlir 7dffff17c7 Odstranil jsem hardcoded IP fallbacky z portálového Python kódu:
DEFAULT_APPFACTORY_HOST = "192.168.66.130" je pryč z config.py (line 10).
DEFAULT_GITEA_URL = "http://192.168.66.130:3000" je pryč z auth.py (line 24).
Doplněné chování:
APPFACTORY_HOST se odvozuje přes helper: env APPFACTORY_HOST, potom APPFACTORY_PORTAL_PUBLIC_URL, potom request host.
Gitea browser redirect používá jen explicitní veřejnou URL z GITEA_URL nebo GITEA_ROOT_URL.
Server-side Gitea token/userinfo requesty používají GITEA_URL, potom GITEA_ROOT_URL, jinak interní Docker URL http://appfactory-gitea:3000.
Gitea login tlačítko se zobrazí jen při kompletní konfiguraci: public URL, client id, client secret a redirect URI.
Přímý Gitea login bez kompletní konfigurace vrací čitelnou chybu.
2026-06-08 11:38:57 +02:00
JiriUhlir 9916e4d833 Změny:
Přidaná centrální runtime konfigurace public URL, HTTPS a Google OAuth readiness v config.py (line 37).
Google OAuth přidaný jako volitelná další možnost přihlášení, bez nahrazení lokálního/Gitea loginu, v auth.py (line 128).
Default Google redirect URI se skládá z APPFACTORY_PORTAL_PUBLIC_URL + /auth/google/callback, bez hardcoded IP/localhost/domény.
Readiness JSON endpoint přidán na /portal/migration-readiness/auth-domain-config; vrací jen boolean hodnoty, žádné secrety, v migration_readiness.py (line 112).
UI sekce Auth & Domain Readiness přidaná do Migration Readiness v migration_readiness.py (line 41).
Audit event auth_domain_readiness.viewed se zapisuje při zobrazení readiness stránky v migration_readiness.py (line 133).
APPFACTORY_ENABLE_HTTPS se promítá i do secure session cookies v main.py (line 19).
2026-06-08 11:21:29 +02:00
JiriUhlir caeb7daf6f mr caddy 2026-06-08 08:20:22 +02:00
JiriUhlir f101d91821 Upraveno. Portál už nečte ani neinterpretuje READY/NOT READY z textu výstupu a nepřidává žádnou logiku pro disk, backup, Gitea ani Registry.
Změny:
migration_readiness.py (line 140) teď určuje READY pouze jako returncode == 0; chybějící nebo nenulový return code je NOT READY.
Preflight UI v routes/migration_readiness.py (line 85) zobrazuje Return code, summary OK/WARN/FAIL a oddělené raw stdout / stderr.
Odstraněná vlastní logika, která hledala READY/NOT READY ve výstupu skriptu.
2026-06-08 08:15:27 +02:00
JiriUhlir 2571e6e50e Bootstrap v2 už nejde spustit bez režimu:
výchozí akce je Run Bootstrap Check s mode=check,
Run Bootstrap Repair je samostatná akce s potvrzením,
Run Bootstrap Deploy je oddělený ve výrazném varování a není defaultní.
2026-06-08 08:08:14 +02:00
JiriUhlir 6622db2fb3 Hotovo. Přidal jsem podporu bootstrap-v2.sh do stránky Migration Readiness.
Co se změnilo:
migration_readiness.py (line 9) nově zná BOOTSTRAP_SCRIPT = "bootstrap-v2.sh".
Helper umí najít poslední job pro bootstrap a připravit status, return code, started_at, finished_at, raw stdout/stderr z DB.
routes/migration_readiness.py (line 111) přidává tlačítko Run Bootstrap v2, které pouze vytvoří run_script job s script_name=bootstrap-v2.sh.
Přidal jsem výrazné varování k bootstrapu a blok “Poslední výsledek Bootstrap v2”.
Zobrazení logů redaktuje env-like citlivé hodnoty typu TOKEN, PASSWORD, SECRET, API_KEY, PRIVATE, CREDENTIAL.
2026-06-08 08:02:56 +02:00
JiriUhlir ad0b35c09f Upraveno. Portál už neurčuje readiness podle job.status == success ani podle žádné Docker/group logiky.
Teď READY / NOT READY bere jen z explicitního výstupu skriptu uloženého v DB:

result_json.ready jako boolean,
result_json.readiness / migration_readiness s hodnotou READY nebo NOT READY,
případně text READY / NOT READY v uloženém raw výstupu jobu.
2026-06-08 07:53:21 +02:00
JiriUhlir 2f5b5bcb89 readinness 2026-06-08 07:49:06 +02:00
JiriUhlir 382825085f Hotovo. Přidal jsem správu Alertingu do appfactory-portal bez ORM:
Nové SQL migrace pro alert_rules a alert_events v migrations.py (line 165).
Nová ruční DB vrstva v alerting.py (line 7).
Nové stránky a akce v routes/alerting.py (line 288):Alert pravidla, detail, vytvoření, úprava, smazání
povolit/zakázat pravidlo
Alert eventy a detail eventu s payload_json
odkazy z job_id na detail úlohy
detail pravidla s posledními eventy
admin-only editor .sh alert skriptů v /opt/appfactory/workspace/appfactory-tools/alerts
audit eventy podle zadání

Menu Provoz → Alerting v layout.py (line 23).
Router je zaregistrovaný v main.py (line 8).
2026-06-08 06:57:12 +02:00
JiriUhlir 64f8fe806d Hotovo. Do detailu plánovaného skriptu jsem přidal sekci Obsah skriptu.
Implementováno v app/routes/scheduled_scripts.py:
bezpečné načtení pouze z /opt/appfactory/workspace/appfactory-tools/maintenance/{script_name},
validace script_name: .sh, bez /, \, .., neprázdné,
zobrazení obsahu v textarea,
pokud soubor neexistuje, zobrazí se hláška a výchozí obsah:bash

#!/usr/bin/env bash
set -euo pipefail

echo "TODO"

admin může obsah uložit přes POST /portal/scheduled-scripts/{id}/script,
neadmin vidí read-only editor,
obsah nesmí být prázdný ani větší než 100 KB,
pokud chybí shebang #!/usr/bin/env bash, automaticky se doplní,
po uložení se nastaví chmod 755,
audit event scheduled_script.file_updated s scheduled_script_id a script_name.
Tlačítko Spustit nyní zůstává na detailu dostupné.
2026-06-03 12:33:37 +02:00
JiriUhlir f7a8007af8 Změny:
Nový DB helper bez ORM: app/db/scheduled_scripts.py
Nové route/UI: app/routes/scheduled_scripts.py
Router registrovaný v app/main.py
Menu doplněné v app/templates/layout.py
Job filtr rozšířený o run_script v app/routes/jobs.py
Implementováno:
GET /portal/scheduled-scripts
GET /portal/scheduled-scripts/{id}
GET/POST /portal/scheduled-scripts/new
GET/POST /portal/scheduled-scripts/{id}/edit
POST /portal/scheduled-scripts/{id}/run-now
POST /portal/scheduled-scripts/{id}/toggle
POST /portal/scheduled-scripts/{id}/delete
Ruční spuštění vytváří run_script job přes existující create_job(...) se source="portal_manual" a payloadem podle zadání. Mazání je blokované, pokud is_running = 1. Validace script_name, schedule_type a timeout_seconds je v route vrstvě.
Audit eventy jsou přidané:
scheduled_script.created
scheduled_script.updated
scheduled_script.deleted
scheduled_script.enabled
scheduled_script.disabled
scheduled_script.run_now
2026-06-03 12:18:39 +02:00
JiriUhlir 46f8024d4e Register apps before queued deployment 2026-06-03 10:38:23 +02:00
JiriUhlir 0a37507d86 Změny:
NEW_APP_SCRIPT odstraněn z app/config.py.
create_app už volá skeleton přes app_templates.create_script:načte template podle ID,
ověří is_enabled = 1 a create_enabled = 1 přes get_app_template(..., create_enabled=True),
ověří neprázdný create_script,
volá [create_script, app_id, app_name].

runtime, language, container_port, health_url dál bere z vybraného template řádku.
DB helper a migrace znají nové sloupce create_script a deploy_script.
deploy_script se při create použije, pokud je v template vyplněný; jinak zůstává dosavadní deploy fallback.
2026-06-03 09:23:59 +02:00
JiriUhlir 54c86702d2 Co se změnilo:
app_templates je teď jediný source of truth.
Detail služby načítá šablony přes is_enabled = 1.
Vytvoření služby načítá šablony přes is_enabled = 1 AND create_enabled = 1.
Select hodnoty používají app_templates.id, takže fastapi odpovídá existující službě microsoft-365-service.
Při vytvoření služby se z vybrané šablony nastaví template, runtime, language, container_port a health_url.
Neznámá šablona se zobrazí jako Neznámá šablona a detail nespadne.
Hardcoded python-fastapi / seznam šablon byl odstraněn.
2026-06-03 09:02:36 +02:00
JiriUhlir 786d055f6b Přidáno:
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
2026-06-01 13:53:06 +02:00
JiriUhlir 6aa5e69ee4 Přidáno:
nová stránka /portal/incidents s title CSBot Services Portal - Incidenty
menu Provoz -> Incidenty
aktivní incidenty a historie posledních 100 incidentů
barevné stavy: open červeně, resolved zeleně
karta Aktivní incidenty a seznam Poslední incidenty na přehledu
realtime napojení přes existující operations-live.js a snapshot
sekce Incidenty služby v detailu služby, posledních 20 incidentů
DB helpery pro service_incidents
migrace/indexy pro lokální prostředí, kde tabulka ještě neexistuje
2026-06-01 13:38:06 +02:00
JiriUhlir 994171be1a feat(portal): add app metadata and variables management 2026-06-01 13:13:17 +02:00
JiriUhlir 1ade865df4 update seznamu sluzeb 2026-05-29 12:07:13 +02:00
JiriUhlir ed194093e6 Přidal jsem Health Monitoring do portálu:
Přehled má nové karty: Zdravé služby, Nezdravé služby, Nedostupné služby.
Přehled zobrazuje sekci Služby vyžadující pozornost pro unhealthy a unreachable.
Snapshot /portal/ws/operations teď obsahuje health data a stránka je aktualizuje přes existující realtime vrstvu.
Seznam služeb zobrazuje aktuální health status a poslední kontrolu, včetně řazení Podle zdraví.
Detail služby má sekce Zdraví služby a Historie kontrol s posledními 50 záznamy.
Přidal jsem audit event service.health.view.
Browser title teď používá formát CSBot Services Portal - ..., takže detail služby odpovídá požadavku.
Nepoužil jsem ORM, vše je přes SQLite dotazy.
2026-05-29 11:57:57 +02:00
JiriUhlir 56f0b632de navigace 2026-05-29 11:42:46 +02:00
JiriUhlir 064ae93831 Upravil jsem:
responzivitu layoutu, menu, karet, filtrů, tlačítek, tabulek a log panelů v styles.css
tabulky se na menších šířkách horizontálně posouvají místo rozbíjení layoutu
menu má teď přímé položky Přehled, Služby a rozbalovací skupiny Provoz, Správa
stránkování se vůbec nezobrazuje, pokud existuje jen jedna stránka
Předchozí / Další se nezobrazují, když daný směr není dostupný
odstranil jsem staré neaktivní disabled pagination odkazy
2026-05-29 11:40:09 +02:00
JiriUhlir 6109bdfe61 cestina, UI, UX 2026-05-29 11:34:07 +02:00
JiriUhlir d145161e4e Add unified operations realtime dashboard
- add /portal/ws/operations WebSocket snapshot endpoint
- add shared operations-live.js with reconnect and operations:snapshot events
- update Operations, Jobs, and Workers pages to use realtime snapshots
- keep job detail live logs on dedicated /ws/jobs/{job_id}/logs endpoint
- add Jobs and Workers pagination/filtering
- remove old page auto-refresh behavior from jobs/deployments
- normalize main navigation labels
- move New App CTA from menu to Apps page
- add backup download action for admins
- add Workers pages and operations dashboard data helpers
2026-05-29 11:17:17 +02:00
JiriUhlir 0dcf9b7b05 life jobs logs 2026-05-29 11:02:43 +02:00
JiriUhlir e3019bd76e download backup admin possibility 2026-05-29 10:56:20 +02:00
JiriUhlir 6e5d9b3120 operations 2026-05-29 10:44:25 +02:00
JiriUhlir 3804bb32c4 workers fix 2026-05-29 10:40:15 +02:00
JiriUhlir 48a9b20379 workers 2026-05-29 10:35:56 +02:00
JiriUhlir 765c840120 kontrola na jobs na nedoployovatelne repositare 2026-05-29 09:30:54 +02:00
JiriUhlir 4b4bf55696 filtry v jobs a shrnuti 2026-05-29 09:23:36 +02:00
JiriUhlir f651f7efd6 added jobs handling. 2026-05-29 09:16:37 +02:00
JiriUhlir 88601451dc Implementována portálová část SQLite job queue.
Přidán DB helper pro jobs a job_logs bez ORM.
Přidána idempotentní migrace pro job tabulky včetně created_by_display_name.
Přidány stránky /portal/jobs a /portal/jobs/{id}.
Jobs page zobrazuje status, type, target, source, created_by, created_at, started_at, finished_at.
Job detail zobrazuje payload, result/error a job_logs.
Queued/running joby mají auto-refresh po 5 s.
Navigace portálu obsahuje odkaz na Joby.
App redeploy už nespouští deploy script přímo; vytváří queued job deploy_app s prázdným payloadem.
Po redeploy se uživatel přesměruje na detail jobu.
Přidán audit event app.redeploy.queued s metadata={"job_id": job_id}.
Přidána ochrana proti duplicitnímu aktivnímu deploy jobu pro stejnou appku.
2026-05-28 14:02:49 +02:00
JiriUhlir 17a4d4db1b copying, evidovat btn hidden 2026-05-28 13:33:22 +02:00
JiriUhlir 8624352253 strankovani u deploys a styly pro pocitadla 2026-05-28 13:26:58 +02:00
JiriUhlir e6ffeb8fef deployment observability, filters, stats, details 2026-05-28 13:22:51 +02:00
JiriUhlir 80d82d36dd audit logging 2026-05-28 11:49:59 +02:00
JiriUhlir f18aabb5ba Add portal authentication and removed deploy old templates 2026-05-28 11:45:29 +02:00
JiriUhlir aa103bc129 Merge branch 'main' of http://192.168.66.130:3000/appfactory/appfactory-portal 2026-05-28 11:40:52 +02:00
JiriUhlir 09c742fefb auth via DB 2026-05-28 11:40:49 +02:00
AppFactory Bot 915ee48131 Use database as apps source and add deployments UI 2026-05-28 10:14:22 +02:00
JiriUhlir db039e5988 Read apps and resources from database 2026-05-28 10:11:31 +02:00