Skip to content

API Rest para salvar e criar suas receitas favoritas.

License

Notifications You must be signed in to change notification settings

tiaggofg/recipe-book-api

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

61 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Recipe Book API

Esse é um fork do projeto Zord Recipe API e se trata de uma API CRUD de para salvar e compartilhar receitas.

O fork foi realizado para implementar novas funcionalidades a API, como cadastro de usuários, autenticação e integração com o Chat GPT.

Como utilizar a API?

Para utilizar/testar a API é preciso clonar esse repositório e compilar o projeto utilizando maven. Antes disso é preciso ter o arquivo de configurações recipe-book.properties na pasta resources. Você pode saber mais na seção Arquivo de configuração.

Tendo o arquivo recipe-book.properties preenchido com os dados necessários basta exeuctar o comando abaixo

mvn package

Que um arquivo .jar será gerado na pasta target e poderá ser executado com o seguinte comando

java -jar recipe-book-api.jar

Ressalto que para gerar e executar o arquivo jar é preciso ter o maven assim como o Java versão 11 instalado. Caso tenha dificuldades entre em contato via email que estarei disposto a ajudá-lo.

Arquivo de configuração

As informações referente a acesso a banco de dados e qual porta a aplicação vai subir devem ser preenchidas no arquivo recipe-book.properties na pasta resources. Nessa mesma pasta há um arquivo sample de como as informações devem ser preenchidas. Ressalto que a aplicação não irá subir sem esse arquivo e uma exeção será lançada.

Endpoints Implementados

POST /authenticate

Esse endponint tem a finalidade de um cliente, como um frontend ou outra API, validar se as credenciais do usuário são válidas para assim inciar uma sessão para o mesmo.

O método de autenticação utilizado em todos os endpoints é o basic auth qual consiste no envio do usuário e senha encondados em Base64 no header de cada requisição. Na linguagem Javascript é possível utilizar o método btoa() para encondar strings em base64.

Conforme disposto no RFC 7617 o usuário e a senha devem ser concatenados com : entre eles username:password e posteriormente encondados em base64 para que sejam enviados no header HTTP chamado Authorization cujo valor é a palavra Basic seguido da string em base64. Conforme exemplo abaixo

POST /authenticate
Authorization: Basic <BASE64(username:password)>

Se utilizarmos a função Javascript btoa e passar como argumento username:password, teremos uma string em base64 como output

input: btoa("username:password")
output: dXNlcm5hbWU6cGFzc3dvcmQ=

E essa string que deve ser utilizada nas requisições. No caso de /authenticate

POST /authenticate
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=

Se o usuário e senha forem válidos será retornado um HTTP status 200 (OK). Do contrário, é retornado um HTTP status 401 (Not Authorized) com um response body conforme exemplo abaixo

{
  "timestamp": "1680550301878",
  "status": "401 Unauthorized",
  "error": "Usuário ou senha inválidos!",
  "path": "/authenticate"
}

Conforme mencionado, esse endpoint deve ser utilizado para validar se as credenciais do usuário são válidas. No entanto, é necessário que seja o header Authorization seja enviado em todas as requisições para que sejam aceitas pelo servidor.

POST /user

Endpoint utilizado para realizar o cadastro de um usuário. Esse é o úncio endpoint que não precisa de autenticação.

Para cadastrar um usuário é necessário enviar a seguinte requisição

POST /authenticate
Content-Type: application/json

{
  "email":"heloisa.figueiredo@mail.com",
  "firstName":"Heloisa",
  "lastName":"Figueiredo",
  "password":"UbVw6xDZoT3ESH",
  "phoneNumber":"(43) 98460-8554",
  "username":"heloisa.figueiredo"
}

Que será retornar HTTP status 200 (ok) sinalizando que o cadastro foi realizado com sucesso.

POST /recipe/

Endpoint utilizado para cadastrar uma nova receita no banco de dados. Recebe um request body com exemplo abaixo

