"use server"; import { SignJWT, jwtVerify } from "jose"; // JWT_SECRET 환경변수 검증 if (!process.env.JWT_SECRET) { console.error("JWT_SECRET environment variable is not set. Please configure JWT_SECRET in your environment variables."); throw new Error("JWT_SECRET environment variable is required"); } const secretKey = process.env.JWT_SECRET; const key = new TextEncoder().encode(secretKey); export interface TechVendorInvitationPayload { vendorId: number; vendorName: string; email: string; vendorType: "조선" | "해양TOP" | "해양HULL" | ("조선" | "해양TOP" | "해양HULL")[]; type: "tech-vendor-invitation"; expiresAt: number; } /** * 기술영업 벤더 초대용 일회성 토큰 생성 */ export async function createTechVendorInvitationToken(payload: { vendorId: number; vendorName: string; email: string; vendorType: "조선" | "해양TOP" | "해양HULL" | ("조선" | "해양TOP" | "해양HULL")[]; }): Promise { const expiresAt = Date.now() + 7 * 24 * 60 * 60 * 1000; // 7일 const token = await new SignJWT({ vendorId: payload.vendorId, vendorName: payload.vendorName, email: payload.email, type: "tech-vendor-invitation", vendorType: payload.vendorType, expiresAt, }) .setProtectedHeader({ alg: "HS256" }) .setIssuedAt() .setExpirationTime("7d") .sign(key); return token; } /** * 기술영업 벤더 초대 토큰 검증 */ export async function verifyTechVendorInvitationToken( token: string ): Promise { try { const { payload } = await jwtVerify(token, key); const tokenPayload = payload as unknown as TechVendorInvitationPayload; // 토큰 타입 검증 if (tokenPayload.type !== "tech-vendor-invitation") { console.error("Invalid token type:", tokenPayload.type); return null; } // 만료 시간 검증 if (Date.now() > tokenPayload.expiresAt) { console.error("Token has expired"); return null; } return tokenPayload; } catch (error) { console.error("Token verification failed:", error); return null; } } /** * 초대 토큰을 포함한 가입 URL 생성 */ export async function createTechVendorSignupUrl(token: string): Promise { const baseUrl = process.env.NEXT_PUBLIC_URL || "http://localhost:3000"; return `${baseUrl}/partners/tech-signup?token=${token}`; }