-
Notifications
You must be signed in to change notification settings - Fork 13
Expand file tree
/
Copy pathroute.ts
More file actions
139 lines (122 loc) · 4.95 KB
/
Copy pathroute.ts
File metadata and controls
139 lines (122 loc) · 4.95 KB
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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
import { NextRequest, NextResponse } from "next/server";
import { createAuthErrorResponse } from "@/lib/middleware/auth";
import dbConnect from "@/lib/db";
import Evaluator from "@/models/Evaluator";
import User from "@/models/User";
import { getAuth } from "@/lib/firebase-admin";
import { checkRateLimit, getClientIp } from "@/lib/rate-limit";
import { verifyRecaptcha } from "@/lib/recaptcha";
export const dynamic = 'force-dynamic';
function createSuccessResponse(message: string, data: any, status = 200) {
return NextResponse.json({
success: true,
message,
data,
timestamp: new Date().toISOString(),
}, { status });
}
function createErrorResponse(message: string, code: string, status: number) {
return NextResponse.json({
success: false,
message,
error: { code, message },
timestamp: new Date().toISOString(),
}, { status });
}
/**
* POST /api/evaluator/register
* Register a new evaluator
* This endpoint should be called AFTER Firebase Auth registration on the client
*/
export async function POST(request: NextRequest) {
try {
const ip = getClientIp(request);
if (!(await checkRateLimit(ip, 5, 60 * 1000))) {
return createErrorResponse("Too many requests. Please try again later.", "RATE_LIMIT_EXCEEDED", 429);
}
const authHeader = request.headers.get('authorization');
if (!authHeader || !authHeader.startsWith('Bearer ')) {
return createErrorResponse("Authentication required", "AUTH_REQUIRED", 401);
}
const token = authHeader.split('Bearer ')[1];
let decodedToken;
try {
decodedToken = await getAuth().verifyIdToken(token);
} catch (error) {
return createErrorResponse("Invalid or expired token", "TOKEN_INVALID", 401);
}
const uid = decodedToken.uid;
const email = decodedToken.email || "";
const body = await request.json();
const { name, evaluatorCode, recaptcha_token } = body;
// reCAPTCHA v3 background score check. The Firebase user was created
// client-side before this call, so clean it up if the check fails.
const captcha = await verifyRecaptcha(recaptcha_token, "evaluator_register");
if (!captcha.ok) {
console.warn("[evaluator/register] reCAPTCHA rejected:", captcha.reason, captcha.score);
try {
await getAuth().deleteUser(uid);
} catch (deleteError) {
console.error(`Failed to delete user ${uid} after reCAPTCHA failure:`, deleteError);
}
return createErrorResponse("Security check failed. Please try again.", "RECAPTCHA_FAILED", 400);
}
if (!name) {
return createErrorResponse("Name is required", "VALIDATION_ERROR", 400);
}
const expectedCode = process.env.EVALUATOR_CODE;
if (!expectedCode) {
console.error("EVALUATOR_CODE not set on server");
return createErrorResponse("Server configuration error", "CONFIG_ERROR", 500);
}
if (evaluatorCode !== expectedCode) {
// Delete the unauthorized user from Firebase Auth
try {
await getAuth().deleteUser(uid);
console.log(`Deleted unauthorized user ${uid} due to invalid evaluator code`);
} catch (deleteError) {
console.error(`Failed to delete unauthorized user ${uid}:`, deleteError);
}
return createErrorResponse("Invalid evaluator code", "INVALID_CODE", 403);
}
await dbConnect();
// Check if already exists
const existingEvaluator = await Evaluator.findOne({ uid });
if (existingEvaluator) {
return createErrorResponse("Evaluator profile already exists", "DUPLICATE", 409);
}
// Check if user exists (User collection)
const existingUser = await User.findOne({ uid });
if (existingUser) {
// Update role if exists
existingUser.role = "evaluator";
await existingUser.save();
} else {
// Create User if not exists (though AuthProvider might have done it?)
await User.create({
uid,
email,
name,
role: "evaluator"
});
}
// Create Evaluator Profile
const newEvaluator = await Evaluator.create({
uid,
email,
name,
role: "evaluator",
assignedTeams: [],
stats: {
evaluationsCompleted: 0,
evaluationsPending: 0
}
});
return createSuccessResponse("Evaluator registered successfully", {
evaluator: newEvaluator
});
} catch (error: any) {
console.error("Evaluator registration error:", error);
return createErrorResponse("Failed to register evaluator", "SERVER_ERROR", 500);
}
}