Skip to content

jsfoliveira/Project-Blog-Api

Repository files navigation

👩‍💻 Project Blog API

Esse projeto contém uma série de informações sobre o que eu aprendi aqui na Trybe ao longo do curso de desenvolvimento web da Trybe.

🚀Começando

Esse projeto foi proposto pelo curso de desenvolvimento web da Trybe.

Desenvolvimento

Esse projeto foi desenvolvido no bloco de back-end, desenvolvi uma aplicação Node.js usando sequelize para fazer um CRUD de posts. Desenvolver endpoints que foram conectados ao seu banco de dados seguindo os princípios do REST. Para fazer um post, precisei criar um usuário e login. Fiz a autenticação do login usando o token JWT. Criei uma função para verificar o token criado e o secret.

Commits

Os commits foram feitos de acordo com os requisitos finalizados.

Branch

Todo o projeto foi feita na branch 'juliana-oliveira-project-blogs-api', isso por conta da exigência do curso.

Instalação

Antes de realizar o projeto, precisei instalar as dependências usando npm install.

Testes

Os testes usando foram feitos através do comando npm test.

Autores

Esse foi um projeto individual,que desenvolvido somente por Juliana Oliveira.

Ferramentas usadas

Foi usado Visual Studio Code, além do Trello que auxiliou na organização das tarefas.

Framework usado

Nenhum.

Informações Importantes

Antes de começar, seu docker-compose precisa estar na versão 1.29 ou superior.

👣Requisitos

Metodologia usada

No trabalho do desenvolvimento de software a gente sempre tem prazos, muitas vezes os prazos são apertados.
Por outro lado, eu não quero criar algo que não entendo perfeitamente, como também fazer códigos rápidos pode levar a erros que podem demorar muito pra corrigir.
Por isso, usei e sempre uso o método Baby Steps, que é uma estratégia de abordar o desafio passo à passo, defensivamente.
Baby steps é um termo em inglês que quer dizer passos de bebê. Refere-se a fazer as coisas, quaisquer que sejam, devagar, com calma, passo a passo.

Requisitos Obrigatórios

👣Requisito 1 - Crie migrations para as entidades Users, Categories, BlogPosts, PostCategories

  • Esse teste fará uma conexão no banco utilizando a configuração de teste do arquivo src/database/config/config.js;
  • Suas migrations devem estar no diretório correto e respeitar a nomenclatura pedida no requisito;
  • Suas migrations devem respeitar o diagrama de Entidade-Relacionamento e o formato das entidades, como descrito na seção de Diagrama ER e Entidades.
  • Exclua na pasta ./src/database/migrations/, o arquivo remove-me.js.
Os seguintes pontos serão avaliados:
  • [Será validado que é possível fazer um INSERT e um SELECT na tabela Users]

    • O avaliador irá inserir um dado de exemplo na tabela Users;
    • O avaliador irá fazer um select, desse mesmo dado, na tabela Users.
  • [Será validado que é possível fazer um INSERT e um SELECT na tabela Categories]

    • O avaliador irá inserir um dado de exemplo na tabela Categories;
    • O avaliador irá fazer um select, desse mesmo dado, na tabela Categories.
  • [Será validado que, a partir de um INSERT em User, é possível fazer um INSERT e um SELECT na tabela BlogPosts]

    • Dado que BlogPosts possui uma chave estrangeira userId:
      • O avaliador irá inserir um dado de exemplo na tabela Users;
    • Desse modo:
      • O avaliador irá inserir um dado de exemplo na tabela BlogPosts;
      • O avaliador irá fazer um select, desse mesmo dado, na tabela BlogPosts.
  • [Será validado que, a partir de INSERTs em User, Categories e BlogPosts, é possível fazer um INSERT e um SELECT na tabela PostCategories]

    • Dado que PostCategories possui uma chave primária composta de duas chaves estrangeiras, respectivamente, postId, categoryId:
      • O avaliador irá inserir um dado de exemplo na tabela Users;
      • O avaliador irá inserir um dado de exemplo na tabela Categories;
      • O avaliador irá inserir um dado de exemplo na tabela BlogPosts;
    • Desse modo:
      • O avaliador irá inserir um dado de exemplo na tabela PostCategories;
      • O avaliador irá fazer um select, desse mesmo dado, na tabela PostCategories.


