add initial complete webui, more ai commands for moderation, add api
This commit is contained in:
parent
19e794e34c
commit
173d4e7a52
112 changed files with 8176 additions and 780 deletions
107
webui/app/api/auth/verify/route.ts
Executable file
107
webui/app/api/auth/verify/route.ts
Executable file
|
@ -0,0 +1,107 @@
|
|||
import { NextRequest, NextResponse } from "next/server";
|
||||
import { eq, and, gt } from "drizzle-orm";
|
||||
import * as schema from "@/lib/schema";
|
||||
import { db } from "@/lib/db";
|
||||
import { createSession, getSessionCookieOptions } from "@/lib/auth";
|
||||
import { SESSION_COOKIE_NAME } from "@/lib/auth-constants";
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
try {
|
||||
const contentType = request.headers.get('content-type');
|
||||
if (!contentType || !contentType.includes('application/json')) {
|
||||
return NextResponse.json({
|
||||
success: false,
|
||||
error: "Invalid content type"
|
||||
}, { status: 400 });
|
||||
}
|
||||
|
||||
const body = await request.json();
|
||||
const { userId, code } = body;
|
||||
|
||||
if (!userId || !code) {
|
||||
return NextResponse.json({
|
||||
success: false,
|
||||
error: "User ID and code are required"
|
||||
}, { status: 400 });
|
||||
}
|
||||
|
||||
if (typeof userId !== 'string' || typeof code !== 'string') {
|
||||
return NextResponse.json({
|
||||
success: false,
|
||||
error: "Invalid input format"
|
||||
}, { status: 400 });
|
||||
}
|
||||
|
||||
if (!/^\d{6}$/.test(code)) {
|
||||
return NextResponse.json({
|
||||
success: false,
|
||||
error: "Invalid code format"
|
||||
}, { status: 400 });
|
||||
}
|
||||
|
||||
const twoFactorRecord = await db.query.twoFactorTable.findFirst({
|
||||
where: and(
|
||||
eq(schema.twoFactorTable.userId, userId),
|
||||
gt(schema.twoFactorTable.codeExpiresAt, new Date())
|
||||
),
|
||||
});
|
||||
|
||||
if (!twoFactorRecord) {
|
||||
return NextResponse.json({
|
||||
success: false,
|
||||
error: "No valid 2FA code found or code has expired"
|
||||
}, { status: 404 });
|
||||
}
|
||||
|
||||
if (twoFactorRecord.codeAttempts >= 5) {
|
||||
await db.delete(schema.twoFactorTable)
|
||||
.where(eq(schema.twoFactorTable.userId, userId));
|
||||
|
||||
return NextResponse.json({
|
||||
success: false,
|
||||
error: "Too many failed attempts. Please request a new code."
|
||||
}, { status: 429 });
|
||||
}
|
||||
|
||||
if (twoFactorRecord.currentCode !== code) {
|
||||
await db.update(schema.twoFactorTable)
|
||||
.set({
|
||||
codeAttempts: twoFactorRecord.codeAttempts + 1,
|
||||
updatedAt: new Date()
|
||||
})
|
||||
.where(eq(schema.twoFactorTable.userId, userId));
|
||||
|
||||
console.log(`2FA verification failed for user: ${userId}, attempts: ${twoFactorRecord.codeAttempts + 1}`);
|
||||
return NextResponse.json({
|
||||
success: false,
|
||||
error: "Invalid 2FA code"
|
||||
}, { status: 401 });
|
||||
}
|
||||
|
||||
const session = await createSession(userId);
|
||||
|
||||
await db.delete(schema.twoFactorTable)
|
||||
.where(eq(schema.twoFactorTable.userId, userId));
|
||||
|
||||
console.log("2FA verification successful for user:", userId);
|
||||
|
||||
const response = NextResponse.json({
|
||||
success: true,
|
||||
message: "2FA verification successful",
|
||||
redirectTo: "/account",
|
||||
sessionToken: session.sessionToken
|
||||
});
|
||||
|
||||
const cookieOptions = getSessionCookieOptions();
|
||||
response.cookies.set(SESSION_COOKIE_NAME, session.sessionToken, cookieOptions);
|
||||
|
||||
return response;
|
||||
|
||||
} catch (error) {
|
||||
console.error("Error in verify API:", error);
|
||||
return NextResponse.json({
|
||||
success: false,
|
||||
error: "Internal server error"
|
||||
}, { status: 500 });
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue