Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Latest commit

Β 

History

11 Commits

Folders and files

NameName
Last commit message
Last commit date
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

πŸ“„ DocVault API

API REST completa para gerenciamento seguro de documentos β€” com autenticaΓ§Γ£o JWT, upload de PDF, versionamento automΓ‘tico, verificaΓ§Γ£o de integridade via hash SHA-256, rate limiting e dashboard web.

πŸ”— Demo em produΓ§Γ£o: docvault-api-cl21.vercel.app


πŸš€ Stack

Camada Tecnologia
Framework Next.js 14+ (App Router) + TypeScript
Banco de dados Supabase (PostgreSQL)
AutenticaΓ§Γ£o Supabase Auth (JWT)
Storage Supabase Storage
Rate Limiting Upstash Redis
Testes Vitest + Testing Library
Deploy Vercel

✨ Funcionalidades

πŸ” AutenticaΓ§Γ£o

  • Registro e login com email + senha
  • SessΓ΅es JWT via Supabase Auth
  • Middleware de autenticaΓ§Γ£o em todas as rotas protegidas
  • RenovaΓ§Γ£o automΓ‘tica de tokens

πŸ“„ Documentos

  • Upload de PDFs (mΓ‘x. 10MB)
  • CRUD completo com autorizaΓ§Γ£o por ownership
  • Filtros por status e busca por tΓ­tulo
  • PaginaΓ§Γ£o configurΓ‘vel

πŸ—‚οΈ Versionamento

  • HistΓ³rico automΓ‘tico a cada novo upload
  • Rastreio de quem criou cada versΓ£o e notas de mudanΓ§a

πŸ”’ Integridade

  • Hash SHA-256 gerado no upload e salvo no banco
  • Endpoint de verificaΓ§Γ£o: compara o hash do arquivo enviado com o registrado
  • ComparaΓ§Γ£o timing-safe para evitar timing attacks

πŸ”— Webhooks

  • Eventos automaticamente disparados: document.created, document.updated, document.deleted, document.signed, version.created
  • Assinatura HMAC-SHA256 em todos os payloads
  • Endpoint receptor protegido por X-Webhook-Secret

πŸ›‘οΈ Rate Limiting

  • LimitaΓ§Γ£o por IP via Upstash Redis (sliding window)
  • Rotas de autenticaΓ§Γ£o: 10 req/min
  • Demais rotas: 60 req/min
  • Headers informativos: X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset
  • Fail-open: se o Redis estiver indisponΓ­vel, a API continua funcionando

πŸ–₯️ Dashboard

  • Interface web completa acessΓ­vel em /
  • Login e cadastro integrados
  • Listagem, busca e atualizaΓ§Γ£o de status de documentos
  • Drag-and-drop para upload
  • VerificaΓ§Γ£o de integridade visual
  • NotificaΓ§Γ΅es toast em tempo real

πŸ› οΈ Setup Local

1. Clone e instale

git clone https://github.com/Junio243/docvault-api.git
cd docvault-api
npm install

2. Configure o Supabase

  1. Crie um projeto em supabase.com
  2. VΓ‘ em SQL Editor β†’ New query
  3. Cole e execute o conteΓΊdo de supabase/schema.sql

    O script cria as tabelas, Γ­ndices, polΓ­ticas RLS e o bucket de storage automaticamente.

3. Configure as variΓ‘veis de ambiente

cp .env.example .env.local

Edite .env.local:

# Supabase
NEXT_PUBLIC_SUPABASE_URL=https://seu-projeto.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=sua-anon-key
SUPABASE_SERVICE_ROLE_KEY=sua-service-role-key
NEXT_PUBLIC_APP_URL=http://localhost:3000

# Webhook
WEBHOOK_SECRET=uma-string-secreta-qualquer

# Upstash Redis β€” Rate Limiting (opcional)
# Crie grΓ‘tis em https://console.upstash.com/redis
UPSTASH_REDIS_REST_URL=https://...
UPSTASH_REDIS_REST_TOKEN=...