👣Requisito 2 - Crie o modelo 'User' em 'src/database/models/user.js' com as propriedades corretas

  • Sua model deve estar no diretório correto e respeitar a nomenclatura pedida no requisito;
  • Sua model deve respeitar o diagrama de Entidade-Relacionamento e o formato das entidades, como descrito na seção de Diagrama ER e Entidades.
Os seguintes pontos serão avaliados:
  • [Será validado que existe o arquivo 'user.js']

  • [Será validado que o modelo possui o nome 'User']

  • [Será validado que o modelo possui a propriedade 'id']

  • [Será validado que o modelo possui a propriedade 'displayName']

  • [Será validado que o modelo possui a propriedade 'email']

  • [Será validado que o modelo possui a propriedade 'password']

  • [Será validado que o modelo possui a propriedade 'image']



👣Requisito 3 - Sua aplicação deve ter o endpoint POST /login

  • O endpoint deve ser acessível através do URL /login;
  • O corpo da requisição deverá seguir o formato abaixo:
    {
      "email": "lewishamilton@gmail.com",
      "password": "123456"
    }
Os seguintes pontos serão avaliados:
  • [Será validado que não é possível fazer login sem todos os campos preenchidos]

    • Se a requisição não tiver todos os campos devidamente preenchidos(não pode haver campos em branco), o resultado retornado deverá ser conforme exibido abaixo, com um status http 400:
    {
      "message": "Some required fields are missing"
    }
  • [Será validado que não é possível fazer login com um usuário que não existe]

    • Se a requisição receber um par de email e password errados/inexistentes, o resultado retornado deverá ser conforme exibido abaixo, com um status http 400:
    {
      "message": "Invalid fields"
    }
  • [Será validado que é possível fazer login com sucesso]

    • Se o login foi feito com sucesso o resultado retornado deverá ser conforme exibido abaixo, com um status http 200:
    {
      "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJwYXlsb2FkIjp7ImlkIjo1LCJkaXNwbGF5TmFtZSI6InVzdWFyaW8gZGUgdGVzdGUiLCJlbWFpbCI6InRlc3RlQGVtYWlsLmNvbSIsImltYWdlIjoibnVsbCJ9LCJpYXQiOjE2MjAyNDQxODcsImV4cCI6MTYyMDY3NjE4N30.Roc4byj6mYakYqd9LTCozU1hd9k_Vw5IWKGL4hcCVG8"
    }

    ⚠️ O token anterior é fictício, seu token deve ser gerado a partir da variável de ambiente JWT_SECRET, do payload da requisição e não deve conter o atributo password em sua construção.



👣Requisito 4 - Sua aplicação deve ter o endpoint POST /user

  • O endpoint deve ser acessível através do URL /user;
  • O endpoint deve ser capaz de adicionar um novo user a sua tabela no banco de dados;
  • 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"
    }
Os seguintes pontos serão avaliados
  • [Será validado que não é possível cadastrar com o campo displayName menor que 8 caracteres]

    • Se a requisição não tiver o campo displayName devidamente preenchido com 8 caracteres ou mais, o resultado retornado deverá ser conforme exibido abaixo, com um status http 400:
    {
      "message": "\"displayName\" length must be at least 8 characters long"
    }
  • [Será validado que não é possível cadastrar com o campo email com formato inválido]

    • Se a requisição não tiver o campo email devidamente preenchido com o formato <prefixo@dominio>, o resultado retornado deverá ser conforme exibido abaixo, com um status http 400:
    {
      "message": "\"email\" must be a valid email"
    }
  • [Será validado que não é possível cadastrar com o campo password menor que 6 caracteres]

    • Se a requisição não tiver o campo password devidamente preenchido com 6 caracteres ou mais, o resultado retornado deverá ser conforme exibido abaixo, com um status http 400:
    {
      "message": "\"password\" length must be at least 6 characters long"
    }
  • [Será validado que não é possível cadastrar com um email já existente]

    • Se a requisição enviar o campo email com um email que já existe, o resultado retornado deverá ser conforme exibido abaixo, com um status http 409:
    {
      "message": "User already registered"
    }
  • [Será validado que é possível cadastrar um pessoa usuária com sucesso]

    • Se o user for criado com sucesso o resultado retornado deverá ser conforme exibido abaixo, com um status http 201:
      {
        "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJwYXlsb2FkIjp7ImlkIjo1LCJkaXNwbGF5TmFtZSI6InVzdWFyaW8gZGUgdGVzdGUiLCJlbWFpbCI6InRlc3RlQGVtYWlsLmNvbSIsImltYWdlIjoibnVsbCJ9LCJpYXQiOjE2MjAyNDQxODcsImV4cCI6MTYyMDY3NjE4N30.Roc4byj6mYakYqd9LTCozU1hd9k_Vw5IWKGL4hcCVG8"
      }

    ⚠️ O token anterior é fictício, seu token deve ser gerado a partir da variável de ambiente JWT_SECRET, do payload da requisição e não deve conter o atributo password em sua construção.



