Nouveau service apps/admin (admin.metalfrom.eu / admin.dev.metalfrom.eu) : - Frontend statique vanilla JS/CSS reprenant le design system du site (login, dashboard stats, table bands éditable, queue d'enrichissement, historique crawl_run, logs live, checkpoints, journal d'audit) - nginx reverse-proxy /admin/api/* et /admin/auth/* vers le service api interne (same-origin côté navigateur, pas de CORS cross-site nécessaire pour le cookie de session) apps/api : - Nouvelle auth dédiée au dashboard, séparée du token BM_IMPORT_TOKEN existant : login bcrypt + session JWT en cookie httpOnly/secure/ sameSite=strict, rate-limit + lockout après 5 échecs/15min, seeding du compte admin via env vars (jamais de mot de passe en clair en DB ou en git) - Routes /admin/api/* : stats, queue (breakdown priorité identique au crawler Python), bands (recherche/tri/pagination/édition + audit log), crawl-runs, crawl-checkpoints, logs, audit-log - trustProxy activé (Traefik + nginx en amont) apps/crawler : - log_event() écrit dans la nouvelle table crawl_log (run start/finish/ erreurs) pour que le dashboard affiche les logs sans exposer le socket Docker (choix délibéré : pas de docker.sock monté, accès DB only) migration 006_admin_dashboard.sql : admin_users, admin_login_attempts, admin_audit_log, crawl_log Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
42 lines
1.4 KiB
SQL
42 lines
1.4 KiB
SQL
-- 006: tables pour le dashboard admin (auth, audit, logs crawler)
|
|
|
|
CREATE TABLE IF NOT EXISTS admin_users (
|
|
id BIGSERIAL PRIMARY KEY,
|
|
username TEXT UNIQUE NOT NULL,
|
|
password_hash TEXT NOT NULL,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
last_login_at TIMESTAMPTZ
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS admin_login_attempts (
|
|
id BIGSERIAL PRIMARY KEY,
|
|
username TEXT NOT NULL,
|
|
ip TEXT,
|
|
success BOOLEAN NOT NULL,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
);
|
|
CREATE INDEX IF NOT EXISTS idx_admin_login_attempts_username_time
|
|
ON admin_login_attempts (username, created_at DESC);
|
|
|
|
CREATE TABLE IF NOT EXISTS admin_audit_log (
|
|
id BIGSERIAL PRIMARY KEY,
|
|
admin_username TEXT NOT NULL,
|
|
action TEXT NOT NULL,
|
|
target_table TEXT NOT NULL,
|
|
target_id TEXT,
|
|
before_data JSONB,
|
|
after_data JSONB,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
);
|
|
CREATE INDEX IF NOT EXISTS idx_admin_audit_log_created_at ON admin_audit_log (created_at DESC);
|
|
|
|
CREATE TABLE IF NOT EXISTS crawl_log (
|
|
id BIGSERIAL PRIMARY KEY,
|
|
run_id BIGINT REFERENCES crawl_run(id) ON DELETE SET NULL,
|
|
level TEXT NOT NULL DEFAULT 'info',
|
|
message TEXT NOT NULL,
|
|
ma_id BIGINT,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
);
|
|
CREATE INDEX IF NOT EXISTS idx_crawl_log_created_at ON crawl_log (created_at DESC);
|
|
CREATE INDEX IF NOT EXISTS idx_crawl_log_run_id ON crawl_log (run_id);
|