Archived
90 lines
3.6 KiB
Python
90 lines
3.6 KiB
Python
from __future__ import annotations
|
|
|
|
import sqlite3
|
|
|
|
from fastapi import APIRouter, HTTPException, Request
|
|
from fastapi.responses import HTMLResponse, PlainTextResponse, RedirectResponse
|
|
from starlette.concurrency import run_in_threadpool
|
|
|
|
from ..ddns_security import client_ip
|
|
from ..ddns_service import normalize_domain
|
|
from ..dependencies import ServiceDep, SettingsDep
|
|
from ..web.forms import first_form_value, request_form
|
|
from ..web.templates_public import _render_privacy_page, _render_public_home
|
|
|
|
router = APIRouter()
|
|
|
|
|
|
@router.get("/", response_class=HTMLResponse, include_in_schema=False)
|
|
def index(settings: SettingsDep, service: ServiceDep) -> str:
|
|
return _render_public_home(service, settings, None, None)
|
|
|
|
|
|
@router.get("/magic", include_in_schema=False)
|
|
def magic_form() -> RedirectResponse:
|
|
return RedirectResponse("/#create", status_code=303)
|
|
|
|
|
|
@router.post("/magic", response_class=HTMLResponse, include_in_schema=False)
|
|
async def magic_account(request: Request, settings: SettingsDep, service: ServiceDep) -> str:
|
|
await request_form(request, settings)
|
|
account = await run_in_threadpool(service.create_managed_account, None)
|
|
return _render_public_home(service, settings, account, None)
|
|
|
|
|
|
@router.post("/request-domain", response_class=HTMLResponse, include_in_schema=False)
|
|
async def request_domain(request: Request, settings: SettingsDep, service: ServiceDep) -> str:
|
|
form = await request_form(request, settings)
|
|
try:
|
|
challenge = await run_in_threadpool(
|
|
service.create_domain_challenge,
|
|
first_form_value(form, "domain"),
|
|
)
|
|
except sqlite3.IntegrityError as exc:
|
|
raise HTTPException(status_code=409, detail="domain is already verified") from exc
|
|
return _render_public_home(service, settings, None, None, challenge)
|
|
|
|
|
|
@router.post("/verify-domain", response_class=HTMLResponse, include_in_schema=False)
|
|
async def verify_domain(request: Request, settings: SettingsDep, service: ServiceDep) -> str:
|
|
form = await request_form(request, settings)
|
|
domain = normalize_domain(first_form_value(form, "domain"))
|
|
claim_secret = first_form_value(form, "claim_secret")
|
|
found, challenge = await run_in_threadpool(service.verify_domain, domain, claim_secret)
|
|
if not found:
|
|
message = "TXT record not found yet. DNS propagation can take a few minutes."
|
|
return _render_public_home(service, settings, None, message, challenge)
|
|
return _render_public_home(service, settings, None, "Domain verified. You can now create a hostname under it.", challenge)
|
|
|
|
|
|
@router.post("/accounts", response_class=HTMLResponse, include_in_schema=False)
|
|
async def self_service_account(request: Request, settings: SettingsDep, service: ServiceDep) -> str:
|
|
form = await request_form(request, settings)
|
|
mode = first_form_value(form, "mode")
|
|
if mode == "managed":
|
|
account = await run_in_threadpool(service.create_managed_account, None)
|
|
else:
|
|
claim_secret = first_form_value(form, "claim_secret")
|
|
account = await run_in_threadpool(
|
|
service.create_custom_account,
|
|
first_form_value(form, "hostname"),
|
|
claim_secret,
|
|
None,
|
|
)
|
|
return _render_public_home(service, settings, account, None)
|
|
|
|
|
|
@router.get("/healthz", response_class=PlainTextResponse)
|
|
def healthz() -> str:
|
|
return "ok"
|
|
|
|
|
|
@router.get("/ip", response_class=PlainTextResponse)
|
|
def visible_ip(request: Request, settings: SettingsDep) -> str:
|
|
return client_ip(request, settings)
|
|
|
|
|
|
@router.get("/privacy", response_class=HTMLResponse, include_in_schema=False)
|
|
def privacy() -> str:
|
|
return _render_privacy_page()
|