Simplify public hostname generation

This commit is contained in:
StasonJatham committed 2026-05-20 20:07:27 +02:00
1 parent 2403a40800
commit d2b160438d
3 files changed
+11 -18

No files matched your search

Binary file not shown.

Before

Width:  |  Height:  |  Size: 442 KiB

After

Width:  |  Height:  |  Size: 442 KiB

+6 -14
View File
@@ -327,9 +327,8 @@ def make_app(settings: DdnsSettings | None = None) -> FastAPI:
@app.post("/magic", response_class=HTMLResponse) @app.post("/magic", response_class=HTMLResponse)
async def magic_account(request: Request) -> str: async def magic_account(request: Request) -> str:
form = await _request_form(request, settings) await _request_form(request, settings)
username = _first_form_value(form, "username") or None account = await run_in_threadpool(service.create_managed_account, None)
account = await run_in_threadpool(service.create_managed_account, username)
return _render_public_home(service, settings, account, None) return _render_public_home(service, settings, account, None)
@app.get("/m/{management_slug}", response_class=HTMLResponse) @app.get("/m/{management_slug}", response_class=HTMLResponse)
@@ -401,16 +400,15 @@ def make_app(settings: DdnsSettings | None = None) -> FastAPI:
async def self_service_account(request: Request) -> str: async def self_service_account(request: Request) -> str:
form = await _request_form(request, settings) form = await _request_form(request, settings)
mode = _first_form_value(form, "mode") mode = _first_form_value(form, "mode")
username = _first_form_value(form, "username") or None
if mode == "managed": if mode == "managed":
account = await run_in_threadpool(service.create_managed_account, username) account = await run_in_threadpool(service.create_managed_account, None)
else: else:
claim_secret = _first_form_value(form, "claim_secret") claim_secret = _first_form_value(form, "claim_secret")
account = await run_in_threadpool( account = await run_in_threadpool(
service.create_custom_account, service.create_custom_account,
_first_form_value(form, "hostname"), _first_form_value(form, "hostname"),
claim_secret, claim_secret,
username, None,
) )
return _render_public_home(service, settings, account, None) return _render_public_home(service, settings, account, None)
@@ -678,10 +676,7 @@ def _render_public_home(
</div> </div>
</div> </div>
<form method="post" action="/magic" class="col-lg-5 card card-body gap-3" aria-label="Create a generated DynDNS hostname"> <form method="post" action="/magic" class="col-lg-5 card card-body gap-3" aria-label="Create a generated DynDNS hostname">
<label>Router login name <span class="text-secondary fw-normal">(optional)</span> <p class="section-copy mb-0">KarlDNS generates the hostname, secret update URL, and optional router compatibility credentials automatically.</p>
<input class="form-control" name="username" placeholder="optional" autocomplete="off" inputmode="text">
<span class="form-text m-0">This becomes the FRITZ!Box Benutzername. Leave empty to generate one automatically.</span>
</label>
<button type="submit" class="btn btn-primary rounded-pill">Generate hostname</button> <button type="submit" class="btn btn-primary rounded-pill">Generate hostname</button>
</form> </form>
</div> </div>
@@ -775,10 +770,7 @@ def _custom_domain_flow(service: DdnsService, challenge: dict[str, str | None] |
<label>Verified hostname <label>Verified hostname
<input class="form-control" name="hostname" placeholder="home.example.com" autocomplete="off" autocapitalize="none" spellcheck="false" required> <input class="form-control" name="hostname" placeholder="home.example.com" autocomplete="off" autocapitalize="none" spellcheck="false" required>
</label> </label>
<label>Router login name <span class="text-secondary fw-normal">(optional)</span> <p class="section-copy mb-0">Router compatibility credentials are generated automatically after creation.</p>
<input class="form-control" name="username" placeholder="optional" autocomplete="off">
<span class="form-text m-0">This becomes the FRITZ!Box Benutzername. Leave empty to generate one automatically.</span>
</label>
<button type="submit" class="btn btn-primary rounded-pill">Create credentials</button> <button type="submit" class="btn btn-primary rounded-pill">Create credentials</button>
</form> </form>
</div> </div>
+5 -4
View File
@@ -391,7 +391,7 @@ def test_magic_hostname_without_login_generates_update_and_management_links(tmp_
) )
client = TestClient(app) client = TestClient(app)
response = client.post("/magic", data={"username": "alice"}) response = client.post("/magic")
assert response.status_code == 200 assert response.status_code == 200
assert "Update-URL:" in response.text assert "Update-URL:" in response.text
@@ -558,7 +558,7 @@ def test_api_docs_include_versioned_ddns_api(tmp_path: Path) -> None:
assert all(tag["name"] != "admin" for tag in schema["tags"]) assert all(tag["name"] != "admin" for tag in schema["tags"])
def test_public_home_hides_admin_link_and_explains_router_login(tmp_path: Path) -> None: def test_public_home_hides_admin_link_and_uses_automatic_router_login(tmp_path: Path) -> None:
app = make_app( app = make_app(
DdnsSettings( DdnsSettings(
database_path=tmp_path / "ddns.sqlite3", database_path=tmp_path / "ddns.sqlite3",
@@ -572,8 +572,9 @@ def test_public_home_hides_admin_link_and_explains_router_login(tmp_path: Path)
assert response.status_code == 200 assert response.status_code == 200
assert 'href="/admin"' not in response.text assert 'href="/admin"' not in response.text
assert "Router login name" in response.text assert "Router login name" not in response.text
assert "FRITZ!Box Benutzername" in response.text assert 'name="username"' not in response.text
assert "generates the hostname, secret update URL, and optional router compatibility credentials automatically" in response.text
def test_application_pages_use_stricter_script_csp(tmp_path: Path) -> None: def test_application_pages_use_stricter_script_csp(tmp_path: Path) -> None: