Archived
Polish KarlDNS production UI and docs
This commit is contained in:
1 parent
ca92dc211a
commit
5beee0e5c6
61 files changed
+1566
-523
No files matched your search
@@ -57,10 +57,10 @@ def _render_management_page(
|
||||
{_top_nav()}
|
||||
<section class="hero-band compact">
|
||||
<div class="container text-center d-grid justify-items-center gap-3">
|
||||
<p class="eyebrow">Magic management</p>
|
||||
<p class="eyebrow">Dashboard</p>
|
||||
<h1>{hostname}</h1>
|
||||
<p class="lead">Anyone with this link can manage or delete this hostname. Keep it private.</p>
|
||||
<a class="btn btn-outline-primary rounded-pill" href="/">Back home</a>
|
||||
<p class="lead">This private link can manage this hostname. Keep it safe.</p>
|
||||
<a class="btn btn-outline-primary rounded-pill" href="/">Home</a>
|
||||
</div>
|
||||
</section>
|
||||
{message_html}
|
||||
@@ -71,12 +71,12 @@ def _render_management_page(
|
||||
<div class="col-lg-6">
|
||||
<p class="eyebrow">Router settings</p>
|
||||
<h2>Router update settings</h2>
|
||||
<p class="section-copy">Use the Update-URL directly if your router only has one URL field. Separate Benutzername and Kennwort values are optional compatibility fields. If you use your own DNS name, point it at this hostname with a CNAME.</p>
|
||||
<p class="section-copy">Use the Update-URL if your router has one URL field. Username and password are only for routers that require them. For your own subdomain, create a CNAME to this hostname.</p>
|
||||
{_one_time_secret_notice()}
|
||||
{_secret_notice()}
|
||||
<div class="d-flex gap-2 flex-wrap mt-3">
|
||||
{_copy_button("Copy complete FRITZ!Box fields", fritzbox_fields)}
|
||||
{_copy_button("Copy CNAME record", cname_record)}
|
||||
{_copy_button("Copy router fields", fritzbox_fields)}
|
||||
{_copy_button("Copy CNAME", cname_record)}
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-6 d-grid gap-2">
|
||||
@@ -91,19 +91,19 @@ def _render_management_page(
|
||||
<div class="card card-body gap-3 mt-4">
|
||||
<div>
|
||||
<p class="eyebrow">Actions</p>
|
||||
<h3>Rotate dashboard secrets</h3>
|
||||
<p class="section-copy">Rotate the URL used by routers, or issue a new router password for compatibility clients. Update your router after rotating.</p>
|
||||
<h3>Replace router secrets</h3>
|
||||
<p class="section-copy">Create a new update URL or router password. Update your router after changing either one.</p>
|
||||
</div>
|
||||
<div class="d-flex gap-2 flex-wrap">
|
||||
<form method="post" action="/m/{attr(management_slug)}/rotate">
|
||||
<input type="hidden" name="csrf" value="{attr(csrf_token)}">
|
||||
<input type="hidden" name="action" value="update">
|
||||
<button class="btn btn-outline-primary rounded-pill" type="submit">Rotate Update-URL</button>
|
||||
<button class="btn btn-outline-primary rounded-pill" type="submit">New update URL</button>
|
||||
</form>
|
||||
<form method="post" action="/m/{attr(management_slug)}/rotate">
|
||||
<input type="hidden" name="csrf" value="{attr(csrf_token)}">
|
||||
<input type="hidden" name="action" value="password">
|
||||
<button class="btn btn-outline-primary rounded-pill" type="submit">Rotate router credentials</button>
|
||||
<button class="btn btn-outline-primary rounded-pill" type="submit">New password</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
@@ -134,7 +134,7 @@ def _render_management_page(
|
||||
<div>
|
||||
<p class="eyebrow">History</p>
|
||||
<h2>Router updates</h2>
|
||||
<p class="section-copy">Recent IP changes and failed DNS publishes for this hostname.</p>
|
||||
<p class="section-copy">Recent IP changes and failed updates for this hostname.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="table-responsive border rounded admin-table-scroll">
|
||||
@@ -148,7 +148,7 @@ def _render_management_page(
|
||||
<section class="section danger-section">
|
||||
<div class="container d-flex align-items-md-center justify-content-between gap-4 flex-column flex-md-row">
|
||||
<div>
|
||||
<p class="eyebrow">Danger zone</p>
|
||||
<p class="eyebrow">Delete</p>
|
||||
<h2>Delete hostname</h2>
|
||||
<p class="section-copy">This removes the hostname and DNS records. The router update URL will stop working.</p>
|
||||
</div>
|
||||
@@ -160,6 +160,7 @@ def _render_management_page(
|
||||
</section>
|
||||
</main>
|
||||
"""),
|
||||
extra_styles=trusted('<link href="/admin.css?v=2" rel="stylesheet">'),
|
||||
)
|
||||
|
||||
def _management_message(message: str | None) -> SafeHtml:
|
||||
@@ -176,22 +177,22 @@ def _management_message(message: str | None) -> SafeHtml:
|
||||
|
||||
def _dashboard_password_panel(management_slug: str, csrf_token: str, password_enabled: bool) -> SafeHtml:
|
||||
password_status = "Enabled" if password_enabled else "Not enabled"
|
||||
password_action = "Change dashboard password" if password_enabled else "Set dashboard password"
|
||||
password_action = "Change password" if password_enabled else "Set password"
|
||||
remove_form = ""
|
||||
if password_enabled:
|
||||
remove_form = f"""
|
||||
<form class="card card-body gap-3" method="post" action="/m/{attr(management_slug)}/password/remove">
|
||||
<input type="hidden" name="csrf" value="{attr(csrf_token)}">
|
||||
<label class="form-label" for="dashboard-remove-current-password">Current dashboard password</label>
|
||||
<label class="form-label" for="dashboard-remove-current-password">Current password</label>
|
||||
<input class="form-control" id="dashboard-remove-current-password" name="current_dashboard_password" type="password" autocomplete="current-password" required>
|
||||
<button class="btn btn-outline-danger rounded-pill" type="submit">Remove dashboard password</button>
|
||||
<button class="btn btn-outline-danger rounded-pill" type="submit">Remove password</button>
|
||||
</form>
|
||||
"""
|
||||
current_password_field = ""
|
||||
if password_enabled:
|
||||
current_password_field = """
|
||||
<div>
|
||||
<label class="form-label" for="dashboard-current-password">Current dashboard password</label>
|
||||
<label class="form-label" for="dashboard-current-password">Current password</label>
|
||||
<input class="form-control" id="dashboard-current-password" name="current_dashboard_password" type="password" autocomplete="current-password" required>
|
||||
</div>
|
||||
"""
|
||||
@@ -203,7 +204,7 @@ def _dashboard_password_panel(management_slug: str, csrf_token: str, password_en
|
||||
<div class="col-lg-5">
|
||||
<p class="eyebrow">Dashboard password</p>
|
||||
<h2>Password protection</h2>
|
||||
<p class="section-copy">Status: {escape(password_status)}. This protects this management dashboard only. Router update URLs continue to work normally.</p>
|
||||
<p class="section-copy">Status: {escape(password_status)}. This password protects only this dashboard. Router updates still work.</p>
|
||||
</div>
|
||||
<div class="col-lg-7 d-grid gap-3">
|
||||
<form class="card card-body gap-3" method="post" action="/m/{attr(management_slug)}/password">
|
||||
@@ -249,7 +250,7 @@ def _render_management_unlock_page(
|
||||
<div class="container text-center d-grid justify-items-center gap-3">
|
||||
<p class="eyebrow">Dashboard locked</p>
|
||||
<h1>{hostname}</h1>
|
||||
<p class="lead">Enter the dashboard password to manage this hostname.</p>
|
||||
<p class="lead">Enter the dashboard password for this hostname.</p>
|
||||
</div>
|
||||
</section>
|
||||
<section class="section">
|
||||
@@ -263,9 +264,9 @@ def _render_management_unlock_page(
|
||||
</div>
|
||||
<label class="form-check d-flex align-items-center gap-2">
|
||||
<input class="form-check-input" type="checkbox" name="stay_unlocked" value="1">
|
||||
<span class="form-check-label">Stay unlocked for 30 days on this browser</span>
|
||||
<span class="form-check-label">Remember this browser for 30 days</span>
|
||||
</label>
|
||||
<button class="btn btn-primary rounded-pill" type="submit">Unlock dashboard</button>
|
||||
<button class="btn btn-primary rounded-pill" type="submit">Unlock</button>
|
||||
</form>
|
||||
</div>
|
||||
</section>
|
||||
@@ -285,15 +286,15 @@ def _management_domain_claim_panel(
|
||||
<div class="card card-body gap-3">
|
||||
<div>
|
||||
<p class="eyebrow">Custom domain</p>
|
||||
<h2>Claim a domain</h2>
|
||||
<p class="section-copy">Create a TXT challenge, verify it from this dashboard, then create router credentials for a hostname under that verified domain.</p>
|
||||
<h2>Use your domain</h2>
|
||||
<p class="section-copy">Create a TXT record, verify it here, then create a hostname under that domain.</p>
|
||||
</div>
|
||||
<form method="post" action="/m/{attr(management_slug)}/domains/request" class="d-grid gap-3" aria-label="Create dashboard domain claim">
|
||||
<input type="hidden" name="csrf" value="{attr(csrf_token)}">
|
||||
<label>Domain
|
||||
<input class="form-control" name="domain" placeholder="example.com" autocomplete="off" autocapitalize="none" spellcheck="false" required>
|
||||
</label>
|
||||
<button type="submit" class="btn btn-primary rounded-pill">Create domain claim</button>
|
||||
<button type="submit" class="btn btn-primary rounded-pill">Create claim</button>
|
||||
</form>
|
||||
</div>
|
||||
"""
|
||||
@@ -312,7 +313,7 @@ def _management_domain_claim_panel(
|
||||
verification_name = service.verification_name(domain)
|
||||
token = str(challenge["token"])
|
||||
claim_url = service.domain_claim_url(challenge)
|
||||
status = "Verified" if challenge.get("verified_at") else "Waiting for TXT verification"
|
||||
status = "Verified" if challenge.get("verified_at") else "Waiting for TXT"
|
||||
txt_bundle = f"TXT name: {verification_name}\nTXT value: {token}"
|
||||
create_hostname = _management_custom_hostname_form(management_slug, claim_secret, csrf_token) if challenge.get("verified_at") else trusted("")
|
||||
return trusted(
|
||||
@@ -325,11 +326,11 @@ def _management_domain_claim_panel(
|
||||
<p class="eyebrow">Domain claim</p>
|
||||
<h2>{escape(domain)}</h2>
|
||||
<p class="section-copy">Status: {escape(status)}</p>
|
||||
<p class="small text-secondary mb-0">This claim belongs to this dashboard. Another dashboard cannot verify or use it.</p>
|
||||
<p class="small text-secondary mb-0">This claim belongs to this dashboard. Other dashboards cannot use it.</p>
|
||||
</div>
|
||||
<div class="alert alert-info mb-0 py-2 small">TXT name and value are public DNS records. The claim secret and private claim link are secrets.</div>
|
||||
<div class="alert alert-info mb-0 py-2 small">TXT name and value are public. Claim secret and private claim link are secret.</div>
|
||||
<div class="d-flex gap-2 flex-wrap">
|
||||
{_copy_button("Copy TXT record", txt_bundle)}
|
||||
{_copy_button("Copy TXT", txt_bundle)}
|
||||
</div>
|
||||
<div class="d-grid gap-2">
|
||||
{_copy_row("TXT name", verification_name, "Public")}
|
||||
@@ -341,7 +342,7 @@ def _management_domain_claim_panel(
|
||||
<input type="hidden" name="csrf" value="{attr(csrf_token)}">
|
||||
<input type="hidden" name="domain" value="{attr(domain)}">
|
||||
<input type="hidden" name="claim_secret" value="{attr(claim_secret)}">
|
||||
<button type="submit" class="btn btn-primary rounded-pill">Verify claim</button>
|
||||
<button type="submit" class="btn btn-primary rounded-pill">Verify</button>
|
||||
</form>
|
||||
{create_hostname}
|
||||
</div>
|
||||
@@ -358,10 +359,10 @@ def _management_custom_hostname_form(management_slug: str, claim_secret: str, cs
|
||||
<form method="post" action="/m/{attr(management_slug)}/domains/hostnames" class="d-grid gap-3" aria-label="Create verified custom hostname">
|
||||
{csrf_field}
|
||||
<input type="hidden" name="claim_secret" value="{attr(claim_secret)}">
|
||||
<label>Custom hostname
|
||||
<label>Hostname
|
||||
<input class="form-control" name="hostname" placeholder="home.example.com" autocomplete="off" autocapitalize="none" spellcheck="false" required>
|
||||
</label>
|
||||
<button type="submit" class="btn btn-primary rounded-pill">Create custom hostname</button>
|
||||
<button type="submit" class="btn btn-primary rounded-pill">Create hostname</button>
|
||||
</form>
|
||||
"""
|
||||
)
|
||||
|
||||
Reference in new issue
Block a user