juntekim.com/stripe_to_invoice/app/api/auth/request-link/route.ts
2025-12-31 00:02:22 +00:00

49 lines
1.2 KiB
TypeScript

// app/api/auth/request-link/route.ts
import { NextResponse } from "next/server";
import { db } from "@/lib/db";
import { users, loginTokens } from "@/lib/schema";
import { eq } from "drizzle-orm";
import { generateToken, hashToken } from "@/lib/auth/tokens";
import { sendMagicLinkEmail } from "@/lib/email/sendMagicLink";
export async function POST(req: Request) {
const { email } = await req.json();
if (!email) {
return NextResponse.json({ error: "Email required" }, { status: 400 });
}
// 1. find user
let user = await db
.select()
.from(users)
.where(eq(users.email, email))
.then((rows) => rows[0]);
// 2. create user if missing
if (!user) {
const inserted = await db
.insert(users)
.values({ email })
.returning();
user = inserted[0];
}
// 3. generate token
const token = generateToken();
const tokenHash = hashToken(token);
// 4. store login token
await db.insert(loginTokens).values({
userId: user.id,
tokenHash,
expiresAt: new Date(Date.now() + 15 * 60 * 1000),
});
// 5. send email
const link = `${process.env.APP_URL}/auth/callback?token=${token}`;
await sendMagicLinkEmail(email, link);
return NextResponse.json({ ok: true });
}