from __future__ import annotations
from ..ddns_models import DdnsSettings
from ..ddns_service import DdnsService
from .html_utils import SafeHtml, attr, escape, trusted
from .templates import (
_copy_menu,
_copy_row,
_fritzbox_fields,
_manual_update_commands,
_manual_update_panel,
_one_time_secret_notice,
_page,
_secret_notice,
_top_nav,
)
from .templates_public_sections import _credentials_panel
def _render_management_page(
service: DdnsService,
settings: DdnsSettings,
management_slug: str,
account: dict[str, str | int | None],
csrf_token: str,
message: str | None = None,
created_account: dict[str, str] | None = None,
) -> str:
account_for_url = {
"hostname": str(account["hostname"]),
"username": str(account["username"]),
"password": "",
"update_slug": str(account["update_slug"]),
"management_slug": management_slug,
}
update_url = service.fritz_update_url(account_for_url)
hostname = escape(account["hostname"])
username = escape(account["username"])
ipv4 = escape(account.get("ipv4") or "-")
ipv6 = escape(account.get("ipv6") or "-")
updated = escape(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}."
manual_commands = _manual_update_commands(update_url)
history_rows = "\n".join(_user_event_row(event) for event in service.store.list_update_events_for_hostname(str(account["hostname"]), 10)) or """
No router updates yet.
"""
message_html = _management_message(message)
rotated_credentials = _credentials_panel(service, created_account)
dashboard_password_panel = _dashboard_password_panel(management_slug, csrf_token, bool(account.get("dashboard_password_hash")))
return _page(
"KarlDNS management",
trusted(f"""
{_top_nav()}
Dashboard
{hostname}
This private link can manage this hostname. Keep it safe.
Home
{message_html}
{rotated_credentials}
Router settings
Router update settings
Use the Update-URL if your router has one URL field. Username and password are only for routers that require them. Optional: point another DNS name at this hostname with a CNAME.
{_one_time_secret_notice()}
{_secret_notice()}
{_copy_menu("Copy setup values", [("Router fields", fritzbox_fields), ("CNAME", cname_record)])}
{_copy_row("Update-URL:", update_url, "Secret")}
{_copy_row("Domainnamen:", hostname, "Public")}
{_copy_row("CNAME target:", hostname, "Public")}
{_copy_row("Benutzername (optional):", username, "Public")}
{_copy_row("Kennwort (optional):", "unchanged; only shown when generated", "Secret")}
{_manual_update_panel(manual_commands)}
Actions
Replace router secrets
Create a new update URL or router password. Update your router after changing either one.
{dashboard_password_panel}
IPv4 {ipv4}
IPv6 {ipv6}
Updated {updated}
History
Router updates
Recent IP changes and failed updates for this hostname.
Delete
Delete hostname
This removes the hostname and DNS records. The router update URL will stop working.
"""),
extra_styles=trusted(' '),
)
def _management_message(message: str | None) -> SafeHtml:
if not message:
return trusted("")
return trusted(
f"""
"""
)
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 password" if password_enabled else "Set password"
remove_form = ""
if password_enabled:
remove_form = f"""
"""
current_password_field = ""
if password_enabled:
current_password_field = """
Current password
"""
return trusted(
f"""
Dashboard password
Password protection
Status: {escape(password_status)}. This password protects only this dashboard. Router updates still work.
"""
)
def _render_management_unlock_page(
management_slug: str,
account: dict[str, str | int | None],
csrf_token: str,
message: str | None = None,
) -> str:
hostname = escape(account["hostname"])
message_html = ""
if message:
message_html = f'{escape(message)}
'
return _page(
"Unlock KarlDNS management",
trusted(f"""
{_top_nav()}
Dashboard locked
{hostname}
Enter the dashboard password for this hostname.
"""),
)
def _user_event_row(event: dict[str, str | int | None]) -> str:
created = escape(event.get("created_at") or "-")
status = escape(event.get("status") or "-")
ipv4 = escape(event.get("ipv4") or "-")
ipv6 = escape(event.get("ipv6") or "-")
count = escape(event.get("count") or 1)
detail = escape(event.get("detail") or "-")
return f"{created} {status} {ipv4} {ipv6} {count} {detail} "