Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | 7x 19x 19x 1x 18x 18x 1x 1x 17x 17x 1x 16x 16x 16x 16x 16x 16x 16x 16x | import type { FastifyInstance } from "fastify";
import { eq } from "drizzle-orm";
import { db } from "../db/index.js";
import { users, accounts, memberships } from "../db/schema.js";
import { verifyOtp, OtpError } from "../lib/otp.js";
import { createSession } from "../lib/sessions.js";
import { getUserAccounts } from "../lib/accounts.js";
export async function signupRoutes(app: FastifyInstance) {
// POST /signup — validate OTP, create user + account, return tokens
app.post<{ Body: { email: string; code: string; accountName: string } }>(
"/signup",
async (request, reply) => {
const { email, code, accountName } = request.body;
if (!email || !code || !accountName) {
return reply
.status(400)
.send({ error: "Email, code, and accountName are required" });
}
try {
await verifyOtp(email, code);
} catch (err) {
Eif (err instanceof OtpError) {
return reply.status(400).send({ error: err.message });
}
throw err;
}
// Check that user does not already exist
const [existingUser] = await db.select().from(users).where(eq(users.email, email));
if (existingUser) {
return reply.status(409).send({ error: "User already exists. Please log in." });
}
const { user, tokens } = await db.transaction(async (tx) => {
const [created] = await tx
.insert(users)
.values({ email, name: email.split("@")[0] })
.returning();
const [account] = await tx.insert(accounts).values({ name: accountName }).returning();
await tx.insert(memberships).values({
userId: created.id,
accountId: account.id,
role: "owner",
});
const t = await createSession(created.id, tx);
return { user: created, tokens: t };
});
const userAccounts = await getUserAccounts(user.id);
return reply
.status(201)
.send({ ...tokens, user, accounts: userAccounts });
},
);
}
|