Archived
Refactor UI assets and harden quality checks
This commit is contained in:
1 parent
23ab466c52
commit
4ecc8eb874
62 files changed
+3314
-3206
No files matched your search
@@ -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()
|
||||
|
||||
|
||||
Reference in new issue
Block a user