Add login and register dialogs, user dropdown menu with profile link and logout option, and integrate with session management hook. Prevent hydration mismatches by conditionally rendering auth elements after mount. Update package-lock.json with new @esbuild dependencies for build tooling.
151 lines
4.1 KiB
TypeScript
151 lines
4.1 KiB
TypeScript
import { NextRequest, NextResponse } from "next/server";
|
|
import { secureLogger } from "@/lib/secure-logger";
|
|
import { requireAuth } from "@/lib/auth/middleware";
|
|
import { getUserCharacters, createCharacter } from "@/lib/db/queries/characters";
|
|
import { characterSchema } from "@/lib/validation-schemas";
|
|
|
|
export async function GET(request: NextRequest) {
|
|
try {
|
|
// Middleware de autenticação
|
|
const authResult = await requireAuth(request);
|
|
|
|
if (authResult instanceof NextResponse) {
|
|
return authResult;
|
|
}
|
|
|
|
const auth = authResult;
|
|
|
|
// Listar personagens do usuário
|
|
const characters = await getUserCharacters(auth.userId);
|
|
|
|
return NextResponse.json(
|
|
{
|
|
success: true,
|
|
characters: characters.map((char) => ({
|
|
characterId: char.character_id,
|
|
characterName: char.character_name,
|
|
serverName: char.server_name,
|
|
isMain: char.is_main,
|
|
verified: char.verified,
|
|
createdAt: char.created_at,
|
|
})),
|
|
},
|
|
{ status: 200 }
|
|
);
|
|
} catch (error) {
|
|
// Se for NextResponse (erro de autenticação), re-lançar
|
|
if (error instanceof NextResponse) {
|
|
return error;
|
|
}
|
|
|
|
secureLogger.error("❌ Erro ao listar personagens", {
|
|
error: error instanceof Error ? error.message : "Erro desconhecido",
|
|
stack: error instanceof Error ? error.stack : undefined,
|
|
timestamp: new Date().toISOString(),
|
|
});
|
|
|
|
return NextResponse.json(
|
|
{
|
|
success: false,
|
|
error: error instanceof Error ? error.message : "Erro interno",
|
|
},
|
|
{ status: 500 }
|
|
);
|
|
}
|
|
}
|
|
|
|
export async function POST(request: NextRequest) {
|
|
try {
|
|
// Middleware de autenticação
|
|
const authResult = await requireAuth(request);
|
|
|
|
if (authResult instanceof NextResponse) {
|
|
return authResult;
|
|
}
|
|
|
|
const auth = authResult;
|
|
|
|
const body = await request.json();
|
|
|
|
// Validação com Zod
|
|
const validationResult = characterSchema.safeParse(body);
|
|
|
|
if (!validationResult.success) {
|
|
const errors = validationResult.error.issues.map((err) => ({
|
|
field: err.path.join("."),
|
|
message: err.message,
|
|
}));
|
|
|
|
return NextResponse.json(
|
|
{
|
|
success: false,
|
|
error: "Dados de entrada inválidos",
|
|
details: errors,
|
|
},
|
|
{ status: 400 }
|
|
);
|
|
}
|
|
|
|
const validatedData = validationResult.data;
|
|
|
|
// Criar personagem
|
|
const newCharacter = await createCharacter(auth.userId, {
|
|
character_name: validatedData.characterName,
|
|
server_name: validatedData.serverName,
|
|
is_main: validatedData.isMain,
|
|
});
|
|
|
|
secureLogger.info("✅ Personagem criado com sucesso", {
|
|
userId: auth.userId,
|
|
characterId: newCharacter.character_id,
|
|
timestamp: new Date().toISOString(),
|
|
});
|
|
|
|
return NextResponse.json(
|
|
{
|
|
success: true,
|
|
character: {
|
|
characterId: newCharacter.character_id,
|
|
characterName: newCharacter.character_name,
|
|
serverName: newCharacter.server_name,
|
|
isMain: newCharacter.is_main,
|
|
verified: newCharacter.verified,
|
|
createdAt: newCharacter.created_at,
|
|
},
|
|
},
|
|
{ status: 201 }
|
|
);
|
|
} catch (error) {
|
|
// Se for NextResponse (erro de autenticação), re-lançar
|
|
if (error instanceof NextResponse) {
|
|
return error;
|
|
}
|
|
|
|
// Verificar se é erro de constraint (personagem duplicado)
|
|
if (error instanceof Error && error.message.includes("UNIQUE")) {
|
|
return NextResponse.json(
|
|
{
|
|
success: false,
|
|
error: "Este personagem já está cadastrado neste servidor",
|
|
},
|
|
{ status: 409 }
|
|
);
|
|
}
|
|
|
|
secureLogger.error("❌ Erro ao criar personagem", {
|
|
error: error instanceof Error ? error.message : "Erro desconhecido",
|
|
stack: error instanceof Error ? error.stack : undefined,
|
|
timestamp: new Date().toISOString(),
|
|
});
|
|
|
|
return NextResponse.json(
|
|
{
|
|
success: false,
|
|
error: error instanceof Error ? error.message : "Erro interno",
|
|
},
|
|
{ status: 500 }
|
|
);
|
|
}
|
|
}
|
|
|