Administration depuis le site : bouton Connexion sur l'accueil
site.toml [administration] adresse : l'accueil affiche un bouton « Connexion » vers l'interface. Celle-ci peut tourner derrière le serveur web du site (rtg interface --proxy --prefixe /admin) : adresses préfixées, mot de passe obligatoire, visiteur identifié par X-Forwarded-For, cookie Secure limité au préfixe quand le site est en HTTPS. Exemples nginx et Apache dans le README. Le bouton Arrêter ne remplace plus le bloc de la tâche en même temps que la relève. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Mf2kATMtqVABHSYdxJMnim
This commit is contained in:
1 parent
71779f6f53
commit
4366db94ed
22 files changed
+229
-86
No files matched your search
@@ -176,3 +176,46 @@ def test_corrections(client):
|
||||
for pistes in v.traces.values():
|
||||
for piste, pts in pistes:
|
||||
assert all(corrections.distance_m(la, lo, 56.7, 2.24) > 3000 for la, lo in pts)
|
||||
|
||||
|
||||
def test_derriere_le_serveur_web(voyage_sans_heures, tmp_path, monkeypatch):
|
||||
"""--proxy --prefixe /admin : adresses préfixées, mot de passe, cookie Secure."""
|
||||
racine, voyage = voyage_sans_heures
|
||||
monkeypatch.setenv("XDG_CONFIG_HOME", str(tmp_path / "config"))
|
||||
monkeypatch.setenv("APPDATA", str(tmp_path / "config"))
|
||||
acces.definir("un mot de passe solide")
|
||||
app = serveur.Application(str(racine), "/admin")
|
||||
srv = ThreadingHTTPServer(("127.0.0.1", 0), None)
|
||||
port = srv.server_address[1]
|
||||
gardien = Gardien(port, proxy=True, prefixe=app.prefixe)
|
||||
srv.RequestHandlerClass = serveur.creer_gestionnaire(app, port, gardien)
|
||||
threading.Thread(target=srv.serve_forever, daemon=True).start()
|
||||
ouvreur = urllib.request.build_opener(_SansRedirection)
|
||||
entetes = {"Host": "roadtrip.example", "X-Forwarded-For": "203.0.113.7", "X-Forwarded-Proto": "https"}
|
||||
|
||||
def requete(chemin, donnees=None, extra=None):
|
||||
req = urllib.request.Request(f"http://127.0.0.1:{port}{chemin}", headers=dict(entetes, **(extra or {})),
|
||||
data=urllib.parse.urlencode(donnees).encode() if donnees else None)
|
||||
try:
|
||||
return ouvreur.open(req)
|
||||
except urllib.error.HTTPError as e:
|
||||
return e
|
||||
try:
|
||||
r = requete("/admin/")
|
||||
assert r.status == 303 and r.headers["Location"] == "/admin/connexion"
|
||||
assert requete("/").status == 404 # hors du préfixe
|
||||
assert requete("/admin/connexion").status == 200
|
||||
r = requete("/admin/connexion", {"mot_de_passe": "un mot de passe solide"}, {"HX-Request": "true"})
|
||||
cookie = r.headers["Set-Cookie"]
|
||||
assert r.headers["HX-Redirect"] == "/admin/" and "Path=/admin/" in cookie and "Secure" in cookie
|
||||
sid = cookie.split(";")[0]
|
||||
r = requete("/admin/", extra={"Cookie": sid})
|
||||
html = r.read().decode()
|
||||
assert r.status == 200 and 'href="/admin/nouveau"' in html and 'href="/"' in html # Voir le site
|
||||
# Les échecs sont comptés par visiteur (X-Forwarded-For), pas pour le serveur web
|
||||
for _ in range(5):
|
||||
requete("/admin/connexion", {"mot_de_passe": "faux"}, {"HX-Request": "true"})
|
||||
assert gardien.attente("203.0.113.7") > 0 and gardien.attente("127.0.0.1") == 0
|
||||
finally:
|
||||
srv.shutdown()
|
||||
serveur.ENV.globals["base"] = ""
|
||||
Reference in new issue
Block a user