{
  "title": "Panquecas americanas",
  "description": "Uma receita clássica e deliciosa para um café da manhã perfeito",
  "ingredients": [
    "1 e 1/2 xícaras de farinha de trigo",
    "3 e 1/2 colheres de chá de fermento em pó",
    "1 colher de chá de sal",
    "1 colher de sopa de açúcar",
    "1 e 1/4 xícaras de leite",
    "1 ovo",
    "3 colheres de sopa de manteiga derretida",
    "Óleo ou manteiga para untar a frigideira"
  ],
  "preparation": [
    "Em uma tigela grande, misture a farinha de trigo, o fermento em pó, o sal e o açúcar.",
    "Em outra tigela, bata o leite, o ovo e a manteiga derretida.",
    "Adicione os ingredientes líquidos aos ingredientes secos e misture bem até obter uma massa homogênea.",
    "Aqueça uma frigideira antiaderente em fogo médio e unte com óleo ou manteiga.",
    "Com uma concha, coloque porções da massa na frigideira, deixando espaço suficiente entre elas.",
    "Cozinhe por cerca de 2 a 3 minutos, ou até que a superfície da panqueca esteja cheia de bolhas e as bordas comecem a se soltar.",
    "Vire a panqueca com uma espátula e cozinhe do outro lado por mais 1 a 2 minutos, ou até que esteja dourada.",
    "Repita o processo com o restante da massa, untando a frigideira a cada vez que fizer uma nova panqueca.",
    "Sirva quente com manteiga, mel, xarope de bordo ou outros acompanhamentos de sua preferência!"
  ]
}

E retorna um response body com o objeto criado e com o id gerado

{
  "title": "Bolo de chocolate",
  "description": "Bolo de chocolate caseiro",
  "ingredients": [
    "ovo",
    "chocolate"
  ],
  "likes": [],
  "comments": []
}

GET /recipe/

Esse endpoint retorna todas as receitas cadastradas no banco de dados conforme modelo abaixo. Retorna também HTTP status OK.

[
  {
    "title": "Feijoada",
    "description": "Feijoada deliciosa para o fim de semana",
    "ingredients": [
      "Feijão",
      "Bacon",
      "Calabresa",
      "Água",
      "Sal",
      "Alho",
      "Cebola",
      "Folhas de Louro"
    ],
    "likes": [
      789,
      510
    ],
    "comments": [
      {
        "comment": "Excelente receita!"
      }
    ]
  },
  {
    "title": "Pão com banana e queijo",
    "description": "Receita deliciosa para um café da manhã mais saudável",
    "ingredients": [
      "1 Banana",
      "2 Fatias de pães",
      "2 Fatias de queijo",
      "Requeijão"
    ],
    "likes": [
      759,
      7596546,
      7596
    ],
    "comments": []
  },
  {
    "title": "Bolo de chocolate",
    "description": "Bolo de chocolate caseiro",
    "ingredients": [
      "ovo",
      "chocolate"
    ],
    "likes": [],
    "comments": [
      {
        "comment": "Topzera!"
      }
    ]
  }
]

GET /recipe/ingredient

Esse endpoint retorna uma lista de receitas que contém o ingrediente passado como parâmetro de consulta na requisição. Por exemplo, a request localhost:8080/recipe/ingredient?ingredient=Banana irá retornar uma array de receitas que contém o ingrediente Banana e o HTTP status 200

[
  {
    "title": "Pão com banana e queijo",
    "description": "Receita deliciosa para um café da manhã mais saudável",
    "ingredients": [
      "1 Banana",
      "2 Fatias de pães",
      "2 Fatias de queijo",
      "Requeijão"
    ],
    "likes": [
      759,
      7596546,
      7596
    ],
    "comments": []
  }
]

Caso a array retornada seja vazia, um erro padrão juntamente com o HTTP status Not Found (404) é retornado.

Por exemplo, a request localhost:8080/recipe/ingredients?ingredients=banana irá retornar um response body como abaixo, pois a consulta realizada no banco de dados é case sensitive

{
  "timestamp": "1671233843297",
  "status": "404 Not Found",
  "error": "Nenhuma receita encontada!",
  "path": "/recipe/ingredient"
}

GET /recipe/search

Assim como o endpoint acima, esse também realiza buscas e retorna uma array de receitas a partir de um parâmetro de consulta. Todavia, a consulta é realizada tanto no título quanto na descrição da receita.

Por exemplo, a requisção localhost:8080/recipe/search?search=deliciosa irá retornar todas as receitas que contém a palavra deleciosa no título ou na descrição da receita

