feat: bell-tower favicon, lfx-clean flows, branded HTML mail

This commit is contained in:
Jonas Miederer 2026-09-13 17:57:42 +02:00
parent 672faf3af8
commit df5c1e296c
15 changed files with 288 additions and 30 deletions

View file

@ -422,7 +422,7 @@
"placeholder": "",
"show": true,
"name": "full_name",
"value": "",
"value": " ",
"display_name": "Full name",
"advanced": false,
"api_editable": false,

View file

@ -316,3 +316,34 @@ async def test_magic_request_rate_limit(client, session):
"/api/auth/magic/request", json={"email": MEMBER}
)
assert limited.status_code == 429
def test_magic_link_mail_has_clickable_branded_html(monkeypatch):
from app.auth import mail
monkeypatch.setattr(settings, "smtp_host", "dummy")
message = mail._branded_mail(
subject="Dein Login-Link",
to_email="a@example.com",
headline="Anmeldung bei Kirche Einfach",
intro="Klicke auf den Button.",
button_label="Jetzt anmelden",
button_url="http://localhost:3000/login?token=GEHEIM",
note="Gültig 15 Minuten.",
)
html_part = next(
p for p in message.walk() if p.get_content_type() == "text/html"
)
html = html_part.get_content()
# Button = anchor with href around the label; token never in text-only form.
assert '<a href="http://localhost:3000/login?token=GEHEIM"' in html
assert ">Jetzt anmelden</a>" in html
assert mail.BLUE in html # kirchenblau brand bar
assert 'lang="de"' in html
# Multipart: plain-text fallback keeps the raw link.
parts = [p.get_content_type() for p in message.walk()]
assert "text/plain" in parts and "text/html" in parts
plain = next(
p.get_content() for p in message.walk() if p.get_content_type() == "text/plain"
)
assert "http://localhost:3000/login?token=GEHEIM" in plain

View file

@ -0,0 +1,34 @@
"""Canonical flows must pass lfx's strict validator (level 4).
Guards the source-of-truth directory against authoring mistakes: the
input_schema parser and the LFX runtime both assume well-formed exports.
Runs `lfx validate --level 4` (the dev dep, same minor as Langflow).
"""
import subprocess
import sys
from pathlib import Path
FLOW_DIR = Path(__file__).resolve().parent.parent / "flows"
def test_canonical_flows_pass_lfx_validate():
files = sorted(FLOW_DIR.glob("*.json"))
assert files, "no canonical flows found"
process = subprocess.run(
[
sys.executable,
"-m",
"lfx",
"validate",
"--level",
"4",
*[str(f) for f in files],
],
capture_output=True,
text=True,
timeout=300,
)
assert process.returncode == 0, (
f"lfx validate failed:\n{process.stdout}\n{process.stderr}"
)