PingQL
Uptime monitoring for developers
-
-
-
-
No account?
+
+
+
+
+
+
+
+
No account?
+
+
+
+
+
+
✓
+
+
Account created
+
Save your key — it's the only way to log in
+
+
+
+
+
+
⚠ This key is shown once. Copy it now — we don't store it.
+
+
+
+
+
Used for account recovery and uptime alerts. Never shared.
+
+
+
+
+
+
+
+
+
diff --git a/apps/web/src/index.ts b/apps/web/src/index.ts
index e92c7d2..5118458 100644
--- a/apps/web/src/index.ts
+++ b/apps/web/src/index.ts
@@ -3,7 +3,7 @@ import { cors } from "@elysiajs/cors";
import { swagger } from "@elysiajs/swagger";
import { checks } from "./routes/checks";
import { monitors } from "./routes/monitors";
-import { auth } from "./routes/auth";
+import { auth, account } from "./routes/auth";
import { internal } from "./routes/internal";
import { dashboard } from "./routes/dashboard";
import { migrate } from "./db";
@@ -16,6 +16,7 @@ const app = new Elysia()
.get("/", () => ({ name: "PingQL", version: "0.1.0", docs: "/docs", dashboard: "/dashboard" }))
.use(dashboard)
.use(auth)
+ .use(account)
.use(monitors)
.use(checks)
.use(internal)
diff --git a/apps/web/src/routes/auth.ts b/apps/web/src/routes/auth.ts
index cdf966f..71d7906 100644
--- a/apps/web/src/routes/auth.ts
+++ b/apps/web/src/routes/auth.ts
@@ -22,6 +22,22 @@ export function requireAuth(app: Elysia) {
});
}
+export const account = new Elysia({ prefix: "/account" })
+ .use(requireAuth)
+ // Update email (post-registration or settings)
+ .post("/email", async ({ accountId, body }) => {
+ const emailHash = body.email
+ ? createHash("sha256").update(body.email.toLowerCase().trim()).digest("hex")
+ : null;
+ await sql`UPDATE accounts SET email_hash = ${emailHash} WHERE id = ${accountId}`;
+ return { ok: true };
+ }, {
+ body: t.Object({
+ email: t.Optional(t.String({ description: "Email for recovery and notifications" })),
+ }),
+ detail: { summary: "Update account email", tags: ["account"] },
+ });
+
export const auth = new Elysia({ prefix: "/auth" })
// Create a new account — no email required
.post("/register", async ({ body }) => {