⚠️ Validando token nas requisições

  • Após termos feito o requisito de criação de users e o requisito de login, alguns requisitos abaixo vão precisar desta autenticação prévia, para que seja possível consumir o endpoint;
  • Todo requisito que precisar validar o token terá o símbolo ☝;
  • ✨ Dica: Se é algo que vamos utilizar em mais de uma rota, será que podemos separa-lo em algum lugar que comece com M de middleware? 😜
Os seguintes pontos serão avaliados
  • [Será validado que não é possível fazer uma operação sem o token na requisição]

    • Se o token for inexistente o resultado retornado deverá ser conforme exibido abaixo, com um status http 401:
    {
      "message": "Token not found"
    }
  • [Será validado que não é possível fazer uma operação com o token inválido]

    • Se o token for inválido o resultado retornado deverá ser conforme exibido abaixo, com um status http 401:
    {
      "message": "Expired or invalid token"
    }

👣Requisito 5 - Sua aplicação deve ter o endpoint GET /user

  • ☝ Não esqueça de validar o token neste requisito, como descrito na seção de Validando token nas requisições;
  • O endpoint deve ser acessível através do URL /user;
  • O endpoint deve ser capaz de trazer todos users do banco de dados;
Os seguintes pontos serão avaliados
  • [Será validado o token, como descrito na seção de Validando token nas requisições]

  • [Será validado que é possível listar todos os usuários]

    • Ao listar usuários 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"
      },
    
      /* ... */
    ]


👣Requisito 6 - Sua aplicação deve ter o endpoint GET /user/:id

  • ☝ Não esqueça de validar o token neste requisito, como descrito na seção de Validando token nas requisições;
  • O endpoint deve ser acessível através do URL /user/:id;
  • O endpoint deve ser capaz de trazer o user baseado no id do banco de dados se ele existir;
Os seguintes pontos serão avaliados
  • [Será validado o token, como descrito na seção de Validando token nas requisições]

  • [Será validado que é possível listar um usuário específico com sucesso]

    • 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"
    }
  • [Será validado que não é possível listar um usuário inexistente]

    • Se o usuário for inexistente o resultado retornado deverá ser conforme exibido abaixo, com um status http 404:
    {
      "message": "User does not exist"
    }


👣Requisito 7 - Crie o modelo 'Category' em 'src/database/models/category.js' com as propriedades corretas

  • Sua model deve estar no diretório correto e respeitar a nomenclatura pedida no requisito;
  • Sua model deve respeitar o diagrama de Entidade-Relacionamento e o formato das entidades, como descrito na seção de Diagrama ER e Entidades.
Os seguintes pontos serão avaliados
  • [Será validado que existe o arquivo 'category.js']

  • [Será validado que o modelo possui o nome 'Category']

  • [Será validado que o modelo possui a propriedade 'id']

  • [Será validado que o modelo possui a propriedade 'name']



👣Requisito 8 - Sua aplicação deve ter o endpoint POST /categories

  • ☝ Não esqueça de validar o token neste requisito, como descrito na seção de Validando token nas requisições;
  • O endpoint deve ser acessível através do URL /categories;
  • O endpoint deve ser capaz de adicionar uma nova categoria a sua tabela no banco de dados;
  • O corpo da requisição deverá seguir o formato abaixo:
    {
      "name": "Typescript"
    }
Os seguintes pontos serão avaliados
  • [Será validado o token, como descrito na seção de Validando token nas requisições]

  • [Será validado que não é possível cadastrar uma categoria sem o campo name]

    • Se a requisição não tiver o campo name devidamente preenchidos(não pode haver campo em branco), o resultado retornado deverá ser conforme exibido abaixo, com um status http 400:
    {
      "message": "\"name\" is required"
    }
  • [Será validado que é possível cadastrar uma categoria com sucesso]

    • Se a categoria for criada com sucesso o resultado retornado deverá ser conforme exibido abaixo, com um status http 201:
    {
      "id": 3,
      "name": "Typescript"
    }


