feat: adicionar sistema de backup e badge editável na página inicial

This commit is contained in:
Erik
2025-11-29 12:22:56 -03:00
parent b73eb6c3eb
commit 99530200b4
13 changed files with 1511 additions and 41 deletions

353
docs/BACKUP_SYSTEM.md Normal file
View File

@@ -0,0 +1,353 @@
# Backup & Restore System - Guia de Implementação
## 📋 Visão Geral
Este sistema permite criar, gerenciar e fazer download de backups completos do banco de dados PostgreSQL e arquivos MinIO através de uma interface web integrada ao painel administrativo.
## 🎯 Características
- ✅ Backup completo do PostgreSQL com `pg_dump`
- ✅ Backup dos dados do MinIO
- ✅ Compactação automática em `tar.gz`
- ✅ Interface intuitiva no painel admin
- ✅ Download de backups
- ✅ Remoção de backups antigos
- ✅ Histórico com datas e tamanhos
- ✅ Funcionamento multi-ambiente (Docker, Local, Dokploy)
## 📁 Estrutura de Arquivos
```
frontend/
├── src/
│ ├── app/
│ │ ├── api/
│ │ │ └── backup/
│ │ │ ├── route.ts # POST/GET/DELETE - CRUD de backups
│ │ │ └── download/
│ │ │ └── route.ts # GET - Download de backups
│ │ └── admin/
│ │ └── configuracoes/
│ │ └── page.tsx # Interface de configurações com backup
│ └── components/
│ └── admin/
│ └── BackupManager.tsx # Componente UI do gerenciador
└── .backups/ # Diretório onde os backups são salvos
```
## 🔧 Variáveis de Ambiente Necessárias
Adicione ao seu `.env` ou ao `docker-compose.yml`:
```env
# PostgreSQL
POSTGRES_USER=admin
POSTGRES_PASSWORD=adminpassword
POSTGRES_DB=occto_db
POSTGRES_HOST=postgres
POSTGRES_PORT=5432
# MinIO
MINIO_ENDPOINT=minio
MINIO_PORT=9000
MINIO_ACCESS_KEY=admin
MINIO_SECRET_KEY=adminpassword
MINIO_BUCKET_NAME=occto-images
MINIO_USE_SSL=false
```
## 🚀 Como Usar
### 1. **No Painel Admin**
1. Acesse `/admin/configuracoes`
2. Desça até a seção **"Backup & Restauração"**
3. Clique em **"Criar Backup Agora"** para iniciar um novo backup
4. Visualize o histórico de backups salvos
5. Download de um backup específico: clique no ícone de download
6. Remover um backup: clique no ícone de lixeira
### 2. **Via API (Programaticamente)**
```javascript
// Criar backup
const response = await fetch('/api/backup', {
method: 'POST',
headers: {
'Authorization': 'Bearer seu_token_aqui',
'Content-Type': 'application/json'
}
});
// Listar backups
const response = await fetch('/api/backup', {
headers: {
'Authorization': 'Bearer seu_token_aqui'
}
});
// Download de backup
const response = await fetch('/api/backup/download?file=backup-2025-11-28.tar.gz', {
headers: {
'Authorization': 'Bearer seu_token_aqui'
}
});
// Remover backup
const response = await fetch('/api/backup?id=backup-2025-11-28', {
method: 'DELETE',
headers: {
'Authorization': 'Bearer seu_token_aqui'
}
});
```
## 🏗️ Replicação em Outro Projeto Next.js
Se você quer implementar este sistema em outro projeto Next.js:
### Passo 1: Copiar os Arquivos
```bash
# Copiar as rotas da API
cp -r frontend/src/app/api/backup seu_projeto/src/app/api/
# Copiar o componente UI
cp frontend/src/components/admin/BackupManager.tsx seu_projeto/src/components/admin/
```
### Passo 2: Adicionar ao Docker Compose
Se estiver usando Docker:
```yaml
services:
postgres:
image: postgres:12-alpine
container_name: seu_postgres
environment:
POSTGRES_USER: admin
POSTGRES_PASSWORD: adminpassword
POSTGRES_DB: seu_db
volumes:
- postgres_data:/var/lib/postgresql/data
# Montar diretório de backups
- ./backups:/app/.backups
networks:
- seu_network
healthcheck:
test: ["CMD-SHELL", "pg_isready -U admin"]
interval: 10s
timeout: 5s
retries: 5
seu_frontend:
# ... suas configurações
volumes:
# Compartilhar diretório de backups
- ./backups:/app/.backups
depends_on:
postgres:
condition: service_healthy
```
### Passo 3: Integrar na Página de Configurações
```tsx
// Sua página de configurações
import { BackupManager } from '@/components/admin/BackupManager';
export default function ConfiguracoesPage() {
return (
<div>
{/* Suas outras configurações */}
{/* Adicionar seção de backup */}
<div className="border-t pt-8 mt-8">
<h2 className="text-2xl font-bold mb-6">Backup & Restauração</h2>
<BackupManager />
</div>
</div>
);
}
```
### Passo 4: Autenticação
O sistema espera um token no header `Authorization: Bearer token`.
Você pode:
**Opção A:** Usar o token do usuário logado
```typescript
// No componente BackupManager
const token = localStorage.getItem('auth_token');
```
**Opção B:** Criar um middleware de autenticação
```typescript
// api/backup/route.ts
function authenticateRequest(request: NextRequest): boolean {
const token = request.headers.get('authorization');
// Implementar sua lógica de autenticação
return validateToken(token);
}
export async function POST(request: NextRequest) {
if (!authenticateRequest(request)) {
return NextResponse.json({ error: 'Não autorizado' }, { status: 401 });
}
// ... resto do código
}
```
**Opção C:** Usar autenticação de sessão (exemplo com NextAuth)
```typescript
import { getServerSession } from 'next-auth/next';
import { authOptions } from '@/app/api/auth/[...nextauth]/route';
export async function POST(request: NextRequest) {
const session = await getServerSession(authOptions);
if (!session) {
return NextResponse.json({ error: 'Não autorizado' }, { status: 401 });
}
// ... resto do código
}
```
## 📊 Estrutura do Backup
Um backup `.tar.gz` contém:
```
backup-2025-11-28/
├── database.sql # Dump completo do PostgreSQL
├── minio-data/ # Cópia de todos os arquivos do MinIO
│ └── [arquivos...]
└── metadata.json # Informações do backup
{
"timestamp": "2025-11-28T10:30:45.123Z",
"database": "occto_db",
"hostname": "postgres",
"minioEndpoint": "minio",
"version": "1.0"
}
```
## 🔐 Segurança
### Recomendações:
1. **Autenticação**
- Sempre valide a autenticação nas rotas de backup
- Use tokens JWT ou sessões seguras
2. **Autorização**
- Apenas administradores devem ter acesso
- Adicione verificação de roles/permissões
3. **Armazenamento de Backups**
- Considere armazenar em local protegido
- Implemente limpeza automática de backups antigos
- Criptografe backups sensíveis
4. **Path Traversal**
- O código já implementa validação com `path.resolve()`
- Nunca permita caminhos arbitrários
### Exemplo de Middleware de Autorização:
```typescript
import { NextRequest, NextResponse } from 'next/server';
function isAdmin(request: NextRequest): boolean {
const token = request.headers.get('authorization');
// Validar se o token corresponde a um admin
return validateAdminToken(token);
}
export async function POST(request: NextRequest) {
if (!isAdmin(request)) {
return NextResponse.json(
{ error: 'Apenas administradores podem criar backups' },
{ status: 403 }
);
}
// ... resto do código
}
```
## 🐛 Troubleshooting
### Erro: "pg_dump: comando não encontrado"
**Solução:** Certifique-se de que PostgreSQL Tools está instalado no container ou host.
```dockerfile
FROM node:18-alpine
# Adicionar PostgreSQL client
RUN apk add --no-cache postgresql-client
WORKDIR /app
# ... resto do Dockerfile
```
### Erro: "MinIO data não encontrado"
**Solução:** Verifique o caminho do volume do MinIO no docker-compose.
```yaml
volumes:
- ./minio_data:/data # Caminho correto no container
- ./backups:/app/.backups
```
### Erro 401 "Não autorizado"
**Solução:** Verifique se o token está sendo enviado corretamente.
```javascript
// Sempre enviar token
const token = localStorage.getItem('auth_token');
if (!token) {
console.error('Token não encontrado');
return;
}
fetch('/api/backup', {
headers: {
'Authorization': `Bearer ${token}`
}
});
```
## 📈 Melhorias Futuras
- [ ] Agendamento automático de backups (cron)
- [ ] Envio automático para S3/Cloud Storage
- [ ] Compressão em background
- [ ] Restauração de backups via interface
- [ ] Notificações via email
- [ ] Verificação de integridade de backup
- [ ] Versionamento de backups
- [ ] Limpeza automática de backups antigos
## 📞 Suporte
Para mais informações ou dúvidas sobre implementação, consulte a documentação oficial:
- [Next.js API Routes](https://nextjs.org/docs/app/building-your-application/routing/route-handlers)
- [PostgreSQL pg_dump](https://www.postgresql.org/docs/current/app-pgdump.html)
- [MinIO Client](https://docs.min.io/minio/baremetal/)
---
**Versão:** 1.0
**Data:** Novembro 2025
**Compatibilidade:** Next.js 13.4+ com App Router