Essa aplicação contém o back-end de dois produtos financeiros simplificados:
- Acesso a Dívidas: usuários podem acessar uma lista de seus próprios débitos e empresas parceiras(admins) podem registrar novas dívidas.
- Cálculo de Score: usuários podem acessar seu score, que é calculado com base nas suas dívidas, seguindo a fórmula: Score = 10000 / ( x + 100 ), sendo x a média do valor das dívidas.
Os Endpoints são protegidos com base na autenticação em JWT, o que garante que apenas os usuários podem ver suas próprias dívidas, e apenas administradores podem cadastrar novas dívidas.
Antes de rodar o projeto, é necessário satisfazer as seguintes dependências:
- JDK 17
- Maven >= 3.9
- Docker >= 24
- Para acessar o banco do projeto foi usado o DBeaver, mas podem ser utilizadas outras plataformas.
Clone o projeto a partir do github e instale as dependências com maven.
Para rodar o PostgreSQL de forma isolada e sem necessidade de instalação na máquina, foi utilizado o Docker. Portanto, existe um arquivo docker-compose.yml, que pode ser iniciado com o comando na mesma pasta do projeto:
docker-compose up -d
Depois, conecte ao banco de dados com os dados do arquivo docker-compose referentes ao PostgreSQL:
Host: localhost
Port: 5432
Database: authdb
Username: authuser
Password: authpass
Crie as tabelas no banco de dados com os scripts na seção Banco de Dados.
Agora, a aplicação pode ser iniciada com o comando
mvn spring-boot:run
Foi escolhido o JWT para permitir a escalabilidade do sistema. Também faz com que apenas usuários com permissão possam acessar determinados endpoints. As duas roles disponíveis são:
USER(normal) -> Usuário pode acessas qualquer endpoint GET, para ver as informações referentes aos seus débitos e seu score
ADMIN(admin) -> Admin tem as mesmas permissões que o usuário(pode acessar suas próprias dívidas e seu próprio score), mas também pode cadastrar novas dívidas para qualquer usuário
Abaixo estão descritos os endpoints disponíveis nessa aplicação:
POST/auth/register: criação de um novo usuário (sem necessidade de autenticação)
POST/auth/login: obtenção do JWT usando cpf + senha do usuário (sem necessidade de autenticação)
GET/debts: lista as dívidas pertencentes ao usuário autenticado (autenticação normal)
POST/debts: registra as novas dívidas para um usuário com base em seu cpf (autenticação como admin)
GET/score: retorna o score do usuário com base em suas dívidas
O endpoint não possui necessidade de autenticação, para permitir que qualquer um possa se cadastrar. Aqui, o usuário precisa fornecer as seguintes informações: login(CPF), senha, tipo de usuário(pode ser normal ou admin), nome, data de nascimento e email. Todas essas informações precisam estar presentes para que a request tenha sucesso.
É necessário que o cpf não exista no banco de dados ainda, para evitar usuários duplicados. Caso o cpf já pertença a um usuário existente, outro usuário com o mesmo cpf não será criado.
Content‑Type: application/json
{
"login": "12345678901",
"password": "1234",
"role": "normal",
"name": "Joao Lucio",
"birthday": "2003-01-01",
"email": "lucio@email.com"
}
Para esse endpoint, assim como o anterior, não é necessária autenticação do usuário. Caso o login(CPF) exista no banco e a senha(hasheada) corresponda à senha do usuário, o login terá sucesso, retornando um token JWT, que precisará ser utilizado para acessar os endpoints abaixo.
Content‑Type: application/json
{
"login": "12345678901",
"password": "1234"
}
Esse endpoint não precisa de parâmetros. Ele utiliza o token do usuário para retornar as dívidas correspondentes ao seu CPF, caso existam.
[
{
"value": 150.75,
"dueDate": "2024-10-10"
},
{
"value": 320.50,
"dueDate": "2025-01-15"
}
]
Como o anterior, é necessário que o usuário esteja autenticado, mas apenas uma role de USER("normal") já é suficiente. Com base nas dívidas do usuário será calculado seu score seguindo a fórmula 10000 / ( x + 100 ), sendo x a média do valor das dívidas. Esse endpoint também não utiliza parâmetros.
{
"score": 29.79
}
Esse é o único endpoint que necessita da role ADMIN("admin"). Aqui, o usuário admin pode cadastrar dívidas para diferentes usuários, apenas caso eles existam. Para isso, é necessário fornecer o cpf do usuário, valor da dívida e data de vencimento.
{
"value": 1500.75,
"dueDate": "2025-12-01",
"cpf": "12345678900"
}
"CREATED"
Foi utilizado o PostgreSQL como banco de dados desse projeto. A seguir, os scripts utilizados para a criação da tabela Users e Debts:
CREATE TABLE users (
id SERIAL PRIMARY KEY,
cpf VARCHAR(11) UNIQUE NOT NULL,
name VARCHAR(100) NOT NULL,
birthday DATE NOT NULL,
email VARCHAR(100) UNIQUE NOT NULL,
password TEXT NOT NULL,
user_role VARCHAR(20) CHECK (user_role IN ('normal', 'admin')) NOT NULL
);
CREATE TABLE debts (
id SERIAL PRIMARY KEY,
value NUMERIC(10, 2) NOT NULL,
due_date DATE NOT NULL,
user_id INTEGER NOT NULL,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
);
Por se tratar de um sistema financeiro, foi escolhido utilizar BigDecimal para os valores numéricos correspondentes a moedas, e para o cálculo do score, assegurando maior exatidão dos dados apresentados ao cliente.
No banco de dados, foi utilizado um id gerado automaticamente para as dívidas e usuários. Não foi usado o CPF como chave primária do usuário, para facilitar mudanças no banco sem afetar os dados já existentes, caso ocorra uma mudança nos requisitos de login(para utilizar outros documentos, como CNPJ, por exemplo). Além disso, tentei expor esse dado da menor maneira possível, por se tratar de um dado sensível.
Optei pelo SpringBoot por familiaridade, e pelo JWT/Spring Security pensando na possibilidade de escalabilidade do projeto. As senhas são encriptadas com auxílio do BCrypt, e utilizei DTOs para evitar a exposição desnecessária das entidades ao longo do projeto, além de facilitar mudanças futuras nele.
A versão inicial desse projeto foi produzida em dois dias. Por isso, está incompleta e com diversas melhorias que serão implementadas nas próximas versões. As principais são:
- A implementação de um endpoint de logout: atualmente, a única maneira do usuário realizar logout é por meio da expiração do token.
- Tratamento de Erros: para retornar mensagens claras para erros mapeados, auxiliando o cliente a entender as falhas tomadas.
- Testes Unitários: para garantir que mudanças futuras não impactem o projeto já existente, além de encontrar possíveis falhas no sistema.
- Migration do Banco de Dados: implementarei um gerenciador para garantir que as migrations sejam aplicadas de maneira automática, evitando erros devido a processos manuais.
- Inclusão de um Swagger: para expor a documentação da API.