from __future__ import annotations
from ..services.ddns import DdnsService
from ..settings import DdnsSettings
from .components import (
_copy_menu,
_copy_row,
_event_label,
_fritzbox_fields,
_manual_update_commands,
_manual_update_panel,
_secret_notice,
)
from .html_utils import SafeHtml, attr, escape, trusted
from .layout import _page, _top_nav
from .templates_public_sections import _created_hostname_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,
request_ip: str | None = None,
) -> str:
account_for_url = {
"hostname": str(account["hostname"]),
"update_slug": str(account["update_slug"]),
"management_slug": management_slug,
}
update_url = service.fritz_update_url(account_for_url)
hostname = escape(account["hostname"])
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)
cname_record = f"your-subdomain.example.com. CNAME {hostname}."
manual_commands = _manual_update_commands(update_url, request_ip)
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_links = _created_hostname_panel(service, created_account, request_ip)
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_links}
Router settings
Router update settings
Use this Update-URL in your router or script. Optional: point another DNS name at this hostname with a CNAME.
{_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")}
{_manual_update_panel(manual_commands)}
Actions
Replace router update URL
Create a new update URL. Update your router after changing it.
{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 _render_pending_management_page(
settings: DdnsSettings,
management_slug: str,
account: dict[str, str | int | None],
csrf_token: str,
message: str | None = None,
) -> str:
hostname = escape(account["hostname"])
message_html = _management_message(message)
cleanup_hours = settings.cleanup_pending_account_hours
cleanup_text = f"{cleanup_hours} hours" if cleanup_hours != 24 else "24 hours"
return _page(
"Register hostname",
trusted(f"""
{_top_nav()}
Pending setup
{hostname}
Register this hostname after you have copied the private values. Unregistered setups are cleaned up after {escape(cleanup_text)}.
{message_html}
Lost the first page? Create a new hostname. Private URLs are shown only once.
"""),
)
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 = """
"""
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_label(event.get("status")))
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} |
"