Esse projeto é uma API REST, inspirada no GymPass, nessa API temos serviços como:
- Cadastrar;
- Autenticar;
- Cadastrar uma academia;
- Procurar academias por nome;
- Procurar academias próximas em um raio de 10km;
- Fazer check-in em uma academia;
- Validar o check-in de um cliente;
- Verificar seu histórico de check-ins;
- Verificar suas métricas;
- Recuperar suas informações de perfil;
Repository
O Repository Pattern é um padrão de projeto de software que promove a separação de preocupações entre a lógica de negócios e o acesso a dados. Ele introduz uma camada de abstração, geralmente na forma de interfaces ou classes abstratas, para operações de persistência, como criação, leitura, atualização e exclusão (CRUD). Isso isola o código de negócios de implementações específicas de armazenamento de dados, facilitando a reutilização, manutenção e testabilidade do código. O padrão oferece flexibilidade ao permitir a troca da fonte de dados sem afetar a lógica de negócios. Em resumo, o Repository Pattern promove uma arquitetura mais organizada e modularizada em aplicações.
Factory
O Factory Pattern é um padrão de projeto que fornece uma interface para criar objetos em uma superclasse, mas permite que as subclasses alterem o tipo de objetos que serão criados. Ele abstrai o processo de instanciação, proporcionando flexibilidade na criação de objetos e promovendo o princípio da programação para interfaces. O Factory Pattern é útil quando a criação de objetos envolve lógica complexa ou quando é necessário desacoplar o código cliente da implementação específica das classes concretas. Em resumo, esse padrão oferece uma maneira de criar objetos de forma flexível e extensível.
Dependency Injection
O Dependency Injection Pattern é uma abordagem de design em que as dependências de uma classe são injetadas externamente, em vez de serem criadas internamente. Isso promove a flexibilidade e a reusabilidade do código, facilitando a troca de implementações de dependências sem modificar o código cliente. O padrão ajuda a melhorar a testabilidade, facilitando a introdução de substitutos (mocks) durante os testes unitários. Em essência, o Dependency Injection reduz o acoplamento entre as classes, promovendo um código mais modular e fácil de manter.
Middleware
O Middleware Pattern é um design pattern utilizado para processar solicitações ou mensagens em um sistema de software em vários estágios durante sua execução. Em uma aplicação web, os middlewares são componentes modulares que desempenham funções específicas, como autenticação, autorização, manipulação de solicitações e respostas, entre outras. Cada middleware na cadeia é capaz de modificar ou complementar o comportamento da solicitação. Esse padrão proporciona flexibilidade ao permitir a fácil inclusão, remoção ou modificação de funcionalidades, sem afetar diretamente o núcleo da aplicação. Os middlewares são frequentemente empregados em frameworks e bibliotecas web, oferecendo uma abordagem extensível para lidar com diferentes aspectos do processamento de requisições em uma aplicação.
Error Handling
O Error Handling Pattern é um design pattern que estabelece práticas para gerenciar erros e exceções de forma consistente em um sistema de software. Ele visa melhorar a robustez, identificação rápida de problemas e manutenção eficiente. No contexto do código fornecido, o uso do setErrorHandler no arquivo server.ts exemplifica a implementação desse padrão, fornecendo um manipulador global para tratar e responder a diferentes tipos de erros de maneira organizada, melhorando a experiência do usuário e facilitando a depuração.
O sistema de autenticação utiliza JSON Web Tokens JWT para autenticar usuários. Quando um usuário fornece credenciais válidas em /sessions, o sistema gera um token JWT de acesso e um token de atualização (refresh token). O token JWT é utilizado para autenticar solicitações subsequentes, enquanto o refresh token é armazenado como um cookie chamado refreshToken.
O middleware verifyJWT é empregado em rotas específicas, como /me, para garantir a autenticidade do token JWT. Além disso, há uma rota /token/refresh que renova o token de acesso usando o refresh token armazenado no cookie. Isso contribui para a segurança e a manutenção da sessão do usuário.
No sistema de Role-Based Access Control RBAC, as permissões são atribuídas aos usuários com base em suas funções (roles). O sistema utiliza essa função como middleware para verificar se o usuário autenticado possui a função necessária para acessar determinados recursos. No caso, o RBAC verifica se o papel (role) do usuário corresponde à função que está sendo verificada. Se não corresponder, a resposta é uma negação de acesso (código 401), indicando "Não Autorizado". Isso fortalece a segurança, controlando de maneira granular o acesso a diferentes partes do sistema com base nas funções atribuídas aos usuários.
Para persistência de dados, o sistema utiliza PostgreSQL, sendo orquestrado por meio de um contêiner Docker gerenciado pelo Docker Compose. Essa abordagem oferece portabilidade e facilidade na implantação do ambiente de desenvolvimento.
O Prisma é adotado como ORM (Object-Relational Mapping) para definir e manipular os esquemas do banco de dados. Ele simplifica a interação com o PostgreSQL, permitindo a criação de consultas e operações de banco de dados de maneira eficiente e intuitiva. Essa escolha de tecnologias reflete uma arquitetura moderna e escalável para garantir a robustez e a manutenibilidade da camada de persistência do sistema.
O sistema passou por rigorosos testes para garantir a qualidade e robustez do código. No contexto dos testes unitários, adotamos a metodologia Test-Driven Development TDD, concentrando-nos na avaliação das camadas mais internas, em particular nos casos de uso. A utilização do supertest é fundamental para simular solicitações HTTP, proporcionando uma análise precisa do comportamento do sistema em um ambiente semelhante ao de produção. Além disso, para a execução dos testes end-to-end e2e, que abrangem desde as solicitações HTTP até a persistência de dados no banco de dados, é necessário configurar um ambiente específico. Isso inclui a criação de um novo schema no banco de dados, que é descartado após a conclusão dos testes. Todas essas configurações foram implementadas com cuidado no sistema utilizando vitest.
erDiagram
User {
id text[PK]
name text
email text
password_hash text
role text
created_at timestamp
}
CheckIn {
id text[PK]
created_at timestamp
validated_at timestamp
gym_id text[FK]
user_id text[FK]
}
Gym {
id text[PK]
title text
description text
phone text
latitude numeric
longitude numeric
}
User ||--o{ CheckIn : "Has"
CheckIn }o--|| Gym : "Belongs to"
✅ Deve ser possível se cadastrar;
✅ Deve ser possível se autenticar;
✅ Deve ser possível obter o perfil de um usuário logado;
✅ Deve ser possível obter o número de check-ins realizados pelo usuário logado;
✅ Deve ser possível o usuário obter seu histórico de check-ins;
✅ Deve ser possível o usuário buscar academias próximas (10km);
✅ Deve ser possível o usuário buscar academia pelo nome;
✅ Deve ser possível o usuário realizar check-in em uma academia;
✅ Deve ser possível validar o check-in de um usuário;
✅ Deve ser possível cadastrar uma academia;✅ O usuário não deve poder se cadastrar com um e-mail duplicado;
✅ O usuário não pode fazer 2 check-ins no mesmo dia;
✅ O usuário não pode fazer check-in se não estiver perto (100m) da academia;
✅ O check-in só pode ser validado até 20 minutos após criado;
✅ O check-in só pode ser validado por administradores;
✅ A academia só pode ser cadastrada por administradores;✅ A senha do usuário precisa estar criptografada;
✅ Os dados da aplicação precisam estar persistidos em um banco PostgreSQL;
✅ Todas listas de dados precisam estar paginadas com 20 itens por página;
✅ O usuário deve ser identificado por um JWT;Para executar esse projeto será necessário ter o node instalado, de a preferência para a versão apresentada na tag do início desse readme.
Para conseguir transitar bem entre as versões sugiro o uso do nvm
Para criar um container com o banco de dados será necessário ter o docker e docker compose instalados.
Após acessar o diretório do projeto, crie seu arquivo
.envna raiz do projeto seguindo o arquivo.env.example, leve em consideração as informações do campoenvironmentdodocker-composepara substituir${username},${password}e${databaseName}.
Com o docker rodando em sua maquina e com o projeto aberto, abra seu terminal e execute os seguintes passos:
# Instalação dos pacotes
$ npm install
# Execução das migrations
$ npx prisma migrate dev
# Execução do servidor
$ npm run dev
# Execução dos testes unitários
$ npm run test
# Execução dos testes e2e
$ npm run e2e
# Execução da cobertura dos testes
$ npm run coverageVocê pode está utilizando ferramentas como insomnia, postman e apidog para realizar as requisições.
Para acompanhar os registros no banco de dados execute npx prisma studio.