Initial commit: LexMind - Plataforma Jurídica Inteligente

This commit is contained in:
bigtux
2026-02-10 15:46:26 -03:00
commit 08bd4f039d
108 changed files with 75782 additions and 0 deletions

View File

@@ -0,0 +1,162 @@
import { NextRequest, NextResponse } from 'next/server'
import { getServerSession } from 'next-auth'
import { authOptions } from '@/lib/auth'
import { prisma } from '@/lib/prisma'
import { uploadFile, buildKey } from '@/lib/spaces'
const ALLOWED_TYPES = [
'application/pdf',
'application/msword',
'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
'text/plain',
]
const MAX_SIZE = 50 * 1024 * 1024 // 50MB
const STORAGE_LIMITS: Record<string, number> = {
FREE: 1 * 1024 * 1024 * 1024, // 1GB
STARTER: 1 * 1024 * 1024 * 1024, // 1GB
PRO: 5 * 1024 * 1024 * 1024, // 5GB
ENTERPRISE: 20 * 1024 * 1024 * 1024, // 20GB
}
export async function POST(req: NextRequest) {
const session = await getServerSession(authOptions)
if (!session?.user?.id) {
return NextResponse.json({ error: 'Não autorizado' }, { status: 401 })
}
try {
const formData = await req.formData()
const file = formData.get('file') as File | null
if (!file) {
return NextResponse.json({ error: 'Nenhum arquivo enviado' }, { status: 400 })
}
// Validate file extension (defense in depth)
const ext = file.name.split(".").pop()?.toLowerCase()
const ALLOWED_EXTENSIONS = ["pdf", "doc", "docx", "txt"]
if (!ext || !ALLOWED_EXTENSIONS.includes(ext)) {
return NextResponse.json(
{ error: "Extensão de arquivo não permitida" },
{ status: 400 }
)
}
// Validate mime type
if (!ALLOWED_TYPES.includes(file.type)) {
return NextResponse.json(
{ error: 'Tipo de arquivo não permitido. Aceitos: PDF, DOCX, DOC, TXT' },
{ status: 400 }
)
}
// Validate size
if (file.size > MAX_SIZE) {
return NextResponse.json(
{ error: 'Arquivo muito grande. Máximo: 50MB' },
{ status: 400 }
)
}
// Check storage limit
const user = await prisma.user.findUnique({
where: { id: session.user.id },
select: { plan: true },
})
const storageLimit = STORAGE_LIMITS[user?.plan || 'FREE'] || STORAGE_LIMITS.FREE
const usedStorage = await prisma.upload.aggregate({
where: { userId: session.user.id },
_sum: { size: true },
})
const currentUsage = usedStorage._sum.size || 0
if (currentUsage + file.size > storageLimit) {
return NextResponse.json(
{ error: 'Limite de armazenamento atingido. Faça upgrade do plano para mais espaço.' },
{ status: 400 }
)
}
// Upload to Spaces
const buffer = Buffer.from(await file.arrayBuffer())
const key = buildKey(session.user.id, file.name)
await uploadFile(buffer, key, file.type)
// Save to DB
const upload = await prisma.upload.create({
data: {
userId: session.user.id,
filename: file.name,
key,
size: file.size,
mimeType: file.type,
},
})
return NextResponse.json({
upload: {
id: upload.id,
filename: upload.filename,
size: upload.size,
mimeType: upload.mimeType,
createdAt: upload.createdAt,
},
})
} catch (error) {
console.error('Upload error:', error)
return NextResponse.json({ error: 'Erro ao fazer upload' }, { status: 500 })
}
}
export async function GET(req: NextRequest) {
const session = await getServerSession(authOptions)
if (!session?.user?.id) {
return NextResponse.json({ error: 'Não autorizado' }, { status: 401 })
}
const { searchParams } = new URL(req.url)
const page = Math.max(1, Math.min(1000, parseInt(searchParams.get('page') || '1')))
const limit = Math.max(1, Math.min(100, parseInt(searchParams.get('limit') || '20')))
const skip = (page - 1) * limit
const [uploads, total, storageUsed] = await Promise.all([
prisma.upload.findMany({
where: { userId: session.user.id },
orderBy: { createdAt: 'desc' },
skip,
take: limit,
select: {
id: true,
filename: true,
size: true,
mimeType: true,
createdAt: true,
},
}),
prisma.upload.count({ where: { userId: session.user.id } }),
prisma.upload.aggregate({
where: { userId: session.user.id },
_sum: { size: true },
}),
])
const user = await prisma.user.findUnique({
where: { id: session.user.id },
select: { plan: true },
})
const storageLimit = STORAGE_LIMITS[user?.plan || 'FREE'] || STORAGE_LIMITS.FREE
return NextResponse.json({
uploads,
total,
page,
totalPages: Math.ceil(total / limit),
storageUsed: storageUsed._sum.size || 0,
storageLimit,
})
}