[
  {
    "title": "Feijoada",
    "description": "Feijoada deliciosa para o fim de semana",
    "ingredients": [
      "Feijão",
      "Bacon",
      "Calabresa",
      "Água",
      "Sal",
      "Alho",
      "Cebola",
      "Folhas de Louro"
    ],
    "likes": [
      789,
      510
    ],
    "comments": [
      {
        "comment": "Excelente receita!"
      }
    ]
  },
  {
    "title": "Pão com banana e queijo",
    "description": "Receita deliciosa para um café da manhã mais saudável",
    "ingredients": [
      "1 Banana",
      "2 Fatias de pães",
      "2 Fatias de queijo",
      "Requeijão"
    ],
    "likes": [
      759,
      7596546,
      7596
    ],
    "comments": []
  }
]

Vale ressaltar que as receitas retornadas estarão ordenadas de forma alfabética crescente a partir do título. Esse endpoint também retorna um erro padrão e um HTTP status 404 caso não seja encontrado nenhuma receita com o parâmetro de consulta passado na URI.

GET /recipe/{id}

Esse endpoint retorna uma única receita caso o id passado na URI exista. Por exemplo, a request localhost:8080/recipe/639c7d79bf89243463a2cda5 irá retornar a receita que contém o id 639c7d79bf89243463a2cda5, como exemplo abaixo, e o HTTP status 200

{
  "title": "Feijoada",
  "description": "Feijoada deliciosa para o fim de semana",
  "ingredients": [
    "Feijão",
    "Bacon",
    "Calabresa",
    "Água",
    "Sal",
    "Alho",
    "Cebola",
    "Folhas de Louro"
  ],
  "likes": [
    789,
    510
  ],
  "comments": [
    {
      "comment": "Excelente receita!"
    }
  ]
}

Caso não seja encontrado uma receita com o id fornecido, um erro padrão é retornado asism como o HTTP status 404

{
  "timestamp": "1671237132883",
  "status": "404 Not Found",
  "error": "Receita id: 639c7d79bf89243463a2cda5asdfa não encontrada!",
  "path": "/recipe/639c7d79bf89243463a2cda5asdfa"
}

PUT /recipe/{id}

Esse endpoint atualiza a receita que tem o id passado URI. Os dados dessa receita são alterados para aqueles passados no request body.

Por exemplo, a requisição PUT localhost:8080/recipe/639cb6ffe478d8453d857150 com o request body abaixo

{
  "title": "Bolo de chocolate",
  "description": "Bolo de chocolate caseiro",
  "ingredients": [
    "ovo",
    "chocolate",
    "açucar",
    "farinha"
  ],
  "likes": [],
  "comments": [
    {
      "comment": "Topzera!"
    }
  ]
}

Irá retornar o HTTP status No Content (204) e terá atualizado o a receita com o id 639cb6ffe478d8453d857150. Caso não exista uma receita com o id passado na URI, então um erro padrão e um HTTP status 404 são retornados

{
  "timestamp": "1671237774339",
  "status": "404 Not Found",
  "error": "Não foi possível atualizar a receita. Id: 639cb6ffe478d8453asdfasd857150 inexistente!",
  "path": "/recipe/639cb6ffe478d8453asdfasd857150"
}

DELETE /recipe/{id}

Endpoint utilizado para excluir uma receita do banco de dados. Caso a receita contenha algum comentário, esses também são excluídos do banco de dados. Pois os comentários são salvos em uma collection separada e uma cópia de cada comentário é agregada às receitas. Após excluir as receitas e os comentários agregados a ela, é retornado um HTTP status 204.

Se não for encontrado nenhum usuário com o id passado na URI, será retornado um HTTP status 404 e um erro padrão como abaixo

{
  "timestamp": "1671238204203",
  "status": "404 Not Found",
  "error": "Receita id: 639c7cfcbf89243463a2acda4sdfa não encontrada!",
  "path": "/recipe/639c7cfcbf89243463a2acda4sdfa"
}

POST /recipe/{id}/like/{userId}

Esse endpoint adiciona o userId passado na URI a uma lista de ids de usuários que deram like na receita que contém o id também passado na URi. Retorna HTTP status 201, assim como a receita com a lista de likes atualizada.

