Files
Enclume/enclume/config.py
T
hcornet b063d59525
build / Garde-fou (pull_request) Failing after 7s
build / Images Harbor (catalog-sync, Dockerfile.catalog-sync) (pull_request) Skipped
build / Images Harbor (web, Dockerfile) (pull_request) Skipped
build / Garde-fou (push) Failing after 8s
build / Images Harbor (catalog-sync, Dockerfile.catalog-sync) (push) Skipped
build / Images Harbor (web, Dockerfile) (push) Skipped
Partage par lien, comptes Authentik, soumission et moderation de packs, prerequis des sondes ; corrige le lien casse vers le script de l'editeur
2026-09-10 16:28:26 +02:00

106 lines
4.5 KiB
Python

"""Configuration lue depuis l'environnement.
Toutes les fonctionnalites ajoutees aux chantiers 3 a 5 sont facultatives :
sans base de donnees, sans OIDC et sans jeton Gitea, l'application reste
exactement ce qu'elle etait — un editeur qui genere du CLAPI. C'est ce qui
permet a n'importe qui de l'auto-heberger en trois lignes.
"""
from __future__ import annotations
import os
import secrets
def _bool(nom: str, defaut: bool = False) -> bool:
brut = os.environ.get(nom)
if brut is None:
return defaut
return brut.strip().lower() in {"1", "true", "oui", "yes", "on"}
def _int(nom: str, defaut: int) -> int:
try:
return int(os.environ.get(nom, defaut))
except (TypeError, ValueError):
return defaut
class Config:
# --- Identite du service ------------------------------------------------
VERSION = os.environ.get("ENCLUME_VERSION", "dev")
COMMIT = os.environ.get("ENCLUME_COMMIT", "inconnu")
URL_PUBLIQUE = os.environ.get("ENCLUME_URL_PUBLIQUE", "").rstrip("/")
# --- Sessions -----------------------------------------------------------
# Sans cle fournie, on en tire une au demarrage : les sessions ne survivent
# pas a un redemarrage, ce qui est acceptable en developpement et bruyant
# en production, donc visible.
SECRET_KEY = os.environ.get("ENCLUME_SECRET_KEY") or secrets.token_hex(32)
SECRET_KEY_FOURNIE = bool(os.environ.get("ENCLUME_SECRET_KEY"))
SESSION_COOKIE_NAME = "enclume"
SESSION_COOKIE_HTTPONLY = True
SESSION_COOKIE_SAMESITE = "Lax"
SESSION_COOKIE_SECURE = _bool("ENCLUME_COOKIE_SECURE", True)
PERMANENT_SESSION_LIFETIME = _int("ENCLUME_SESSION_JOURS", 30) * 86400
# --- Base de donnees ----------------------------------------------------
SQLALCHEMY_DATABASE_URI = os.environ.get("ENCLUME_DATABASE_URL", "")
SQLALCHEMY_ENGINE_OPTIONS = {"pool_pre_ping": True, "pool_recycle": 1800}
# --- Partage ------------------------------------------------------------
PARTAGE_JOURS = _int("ENCLUME_PARTAGE_JOURS", 90)
PROJETS_PAR_COMPTE = _int("ENCLUME_PROJETS_PAR_COMPTE", 50)
# --- Authentification OIDC (Authentik) ----------------------------------
OIDC_NOM = os.environ.get("ENCLUME_OIDC_NOM", "Authentik")
OIDC_METADATA = os.environ.get("ENCLUME_OIDC_METADATA", "")
OIDC_CLIENT_ID = os.environ.get("ENCLUME_OIDC_CLIENT_ID", "")
OIDC_CLIENT_SECRET = os.environ.get("ENCLUME_OIDC_CLIENT_SECRET", "")
OIDC_SCOPES = os.environ.get("ENCLUME_OIDC_SCOPES", "openid email profile")
# Le groupe qui donne acces a la moderation. Necessite que le fournisseur
# place la revendication "groups" dans le jeton (mapping de portee dedie
# cote Authentik).
ADMIN_GROUPE = os.environ.get("ENCLUME_ADMIN_GROUPE", "enclume-admins")
ADMIN_COMPTES = [
c.strip().lower()
for c in os.environ.get("ENCLUME_ADMIN_COMPTES", "").split(",")
if c.strip()
]
# --- Depot du catalogue, pour les soumissions ---------------------------
GITEA_URL = os.environ.get("ENCLUME_GITEA_URL", "").rstrip("/")
GITEA_TOKEN = os.environ.get("ENCLUME_GITEA_TOKEN", "")
GITEA_PROPRIETAIRE = os.environ.get("ENCLUME_GITEA_PROPRIETAIRE", "")
GITEA_DEPOT = os.environ.get("ENCLUME_GITEA_DEPOT", "")
GITEA_BRANCHE = os.environ.get("ENCLUME_GITEA_BRANCHE", "main")
GITEA_SOUS_DOSSIER = os.environ.get("ENCLUME_GITEA_SOUS_DOSSIER", "catalog")
# --- Limites ------------------------------------------------------------
TAILLE_MAX_PROJET = _int("ENCLUME_TAILLE_MAX_PROJET", 2 * 1024 * 1024)
TAILLE_MAX_PACK = _int("ENCLUME_TAILLE_MAX_PACK", 256 * 1024)
SOUMISSIONS_PAR_JOUR = _int("ENCLUME_SOUMISSIONS_PAR_JOUR", 10)
@classmethod
def base_active(cls) -> bool:
return bool(cls.SQLALCHEMY_DATABASE_URI)
@classmethod
def oidc_actif(cls) -> bool:
return bool(cls.OIDC_METADATA and cls.OIDC_CLIENT_ID and cls.OIDC_CLIENT_SECRET)
@classmethod
def gitea_actif(cls) -> bool:
return bool(cls.GITEA_URL and cls.GITEA_TOKEN and cls.GITEA_PROPRIETAIRE and cls.GITEA_DEPOT)
@classmethod
def etat(cls) -> dict[str, bool]:
"""Ce que le site sait faire, tel qu'annonce a l'interface."""
return {
"comptes": cls.base_active() and cls.oidc_actif(),
"partage": cls.base_active(),
"projets_enregistres": cls.base_active() and cls.oidc_actif(),
"soumissions": cls.base_active() and cls.oidc_actif(),
"publication_gitea": cls.gitea_actif(),
}