API Catálogo-Produtos

API para catálogo de produtos.

📜 Sumário

  1. Detalhes do projeto
  2. Tecnologias usadas
  3. Para rodar o projeto
  4. Documentação
  5. Autor

1. 🔍 Detalhes do projeto

A API Catálogo-Produtos tem como objetivo persistir dados para gerenciamento de um catálogo de produtos. Foi realizado para um teste de um estágio.

Cenário:

  • Sistema permite o cadastro de usuário, com validação de informações;
  • Sistema recupera e armazena, caso a tabela de produtos esteja vazia, os produtos da API externa: https://dummyjson.com/products/category/smartphones e https://dummyjson.com/products/category/laptops
  • Sistema permite apenas as requisições de cadastro de usuário e login sem autenticação por meio de JWT;
  • Com usuário logado, o sistema permite a criação, listagem, detalhamento, edição e deleção de produtos;
  • Sistema armazena em cache (Redis) o resultado das buscas de listagem e detalhamento de produtos;

2. 💻 Tecnologias usadas

Languages, Frameworks & Librarys:
Java SpringBoot Hibernate JSON JWT

Tests:
Insomnia JUnit

Cache:
Redis

Database:
PostgreSQL

IDE:
Intellij

3. 🔌 Para rodar o projeto

  1. Instale as dependências necessárias com o Maven para rodar a API (relacionadas no pom.xml):

    mvn dependency:copy-dependencies
    
  2. A API utiliza o PostgreSQL como banco de dados e o Redis como cache, então se faz necessário que você verifique se o arquivo docker-compose.yaml não possui confronto de portas com as existentes no sistema local. Para criar um container com os servidores basta rodar o comando abaixo:

    docker compose up -d
    
  3. Se alguma configuração no arquivo docker-compose.yaml foi alterada, verifique as propriedades de conexão com o banco de dados e o cache no arquivo application.properties:

    spring.datasource.url=jdbc:jdbc:postgresql://localhost:{porta}/{nome_db}
    spring.datasource.username={username}
    spring.datasource.password={password}
    
    redis.host=localhost
    redis.port={porta}
    
  4. Rode a aplicação que o sistema já irá criar as tabelas e popular a tabela produtos automaticamente, deixando-as prontas para uso. Por padrão, a aplicação rodará na porta 8080.

  5. Você precisará de uma ferramenta de teste de requisições como o Insomnia ou utilizar o Swagger-Ui, devendo seguir as orientações da documentação abaixo para utilizar a API.

  6. Você também pode usar o front-end desenvolvido para teste desta api: Front-end

  7. Você pode rodar os testes automatizados criados com JUnit, caso queira (mais testes em desenvolvimento).

4. 🔌 Documentação

Endpoints

Login - Autenticação de usuário

POST users/login

Logar com um usuário por meio de username e password. Retorna um token JWT para ser utilizado nas requisições.

Request

Nome Obrigatório Tipo Descrição
username sim string E-mail do usuário
password sim string Senha do usuário

NOTA: Não é necessário enviar Token JWT via Authorization Header.

Exemplo de requisição:

{
    "username": "fulaninho",
    "password": "password"
}

Response

Sucesso

{
    "type": "Bearer",
    "token": "abcdefghijklmno.abcdefghijklmnopqrstuvwxyz.abcdefghijklmnop"
}

status: 201

Erro comum

{
   "statusCode": "UNAUTHORIZED",
   "message": "Bad credentials",
   "dateTime": "02-12-2023 19:00:24"
}

User - Criação de um novo usuário, edição de um usuário, detalhamento de um usuário e deleção do usuário

POST user

Criar um usuário para poder utilizar a API.

Request

Nome Obrigatório Tipo Descrição
name sim string Nome do usuário
username sim string Username do usuário
email sim string Email do usuário
password sim string Senha do usuário

NOTA: Não é necessário enviar Token JWT via Authorization Header.

Exemplo de requisição:

{
    "name": "Fulano de Ciclano",
    "username": "fulaninho",
    "email": "fulano@email.com",
    "password": "password"
}

Response

Sucesso

{
    "id": "753ae2c4-edd0-4d4c-8f7f-1cffa5eea4f6",
    "name": "Fulano de Ciclano",
    "username": "fulaninho",
    "email": "fulano@email.com"
}

status: 201

Erro comum

{
   "statusCode": "BAD_REQUEST",
   "message": "Email already in use",
   "dateTime": "29-11-2023 21:31:14"
}
PUT user

