From e798365be26a0cbce3f345dec46b7822fdc2dc38 Mon Sep 17 00:00:00 2001 From: mrhid6 Date: Fri, 24 Jul 2026 09:56:54 +0100 Subject: [PATCH] feat: Removed comments --- server/internal/services/users.go | 2 +- server/internal/services/workflow_runner.go | 65 +- site/app/globals.css | 16 +- site/app/page.tsx | 6 +- site/components/InstrumentPanel.tsx | 271 ++-- site/components/OrgForm.tsx | 4 +- site/next-env.d.ts | 8 +- site/next.config.ts | 4 +- sitesvc/cmd/main.go | 19 +- sitesvc/internal/api/api.go | 29 +- sitesvc/internal/api/signup.go | 19 +- sitesvc/internal/mail/mail.go | 27 +- sitesvc/internal/provision/provision.go | 9 +- web/app/(app)/keys/[id]/page.tsx | 4 +- web/app/(app)/keys/page.tsx | 360 +++-- web/app/(app)/monitors/[id]/page.tsx | 408 +++--- web/app/(app)/monitors/page.tsx | 2 +- web/app/(app)/servers/[id]/page.tsx | 203 +-- web/app/(app)/settings/page.tsx | 11 +- web/app/(app)/steps/page.tsx | 2 +- .../workflows/[id]/runs/[runId]/page.tsx | 23 +- web/app/setup/page.tsx | 6 +- web/components/AuthProvider.tsx | 145 +- web/components/Sidebar.tsx | 302 ++-- web/lib/api.ts | 1288 ++++++++--------- web/lib/guacConsole.ts | 30 +- web/next-env.d.ts | 8 +- 27 files changed, 1557 insertions(+), 1714 deletions(-) diff --git a/server/internal/services/users.go b/server/internal/services/users.go index f2f1b36..ceb326b 100644 --- a/server/internal/services/users.go +++ b/server/internal/services/users.go @@ -17,7 +17,7 @@ import ( -var ErrLastOwner = errors.New("this is the organization's last owner — promote another member to owner first") +var ErrLastOwner = errors.New("this is the organization's last owner promote another member to owner first") diff --git a/server/internal/services/workflow_runner.go b/server/internal/services/workflow_runner.go index 0f9230d..0da1cfb 100644 --- a/server/internal/services/workflow_runner.go +++ b/server/internal/services/workflow_runner.go @@ -17,8 +17,6 @@ import ( const stepDispatchGrace = 15 * time.Second - - func TriggerWorkflow(orgID, workflowID, actor string) (string, error) { wf, err := GetWorkflow(orgID, workflowID) if err != nil { @@ -30,13 +28,11 @@ func TriggerWorkflow(orgID, workflowID, actor string) (string, error) { if len(wf.Steps) == 0 { return "", fmt.Errorf("workflow has no steps") } - - + if err := validateTargetServers(orgID, wf.TargetServerIDs); err != nil { return "", err } - ctx, cancel := wfCtx() running := db.Col("workflow_runs").FindOne(ctx, bson.M{"org_id": orgID, "workflow_id": workflowID, "status": "running"}) cancel() @@ -82,8 +78,6 @@ func TriggerWorkflow(orgID, workflowID, actor string) (string, error) { return run.RunID, nil } - - func resolveSteps(orgID string, wf *models.Workflow) ([]models.ResolvedStep, error) { ctx, cancel := wfCtx() defer cancel() @@ -133,7 +127,6 @@ func resolveSteps(orgID string, wf *models.Workflow) ([]models.ResolvedStep, err return out, nil } - func resolveInlineStep(ref models.WorkflowStepRef) models.ResolvedStep { in := ref.Inline inputs := map[string]string{} @@ -162,7 +155,6 @@ func resolveInlineStep(ref models.WorkflowStepRef) models.ResolvedStep { } } - func executeRun(runID string) { run, err := getRunByID(runID) if err != nil { @@ -179,7 +171,6 @@ func executeRun(runID string) { <-done } - final, _ := getRunByID(runID) status := "success" for _, sr := range final.ServerRuns { @@ -194,20 +185,18 @@ func executeRun(runID string) { bson.M{"$set": bson.M{"status": status, "finished_at": now}}) } - - func runServer(orgID, runID string, srvIdx int, steps []models.ResolvedStep, serverID string) { now := time.Now() setServerRun(runID, srvIdx, bson.M{"server_runs.$.status": "running", "server_runs.$.started_at": now}) if !Dispatcher.IsConnected(serverID) { fin := time.Now() - _, _ = AppendMarker(runID, serverID, "agent not connected — server skipped") + _, _ = AppendMarker(runID, serverID, "agent not connected server skipped") setServerRun(runID, srvIdx, bson.M{"server_runs.$.status": "skipped", "server_runs.$.finished_at": fin}) return } - _, _ = AppendMarker(runID, serverID, fmt.Sprintf("run started on %s — %d step(s), workspace vantage-run-%s", serverID, len(steps), runID)) + _, _ = AppendMarker(runID, serverID, fmt.Sprintf("run started on %s %d step(s), workspace vantage-run-%s", serverID, len(steps), runID)) runEnv := map[string]string{} allSecrets := map[string]string{} @@ -223,14 +212,11 @@ func runServer(orgID, runID string, srvIdx int, steps []models.ResolvedStep, ser maxAttempts = step.MaxRetries + 1 } - secretVals := resolveSecrets(orgID, step.SecretRefs) for k, v := range secretVals { allSecrets[k] = v } - - - + subst := map[string]string{} for k, v := range runEnv { subst[k] = v @@ -249,8 +235,6 @@ func runServer(orgID, runID string, srvIdx int, steps []models.ResolvedStep, ser cmdEnv[k] = v } - - marker := fmt.Sprintf("===== step %d/%d: %s (%s) =====", step.Order+1, len(steps), step.Name, step.Interpreter) offset, _ := AppendMarker(runID, serverID, marker) logPath := ServerRunLogPath(runID, serverID) @@ -262,8 +246,7 @@ func runServer(orgID, runID string, srvIdx int, steps []models.ResolvedStep, ser if attempts > 1 { _, _ = AppendMarker(runID, serverID, fmt.Sprintf("retry %d/%d after failure", attempts-1, maxAttempts-1)) } - - + _ = StepLogs.Open(commandID, logPath, secretsSlice) res = dispatchAndWait(serverID, commandID, &pb.RunStepCmd{ Interpreter: step.Interpreter, @@ -272,18 +255,18 @@ func runServer(orgID, runID string, srvIdx int, steps []models.ResolvedStep, ser TimeoutSeconds: 0, WorkspaceId: runID, }) - StepLogs.Close(commandID) + StepLogs.Close(commandID) if res != nil && res.ExitCode == 0 { break } } exit := 1 - outEnv := map[string]string{} + outEnv := map[string]string{} if res != nil { exit = res.ExitCode for k, v := range res.OutputEnv { - runEnv[k] = v + runEnv[k] = v outEnv[k] = maskSecrets(v, allSecrets) } } else { @@ -297,26 +280,24 @@ func runServer(orgID, runID string, srvIdx int, steps []models.ResolvedStep, ser finishStep(runID, serverID, i, status, attempts, exit, offset, outEnv) dur := time.Since(stepStart).Round(time.Millisecond) - _, _ = AppendMarker(runID, serverID, fmt.Sprintf("step %d/%d %s — exit %d, %d attempt(s), %s", + _, _ = AppendMarker(runID, serverID, fmt.Sprintf("step %d/%d %s exit %d, %d attempt(s), %s", step.Order+1, len(steps), status, exit, attempts, dur)) if exit != 0 { switch step.OnFailure { case "continue": - _, _ = AppendMarker(runID, serverID, "on_failure=continue — proceeding to next step") - default: + _, _ = AppendMarker(runID, serverID, "on_failure=continue proceeding to next step") + default: serverFailed = true } if serverFailed { - _, _ = AppendMarker(runID, serverID, "stopping run — remaining steps skipped") + _, _ = AppendMarker(runID, serverID, "stopping run remaining steps skipped") markRemainingSkipped(runID, serverID, i+1) break } } } - - DispatchCleanupWorkspace(serverID, runID) fin := time.Now() @@ -324,10 +305,9 @@ func runServer(orgID, runID string, srvIdx int, steps []models.ResolvedStep, ser if serverFailed { status = "failed" } - _, _ = AppendMarker(runID, serverID, fmt.Sprintf("run %s in %s — workspace removed", + _, _ = AppendMarker(runID, serverID, fmt.Sprintf("run %s in %s workspace removed", status, fin.Sub(now).Round(time.Millisecond))) - - + maskedRunEnv := make(map[string]string, len(runEnv)) for k, v := range runEnv { maskedRunEnv[k] = maskSecrets(v, allSecrets) @@ -339,8 +319,6 @@ func runServer(orgID, runID string, srvIdx int, steps []models.ResolvedStep, ser }) } - - func dispatchAndWait(serverID, commandID string, cmd *pb.RunStepCmd) *pb.StepResult { ch := StepResults.Await(commandID) if err := DispatchRunStep(serverID, commandID, cmd); err != nil { @@ -360,9 +338,6 @@ func dispatchAndWait(serverID, commandID string, cmd *pb.RunStepCmd) *pb.StepRes } } - - - func expandVars(v string, lookup map[string]string) string { return os.Expand(v, func(name string) string { if name == "$" { @@ -375,7 +350,7 @@ func expandVars(v string, lookup map[string]string) string { func resolveSecrets(orgID string, refs []string) map[string]string { out := map[string]string{} for _, ref := range refs { - + parts := strings.SplitN(ref, "/", 2) if len(parts) != 2 { continue @@ -397,8 +372,6 @@ func maskSecrets(s string, secrets map[string]string) string { return s } - - func setServerRun(runID string, srvIdx int, set bson.M) { ctx, cancel := wfCtx() defer cancel() @@ -407,7 +380,6 @@ func setServerRun(runID string, srvIdx int, set bson.M) { bson.M{"$set": set}) } - func serverIDAt(runID string, srvIdx int) string { r, err := getRunByID(runID) if err != nil || srvIdx >= len(r.ServerRuns) { @@ -436,7 +408,6 @@ func finishStep(runID, serverID string, order int, status string, attempts, exit }) } - func secretValues(m map[string]string) []string { out := make([]string, 0, len(m)) for _, v := range m { @@ -471,11 +442,6 @@ func updateStep(runID, serverID string, order int, set bson.M) { ) } - - - - - func getRunByID(runID string) (*models.WorkflowRun, error) { ctx, cancel := wfCtx() defer cancel() @@ -487,7 +453,6 @@ func getRunByID(runID string) (*models.WorkflowRun, error) { return &r, err } - func GetRun(orgID, runID string) (*models.WorkflowRun, error) { ctx, cancel := wfCtx() defer cancel() diff --git a/site/app/globals.css b/site/app/globals.css index 527e62e..a0fbfd6 100644 --- a/site/app/globals.css +++ b/site/app/globals.css @@ -1,5 +1,5 @@ /* ========================================================================== - Vantage marketing site — design tokens + Vantage marketing site design tokens Palette is anchored on the logo navy (#0B2A58). The accent IS the brand navy, lifting to a readable blue on dark grounds; status colours (up/down/ pending) are semantic and deliberately never reused as the accent. @@ -346,7 +346,10 @@ code { border-radius: 4px; border: 1px solid transparent; cursor: pointer; - transition: transform 0.1s ease, filter 0.15s ease, border-color 0.15s ease; + transition: + transform 0.1s ease, + filter 0.15s ease, + border-color 0.15s ease; } .btn:active { @@ -439,14 +442,7 @@ code { content: ""; position: absolute; inset: 0; - background: linear-gradient( - 100deg, - #071628 0%, - #071628 26%, - rgba(7, 22, 40, 0.86) 42%, - rgba(7, 22, 40, 0.35) 62%, - rgba(7, 22, 40, 0.1) 100% - ); + background: linear-gradient(100deg, #071628 0%, #071628 26%, rgba(7, 22, 40, 0.86) 42%, rgba(7, 22, 40, 0.35) 62%, rgba(7, 22, 40, 0.1) 100%); z-index: 0; } diff --git a/site/app/page.tsx b/site/app/page.tsx index 715bc13..73e0da0 100644 --- a/site/app/page.tsx +++ b/site/app/page.tsx @@ -9,8 +9,8 @@ export default function OverviewPage() { Self-hosted fleet control plane

Your servers, under one pane of glass you actually own.

- Vantage holds SSH keys, runs scripts, watches services, stores secrets and opens consoles — across every machine you manage. One agent per server, outbound connections only, - all state in your own database. + Vantage holds SSH keys, runs scripts, watches services, stores secrets and opens consoles across every machine you manage. One agent per server, outbound connections only, all + state in your own database.

@@ -32,7 +32,7 @@ export default function OverviewPage() {

Most small fleets end up with keys in a spreadsheet, scripts in someone's home directory, uptime checks in a separate service, secrets in a chat thread, and no record of - who ran what. None of those systems know about each other, so every question — who can reach this box, what ran on it last, is it even up — gets answered by hand. + who ran what. None of those systems know about each other, so every question who can reach this box, what ran on it last, is it even up gets answered by hand.

diff --git a/site/components/InstrumentPanel.tsx b/site/components/InstrumentPanel.tsx index e67233a..bc83f26 100644 --- a/site/components/InstrumentPanel.tsx +++ b/site/components/InstrumentPanel.tsx @@ -4,163 +4,170 @@ import { useEffect, useState } from "react"; /* * The hero's signature element: a fleet panel that plays one honest cycle of - * what the product actually does — a workflow runs three steps, a TLS monitor - * fails and opens an incident, a key revocation lands — then rests. It is a + * what the product actually does a workflow runs three steps, a TLS monitor + * fails and opens an incident, a key revocation lands then rests. It is a * dramatisation, not live data, so nothing here talks to an API. */ type LogLine = { time: string; body: React.ReactNode }; type Beat = { - at: number; - line: LogLine; - effect?: "incident" | "runDone" | "revoked"; + at: number; + line: LogLine; + effect?: "incident" | "runDone" | "revoked"; }; const BEATS: Beat[] = [ - { at: 600, line: { time: "14:22:02", body: "running · step 1/3 · pull image" } }, - { at: 1500, line: { time: "14:22:04", body: "running · step 2/3 · migrate database" } }, - { - at: 2600, - line: { time: "14:22:07", body: <>ok · migrate database · exit 0 }, - }, - { - at: 3400, - line: { time: "14:22:08", body: "running · step 3/3 · restart service" }, - effect: "incident", - }, - { - at: 4300, - line: { time: "14:22:10", body: <>monitor · edge-gw-02 tls · connection refused }, - }, - { - at: 5200, - line: { time: "14:22:11", body: <>ok · restart service · exit 0 }, - effect: "runDone", - }, - { - at: 6000, - line: { time: "14:22:12", body: <>run finished · success · 3 steps · 1 server }, - effect: "revoked", - }, + { at: 600, line: { time: "14:22:02", body: "running · step 1/3 · pull image" } }, + { at: 1500, line: { time: "14:22:04", body: "running · step 2/3 · migrate database" } }, + { + at: 2600, + line: { + time: "14:22:07", + body: ( + <> + ok · migrate database · exit 0 + + ), + }, + }, + { + at: 3400, + line: { time: "14:22:08", body: "running · step 3/3 · restart service" }, + effect: "incident", + }, + { + at: 4300, + line: { + time: "14:22:10", + body: ( + <> + monitor · edge-gw-02 tls · connection refused + + ), + }, + }, + { + at: 5200, + line: { + time: "14:22:11", + body: ( + <> + ok · restart service · exit 0 + + ), + }, + effect: "runDone", + }, + { + at: 6000, + line: { + time: "14:22:12", + body: ( + <> + run finished · success · 3 steps · 1 server + + ), + }, + effect: "revoked", + }, ]; const FIRST_LINE: LogLine = { time: "14:22:01", body: "queued · deploy-app · 1 server" }; const MAX_LINES = 7; export function InstrumentPanel() { - const [lines, setLines] = useState([FIRST_LINE]); - const [incident, setIncident] = useState(false); - const [runActive, setRunActive] = useState(true); - const [revoked, setRevoked] = useState(false); - const [resting, setResting] = useState(false); + const [lines, setLines] = useState([FIRST_LINE]); + const [incident, setIncident] = useState(false); + const [runActive, setRunActive] = useState(true); + const [revoked, setRevoked] = useState(false); + const [resting, setResting] = useState(false); - useEffect(() => { - const reduced = window.matchMedia("(prefers-reduced-motion: reduce)").matches; + useEffect(() => { + const reduced = window.matchMedia("(prefers-reduced-motion: reduce)").matches; - const apply = (effect: Beat["effect"]) => { - if (effect === "incident") setIncident(true); - if (effect === "runDone") setRunActive(false); - if (effect === "revoked") setRevoked(true); - }; + const apply = (effect: Beat["effect"]) => { + if (effect === "incident") setIncident(true); + if (effect === "runDone") setRunActive(false); + if (effect === "revoked") setRevoked(true); + }; - - if (reduced) { - setLines([FIRST_LINE, ...BEATS.map((b) => b.line)].slice(-MAX_LINES)); - BEATS.forEach((b) => apply(b.effect)); - setResting(true); - return; - } + if (reduced) { + setLines([FIRST_LINE, ...BEATS.map((b) => b.line)].slice(-MAX_LINES)); + BEATS.forEach((b) => apply(b.effect)); + setResting(true); + return; + } - const timers = BEATS.map((beat) => - window.setTimeout(() => { - setLines((prev) => [...prev, beat.line].slice(-MAX_LINES)); - apply(beat.effect); - }, beat.at) - ); - timers.push(window.setTimeout(() => setResting(true), 6600)); + const timers = BEATS.map((beat) => + window.setTimeout(() => { + setLines((prev) => [...prev, beat.line].slice(-MAX_LINES)); + apply(beat.effect); + }, beat.at), + ); + timers.push(window.setTimeout(() => setResting(true), 6600)); - return () => timers.forEach(window.clearTimeout); - }, []); + return () => timers.forEach(window.clearTimeout); + }, []); - return ( -
-
-
- - northgate · fleet - - 12 servers - {incident ? "10 up" : "11 up"} - {incident ? "2 down" : "1 down"} - 3 monitors - {runActive ? "1 run active" : "no runs active"} - 14:22:12 UTC -
- -
-
-

- Fleet {revoked ? "key revoked · 1 server updated" : "agents polling"} -

- - - - - - -
- -
-

- Run run_8f31c2 -

-
- {lines.map((line, i) => ( -
- {line.time} {line.body} + return ( +
+
+
+ + northgate · fleet + + 12 servers + {incident ? "10 up" : "11 up"} + {incident ? "2 down" : "1 down"} + 3 monitors + {runActive ? "1 run active" : "no runs active"} + 14:22:12 UTC
- ))} - {resting && ( -
- _ + +
+
+

+ Fleet {revoked ? "key revoked · 1 server updated" : "agents polling"} +

+ + + + + + +
+ +
+

+ Run run_8f31c2 +

+
+ {lines.map((line, i) => ( +
+ {line.time} {line.body} +
+ ))} + {resting && ( +
+ _ +
+ )} +
+
- )}
-
-
-
- ); + ); } -function Row({ - host, - sub, - state, - label, -}: { - host: string; - sub: string; - state: "up" | "down" | "pend"; - label: string; -}) { - return ( -
- - {host} - {sub} - {label} -
- ); +function Row({ host, sub, state, label }: { host: string; sub: string; state: "up" | "down" | "pend"; label: string }) { + return ( +
+ + {host} + {sub} + {label} +
+ ); } diff --git a/site/components/OrgForm.tsx b/site/components/OrgForm.tsx index 1943f06..4110845 100644 --- a/site/components/OrgForm.tsx +++ b/site/components/OrgForm.tsx @@ -41,7 +41,7 @@ export function OrgForm() { We sent a confirmation link. Open it and {slug || "your organisation"} is created with you as its owner. The link works once and expires in 24 hours.

- Nothing exists until you confirm — if the email does not arrive, start again or contact support@hostxtra.co.uk. + Nothing exists until you confirm if the email does not arrive, start again or contact support@hostxtra.co.uk.

); @@ -80,7 +80,7 @@ export function OrgForm() {
- At least {MIN_PASSWORD} characters. Use a manager — you are about to manage SSH keys with it. + At least {MIN_PASSWORD} characters. Use a manager you are about to manage SSH keys with it. {fieldError("password") && ( {fieldError("password")} diff --git a/site/next-env.d.ts b/site/next-env.d.ts index c4b7818..9fd409f 100644 --- a/site/next-env.d.ts +++ b/site/next-env.d.ts @@ -1,6 +1,6 @@ -/// -/// +/ +/ import "./.next/dev/types/routes.d.ts"; -// NOTE: This file should not be edited -// see https://nextjs.org/docs/app/api-reference/config/typescript for more information. + + diff --git a/site/next.config.ts b/site/next.config.ts index 6da86f0..1343a42 100644 --- a/site/next.config.ts +++ b/site/next.config.ts @@ -1,7 +1,7 @@ import type { NextConfig } from "next"; -// Standalone output, matching web/: the build emits a self-contained server -// bundle that runs under Node in the runtime image. + + const nextConfig: NextConfig = { output: "standalone", }; diff --git a/sitesvc/cmd/main.go b/sitesvc/cmd/main.go index 868b389..309db86 100644 --- a/sitesvc/cmd/main.go +++ b/sitesvc/cmd/main.go @@ -16,13 +16,8 @@ import ( "github.com/mrhid6/vantage/sitesvc/internal/store" ) - - - - - func main() { - + godotenv.Load() mongoURI := getEnv("MONGO_URI", "mongodb://localhost:27017/vantage") @@ -33,26 +28,22 @@ func main() { } log.Printf("connected to MongoDB (database %q)", store.DatabaseName()) - - - - if err := store.EnsureIndexes(); err != nil { log.Fatalf("failed to ensure indexes: %v", err) } mailCfg := mail.FromEnv() if mailCfg.Enabled() { - log.Printf("smtp enabled (%s) — contact form delivers to %s", mailCfg.Host, mailCfg.To) + log.Printf("smtp enabled (%s) contact form delivers to %s", mailCfg.Host, mailCfg.To) } else { - log.Println("warning: SMTP_HOST/SMTP_FROM not set — the contact and signup forms will refuse submissions") + log.Println("warning: SMTP_HOST/SMTP_FROM not set the contact and signup forms will refuse submissions") } if os.Getenv("PUBLIC_URL") == "" { - log.Println("warning: PUBLIC_URL is unset — verification links will be relative and will not work") + log.Println("warning: PUBLIC_URL is unset verification links will be relative and will not work") } if os.Getenv("SITE_ORIGIN") == "" { - log.Println("warning: SITE_ORIGIN is unset — cross-origin browser requests will be refused") + log.Println("warning: SITE_ORIGIN is unset cross-origin browser requests will be refused") } srv := &http.Server{ diff --git a/sitesvc/internal/api/api.go b/sitesvc/internal/api/api.go index 6ce04df..28d1b70 100644 --- a/sitesvc/internal/api/api.go +++ b/sitesvc/internal/api/api.go @@ -15,14 +15,11 @@ import ( ) const ( - maxBodyBytes = 32 << 10 + maxBodyBytes = 32 << 10 perIPLimit = 5 perIPWindow = 10 * time.Minute ) - - - type Server struct { mail mail.Config limiter *limiter @@ -49,7 +46,7 @@ func (s *Server) Routes() http.Handler { mux := http.NewServeMux() mux.HandleFunc("POST /api/contact", s.handleContact) mux.HandleFunc("POST /api/signup", s.handleSignup) - + mux.HandleFunc("GET /api/verify", s.handleVerify) mux.HandleFunc("GET /healthz", func(w http.ResponseWriter, r *http.Request) { writeJSON(w, http.StatusOK, map[string]string{"status": "ok"}) @@ -57,8 +54,6 @@ func (s *Server) Routes() http.Handler { return s.withCORS(mux) } - - func parseOrigins(raw string) map[string]bool { out := map[string]bool{} for _, o := range strings.Split(raw, ",") { @@ -69,10 +64,6 @@ func parseOrigins(raw string) map[string]bool { return out } - - - - func (s *Server) withCORS(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { origin := r.Header.Get("Origin") @@ -91,9 +82,6 @@ func (s *Server) withCORS(next http.Handler) http.Handler { }) } - - - func (s *Server) clientIP(r *http.Request) string { if s.trustProxy { if xff := r.Header.Get("X-Forwarded-For"); xff != "" { @@ -110,15 +98,13 @@ func (s *Server) clientIP(r *http.Request) string { return host } - - type contactBody struct { Name string `json:"name"` Email string `json:"email"` Servers string `json:"servers"` Topic string `json:"topic"` Message string `json:"message"` - Website string `json:"website"` + Website string `json:"website"` } var ( @@ -137,8 +123,6 @@ func (s *Server) handleContact(w http.ResponseWriter, r *http.Request) { return } - - if strings.TrimSpace(body.Website) != "" { writeJSON(w, http.StatusAccepted, map[string]string{"status": "received"}) return @@ -201,9 +185,6 @@ func (s *Server) handleContact(w http.ResponseWriter, r *http.Request) { return } - - - if err := s.mail.Send(subject(addr, fields), plainBody(addr, fields), addr); err != nil { log.Printf("contact send: %v", err) writeJSON(w, http.StatusBadGateway, map[string]string{ @@ -216,7 +197,7 @@ func (s *Server) handleContact(w http.ResponseWriter, r *http.Request) { } func subject(addr string, fields map[string]string) string { - return fmt.Sprintf("[Vantage] %s — %s", fields["topic"], addr) + return fmt.Sprintf("[Vantage] %s %s", fields["topic"], addr) } func plainBody(addr string, fields map[string]string) string { @@ -233,8 +214,6 @@ func plainBody(addr string, fields map[string]string) string { return b.String() } - - func decode(w http.ResponseWriter, r *http.Request, dst any) bool { r.Body = http.MaxBytesReader(w, r.Body, maxBodyBytes) dec := json.NewDecoder(r.Body) diff --git a/sitesvc/internal/api/signup.go b/sitesvc/internal/api/signup.go index f5f5394..badde5b 100644 --- a/sitesvc/internal/api/signup.go +++ b/sitesvc/internal/api/signup.go @@ -25,20 +25,15 @@ type signupBody struct { OrgName string `json:"org_name"` Email string `json:"email"` Password string `json:"password"` - Website string `json:"website"` + Website string `json:"website"` } - - - func (s *Server) handleSignup(w http.ResponseWriter, r *http.Request) { var body signupBody if !decode(w, r, &body) { return } - - if strings.TrimSpace(body.Website) != "" { writeJSON(w, http.StatusAccepted, map[string]string{"status": "check_email"}) return @@ -114,9 +109,7 @@ func (s *Server) handleSignup(w http.ResponseWriter, r *http.Request) { link := s.verifyURL(token) if err := s.mail.SendVerification(addr, orgName, link, store.PendingTTL); err != nil { - - - + log.Printf("signup: send verification to %s: %v", addr, err) writeJSON(w, http.StatusBadGateway, map[string]string{ "error": "We could not send the confirmation email. Check the address, or email support@hostxtra.co.uk.", @@ -132,9 +125,6 @@ func (s *Server) verifyURL(token string) string { return fmt.Sprintf("%s/api/verify?token=%s", base, url.QueryEscape(token)) } - - - func (s *Server) handleVerify(w http.ResponseWriter, r *http.Request) { token := r.URL.Query().Get("token") if token == "" { @@ -178,9 +168,6 @@ func (s *Server) handleVerify(w http.ResponseWriter, r *http.Request) { fmt.Sprintf("%s is set up and you are its owner. You can sign in now.", org.Name)) } - - - func (s *Server) verifyPage(w http.ResponseWriter, status int, heading, detail string) { w.Header().Set("Content-Type", "text/html; charset=utf-8") w.Header().Set("X-Content-Type-Options", "nosniff") @@ -193,7 +180,7 @@ func (s *Server) verifyPage(w http.ResponseWriter, status int, heading, detail s -%s — Vantage +%s Vantage