Skip to content

GabrielFinotti/api-backup-service

Repository files navigation

🗄️ API Backup Service

Serviço de Backup Automatizado para MongoDB

License: MIT Version TypeScript Node.js Express MongoDB Tests

CaracterísticasInstalaçãoUsoAPIExemplosContribuir


📋 Sobre o Projeto

API Backup Service é uma solução RESTful robusta e segura para realizar backups automatizados de coleções MongoDB. Este serviço atua como uma ponte de backup, permitindo que você preserve snapshots de seus dados de forma centralizada e organizada.

💡 O que faz?

  • ✅ Recebe dados de coleções MongoDB via API REST
  • ✅ Armazena backups em banco de dados dedicado
  • ✅ Mantém logs de backup em coleção separada (backup_logs)
  • ✅ Substitui dados antigos automaticamente (drop e insert)
  • ✅ Protege endpoints com autenticação Basic Auth
  • ✅ Oferece endpoint de health check para monitoramento
  • NOVO: Recupera dados de coleções específicas
  • NOVO: Consulta logs de backup por database
  • NOVO: Lista todos os databases do MongoDB

🎯 Casos de Uso

  • Backup automatizado de dados críticos
  • Sincronização de dados entre ambientes
  • Histórico de snapshots para auditoria
  • Disaster recovery e continuidade de negócio

✨ Características

Recursos Principais

Recurso Descrição
🔐 Autenticação Segura Basic Auth para proteger todos os endpoints
📊 Sistema de Logs Logs de backup armazenados em coleção separada
🔄 Substituição Inteligente Sobrescreve backups antigos automaticamente
🏥 Health Check Endpoint dedicado para monitoramento
📝 TypeScript Código totalmente tipado para maior segurança
Testado Suíte completa de testes com Jest (49 testes)
🔍 Recuperação de Dados Recupere dados de qualquer coleção
📋 Gestão de Logs Consulte logs de backup por database
🗄️ Listagem de Databases Visualize todos os databases disponíveis
📦 Grande Capacidade Suporta payloads de até 1000mb (1GB) para backups volumosos

Stack Tecnológica

Tecnologia Versão Descrição
Node.js 18+ Runtime JavaScript
TypeScript 5.9+ Superset JavaScript tipado
Express 5.1 Framework web minimalista
MongoDB 5.x Banco de dados NoSQL
Mongoose 5.13 ODM para MongoDB
Jest 30+ Framework de testes

📦 Instalação

Pré-requisitos

Antes de começar, certifique-se de ter instalado:

Passos de Instalação

1. Clone o repositório:

git clone https://github.com/GabrielFinotti/api-backup-service.git
cd api-backup-service

2. Instale as dependências:

npm install

3. Configure as variáveis de ambiente:

Crie um arquivo .env na raiz do projeto:

# Configurações do Servidor
PORT=3000

# Credenciais de Autenticação
SECRET_USER=seu_usuario
SECRET_PASS=sua_senha

# Conexão MongoDB
MONGO_URI=mongodb://localhost:27017

⚠️ Importante: Nunca commite o arquivo .env no repositório. Ele já está incluído no .gitignore.


🚀 Guia de Uso Rápido

🐳 Usando Docker

# 1. Configure as variáveis de ambiente
cp .env.example .env
# Edite o arquivo .env com suas credenciais

# 2. Inicie o container
docker-compose up -d

# 3. Verifique o status
docker-compose ps

# 4. Ver logs
docker-compose logs -f

# 5. Parar o container
docker-compose down

� Instalação Local

Pré-requisitos

Comandos Disponíveis

Comando Descrição
npm run dev Inicia o servidor em modo de desenvolvimento com hot-reload
npm run build Compila o projeto TypeScript para JavaScript
npm start Inicia o servidor em modo produção
npm test Executa a suíte de testes

Desenvolvimento

Inicie o servidor em modo de desenvolvimento:

npm run dev

O servidor estará disponível em http://localhost:3000

Produção

Para executar em produção:

# Compila o projeto
npm run build

# Inicia o servidor
npm start

Executando Testes

npm test

📚 Documentação da API

🌐 Base URL

http://localhost:3000/api

🔐 Autenticação

Todos os endpoints (exceto /health) requerem autenticação Basic Auth.

Como Autenticar

  1. Combine suas credenciais no formato: usuario:senha
  2. Codifique em Base64
  3. Adicione no header: Authorization: Basic <base64>

Exemplo de Codificação:

# Credenciais: admin:password123
# Base64: YWRtaW46cGFzc3dvcmQxMjM=
Authorization: Basic YWRtaW46cGFzc3dvcmQxMjM=