Editar um usuário. Apenas nome e email podem ser alterados, mas nenhum dos dois é obrigatório.

Request

Nome Obrigatório Tipo Descrição
name não string Nome do usuário
email não string Email do usuário

NOTA: É necessário enviar Token JWT via Authorization Header.

Exemplo de requisição:

{
   "name": "Fulano Editado",
   "email": "fulano.editado@email.com",
   "password": "password"
}

Response

Sucesso

{
   "id": "753ae2c4-edd0-4d4c-8f7f-1cffa5eea4f6",
   "name": "Fulano de Ciclano Editado",
   "username": "fulaninho",
   "email": "fulano.editado@email.com"
}

status: 200

Erros comuns

{
   "statusCode": "BAD REQUEST",
   "message": "User not found",
   "dateTime": "02-12-2023 19:21:55"
}
{
   "statusCode": "UNAUTHORIZED",
   "message": "Invalid token",
   "dateTime": "02-12-2023 19:21:55"
}
{
   "statusCode": "BAD_REQUEST",
   "message": "Email already in use",
   "dateTime": "29-11-2023 21:31:14"
}
GET user

Detalhar um usuário. Não é necessário enviar qualquer dado na requisição.

NOTA: É necessário enviar Token JWT via Authorization Header.

Response

Sucesso

{
   "id": "753ae2c4-edd0-4d4c-8f7f-1cffa5eea4f6",
   "name": "Fulano de Ciclano",
   "username": "fulaninho",
   "email": "fulano@email.com"
}

status: 200

Erros comuns

{
   "statusCode": "BAD REQUEST",
   "message": "User not found",
   "dateTime": "02-12-2023 19:21:55"
}
{
   "statusCode": "UNAUTHORIZED",
   "message": "Invalid token",
   "dateTime": "02-12-2023 19:21:55"
}
DELETE user

Deletar o usuario. Não é necessário enviar qualquer dado na requisição.

NOTA: É necessário enviar Token JWT via Authorization Header.

Response

Sucesso
no body returned for response
status: 204

Erro comum

{
   "statusCode": "BAD REQUEST",
   "message": "User not found",
   "dateTime": "02-12-2023 19:21:55"
}
{
   "statusCode": "UNAUTHORIZED",
   "message": "Invalid token",
   "dateTime": "02-12-2023 19:21:55"
}

Products - Criação de um novo produto, edição de um produto, listagem de produtos, deleção de um produto e detalhamento de um produto.

POST products

Criar um filme.

Request

Nome Obrigatório Tipo Descrição
title sim string Nome do produto
description sim string Descrição do produto
price sim bigdecimal Preço do produto
stock sim integer Estoque do produto
brand sim string Marca do produto
category sim string Categoria do produto
image não string URL da imagem do produto

NOTA: É necessário enviar Token JWT via Authorization Header.

Exemplo de requisição:

{
   "title": "Iphone 12",
   "description": "Qualquer coisa",
   "price": 2499.99,
   "stock": 25,
   "brand": "Apple",
   "category": "smartphones"
}

Response

Sucesso

{
   "id": "590ced29-016a-4c7e-bf35-818e2bed8539",
   "title": "Iphone 12",
   "description": "Qualquer coisa",
   "price": 2499.99,
   "stock": 25,
   "brand": "Apple",
   "category": "SMARTPHONES",
   "image": null
}

status: 201

Erros comuns

{
   "statusCode": "BAD_REQUEST",
   "message": "Product already exist",
   "dateTime": "02-12-2023 19:39:38"
}
{
   "statusCode": "BAD_REQUEST",
   "message": "Invalid category. Categories available: 'smartphones', 'laptops'",
   "dateTime": "02-12-2023 19:59:50"
}
{
   "statusCode": "UNAUTHORIZED",
   "message": "Invalid token",
   "dateTime": "02-12-2023 19:37:36"
}
GET products

Listar produtos. É possível passar um parâmetro query para buscar por categoria.

Request

Nome Obrigatório Tipo Descrição
category não string Enviado via query na url

NOTA: É necessário enviar Token JWT via Authorization Header.

Exemplo de requisição:

http://localhost:8080/products?category=laptop

Response

Sucesso

