feat(landing): self-serve registration page via Drasl API (B1)
Add a static /register page (en/es/eu) that calls the Drasl REST API v2 directly from the browser: register -> login -> optional skin upload, all in the pixel design. Guests never touch Drasl's own web UI. Drasl config gains the pieces this needs: - CORSAllowOrigins scoped to the apex (the API has no CORS until set; never "*"). - [RateLimit] for the now public-facing anonymous POST /users. - [RegistrationNewPlayer] with RequireInvite driven by a new REGISTRATION_MODE (invite|open) .env flag. REGISTRATION_MODE has two consumers from one key: render-config.sh derives the TOML boolean for Drasl (drasl is TOML-only, no env), and the landing build reads it to show/hide the invite-code field. render-config.sh halts on any value other than invite/open. Security verified against drasl source: anonymous POST /users cannot set privileged fields (isAdmin/isLocked/chosenUuid/maxPlayerCount are gated on callerIsAdmin in CreateUser), so browser-direct registration is safe. Docs: plan/16-landing-registration.md captures the design + the B1 vs fork decision; build-order, deploy, and the deploy skill wire REGISTRATION_MODE and the landing-rebuild requirement (www/ is gitignored, not updated by a git pull). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
# Drasl config — password-login mode (NO Keycloak/OIDC for now).
|
||||
# TOML only (drasl has no env support). Rendered by tooling/render-config.sh
|
||||
# -> drasl/config/config.toml (gitignored). Only ${BASE_DOMAIN} is substituted.
|
||||
# -> drasl/config/config.toml (gitignored). Substitutes ${BASE_DOMAIN} and
|
||||
# ${REGISTRATION_REQUIRE_INVITE} (derived from REGISTRATION_MODE in .env).
|
||||
# Reached only via Caddy at auth.${BASE_DOMAIN}; drasl has no published host port.
|
||||
|
||||
# Public scheme is HTTPS — the host nginx terminates TLS in front of caddy.
|
||||
@@ -21,5 +22,27 @@ SignPublicKeys = false
|
||||
# Free-text owner label shown in the web UI (a string, not a table).
|
||||
ApplicationOwner = "Ulicraft"
|
||||
|
||||
# New-account registration (username+password). RequireInvite is derived from
|
||||
# REGISTRATION_MODE in .env by render-config.sh: invite -> true, open -> false.
|
||||
# When true, non-admin callers (web UI + landing register form) must supply a
|
||||
# valid invite code; admins bypass. Mint codes via POST /drasl/api/v2/invites
|
||||
# with an admin api token.
|
||||
[RegistrationNewPlayer]
|
||||
Allow = true
|
||||
RequireInvite = ${REGISTRATION_REQUIRE_INVITE}
|
||||
|
||||
# CORS: the landing register/account form (served from the apex) calls the
|
||||
# Drasl API from the browser. Without this the API has NO CORS headers and the
|
||||
# browser blocks every cross-origin call. Scope to the apex only — never "*",
|
||||
# which would let any site script the auth API. Echo backfills AllowMethods
|
||||
# (incl. PATCH/DELETE) and reflects requested headers (Content-Type/Authorization).
|
||||
CORSAllowOrigins = ["https://${BASE_DOMAIN}"]
|
||||
|
||||
# Rate limit the now public-facing API (anonymous POST /users etc). Token
|
||||
# bucket; admins are exempt. Conservative for a 4-10 player server.
|
||||
[RateLimit]
|
||||
RequestsPerSecond = 5
|
||||
Burst = 10
|
||||
|
||||
# OIDC block intentionally omitted for now (no Keycloak).
|
||||
# [[RegistrationOIDC]] <- future task
|
||||
|
||||
Reference in New Issue
Block a user