- Sobre o Projeto
- Tecnologias
- Funcionalidades
- Como Executar
- Endpoints da API
- Testes
- Documentação Adicional
- Estrutura do Projeto
O FinanceFit é uma API REST completa para gerenciamento de finanças pessoais que oferece controle total sobre suas receitas e despesas com segurança e praticidade.
- 🔐 Autenticação JWT - Sistema seguro de autenticação stateless
- 👤 Gestão de Usuários - Cadastro, login e gerenciamento de perfil
- 💸 Controle de Despesas - Registre e categorize seus gastos
- 💰 Controle de Receitas - Acompanhe suas fontes de renda
- 📊 Categorias - Organize suas transações
- 🎯 Metas Mensais - Defina e acompanhe limites de gastos
- 📈 Relatórios - Visualize suas finanças por período
- 🔒 Segurança - Spring Security com criptografia BCrypt
- ✅ Validações - Bean Validation para garantir integridade dos dados
- 🐳 Docker Ready - Deploy simplificado com containers
| Tecnologia | Versão | Descrição |
|---|---|---|
| Java | 17 | Linguagem de programação |
| Spring Boot | 3.5.7 | Framework principal |
| Spring Security | - | Autenticação e autorização |
| Spring Data JPA | - | Persistência de dados |
| Hibernate | - | ORM (Object-Relational Mapping) |
| MySQL | 8.0 | Banco de dados relacional |
| H2 Database | - | Banco em memória para testes |
| JWT (jjwt) | 0.12.5 | Tokens de autenticação |
| Bean Validation | - | Validação de dados |
| Maven | 3.9+ | Gerenciador de dependências |
| Docker | - | Containerização |
| Docker Compose | - | Orquestração de containers |
A forma mais rápida e fácil de executar o projeto:
docker --version
docker-compose --version# Dar permissão ao script
chmod +x docker.sh
# Iniciar aplicação e banco de dados
./docker.sh start- API: http://localhost:8080
- MySQL: localhost:3307 (usuário:
financefit, senha:financefit123)
./docker.sh stop# Parar o serviço Docker
sudo systemctl stop docker
# Desabilitar Docker na inicialização
sudo systemctl disable docker
# Ver logs da API
docker logs -f financefit-api
# Ver logs do MySQL
docker logs -f financefit-mysql
# Acessar o banco de dados
docker exec -it financefit-mysql mysql -u financefit -pfinancefit123 financefit📖 Para mais detalhes sobre Docker, consulte DOCKER-SETUP.md
- ☕ Java 17+
- 📦 Maven 3.6+
- 🗄️ MySQL 8.0+
git clone <url-do-repositorio>
cd springCREATE DATABASE financefit;Edite src/main/resources/application.properties:
# Database Configuration
spring.datasource.url=jdbc:mysql://localhost:3306/financefit
spring.datasource.username=root
spring.datasource.password=SUA_SENHA_AQUI
# JPA/Hibernate
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
# JWT Configuration
jwt.secret=SUA_CHAVE_SECRETA_AQUI
jwt.expiration=86400000
⚠️ IMPORTANTE: AltereSUA_SENHA_AQUIeSUA_CHAVE_SECRETA_AQUIpara valores reais!
# Compilar
./mvnw clean install
# Executar
./mvnw spring-boot:runA API estará disponível em http://localhost:8080
POST /api/auth/register
Content-Type: application/jsonBody:
{
"nome": "João Silva",
"email": "joao@email.com",
"senha": "senha123",
"metaMensal": 2000.00
}Response (200):
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"email": "joao@email.com",
"nome": "João Silva"
}POST /api/auth/login
Content-Type: application/jsonBody:
{
"email": "joao@email.com",
"senha": "senha123"
}Response (200):
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"email": "joao@email.com",
"nome": "João Silva"
}🔒 Todos os endpoints abaixo requerem:
Authorization: Bearer {seu-token-jwt}
GET /usuariosGET /usuarios/{id}POST /usuarios
Content-Type: application/json
{
"nome": "Maria Santos",
"email": "maria@email.com",
"senha": "senha456",
"metaMensal": 1500.00
}Response (201):
{
"id": 2,
"nome": "Maria Santos",
"email": "maria@email.com",
"metaMensal": 1500.00
}GET /usuarios/email/{email}
Authorization: Bearer {token}Exemplo: GET /usuarios/email/joao@email.com
PUT /usuarios/{id}
Authorization: Bearer {token}
Content-Type: application/jsonBody:
{
"nome": "João Silva Atualizado",
"email": "joao.novo@email.com",
"senha": "novaSenha123"
}DELETE /usuarios/{id}
Authorization: Bearer {token}Response: 204 No Content
PATCH /usuarios/{id}/senha
Authorization: Bearer {token}
Content-Type: application/jsonBody:
{
"senha": "novaSenha789"
}PATCH /usuarios/{id}/meta
Authorization: Bearer {token}
Content-Type: application/jsonBody:
{
"metaMensal": 3000.00
}GET /usuarios/{id}/resumo
Authorization: Bearer {token}Response:
{
"totalDespesas": 1500.50,
"totalReceitas": 3000.00,
"metaMensal": 2000.00,
"saldo": 1499.50,
"percentualGasto": 75.03
}GET /usuarios/{id}/resumo/{mes}/{ano}
Authorization: Bearer {token}Exemplo: GET /usuarios/1/resumo/11/2025
Response:
{
"mes": 11,
"ano": 2025,
"totalDespesas": 850.00,
"totalReceitas": 2500.00,
"metaMensal": 2000.00,
"saldo": 1650.00,
"percentualGasto": 42.50
}POST /categorias
Authorization: Bearer {token}
Content-Type: application/jsonBody:
{
"nome": "Alimentação"
}Response (201 Created):
{
"categoriaId": 1,
"nome": "Alimentação"
}GET /categorias
Authorization: Bearer {token}Response:
[
{
"categoriaId": 1,
"nome": "Alimentação"
},
{
"categoriaId": 2,
"nome": "Transporte"
},
{
"categoriaId": 3,
"nome": "Lazer"
}
]PUT /categorias/{id}
Authorization: Bearer {token}
Content-Type: application/jsonBody:
{
"nome": "Alimentação e Mercado"
}DELETE /categorias/{id}
Authorization: Bearer {token}Response: 204 No Content
POST /despesas
Authorization: Bearer {token}
Content-Type: application/jsonBody:
{
"valor": 150.50,
"data": "2025-11-16",
"descricao": "Compras no supermercado",
"idUsuario": 1,
"idCategoria": 1
}Response (201 Created):
{
"id": 1,
"valor": 150.50,
"data": "2025-11-16",
"descricao": "Compras no supermercado",
"idUsuario": 1,
"idCategoria": 1,
"tipo": "DESPESA"
}GET /despesas/usuario/{idUsuario}
Authorization: Bearer {token}Exemplo: GET /despesas/usuario/1
PUT /despesas/{id}
Authorization: Bearer {token}
Content-Type: application/jsonBody:
{
"valor": 200.00,
"data": "2025-11-16",
"descricao": "Compras no supermercado (atualizado)",
"idUsuario": 1,
"idCategoria": 1
}DELETE /despesas/{id}
Authorization: Bearer {token}Response: 204 No Content
POST /receitas
Authorization: Bearer {token}
Content-Type: application/jsonBody:
{
"valor": 3000.00,
"data": "2025-11-05",
"descricao": "Salário",
"idUsuario": 1,
"idCategoria": 4
}Response (201 Created):
{
"id": 1,
"valor": 3000.00,
"data": "2025-11-05",
"descricao": "Salário",
"idUsuario": 1,
"idCategoria": 4,
"tipo": "RECEITA"
}GET /receitas/usuario/{idUsuario}
Authorization: Bearer {token}Exemplo: GET /receitas/usuario/1
PUT /receitas/{id}
Authorization: Bearer {token}
Content-Type: application/jsonBody:
{
"valor": 3100.00,
"data": "2025-11-05",
"descricao": "Salário com bônus",
"idUsuario": 1,
"idCategoria": 4
}DELETE /receitas/{id}
Authorization: Bearer {token}Response: 204 No Content
O projeto inclui testes automatizados para garantir a qualidade do código.
./mvnw test./mvnw clean testO projeto contém testes unitários e de integração para:
- ✅ Controllers: Testes de API (UsuarioController)
- ✅ Services: Lógica de negócio (UsuarioService, CategoriaService, DespesaService, ReceitaService)
- ✅ Integração: Testes de contexto da aplicação
Os testes utilizam:
- H2 Database - Banco de dados em memória
- Spring Boot Test - Framework de testes
- JUnit 5 - Framework de testes unitários
- Mockito - Mock de dependências
Configurações em src/test/resources/application-test.properties
- Registre-se ou faça login para obter um token JWT
- Inclua o token em todas as requisições autenticadas:
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... - Token válido por 24 horas (86400000 ms)
Apenas 2 endpoints são públicos (não requerem autenticação):
POST /api/auth/register- Registro de novos usuáriosPOST /api/auth/login- Login
Todos os outros endpoints requerem autenticação JWT.
- Senhas são criptografadas com BCrypt
- Tokens JWT assinados com chave secreta configurável
- Configuração via
application.properties
spring/
├── src/
│ ├── main/
│ │ ├── java/com/financefit/financeFit/
│ │ │ ├── controllers/ # Endpoints REST
│ │ │ │ ├── AuthController.java
│ │ │ │ ├── CategoriaController.java
│ │ │ │ ├── DespesaController.java
│ │ │ │ ├── ReceitaController.java
│ │ │ │ └── UsuarioController.java
│ │ │ ├── dtos/ # Data Transfer Objects
│ │ │ ├── entities/ # Entidades JPA
│ │ │ ├── exception/ # Tratamento de exceções
│ │ │ ├── repositories/ # Acesso a dados
│ │ │ ├── security/ # Configurações de segurança
│ │ │ ├── services/ # Lógica de negócio
│ │ │ └── FinanceFitApplication.java
│ │ └── resources/
│ │ ├── application.properties # Configuração padrão
│ │ └── application-docker.properties # Configuração Docker
│ └── test/ # Testes automatizados
│ ├── java/com/financefit/financeFit/
│ │ ├── controllers/
│ │ └── services/
│ └── resources/
│ └── application-test.properties
├── docker/
│ └── init.sql # Script de inicialização do BD
├── target/ # Arquivos compilados
├── docker-compose.yml # Configuração Docker Compose
├── docker-compose.override.yml # Sobrescritas do Docker
├── docker.sh # Script auxiliar Docker
├── Dockerfile # Imagem Docker da aplicação
├── pom.xml # Dependências Maven
├── DOCKER-SETUP.md # Documentação Docker
└── README.md # Este arquivo
- 📖 DOCKER-SETUP.md - Guia completo sobre Docker
- 📝 DTO_VALIDATION_FIXES.md - Validações implementadas
- 🔄 UPDATES.md - Histórico de atualizações
- 🐳 README-Docker.md - Informações adicionais sobre Docker
curl -X POST http://localhost:8080/api/auth/register \
-H "Content-Type: application/json" \
-d '{
"nome": "João Silva",
"email": "joao@email.com",
"senha": "senha123",
"metaMensal": 2000.00
}'curl -X POST http://localhost:8080/categorias \
-H "Content-Type: application/json" \
-H "Authorization: Bearer SEU_TOKEN_AQUI" \
-d '{
"nome": "Alimentação"
}'curl -X POST http://localhost:8080/despesas \
-H "Content-Type: application/json" \
-H "Authorization: Bearer SEU_TOKEN_AQUI" \
-d '{
"valor": 150.50,
"data": "2025-11-27",
"descricao": "Compras no supermercado",
"idUsuario": 1,
"idCategoria": 1
}'curl -X POST http://localhost:8080/receitas \
-H "Content-Type: application/json" \
-H "Authorization: Bearer SEU_TOKEN_AQUI" \
-d '{
"valor": 3000.00,
"data": "2025-11-05",
"descricao": "Salário",
"idUsuario": 1,
"idCategoria": 4
}'curl -X GET http://localhost:8080/usuarios/1/resumo/11/2025 \
-H "Authorization: Bearer SEU_TOKEN_AQUI"Um script bash está disponível para testar os endpoints:
chmod +x test-endpoints.sh
./test-endpoints.shImporte a coleção FinanceFit-API.postman_collection.json no Postman para testar todos os endpoints facilmente.
Para produção, configure as seguintes variáveis de ambiente:
| Variável | Descrição | Exemplo |
|---|---|---|
SPRING_DATASOURCE_URL |
URL do banco MySQL | jdbc:mysql://localhost:3306/financefit |
SPRING_DATASOURCE_USERNAME |
Usuário do banco | financefit |
SPRING_DATASOURCE_PASSWORD |
Senha do banco | senha_segura_aqui |
JWT_SECRET |
Chave secreta JWT | chave_muito_segura_e_longa_aqui |
JWT_EXPIRATION |
Tempo de expiração (ms) | 86400000 (24h) |
- Verifique as credenciais do MySQL no
application.properties - Certifique-se de que o usuário tem permissões no banco
# Encontrar processo na porta 8080
sudo lsof -i :8080
# Matar o processo
sudo kill -9 <PID># Verificar status do Docker
sudo systemctl status docker
# Iniciar Docker
sudo systemctl start docker
# Verificar containers
docker ps -a# Verificar logs do MySQL
docker logs financefit-mysql
# Recriar volumes
docker-compose down -v
docker-compose up --build- Faça um fork do projeto
- Crie uma branch para sua feature (
git checkout -b feature/MinhaFeature) - Commit suas mudanças (
git commit -m 'Adiciona MinhaFeature') - Push para a branch (
git push origin feature/MinhaFeature) - Abra um Pull Request
Este projeto está sob a licença MIT. Veja o arquivo LICENSE para mais detalhes.
Desenvolvido com ☕ e 💚 usando Spring Boot
- 📧 Email: seu-email@exemplo.com
- 🐛 Issues: Use a aba Issues do GitHub para reportar bugs
- 💬 Discussões: Use a aba Discussions para perguntas
> - Não é possível recuperar os dados após a exclusão
curl -X POST http://localhost:8080/api/auth/register \
-H "Content-Type: application/json" \
-d '{
"nome": "João Silva",
"email": "joao@email.com",
"senha": "senha123",
"metaMensal": 2000.00
}'curl -X POST http://localhost:8080/api/auth/login \
-H "Content-Type: application/json" \
-d '{
"email": "joao@email.com",
"senha": "senha123"
}'Salve o token retornado!
curl -X POST http://localhost:8080/categorias \
-H "Content-Type: application/json" \
-H "Authorization: Bearer SEU_TOKEN_AQUI" \
-d '{
"nome": "Alimentação"
}'curl -X POST "http://localhost:8080/despesas" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer SEU_TOKEN_AQUI" \
-d '{
"valor": 150.50,
"data": "2025-11-16",
"descricao": "Compras no supermercado",
"idUsuario": 1,
"idCategoria": 1
}'curl -X POST "http://localhost:8080/receitas" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer SEU_TOKEN_AQUI" \
-d '{
"valor": 3000.00,
"data": "2025-11-05",
"descricao": "Salário",
"idUsuario": 1
}'curl -X GET http://localhost:8080/usuarios/1/resumo/11/2025 \
-H "Authorization: Bearer SEU_TOKEN_AQUI"curl -X GET http://localhost:8080/usuarios/me \
-H "Authorization: Bearer SEU_TOKEN_AQUI"curl -X PATCH http://localhost:8080/usuarios/me \
-H "Content-Type: application/json" \
-H "Authorization: Bearer SEU_TOKEN_AQUI" \
-d '{
"nome": "João Silva Junior"
}'curl -X PATCH http://localhost:8080/usuarios/me \
-H "Content-Type: application/json" \
-H "Authorization: Bearer SEU_TOKEN_AQUI" \
-d '{
"email": "joao.novo@email.com",
"senha": "novaSenhaSegura123"
}'curl -X DELETE http://localhost:8080/usuarios/me \
-H "Authorization: Bearer SEU_TOKEN_AQUI"src/
├── main/
│ ├── java/
│ │ └── com/financefit/financeFit/
│ │ ├── FinanceFitApplication.java # Classe principal
│ │ ├── controllers/ # Controladores REST
│ │ │ ├── AuthController.java # Autenticação (registro/login)
│ │ │ ├── CategoriaController.java # Gerenciamento de categorias
│ │ │ ├── DespesaController.java # Gerenciamento de despesas
│ │ │ ├── ReceitaController.java # Gerenciamento de receitas
│ │ │ └── UsuarioController.java # Gerenciamento de usuários
│ │ ├── dtos/ # Data Transfer Objects
│ │ │ ├── AuthResponseDTO.java # Resposta de autenticação
│ │ │ ├── CategoriaDTO.java
│ │ │ ├── CreateCategoriaDTO.java
│ │ │ ├── CreateDespesaDTO.java
│ │ │ ├── CreateReceitaDTO.java
│ │ │ ├── DespesaDTO.java
│ │ │ ├── LoginDTO.java # Dados de login
│ │ │ ├── ReceitaDTO.java
│ │ │ ├── RegisterDTO.java # Dados de registro
│ │ │ └── UsuarioDTO.java # Dados de usuário
│ │ ├── entities/ # Entidades JPA
│ │ │ ├── Categoria.java # Entidade Categoria
│ │ │ ├── Despesa.java # Entidade Despesa
│ │ │ ├── Receita.java # Entidade Receita
│ │ │ ├── TipoTransacao.java # Enum para tipo de transação
│ │ │ └── Usuario.java # Entidade Usuario
│ │ ├── exception/ # Tratamento de exceções
│ │ │ └── GlobalExceptionHandler.java # Handler global
│ │ ├── repositories/ # Camada de persistência
│ │ │ ├── CategoriaRepository.java
│ │ │ ├── DespesaRepository.java
│ │ │ ├── ReceitaRepository.java
│ │ │ └── UsuarioRepository.java
│ │ ├── security/ # Configuração de segurança
│ │ │ ├── CustomUserDetailsService.java # Service de autenticação
│ │ │ ├── JwtAuthenticationFilter.java # Filtro JWT
│ │ │ ├── JwtUtil.java # Utilitário JWT
│ │ │ └── SecurityConfig.java # Configuração Spring Security
│ │ └── services/ # Camada de negócio
│ │ ├── AuthService.java
│ │ ├── CategoriaService.java
│ │ ├── DespesaService.java
│ │ ├── ReceitaService.java
│ │ └── UsuarioService.java
│ └── resources/
│ └── application.properties # Configurações da aplicação
└── test/
└── java/
└── com/financefit/financeFit/
└── FinanceFitApplicationTests.java # Testes
A API implementa as seguintes medidas de segurança:
- ✅ Autenticação JWT stateless - Tokens seguros para autenticação
- ✅ Senhas criptografadas - BCrypt para hash de senhas
- ✅ Validação de dados - Bean Validation em todas as entradas
- ✅ Tratamento global de exceções - Respostas padronizadas de erro
- ✅ CORS configurado - Controle de acesso entre origens
- ✅ Endpoints protegidos - Rotas sensíveis requerem autenticação
O token JWT tem validade de 24 horas (86400000 ms) e contém:
- Email do usuário
- Data de emissão
- Data de expiração
| Campo | Tipo | Descrição |
|---|---|---|
| userId | Integer (PK) | ID único do usuário |
| nome | String | Nome completo |
| String (Unique) | Email para login | |
| senha | String | Senha criptografada |
| dataCriacao | LocalDate | Data de cadastro |
| metaMensal | Double | Meta de gastos mensais |
| Campo | Tipo | Descrição |
|---|---|---|
| categoriaId | Long (PK) | ID único da categoria |
| nome | String | Nome da categoria |
| Campo | Tipo | Descrição |
|---|---|---|
| id | Integer (PK) | ID único da despesa |
| valor | BigDecimal | Valor da despesa |
| data | LocalDate | Data da despesa |
| descricao | String | Descrição opcional |
| tipo | String | "DESPESA" |
| usuario_id | Integer (FK) | Referência ao usuário |
| categoria_id | Long (FK) | Referência à categoria |
| Campo | Tipo | Descrição |
|---|---|---|
| id | Integer (PK) | ID único da receita |
| valor | BigDecimal | Valor da receita |
| data | LocalDate | Data da receita |
| descricao | String | Descrição opcional |
| tipo | String | "RECEITA" |
| usuario_id | Integer (FK) | Referência ao usuário |
| categoria_id | Long (FK) | Referência à categoria (opcional) |
- Importe a collection (se disponível)
- Configure a variável de ambiente
baseUrlcomohttp://localhost:8080 - Após o login, salve o token na variável
token - Use
{{token}}no header Authorization
Similar ao Postman, configure o environment e utilize o token nos requests.
A API retorna erros padronizados no formato:
{
"timestamp": "2025-11-16T10:30:00",
"status": 400,
"error": "Bad Request",
"message": "Email é obrigatório",
"path": "/api/auth/register"
}| Código | Descrição |
|---|---|
| 200 | OK - Requisição bem-sucedida |
| 201 | Created - Recurso criado com sucesso |
| 204 | No Content - Requisição bem-sucedida sem conteúdo |
| 400 | Bad Request - Dados inválidos |
| 401 | Unauthorized - Não autenticado |
| 403 | Forbidden - Sem permissão |
| 404 | Not Found - Recurso não encontrado |
| 500 | Internal Server Error - Erro no servidor |
- Email: Deve ser válido e único
- Senha: Mínimo de 6 caracteres no registro
- Valores: Não podem ser negativos
- Datas: Formato ISO (YYYY-MM-DD)
- IDs: Devem ser positivos e existentes
- Sempre use HTTPS em produção
- Armazene o token de forma segura (localStorage, sessionStorage)
- Implemente refresh tokens para melhor experiência
- Configure CORS adequadamente para seu frontend
- Use variáveis de ambiente para dados sensíveis
- Faça backup regular do banco de dados
- Receitas além de despesas
- Paginação nos endpoints de listagem
- Filtros avançados de despesas (por período, categoria, valor)
- Dashboard com gráficos de gastos
- Exportação de relatórios (PDF, Excel)
- Notificações quando ultrapassar a meta
- Categorias customizadas por usuário
- Múltiplas moedas
- Refresh token automático
Contribuições são bem-vindas! Para contribuir:
- Faça um Fork do projeto
- Crie uma branch para sua feature (
git checkout -b feature/NovaFuncionalidade) - Commit suas mudanças (
git commit -m 'Adiciona nova funcionalidade') - Push para a branch (
git push origin feature/NovaFuncionalidade) - Abra um Pull Request
Este projeto é open source e está disponível sob a licença MIT.
Dúvidas ou sugestões? Entre em contato!
Desenvolvido com ☕ e ❤️
⭐ Se este projeto te ajudou, considere dar uma estrela!