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:
@@ -0,0 +1,177 @@
|
||||
"""FlowDeck — réglages d'accès : inscription locale (fusion #146, #144).
|
||||
|
||||
Contrat de la phase 1 du programme « compte partout » :
|
||||
|
||||
- inscription locale **fermée par défaut** (décision de Bruno) :
|
||||
le parcours public d'inscription est refusé proprement et nomme
|
||||
le Hub Dracodev, là où les comptes se créent ;
|
||||
- réglage **réversible par un administrateur** (API
|
||||
``/api/admin/reglages-acces``) : ouverte, l'inscription redevient
|
||||
exactement celle d'aujourd'hui ;
|
||||
- la connexion des comptes existants (locaux et draco) n'est
|
||||
**jamais** affectée par le réglage ;
|
||||
- #144 : l'échec du formulaire de connexion locale suggère la voie
|
||||
ObsiGate (SSO).
|
||||
|
||||
Le harnais de test ouvre l'inscription pour les suites historiques
|
||||
(voir conftest) ; chaque test pose donc explicitement l'état qu'il
|
||||
vérifie via le service des réglages.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
from conftest import anon_csrf
|
||||
|
||||
from app.services import reglages_acces
|
||||
|
||||
|
||||
def _fermer():
|
||||
reglages_acces.set_reglages_acces(inscription_locale_ouverte=False)
|
||||
|
||||
|
||||
def _ouvrir():
|
||||
reglages_acces.set_reglages_acces(inscription_locale_ouverte=True)
|
||||
|
||||
|
||||
def _creer_compte_local(login: str, mot_de_passe: str, admin: int = 0) -> None:
|
||||
from app.db import get_conn
|
||||
from app.password_utils import hash_password
|
||||
|
||||
with get_conn() as conn:
|
||||
conn.execute(
|
||||
"INSERT OR REPLACE INTO users (login, full_name, email,"
|
||||
" password_hash, is_admin) VALUES (?, ?, ?, ?, ?)",
|
||||
(login, login, f"{login}@test.dev",
|
||||
hash_password(mot_de_passe), admin),
|
||||
)
|
||||
conn.commit()
|
||||
|
||||
|
||||
# ── Réglage fermé : inscription impossible + message ────────────────
|
||||
|
||||
def test_inscription_fermee_par_defaut_dans_le_code():
|
||||
"""Le défaut du code (hors toute ligne en base) est « fermée »."""
|
||||
from app.config import settings
|
||||
|
||||
assert settings.inscription_locale_ouverte is False
|
||||
|
||||
|
||||
def test_inscription_fermee_post_refuse_avec_message_hub(client):
|
||||
_fermer()
|
||||
r = client.post("/auth/register", json={
|
||||
"email": "[email protected]", "password": "secret123",
|
||||
"name": "Visiteur"})
|
||||
assert r.status_code == 403
|
||||
erreur = r.json()["error"]
|
||||
assert "Hub Dracodev" in erreur
|
||||
# Lien dérivé vers le Hub fourni à l'écran comme aux API.
|
||||
assert r.json()["hub_url"]
|
||||
# Aucun compte n'a été créé.
|
||||
from app.db import get_conn
|
||||
with get_conn() as conn:
|
||||
assert conn.execute(
|
||||
"SELECT COUNT(*) FROM users WHERE login='[email protected]'"
|
||||
).fetchone()[0] == 0
|
||||
|
||||
|
||||
def test_inscription_fermee_page_refus_propre(client):
|
||||
_fermer()
|
||||
r = anon_csrf(client).get("/auth/register", follow_redirects=False)
|
||||
assert r.status_code == 403
|
||||
assert "Hub Dracodev" in r.text
|
||||
assert "les comptes se créent" in r.text
|
||||
|
||||
|
||||
def test_inscription_fermee_page_connexion_sans_onglet_register(client):
|
||||
_fermer()
|
||||
r = anon_csrf(client).get("/auth/login?provider=local")
|
||||
assert r.status_code == 200
|
||||
assert 'id="tab-register"' not in r.text
|
||||
# L'avis nomme le Hub et la voie SSO reste visible.
|
||||
assert "Hub Dracodev" in r.text
|
||||
assert "Login with ObsiGate (SSO)" in r.text
|
||||
|
||||
|
||||
# ── Réglage ouvert : inscription comme aujourd'hui ──────────────────
|
||||
|
||||
def test_inscription_ouverte_post_comme_avant(client):
|
||||
_ouvrir()
|
||||
r = client.post("/auth/register", json={
|
||||
"email": "[email protected]", "password": "secret123",
|
||||
"name": "Nouveau"})
|
||||
assert r.status_code == 200
|
||||
assert r.json()["status"] == "ok"
|
||||
|
||||
|
||||
def test_inscription_ouverte_page_register_affichee(client):
|
||||
_ouvrir()
|
||||
r = anon_csrf(client).get("/auth/register", follow_redirects=False)
|
||||
assert r.status_code == 200
|
||||
assert 'id="tab-register"' in r.text
|
||||
|
||||
|
||||
# ── Connexion des comptes existants : jamais affectée ───────────────
|
||||
|
||||
def test_connexion_compte_local_existant_inscription_fermee(client):
|
||||
_creer_compte_local("ancien", "secret123")
|
||||
_fermer()
|
||||
r = anon_csrf(client).post("/auth/local-login", json={
|
||||
"email": "ancien", "password": "secret123"})
|
||||
assert r.status_code == 200
|
||||
assert r.json()["status"] == "ok"
|
||||
|
||||
|
||||
def test_connexion_compte_draco_sans_mot_de_passe_inchangee(client):
|
||||
"""Un compte draco (sans mot de passe local) reste refusé en local
|
||||
de la même façon, réglage ouvert ou fermé : le réglage ne change
|
||||
rien à l'authentification."""
|
||||
from app.db import get_conn
|
||||
with get_conn() as conn:
|
||||
conn.execute(
|
||||
"INSERT OR REPLACE INTO users (login, full_name, email,"
|
||||
" password_hash, auth_method) VALUES"
|
||||
" ('draco-42', 'Dan Test', '[email protected]', NULL, 'draco')")
|
||||
conn.commit()
|
||||
for ouvrir in (True, False):
|
||||
reglages_acces.set_reglages_acces(
|
||||
inscription_locale_ouverte=ouvrir)
|
||||
r = anon_csrf(client).post("/auth/local-login", json={
|
||||
"email": "draco-42", "password": "nimporte"})
|
||||
assert r.status_code == 401
|
||||
|
||||
|
||||
# ── #144 : l'échec local suggère la voie ObsiGate (SSO) ─────────────
|
||||
|
||||
def test_echec_connexion_locale_suggere_sso(client):
|
||||
_creer_compte_local("quelquun", "secret123")
|
||||
r = anon_csrf(client).post("/auth/local-login", json={
|
||||
"email": "quelquun", "password": "mauvais-mot-de-passe"})
|
||||
assert r.status_code == 401
|
||||
assert "ObsiGate (SSO)" in r.json()["error"]
|
||||
assert "Hub Dracodev" in r.json()["error"]
|
||||
|
||||
|
||||
def test_echec_connexion_compte_inconnu_suggere_sso(client):
|
||||
r = anon_csrf(client).post("/auth/local-login", json={
|
||||
"email": "[email protected]", "password": "nimporte"})
|
||||
assert r.status_code == 401
|
||||
assert "ObsiGate (SSO)" in r.json()["error"]
|
||||
|
||||
|
||||
# ── Administration du réglage ────────────────────────────────────────
|
||||
|
||||
def test_api_admin_reglages_acces_aller_retour(client):
|
||||
"""Le client de test est administrateur : lecture + écriture."""
|
||||
_fermer()
|
||||
r = client.get("/api/admin/reglages-acces")
|
||||
assert r.status_code == 200
|
||||
assert r.json()["inscription_locale_ouverte"] is False
|
||||
r = client.put("/api/admin/reglages-acces",
|
||||
json={"inscription_locale_ouverte": True})
|
||||
assert r.status_code == 200
|
||||
assert r.json()["inscription_locale_ouverte"] is True
|
||||
assert reglages_acces.inscription_locale_ouverte() is True
|
||||
|
||||
|
||||
def test_api_admin_reglages_acces_refusee_aux_anonymes(client):
|
||||
r = anon_csrf(client).get("/api/admin/reglages-acces")
|
||||
assert r.status_code in (401, 403)
|
||||
Reference in New Issue
Block a user