Gerando Base64:

# Linux/Mac
echo -n "admin:password123" | base64

# Windows PowerShell
[Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes("admin:password123"))

📍 Endpoints Disponíveis

📊 Visão Geral

Método Endpoint Descrição Autenticação
GET /api/health Health check da API
POST /api/backup Salvar backup de uma coleção
POST /api/recover Recuperar dados de uma coleção
POST /api/logs Listar logs de backup de um banco
GET /api/databases Listar todos os databases MongoDB

GET /api/health - Health Check

Verifica se a API está funcionando corretamente.

Autenticação: ❌ Não requerida

Resposta de Sucesso (200):

{
  "status": "ok",
  "timestamp": "2025-10-07T14:30:00.000Z"
}

Exemplo cURL:

curl -X GET http://localhost:3000/api/health

Exemplo JavaScript:

fetch('http://localhost:3000/api/health')
  .then(response => response.json())
  .then(data => console.log(data));

POST /api/backup - Salvar Backup

Realiza o backup de uma coleção MongoDB.

Autenticação: ✅ Requerida (Basic Auth)

Headers:

Content-Type: application/json
Authorization: Basic <credenciais_base64>

Body (JSON):

{
  "database": "nome_do_banco",
  "collectionsName": "nome_da_colecao",
  "data": {
    // Seus dados aqui (qualquer estrutura JSON válida)
  }
}

Parâmetros:

Campo Tipo Descrição Obrigatório
database string Nome do banco de dados MongoDB de destino
collectionsName string Nome da coleção onde o backup será salvo
data any Dados a serem salvos no backup

Respostas:

200 OK - Backup salvo com sucesso
{
  "status": "success",
  "statusCode": 200,
  "message": "Backup salvo com sucesso",
  "data": {
    "itemCount": 1,
    "log": {
      "database": "nome_do_banco",
      "collectionsName": "nome_da_colecao",
      "date": "07/10/2025",
      "timestamp": "2025-10-07T14:30:00.000Z"
    }
  }
}
400 Bad Request - Requisição inválida
{
  "status": "error",
  "statusCode": 400,
  "message": "Requisição inválida",
  "data": null
}
🔒 401 Unauthorized - Não autorizado
{
  "status": "error",
  "statusCode": 401,
  "message": "Não autorizado",
  "data": null
}
💥 500 Internal Server Error - Erro interno
{
  "status": "error",
  "statusCode": 500,
  "message": "Ocorreu um erro interno no servidor",
  "data": null
}

POST /api/recover - Recuperar Dados

Recupera todos os dados de uma coleção específica.

Autenticação: ✅ Requerida (Basic Auth)

Headers:

Content-Type: application/json
Authorization: Basic <credenciais_base64>

Body (JSON):

{
  "database": "nome_do_banco",
  "collectionName": "nome_da_colecao"
}

Parâmetros:

Campo Tipo Descrição Obrigatório
database string Nome do banco de dados MongoDB
collectionName string Nome da coleção a ser recuperada

Resposta de Sucesso (200):

{
  "status": "success",
  "statusCode": 200,
  "message": "Dados recuperados com sucesso",
  "data": {
    "collectionName": "nome_da_colecao",
    "database": "nome_do_banco",
    "documentCount": 150,
    "documents": [
      {
        "_id": "507f1f77bcf86cd799439011",
        "campo1": "valor1",
        "campo2": "valor2"
      }
    ]
  }
}

Exemplo cURL:

curl -X POST http://localhost:3000/api/recover \
  -H "Content-Type: application/json" \
  -H "Authorization: Basic YWRtaW46cGFzc3dvcmQxMjM=" \
  -d '{
    "database": "meu_backup_db",
    "collectionName": "usuarios_backup"
  }'

POST /api/logs - Listar Logs de Backup

Recupera todos os logs de backup de um banco de dados específico.

Autenticação: ✅ Requerida (Basic Auth)

Headers:

Content-Type: application/json
Authorization: Basic <credenciais_base64>

Body (JSON):

{
  "database": "nome_do_banco"
}

Parâmetros:

Campo Tipo Descrição Obrigatório
database string Nome do banco de dados MongoDB

Resposta de Sucesso (200):

{
  "status": "success",
  "statusCode": 200,
  "message": "Logs recuperados com sucesso",
  "data": {
    "database": "meu_backup_db",
    "logCount": 3,
    "logs": [
      {
        "database": "meu_backup_db",
        "collectionsName": "usuarios_backup",
        "date": "07/10/2025",
        "timestamp": "2025-10-07T14:30:00.000Z"
      },
      {
        "database": "meu_backup_db",
        "collectionsName": "produtos_backup",
        "date": "07/10/2025",
        "timestamp": "2025-10-07T13:15:00.000Z"
      }
    ]
  }
}

Exemplo cURL:

curl -X POST http://localhost:3000/api/logs \
  -H "Content-Type: application/json" \
  -H "Authorization: Basic YWRtaW46cGFzc3dvcmQxMjM=" \
  -d '{
    "database": "meu_backup_db"
  }'

GET /api/databases - Listar Databases

Lista todos os databases disponíveis no MongoDB.

Autenticação: ✅ Requerida (Basic Auth)

Headers:

Authorization: Basic <credenciais_base64>

Resposta de Sucesso (200):

{
  "status": "success",
  "statusCode": 200,
  "message": "Databases recuperados com sucesso",
  "data": {
    "databaseCount": 3,
    "databases": [
      {
        "name": "admin",
        "sizeOnDisk": 40960,
        "empty": false
      },
      {
        "name": "meu_backup_db",
        "sizeOnDisk": 8192000,
        "empty": false
      },
      {
        "name": "local",
        "sizeOnDisk": 73728,
        "empty": false
      }
    ]
  }
}

Informações Retornadas:

Campo Tipo Descrição
name string Nome do database
sizeOnDisk number Tamanho em bytes no disco
empty boolean Se o database está vazio

Exemplo cURL:

curl -X GET http://localhost:3000/api/databases \
  -H "Authorization: Basic YWRtaW46cGFzc3dvcmQxMjM="

Exemplo JavaScript:

const credentials = btoa('admin:password123');

fetch('http://localhost:3000/api/databases', {
  method: 'GET',
  headers: {
    'Authorization': `Basic ${credentials}`
  }
})
  .then(response => response.json())
  .then(data => console.log('Databases:', data))
  .catch(error => console.error('Erro:', error));

💻 Exemplos de Uso

cURL

curl -X POST http://localhost:3000/api/backup \
  -H "Content-Type: application/json" \
  -H "Authorization: Basic YWRtaW46cGFzc3dvcmQxMjM=" \
  -d '{
    "database": "meu_backup_db",
    "collectionsName": "usuarios_backup",
    "data": {
      "usuarios": [
        { "id": 1, "nome": "João Silva", "email": "joao@example.com" },
        { "id": 2, "nome": "Maria Santos", "email": "maria@example.com" }
      ],
      "total": 2
    }
  }'

JavaScript (Fetch API)

const username = 'admin';
const password = 'password123';
const credentials = btoa(`${username}:${password}`);

const backupData = {
  database: 'meu_backup_db',
  collectionsName: 'usuarios_backup',
  data: {
    usuarios: [
      { id: 1, nome: 'João Silva', email: 'joao@example.com' },
      { id: 2, nome: 'Maria Santos', email: 'maria@example.com' }
    ],
    total: 2
  }
};

fetch('http://localhost:3000/api/backup', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': `Basic ${credentials}`
  },
  body: JSON.stringify(backupData)
})
  .then(response => response.json())
  .then(data => console.log('✅ Backup realizado:', data))
  .catch(error => console.error('❌ Erro:', error));

Node.js (Axios)

const axios = require('axios');

const username = 'admin';
const password = 'password123';
const credentials = Buffer.from(`${username}:${password}`).toString('base64');

const backupData = {
  database: 'meu_backup_db',
  collectionsName: 'usuarios_backup',
  data: {
    usuarios: [
      { id: 1, nome: 'João Silva', email: 'joao@example.com' },
      { id: 2, nome: 'Maria Santos', email: 'maria@example.com' }
    ],
    total: 2
  }
};

axios.post('http://localhost:3000/api/backup', backupData, {
  headers: {
    'Content-Type': 'application/json',
    'Authorization': `Basic ${credentials}`
  }
})
  .then(response => console.log('✅ Backup realizado:', response.data))
  .catch(error => console.error('❌ Erro:', error.response?.data || error.message));

Python (Requests)

import requests
from base64 import b64encode

# Configuração
username = 'admin'
password = 'password123'
credentials = b64encode(f'{username}:{password}'.encode()).decode()

url = 'http://localhost:3000/api/backup'

headers = {
    'Content-Type': 'application/json',
    'Authorization': f'Basic {credentials}'
}

data = {
    'database': 'meu_backup_db',
    'collectionsName': 'usuarios_backup',
    'data': {
        'usuarios': [
            {'id': 1, 'nome': 'João Silva', 'email': 'joao@example.com'},
            {'id': 2, 'nome': 'Maria Santos', 'email': 'maria@example.com'}
        ],
        'total': 2
    }
}

# Realizar backup
response = requests.post(url, headers=headers, json=data)

if response.status_code == 200:
    print('✅ Backup realizado:', response.json())
else:
    print('❌ Erro:', response.json())

PowerShell

# Configuração
$username = "admin"
$password = "password123"
$credentials = [Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes("${username}:${password}"))

$headers = @{
    "Content-Type" = "application/json"
    "Authorization" = "Basic $credentials"
}

$body = @{
    database = "meu_backup_db"
    collectionsName = "usuarios_backup"
    data = @{
        usuarios = @(
            @{ id = 1; nome = "João Silva"; email = "joao@example.com" }
            @{ id = 2; nome = "Maria Santos"; email = "maria@example.com" }
        )
        total = 2
    }
} | ConvertTo-Json -Depth 10

# Realizar backup
Invoke-RestMethod -Uri "http://localhost:3000/api/backup" -Method Post -Headers $headers -Body $body

🔒 Segurança

Medidas Implementadas

Aspecto Implementação
Autenticação Basic Auth em todos os endpoints protegidos
Variáveis de Ambiente Credenciais armazenadas em .env (não versionado)
Validação Middleware valida credenciais antes de processar requisições
Headers Verificação de headers de autenticação obrigatórios

Recomendações para Produção

  • Use HTTPS: Sempre use HTTPS em produção para criptografar credenciais na transmissão
  • Credenciais Fortes: Use senhas complexas e únicas
  • Rotação de Credenciais: Altere senhas periodicamente
  • Rate Limiting: Considere implementar rate limiting para prevenir ataques de força bruta
  • Logs de Auditoria: Monitore logs para detectar tentativas de acesso não autorizado
  • Firewall: Configure firewall para permitir apenas IPs confiáveis

⚙️ Comportamento do Backup

Como Funciona

graph LR
    A[Cliente] -->|POST /api/backup| B[API]
    B -->|Autentica| C{Válido?}
    C -->|Não| D[401 Unauthorized]
    C -->|Sim| E[Conecta MongoDB]
    E --> F[Drop Coleção de Dados]
    F --> G[Insere Dados]
    G --> H[Atualiza backup_logs]
    H --> I[200 Success]
Loading

Características do Backup

Característica Descrição
Substituição Automática A coleção de dados é dropada antes de inserir novos dados (sobrescreve backup anterior)
Separação de Dados e Logs Dados são salvos na coleção especificada, logs em backup_logs
Logs Persistentes A coleção backup_logs é atualizada (upsert) a cada backup bem-sucedido
Metadados de Log Armazena database, collectionsName, date e timestamp na coleção de logs
Contagem de Itens Retorna a quantidade de itens salvos ao invés dos dados completos
Sanitização de Dados Remove automaticamente chaves que começam com $ (reservadas pelo MongoDB)
Inserção Otimizada Usa insertMany para arrays e insertOne para objetos únicos
Formato da Data DD/MM/YYYY (formato brasileiro)
Dados Puros Apenas os dados (arrays/objetos) são salvos na coleção principal
Limite de Payload Suporta requisições de até 1000mb (1GB) para grandes volumes de dados

Exemplo de Dados Armazenados

Entrada:

{
  "database": "backup_db",
  "collectionsName": "users",
  "data": {
    "users": [{"id": 1, "name": "João"}]
  }
}

Armazenado na Coleção users (dados apenas):

{
  "users": [{"id": 1, "name": "João"}]
}

Armazenado na Coleção backup_logs (metadados):

{
  "database": "backup_db",
  "collectionsName": "users",
  "date": "07/10/2025",
  "timestamp": "2025-10-07T14:30:00.000Z"
}

Retorno da API:

{
  "status": "success",
  "statusCode": 200,
  "message": "Backup salvo com sucesso",
  "data": {
    "itemCount": 1,
    "log": {
      "database": "backup_db",
      "collectionsName": "users",
      "date": "07/10/2025",
      "timestamp": "2025-10-07T14:30:00.000Z"
    }
  }
}

💡 Nota: A API retorna itemCount com a quantidade de documentos inseridos, não os dados completos. Para arrays, retorna o tamanho do array; para objetos, retorna 1.


🧪 Testes

Cobertura de Testes

O projeto inclui testes unitários para componentes críticos:

Componente Arquivo Descrição
Auth Middleware auth.middleware.test.ts Testa autenticação Basic Auth
Backup Service backup.service.test.ts Testa lógica de backup

