Aqui você vai encontrar os detalhes de como foi estruturado o desenvolvimento deste projeto a partir deste repositório.
Neste projeto, fui capaz de:
-
Entender o que há por dentro de um token de autenticação;
-
Gerar tokens a partir de informações como login e senha;
-
Autenticar rotas do Express, usando o token JWT;
-
Fazer upload de arquivos em APIs REST;
-
Salvar arquivos no servidor através de uma API REST;
-
Consultar arquivos do servidor através de uma api REST.
-
Testes de integração a ser Realizado.
Foi desenvolvido o app utilizando a arquitetura MSC!
Neste novo projeto foi possível fazer o cadastro e login de pessoas usuárias, onde apenas essas pessoas poderão acessar, modificar e deletar as receitas que cadastrou.
Foi desenvolvido todas as camadas da aplicação (Models, Service e Controllers) a partir do código no projeto cookmaster.
Foi possível realizar as operações básicas que se pode fazer em um determinado banco de dados: Criação, Leitura, Atualização e Exclusão (ou CRUD
, para as pessoas mais íntimas 😜).
Para realizar qualquer tipo de alteração no banco de dados (como cadastro, edição ou exclusão de receitas) foi necessário autenticar-se. Além disso, as pessoas usuárias podem ser clientes ou administradores. Pessoas clientes apenas poderão disparar ações nas receitas que ele mesmo criou. Já uma pessoa administradora pode disparar qualquer ação em qualquer receita.
A autenticação foi feita via JWT
.
O código para cadastro de pessoas usuárias foi criado utilizando os conhecimentos adquiridos durante os estudos no bloco.
Foi possível adicionar uma imagem à uma receita, utilizando o upload de arquivos fornecido pelo multer
.
- Não tem front-end neste projeto, portanto não a visualização, mas apenas as funcionalidades e organização do código testado via App Insomnia.
- O projeto roda na porta 3000;
- Clone o repositório
-
git clone https://github.com/tryber/sd-0x-cookmaster.git
. -
git clone git@github.com:Paulynho-lima/Projeto-Cookmaster.git
-
Entre na pasta do repositório que você acabou de clonar:
cd sd-0x-cookmaster
cd Projeto-Cookmaster
- Instale as dependências [Caso existam]
npm install
- Rode o projeto
npm start
- Para executar os testes
npm test
para rodar todos os testesnpm test users.test.js
para rodar um teste específico
O avaliador não consegue ler as informações que estão no local (localhost). Portanto, para realizar a conexão com o banco, utilize os seguintes parâmetros:
require("dotenv").config();
const MONGO_DB_URL = `mongodb://${
process.env.HOST || "mongodb"
}:27017/Cookmaster`;
const DB_NAME = "Cookmaster";
Além disso, renomeie o arquivo .env.dev
para .env
.
Com essas configurações, enquanto estiver na máquina local, o banco será executado normalmente via localhost (possibilitando os testes via npm test
).
Como o arquivo .env
não será enviado para o GitHub (não se preocupe com isso, pois já está configurado no .gitignore
), o avaliador não executará o banco via localhost e realizará a avaliação corretamente.
O banco tem duas coleções: usuários e receitas.
A coleção de usuários tem o seguinte nome: users
.
Os campos da coleção users
tem este formato:
{
"name": "Erick Jacquin",
"email": "erickjacquin@gmail.com",
"password": "12345678",
"role": "user"
}
A resposta do insert que foi retornada após a criação é esta:
{ "_id" : ObjectId("5f46914677df66035f61a355"), "name" : "Erick Jacquin", "email" : "erickjacquin@gmail.com", "password" : "12345678", "role" : "user" }
(O _id será gerado automaticamente pelo mongodb)
A coleção de receitas tem o seguinte nome: recipes
.
Os campos da coleção recipes
tem este formato:
{
"name": "Receita do Jacquin",
"ingredients": "Frango",
"preparation": "10 minutos no forno"
}
A resposta do insert que foi retornada após a criação é esta:
{ "_id" : ObjectId("5f46919477df66035f61a356"), "name" : "string", "ingredients" : "string", "preparation" : "string", "userId" : ObjectId("5f46914677df66035f61a355") }
(O _id será gerado automaticamente pelo mongodb, e o userId será gerado com o id do usuário que criou a receita)
Usamos o ESLint para fazer a análise estática do código.
Este projeto tem as dependências relacionadas ao linter configuradas no arquivos package.json
.
Para poder rodar os ESLint
em um projeto basta executar o comando npm install
dentro do projeto e depois npm run lint
. Se a análise do ESLint
encontrar problemas no seu código, tais problemas serão mostrados no seu terminal. Se não houver problema no seu código, nada será impresso no seu terminal.
-
A rota deve ser (
/users
). -
No banco um usuário precisa ter os campos Email, Senha, Nome e Role.
-
Para criar um usuário através da API, todos os campos são obrigatórios, com exceção do Role.
-
O campo Email deve ser único.
-
Usuários criados através desse endpoint devem ter seu campo Role com o atributo user, ou seja, devem ser usuários comuns, e não admins.
-
O body da requisição deve conter o seguinte formato:
{ "name": "string", "email": "string", "password": "string" }
-
Não use
bcrypt
ou outra biblioteca para encriptar a senha, para que o avaliador funcione corretamente.
Além disso, as seguintes verificações serão feitas:
- [Será validado que o campo "name" é obrigatório]
Se o usuário não tiver o campo "name" o resultado retornado deverá ser conforme exibido abaixo, com um status http 400
:
- [Será validado que o campo "email" é obrigatório]
Se o usuário não tiver o campo "email" o resultado retornado deverá ser conforme exibido abaixo, com um status http 400
:
- [Será validado que não é possível cadastrar usuário com o campo email inválido]
Se o usuário tiver o campo email inválido o resultado retornado deverá ser conforme exibido abaixo, com um status http 400
:
- [Será validado que o campo "senha" é obrigatório]
Se o usuário não tiver o campo "senha" o resultado retornado deverá ser conforme exibido abaixo, com um status http 400
:
- [Será validado que o campo "email" é único]
Se o usuário cadastrar o campo "email" com um email que já existe, o resultado retornado deverá ser conforme exibido abaixo, com um status http 409
:
- [Será validado que é possível cadastrar usuário com sucesso]
Se o usuário for cadastrado com sucesso o resultado retornado deverá ser conforme exibido abaixo, com um status http 201
:
- [Será validado que é possível ao cadastrar usuário, o valor do campo "role" tenha o valor "user"]
Se o usuário for criado com sucesso o resultado retornado deverá ser conforme exibido abaixo, com um status http 201
:
-
A rota deve ser (
/login
). -
A rota deve receber os campos Email e Senha e esses campos devem ser validados no banco de dados.
-
Na configuração do
JWT
não use variáveis de ambientes para não ter conflito com o avaliador. -
Um token
JWT
deve ser gerado e retornado caso haja sucesso no login. No seu payload deve estar presente o id, email e role do usuário. -
O body da requisição deve conter o seguinte formato:
{ "email": "string", "password": "string" }
Além disso, as seguintes verificações serão feitas:
- [Será validado que o campo "email" é obrigatório]
Se o login não tiver o campo "email" o resultado retornado deverá ser conforme exibido abaixo, com um status http 401
:
- [Será validado que o campo "password" é obrigatório]
Se o login não tiver o campo "password" o resultado retornado deverá ser conforme exibido abaixo, com um status http 401
:
- [Será validado que não é possível fazer login com um email inválido]
Se o login tiver o email inválido o resultado retornado deverá ser conforme exibido abaixo, com um status http 401
:
- [Será validado que não é possível fazer login com uma senha inválida]
Se o login tiver a senha inválida o resultado retornado deverá ser conforme exibido abaixo, com um status http 401
:
- [Será validado que é possível fazer login com sucesso]
Se foi feito login com sucesso o resultado retornado deverá ser conforme exibido abaixo, com um status http 200
:
-
A rota deve ser (
/recipes
). -
A receita só pode ser criada caso o usuário esteja logado e o token
JWT
validado. -
No banco, a receita deve ter os campos Nome, Ingredientes, Modo de preparo, URL da imagem e Id do Autor.
-
Nome, ingredientes e modo de preparo devem ser recebidos no corpo da requisição, com o seguinte formato:
{ "name": "string", "ingredients": "string", "preparation": "string" }
-
O campo dos ingredientes pode ser um campo de texto aberto.
-
O campo ID do autor, deve ser preenchido automaticamente com o ID do usuário logado, que deve ser extraído do token JWT.
-
A URL da imagem será preenchida através de outro endpoint
Além disso, as seguintes verificações serão feitas:
- [Será validado que não é possível cadastrar receita sem o campo "name"]
Se a receita não tiver o campo "name" o resultado retornado deverá ser conforme exibido abaixo, com um status http 400
:
- [Será validado que não é possível cadastrar receita sem o campo "ingredients"]
Se a receita não tiver o campo "ingredients" o resultado retornado deverá ser conforme exibido abaixo, com um status http 400
:
- [Será validado que não é possível cadastrar receita sem o campo "preparation"]
Se a receita não tiver o campo "preparation" o resultado retornado deverá ser conforme exibido abaixo, com um status http 400
:
- [Será validado que não é possível cadastrar uma receita com token invalido]
Se a receita não tiver o token válido o resultado retornado deverá ser conforme exibido abaixo, com um status http 401
:
- [Será validado que é possível cadastrar uma receita com sucesso]
O resultado retornado para cadastrar a receita com sucesso deverá ser conforme exibido abaixo, com um status http 201
:
-
A rota deve ser (
/recipes
). -
A rota pode ser acessada por usuários logados ou não
Além disso, as seguintes verificações serão feitas:
- [Será validado que é possível listar todas as receitas sem estar autenticado]
O resultado retornado para listar receitas com sucesso deverá ser conforme exibido abaixo, com um status http 200
:
- [Será validado que é possível listar todas as receitas estando autenticado]
O resultado retornado para listar receitas com sucesso deverá ser conforme exibido abaixo, com um status http 200
:
-
A rota deve ser (
/recipes/:id
). -
A rota pode ser acessada por usuários logados ou não
Além disso, as seguintes verificações serão feitas:
- [Será validado que é possível listar uma receita específica sem estar autenticado]
O resultado retornado para listar uma receita com sucesso deverá ser conforme exibido abaixo, com um status http 200
:
- [Será validado que é possível listar uma receita específica estando autenticado]
O resultado retornado para listar uma receita com sucesso deverá ser conforme exibido abaixo, com um status http 200
:
- [Será validado que não é possível listar uma receita que não existe]
O resultado retornado para listar uma receita que não existe deverá ser conforme exibido abaixo, com um status http 404
:
Crie um arquivo seed.js
na raiz do projeto com uma query do Mongo DB capaz de inserir um usuário na coleção users com os seguintes valores:
{ name: 'admin', email: 'root@email.com', password: 'admin', role: 'admin' }
Obs.: Esse usuário tem o poder de criar, deletar, atualizar ou remover qualquer receita, independente de quem a cadastrou. Isso será solicitado ao longo dos próximos requisitos.
Além disso, as seguintes verificações serão feitas:
- [Será validado que o projeto tem um arquivo de seed, com um comando para inserir um usuário root e verifico que é possível fazer login]
Será validado no arquivo seed.js
existe a query para criar um usuário root
-
A rota deve ser (
/recipes/:id
). -
A receita só pode ser atualizada caso o usuário esteja logado e o token
JWT
validado. -
A receita só pode ser atualizada caso pertença ao usuário logado, ou caso esse usuário seja um admin.
-
O corpo da requisição deve receber o seguinte formato:
{ "name": "string", "ingredients": "string", "preparation": "string" }
Além disso, as seguintes verificações serão feitas:
- [Será validado que não é possível editar receita sem estar autenticado]
O resultado retornado para editar receita sem autenticação deverá ser conforme exibido abaixo, com um status http 401
:
- [Será validado que não é possível editar receita com token inválido]
O resultado retornado para editar receita com token inválido deverá ser conforme exibido abaixo, com um status http 401
:
- [Será validado que é possível editar receita estando autenticado]
O resultado retornado para editar uma receita com sucesso deverá ser conforme exibido abaixo, com um status http 200
:
- [Será validado que é possível editar receita com usuário admin]
O resultado retornado para editar uma receita com sucesso deverá ser conforme exibido abaixo, com um status http 200
:
-
A rota deve ser (
/recipes/:id
). -
A receita só pode ser excluída caso o usuário esteja logado e o token
JWT
validado. -
A receita só pode ser excluída caso pertença ao usuário logado, ou caso o usuário logado seja um admin.
Além disso, as seguintes verificações serão feitas:
- [Será validado que não é possível excluir receita sem estar autenticado]
O resultado retornado para excluir uma receita sem autenticação deverá ser conforme exibido abaixo, com um status http 401
:
- [Será validado que é possível excluir receita estando autenticado]
O resultado retornado para excluir uma receita com sucesso deverá ser conforme exibido abaixo, com um status http 204
:
- [Será validado que é possível excluir receita com usuário admin]
O resultado retornado para excluir uma receita com sucesso deverá ser conforme exibido abaixo, com um status http 204
:
-
A rota deve ser (
/recipes/:id/image/
). -
A imagem deve ser lida do campo
image
. -
O endpoint deve aceitar requisições no formato
multipart/form-data
. -
A receita só pode ser atualizada caso o usuário esteja logado e o token
JWT
validado. -
A receita só pode ser atualizada caso pertença ao usuário logado ou caso o usuário logado seja admin.
-
O upload da imagem deverá ser feito utilizando o
Multer
. -
O nome do arquivo deve ser o ID da receita, e sua extensão
.jpeg
. -
A URL completa para acessar a imagem através da API deve ser gravada no banco de dados, junto com os dados da receita.
Além disso, as seguintes verificações serão feitas:
- [Será validado que é possível enviar foto com usuário autenticado]
O resultado retornado para adicionar uma foto na receita com sucesso deverá ser conforme exibido abaixo, com um status http 200
:
- [Será validado que ao enviar foto, o nome da imagem é alterada para o id da receita]
O resultado retornado para adicionar uma foto na receita com sucesso deverá ser conforme exibido abaixo, com um status http 200
:
- [Será validado que não é possível enviar foto sem estar autenticado]
O resultado retornado para adicionar uma foto na receita com sucesso deverá ser conforme exibido abaixo, com um status http 401
:
- [Será validado que é possível enviar foto com usuário admin]
O resultado retornado para adicionar uma foto na receita com sucesso deverá ser conforme exibido abaixo, com um status http 200
:
- As imagens devem estar disponíveis através da rota
/images/<id-da-receita>.jpeg
na API.
Além disso, as seguintes verificações serão feitas:
- [Será validado que é retornada uma imagem como resposta]
O resultado retornado deverá ser do tipo imagem, com um status http 200
:
11 - Crie testes de integração que cubram no mínimo 30% dos arquivos em src
, com um mínimo de 50 linhas cobertas
-
Os testes de integração devem ser criados na pasta
./src/integration-tests
, essa pasta não pode ser renomeada ou removida; -
O arquivo
change.me.test.js
pode ser alterado, renomeado ou removido; -
Os testes devem ser criados usando o instrumental e boas práticas apresentado nos conteúdos de testes do course;
-
Para rodar os testes, utilize o comando
npm run dev:test
; -
Para visualizar a cobertura, utilize o comando
npm run dev:test:coverage
;
Além disso, as seguintes verificações serão feitas:
- [Será validado que o teste cobre o valor esperado]
Nenhum teste pode ser pulado;
O resultado do percentual total de cobertura deve ser igual ou maior que 30
;
O resultado do numero total de linhas cobertas deve ser igual ou maior que 50
.
-
A rota deve ser (
/users/admin
). -
Só será possível adicionar um admin caso esta ação esteja sendo feita por outro admin, portanto, deve ser validado se há um admin logado.
-
Por padrão, as requisições pra esse endpoint devem adicionar um usuário com a role admin.
-
O corpo da requisição deve ter o seguinte formato:
{ "name": "string", "email": "string", "password": "string" }
Além disso, as seguintes verificações serão feitas:
- [Será validado que não é possível cadastrar um usuário admin, sem estar autenticado como um usuário admin]
Se o usuário admin não é criado com sucesso o resultado retornado deverá ser conforme exibido abaixo, com um status http 403
:
- [Será validado que é possível cadastrar um usuário admin]
Se o usuário admin é criado com sucesso o resultado retornado deverá ser conforme exibido abaixo, com um status http 201
:
13 - Crie testes de integração que cubram no mínimo 60% dos arquivos em src
, com um mínimo de 100 linhas cobertas
-
Os testes de integração devem ser criados na pasta
./src/integration-tests
, essa pasta não pode ser renomeada ou removida; -
O arquivo
change.me.test.js
pode ser alterado, renomeado ou removido; -
Os testes devem ser criados usando o instrumental e boas práticas apresentado nos conteúdos de testes do course;
-
Para rodar os testes, utilize o comando
npm run dev:test
; -
Para visualizar a cobertura, utilize o comando
npm run dev:test:coverage
;
Além disso, as seguintes verificações serão feitas:
- [Será validado que o teste cobre o valor esperado]
Nenhum teste pode ser pulado;
O resultado do percentual total de cobertura deve ser igual ou maior que 60
;
O resultado do numero total de linhas cobertas deve ser igual ou maior que 100
.
14 - Crie testes de integração que cubram no mínimo 90% dos arquivos em src
, com um mínimo de 150 linhas cobertas
-
Os testes de integração devem ser criados na pasta
./src/integration-tests
, essa pasta não pode ser renomeada ou removida; -
O arquivo
change.me.test.js
pode ser alterado, renomeado ou removido; -
Os testes devem ser criados usando o instrumental e boas práticas apresentado nos conteúdos de testes do course;
-
Para rodar os testes, utilize o comando
npm run dev:test
; -
Para visualizar a cobertura, utilize o comando
npm run dev:test:coverage
;
Além disso, as seguintes verificações serão feitas:
- [Será validado que o teste cobre o valor esperado]
Nenhum teste pode ser pulado;
O resultado do percentual total de cobertura deve ser igual ou maior que 90
;
O resultado do numero total de linhas cobertas deve ser igual ou maior que 150
.