Archived
Build KarlDNS self-hosted DynDNS service
This commit is contained in:
1 parent
45bc38d950
commit
ca92dc211a
65 files changed
+9200
-3570
No files matched your search
@@ -0,0 +1,89 @@
|
||||
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()
|
||||
Reference in new issue
Block a user