Nota: As variΓ‘veis do Upstash sΓ£o opcionais. Sem elas, o rate limiting Γ© desativado silenciosamente e tudo continua funcionando.

4. Rode

npm run dev

Acesse: http://localhost:3000


πŸ§ͺ Testes

# Rodar todos os testes
npm test

# Modo watch (re-executa ao salvar)
npm run test:watch

# Com relatΓ³rio de cobertura
npm run test:coverage

Cobertura atual: 26 testes passando em 3 suites:

  • tests/lib/crypto.test.ts β€” hash SHA-256, HMAC, tokens
  • tests/lib/api-response.test.ts β€” helpers de resposta padronizada
  • tests/api/documents.test.ts β€” rota de listagem de documentos

πŸ“š DocumentaΓ§Γ£o da API

Base URL

Local:     http://localhost:3000/api
ProduΓ§Γ£o:  https://docvault-api-cl21.vercel.app/api

AutenticaΓ§Γ£o

Todas as rotas protegidas requerem o cookie de sessΓ£o Supabase (gerenciado automaticamente pelo browser) ou Bearer Token:

Authorization: Bearer <access_token>

πŸ” Auth

POST /api/auth/signup

{ "email": "[email protected]", "password": "senha123" }

POST /api/auth/login

{ "email": "[email protected]", "password": "senha123" }

Resposta:

{
  "success": true,
  "data": {
    "user": { "id": "uuid", "email": "...", "created_at": "..." },
    "session": {
      "access_token": "...",
      "refresh_token": "...",
      "expires_at": 1234567890,
      "expires_in": 3600
    }
  }
}

POST /api/auth/logout

POST /api/auth/refresh β€” { "refresh_token": "..." }

GET /api/auth/me


πŸ“„ Documentos

GET /api/documents

Param Tipo Default DescriΓ§Γ£o
page number 1 PΓ‘gina
limit number 10 Itens por pΓ‘gina (mΓ‘x. 50)
status string β€” Filtra: draft, pending, signed, archived
search string β€” Busca no tΓ­tulo

POST /api/documents β€” multipart/form-data

Campo ObrigatΓ³rio DescriΓ§Γ£o
file βœ… Arquivo PDF (mΓ‘x. 10MB)
title βœ… TΓ­tulo do documento (1–255 chars)
status ❌ Status inicial (default: draft)

GET /api/documents/:id

PATCH /api/documents/:id β€” mesmos campos do POST, todos opcionais

DELETE /api/documents/:id


πŸ“œ Versionamento

GET /api/documents/:id/versions

Retorna todas as versΓ΅es em ordem decrescente.


πŸ”’ VerificaΓ§Γ£o de Integridade

POST /api/documents/:id/verify β€” multipart/form-data

Envia um arquivo PDF e verifica se o hash SHA-256 bate com o armazenado.

{
  "success": true,
  "data": {
    "valid": true,
    "document_id": "uuid",
    "version": 2,
    "stored_hash": "abc123...",
    "provided_hash": "abc123...",
    "message": "Integridade verificada: O arquivo Γ© idΓͺntico ao registrado"
  }
}

GET /api/documents/:id/verify

Retorna as informaΓ§Γ΅es do hash sem realizar comparaΓ§Γ£o.


πŸ”— Webhooks

POST /api/webhooks

Endpoint receptor de eventos. Requer o header:

X-Webhook-Secret: <WEBHOOK_SECRET>

Eventos

Evento Disparado quando
document.created Novo documento criado
document.updated Documento atualizado
document.deleted Documento deletado
document.signed Status alterado para signed
version.created Novo arquivo enviado (nova versΓ£o)

Payload

{
  "event": "document.signed",
  "document_id": "uuid",
  "timestamp": "2026-03-14T01:00:00Z",
  "data": { "signed_by": "user-uuid", "signed_at": "..." }
}

Headers enviados

X-Webhook-Signature: <hmac-sha256-do-payload>
X-Webhook-Event: document.signed
X-Webhook-Secret: <secret>
Content-Type: application/json

Verificar assinatura no receptor

const crypto = require('crypto');

