O Backend OdontoLegal é uma API RESTful desenvolvida para gerenciar processos odontolegais, oferecendo uma solução robusta e segura para o gerenciamento de laudos, documentos e processos relacionados à odontologia legal.
- Fornecer uma API segura e escalável para gerenciamento de processos odontolegais
- Facilitar o armazenamento e gerenciamento de documentos e laudos
- Implementar autenticação e autorização robustas
- Garantir a integridade e segurança dos dados
- Oferecer uma documentação clara e completa da API
- Boas práticas
- Banco/ORM
- Design de projeto e rotas
- Boas práticas (HTTP, segurança, código)
- Swagger
- Login/Autorização
- CRUD de Casos
- Gestão de Vítimas
- Evidências com Imagens e Geolocalização
- Laudos e Relatórios
- Dashboard
- Nova entidade vítima
- Laudos e Relatórios com IA
- Requisitos da primeira parte
- Repositório organizado
- Deploy em nuvem
- Sistema de login/autorização para aplicação web e mobile
- Diferentes perfis de usuário (mesmos requisitos web/mobile)
- Proteção de rotas baseada em perfis
- Gerenciamento de sessão e tokens JWT
- Validação de status do usuário (usuários inativos não podem fazer login)
- Cadastro completo de casos
- Consulta e listagem de casos
- Atualização de status (Em andamento, Finalizado, Arquivado)
- Associação de casos com vítimas
- Dashboard com visão geral dos casos
- Cadastro completo de vítimas com:
- NIC (Número de Identificação do Caso)
- Nome completo
- Gênero
- Idade
- Documento de identificação
- Endereço
- Cor/Etnia
- Odontograma com anotações
- Associação de múltiplas vítimas a um caso
- Consulta e atualização de dados das vítimas
- Cadastro de evidências com:
- Captura de imagens via aplicativo mobile
- Geolocalização automática
- Data e hora da coleta
- Tipo de evidência
- Status de análise
- Upload e armazenamento de imagens
- Associação de evidências a casos
- Rastreamento de evidências por usuário
- Geração de laudos de evidências
- Geração de relatórios de casos
- Integração com IA para análise
- Exportação de documentos
- Histórico de laudos e relatórios
- Visualização de estatísticas
- Banco de dados odonto-legal
- Filtros e buscas avançadas
- Relatórios gerenciais
- Criptografia de dados sensíveis
- Proteção contra ataques comuns (XSS, CSRF, etc.)
- Validação de dados
- Políticas de senha seguras
- Tempo de resposta otimizado
- Otimização de consultas ao banco
- Arquitetura modular
- Separação de responsabilidades
- Preparado para aumento de carga
- Estrutura de microserviços
- Interface responsiva (web)
- Aplicativo mobile (React Native)
- Design intuitivo (UI/UX)
- Feedback visual de ações
- Acessibilidade
- API documentada com Swagger
- README completo
- Documentação de código
- Guias de uso
- Documentação de deploy
- Deploy em ambiente cloud
- Monitoramento
- CI/CD
- Ambiente de desenvolvimento
- APIs RESTful
- Integração com serviços de IA
- Integração com serviços de armazenamento
- Código limpo e organizado
- Padrões de projeto
- Testes automatizados
- Versionamento (Git)
- Code review
- Node.js
- Express.js
- MongoDB (Mongoose)
- JWT para autenticação
- Cloudinary para armazenamento de imagens
- Swagger para documentação da API
- Outras dependências importantes:
- bcryptjs (criptografia)
- helmet (segurança)
- cors (controle de acesso)
- multer (upload de arquivos)
- morgan (logging)
backend-pi/
├── app.js # Arquivo principal da aplicação
├── router/ # Rotas da API
├── controllers/ # Controladores da aplicação
├── models/ # Modelos do MongoDB
├── middlewares/ # Middlewares personalizados
├── services/ # Serviços e lógica de negócio
├── utils/ # Funções utilitárias
├── docs/ # Documentação adicional
└── node_modules/ # Dependências
O sistema utiliza MongoDB como banco de dados, com os seguintes models:
{
username: String, // Nome de usuário (único)
email: String, // Email (único)
password: String, // Senha (criptografada, não retornada em queries)
cargo: String, // Enum: ['admin', 'perito', 'assistente']
status: String, // Enum: ['ativo', 'inativo']
fotoPerfil: String, // URL da foto (opcional)
casos: [ObjectId], // Referência aos casos
relatorios: [ObjectId], // Referência aos relatórios
evidencias: [ObjectId] // Referência às evidências
}- Implementa criptografia automática de senha
- Possui método para comparação de senhas
- Mantém timestamps de criação/atualização
{
titulo: String, // Título do caso
descricao: String, // Descrição detalhada
status: String, // Enum: ['Em andamento', 'Finalizado', 'Arquivado']
dataAbertura: Date, // Data de abertura (automática)
dataFechamento: Date, // Data de fechamento (opcional)
geolocalizacao: { // Localização do caso
latitude: String,
longitude: String
},
evidencias: [ObjectId], // Referência às evidências
relatorio: ObjectId, // Referência ao relatório (um por caso)
vitimas: [ObjectId] // Referência às vítimas (obrigatório)
}- Mantém timestamps de criação/atualização
{
nic: String, // Número de Identificação do Caso (8 dígitos, único, imutável)
nome: String, // Nome completo (opcional)
genero: String, // Gênero (opcional)
idade: Number, // Idade (opcional)
documento: String, // Documento de identificação (único, opcional)
endereco: String, // Endereço (opcional)
corEtnia: String, // Cor/Etnia (opcional)
odontograma: [ObjectId] // Referência aos odontogramas (opcional)
}- Validação de formato do NIC (8 dígitos)
- NIC é imutável após criação
{
identificacao: Number, // Identificação do dente (obrigatório)
observacao: String // Observações sobre o dente (obrigatório)
}{
tipo: String, // Tipo da evidência (obrigatório)
dataColeta: Date, // Data da coleta (obrigatório)
status: String, // Enum: ['Em análise', 'Concluído']
coletadaPor: ObjectId, // Referência ao usuário (obrigatório)
geolocalizacao: { // Localização da coleta (obrigatório)
latitude: String,
longitude: String
},
imagens: [ObjectId], // Referência às imagens (obrigatório)
textos: [ObjectId], // Referência aos textos (obrigatório)
laudo: ObjectId // Referência ao laudo (opcional)
}- Mantém timestamps de criação/atualização
{
imagemUrl: String // URL da imagem armazenada (obrigatório)
}{
conteudo: String // Conteúdo textual da evidência (obrigatório)
}- Mantém timestamps de criação/atualização
{
descricao: String, // Descrição detalhada (obrigatório)
conclusao: String, // Conclusão do laudo (obrigatório)
peritoResponsavel: ObjectId, // Referência ao usuário perito (obrigatório)
dataCriacao: Date // Data de criação do laudo (automática)
}{
titulo: String, // Título do relatório (obrigatório)
conteudo: String, // Conteúdo do relatório (gerado por LLM, obrigatório)
peritoResponsavel: ObjectId, // Referência ao usuário perito (obrigatório)
dataCriacao: Date // Data de criação do relatório (automática)
}- Mantém timestamps de criação/atualização
-
User (Usuário)
- Pode ter múltiplos Casos
- Pode ter múltiplos Relatórios
- Pode ter múltiplas Evidências
- Pode ser perito responsável por Laudos e Relatórios
- Possui cargo específico (admin, perito, assistente)
- Possui status (ativo, inativo)
-
Caso
- Deve ter pelo menos uma Vítima
- Pode ter múltiplas Evidências
- Possui um único Relatório
- Possui geolocalização
- Possui status específico (Em andamento, Finalizado, Arquivado)
-
Vitima
- Possui NIC único e imutável
- Pode ter múltiplos Odontogramas
- Possui campos opcionais para informações pessoais
-
Evidência
- Deve ter pelo menos uma Imagem
- Deve ter pelo menos um Texto
- Coletada por um Usuário específico
- Possui geolocalização obrigatória
- Pode ter um Laudo associado
- Possui status específico (Em análise, Concluído)
-
Laudo
- Pertence a uma Evidência
- Criado por um Usuário perito
- Possui data de criação automática
-
Relatorio
- Pertence a um Caso
- Criado por um Usuário perito
- Conteúdo gerado por LLM
- Possui data de criação automática
- Todos os models implementam timestamps (createdAt, updatedAt) quando relevante
- Utiliza referências (ObjectId) para relacionamentos
- Implementa validações de campos obrigatórios
- Utiliza enums para campos com valores predefinidos
- Mantém a integridade referencial através de refs
- Documentos únicos são marcados com
unique: true - Campos opcionais são marcados com
required: false - Implementa validações específicas (ex: formato do NIC)
- Utiliza campos imutáveis quando necessário
- Integração com LLM para geração de relatórios
O sistema segue uma hierarquia específica para inserção de dados, garantindo a integridade e consistência das informações. Abaixo está o fluxo detalhado:
- Pré-requisito: Nenhum
- Campos Obrigatórios: username, email, password, cargo
- Observações:
- O cargo determina as permissões do usuário
- A senha é automaticamente criptografada
- O status padrão é 'ativo'
- Pré-requisito: Usuário criado
- Campos Obrigatórios: titulo, descricao, vitimas
- Fluxo:
- Criar o caso com informações básicas
- Associar pelo menos uma vítima
- O status inicial é 'Em andamento'
- A data de abertura é automática
- Pré-requisito: Caso criado
- Campos Obrigatórios: nic (8 dígitos)
- Campos Opcionais: nome, genero, idade, documento, endereco, corEtnia
- Fluxo:
- Gerar NIC único (8 dígitos)
- Preencher informações básicas
- Associar ao caso
- O NIC não pode ser alterado após a criação
- Pré-requisito: Caso e Usuário criados
- Campos Obrigatórios: tipo, dataColeta, coletadaPor, geolocalizacao, imagens, textos
- Fluxo:
- Registrar tipo e data da evidência
- Incluir geolocalização
- Associar usuário que coletou
- Adicionar pelo menos uma imagem
- Adicionar pelo menos um texto
- Status inicial é 'Em análise'
- Pré-requisito: Evidência criada
- Campos Obrigatórios: imagemUrl
- Fluxo:
- Upload da imagem
- Geração da URL
- Associação à evidência
- Pré-requisito: Evidência criada
- Campos Obrigatórios: conteudo
- Fluxo:
- Inserir conteúdo textual
- Associação à evidência
- Pré-requisito: Vítima criada
- Campos Obrigatórios: identificacao, observacao
- Fluxo:
- Registrar identificação do dente
- Adicionar observações
- Associar à vítima
- Pré-requisito: Evidência criada e Usuário perito
- Campos Obrigatórios: descricao, conclusao, peritoResponsavel
- Fluxo:
- Criar laudo com descrição e conclusão
- Associar perito responsável
- Vincular à evidência
- Data de criação é automática
- Pré-requisito: Caso criado e Usuário perito
- Campos Obrigatórios: titulo, conteudo, peritoResponsavel
- Fluxo:
- Criar relatório com título
- Gerar conteúdo via LLM
- Associar perito responsável
- Vincular ao caso
- Data de criação é automática
- A ordem de inserção deve ser respeitada para manter a integridade dos dados
- Cada nível depende da existência do nível anterior
- Relacionamentos são mantidos através de referências (ObjectId)
- Campos obrigatórios devem ser preenchidos em cada nível
- Alguns campos são preenchidos automaticamente pelo sistema
- Validações específicas são aplicadas em cada nível
- Permissões de usuário são verificadas em cada operação
- Node.js (versão 14 ou superior)
- MongoDB
- NPM ou Yarn
- Conta no Cloudinary (para upload de imagens)
- Clone o repositório:
git clone [URL_DO_REPOSITÓRIO]
cd backend-pi- Instale as dependências:
npm install- Configure as variáveis de ambiente:
Crie um arquivo
.envna raiz do projeto com as seguintes variáveis:
# Configurações do Servidor
PORT=3000 # Porta onde o servidor irá rodar
DISABLE_AUTH=false # Desabilita autenticação (apenas para desenvolvimento)
# Configurações do MongoDB
DATABASE_URL=mongodb://... # URL de conexão com o MongoDB
# Configurações de Segurança
JWT_SECRET=seu_jwt_secret # Chave secreta para geração de tokens JWT
# Configurações do Cloudinary (Armazenamento de Imagens)
CLOUD_NAME=seu_cloud_name # Nome da sua conta no Cloudinary
API_KEY=sua_api_key # Chave de API do Cloudinary
API_SECRET=seu_api_secret # Chave secreta do Cloudinary
# Configurações da IA (Google Gemini)
GEMINI_API_KEY=sua_chave # Chave de API do Google Gemini para geração de relatóriosPORT: Define a porta onde o servidor irá rodar (padrão: 3000)DISABLE_AUTH: Quando true, desabilita a autenticação (use apenas em desenvolvimento)
DATABASE_URL: URL completa de conexão com o MongoDB- Formato:
mongodb://[username:password@]host[:port]/database - Exemplo:
mongodb://localhost:27017/odontolegal
- Formato:
JWT_SECRET: Chave secreta para assinatura dos tokens JWT- Deve ser uma string complexa e segura
- Mantenha em segredo em produção
CLOUD_NAME: Nome da sua conta no CloudinaryAPI_KEY: Chave de API do CloudinaryAPI_SECRET: Chave secreta do Cloudinary- Necessário para upload e gerenciamento de imagens
- Obtenha estas credenciais no dashboard do Cloudinary
GEMINI_API_KEY: Chave de API do Google Gemini- Utilizada para geração automática de relatórios
- Obtenha a chave no Google Cloud Console
- Nunca compartilhe ou comite o arquivo
.envno repositório - Mantenha diferentes arquivos
.envpara desenvolvimento e produção - Use valores diferentes para
JWT_SECRETem cada ambiente - Em produção, use sempre
DISABLE_AUTH=false - Mantenha as chaves de API em segredo
- Faça backup das credenciais em local seguro
- Inicie o servidor:
# Modo desenvolvimento
npm run dev
# Modo produção
npm startA documentação completa da API está disponível através do Swagger UI quando o servidor estiver rodando:
https://backend-pi-26cz.onrender.com/api-docs
O sistema implementa uma validação de segurança que impede usuários com status "inativo" de realizarem login na aplicação.
- Verificação no Login: Quando um usuário tenta fazer login, o sistema verifica automaticamente o status do usuário
- Bloqueio de Acesso: Se o status for "inativo", o login é bloqueado com erro 403 (Forbidden)
- Mensagem Clara: O usuário recebe uma mensagem explicativa: "Usuário inativo. Entre em contato com o administrador."
// 1. Usuário tenta fazer login
POST /auth/login
{
"email": "usuario@exemplo.com",
"password": "senha123"
}
// 2. Sistema verifica se usuário existe
// 3. Sistema verifica se senha está correta
// 4. Sistema verifica status do usuário
if (user.status === 'inativo') {
return res.status(403).json({
error: "Usuário inativo. Entre em contato com o administrador."
});
}
// 5. Se ativo, login é permitido e token é gerado- 200: Login realizado com sucesso (usuário ativo)
- 401: Senha incorreta
- 403: Usuário inativo (novo status)
- 404: Usuário não encontrado
- 500: Erro interno do servidor
Os administradores podem gerenciar o status dos usuários através dos endpoints:
- Desativar usuário:
PUT /auth/users/:id/desativar - Reativar usuário:
PUT /auth/users/:id/reativar
- Controle de Acesso: Impede acesso de usuários desautorizados
- Auditoria: Mantém registro de usuários ativos/inativos
- Flexibilidade: Permite reativação sem perder dados do usuário
- Transparência: Mensagem clara sobre o motivo da rejeição
- Faça um Fork do projeto
- Crie uma Branch para sua Feature (
git checkout -b feature/AmazingFeature) - Faça o Commit das suas mudanças (
git commit -m 'Add some AmazingFeature') - Faça o Push para a Branch (
git push origin feature/AmazingFeature) - Abra um Pull Request
Este projeto está sob a licença ISC.
Para suporte, envie um email para nossa equipe ou abra uma issue no repositório.
O endpoint GET /casos agora suporta busca avançada e paginação através de parâmetros de query:
titulo: Busca casos por título (busca parcial, case insensitive)descricao: Busca casos por descrição (busca parcial, case insensitive)status: Filtra casos por status exato
page: Número da página (padrão: 1, mínimo: 1)limit: Número de itens por página (padrão: 10, mínimo: 1, máximo: 100)
GET /casos?page=1&limit=10GET /casos?titulo=homicídio&page=1&limit=20GET /casos?descricao=vítima&status=Em andamento&page=2&limit=15GET /casos?titulo=homicídio&status=Finalizado&page=3&limit=25- Busca Parcial: Para título e descrição, a busca é parcial (não precisa ser exata)
- Case Insensitive: Não diferencia maiúsculas de minúsculas
- Combinação: Pode usar múltiplos parâmetros simultaneamente
- Status Exato: Para status, a busca é exata (deve corresponder aos valores: "Em andamento", "Finalizado", "Arquivado")
- Página Inicial: A paginação começa em 1 (não em 0)
- Limite Máximo: Máximo de 100 itens por página para evitar sobrecarga
- Validação: Valores inválidos são automaticamente corrigidos
- Performance: Otimizada para grandes volumes de dados
A resposta agora inclui os dados de paginação:
{
"casos": [
{
"_id": "caso_id",
"titulo": "Homicídio em São Paulo",
"descricao": "Vítima encontrada com sinais de violência",
"status": "Em andamento",
"dataAbertura": "2024-01-01T00:00:00.000Z",
"evidencias": [...],
"vitimas": [...],
"relatorio": {...}
}
],
"pagination": {
"currentPage": 1,
"totalPages": 5,
"totalItems": 47,
"itemsPerPage": 10,
"hasNextPage": true,
"hasPrevPage": false,
"nextPage": 2,
"prevPage": null
}
}currentPage: Página atual sendo exibidatotalPages: Total de páginas disponíveistotalItems: Total de itens que atendem aos filtrositemsPerPage: Número de itens por páginahasNextPage: Se existe próxima páginahasPrevPage: Se existe página anteriornextPage: Número da próxima página (null se não existir)prevPage: Número da página anterior (null se não existir)
O sistema oferece um endpoint consolidado para obter todas as estatísticas principais do dashboard em uma única requisição:
GET /dashboard/estatisticas-gerais- Conta todos os casos cadastrados no sistema
- Inclui casos em andamento, finalizados e arquivados
- Conta todas as evidências cadastradas no sistema
- Inclui evidências de todos os tipos (imagens, textos, etc.)
- Conta todas as vítimas cadastradas no sistema
- Inclui vítimas de todos os casos
- Distribuição de casos por status:
- Em andamento: Casos ativos sendo trabalhados
- Finalizado: Casos concluídos
- Arquivado: Casos arquivados
- Estatísticas mensais dos últimos 5 meses, incluindo o mês atual
- Cada entrada inclui:
- Mês: Nome do mês em português
- Ano: Ano do mês
- Quantidade: Número de casos abertos naquele mês
{
"totalCasos": 150,
"totalEvidencias": 450,
"totalVitimas": 200,
"casosPorStatus": {
"Em andamento": 85,
"Finalizado": 45,
"Arquivado": 20
},
"casosPorMes": [
{
"mes": "Janeiro",
"ano": 2024,
"quantidade": 25
},
{
"mes": "Fevereiro",
"ano": 2024,
"quantidade": 30
},
{
"mes": "Março",
"ano": 2024,
"quantidade": 28
},
{
"mes": "Abril",
"ano": 2024,
"quantidade": 35
},
{
"mes": "Maio",
"ano": 2024,
"quantidade": 32
}
]
}- Performance Otimizada: Todas as estatísticas são calculadas em uma única requisição
- Dados em Tempo Real: Estatísticas sempre refletem o estado atual do banco de dados
- Formato Consistente: Resposta padronizada e fácil de consumir
- Autenticação Obrigatória: Requer token JWT válido
- Permissões: Acessível para admin, perito e assistente
- Dashboard Principal: Carregamento inicial do dashboard com todas as métricas
- Relatórios Gerenciais: Geração de relatórios com visão geral do sistema
- Monitoramento: Acompanhamento de tendências e crescimento do sistema
- Análise de Performance: Identificação de períodos de maior atividade
Além do endpoint principal, o sistema também oferece endpoints específicos para cada tipo de estatística:
GET /dashboard/casos- Total de casosGET /dashboard/casos/status- Casos por statusGET /dashboard/evidencias/total- Total de evidênciasGET /dashboard/laudos/total- Total de laudosGET /dashboard/casos/ultimos-meses- Casos por mêsGET /dashboard/casos/ativos/quantidade- Casos ativos
- Redução de Requisições: Uma única chamada para todas as estatísticas
- Melhor Performance: Menos overhead de rede
- Dados Consistentes: Todas as estatísticas são calculadas no mesmo momento
- Facilidade de Implementação: Frontend pode carregar tudo de uma vez
- Menor Latência: Resposta mais rápida para o usuário