👣Requisito 9 - Sua aplicação deve ter o endpoint GET /categories

  • ☝ Não esqueça de validar o token neste requisito, como descrito na seção de Validando token nas requisições;
  • O endpoint deve ser acessível através do URL /categories;
  • O endpoint deve ser capaz de trazer todas categorias do banco de dados;
Os seguintes pontos serão avaliados
  • [Será validado o token, como descrito na seção de Validando token nas requisições]

  • [Será validado que é possível listar todas as categoria com sucesso]

    • Ao listar categorias com sucesso o resultado retornado deverá ser conforme exibido abaixo, com um status http 200:
    [
      {
          "id": 1,
          "name": "Inovação"
      },
      {
          "id": 2,
          "name": "Escola"
      },
    
      /* ... */
    ]


👣Requisito 10 - Crie o modelo 'BlogPost' em 'src/database/models/blogPost.js' com as propriedades e associações corretas

  • Sua model deve estar no diretório correto e respeitar a nomenclatura pedida no requisito;

  • Sua model deve respeitar o diagrama de Entidade-Relacionamento e o formato das entidades, como descrito na seção de Diagrama ER e Entidades;

  • Sua model deve respeitar a associação correta (N:1) com o modelo User;

  • ✨ Dica:

    • Explore como renomear campos no Sequelize;
Os seguintes pontos serão avaliados
  • [Será validado que existe o arquivo 'blogPost.js']

  • [Será validado que o modelo possui o nome 'BlogPost']

  • [Será validado que o modelo possui a propriedade 'id']

  • [Será validado que o modelo possui a propriedade 'title']

  • [Será validado que o modelo possui a propriedade 'content']

  • [Será validado que o modelo possui a propriedade 'userId']

  • [Será validado que o modelo possui a propriedade 'published']

  • [Será validado que o modelo possui a propriedade 'updated']

  • [Será validado que o modelo em 'blogPost.js', define a associação 'belongsTo', com a entidade de nome 'User']

  • [Será validado que o modelo em 'user.js', define a associação 'hasMany', com a entidade de nome 'BlogPost']



👣Requisito 11 - Crie o modelo 'PostCategory' em 'src/database/models/postCategory.js' com as propriedades e associações corretas

  • Sua model deve estar no diretório correto e respeitar a nomenclatura pedida no requisito;
  • Sua model deve respeitar o diagrama de Entidade-Relacionamento e o formato das entidades, como descrito na seção de Diagrama ER e Entidades;
  • Sua model deve respeitar a associação correta (N:N) entre o modelo BlogPost e o modelo Category;
Os seguintes pontos serão avaliados
  • [Será validado que existe o arquivo 'postCategory.js']

  • [Será validado que o modelo possui o nome 'PostCategory']

  • [Será validado que o modelo possui a propriedade 'postId']

  • [Será validado que o modelo possui a propriedade 'categoryId']

  • [Será validado que o modelo em 'postCategory.js', através do(s) modelos(s) de nome(s) 'Category; BlogPost', define a associação 'belongsToMany' respectivamente, com o(s) modelo(s) de nome(s) 'BlogPost, Category']



👣Requisito 13 - Sua aplicação deve ter o endpoint GET /post

  • ☝ Não esqueça de validar o token neste requisito, como descrito na seção de Validando token nas requisições;
  • O endpoint deve ser acessível através do URL /post;
  • O endpoint deve ser capaz de trazer todos os bogs post, user dono dele e as categorias do banco de dados;
Os seguintes pontos serão avaliados
  • [Será validado o token, como descrito na seção de Validando token nas requisições]

  • [Será validado que é possível listar blogpost com sucesso]

    • 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"
          }
        ]
      },
      
      /* ... */
    ]


👣Requisito 14 - Sua aplicação deve ter o endpoint GET /post/:id

  • ☝ Não esqueça de validar o token neste requisito, como descrito na seção de Validando token nas requisições;
  • O endpoint deve ser acessível através do URL /post/:id;
  • O endpoint deve ser capaz de trazer o blog post baseado no id do banco de dados se ele existir;
Os seguintes pontos serão avaliados
  • [Será validado o token, como descrito na seção de Validando token nas requisições]

  • [Será validado que é possível listar um blogpost com sucesso]

    • Ao 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"
          }
      ]
    }
  • [Será validado que não é possível listar um blogpost inexistente]

    • Se o post for inexistente o resultado retornado deverá ser conforme exibido abaixo, com um status http 404:
    {
      "message": "Post does not exist"
    }