function verifyWebhook(payload, signature, secret) {
  const expected = crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('hex');

  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected)
  );
}

❌ Códigos de Erro

{
  "success": false,
  "error": { "code": "ERROR_CODE", "message": "DescriΓ§Γ£o" }
}
CΓ³digo HTTP DescriΓ§Γ£o
UNAUTHORIZED 401 Token ausente ou invΓ‘lido
FORBIDDEN 403 Sem permissΓ£o
NOT_FOUND 404 Recurso nΓ£o existe
VALIDATION_ERROR 400 Dados invΓ‘lidos (Zod)
FILE_REQUIRED 400 Arquivo nΓ£o enviado
INVALID_FILE_TYPE 400 Apenas PDF aceito
FILE_TOO_LARGE 400 Arquivo acima de 10MB
NO_HASH_REGISTERED 400 Documento sem hash para verificar
RATE_LIMIT_EXCEEDED 429 Muitas requisiΓ§Γ΅es
INTERNAL_ERROR 500 Erro interno

πŸ“ Estrutura do Projeto

docvault-api/
β”œβ”€β”€ app/
β”‚   β”œβ”€β”€ page.tsx                    # Dashboard UI
β”‚   β”œβ”€β”€ layout.tsx
β”‚   β”œβ”€β”€ globals.css
β”‚   β”œβ”€β”€ components/
β”‚   β”‚   β”œβ”€β”€ Toast.tsx
β”‚   β”‚   └── UploadModal.tsx
β”‚   └── api/
β”‚       β”œβ”€β”€ auth/
β”‚       β”‚   β”œβ”€β”€ login/route.ts
β”‚       β”‚   β”œβ”€β”€ logout/route.ts
β”‚       β”‚   β”œβ”€β”€ me/route.ts
β”‚       β”‚   β”œβ”€β”€ refresh/route.ts
β”‚       β”‚   └── signup/route.ts
β”‚       β”œβ”€β”€ documents/
β”‚       β”‚   β”œβ”€β”€ route.ts
β”‚       β”‚   └── [id]/
β”‚       β”‚       β”œβ”€β”€ route.ts
β”‚       β”‚       β”œβ”€β”€ verify/route.ts
β”‚       β”‚       └── versions/route.ts
β”‚       └── webhooks/route.ts
β”œβ”€β”€ lib/
β”‚   β”œβ”€β”€ api-response.ts             # Helpers de resposta padronizada
β”‚   β”œβ”€β”€ auth.ts                     # getCurrentUser, requireAuth
β”‚   β”œβ”€β”€ crypto.ts                   # SHA-256, HMAC, tokens seguros
β”‚   β”œβ”€β”€ ratelimit.ts                # Upstash rate limiting
β”‚   β”œβ”€β”€ storage.ts                  # Upload/download Supabase Storage
β”‚   β”œβ”€β”€ supabase.ts                 # Clientes server/service/browser
β”‚   └── webhook.ts                  # Disparo de eventos
β”œβ”€β”€ tests/
β”‚   β”œβ”€β”€ setup.ts
β”‚   β”œβ”€β”€ api/documents.test.ts
β”‚   └── lib/
β”‚       β”œβ”€β”€ api-response.test.ts
β”‚       └── crypto.test.ts
β”œβ”€β”€ types/
β”‚   β”œβ”€β”€ index.ts
β”‚   └── supabase.ts
β”œβ”€β”€ supabase/
β”‚   β”œβ”€β”€ schema.sql                  # Schema v2 completo
β”‚   └── seed.sql
β”œβ”€β”€ middleware.ts                   # Auth + Rate Limiting
β”œβ”€β”€ vitest.config.ts
β”œβ”€β”€ next.config.js
β”œβ”€β”€ tsconfig.json
└── package.json

🚒 Deploy na Vercel

  1. Conecte o repositΓ³rio em vercel.com
  2. Adicione as variΓ‘veis de ambiente no painel da Vercel
  3. Deploy automΓ‘tico a cada push na main

πŸ“ LicenΓ§a

MIT β€” livre para usar e adaptar.

About

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages