O Tilt é uma ferramente de desenvolvimento que serve para orquestração de aplicações Kubernetes localmente.
Para rodar a aplicação, você deve ter o Tilt instalado, e então basta rodar o comando tilt up
na pasta raíz do projeto, onde está o Tiltfile
O Tilt conta com uma interface web para melhor visualização da aplicação:
O primeiro passo é subir o Redis, RabbitMQ e o MongoDB rodando docker-compose up -d
na pasta raíz do projeto.
# Entre na pasta backend
cd backend
# Crie o arquivo contendo as variáveis de ambiente
cp .env.example .env
# Instale as dependências
npm install
# Rode o backend
npm start
# Entre na pasta frontend
cd frontend
# Crie o arquivo contendo as variáveis de ambiente
cp .env.example .env
# Instale as dependências
npm install
# Rode o frontend
npm start
Para o backend, utilizei o NodeJs.
A collection principal é a Users
, definida como no exemplo abaixo:
{
"_id": "6564d13f6a76b0f57933e45a",
"firstName": "Matheus",
"lastName": "Couto",
"addresses": [
{
"street": "Cristo Rei",
"city": "São Paulo",
"state": "São Paulo",
"zipCode": "23242-423",
"_id": "6564d73e6a76b0f57933e470"
}
],
"dateOfBirth": "2023-11-02T17:26:11.561Z",
"email": "[email protected]",
"documentNumber": "063.548.329-30",
"phoneNumbers": [
{
"number": "(44) 99130-6824",
"type": "work",
"_id": "6564d79e850b5928299a28f1"
},
{
"number": "(44) 99101-6482",
"type": "personal",
"_id": "6564d79e850b5928299a28f2"
}
],
"__v": 0
}
Além dela, também existe a collection de Logs
:
{
"_id": "6564d79e850b5928299a28f9",
"requestTime": "2023-11-27T17:53:34.111Z",
"responseTime": "2023-11-27T17:53:34.145Z",
"method": "PUT",
"url": "/6564d13f6a76b0f57933e45a/phoneNumbers",
"statusCode": 200,
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36 OPR/104.0.0.0",
"body": {
"phoneNumbers": [
{
"number": "(44) 99148-6824",
"type": "work",
"_id": "6564d79e850b5928299a28f1"
},
{
"number": "(44) 99101-6482",
"type": "personal",
"_id": "6564d79e850b5928299a28f2"
}
]
},
"params": {
"id": "6564d13f6a76b0f57933e45a"
},
"query": {}
"__v": 0
}
A autenticação é feita através de uma palavra chave, presente na variável de ambiente API_KEY
. Para validar uma palavra chave, uma requisição é feita na rota http://localhost:3001/auth/validate
, passando no body a chave apiKey
, e então a api retorna um token JWT (que contém a palavra chave testada pelo usuário). Este token é salvo no Redis e a cada requisição nas rotas protegidas pelo middleware de autenticação, é feita uma consulta no redis para verificar se o token está presente, e se a palavra chave é válida. Toda requisição protegida pelo middleware deve conter a chave token
no header. Exemplo de body:
{
"apiKey": "KEY_WORD"
}
Para validar os inputs recebidos pela API, utilizei o express-validator
e criei funções de validação utilizando regex para verificar campos como email, número de telefone, documento, CEP.
Dois middlewares foram implementados, explico com mais detalhes sobre eles logo abaixo na sessão de extras:
- Middleware de autenticação
- Middleware de log
A aplicação conta tanto com testes unitários quanto testes e2e, testando as principais funcionalidades do sistema. No total, existem 21 casos de teste para funções de validação (no caso dos testes unitários) e requests para as principais rotas (no caso e2e)
Para rodar, basta utilizar o comando npm run test
(na pasta backend)
A documentação completa da API pode ser acessada em http://localhost:3001/api-docs
A utilização do RabbitMQ se da para a escrita de um novo registro na collection de Logs. Para cada requisição que passa pelo middleware de logs, é publicada uma mensagem para ser consumida de forma assíncrona pelo consumer, e então gerar o novo registro na collection. A ideia é que a escrita do novo log não gere gargalo nas requisições padrões. O consumidor pode ser ligado ou desligado através da variável de ambiente LOGGER
, que por padrão vem com o valor ON
.
O Redis foi utilziado para implementar um sistema de cache, com o objetivo de validar a autenticação do usuário. A validação é feita buscando o token na memória do redis, e extraindo dele a palavra chave. Cada vez que um usuário tenta validar uma apiKey, é salvo um novo registro no Redis.
4 serviços estão presentes no docker-compose.yml
:
- Redis (porta 6379)
- RabbitMQ (porta 5672)
- Painel RabbitMQ (porta 15672)
- MongoDB (porta 27017)
Para o frontend, optei por usar o ant design como biblioteca para estilização. O layout se baseia em 4 principais sessões:
- Um input para validar a palavra chave da API
- A tabela de usuários, com listagem, criação, atualização e exclusão
- Modal para criação de um novo usuário
- A tabela de logs para listagem dos registros
Além disso, o desgin foi feito visando responsividade para se adequar a qualquer tamanho de tela. Também foram adicionados validadores de formulários, máscaras de input, filtros e ordenação nas tabelas, atualização e deleção de usuários, números de telefone e endereços direto na própria tabela, facilitando a experiência do usuário.
Prints para melhor visualização:
- Criar setup inicial
- Criar conexão com banco de dados
- Criar modelos do banco de dados
- Criar rotas
- Create
- Update
- Read One
- Read Many
- Delete
- Adicionar logs para escrita e leitura (loggar no console e também salvar em uma tabela no banco contendo ação, origem, timestamps, etc)
- Adicionar validação de input nas rotas
- Adicionar autenticação com jwt nas rotas (gerar API-KEY para validar requisições)
- Adicionar error e success handlers personalizados
- Adicionar documentação de rotas com swagger
- Implementar fila com RabbitMQ
- Implementar cache com Redis
- Adicionar testes unitarios
- Adicionar testes end to end
- Criar configuração de docker-compose para subir redis, rabbitmq e mongodb
- Criar setup inicial
- Criar componente de botão de submit
- Criar componente de input de texto
- Criar componente de linha da tabela com botão para deletar e atualizar
- Unir componentes para criar tabela de listagem
- Unir componentes para criar formulario de criação
- Criar conexão com o backend
- Adicionar requisições para rotas
- Adicionar validador de input nos formulários
- Adicionar error handler
- Adicionar filtros e ordenação na tabela
- Adicionar loading com skeleton
- Adicionar requisição para API de CEPs
- Adicionar dark/light mode
- Adicionar tradução pt-BR / en-US