Por exemplo, a request localhost:8080/recipe/639cb6ffe478d8453d857150/153 irá retornar

{
  "title": "Bolo de chocolate",
  "description": "Bolo de chocolate caseiro",
  "ingredients": [
    "ovo",
    "chocolate",
    "açucar",
    "farinha"
  ],
  "likes": [
    153
  ],
  "comments": [
    {
      "comment": "Topzera!"
    }
  ]
}

Na aplicação, o userId foi tipado com a Wrapper Class Integer. Ou seja, o userId passado na URI será parseado e caso ocorra algum problema, um erro padrão é retornado no corpo da resposta assim como um HTTP status 400 como abaixo

{
  "timestamp": "1671239106029",
  "status": "400 Bad Request",
  "error": "Id inválido!",
  "path": "/recipe/639cb6ffe478d8453d857150/like/153asd"
}

E caso não seja encontrado nenhuma receita com o id passado na URI, também é retornado um erro padrão com o HTTP status 404, assim como nos outros endpoints. Caso o userId informado na URI já esteja presente na lista de likes da receita, também é retornado um erro padrão como o exemplo abaixo e um HTTP status Conflict (409).

{
  "timestamp": "1671408098079",
  "status": "409 Conflict",
  "error": "Usuário id: 153 já curtiu a receita id: 639cb6ffe478d8453d857150!",
  "path": "/recipe/639cb6ffe478d8453d857150/like/153"
}

DELETE /recipe/{id}/like/{userId}

Endpoint utilizado para dar deslike em uma receita. Em outras palavras, o recurso remove o userId passado na URI da lista de likes da receita que contiver o id passado na URI.

Por exemplo, a request localhost:8080/recipe/639cb6ffe478d8453d857150/153 irá deletar da lista de likes da receita id 639cb6ffe478d8453d857150 o userId 153 e retornar o HTTP status 204.

Caso o userId não exista ou caso a receita não exista, a API retorna um erro padrão com HTTP status 404.

{
  "timestamp": "1671407997957",
  "status": "404 Not Found",
  "error": "O usuário id: 789 não curtiu a receita id: 639c7d79bf89243463a2cda5!",
  "path": "/recipe/639c7d79bf89243463a2cda5/like/789"
}

POST /recipe/{id}/comment

Utilizado para adicionar um comentário a uma receita. Assim como nos outros edpoints, também retorna um erro padrão e HTTP status 404 caso o id da receita não seja encontarado. No request body, é preciso ser informado um JSON contendo o comentário que será inserido na receita.

Por exemplo a requisição localhost:8080/recipe/639c7dfbbf89243463a2cda6/comment com o request body abaixo

{
  "comment": "Bom demais!"
}

Irá incluir um comentário na receita id 639c7dfbbf89243463a2cda6 e irá retornar no corpo da resposta o comentário com um id gerado pelo mongodb

{
  "comment": "Bom demais!"
}

Como já mencionado anteriormente, a receita é salva em uma collection separada da recieta no banco de dados e uma cópia é adicionada a array de comentários da receita.

PUT /recipe/{id}/comment/{commentId}

Utilizado para atualizar um comentário. Também retorna um erro padrão no corpo da resposta e um HTTP status 404 caso o id e o commentId passados na URI não existam.

No corpo da request é passado o comentário atualizado e após a atualização, é retornado um HTTP status 204. Por exemplo, a request localhost:8080\recipe\639c7dfbbf89243463a2cda6\comment\639fab63b98c514ab6363b96 com request body

{
  "comment": "Topzera"
}

Irá atualizar o comentário id 639fab63b98c514ab6363b96 da receita id 639c7dfbbf89243463a2cda6 para Topzera. E retornar HTTP status 404 após isso.

DELETE /recipe/{id}/comment/{commentId}

Utilizado para deletar um comentário de uma receita e se tudo der certo, um HTTP status 204 é retornado.

Caso o id da receita ou o commentId não existam, também retorna um erro padrão e um HTTP status 404.

Tecnologias utilizadas

  • Java versão 11
  • Maven versão 3.8.6
  • MongoDB versão 6.0
  • Javalin versão 5.2

About

API Rest para salvar e criar suas receitas favoritas.

Topics

Resources

License

Stars

Watchers

Forks