Skip to content

Project developed with Node.js, Sequelize and JWT to create a RESTful API focused on content production for a blog

Notifications You must be signed in to change notification settings

allysonbogo/project-blogs-api

Repository files navigation

Project Blogs API

📃 Sobre

O projeto consolida a utilização das ferramentas Node.js, Sequelize e JWT (JSON Web Token) para a criação de uma API RESTful com CRUD completo e banco de dados, focada na produção de conteúdo para um blog.

Este projeto integra um sistema de autenticação de pessoas usuárias utilizando JWT (JSON Web Token), permitindo que apenas pessoas usuárias autenticadas possam criar, editar e pesquisar posts no blog.

👨‍💻 Habilidades desenvolvidas

  • Node.js
  • Sequelize
  • Construção de uma API CRUD e banco de dados
  • Sistema de autenticação utilizando JWT (JSON Web Token)

🛠️ Ferramentas Utilizadas

  • Node.js
  • Sequelize
  • JWT (JSON Web Token)

⚙️ Como Executar

⚠️   É necessário ter o Docker instalado para executar este projeto

Passo a passo
  1. Clone o repositório em uma pasta de preferência
git clone git@github.com:allysonbogo/project-blogs-api.git
  1. Entre na pasta raíz do projeto e instale todas as dependências
npm install
  1. Para rodar o projeto é necessário executar o comando abaixo no diretório raiz do projeto. Isso fará com que os containers docker sejam orquestrados e a aplicação esteja disponível
docker-compose up -d
  1. O comando abaixo irá criar o bando de dados, versionar o schema do banco utilizando as migrations e popular o banco com uso dos seeders
npm run populate
  1. Para iniciar o servidor com live-reload, digite o comando abaixo
npm run dev
  1. Para visualização da interface da API podem ser utilizados o Thunder Client, Postman, Insomnia ou alguma outra ferramenta de sua preferência

📚 Documentação (endpoints)

👤 Login

Rotas
Método Funcionalidade URL
POST Realiza o login de uma pessoa usuária cadastrada http://localhost:3001/login
A estrutura do body da requisição deverá seguir o padrão abaixo:
{
  "email": "lewishamilton@gmail.com",
  "password": "123456"
}
A resposta da requisição é a seguinte com status 200:
{
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJwYXlsb2FkIjp7ImlkIjo1LCJkaXNwbGF5TmFtZSI6InVzdWFyaW8gZGUgdGVzdGUiLCJlbWFpbCI6InRlc3RlQGVtYWlsLmNvbSIsImltYWdlIjoibnVsbCJ9LCJpYXQiOjE2MjAyNDQxODcsImV4cCI6MTYyMDY3NjE4N30.Roc4byj6mYakYqd9LTCozU1hd9k_Vw5IWKGL4hcCVG8"
}

⚠️   O token acima é fictício, o token verdadeiro é gerado a partir da ferramenta JWT (JSON Web Token), utilizando uma palavra-passe e um payload secretos

A requisição irá falhar nos seguintes casos: - A rota retorna um erro 400 { "message": "Some required fields are missing" }, caso a requisição não tenha todos os campos devidamente preenchidos;
- A rota retorna um erro 400 { "message": "Invalid fields" }, caso a requisição receba um par de email e password errados ou inexistentes;

🪙 Token

Autenticação

⚠️   Após o login de uma pessoa usuária cadastrada, é gerado um token válido por 15 minutos, o qual será autenticado em todas as rotas a seguir, exceto na rota de cadastro de uma pessoa usuária

As requisições irão falhar nos seguintes casos: - É disparado o erro 401 { "message": "Token not found" }, ao fazer uma operação sem um token;
- É disparado o erro 401 { "message": "Expired or invalid token" }, ao fazer uma operação com um token expirado ou inválido;

🖥️ User

Rotas
Método Funcionalidade URL
POST Realiza o cadastro de uma pessoa usuária http://localhost:3001/user
A estrutura do body da requisição deverá seguir o padrão 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
}
Para o cadastro de uma pessoa usuária não é necessário estar autenticado no sistema. Após o cadastro, todas as outras requisições exigem um token de autenticação. A resposta da requisição é a seguinte com status 201:
{
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJwYXlsb2FkIjp7ImlkIjo1LCJkaXNwbGF5TmFtZSI6InVzdWFyaW8gZGUgdGVzdGUiLCJlbWFpbCI6InRlc3RlQGVtYWlsLmNvbSIsImltYWdlIjoibnVsbCJ9LCJpYXQiOjE2MjAyNDQxODcsImV4cCI6MTYyMDY3NjE4N30.Roc4byj6mYakYqd9LTCozU1hd9k_Vw5IWKGL4hcCVG8"
}

⚠️   O token acima é fictício, o token verdadeiro é gerado a partir da ferramenta JWT (JSON Web Token), utilizando uma palavra-passe e um payload secretos

A requisição irá falhar nos seguintes casos: - A rota retorna um erro 400 { "message": "\"displayName\" length must be at least 8 characters long" }, caso a requisição não receba o campo displayName devidamente preenchido com pelo menos 8 caracteres;
- A rota retorna um erro 400 { "message": "\"email\" must be a valid email" }, caso a requisição não receba o campo email com formato válido;
- A rota retorna um erro 400 { "message": "\"password\" length must be at least 6 characters long" }, caso a requisição não receba o campo password devidamente preenchido com pelo menos 6 caracteres;
- A rota retorna um erro 409 { "message": "User already registered" }, caso o campo email já esteja cadastrado no banco de dados;

Método Funcionalidade URL
GET Retorna uma lista de pessoas usuárias http://localhost:3001/user
A resposta da requisição é a seguinte com status 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"
  },
  ...
]

Método Funcionalidade URL
GET Retorna uma pessoa usuária a partir do id http://localhost:3001/user/:id
A resposta da requisição é a seguinte com status 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"
  }
A requisição irá falhar nos seguintes casos: - É disparado o erro 404 { message: "User does not exist" }, caso a pessoa usuária não esteja cadastrada no banco de dados;

Método Funcionalidade URL
DELETE Deleta uma pessoa usuária a partir do token de autenticação http://localhost:3001/user/me
  • A resposta da requisição é 204 e sem body em caso de sucesso

🔖 Categories

Rotas
Método Funcionalidade URL
POST Realiza o cadastro de uma categoria http://localhost:3001/categories
A estrutura do body da requisição deverá seguir o padrão abaixo:
{
  "name": "Typescript"
}
A resposta da requisição é a seguinte com status 201:
{
  "id": 3,
  "name": "Typescript"
}
A requisição irá falhar nos seguintes casos: - A rota retorna um erro 400 { "message": "\"name\" is required" }, caso a requisição não receba o campo name devidamente preenchido;

Método Funcionalidade URL
GET Retorna uma lista de categorias http://localhost:3001/categories
A resposta da requisição é a seguinte com status 200:
[
  {
      "id": 1,
      "name": "Inovação"
  },
  {
      "id": 2,
      "name": "Escola"
  },
  ...
]

📰 Post

Rotas
Método Funcionalidade URL
POST Realiza o cadastro de um post http://localhost:3001/post
A estrutura do body da requisição deverá seguir o padrão abaixo:
{
  "title": "Latest updates, August 1st",
  "content": "The whole text for the blog post goes here in this key",
  "categoryIds": [1, 2]
}
A resposta da requisição é a seguinte com status 201:
{
  "id": 3,
  "title": "Latest updates, August 1st",
  "content": "The whole text for the blog post goes here in this key",
  "userId": 1,
  "updated": "2023-06-16T10:00:01.196Z",
  "published": "2023-06-16T10:00:01.196Z"
}
A requisição irá falhar nos seguintes casos: - A rota retorna um erro 400 { "message": "Some required fields are missing" }, caso todos os campos não estejam devidamente preenchidos;
- A rota retorna um erro 400 { "message": "one or more \"categoryIds\" not found" }, caso o campo categoryIds não esteja devidamente preenchido com um array contendo apenas categorias existentes no banco de dados;

Método Funcionalidade URL
GET Retorna uma lista de posts http://localhost:3001/post
A resposta da requisição é a seguinte com status 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"
      }
    ]
  },
  ...
]

Método Funcionalidade URL
GET Retorna um post a partir do id http://localhost:3001/post/:id
A resposta da requisição é a seguinte com status 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"
      }
  ]
}
A requisição irá falhar nos seguintes casos: - É disparado o erro 404 { message: "Post does not exist" }, caso o post não esteja cadastrado no banco de dados;

Método Funcionalidade URL
PUT Atualiza um post a partir do id http://localhost:3001/post/:id
A estrutura do body da requisição deverá seguir o padrão abaixo:
{
  "title": "Latest updates, August 1st",
  "content": "The whole text for the blog post goes here in this key"
}
A resposta da requisição é a seguinte com status 200:
{
  "id": 3,
  "title": "Latest updates, August 1st",
  "content": "The whole text for the blog post goes here in this key",
  "userId": 1,
  "published": "2022-05-18T18:00:01.000Z",
  "updated": "2022-05-18T18:07:32.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,
      "name": "Escola"
    }
  ]
}
A requisição irá falhar nos seguintes casos: - A rota retorna um erro 401 { "message": "Unauthorized user" }, caso o post editado não tenha sido criado pela pessoa usuária autenticada;
- A rota retorna um erro 400 { "message": "Some required fields are missing" }, caso todos os campos não estejam devidamente preenchidos;
- A rota retorna um erro 404 { message: "Post does not exist" }, caso o post não esteja cadastrado no banco de dados;

Método Funcionalidade URL
DELETE Deleta um post a partir do id http://localhost:3001/post/:id
  • A resposta da requisição é 204 e sem body em caso de sucesso
A requisição irá falhar nos seguintes casos: - A rota retorna um erro 401 { "message": "Unauthorized user" }, caso o post deletado não tenha sido criado pela pessoa usuária autenticada;
- É disparado o erro 404 { "message": "Post does not exist" }, caso o post não esteja cadastrado no banco de dados;

Método Funcionalidade URL
GET Retorna uma lista de posts de acordo com o termo de pesquisa http://localhost:3001/post/search?q=searchTerm
A estrutura da URL deverá seguir o padrão abaixo:
/talker/search?q=vamos
O termo de pesquisa pode ser referente ao title ou content do post. A resposta da requisição é a seguinte com status 200:
[
  {
    "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"
      }
    ]
  }
]
Caso o termo de pesquisa não seja informado ou esteja vazio, o endpoint deverá retornar o status 200 e um array com todos os posts cadastrados:
[
  {
    "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 nenhum post satisfaça a busca, o endpoint deve retornar o status 200 e um array vazio. Exemplo: []

README inspired by Italo Amaral

About

Project developed with Node.js, Sequelize and JWT to create a RESTful API focused on content production for a blog

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published