Refactor UI assets and harden quality checks

This commit is contained in:
StasonJatham committed 2026-06-17 23:18:00 +02:00
1 parent 23ab466c52
commit 4ecc8eb874
62 files changed
+3314 -3206

No files matched your search

+78 -45
View File
@@ -1,8 +1,8 @@
from __future__ import annotations
from typing import NoReturn
from typing import Annotated, NoReturn
from fastapi import APIRouter, HTTPException, Request, Response
from fastapi import APIRouter, Depends, HTTPException, Query, Request, Response
from fastapi.responses import HTMLResponse, PlainTextResponse, RedirectResponse
from starlette.concurrency import run_in_threadpool
@@ -14,11 +14,13 @@ from ..event_statuses import (
DASHBOARD_UPDATE_URL_ROTATED,
)
from ..security import client_ip, dashboard_csrf_token, require_dashboard_csrf
from ..services.ddns import BadIpError
from ..services.ddns import BadIpError, UpdateIpParams
from ..web.forms import first_form_value, request_form
from ..web.html_utils import trusted
from ..web.layout import _page
from ..web.templates_management import (
ManagementPageContext,
PendingManagementPageContext,
_render_management_page,
_render_management_unlock_page,
_render_pending_management_page,
@@ -36,6 +38,19 @@ from .path_params import ManagementSlugPath
router = APIRouter()
router.include_router(management_passwords.router)
ActivationIpQuery = Annotated[str | None, Query()]
def _activation_ip_params_from_query(
myip: ActivationIpQuery = None,
ipaddr: ActivationIpQuery = None,
myipv6: ActivationIpQuery = None,
ip6addr: ActivationIpQuery = None,
) -> UpdateIpParams:
return UpdateIpParams(myip=myip, ipaddr=ipaddr, myipv6=myipv6, ip6addr=ip6addr)
ActivationIpParamsDep = Annotated[UpdateIpParams, Depends(_activation_ip_params_from_query)]
@router.get("/m/{management_slug}", response_class=HTMLResponse, include_in_schema=False)
@@ -43,27 +58,34 @@ def manage_dashboard(
management_slug: ManagementSlugPath,
request: Request,
settings: SettingsDep,
store: StoreDep,
service: ServiceDep,
activated: bool = False,
) -> str:
account = get_active_management_account(store, management_slug)
account = get_active_management_account(service.store, management_slug)
csrf_token = dashboard_csrf_token(management_slug, account)
if not management_account_is_accepted(account):
return _render_pending_management_page(
service, settings, management_slug, account, csrf_token, request_ip=client_ip(request, settings)
service,
PendingManagementPageContext(
settings=settings,
management_slug=management_slug,
account=account,
csrf_token=csrf_token,
request_ip=client_ip(request, settings),
),
)
if not has_management_access(request, settings, management_slug, account):
return _render_management_unlock_page(management_slug, account, csrf_token)
message = "Hostname registered. Add the update URL to your router." if activated else None
return _render_management_page(
service,
settings,
management_slug,
account,
csrf_token,
message=message,
request_ip=client_ip(request, settings),
ManagementPageContext(
management_slug=management_slug,
account=account,
csrf_token=csrf_token,
message=message,
request_ip=client_ip(request, settings),
),
)
@@ -72,30 +94,36 @@ async def activate_dashboard(
management_slug: ManagementSlugPath,
request: Request,
settings: SettingsDep,
store: StoreDep,
service: ServiceDep,
myip: str | None = None,
ipaddr: str | None = None,
myipv6: str | None = None,
ip6addr: str | None = None,
ip_params: ActivationIpParamsDep,
) -> RedirectResponse | HTMLResponse:
account = await get_active_management_account_async(store, management_slug)
account = await get_active_management_account_async(service.store, management_slug)
form = await request_form(request, settings)
require_dashboard_csrf(management_slug, account, first_form_value(form, "csrf"))
hostname = str(account["hostname"])
if not management_account_is_accepted(account):
try:
await run_in_threadpool(service.publish_initial_dns, request, hostname, myip, ipaddr, myipv6, ip6addr)
await run_in_threadpool(
service.publish_initial_dns,
request,
hostname,
ip_params,
)
except BadIpError:
return HTMLResponse(
_render_pending_management_page(
service,
settings,
management_slug,
account,
dashboard_csrf_token(management_slug, account),
"The supplied IP address is invalid. Leave IP fields empty and let the router send the first update.",
client_ip(request, settings),
PendingManagementPageContext(
settings=settings,
management_slug=management_slug,
account=account,
csrf_token=dashboard_csrf_token(management_slug, account),
message=(
"The supplied IP address is invalid. Leave IP fields empty and let the router "
"send the first update."
),
request_ip=client_ip(request, settings),
),
),
status_code=400,
)
@@ -103,20 +131,22 @@ async def activate_dashboard(
return HTMLResponse(
_render_pending_management_page(
service,
settings,
management_slug,
account,
dashboard_csrf_token(management_slug, account),
"DNS registration failed. The hostname was not registered.",
client_ip(request, settings),
PendingManagementPageContext(
settings=settings,
management_slug=management_slug,
account=account,
csrf_token=dashboard_csrf_token(management_slug, account),
message="DNS registration failed. The hostname was not registered.",
request_ip=client_ip(request, settings),
),
),
status_code=500,
)
activated_account = await run_in_threadpool(lambda: store.activate_account(hostname))
activated_account = await run_in_threadpool(lambda: service.store.activate_account(hostname))
if not activated_account:
return _not_found()
await run_in_threadpool(
store.log_update_event,
service.store.log_update_event,
hostname,
None,
None,
@@ -140,12 +170,14 @@ async def rotate_dashboard_secrets(
return HTMLResponse(
_render_pending_management_page(
service,
settings,
management_slug,
account,
dashboard_csrf_token(management_slug, account),
"Register this hostname first.",
client_ip(request, settings),
PendingManagementPageContext(
settings=settings,
management_slug=management_slug,
account=account,
csrf_token=dashboard_csrf_token(management_slug, account),
message="Register this hostname first.",
request_ip=client_ip(request, settings),
),
),
status_code=400,
)
@@ -171,12 +203,13 @@ async def rotate_dashboard_secrets(
)
return await render_management_page_async(
service,
settings,
management_slug,
rotated,
dashboard_csrf_token(management_slug, rotated),
message="Update URL changed. Update your router now.",
request_ip=request_ip,
ManagementPageContext(
management_slug=management_slug,
account=rotated,
csrf_token=dashboard_csrf_token(management_slug, rotated),
message="Update URL changed. Update your router now.",
request_ip=request_ip,
),
)
raise _bad_rotation_action()