summaryrefslogtreecommitdiff
path: root/lib/tech-vendor-invitation-token.ts
blob: 04a31bccb8ddebbf4d7837f6e3c94acd73076831 (plain)
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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
"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<string> {
  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<TechVendorInvitationPayload | null> {
  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<string> {
  const baseUrl = process.env.NEXT_PUBLIC_URL || "http://localhost:3000";
  return `${baseUrl}/partners/tech-signup?token=${token}`;
}