Executando os Testes

# Executar todos os testes
npm test

# Executar em modo watch
npm test -- --watch

# Executar com cobertura
npm test -- --coverage

Estrutura de Testes

test/
├── middlewares/
│   └── auth.middleware.test.ts    # Testes de autenticação
└── services/
    └── backup.service.test.ts     # Testes do serviço de backup

📁 Estrutura do Projeto

api-backup-service/
├── src/                        # Código fonte
│   ├── controllers/            # Controladores da API
│   │   └── saveBackup.controller.ts
│   ├── database/               # Configuração do banco de dados
│   │   └── config/
│   │       └── createConnection.ts
│   ├── interface/              # DTOs e interfaces TypeScript
│   │   └── backupDataInput.dto.ts
│   ├── middlewares/            # Middlewares Express
│   │   └── auth.middleware.ts
│   ├── routes/                 # Definição de rotas
│   │   └── backup.route.ts
│   ├── services/               # Lógica de negócio
│   │   └── backup.service.ts
│   └── server.ts               # Ponto de entrada da aplicação
│
├── test/                       # Testes unitários
│   ├── middlewares/
│   │   └── auth.middleware.test.ts
│   └── services/
│       └── backup.service.test.ts
│
├── .env                        # Variáveis de ambiente (não versionado)
├── .gitignore                  # Arquivos ignorados pelo Git
├── jest.config.mjs             # Configuração do Jest
├── LICENSE                     # Licença MIT
├── package.json                # Dependências e scripts
├── README.md                   # Este arquivo
├── tsconfig.json               # Configuração TypeScript
└── tsconfig.test.json          # Configuração TypeScript para testes

🚀 Deploy

Variáveis de Ambiente

Certifique-se de configurar as seguintes variáveis no ambiente de produção:

PORT=3000
SECRET_USER=seu_usuario_seguro
SECRET_PASS=sua_senha_complexa
MONGO_URI=mongodb://seu-servidor:27017

Recomendações para Produção

  • Use HTTPS: Sempre configure SSL/TLS
  • Credenciais Fortes: Use senhas complexas e únicas
  • Firewall: Configure regras de firewall adequadas
  • Monitoramento: Implemente logs e alertas
  • Backup: Configure backup regular do MongoDB

🤝 Contribuindo

Contribuições são muito bem-vindas! Este projeto segue o padrão de Conventional Commits.

Como Contribuir

  1. Fork o projeto
  2. Clone seu fork: git clone https://github.com/seu-usuario/api-backup-service.git
  3. Crie uma branch para sua feature: git checkout -b feature/minha-feature
  4. Commit suas mudanças: git commit -m 'feat: adiciona nova feature'
  5. Push para a branch: git push origin feature/minha-feature
  6. Abra um Pull Request

Padrão de Commits

  • feat: Nova funcionalidade
  • fix: Correção de bug
  • docs: Alterações na documentação
  • style: Formatação, ponto e vírgula, etc
  • refactor: Refatoração de código
  • test: Adição ou correção de testes
  • chore: Atualizações de build, configs, etc

Diretrizes

  • Mantenha o código limpo e bem documentado
  • Adicione testes para novas funcionalidades
  • Siga o estilo de código existente
  • Atualize a documentação quando necessário

📝 Changelog

Versão Atual: 2.3.0

Para ver o histórico completo de mudanças, consulte o arquivo CHANGELOG.md.

Últimas Mudanças (v2.3.0)

  • ✨ Novo: Limite de payload aumentado para 1000mb (1GB)
  • � Melhorado: Suporte para backups de grandes volumes de dados
  • 🎯 Impacto: Permite backup de coleções com milhares de documentos em uma única requisição

Ver changelog completo →


🐛 Problemas Conhecidos

Nenhum problema conhecido no momento. Se encontrar algum bug, por favor abra uma issue.


💬 Suporte

Se você tiver dúvidas ou precisar de ajuda:

  • 📧 Abra uma issue
  • 💡 Consulte a documentação
  • 🌟 Dê uma estrela no projeto se ele foi útil!

📄 Licença

Este projeto está licenciado sob a Licença MIT - veja o arquivo LICENSE para mais detalhes.

TL;DR: Você pode usar, copiar, modificar, distribuir e até vender este software, desde que mantenha o aviso de copyright original.


👤 Autor

Gabriel H. Finotti


⭐ Se este projeto foi útil, considere dar uma estrela

Feito com ❤️ e TypeScript

About

Um serviço para realizar um ponte de backup de dados

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 2

  •  
  •