fix(auth): auth deps use their own DB session; smoke suites made dataset-independent

RUNTIME BUG (caught by live smoke tests): the global auth dependency
queried the request-scoped session, auto-beginning its transaction — any
endpoint opening 'async with db.begin()' afterwards crashed with
'transaction already begun' (POST /materials 500). get_current_user /
get_actor now resolve in a short-lived session (expire_on_commit=False
keeps the context usable detached); inventory/pm scopes keep passing the
request session explicitly.

Smoke suites rewritten against CURRENT contracts:
- assertions are behavior-based (shapes, envelopes, filters), no magic
  seed counts; dynamic lookups instead of hard-coded names/ids
- rerun-tolerant: tolerate 409-on-create by reusing prior artifacts
- aligned with current rules: revert blocked after inventory receipts
  (v2.6), attachments allowed in every status, termsheets optional at
  quote level
- SMOKE_USER/SMOKE_PASSWORD env for login (default tester/123456)

Verified on a fresh volume: migration + audit_log bootstrap, Casdoor
seed (bcrypt), demo data, and 29+76+61 smoke checks all green.
This commit is contained in:
MMD
2026-09-19 00:49:15 +03:30
parent e03d94207b
commit e1495afee9
6 changed files with 351 additions and 167 deletions
+8 -11
View File
@@ -18,27 +18,24 @@ for the in-page login flow.
import http.cookiejar
import json
import os
import secrets
import urllib.request
import bcrypt
BASE = os.environ.get("CASDOOR_BASE", "http://localhost:8080")
ADMIN = os.environ.get("CASDOOR_ADMIN", "admin")
# Console admin password — MUST be overridden outside local dev (see
# docs/SECRET-MANAGEMENT.md); the historical default "123" is gone.
ADMIN_PW = os.environ.get("CASDOOR_ADMIN_PW", "")
if not ADMIN_PW:
ADMIN_PW = secrets.token_urlsafe(12)
print(f"[seed] generated Casdoor console admin password: {ADMIN_PW}")
# Casdoor's own bootstrap default for the built-in console admin is "123" —
# the seeder LOGS IN with it (it cannot change the console password).
# Override with CASDOOR_ADMIN_PW after rotating (docs/SECRET-MANAGEMENT.md);
# production MUST set a real value here once the console password is rotated.
ADMIN_PW = os.environ.get("CASDOOR_ADMIN_PW", "123")
ORG = "inventory"
APP = "inventory-app"
CLIENT_ID = "inventory-app-client"
CLIENT_SECRET = os.environ.get("CASDOOR_CLIENT_SECRET", "")
if not CLIENT_SECRET:
CLIENT_SECRET = secrets.token_urlsafe(24)
print(f"[seed] generated Casdoor client secret: {CLIENT_SECRET}")
# Must MATCH the API's PROCUREMENT_CASDOOR_CLIENT_SECRET (compose default
# below) — changing one without the other breaks POST /auth/login.
CLIENT_SECRET = os.environ.get("CASDOOR_CLIENT_SECRET", "inventory-app-secret-2026")
REDIRECT_URI = "http://localhost/login" # Traefik edge (v1.3); unused by the in-page flow
# One password for all seeded dev users — override with CASDOOR_SEED_PASSWORD;