Flowdeck 7.85.5 — inscription locale fermée par défaut (fusion #146) + échec de connexion nommant la voie ObsiGate SSO (fusion #144)
FlowDeck CI / docker (push) Blocked by required conditions
FlowDeck CI / test (push) In progress
FlowDeck CI / lint (push) Failing after 1s
FlowDeck CI / lint (pull_request) Failing after 3s
FlowDeck CI / test (pull_request) Failing after 35m42s
FlowDeck CI / docker (pull_request) Skipped
FlowDeck CI / docker (push) Blocked by required conditions
FlowDeck CI / test (push) In progress
FlowDeck CI / lint (push) Failing after 1s
FlowDeck CI / lint (pull_request) Failing after 3s
FlowDeck CI / test (pull_request) Failing after 35m42s
FlowDeck CI / docker (pull_request) Skipped
This commit is contained in:
+94
-4
@@ -51,6 +51,76 @@ def _sso_login_url() -> str:
|
||||
f"?return_to={quote(retour, safe='')}")
|
||||
|
||||
|
||||
# Échec de connexion locale (fusion #144) : le message suggère la voie
|
||||
# centrale — un compte créé dans le Hub Dracodev n'a pas de mot de
|
||||
# passe local, son entrée est le bouton « Login with ObsiGate (SSO) »
|
||||
# du même écran (libellé repris tel quel).
|
||||
MESSAGE_ECHEC_CONNEXION_LOCALE = (
|
||||
"Identifiants invalides. Si votre compte a été créé dans le Hub "
|
||||
"Dracodev, connectez-vous avec le bouton « Login with ObsiGate "
|
||||
"(SSO) » de cet écran : les comptes de la suite n'ont pas de mot "
|
||||
"de passe local."
|
||||
)
|
||||
|
||||
|
||||
def _page_inscription_fermee() -> str:
|
||||
"""Page de refus propre du parcours d'inscription fermé (#146)."""
|
||||
from app.services import draco_urls, reglages_acces
|
||||
|
||||
hub = draco_urls.hub_url()
|
||||
message = reglages_acces.message_inscription_fermee()
|
||||
return f"""<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>FlowDeck — Inscription fermée</title>
|
||||
<style>
|
||||
body{{background:#191919;color:#fff;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;display:flex;align-items:center;justify-content:center;min-height:100vh;margin:0;}}
|
||||
.box{{background:#222;border:1px solid rgba(255,255,255,.08);border-radius:12px;padding:40px;width:100%;max-width:420px;}}
|
||||
.box h1{{font-size:22px;margin:0 0 12px;}}
|
||||
.box p{{color:rgba(255,255,255,.6);font-size:14px;line-height:1.6;margin:0 0 16px;}}
|
||||
.box a{{color:#2383E2;}}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="box">
|
||||
<h1>Inscription fermée</h1>
|
||||
<p>{message}</p>
|
||||
<p><a href="{hub}">Ouvrir le Hub Dracodev</a> ·
|
||||
<a href="/auth/login?provider=local">Retour à la connexion</a></p>
|
||||
</div>
|
||||
</body>
|
||||
</html>"""
|
||||
|
||||
|
||||
def _rendre_page_connexion(html: str) -> str:
|
||||
"""Rend la page de connexion en tenant compte du réglage #146.
|
||||
|
||||
Inscription fermée : l'onglet Register disparaît et un avis nomme
|
||||
le Hub Dracodev (lien dérivé de l'hôte, comme les autres liens de
|
||||
la suite). Inscription ouverte : page intégralement inchangée.
|
||||
"""
|
||||
from app.services import draco_urls, reglages_acces
|
||||
|
||||
if reglages_acces.inscription_locale_ouverte():
|
||||
return _with_nonce(html)
|
||||
html = html.replace(
|
||||
"""<button class="tab" onclick="switchTab('register')" id="tab-register">Register</button>""",
|
||||
"",
|
||||
)
|
||||
avis = (
|
||||
'<div class="success" style="display:block;'
|
||||
'background:rgba(35,131,226,.15);color:#7db8f0">'
|
||||
"Pas encore de compte ? Les comptes se créent dans le "
|
||||
f'<a href="{draco_urls.hub_url()}" style="color:#7db8f0">'
|
||||
"Hub Dracodev</a>, puis se connectent ici avec le bouton "
|
||||
"« Login with ObsiGate (SSO) ».</div>"
|
||||
)
|
||||
html = html.replace('<div id="expired-msg"', avis + '<div id="expired-msg"', 1)
|
||||
return _with_nonce(html)
|
||||
|
||||
|
||||
def _with_nonce(html: str) -> str:
|
||||
"""A20 : injecte le nonce CSP au moment du rendu.
|
||||
|
||||
@@ -180,7 +250,15 @@ async function handleLogin(e){e.preventDefault();const email=document.getElement
|
||||
|
||||
@router.get("/register")
|
||||
def register_page(request: Request):
|
||||
"""Show the registration page (local login page with register tab active)."""
|
||||
"""Show the registration page (local login page with register tab active).
|
||||
|
||||
Inscription fermée (#146, défaut) : refus propre — page en
|
||||
français nommant le Hub Dracodev, là où les comptes se créent.
|
||||
"""
|
||||
from app.services import reglages_acces
|
||||
|
||||
if not reglages_acces.inscription_locale_ouverte():
|
||||
return HTMLResponse(_page_inscription_fermee(), status_code=403)
|
||||
return HTMLResponse(_with_nonce(LOCAL_LOGIN_HTML.replace(
|
||||
'class="tab active" onclick="switchTab(\'login\')"',
|
||||
'class="tab" onclick="switchTab(\'login\')"'
|
||||
@@ -205,7 +283,7 @@ def login(request: Request, provider: str = Query("gitea")):
|
||||
# Local login page (POST handled by /auth/local-login)
|
||||
from fastapi.responses import HTMLResponse
|
||||
if provider == "local":
|
||||
return HTMLResponse(_with_nonce(LOCAL_LOGIN_HTML), status_code=200)
|
||||
return HTMLResponse(_rendre_page_connexion(LOCAL_LOGIN_HTML), status_code=200)
|
||||
|
||||
# OAuth flow — check if provider is configured
|
||||
from app.auth.providers import get_provider
|
||||
@@ -259,6 +337,18 @@ def register(request: Request, body: dict = Body(default={})):
|
||||
from fastapi.responses import JSONResponse
|
||||
return JSONResponse({"error": "Password must be at least 6 characters"}, status_code=400)
|
||||
|
||||
# Inscription locale fermée (fusion #146, défaut) : les comptes
|
||||
# naissent dans le Hub Dracodev — aucun compte local ne se crée
|
||||
# ici. La connexion des comptes existants n'est pas touchée.
|
||||
from app.services import draco_urls, reglages_acces
|
||||
if not reglages_acces.inscription_locale_ouverte():
|
||||
from fastapi.responses import JSONResponse
|
||||
return JSONResponse(
|
||||
{"error": reglages_acces.message_inscription_fermee(),
|
||||
"hub_url": draco_urls.hub_url()},
|
||||
status_code=403,
|
||||
)
|
||||
|
||||
# SSO-only instance (v6.7.0): local registration is refused — accounts are
|
||||
# auto-provisioned by the IdP instead (admins still come from Settings).
|
||||
from app.services.sso_provisioning import is_sso_only
|
||||
@@ -313,7 +403,7 @@ def local_login(request: Request, body: dict = Body(default={})):
|
||||
with get_conn() as conn:
|
||||
user = conn.execute("SELECT * FROM users WHERE login=?", (email,)).fetchone()
|
||||
if not user:
|
||||
return JSONResponse({"error": "Invalid credentials"}, status_code=401)
|
||||
return JSONResponse({"error": MESSAGE_ECHEC_CONNEXION_LOCALE}, status_code=401)
|
||||
|
||||
ud = dict(user)
|
||||
if not ud.get("is_active"):
|
||||
@@ -332,7 +422,7 @@ def local_login(request: Request, body: dict = Body(default={})):
|
||||
(attempts, lock, ud["id"]),
|
||||
)
|
||||
conn.commit()
|
||||
return JSONResponse({"error": "Invalid credentials"}, status_code=401)
|
||||
return JSONResponse({"error": MESSAGE_ECHEC_CONNEXION_LOCALE}, status_code=401)
|
||||
|
||||
# Successful local login — SSO-only instances keep a way in for admins
|
||||
# only (every other account must use the IdP, design §7.1).
|
||||
|
||||
Reference in New Issue
Block a user