48 lines
1.3 KiB
Python
48 lines
1.3 KiB
Python
"""Router opérateur : santé, déverrouillage du store, audit."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from fastapi import APIRouter, HTTPException
|
|
from pydantic import BaseModel
|
|
|
|
from .context import VERSION, Ctx
|
|
from .store import BadPassword
|
|
|
|
|
|
class _Password(BaseModel):
|
|
password: str
|
|
|
|
|
|
def make_router(ctx: Ctx) -> APIRouter:
|
|
r = APIRouter(prefix="/api", tags=["operator"])
|
|
|
|
@r.get("/health")
|
|
def health():
|
|
return {"ok": True, "version": VERSION}
|
|
|
|
@r.get("/lock-status")
|
|
def lock_status():
|
|
return {"initialized": ctx.store.is_initialized, "unlocked": ctx.store.is_unlocked}
|
|
|
|
@r.post("/unlock")
|
|
def unlock(body: _Password):
|
|
first = not ctx.store.is_initialized
|
|
try:
|
|
ctx.store.unlock(body.password)
|
|
except BadPassword as e:
|
|
raise HTTPException(401, "mot de passe incorrect") from e
|
|
ctx.store.audit("store_init" if first else "store_unlock",
|
|
actor=ctx.operator, now=ctx.now_ms())
|
|
return {"unlocked": True, "initialized_now": first}
|
|
|
|
@r.post("/lock")
|
|
def lock():
|
|
ctx.store.lock()
|
|
return {"unlocked": False}
|
|
|
|
@r.get("/audit")
|
|
def audit(limit: int = 200):
|
|
return ctx.guard(lambda: ctx.store.audit_log(limit))
|
|
|
|
return r
|