Commit Graph

11 Commits

Author SHA1 Message Date
Colin Maudry 1551faaf0c Normaliser les échecs d'écriture set_cell en ValueError
- IntegrityError (ex: email déjà utilisé) est désormais capturée et
  reconvertie en ValueError, pour rester dans le funnel d'alerte
  existant du callback admin au lieu de faire planter le callback Dash.
- Une UPDATE qui touche 0 ligne (ligne supprimée entre le chargement du
  tableau et la soumission de l'édition) lève désormais une ValueError
  au lieu d'être silencieusement traitée comme un succès (ce qui aurait
  créé un log d'audit trompeur).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-03 23:10:32 +02:00
Colin Maudry 6739e4926b test(admin): add end-to-end Selenium coverage for the generic table editor
Covers anonymous/non-admin access (404), and the full admin flow: switch
table, edit a subscriptions.prix_ht cell through the real DataTable UI,
verify the write lands in the DB, and verify the edit is logged and
visible in the admin_actions table.

tests/users.test.sqlite is committed and shared by the whole Selenium
session, so _cleanup_user deletes every row the tests create. Beyond
resetting sqlite_sequence (already needed for the AUTOINCREMENT
counter), a plain DELETE also leaves stale, never-zeroed bytes behind
in the admin_actions/subscriptions b-tree pages once they go back to
zero rows, which byte-diffs the file even though its logical content
is unchanged. VACUUM rebuilds the file from live data only, producing
a deterministic page layout (verified empirically across independent
runs with different random test data). Re-baselined the fixture to
that canonical vacuumed state so `git status` stays clean after
running the suite.
2026-07-03 22:43:53 +02:00
Colin Maudry caf800e5e8 fix(admin): guard find_changed_cell against cross-table schema mismatch
When switching tables, the table-switch branch writes fresh data for the
new table, which re-fires the same callback with data_previous still
holding the old table's rows. find_changed_cell only checked row count
before diffing, so if the two tables happened to have the same number of
rows it would zip mismatched-schema dicts and report a spurious changed
cell (usually the PK column), producing a confusing red alert right after
switching tables.
2026-07-03 14:46:12 +02:00
Colin Maudry d229b58f3b feat(admin): replace dedicated pages with a generic table editor at /admin 2026-07-03 14:19:01 +02:00
Colin Maudry cf23863a30 refactor(admin): apply formatting fixes from linter hooks 2026-07-03 13:04:15 +02:00
Colin Maudry 348da79175 test(admin): verify login succeeded in non-admin 404 test
test_admin_non_admin_gets_404 asserted the same /admin 404 that
anonymous visitors also get, without first confirming the login
actually went through. A broken login (falls back to /connexion on
bad credentials, unverified email, etc.) would leave the session
anonymous and the test would keep passing for the wrong reason,
silently degrading into a duplicate of test_admin_anonymous_gets_404.
Now waits for the post-login redirect to /compte/abonnement (this
user has no subscription) before exercising the admin guard.
2026-07-03 10:44:31 +02:00
Colin Maudry 7cc1fadf0f test(admin): add end-to-end Selenium coverage for the admin panel
Covers anonymous → 404, non-admin → 404, and the full admin flow
(list, detail, status change, journal) through a real login and a
real running app. tests/users.test.sqlite is committed and shared by
the whole Selenium session, so the test cleanup also resets the
sqlite_sequence high-water marks that plain DELETEs don't roll back,
keeping the file byte-stable across runs. This run additionally bakes
in migration 0006_create_admin_actions (new admin_actions table), the
first time any Selenium test has booted the real app since that
migration was added — the same one-time process by which migrations
0001-0005 already ended up committed in this fixture.
2026-07-03 10:34:35 +02:00
Colin Maudry e483d7af4d feat(admin): add subscription-status mutation route
Wires is_admin(), SUBSCRIPTION_STATUSES/get_current/set_status, and
log_action() into POST /admin/actions/subscription-status: validates
the requested status and that subscription_id matches the user's
current subscription, applies the change, and logs an audit entry.
Registers the admin blueprint in init_auth() and documents ADMIN_EMAIL
in .template.env.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-03 09:46:22 +02:00
Colin Maudry 2f2cd151fb feat(admin): add is_admin() access guard
Implement access control function for admin panel. Returns True only if
ADMIN_EMAIL env var is set, user is authenticated, and email matches
case-insensitively.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-03 09:41:57 +02:00
Colin Maudry c4851ff0ae refactor: format test_db.py for consistency
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-03 09:38:46 +02:00
Colin Maudry fb62c28e10 feat(admin): add admin_actions audit table and log/list functions
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-03 09:38:33 +02:00