feat: implement POST method for full backup restoration in API
This commit is contained in:
@@ -1,9 +1,10 @@
|
||||
import { NextRequest, NextResponse } from 'next/server';
|
||||
import prisma from '@/lib/prisma';
|
||||
import { minioClient, bucketName, ensureBucketExists } from '@/lib/minio';
|
||||
import { minioClient, bucketName, ensureBucketExists, s3Client } from '@/lib/minio';
|
||||
import { cookies } from 'next/headers';
|
||||
import jwt from 'jsonwebtoken';
|
||||
import JSZip from 'jszip';
|
||||
import { PutObjectCommand } from '@aws-sdk/client-s3';
|
||||
|
||||
async function authenticate() {
|
||||
const cookieStore = await cookies();
|
||||
@@ -94,3 +95,105 @@ export async function GET() {
|
||||
return NextResponse.json({ error: 'Erro ao processar backup completo' }, { status: 500 });
|
||||
}
|
||||
}
|
||||
|
||||
// POST /api/admin/backup/full - Restaurar TUDO (Dados + Mídias) a partir de um ZIP
|
||||
export async function POST(req: NextRequest) {
|
||||
try {
|
||||
// Verificar se é uma restauração de emergência (banco vazio) ou se está logado
|
||||
const userCount = await prisma.user.count();
|
||||
const user = await authenticate();
|
||||
|
||||
// Se houver usuários e não estiver logado, bloqueia
|
||||
if (userCount > 0 && !user) {
|
||||
return NextResponse.json({ error: 'Não autorizado. Use a página de emergência apenas em instalações novas.' }, { status: 401 });
|
||||
}
|
||||
|
||||
const formData = await req.formData();
|
||||
const file = formData.get('file') as File;
|
||||
|
||||
if (!file) {
|
||||
return NextResponse.json({ error: 'Arquivo não enviado' }, { status: 400 });
|
||||
}
|
||||
|
||||
const buffer = Buffer.from(await file.arrayBuffer());
|
||||
const zip = await JSZip.loadAsync(buffer);
|
||||
|
||||
// 1. Restaurar Dados do Banco (data.json)
|
||||
const dataFile = zip.file('data.json');
|
||||
if (!dataFile) {
|
||||
return NextResponse.json({ error: 'Arquivo data.json não encontrado no ZIP' }, { status: 400 });
|
||||
}
|
||||
|
||||
const dataContent = await dataFile.async('string');
|
||||
const data = JSON.parse(dataContent);
|
||||
|
||||
// Importação atômica
|
||||
await prisma.$transaction(async (tx) => {
|
||||
// Limpar dados atuais
|
||||
await tx.message.deleteMany();
|
||||
await tx.project.deleteMany();
|
||||
await tx.service.deleteMany();
|
||||
await tx.pageContent.deleteMany();
|
||||
await tx.user.deleteMany();
|
||||
|
||||
// Restaurar Usuários
|
||||
if (data.users && data.users.length > 0) {
|
||||
await tx.user.createMany({ data: data.users });
|
||||
}
|
||||
|
||||
// Restaurar Projetos
|
||||
if (data.projects && data.projects.length > 0) {
|
||||
await tx.project.createMany({ data: data.projects });
|
||||
}
|
||||
|
||||
// Restaurar Serviços
|
||||
if (data.services && data.services.length > 0) {
|
||||
await tx.service.createMany({ data: data.services });
|
||||
}
|
||||
|
||||
// Restaurar Conteúdo de Páginas
|
||||
if (data.pageContents && data.pageContents.length > 0) {
|
||||
await tx.pageContent.createMany({ data: data.pageContents });
|
||||
}
|
||||
|
||||
// Restaurar Mensagens
|
||||
if (data.messages && data.messages.length > 0) {
|
||||
await tx.message.createMany({ data: data.messages });
|
||||
}
|
||||
|
||||
// Restaurar Configurações
|
||||
if (data.settings) {
|
||||
await tx.settings.deleteMany();
|
||||
await tx.settings.create({ data: data.settings });
|
||||
}
|
||||
});
|
||||
|
||||
// 2. Restaurar Mídias no S3/MinIO
|
||||
await ensureBucketExists();
|
||||
const mediaFolder = zip.folder('media');
|
||||
if (mediaFolder) {
|
||||
const files = Object.keys(mediaFolder.files);
|
||||
for (const fileName of files) {
|
||||
const mediaFile = mediaFolder.file(fileName);
|
||||
if (mediaFile && !mediaFile.dir) {
|
||||
const content = await mediaFile.async('nodebuffer');
|
||||
const pureFileName = fileName.replace('media/', '');
|
||||
|
||||
await s3Client.send(new PutObjectCommand({
|
||||
Bucket: bucketName,
|
||||
Key: pureFileName,
|
||||
Body: content
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NextResponse.json({ message: 'Restauração completa concluída com sucesso' });
|
||||
} catch (error) {
|
||||
console.error('Erro na restauração completa:', error);
|
||||
return NextResponse.json({
|
||||
error: 'Erro ao processar restauração',
|
||||
details: error instanceof Error ? error.message : String(error)
|
||||
}, { status: 500 });
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user