Archived
Add grouped clipboard actions
This commit is contained in:
1 parent
73bc201511
commit
7ba7610c41
2 files changed
+45
No files matched your search
@@ -719,6 +719,7 @@ def _custom_domain_flow(service: DdnsService, challenge: dict[str, str | None] |
|
|||||||
verification_name = service.verification_name(str(challenge["domain"]))
|
verification_name = service.verification_name(str(challenge["domain"]))
|
||||||
claim_url = service.domain_claim_url(challenge)
|
claim_url = service.domain_claim_url(challenge)
|
||||||
status = html.escape(message or "Add this TXT record at your DNS provider, then check when it has propagated.")
|
status = html.escape(message or "Add this TXT record at your DNS provider, then check when it has propagated.")
|
||||||
|
txt_bundle = f"TXT name: {verification_name}\nTXT value: {token}"
|
||||||
challenge_html = f"""
|
challenge_html = f"""
|
||||||
<div class="col-md-4">
|
<div class="col-md-4">
|
||||||
<div class="card card-body h-100 gap-3">
|
<div class="card card-body h-100 gap-3">
|
||||||
@@ -726,6 +727,7 @@ def _custom_domain_flow(service: DdnsService, challenge: dict[str, str | None] |
|
|||||||
<h3>Add the TXT record</h3>
|
<h3>Add the TXT record</h3>
|
||||||
<p class="small text-secondary mb-0 mt-2">{status}</p>
|
<p class="small text-secondary mb-0 mt-2">{status}</p>
|
||||||
<div class="alert alert-info mb-0 py-2 small">TXT name and value are public DNS records. The private claim link is secret.</div>
|
<div class="alert alert-info mb-0 py-2 small">TXT name and value are public DNS records. The private claim link is secret.</div>
|
||||||
|
{_copy_button("Copy TXT record", txt_bundle)}
|
||||||
{_copy_row("TXT name", verification_name, "Public")}
|
{_copy_row("TXT name", verification_name, "Public")}
|
||||||
{_copy_row("TXT value", token, "Public")}
|
{_copy_row("TXT value", token, "Public")}
|
||||||
{_copy_row("Private claim link", claim_url, "Secret")}
|
{_copy_row("Private claim link", claim_url, "Secret")}
|
||||||
@@ -808,6 +810,8 @@ def _credentials_panel(service: DdnsService, created_account: dict[str, str] | N
|
|||||||
password = created_account["password"]
|
password = created_account["password"]
|
||||||
update_url = service.fritz_update_url(created_account)
|
update_url = service.fritz_update_url(created_account)
|
||||||
management_url = service.magic_management_url(created_account)
|
management_url = service.magic_management_url(created_account)
|
||||||
|
cname_record = f"your-subdomain.example.com. CNAME {hostname}."
|
||||||
|
fritzbox_fields = _fritzbox_fields(update_url, hostname, username, password, management_url)
|
||||||
return f"""
|
return f"""
|
||||||
<section class="section success-section">
|
<section class="section success-section">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
@@ -815,6 +819,10 @@ def _credentials_panel(service: DdnsService, created_account: dict[str, str] | N
|
|||||||
<h2>{html.escape(hostname)}</h2>
|
<h2>{html.escape(hostname)}</h2>
|
||||||
<p class="section-copy">Save this now. The password and private status page are only shown on this screen. To use your own DNS name, create a CNAME from that name to this hostname.</p>
|
<p class="section-copy">Save this now. The password and private status page are only shown on this screen. To use your own DNS name, create a CNAME from that name to this hostname.</p>
|
||||||
{_secret_notice()}
|
{_secret_notice()}
|
||||||
|
<div class="d-flex gap-2 flex-wrap my-3">
|
||||||
|
{_copy_button("Copy FRITZ!Box fields", fritzbox_fields)}
|
||||||
|
{_copy_button("Copy CNAME record", cname_record)}
|
||||||
|
</div>
|
||||||
<div class="d-grid gap-2">
|
<div class="d-grid gap-2">
|
||||||
{_copy_row("Update-URL:", update_url, "Secret")}
|
{_copy_row("Update-URL:", update_url, "Secret")}
|
||||||
{_copy_row("Domainnamen:", hostname, "Public")}
|
{_copy_row("Domainnamen:", hostname, "Public")}
|
||||||
@@ -860,6 +868,31 @@ def _copy_row(label: str, value: str, sensitivity: str | None = None) -> str:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def _copy_button(label: str, value: str) -> str:
|
||||||
|
safe_label = html.escape(label)
|
||||||
|
safe_value = html.escape(value)
|
||||||
|
return f'<button type="button" class="btn btn-outline-primary rounded-pill" data-copy="{safe_value}">{safe_label}</button>'
|
||||||
|
|
||||||
|
|
||||||
|
def _fritzbox_fields(
|
||||||
|
update_url: str,
|
||||||
|
hostname: str,
|
||||||
|
username: str,
|
||||||
|
password: str,
|
||||||
|
management_url: str | None = None,
|
||||||
|
) -> str:
|
||||||
|
lines = [
|
||||||
|
f"Update-URL: {update_url}",
|
||||||
|
f"Domainnamen: {hostname}",
|
||||||
|
f"CNAME target: {hostname}",
|
||||||
|
f"Benutzername: {username}",
|
||||||
|
f"Kennwort: {password}",
|
||||||
|
]
|
||||||
|
if management_url:
|
||||||
|
lines.append(f"Private status page: {management_url}")
|
||||||
|
return "\n".join(lines)
|
||||||
|
|
||||||
|
|
||||||
def _secret_notice() -> str:
|
def _secret_notice() -> str:
|
||||||
return """
|
return """
|
||||||
<div class="alert alert-info my-3 py-2 small" role="note">
|
<div class="alert alert-info my-3 py-2 small" role="note">
|
||||||
@@ -893,6 +926,8 @@ def _render_management_page(service: DdnsService, settings: DdnsSettings, manage
|
|||||||
ipv4 = html.escape(str(account.get("ipv4") or "-"))
|
ipv4 = html.escape(str(account.get("ipv4") or "-"))
|
||||||
ipv6 = html.escape(str(account.get("ipv6") or "-"))
|
ipv6 = html.escape(str(account.get("ipv6") or "-"))
|
||||||
updated = html.escape(str(account.get("updated_at") or "Never"))
|
updated = html.escape(str(account.get("updated_at") or "Never"))
|
||||||
|
fritzbox_fields = _fritzbox_fields(update_url, hostname, username, "unchanged; only shown when generated")
|
||||||
|
cname_record = f"your-subdomain.example.com. CNAME {hostname}."
|
||||||
history_rows = "\n".join(_user_event_row(event) for event in service.store.list_update_events_for_hostname(str(account["hostname"]), 20)) or """
|
history_rows = "\n".join(_user_event_row(event) for event in service.store.list_update_events_for_hostname(str(account["hostname"]), 20)) or """
|
||||||
<tr><td colspan="5" class="empty">No router updates yet.</td></tr>
|
<tr><td colspan="5" class="empty">No router updates yet.</td></tr>
|
||||||
"""
|
"""
|
||||||
@@ -917,6 +952,10 @@ def _render_management_page(service: DdnsService, settings: DdnsSettings, manage
|
|||||||
<h2>FRITZ!Box fields</h2>
|
<h2>FRITZ!Box fields</h2>
|
||||||
<p class="section-copy">Use these values in the FRITZ!Box custom DynDNS provider fields. If you use your own DNS name, point it at this hostname with a CNAME.</p>
|
<p class="section-copy">Use these values in the FRITZ!Box custom DynDNS provider fields. If you use your own DNS name, point it at this hostname with a CNAME.</p>
|
||||||
{_secret_notice()}
|
{_secret_notice()}
|
||||||
|
<div class="d-flex gap-2 flex-wrap mt-3">
|
||||||
|
{_copy_button("Copy FRITZ!Box fields", fritzbox_fields)}
|
||||||
|
{_copy_button("Copy CNAME record", cname_record)}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-lg-6 d-grid gap-2">
|
<div class="col-lg-6 d-grid gap-2">
|
||||||
{_copy_row("Update-URL:", update_url, "Secret")}
|
{_copy_row("Update-URL:", update_url, "Secret")}
|
||||||
|
|||||||
@@ -309,6 +309,8 @@ def test_self_service_managed_hostname_generates_random_account(tmp_path: Path)
|
|||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
assert "Update-URL:" in response.text
|
assert "Update-URL:" in response.text
|
||||||
assert "CNAME target:" in response.text
|
assert "CNAME target:" in response.text
|
||||||
|
assert "Copy FRITZ!Box fields" in response.text
|
||||||
|
assert "Copy CNAME record" in response.text
|
||||||
assert "Public:" in response.text
|
assert "Public:" in response.text
|
||||||
assert "Secret:" in response.text
|
assert "Secret:" in response.text
|
||||||
assert ".ddns.example.net" in response.text
|
assert ".ddns.example.net" in response.text
|
||||||
@@ -333,6 +335,8 @@ def test_magic_hostname_without_login_generates_update_and_management_links(tmp_
|
|||||||
assert "Update-URL:" in response.text
|
assert "Update-URL:" in response.text
|
||||||
assert "CNAME target:" in response.text
|
assert "CNAME target:" in response.text
|
||||||
assert "Private status page:" in response.text
|
assert "Private status page:" in response.text
|
||||||
|
assert "Copy FRITZ!Box fields" in response.text
|
||||||
|
assert "Copy CNAME record" in response.text
|
||||||
assert response.text.count("Secret") >= 3
|
assert response.text.count("Secret") >= 3
|
||||||
assert response.text.count("Public") >= 3
|
assert response.text.count("Public") >= 3
|
||||||
assert ".ddns.example.net" in response.text
|
assert ".ddns.example.net" in response.text
|
||||||
@@ -349,6 +353,8 @@ def test_magic_management_link_can_delete_hostname(tmp_path: Path) -> None:
|
|||||||
assert management.status_code == 200
|
assert management.status_code == 200
|
||||||
assert "home.ddns.example.net" in management.text
|
assert "home.ddns.example.net" in management.text
|
||||||
assert "CNAME target:" in management.text
|
assert "CNAME target:" in management.text
|
||||||
|
assert "Copy FRITZ!Box fields" in management.text
|
||||||
|
assert "Copy CNAME record" in management.text
|
||||||
assert "Public:" in management.text
|
assert "Public:" in management.text
|
||||||
assert "Secret:" in management.text
|
assert "Secret:" in management.text
|
||||||
assert "Router updates" in management.text
|
assert "Router updates" in management.text
|
||||||
|
|||||||
Reference in new issue
Block a user