BlogsAPI é um projeto back-end, onde foi desenvolvido uma API RESTFul para um blog, utilizando arquitetura MSC - Models, Services e Controller utilizando MySQL como banco de dados.
A base do projeto foi desenvolvido pela Trybe (Dockerfile, package.json, docker-compose.yml e outras configurações). Arquivos desenvolvidos por mim:
- tudo na pasta
./src/
;
Tecnologias aplicadas por mim no projeto:
- NodeJS;
- Express;
- Sequelize;
- MySQL;
- Docker;
- JWT;
Etapas de instalação:
- Certifique-se de ter o docker instalado com as versões 1.29 ou superior;
- Clone o repositório;
- Acesse a pasta raiz do repositório e execute o comando
docker-compose up -d
; - O comando acima irá subir dois containers: um container Node chamado blogs_api, e um container MySQL de nome blogs_api_db;
- Você deve acessar o container Node (blogs_api) para instalar as dependências do projeto. Execute o comando:
docker exec -it blogs_api bash
; - Já dentro da linha de comando do 'blogs_api', instale as dependências do projeto com o comando
npm install
; - Execute o comando
npm run prestart
. Esse comando irá rodar os comandos Sequelize para criar e migrar o banco de dados MySQL; - Execute a aplicação com
npm start
; - Você pode testar e depurar a API com programas como ThunderClient ou Postman. As rotas e os retornos esperados são explicados em 'Requisitos do projeto'.;
- A porta padrão para testar os requisitos é a 3000. (http://localhost:3000/);
Para orientar a construção das tabelas através do ORM, foi utilizado o DER abaixo:
Foi criado migrations para as tabelas na pasta './src/migrations/'.
O corpo da requisição deverá seguir o formato abaixo:
{
"email": "lewishamilton@gmail.com",
"password": "123456"
}
Caso a requisição não tiver todos os campos devidamente preenchidos, o retorno será um status 400
com a mensagem:
{
"message": "Some required fields are missing"
}
Caso a requisição receba um usuário errado/inexistente, o retorno será um status 400
com a mensagem:
{
"message": "Invalid fields"
}
Se o login for feito com sucesso, o retorno será status 200
com um token de autenticação:
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJwYXlsb2FkIjp7ImlkIjo1LCJkaXNwbGF5TmFtZSI6InVzdWFyaW8gZGUgdGVzdGUiLCJlbWFpbCI6InRlc3RlQGVtYWlsLmNvbSIsImltYWdlIjoibnVsbCJ9LCJpYXQiOjE2MjAyNDQxODcsImV4cCI6MTYyMDY3NjE4N30.Roc4byj6mYakYqd9LTCozU1hd9k_Vw5IWKGL4hcCVG8"
}
O corpo da requisição deverá seguir o formato abaixo:
{
"displayName": "Brett Wiltshire",
"email": "brett@email.com",
"password": "123456",
"image": "http://4.bp.blogspot.com/_YA50adQ-7vQ/S1gfR_6ufpI/AAAAAAAAAAk/1ErJGgRWZDg/S45/brett.png"
// a imagem não é obrigatória
}
Caso displayName, email ou password não estejam preenchido, o sistema retornará status 400
com uma mensagem personalizada, dependendo do campo que esteja faltando:
{
"message": "\"displayName\" length must be at least 8 characters long"
}
{
"message": "\"email\" must be a valid email"
}
{
"message": "\"password\" length must be at least 6 characters long"
}
Também é feito uma conferência para não ser possível cadastrar um email que já esteja cadastrado. Caso o email já esteja cadastrado, será retornado status 409
com a mensagem:
{
"message": "User already registered"
}
Caso tudo esteja correto e o usuário seja cadastrado corretamente, o retorno será status 201
com o token:
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJwYXlsb2FkIjp7ImlkIjo1LCJkaXNwbGF5TmFtZSI6InVzdWFyaW8gZGUgdGVzdGUiLCJlbWFpbCI6InRlc3RlQGVtYWlsLmNvbSIsImltYWdlIjoibnVsbCJ9LCJpYXQiOjE2MjAyNDQxODcsImV4cCI6MTYyMDY3NjE4N30.Roc4byj6mYakYqd9LTCozU1hd9k_Vw5IWKGL4hcCVG8"
}
Os próximos requisitos precisarão do token para serem testados. O token gerado ou pelo login, ou pelo cadastro do usuário deve ser salvo como header no formato:
header: authorization
value: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwiZGlzcGxheU5hbWUiOiJGZWxpcGUgQ3J1eiIsImVtYWlsIjoiZmVsaXBlQGVtYWlsLmNvbSIsInBhc3N3b3JkIjoiMTIzNDU2IiwiaW1hZ2UiOiJodHRwOi8vNC5icC5ibG9nc3BvdC5jb20vX1lBNTBhZFEtN3ZRL1MxZ2ZSXzZ1ZnBJL0FBQUFBQUFBQUFrLzFFckpHZ1JXWkRnL1M0NS9icmV0dC5wbmciLCJpYXQiOjE2OTE0MTMzOTcsImV4cCI6MTY5MzE0MTM5N30.hELaGIdRMPw9xruZhH5Rr8epEkkiqq1muYTXEzGY9VU
(sem aspas)
Caso o token seja inexistente o retorno será status 401
com a mensagem:
{
"message": "Token not found"
}
Se o token for inválido ou estiver expirado, o retorno será status 401
e a mensagem:
{
"message": "Expired or invalid token"
}
Ao listar os usuário com sucesso, o retorno será status 200
com a mensagem:
[
{
"id": 1,
"displayName": "Lewis Hamilton",
"email": "lewishamilton@gmail.com",
"image": "https://upload.wikimedia.org/wikipedia/commons/1/18/Lewis_Hamilton_2016_Malaysia_2.jpg"
},
/* ... */
]
Ao listar um usuário com sucesso o resultado retornado deverá ser conforme exibido abaixo, com um status http 200:
{
"id": 1,
"displayName": "Lewis Hamilton",
"email": "lewishamilton@gmail.com",
"image": "https://upload.wikimedia.org/wikipedia/commons/1/18/Lewis_Hamilton_2016_Malaysia_2.jpg"
}
Caso o id do usuário solicitado seja inexistente, o retorno será status 404
:
{
"message": "User does not exist"
}
O corpo da requisição deverá seguir o formato abaixo:
{
"name": "Typescript"
}
caso "name" não for preenchido, o retorno será status 400
com a mensagem:
{
"message": "\"name\" is required"
}
Se a categoria for criada com sucesso, o retorno será status 201
:
{
"id": 3,
"name": "Typescript"
}
Ao listar as categorias com sucesso, status 200
:
[
{
"id": 1,
"name": "Inovação"
},
{
"id": 2,
"name": "Escola"
},
/* ... */
]
11 - Crie o modelo PostCategory em src/models/PostCategory.js com as propriedades e associações corretas
O corpo da requisição deverá seguir o formato abaixo:
{
"title": "Latest updates, August 1st",
"content": "The whole text for the blog post goes here in this key",
"categoryIds": [1, 2]
}
Ao listar posts com sucesso o resultado retornado deverá ser conforme exibido abaixo, com um status http 200:
[
{
"id": 1,
"title": "Post do Ano",
"content": "Melhor post do ano",
"userId": 1,
"published": "2011-08-01T19:58:00.000Z",
"updated": "2011-08-01T19:58:51.000Z",
"user": {
"id": 1,
"displayName": "Lewis Hamilton",
"email": "lewishamilton@gmail.com",
"image": "https://upload.wikimedia.org/wikipedia/commons/1/18/Lewis_Hamilton_2016_Malaysia_2.jpg"
},
"categories": [
{
"id": 1,
"name": "Inovação"
}
]
},
/* ... */
]
o listar um post com sucesso o resultado retornado deverá ser conforme exibido abaixo, com um status http 200:
{
"id": 1,
"title": "Post do Ano",
"content": "Melhor post do ano",
"userId": 1,
"published": "2011-08-01T19:58:00.000Z",
"updated": "2011-08-01T19:58:51.000Z",
"user": {
"id": 1,
"displayName": "Lewis Hamilton",
"email": "lewishamilton@gmail.com",
"image": "https://upload.wikimedia.org/wikipedia/commons/1/18/Lewis_Hamilton_2016_Malaysia_2.jpg"
},
"categories": [
{
"id": 1,
"name": "Inovação"
}
]
}
Caso o post não exista, o retorno será status 404 com a mensagem:
{
"message": "Post does not exist"
}
O corpo da requisição deverá seguir o formato abaixo:
{
"title": "Latest updates, August 1st",
"content": "The whole text for the blog post goes here in this key"
}