[
   {
      "id": "201c2e19-a6e1-4036-8678-692b50d5b246",
      "title": "MacBook Pro",
      "description": "MacBook Pro 2021 with mini-LED display may launch between September, November",
      "price": 6996.00,
      "stock": 83,
      "brand": "Apple",
      "category": "LAPTOPS",
      "image": "https://i.dummyjson.com/data/products/6/1.png"
   },
   {
      "id": "e9812960-678b-4fad-9756-9b936aaed303",
      "title": "Samsung Galaxy Book",
      "description": "Samsung Galaxy Book S (2020) Laptop With Intel Lakefield Chip, 8GB of RAM Launched",
      "price": 5996.00,
      "stock": 50,
      "brand": "Samsung",
      "category": "LAPTOPS",
      "image": "https://i.dummyjson.com/data/products/7/1.jpg"
   },
   {
      "id": "b2d77720-4267-4d13-9f2a-2cd9c2d6902f",
      "title": "Microsoft Surface Laptop 4",
      "description": "Style and speed. Stand out on HD video calls backed by Studio Mics. Capture ideas on the vibrant touchscreen.",
      "price": 5996.00,
      "stock": 68,
      "brand": "Microsoft Surface",
      "category": "LAPTOPS",
      "image": "https://i.dummyjson.com/data/products/8/1.jpg"
   }
]

status: 200

Sucesso sem retorno

[]

status: 200

GET products/id

Detalhar um produto. O id deve ser enviado na url.

Request

Nome Obrigatório Tipo Descrição
id sim string Enviar via parâmetro de rota

NOTA: É necessário enviar Token JWT via Authorization Header.

Response

Sucesso

{
   "id": "4b5a9bcd-a10e-4965-8939-22d24f408138",
   "title": "Infinix INBOOK",
   "description": "Infinix Inbook X1 Ci3 10th 8GB 256GB 14 Win10 Grey – 1 Year Warranty",
   "price": 4396.00,
   "stock": 96,
   "brand": "Infinix",
   "category": "LAPTOPS",
   "image": "https://i.dummyjson.com/data/products/9/1.jpg"
}

status: 200

Erros comuns

{
   "statusCode": "NOT_FOUND",
   "message": "Product not found",
   "dateTime": "02-12-2023 19:48:00"
}
{
   "statusCode": "UNAUTHORIZED",
   "message": "Invalid token",
   "dateTime": "02-12-2023 19:48:12"
}
PUT products/id

Alterar os dados do produto. O id deve ser enviado na url. Nenhuma propriedade do body é obrigatória, mas as validações persistem.

Request

Nome Obrigatório Tipo Descrição
id sim string Enviar via parâmetro de rota
title não string Nome do produto
description não string Descrição do produto
price não bigdecimal Preço do produto
stock não integer Estoque do produto
brand não string Marca do produto
category não string Categoria do produto
image não string URL da imagem do produto

NOTA: É necessário enviar Token JWT via Authorization Header.

Response

Sucesso

{
   "id": "4b5a9bcd-a10e-4965-8939-22d24f408138",
   "title": "Infinix INBOOK EDITADO",
   "description": "Infinix Inbook X1 Ci3 10th 16GB 256GB 14 Win10 Grey",
   "price": 5000.00,
   "stock": 50,
   "brand": "Infinix",
   "category": "LAPTOPS",
   "image": "https://i.dummyjson.com/data/products/9/1.jpg"
}

status: 200

Erros comuns

{
   "statusCode": "NOT_FOUND",
   "message": "Product not found",
   "dateTime": "02-12-2023 19:48:00"
}
{
   "statusCode": "BAD_REQUEST",
   "message": "Other product already have this title and brand",
   "dateTime": "02-12-2023 19:51:34"
}
{
   "statusCode": "UNAUTHORIZED",
   "message": "Invalid token",
   "dateTime": "02-12-2023 19:48:12"
}
DELETE products/id

Deletar um produto. O id deve ser enviado na url.

Request

Nome Obrigatório Tipo Descrição
id sim string Enviar via parâmetro de rota

NOTA: É necessário enviar Token JWT via Authorization Header.

Response

Sucesso
no body returned for response
status: 204

Erros comums

{
   "statusCode": "NOT_FOUND",
   "message": "Product not found",
   "dateTime": "02-12-2023 19:48:00"
}
{
   "statusCode": "UNAUTHORIZED",
   "message": "Invalid token",
   "dateTime": "02-12-2023 19:48:12"
}

5. 👨‍💻 Autor

Criado por Daniel Justo

linkedin github

Obrigado pela visita!