β¨ A copy (or something like) of the Gympass API. Node.js & Typescript based, developed with concepts like SOLID, DDD, TDD, Repository Pattern, Factory Method and RBAC system. Has unit test for especific use-cases and test E2E for every HTTP controller. β¨
GympassAPI was a project to better learn the concepts involved in the backend, such as SOLID concepts, the principles of DDD and TDD. I also learned about the RBAC authorization system, the use of the JWT token, authentication and validation systems and much more.
To get started with GympassAPI, follow these simple steps:
First of all, clone the repository and install de dependencies.
npm install
Now we must setup our environment variables. Create a file on root as .env. Inside, put all data like is on .env.example
NODE_ENV=dev
# Auth
JWT_SECRET=YOUR_SECRET_HERE
# Database
DATABASE_URL="url_from_your_database"
There is a docker-compose.yml
file inside the project, so if you want to create the container as I thot, you can run the following command
docker compose up -d
and if you want to stop the container
docker compose stop
- It must be possible to register;
- It must be possible to authenticate;
- It must be possible to obtain the profile of a logged-in user;
- It must be possible to obtain the number of check-ins carried out by the logged-in user;
- It must be possible for the user to obtain their check-in history;
- It must be possible for the user to search for nearby gyms (up to 10km);
- It must be possible for the user to search for gyms by name;
- It must be possible for the user to check-in at a gym;
- It must be possible to validate a user's check-in;
- It must be possible to register a gym;
- The user must not be able to register with a duplicate e-mail address;
- The user cannot make 2 check-ins on the same day;
- The user cannot check in if they are not close (100m) to the gym;
- The check-in can only be validated up to 20 minutes after it has been created;
- The check-in can only be validated by administrators;
- The gym can only be registered by administrators;
- The user's password must be encrypted;
- The application data must be persisted in a PostgreSQL database;
- All data lists must be paginated with 20 items per page;
- The user must be identified by a JWT (JSON Web Token);
Here you can see all the endpoints of the application
POST - '/users'
-
This is the user's entry route, where the user will register with on the application. You must send the request with a data equal a some user's informations on the body of the requisition.
Params Type Default name
string - email
string - password
string - role
string 'MEMBER'
-
POST - '/sessions'
-
This is the authenticate route. Here, the user can log-in on our application. Send this data as the body of the request as a JSON. After that, we will generate a access token that contains the user ID and about his role.
Params Type Default email
string - password
string -
-
PATCH - '/token/refresh'
-
This route will check if the user has an access token. If not, it will try to create another one based on the refresh token located in cookies. You must send the requisition with the access token as authorization (if you have one).
Header Type Authorization
Bearer
-
-
GET - '/me'
-
This route requires that you already be logged-in. Here, you send your requisition with a JWT Token as authorization.
Header Type Authorization
Bearer
will be something like this
fetch(url, { method: 'GET', headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' } })
-
On Gyms, every route needs to be authenticated, that means every request must have the following header: Authorization Bearer ${token}
. Some routes also require role = 'ADMIN'
.
GET - '/gyms/search'
-
Here you can search gyms by their name. You must send the request with a query as q on the body of the requisition as a JSON.
Params Type Default q
string - page
number 1
-
GET - '/gyms/nearby'
-
Here you can find nearby gyms based on latitude and longitude of the user. You must send the request with a latitude and longitude of the user on the body of the requisitionas as a JSON.
Params Type Default latitude
number - longitude
number -
-
POST - '/gyms'
-
Here we create a new Gym on database. You must do this as a
'ADMIN'
user so your access token must have this proprerty. You can pass the informations of the gym on the body of the requisition as a JSON.Params Type Default title
string - description
string - phone
number - latitude
number - longitude
number -
-
On Check Ins, every route needs to be authenticated.
-
GET - '/check-ins/history'
-
Here we can take the history of all check-ins that the user made it. You must just provide your JWT Token for the authorization.
Header Type Authorization
Bearer
will be something like this
fetch(url, { method: 'GET', headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' } })
-
-
GET - '/check-ins/metrics'
-
Here we can take the metrics of the user. You must just provide your JWT Token for the authorization.
Header Type Authorization
Bearer
will be something like this
fetch(url, { method: 'GET', headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' } })
-
POST - '/gyms/:gymId/check-ins'
-
Here we can create a check-in on a gym. You must provide on the URL param the id of the gym as gymID and on the body of the request the latitude and longitude of the user as a JSON.
Params Type Default gymId
string - latitude
number - longitude
number -
-
POST - '/check-ins/:checkInId/validate'
-
Here we validate the check-in of the user. You must do this as a
'ADMIN'
user so your access token must have this proprerty. You also must provide on the URL param the checkInId as the check-in that will be validated.Params Type Default checkInId
string -
-
The technologies used to develop this application was:
- nodejs
- typescript
- fastify
- @fastify/cookie
- @fastify/jwt
- prisma
- zod
- vitest
- supertest
- dayjs
- tsup
- dotenv
- bcryptjs
- eslint
GympassAPI is released under the MIT License.