API para um blog. Desenvolvida em Node.js, com JavaScript, Express.js para ligar com rotas, Sequelize(ORM) para criar e gerenciar um banco de dados, MySQL, JWT para autenticação e Joi para validação de dados. Com sistema CRUD (POST, GET, PUT e DELETE) utilizando a arquitetura API-REST(Representational State Transfer).
💻 Tecnologias utilizadas
- JavaScript: Linguagem de programação.
- NodeJS: Motor de JavaScript para criação de aplicações web.
- ExpressJS: Framework para desenvolvimento da API.
- MYSQL: Banco de dados.
- Sequilize: ORM para o MYSQL.
- Joi: Validação de dados.
- JWT: Autenticação.
- Dotenv: Carregamento de variáveis de ambiente.
- Mocha: Framework de testes.
- Chai: Framework de testes.
- Sinon: Framework de testes.
-
-
# clonando o repositório ou baixe por zip(ali em cima) $ git clone git@github.com:Dogl4/Blogs-Api.git # entrando na pasta do repositório $ cd Blogs-Api # instalando dependências $ npm install
-
Renomei o arquivo
.env.example
para.env
, substituindo os valores por seus respectivos dados locais. -
# criando o banco de dados $ npm run init # populando o banco, executando as seeds $ npm run seed # se quiser deletar o banco de dados $ npm run drop
-
# iniciando o servidor $ npm run start # iniciando o servidor em modo de desenvolvimento $ npm run dev
# se não inicializar, verifica se não existe nada rodando na porta 3000, comando para linux $ lsof -i:3000 # se existir, feche o processo, comando para linux $ kill -9 $(lsof -t -i:3000)
🚪 Modificando a porta
A porta padrão é
3000
. Você pode alterar isso renomeando o arquivo.env.example
para.env
e modificando o valor da variávelPORT
.
# unit test
$ npm run test
# test coverage
$ npm run test:cov
Use algum dos seguintes programas para fazer as requisições: Postman ou Thunder Client ou Insomnia. Se estiver utilizando o Postman, vá em importe a
collection.json
do repositório, que está localizada em./postman/collection.json
. Rotas com 🔐 (protected) são protegidas por um token JWT.
-
POST (cadastra)
-
Url:
/user
- Exemplo:
http://localhost:3000/user
-
Request:
- Body:
{ "email": "doougllas@hotmail.com.br", "password": "123456" }
- Body:
-
Response sucesso:
- Status:
201 Created
- Body:
{ "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc0FkbWluIjpmYWxzZSwidXNlckVtYWlsIjoiYWFhQGFhYS5jbyIsImlhdCI6MTY1OTM1NjE1NywiZXhwIjoxNjU5NDQyNTU3LCJzdWIiOiJhYWFAYWFhLmNvIn0.y3TmHszGD1XvS-PatCJ1zofM8ZLG4YnGm5UantcP2Ak" }
- Status:
-
Response erro:
-
Status:
400 Bad Request
-
Body:
{ "message": "\"email\" is required" }
{ "message": "\"email\" is not allowed to be empty" }
{ "message": "\"password\" is required" }
{ "message": "\"password\" is not allowed to be empty" }
{ "message": "\"password\" length must be at least 6 characters long" }
-
Status:
409 Conflict
-
Body:
{ "message": "User already registered" }
-
-
-
POST (login)
-
Url:
/login
- Exemplo:
http://localhost:3000/login
-
Request:
- Body:
{ "email": "doougllas@hotmail.com.br", "password": "123456" }
- Body:
-
Response sucesso:
- Status:
200 OK
- Body:
{ "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc0FkbWluIjpmYWxzZSwidXNlckVtYWlsIjoiYWFhQGFhYS5jbyIsImlhdCI6MTY1OTUyNDkwNiwiZXhwIjoxNjU5NjExMzA2LCJzdWIiOiJhYWFAYWFhLmNvIn0.tHMoYbyjXGYEK0ZghfmUh3jmBOv4cZxRbDjZrYYKVL8" }
- Status:
-
Response erro:
- Status:
400 Bad Request
- Body:
{ "message": "\"email\" is required" }
{ "message": "\"email\" is not allowed to be empty" }
{ "message": "\"email\" must be a valid email" }
{ "message": "\"password\" is required" }
{ "message": "\"password\" is not allowed to be empty" }
{ "message": "\"password\" length must be at least 6 characters long" }
{ "message": "Invalid fields" }
- Status:
-
-
🔐 GET (todos os usuários)
-
Url:
/user
- Exemplo:
http://localhost:3000/user
-
Request:
- Headers:
{ "Authorization": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc0FkbWluIjpmYWxzZSwidXNlckVtYWlsIjoiZG9vdWdsbGFzQGhvdG1haWwuY29tLmJyIiwiaWF0IjoxNjU5NTI1NjgzLCJleHAiOjE2NTk2MTIwODMsInN1YiI6ImRvb3VnbGxhc0Bob3RtYWlsLmNvbS5iciJ9.HlIe_JlHWPBdqyh80fCR-umYbVwy0aFqaGIMI63kgWQ", }
- Headers:
-
Response sucesso:
- Status:
200 OK
- Body:
[ { "id": 1, "displayName": "Lewis Hamilton", "email": "lewishamilton@gmail.com", "password": "123456", "image": "https://upload.wikimedia.org/wikipedia/commons/1/18/Lewis_Hamilton_2016_Malaysia_2.jpg" }, { "id": 2, "displayName": "Michael Schumacher", "email": "MichaelSchumacher@gmail.com", "password": "123456", "image": "https://sportbuzz.uol.com.br/media/_versions/gettyimages-52491565_widelg.jpg" }, { "id": 3, "displayName": null, "email": "aaa@aaa.co", "password": "123456", "image": null }, { "id": 4, "displayName": null, "email": "doougllas@hotmail.com.br", "password": "123456", "image": null } ]
- Status:
-
Response erro:
- Status:
401 Unauthorized
- Body:
{ "message": "Token not found" }
{ "message": "Expired or invalid token" }
- Status:
-
-
🔐 GET (um usuário)
-
Url:
/user/:id
- Exemplo:
http://localhost:3000/user/1
-
Request:
- Headers:
{ "Authorization": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc0FkbWluIjpmYWxzZSwidXNlckVtYWlsIjoiZG9vdWdsbGFzQGhvdG1haWwuY29tLmJyIiwiaWF0IjoxNjU5NTI1NjgzLCJleHAiOjE2NTk2MTIwODMsInN1YiI6ImRvb3VnbGxhc0Bob3RtYWlsLmNvbS5iciJ9.HlIe_JlHWPBdqyh80fCR-umYbVwy0aFqaGIMI63kgWQ", }
- Headers:
-
Response sucesso:
- Status:
200 OK
- Body:
{ "id": 1, "displayName": "Lewis Hamilton", "email": "lewishamilton@gmail.com", "password": "123456", "image": "https://upload.wikimedia.org/wikipedia/commons/1/18/Lewis_Hamilton_2016_Malaysia_2.jpg" }
- Status:
-
Response erro:
- Status:
401 Unauthorized
- Body:
{ "message": "Token not found" }
{ "message": "Expired or invalid token" }
- Status:
-
-
🔐 DELETE (deleta usuário)
-
Url:
/user/me
- Exemplo:
http://localhost:3000/user/me
-
Request:
- Headers:
{ "Authorization": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc0FkbWluIjpmYWxzZSwidXNlckVtYWlsIjoiZG9vdWdsbGFzQGhvdG1haWwuY29tLmJyIiwiaWF0IjoxNjU5NTI1NjgzLCJleHAiOjE2NTk2MTIwODMsInN1YiI6ImRvb3VnbGxhc0Bob3RtYWlsLmNvbS5iciJ9.HlIe_JlHWPBdqyh80fCR-umYbVwy0aFqaGIMI63kgWQ", }
- Headers:
-
Response sucesso:
- Status:
204 No Content
- Status:
-
Response erro:
-
Status:
401 Unauthorized
-
Body:
{ "message": "Token not found" }
{ "message": "Expired or invalid token" }
-
Status:
404 Not Found
-
Body:
{ "message": "User does not exist" }
-
-
-
🔐 POST (cadastra)
-
Url:
/categories
- Exemplo:
http://localhost:3000/categories
-
Request:
- Headers:
{ "Authorization": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc0FkbWluIjpmYWxzZSwidXNlckVtYWlsIjoiZG9vdWdsbGFzQGhvdG1haWwuY29tLmJyIiwiaWF0IjoxNjU5NTI1NjgzLCJleHAiOjE2NTk2MTIwODMsInN1YiI6ImRvb3VnbGxhc0Bob3RtYWlsLmNvbS5iciJ9.HlIe_JlHWPBdqyh80fCR-umYbVwy0aFqaGIMI63kgWQ", }
- Body:
{ "name": "Programação" }
- Headers:
-
Response sucesso:
- Status:
201 Created
- Body:
{ "id": 4, "name": "Programação" }
- Status:
-
Response erro:
-
Status:
400 Bad Request
-
Body:
{ "message": "\"name\" is required" }
{ "message": "\"name\" is not allowed to be empty" }
-
Status:
401 Unauthorized
-
Body:
{ "message": "Token not found" }
{ "message": "Expired or invalid token" }
-
Status:
409 Conflict
-
Body:
{ "message": "Categorier already registered" }
-
-
-
🔐 GET (todas categorias)
-
Url:
/categories
- Exemplo:
http://localhost:3000/categories
-
Request:
- Headers:
{ "Authorization": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc0FkbWluIjpmYWxzZSwidXNlckVtYWlsIjoiZG9vdWdsbGFzQGhvdG1haWwuY29tLmJyIiwiaWF0IjoxNjU5NTI1NjgzLCJleHAiOjE2NTk2MTIwODMsInN1YiI6ImRvb3VnbGxhc0Bob3RtYWlsLmNvbS5iciJ9.HlIe_JlHWPBdqyh80fCR-umYbVwy0aFqaGIMI63kgWQ", }
- Headers:
-
Response sucesso:
- Status:
200 OK
- Body:
[ { "id": 1, "name": "Inovação" }, { "id": 2, "name": "Escola" }, { "id": 3, "name": "1" }, { "id": 4, "name": "Programação" } ]
- Status:
-
Response erro:
- Status:
401 Unauthorized
- Body:
{ "message": "Token not found" }
{ "message": "Expired or invalid token" }
- Status:
-
-
🔐 POST (cadastra)
-
Url:
/post
- Exemplo:
http://localhost:3000/post
-
Request:
- Headers:
{ "Authorization": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc0FkbWluIjpmYWxzZSwidXNlckVtYWlsIjoiZG9vdWdsbGFzQGhvdG1haWwuY29tLmJyIiwiaWF0IjoxNjU5NTI1NjgzLCJleHAiOjE2NTk2MTIwODMsInN1YiI6ImRvb3VnbGxhc0Bob3RtYWlsLmNvbS5iciJ9.HlIe_JlHWPBdqyh80fCR-umYbVwy0aFqaGIMI63kgWQ", }
- Body:
{ "title": "Post do Futuro", "content": "Inovação na escola", "categoryIds": [1,2] }
- Headers:
-
Response sucesso:
- Status:
201 Created
- Body:
{ "id": 10, "userId": 7, "title": "Post do Futuro", "content": "Inovação na escola" }
- Status:
-
Response erro:
-
Status:
400 Bad Request
-
Body:
{ "message": "\"title\" is required" }
{ "message": "\"title\" is not allowed to be empty" }
{ "message": "\"content\" is required" }
{ "message": "\"content\" is not allowed to be empty" }
{ "message": "\"categoryIds\" is required" }
{ "message": "\"categoryIds\" must be an array" }
{ "message": "\"categoryIds\" does not contain 1 required value(s)" }
{ "message": "\"categoryIds[0]\" must be a number" }
-
Status:
401 Unauthorized
-
Body:
{ "message": "Token not found" }
{ "message": "Expired or invalid token" }
-
Status:
404 Not Found
-
Body:
{ "message": "\"categoryIds\" not found" }
-
-
-
🔐 GET (todos posts)
-
Url:
/post
- Exemplo:
http://localhost:3000/post
-
Request:
- Headers:
{ "Authorization": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc0FkbWluIjpmYWxzZSwidXNlckVtYWlsIjoiZG9vdWdsbGFzQGhvdG1haWwuY29tLmJyIiwiaWF0IjoxNjU5NTI1NjgzLCJleHAiOjE2NTk2MTIwODMsInN1YiI6ImRvb3VnbGxhc0Bob3RtYWlsLmNvbS5iciJ9.HlIe_JlHWPBdqyh80fCR-umYbVwy0aFqaGIMI63kgWQ", }
- Headers:
-
Response sucesso:
- Status:
200 OK
- Body:
[ { "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" } ] }, { "id": 2, "title": "Vamos que vamos", "content": "Foguete não tem ré", "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": 2, "name": "Escola" } ] } ]
- Status:
-
Response erro:
- Status:
401 Unauthorized
- Body:
{ "message": "Token not found" }
{ "message": "Expired or invalid token" }
- Status:
-
-
🔐 GET (um post)
-
Url:
/post/:id
- Exemplo:
http://localhost:3000/post/1
-
Request:
- Headers:
{ "Authorization": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc0FkbWluIjpmYWxzZSwidXNlckVtYWlsIjoiZG9vdWdsbGFzQGhvdG1haWwuY29tLmJyIiwiaWF0IjoxNjU5NTI1NjgzLCJleHAiOjE2NTk2MTIwODMsInN1YiI6ImRvb3VnbGxhc0Bob3RtYWlsLmNvbS5iciJ9.HlIe_JlHWPBdqyh80fCR-umYbVwy0aFqaGIMI63kgWQ", }
- Headers:
-
Response sucesso:
- Status:
200 OK
- Body:
{ "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" } ] }
- Status:
-
Response erro:
- Status:
401 Unauthorized
- Body:
{ "message": "Token not found" }
{ "message": "Expired or invalid token" }
- Status:
-
-
🔐 GET (um post por título)
-
Url:
/post/search?q=
- Exemplo:
http://localhost:3000/post/search?q=vamos
-
Request:
- Headers:
{ "Authorization": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc0FkbWluIjpmYWxzZSwidXNlckVtYWlsIjoiZG9vdWdsbGFzQGhvdG1haWwuY29tLmJyIiwiaWF0IjoxNjU5NTI1NjgzLCJleHAiOjE2NTk2MTIwODMsInN1YiI6ImRvb3VnbGxhc0Bob3RtYWlsLmNvbS5iciJ9.HlIe_JlHWPBdqyh80fCR-umYbVwy0aFqaGIMI63kgWQ", }
- Headers:
-
Response sucesso:
- Status:
200 OK
- Body:
[ { "id": 2, "title": "Vamos que vamos", "content": "Foguete não tem ré", "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": 2, "name": "Escola" } ] } ]
- Status:
-
Response erro:
- Status:
401 Unauthorized
- Body:
{ "message": "Token not found" }
{ "message": "Expired or invalid token" }
- Status:
-
-
🔐 PUT (edit um post)
-
Url:
/post/:id
- Exemplo:
http://localhost:3000/post/1
-
Request:
- Headers:
{ "Authorization": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc0FkbWluIjpmYWxzZSwidXNlckVtYWlsIjoiZG9vdWdsbGFzQGhvdG1haWwuY29tLmJyIiwiaWF0IjoxNjU5NTI1NjgzLCJleHAiOjE2NTk2MTIwODMsInN1YiI6ImRvb3VnbGxhc0Bob3RtYWlsLmNvbS5iciJ9.HlIe_JlHWPBdqyh80fCR-umYbVwy0aFqaGIMI63kgWQ", }
- Body:
{ "title": "Refletir sobre o vôo", "content": "Foguete tem ré" }
- Headers:
-
Response sucesso:
- Status:
200 OK
- Body:
{ "0": { "id": 1, "name": "Inovação" }, "1": { "id": 2, "name": "Escola" }, "title": "Refletir sobre o vôo", "content": "Foguete tem ré", "userId": 3 }
- Status:
-
Response erro:
-
Status:
400 Bad Request
-
Body:
{ "message": "\"title\" is required" }
{ "message": "\"title\" is not allowed to be empty" }
{ "message": "\"content\" is required" }
{ "message": "\"content\" is not allowed to be empty" }
-
Status:
401 Unauthorized
-
Body:
{ "message": "Token not found" }
{ "message": "Expired or invalid token" }
{ "message": "You can only edit your own posts" }
-
Status:
404 Not Found
-
Body:
{ "message": "Post does not exist" }
-
-
-
🔐 DELETE (deleta usuário)
-
Url:
/post/:id
- Exemplo:
http://localhost:3000/post/1
-
Request:
- Headers:
{ "Authorization": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc0FkbWluIjpmYWxzZSwidXNlckVtYWlsIjoiZG9vdWdsbGFzQGhvdG1haWwuY29tLmJyIiwiaWF0IjoxNjU5NTI1NjgzLCJleHAiOjE2NTk2MTIwODMsInN1YiI6ImRvb3VnbGxhc0Bob3RtYWlsLmNvbS5iciJ9.HlIe_JlHWPBdqyh80fCR-umYbVwy0aFqaGIMI63kgWQ", }
- Headers:
-
Response sucesso:
- Status:
204 No Content
- Status:
-
Response erro:
-
Status:
401 Unauthorized
-
Body:
{ "message": "Token not found" }
{ "message": "Expired or invalid token" }
{ "message": "Unauthorized user" }
-
Status:
404 Not Found
-
Body:
{ "message": "Post does not exist" }
-
-
Estas pessoas participaram deste projeto:
Pedro Barreto |
Trybe |
Desenvolvimento do código da api, requisições, validações. | Ideia e banco. |