refactor: merge auth into account prefix (/account/register, /account/email)
This commit is contained in:
parent
fd4af848bc
commit
a22112dc77
|
|
@ -119,7 +119,7 @@
|
|||
document.getElementById('register-btn').addEventListener('click', async () => {
|
||||
setLoading('register-btn', true, 'Creating...');
|
||||
try {
|
||||
const res = await fetch(`${API}/auth/register`, {
|
||||
const res = await fetch(`${API}/account/register`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({}),
|
||||
|
|
|
|||
|
|
@ -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, account } from "./routes/auth";
|
||||
import { account } from "./routes/auth";
|
||||
import { internal } from "./routes/internal";
|
||||
import { dashboard } from "./routes/dashboard";
|
||||
import { migrate } from "./db";
|
||||
|
|
@ -15,7 +15,6 @@ const app = new Elysia()
|
|||
.use(swagger({ path: "/docs", documentation: { info: { title: "PingQL API", version: "0.1.0" } } }))
|
||||
.get("/", () => ({ name: "PingQL", version: "0.1.0", docs: "/docs", dashboard: "/dashboard" }), { detail: { hide: true } })
|
||||
.use(dashboard)
|
||||
.use(auth)
|
||||
.use(account)
|
||||
.use(monitors)
|
||||
.use(checks)
|
||||
|
|
|
|||
|
|
@ -2,14 +2,12 @@ import { Elysia, t } from "elysia";
|
|||
import { randomBytes, createHash } from "crypto";
|
||||
import sql from "../db";
|
||||
|
||||
// Generate a memorable 16-digit account key: XXXX-XXXX-XXXX-XXXX
|
||||
function generateAccountKey(): string {
|
||||
const bytes = randomBytes(8);
|
||||
const hex = bytes.toString("hex").toUpperCase();
|
||||
return `${hex.slice(0, 4)}-${hex.slice(4, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}`;
|
||||
}
|
||||
|
||||
// Middleware: validate account key from Authorization header
|
||||
export function requireAuth(app: Elysia) {
|
||||
return app.derive(async ({ headers, error }) => {
|
||||
const key = headers["authorization"]?.replace("Bearer ", "").trim();
|
||||
|
|
@ -23,8 +21,28 @@ export function requireAuth(app: Elysia) {
|
|||
}
|
||||
|
||||
export const account = new Elysia({ prefix: "/account" })
|
||||
// Create account
|
||||
.post("/register", async ({ body }) => {
|
||||
const key = generateAccountKey();
|
||||
const emailHash = body.email
|
||||
? createHash("sha256").update(body.email.toLowerCase().trim()).digest("hex")
|
||||
: null;
|
||||
|
||||
await sql`INSERT INTO accounts (id, email_hash) VALUES (${key}, ${emailHash})`;
|
||||
|
||||
return {
|
||||
key,
|
||||
...(body.email ? { email_registered: true } : { email_registered: false }),
|
||||
};
|
||||
}, {
|
||||
body: t.Object({
|
||||
email: t.Optional(t.String({ format: "email", description: "Optional. Used for recovery and alerts." })),
|
||||
}),
|
||||
detail: { summary: "Create account", tags: ["account"] },
|
||||
})
|
||||
|
||||
// Update email
|
||||
.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")
|
||||
|
|
@ -37,25 +55,3 @@ export const account = new Elysia({ prefix: "/account" })
|
|||
}),
|
||||
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 }) => {
|
||||
const key = generateAccountKey();
|
||||
const emailHash = body.email
|
||||
? createHash("sha256").update(body.email.toLowerCase().trim()).digest("hex")
|
||||
: null;
|
||||
|
||||
await sql`INSERT INTO accounts (id, email_hash) VALUES (${key}, ${emailHash})`;
|
||||
|
||||
return {
|
||||
key,
|
||||
message: "Save this key — it's your only credential. We don't store it.",
|
||||
...(body.email ? { email_registered: true } : { email_registered: false }),
|
||||
};
|
||||
}, {
|
||||
body: t.Object({
|
||||
email: t.Optional(t.String({ format: "email", description: "Optional. Only used for account recovery." })),
|
||||
}),
|
||||
detail: { summary: "Create account", tags: ["auth"] },
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in New Issue