Table `app_user`, son dépôt, et la commande `create-admin`. Le nom évite `user`, mot réservé de PostgreSQL, et rappelle qu'il s'agit d'un compte applicatif, par opposition au rôle PostgreSQL qui portera le cantonnement des accès ETL et ML. `credentials_changed_at` couvre à elle seule le changement de mot de passe, le changement de rôle et la désactivation : tout jeton émis avant cet instant sera refusé, sans attendre son expiration. La configuration refuse désormais de démarrer sur cinq erreurs silencieuses : secret trop court ou laissé à sa valeur d'exemple, `debug` en production, joker CORS, origines vides hors local, et cookie `SameSite=None` sans `Secure`. Les fixtures de test et les deux `.env.example` suivent, sans quoi rien ne démarrerait. Le mot de passe de l'admin ne transite jamais par `argv`, visible de tout `ps` : il est saisi par `getpass` ou tiré au sort. Une révision Alembic qui insérerait ce compte graverait son empreinte dans Git pour toujours.
38 lines
1.2 KiB
Python
38 lines
1.2 KiB
Python
from typing import Any
|
|
|
|
from app.core.config import Settings
|
|
|
|
SETTINGS_DE_TEST: dict[str, Any] = {
|
|
"env": "local",
|
|
"debug": False,
|
|
"log_level": "WARNING",
|
|
"cors_origins": "",
|
|
"secret_key": "secret-de-test-assez-long-pour-le-validateur",
|
|
"database_url": "postgresql+asyncpg://enervision:change_me@localhost:5433/enervision_test",
|
|
}
|
|
|
|
|
|
class FakeSession:
|
|
"""Session factice : renvoie `result`, ou leve `failure` si elle est fournie."""
|
|
|
|
def __init__(self, result: object = None, failure: Exception | None = None) -> None:
|
|
self._result = result
|
|
self._failure = failure
|
|
|
|
async def scalar(self, *_: object, **__: object) -> object:
|
|
return self._repondre()
|
|
|
|
async def execute(self, *_: object, **__: object) -> object:
|
|
return self._repondre()
|
|
|
|
def _repondre(self) -> object:
|
|
if self._failure is not None:
|
|
raise self._failure
|
|
return self._result
|
|
|
|
|
|
# Piège : les arguments nommés priment sur l'environnement et sur .env, contrairement
|
|
# aux variables posées par la fixture `environment`, qui restent surchargeables.
|
|
def make_settings(**overrides: Any) -> Settings:
|
|
return Settings(**{**SETTINGS_DE_TEST, **overrides})
|