Projeto API de Blogs! 📑
Nesse projeto, o objetivo era desenvolver um back-end usando ORM
com o pacote sequelize
do npm
, e ser capaz de:
- Criar e associar tabelas usando
models
dosequelize
- Construir endpoints para consumir os models que criar
- Fazer um
CRUD
com oORM
Essa API, possui alguns endpoints (seguindo os princÃpios do REST) que estão conectados ao banco de dados, sempre pensando no modelo de negócio. A ideia dessa API é criar uma tabela para os usuários que desejam se cadastar. Após o cadastro vamos ao endpoint de login com algumas validaçoẽs, caso esteja tudo certo a requisição retorna um token que será usado para futuras rotas. Além da tebela de usuários, temos a de categorias, blogpost e a tabela intermediária que conecta o as categorias e os post, seguindo o principio da 3º forma normal.
Ferramentas usadas 🧰
🔨 Estè projeto foi feito com Node.js utilizando o pacote sequelize.
INSTRUÇÕES :
- Clone o repositório
git clone git@github.com:luanamonero/api-blog.git
.- Entre na pasta do repositório que você acabou de clonar:
cd api-blog
- Instale as dependências
npm install
- Crie, na raÃz do projeto, um arquivo
.env
contendo as seguintes variáveis:
HOSTNAME=seu-host-mysql
MYSQL_USER=seu-usuario-mysql
MYSQL_PASSWORD=sua-senha-mysql
JWT_SECRET=qualquer-string-aleatoria
PORT=porta-para-iniciar-aplicação(padrão = 3000)
Você irá precisar configurar as variáveis globais do MySQL. Você pode usar esse Conteúdo de variáveis de ambiente com NodeJS como referência.
Faça essas configurações também para as variáveis de ambiente usadas nesses arquivo:
api-blog/config/config.js
module.exports = {
development: {
username: process.env.MYSQL_USER,
password: process.env.MYSQL_PASSWORD,
database: 'blogs_api',
host: process.env.HOSTNAME,
dialect: 'mysql',
},
test: {
username: process.env.MYSQL_USER,
password: process.env.MYSQL_PASSWORD,
database: 'blogs_api',
host: process.env.HOSTNAME,
dialect: 'mysql',
},
production: {
username: process.env.MYSQL_USER,
password: process.env.MYSQL_PASSWORD,
database: 'blogs_api',
host: process.env.HOSTNAME,
dialect: 'mysql',
},
};
(Neste arquivo é obrigatório deixar o nome do database como "database": 'blogs_api'
)
Variável JWT (opcional):
JWT_SECRET
Também poderá ser utilizada esta variável de ambiente para o SECRET do JWT
- Inicie o projeto
npm start
npm run debug
caso queria rodar o projeto através do nodemon
- Acesse as rotas através de softwares como Postman e Insomnia através do endereço:
http://localhost:3000
Rotas:
/user
Endpoint POST - O corpo da requisição deve ter o seguinte formato:
{
"displayName": "Brett Wiltshire",
"email": "brett@email.com",
"password": "123456",
"image": "http://4.bp.blogspot.com/_YA50adQ-7vQ/S1gfR_6ufpI/AAAAAAAAAAk/1ErJGgRWZDg/S45/brett.png"
}
-
displayName
deve ser uma string com pelo menos 8 caracteres; -
email
deve ser uma string no formatoemail@email.com
e único; -
password
deve ser uma string com 6 caracteres; -
image
deve ser uma string; -
Caso haja falha na validação a requisição será respondida com o
status 400
e uma mensagem de erro como o exemplo abaixo:
{
"message": "\"displayName\" is required"
}
- Caso o email já esteja em uso a requisição será respondida com o
status 409
e uma mensagem de erro como o exemplo abaixo:
{
"message": "User already registered"
}
- Caso haja sucesso na validação a requisição será respondida com o
status 201
com o token de autenticação:
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJwYXlsb2FkIjp7ImlkIjo1LCJkaXNwbGF5TmFtZSI6InVzdWFyaW8gZGUgdGVzdGUiLCJlbWFpbCI6InRlc3RlQGVtYWlsLmNvbSIsImltYWdlIjoibnVsbCJ9LCJpYXQiOjE2MjAyNDQxODcsImV4cCI6MTYyMDY3NjE4N30.Roc4byj6mYakYqd9LTCozU1hd9k_Vw5IWKGL4hcCVG8"
}
/login
Endpoint POST - O corpo da requisição deve ter o seguinte formato:
{
"email": "email@mail.com",
"password": "123456"
}
- Caso haja falha na validação a requisição será respondida com o
status 400
e uma mensagem de erro como o exemplo abaixo:
{
"message": "\"email\" is required"
}
- Caso haja falha no login a requisição será respondida com o
status 400
e uma mensagem de erro como o exemplo abaixo:
{
"message": "Invalid fields"
}
- Caso haja sucesso na validação a requisição será respondida com o
status 200
com o token de autenticação:
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJwYXlsb2FkIjp7ImlkIjo1LCJkaXNwbGF5TmFtZSI6InVzdWFyaW8gZGUgdGVzdGUiLCJlbWFpbCI6InRlc3RlQGVtYWlsLmNvbSIsImltYWdlIjoibnVsbCJ9LCJpYXQiOjE2MjAyNDQxODcsImV4cCI6MTYyMDY3NjE4N30.Roc4byj6mYakYqd9LTCozU1hd9k_Vw5IWKGL4hcCVG8"
}
/user
Endpoint GET -
A rota deve ser autenticada enviando o token como header
authorization
da requisição, que é obtido na rota de login ou de cadastro -
Caso o token não seja enviado a requisição será respondida com o
status 401
e uma mensagem de erro como o exemplo abaixo:
{
"message": "Token not found"
}
- Caso o token não seja válido a requisição será respondida com o
status 401
e uma mensagem de erro como o exemplo abaixo:
{
"message": "Expired or invalid token"
}
- Caso o token seja válido a requisição será respondida com o
status 200
com o seguinte corpo:
[
{
"id": "401465483996",
"displayName": "Brett Wiltshire",
"email": "brett@email.com",
"image": "http://4.bp.blogspot.com/_YA50adQ-7vQ/S1gfR_6ufpI/AAAAAAAAAAk/1ErJGgRWZDg/S45/brett.png"
}
]
/user/:id
Endpoint GET -
A rota deve ser autenticada enviando o token como header
authorization
da requisição, que é obtido na rota de login ou de cadastro -
Caso o token não seja enviado a requisição será respondida com o
status 401
e uma mensagem de erro como o exemplo abaixo:
{
"message": "Token not found"
}
- Caso o token não seja válido a requisição será respondida com o
status 401
e uma mensagem de erro como o exemplo abaixo:
{
"message": "Expired or invalid token"
}
- Caso o usuário não exista a requisição será respondida com o
status 404
e uma mensagem de erro como o exemplo abaixo:
{
"message": "User does not exist"
}
- Caso o token seja válido a requisição será respondida com o
status 200
com o seguinte corpo:
{
"id": "401465483996",
"displayName": "Brett Wiltshire",
"email": "brett@email.com",
"image": "http://4.bp.blogspot.com/_YA50adQ-7vQ/S1gfR_6ufpI/AAAAAAAAAAk/1ErJGgRWZDg/S45/brett.png"
}
/categories
Endpoint POST -
A rota deve ser autenticada enviando o token como header
authorization
da requisição, que é obtido na rota de login ou de cadastro -
O corpo da requisição deve ter o seguinte formato:
{
"name": "Inovação"
}
- Caso haja falha na validação a requisição será respondida com o
status 400
e uma mensagem de erro como o exemplo abaixo:
{
"message": "\"name\" is required"
}
- Caso o token não seja enviado a requisição será respondida com o
status 401
e uma mensagem de erro como o exemplo abaixo:
{
"message": "Token not found"
}
- Caso o token não seja válido a requisição será respondida com o
status 401
e uma mensagem de erro como o exemplo abaixo:
{
"message": "Expired or invalid token"
}
- Caso o token seja válido a requisição será respondida com o
status 201
com o seguinte corpo:
{
"id": 3,
"name": "Inovação"
}
/categories
Endpoint GET -
A rota deve ser autenticada enviando o token como header
authorization
da requisição, que é obtido na rota de login ou de cadastro -
Caso o token não seja enviado a requisição será respondida com o
status 401
e uma mensagem de erro como o exemplo abaixo:
{
"message": "Token not found"
}
- Caso o token não seja válido a requisição será respondida com o
status 401
e uma mensagem de erro como o exemplo abaixo:
{
"message": "Expired or invalid token"
}
- Caso o token seja válido a requisição será respondida com o
status 200
com o seguinte corpo:
[
{
"id": 1,
"name": "Escola"
},
{
"id": 2,
"name": "Inovação"
}
]
/post
Endpoint POST -
A rota deve ser autenticada enviando o token como header
authorization
da requisição, que é obtido na rota de login ou de cadastro -
O corpo da requisição deve ter o seguinte formato:
{
"title": "Latest updates, August 1st",
"content": "The whole text for the blog post goes here in this key",
"categoryIds": [1, 2]
}
-
categoryIds
deve ser um array contendo os ids de categorias cadastradas; -
Caso haja falha na validação a requisição será respondida com o
status 400
e uma mensagem de erro como o exemplo abaixo:
{
"message": "\"title\" is required"
}
- Caso o token não seja enviado a requisição será respondida com o
status 401
e uma mensagem de erro como o exemplo abaixo:
{
"message": "Token not found"
}
- Caso o token não seja válido a requisição será respondida com o
status 401
e uma mensagem de erro como o exemplo abaixo:
{
"message": "Expired or invalid token"
}
- Caso alguma das categorias seja inválida a requisição será respondida com o
status 400
e uma mensagem de erro como o exemplo abaixo:
{
"message": "\"categoryIds\" not found"
}
- Caso o token seja válido a requisição será respondida com o
status 201
com o seguinte corpo:
{
"id": 4,
"userId": 1,
"title": "Latest updates, August 1st",
"content": "The whole text for the blog post goes here in this key"
}
/post
Endpoint GET -
A rota deve ser autenticada enviando o token como header
authorization
da requisição, que é obtido na rota de login ou de cadastro -
Caso o token não seja enviado a requisição será respondida com o
status 401
e uma mensagem de erro como o exemplo abaixo:
{
"message": "Token not found"
}
- Caso o token não seja válido a requisição será respondida com o
status 401
e uma mensagem de erro como o exemplo abaixo:
{
"message": "Expired or invalid token"
}
- Caso o token seja válido a requisição será respondida com o
status 200
com o seguinte corpo:
[
{
"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_2017_Malaysia.jpg"
},
"categories": [
{
"id": 1,
"name": "Inovação"
}
]
}
]
/post/:id
Endpoint GET -
A rota deve ser autenticada enviando o token como header
authorization
da requisição, que é obtido na rota de login ou de cadastro -
Caso o token não seja enviado a requisição será respondida com o
status 401
e uma mensagem de erro como o exemplo abaixo:
{
"message": "Token not found"
}
- Caso o token não seja válido a requisição será respondida com o
status 401
e uma mensagem de erro como o exemplo abaixo:
{
"message": "Expired or invalid token"
}
- Caso o post não exista a requisição será respondida com o
status 404
e uma mensagem de erro como o exemplo abaixo:
{
"message": "Post does not exist"
}
- Caso o token seja válido a requisição será respondida com o
status 200
com o seguinte corpo:
{
"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_2017_Malaysia.jpg"
},
"categories": [
{
"id": 1,
"name": "Inovação"
}
]
}
FEEDBACKS
Caso queira dar alguma sugestão entre em contato comigo via linkedin: www.linkedin.com/in/luanamonero
Ficarei feliz em receber!