158 lines
4.6 KiB
TypeScript
158 lines
4.6 KiB
TypeScript
import { httpRouter } from "convex/server";
|
|
import { httpAction } from "./_generated/server";
|
|
import { internal } from "./_generated/api";
|
|
import { getClientIP } from "./utils/getClientIP";
|
|
import { v } from "convex/values";
|
|
import { authComponent, createAuth } from "./auth";
|
|
|
|
const http = httpRouter();
|
|
|
|
/**
|
|
* Endpoint de teste para debug - retorna todos os headers disponíveis
|
|
* GET /api/debug/headers
|
|
*/
|
|
http.route({
|
|
path: "/api/debug/headers",
|
|
method: "GET",
|
|
handler: httpAction(async (ctx, request) => {
|
|
const headers: Record<string, string> = {};
|
|
request.headers.forEach((value, key) => {
|
|
headers[key] = value;
|
|
});
|
|
|
|
const ip = getClientIP(request);
|
|
|
|
return new Response(
|
|
JSON.stringify({
|
|
headers,
|
|
extractedIP: ip,
|
|
url: request.url,
|
|
}),
|
|
{
|
|
status: 200,
|
|
headers: { "Content-Type": "application/json" },
|
|
}
|
|
);
|
|
}),
|
|
});
|
|
|
|
/**
|
|
* Endpoint HTTP para login que captura automaticamente o IP do cliente
|
|
* POST /api/login
|
|
* Body: { matriculaOuEmail: string, senha: string }
|
|
*/
|
|
http.route({
|
|
path: "/api/login",
|
|
method: "POST",
|
|
handler: httpAction(async (ctx, request) => {
|
|
try {
|
|
// Debug: Log todos os headers disponíveis
|
|
console.log("=== DEBUG: Headers HTTP ===");
|
|
const headersEntries: string[] = [];
|
|
request.headers.forEach((value, key) => {
|
|
headersEntries.push(`${key}: ${value}`);
|
|
});
|
|
console.log("Headers:", headersEntries.join(", "));
|
|
console.log("Request URL:", request.url);
|
|
|
|
// Extrair IP do cliente do request
|
|
let clientIP = getClientIP(request);
|
|
console.log("IP extraído:", clientIP);
|
|
|
|
// Se não encontrou IP, tentar obter do URL ou usar valor padrão
|
|
if (!clientIP) {
|
|
try {
|
|
const url = new URL(request.url);
|
|
// Tentar pegar do query param se disponível
|
|
const ipParam = url.searchParams.get("client_ip");
|
|
if (ipParam && /^(\d{1,3}\.){3}\d{1,3}$/.test(ipParam)) {
|
|
clientIP = ipParam;
|
|
console.log("IP obtido do query param:", clientIP);
|
|
} else {
|
|
// Se ainda não tiver IP, usar um identificador baseado no timestamp
|
|
// Isso pelo menos diferencia requisições
|
|
console.warn("IP não encontrado nos headers. Usando fallback.");
|
|
clientIP = undefined; // Deixar como undefined para registrar como não disponível
|
|
}
|
|
} catch {
|
|
console.warn("Erro ao processar URL para IP");
|
|
}
|
|
}
|
|
|
|
// Extrair User-Agent
|
|
const userAgent = request.headers.get("user-agent") || undefined;
|
|
|
|
// Ler body da requisição
|
|
const body = await request.json();
|
|
|
|
if (!body.matriculaOuEmail || !body.senha) {
|
|
return new Response(
|
|
JSON.stringify({
|
|
sucesso: false,
|
|
erro: "Matrícula/Email e senha são obrigatórios",
|
|
}),
|
|
{
|
|
status: 400,
|
|
headers: { "Content-Type": "application/json" },
|
|
}
|
|
);
|
|
}
|
|
|
|
// Chamar a mutation de login interna com IP e userAgent
|
|
const resultado = await ctx.runMutation(
|
|
internal.autenticacao.loginComIP,
|
|
{
|
|
matriculaOuEmail: body.matriculaOuEmail,
|
|
senha: body.senha,
|
|
ipAddress: clientIP,
|
|
userAgent: userAgent,
|
|
}
|
|
);
|
|
|
|
return new Response(JSON.stringify(resultado), {
|
|
status: 200,
|
|
headers: {
|
|
"Content-Type": "application/json",
|
|
"Access-Control-Allow-Origin": "*",
|
|
"Access-Control-Allow-Methods": "POST, OPTIONS",
|
|
"Access-Control-Allow-Headers": "Content-Type",
|
|
},
|
|
});
|
|
} catch (error) {
|
|
return new Response(
|
|
JSON.stringify({
|
|
sucesso: false,
|
|
erro:
|
|
error instanceof Error ? error.message : "Erro ao processar login",
|
|
}),
|
|
{
|
|
status: 500,
|
|
headers: { "Content-Type": "application/json" },
|
|
}
|
|
);
|
|
}
|
|
}),
|
|
});
|
|
|
|
/**
|
|
* Endpoint OPTIONS para CORS preflight
|
|
*/
|
|
http.route({
|
|
path: "/api/login",
|
|
method: "OPTIONS",
|
|
handler: httpAction(async () => {
|
|
return new Response(null, {
|
|
status: 200,
|
|
headers: {
|
|
"Access-Control-Allow-Origin": "*",
|
|
"Access-Control-Allow-Methods": "POST, OPTIONS",
|
|
"Access-Control-Allow-Headers": "Content-Type",
|
|
},
|
|
});
|
|
}),
|
|
});
|
|
|
|
authComponent.registerRoutes(http, createAuth);
|
|
|
|
export default http;
|