Files
page-builder/src/app/api/auth/signup/route.ts
T
jaybe 3e223a45d4
CI / test (push) Failing after 4m41s
CI / pr_and_merge (push) Has been skipped
폼 전송 TDD추가 및 암호화 적용 중
2025-12-02 11:02:15 +09:00

72 lines
2.1 KiB
TypeScript

import { NextResponse } from "next/server";
import { PrismaClient } from "@prisma/client";
import { hashPassword, signAccessToken } from "@/features/auth/authCrypto";
// /api/auth/signup
// - 이메일/비밀번호를 받아 새 유저를 생성하고,
// - JWT 액세스 토큰을 httpOnly 쿠키에 설정한 뒤, 비밀번호 해시를 제외한 유저 정보를 반환한다.
const prisma = new PrismaClient();
export async function POST(request: Request) {
try {
const body = await request.json().catch(() => null as any);
const emailRaw = body?.email;
const password: string | undefined = body?.password;
if (typeof emailRaw !== "string" || typeof password !== "string") {
return NextResponse.json({ message: "email 과 password 는 필수입니다." }, { status: 400 });
}
const email = emailRaw.trim().toLowerCase();
if (password.length < 8) {
return NextResponse.json({ message: "비밀번호는 최소 8자 이상이어야 합니다." }, { status: 400 });
}
// 이미 존재하는 이메일인지 확인한다.
const existing = await prisma.user.findUnique({ where: { email } });
if (existing) {
return NextResponse.json({ message: "이미 가입된 이메일입니다." }, { status: 409 });
}
// 비밀번호를 해시한 뒤 유저를 생성한다.
const passwordHash = await hashPassword(password);
const user = await prisma.user.create({
data: {
email,
passwordHash,
tokenVersion: 1,
},
});
const token = await signAccessToken({
id: user.id,
email: user.email,
tokenVersion: user.tokenVersion,
});
const { passwordHash: _ph, ...safeUser } = user;
const res = NextResponse.json(safeUser, { status: 201 });
res.cookies.set("pb_access", token, {
httpOnly: true,
secure: true,
sameSite: "lax",
path: "/",
maxAge: 7 * 24 * 60 * 60,
});
return res;
} catch (error: any) {
return NextResponse.json(
{ message: "회원가입 처리 중 오류가 발생했습니다.", error: error?.message },
{ status: 500 },
);
}
}