Professor Marco Antonio Andrade

Implementando uma API com Nodejs e MySQL para gerenciamento de tarefas

03/09/2019 - 37 mins de leitura

Pré-requisitos

Para implementar este tutorial é necessário um editor de texto (estou utilizando o VS Code), Git, Nodejs e MariaDB. Também será utilizado o cURL, Postman e um navegador (Chrome ou Firefox).

Baixando a estrutura básica

Faça um fork do repositório com a estrutura básica https://github.com/marcoaugustoandrade/api-tarefas-default

Clone seu repositório no GitHub em seu computador:

git clone https://github.com/<USUARIO>/api-tarefas-default

Criando o projeto nodejs

Após clonar a estrutura básica acesse o diretório:

cd api-tarefas-default

Crie um projeto nodejs com o comando a seguir e, em seguida, responda os questionamentos:

npm init

package name: (api-tarefas-default)
version: (1.0.0)
description: API Tarefas v1
entry point: (index.js) src/index.js
test command:
git repository: (https://github.com/marcoaugustoandrade/api-tarefas-default.git)
keywords: tarefas
author: Marco Andrade
license: (ISC) MIT

Instalando o expressjs

Para implementarmos uma API vamos utilizar o framework Expressjs. Para utiliza-lo como dependência do projeto utilize o NPM (que é o gerenciador de pacotes do nodejs):

npm install --save express

Se abrir o arquivo package.json vai perceber que o expressjs agora faz parte das dependências deste projeto:

"dependencies": {
    "express": "^4.17.1"

As dependências são instaladas na pasta node_modules. Esta pasta está listada no arquivo .gitignore e significa que eles serão ignorados pelo Git. Por exemplo, se você commitar, enviar estes commits para o repositório remoto e clonar este repositório em outra máquina, será necessário instalar as dependências. Como essas dependências estão listadas no arquivo package.json basta utilizar o seguinte comando dentro da pasta do projeto:

npm install

Criando a aplicação e a primeira rota

Abra o arquivo index.js dentro da pasta src. Neste arquivo vamos criar a primeira rota de nossa API:

// Importando o expressjs
const express = require('express')

// Criando uma instância do expressjs
const app = express()

// Criando uma rota
app.get('/', (req, res) => {
  res.send('<h1>Olá mundo!</h1>')
})

// Configurando o servidor
const port = 3009
app.listen(port, () => { console.log(`Servidor rodando na porta ${port}`) })

Configurando o package.json

Antes de subir o servidor vamos editar o arquivo package.json adicionando um script para isso:

"scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "node src/index.js"
}

Subindo o servidor

No console utilize o comando a seguir para subir o servidor:

npm run start

Para testar abra no navegador com o seguinte endereço http://localhost:3009/.

Adicionando uma nova rota

Vamos adicionar uma nova rota no arquivo index.js:

// Criando uma nova rota
app.get('/api/v1', (req, res) => {
  res.json({
    message: "API Tarefas v1"
  })
})

Observe que agora estamos retornando um JSON. Abra o navegador e abra o endereço http://localhost:3000/api/v1. Percebeu que a rota não foi carregada? Para que as novas alterações possam funcionar precisamos parar o servidor com CTRL + C e novamente utilizar o comando npm run start para subi-lo. Para que toda vez que fizermos alterações não precisarmos deste procedimento vamos instalar o Nodemon, uma dependência que monitora as alterações parando e iniciando o servidor.

Instalando o nodemon

Vamos instalar o nodemon de forma global:

sudo npm install -g nodemon

Também vamos editar o package.json para que o nodemon seja utilizado no comando que sobe o servidor:

"scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "nodemon src/index.js"
}

Importando o schema do banco de dados

Antes de continuarmos vamos preparar o banco de dados da API. Acesse o SGDB com o comando:

sudo mysql -u root -p
// Criando um usuário para uso da API
create user 'suporte'@'localhost' identified by '$uportE99';

// Concedendo privilégios
grant all privileges on db_tarefas.* to 'suporte'@'localhost';

// Saindo do SGDB
exit

// Importando o schema do banco de dados
mysql -u suporte -p < database/schema.sql

Criando o módulo de rotas

Vamos organizar nosso projeto criando um módulo para as rotas. Dentro da pasta src crie a pasta routes e, dentro desta pasta, crie o arquivo tarefaRouter.js. Neste arquivo vamos listar todas as rotas do recurso tarefa:

const express = require('express')
const router = express.Router()

// Exportando as rotas
module.exports = router

Abra o `index.js` para que possamos importar as rotas do recurso `tarefa`:
const express = require('express')
const app = express()

app.get('/api/v1', (req, res) => {
  res.json({
    message: "API Tarefas v1.0"
  })
})

// Rotas
const tarefaRouter = require('./routes/tarefaRouter')
app.use('/api/v1/tarefas', tarefaRouter)

const port = 3000
app.listen(port, () => { console.log(`Servidor rodando na porta ${port}`) })

A rota /api/v1/tarefas utiliza o módulo tarefaRouter que contém todas as rotas do recurso tarefa.

Criando uma rota para listar todas as tarefas

Vamos criar a primeira rota que será responsável por listar todas as tarefas. Vamos adicionar as rotas no arquivo src/routes/tarefaRouter:

const express = require('express')
const router = express.Router()
const tarefaController = require('../controllers/tarefaController')

// Lista de rotas
router.get('/', tarefaController.listar)

module.exports = router

Ao utilizar a rota /api/v1/tarefas com o método GET vamos direcionar o processamento para a função listar do módulo tarefaController.

Na pasta src vamos criar a pasta controllers e, dentro desta, criar o módulo tarefaController. Este módulo será responsável pelo processamento das rotas do recurso tarefa.

exports.listar = (req, res) => {
  res.json({
    message: "Listando tarefas!"
  })
}

A partir de agora vamos utilizar o Postman para realizar os testes em nossa API.

Variáveis de ambiente

No arquivo index.js temos uma variável port destinada a armazenar a porta utilizada pelo servidor de nossa API. Provavelmente, vamos ter outras variáveis para acesso a banco de dados espalhadas por nosso código. Como forma de organizar vamos utilizar uma dependência para controlar nossas variáveis de ambiente:

npm install --save dotenv

As variáveis ficarão localizadas no arquivo .env. Por questões de segurança este arquivo faz parte da lista ignorada de arquivos do .gitignore. Há um arquivo de exemplo .env.example, listado na raiz do projeto. Faça uma cópia deste arquivo com o nome .env e edite conforme suas configurações:

# App
PORT=3009

# MariaDB
DB_HOST=127.0.0.1
DB_PORT=3306
DB_USER=suporte
DB_PASS=$uportE99
DB_NAME=db_tarefas

No arquivo index.js vamos importar e configurar a dependência dotenv:

const express = require('express')
const app = express()
require('dotenv').config()

app.get('/', (req, res) => {
  res.send('<h1>Olá mundo!</h1>')
})

const tarefaRouter = require('./routes/tarefaRouter')
app.use('/api/v1/tarefas', tarefaRouter)

const port = process.env.PORT
app.listen(port, () => { console.log(`Servidor rodando na porta ${port}`) })

Observe que para acessar as variáveis de ambiente do arquivo .env basta utilizar process.env.NOME-DA-VARIAVEL.

Registrando logs com o Morgan

Para auxiliar no processo de debug da nossa API vamos instalar uma dependência para gerenciar os logs:

npm install --save morgan

No arquivo index.js vamos importa-la e configura-la:

const morgan = require('morgan')
app.use(morgan('dev'))

Há várias opções para uso no morgan como: tiny, combined, etc.

O módulo principal vai ficar assim:

const express = require('express')
const app = express()
require('dotenv').config()
const morgan = require('morgan')

app.use(morgan('dev'))

app.get('/', (req, res) => {
  res.send('<h1>Olá mundo!</h1>')
})

const tarefaRouter = require('./routes/tarefaRouter')
app.use('/api/v1/tarefas', tarefaRouter)

const port = process.env.PORT
app.listen(port, () => { console.log(`Servidor rodando na porta ${port}`) })

Acessando o banco de dados

Na pasta src crie uma pasta config e um arquivo denominado conexao.js. Neste módulo vamos criar uma conexão com o banco de dados e exporta-la:

const mysql = require('mysql');

const conexao = mysql.createConnection({
  host: process.env.DB_HOST,
  port: process.env.DB_PORT,
  user: process.env.DB_USER,
  password: process.env.DB_PASS,
  database: process.env.DB_NAME,
});

module.exports = conexao;

Perceba que este módulo necessita da dependência mysql. Para instalar utilize o comando:

npm install --save mysql

Carregando a documentação da API

Devemos implementar a nossa API de acordo com a especificação contida na pasta docs. Para isso, vamos instalar algumas dependências:

npm install --save swagger-ui-express
npm install --save yamljs

No módulo principal vamos adicionar a implementação que carrega a documentação da API na rota /api/v1/docs:

const swaggerUi = require('swagger-ui-express')
const YAML = require('yamljs')
const swaggerDocument = YAML.load('./docs/swagger.yml')
app.use('/api/v1/docs', swaggerUi.serve, swaggerUi.setup(swaggerDocument))

Listando todas as tarefas

Para efetivamente listar as tarefas registradas no banco de dados vamos editar a função listar do módulo tarefaController:

// Se vamos acessar um banco de dados precisamos do módulo que faz isso
const conexao = require('../config/conexao')

exports.listar = (req, res) => {
 
  let descricao = req.query.f || ""
  descricao = "%" + descricao + "%"

  const query = 'select t.id, t.descricao, t.data, t.realizado, c.descricao as categoria, c.cor from tarefas t, categorias c where t.categoria_id = c.id and t.descricao like ?'

  conexao.query(query, [descricao], (err, rows) => {
    if (err){
      console.log(err)
      res.status(500)
      res.json({"message": "Internal Server Error"})
    } else if (rows.length > 0){
      res.status(200)
      res.json(rows)
    } else {
      res.status(404)
      res.json({"message": "Nenhuma tarefa cadastrada para esta busca"})
    }
  })
}

Listando uma tarefa atráves do seu id

Sempre que precisarmos implementar uma nova rota é necessário cria-la no módulo tarefaRouter e implementa-la no módulo tarefaController.

const express = require('express')
const router = express.Router()
const tarefaController = require('../controllers/tarefaController')

router.get('/', tarefaController.listar)
router.get('/:id', tarefaController.listarPorId)

module.exports = router

No módulo tarefaController vamos implementar a função listarPorId:

exports.listarPorId = (req, res) => {
     
  const id = req.params.id

  const query = 'select * from tarefas where id = ?'

  conexao.query(query, [id], (err, rows) => {
    if (err){
      console.log(err)
      res.status(500)
      res.json({"message": "Internal Server Error"})
    } else if (rows.length > 0){
      res.status(200)
      res.json(rows[0])
    } else {
      res.status(404)
      res.json({"message": "Nenhuma tarefa cadastrada com esse id"})
    }
  })
}

Para testar no Postman crie um novo request com o método DELETE para a url http://localhost:3009/api/v1/tarefa/1.

Inserindo uma nova tarefa

Para inserir uma nova tarefa vamos utilizar o método POST e enviar, no corpo da requisição, os dados de uma tarefa para cadastro. Assim, precisamos instalar a dependência body-parser:

npm install --save body-parser

E utiliza-la no arquivo index.js:

const bodyParser = require('body-parser')

app.use(bodyParser.json())
app.use(bodyParser.urlencoded( {extended: true} ))

Vamos aproveitar e instalar a dependência cors. Esta dependência habilita o uso da API por domínios diferentes:

npm install --save cors

E utiliza-la no arquivo index.js:

const cors = require('cors')

app.use(cors());

O módulo principal vai ficar assim:

const express = require('express')
const app = express()
require('dotenv').config()
const morgan = require('morgan')
const bodyParser = require('body-parser')
const cors = require('cors')

app.use(morgan('dev'))
app.use(bodyParser.json())
app.use(bodyParser.urlencoded( {extended: true} ))
const cors = require('cors')

app.get('/', (req, res) => {
  res.send('<h1>Olá mundo!</h1>')
})

const tarefaRouter = require('./routes/tarefaRouter')
app.use('/api/v1/tarefas', tarefaRouter)

const port = process.env.PORT
app.listen(port, () => { console.log(`Servidor rodando na porta ${port}`) })

Vamos criar a rota para inserção de novas tarefas. No arquivo tarefaRouter insira a rota:

router.post('/', tarefaController.inserir)

No módulo tarefaController vamos criar a função inserir:

exports.inserir = (req, res) => {
 
  const tarefa = {}
  tarefa.descricao = req.body.descricao
  tarefa.data = req.body.data
  tarefa.realizado = req.body.realizado
  tarefa.categoria_id = req.body.categoria_id
 
  const query = 'insert into tarefas (descricao, data, realizado, categoria_id) values (?, ?, ?, ?)'
 
  conexao.query(query, [tarefa.descricao, tarefa.data, tarefa.realizado, tarefa.categoria_id], (err, result) => {
    if (err){
      console.log(err)
      res.status(500)
      res.json({"message": "Internal Server Error"})
    } else {
      res.status(201)
      res.json({"message": result.insertId})
    }
  })
}

Utilize o postman para inserir uma nova tarefa.

Alterando dados de uma tarefa

No módulo tarefaRouter vamos criar a rota do tipo PUT que será responsável pela alteração de recusos do tipo tarefa:

router.put('/:id', tarefaController.alterar)

No módulo tarefaController vamos criar a função alterar que será responsável pela alteração de recursos do tipo tarefa:

exports.alterar = (req, res) => {
 
    const tarefa = {}
    tarefa.id = req.params.id
    tarefa.descricao = req.body.descricao
    tarefa.data = req.body.data
    tarefa.realizado = req.body.realizado
    tarefa.categoria_id = req.body.categoria_id

    const query = 'update tarefas set descricao = ?, data = ?, realizado = ?, categoria_id = ? where id = ?'

    conexao.query(query, [tarefa.descricao, tarefa.data, tarefa.realizado, tarefa.realizado, tarefa.id], (err, result) => {
      if (err){
        console.log(err)
        res.status(500)
        res.json({"message": "Internal Server Error"})
      } else if (result.affectedRows > 0){
        res.status(202)
        res.json({"message": "Tarefa alterada"})
      } else {
        res.status(404)
        res.json({"message": "Tarefa não encontrada"})
      }
    })
}

Utilize o Postman para alterar uma tarefa.

Deletando uma tarefa

Para deletar uma tarefa vamos criar uma rota com o método DELETE informando o id da tarefa a ser excluída. No módulo tarefaRouter crie a rota:

router.delete('/:id', tarefaController.deletar)

No módulo tarefaController vamos criar a função deletar que será responsável pela exclusão de recursos do tipo tarefa:

exports.deletar = (req, res) => {
 
  const id = req.params.id

  const query = 'delete from tarefas where id = ?'

  conexao.query(query, [id], (err, result) => {
    if (err){
      console.log(err)
      res.status(500)
      res.json({"message": "Internal Server Error"})
    } else if (result.affectedRows > 0){
      res.status(200)
      res.json({"message": "Tarefa deleta"})
    } else {
      res.status(404)
      res.json({"message": "Tarefa não encontrada"})
    }
  })
}

Observer que temos três tipos de respostas: quando há algum erro no servidor, quando a tarefa foi deletar e quando a tarefa informada não foi encontrada.

Para testar no Postman crie um novo request com o método DELETE para a url http://localhost:3009/api/v1/tarefa/1. Tente novamente executar a solicitação para a exclusão da tarefa 1 e veja o response.

Implementando a autenticação e autorização com JWT

Até o momento a API tem acesso público e qualquer um pode acessa-la e utiliza-la e apartir de agora vamos implementar mecanismos de autenticação e autorização.

Instale as dependências:

npm install --save jsonwebtoken
npm install --save bcrypt

Crie o modulo apiRouter na pasta src/routers. Neste módulo vamos implementar duas rotas uma para login e uma para logoff:

const express = require('express')
const router = express.Router()
const apiController = require('../controllers/apiController')

router.post('/login', apiController.login)
router.get('/logoff', apiController.logoff)

module.exports = router

Agora vamos implementar o módulo apiController na pasta src/controllers.

// Importações necessárias
const conexao = require('../config/conexao')
const jwt  = require('jsonwebtoken')
const bcrypt = require('bcrypt')
require('dotenv').config()

Função para realizar login:

exports.login = (req, res) => {

  const email = req.body.email
  const senha = req.body.senha

  const query = 'select * from usuarios where email = ?'

  conexao.query(query, [email], (err, rows) => {

    if (err){        
      console.log(err)
      res.status(500)
      res.json({
        auth: false,
        "message": "Internal Server Error"
      })
   
    } else if (rows.length > 0){
      bcrypt.compare(senha, rows[0].senha, (err, resp) => {
        if (resp){
          const usuario = rows[0].id
          jwt.sign({usuario}, process.env.SECRET, {expiresIn: 30}, (err, token) => {
            res.status(200)
            res.json({
              auth: true,
              token: token
            })
          })
        } else {

          res.status(403)
          res.json({
            auth: false,
            message: "E-mail e/ou senhas incorreto(s)"
          })
        }
      })
    } else {
      res.status(403)
      res.json({
        auth: false,
        message: "E-mail e/ou senhas incorreto(s)"
      })
    }
  })
}

Função para verificar se há autorização para uso de um recurso:

exports.verificar = (req, res, next) => {

  const token = req.headers['access-token']
 
  if (!token){
    res.status(401)
    res.send({
      auth: false,
      message: 'O token está em branco'
    })
  }
 
  jwt.verify(token, process.env.SECRET, (err, decoded) => {
   
    if (err){
      res.status(500)
      res.send({
        auth: false,
        message: 'Falha de autenticação'
      })
    } else {
      next()
    }
  })
}

Função para realizar logoff:

exports.logoff = (req, res) => {
  res.status(200)
  res.send({
    auth: false,
    token: null
  })
}

O próximo passo é editar as rotas do recurso tarefa para que verifiquem as autorizações:

const express = require('express')
const router = express.Router()
const tarefaController = require('../controllers/tarefaController')
const apiController = require('../controllers/apiController')

// Lista de rotas
router.get('/', apiController.verificar, tarefaController.listar)
router.get('/:id', apiController.verificar, tarefaController.listarPorId)
router.post('/', apiController.verificar, tarefaController.inserir)
router.put('/:id', apiController.verificar, tarefaController.alterar)
router.delete('/:id', apiController.verificar, tarefaController.deletar)

module.exports = router

Validando dados com express-validator

Instale a dependência express-validator:

npm install --save express-validator

Dentro da pasta src crie a pasta util. Nesta pasta crie o arquivo tarefaValidation.js. No tarefaValidation.js vamos importar o express-validator:

const { check } = require('express-validator')

Agora vamos exportar uma constante que contém as regras de validação que serão utilizadas na rota que lista as tarefas por id. A validação consiste em verificar se o id foi setado e se é numérico, retornando uma string para o caso negativo a algumas dessas verificações:

exports.listarPorId = [
  check('id')
    .exists().withMessage('O id não pode estar em branco')
    .isInt().withMessage('O id deve ser numérico')
]

Vamos modificar nossa rota que lista tarefas por id para que utilize a validação que criamos. Abra o arquivo src\routes\tarefaRoute.js:

// Importando o arquivo de validação
const tarefaValidation = require('../util/tarefaValidation')

// Utilizando as regras de validação na rota que lista por id
router.get('/:id', tarefaValidation.listarPorId, tarefaController.listarPorId)

No controller vamos utilizar a validação para retornar adequadamente os erros de validação:

exports.listarPorId = (req, res) => {
  
  const errors = validationResult(req);
  if (!errors.isEmpty()) {
    return res.status(422).json({ errors: errors.array() })
  } else {
    
    const id = req.params.id

    const query = 'select * from tarefas where id = ?'

    conexao.query(query, [id], (err, rows) => {
      if (err){
        console.log(err)
        res.status(500)
        res.json({"message": "Internal Server Error"})
      } else if (rows.length > 0){
        res.status(200)
        res.json(rows[0])
      } else {
        res.status(404)
        res.json({"message": "Nenhuma tarefa cadastrada com esse id"})
      }
    })
  }
}

Já sabemos criar validações dos dados de entrada na API, então iremos adicionar validações para as operações de inserir, alterar e deletar tarefas. Abra o arquivo src\util\tarefaValidation.js, que deve ficar da seguinte forma:

const { check } = require('express-validator')

exports.listarPorId = [
  check('id')
    .exists().withMessage('O id não pode estar em branco')
    .isInt().withMessage('O id deve ser numérico')
]

exports.inserir = [
  check('descricao').exists().trim().withMessage('A descrição da tarefa não pode estar em branco'),
  check('data').exists().trim().withMessage('O horário e data da tarefa não pode estar em branco'),
  check('categoria_id').exists().trim().withMessage('A categoria da tarefa deve ser definida')
]

exports.alterar = [
  check('id')
    .exists().withMessage('O id não pode estar em branco')
    .isInt().withMessage('O id deve ser numérico'),
  check('descricao').exists().trim().withMessage('A descrição da tarefa não pode estar em branco'),
  check('data').exists().trim().withMessage('O horário e data da tarefa não pode estar em branco'),
  check('categoria_id').exists().trim().withMessage('A categoria da tarefa deve ser definida')
]

exports.deletar = [
  check('id')
    .exists().withMessage('O id não pode estar em branco')
    .isInt().withMessage('O id deve ser numérico')
]

Abra o arquivo de rotas, localizado em src\routes\tarefaRoute.js, que deve ser alterado para ficar assim:

const express = require('express')
const router = express.Router()
const tarefaController = require('../controllers/tarefaController')
const tarefaValidation = require('../util/tarefaValidation')

router.get('/', tarefaController.listar)
router.get('/:id', tarefaValidation.listarPorId, tarefaController.listarPorId)
router.post('/', tarefaValidation.inserir, tarefaController.inserir)
router.put('/:id', tarefaValidation.alterar, tarefaController.alterar)
router.delete('/:id', tarefaValidation.deletar, tarefaController.deletar)

module.exports = router

Por fim, abra o arquivo de controllers, em src\controllers\tarefaController.js, e altere os métodos inserir, alterar e deletar:

exports.inserir = (req, res) => {
  
  const errors = validationResult(req);
  if (!errors.isEmpty()) {
    return res.status(422).json({ errors: errors.array() })
  } else {
    
    const tarefa = {}
    tarefa.descricao = req.body.descricao
    tarefa.data = req.body.data
    tarefa.realizado = req.body.realizado
    tarefa.categoria_id = req.body.categoria_id
    
    const query = 'insert into tarefas (descricao, data, realizado, categoria_id) values (?, ?, ?, ?)'
    
    conexao.query(query, [tarefa.descricao, tarefa.data, tarefa.realizado, tarefa.categoria_id], (err, result) => {
      if (err){
        console.log(err)
        res.status(500)
        res.json({"message": "Internal Server Error"})
      } else {
        res.status(201)
        res.json({"message": result.insertId})
      }
    })
  }
}

exports.alterar = (req, res) => {
  
  const errors = validationResult(req);
  if (!errors.isEmpty()) {
    return res.status(422).json({ errors: errors.array() })
  } else {

    const tarefa = {}
    tarefa.id = req.params.id
    tarefa.descricao = req.body.descricao
    tarefa.data = req.body.data
    tarefa.realizado = req.body.realizado
    tarefa.categoria_id = req.body.categoria_id

    const query = 'update tarefas set descricao = ?, data = ?, realizado = ?, categoria_id = ? where id = ?'

    conexao.query(query, [tarefa.descricao, tarefa.data, tarefa.realizado, tarefa.realizado, tarefa.id], (err, result) => {
      if (err){
        console.log(err)
        res.status(500)
        res.json({"message": "Internal Server Error"})
      } else if (result.affectedRows > 0){
        res.status(202)
        res.json({"message": "Tarefa alterada"})
      } else {
        res.status(404)
        res.json({"message": "Tarefa não encontrada"})
      }
    })
    conexao.end()
  }
}

exports.deletar = (req, res) => {
  
  const errors = validationResult(req);
  if (!errors.isEmpty()) {
    return res.status(422).json({ errors: errors.array() })
  } else {
    
    const id = req.params.id

    const query = 'delete from tarefas where id = ?'

    conexao.query(query, [id], (err, result) => {
      if (err){
        console.log(err)
        res.status(500)
        res.json({"message": "Internal Server Error"})
      } else if (result.affectedRows > 0){
        res.status(200)
        res.json({"message": "Tarefa deleta"})
      } else {
        res.status(404)
        res.json({"message": "Tarefa não encontrada"})
      }
    })
  }
}
Este site usa cookies próprios e de terceiros para melhorar os seus serviços, elaborar informação estatística e mostrar conteúdos ou serviços personalizados através da análise da sua navegação. Para aceitar o seu uso, você pode clicar em Aceitar ou continuar navegando. Além disso, você pode configurar ou rejeitar o uso de cookies ajustando suas Configurações. Para obter mais informações sobre o uso de cookies e seus direitos, acesse nossa Política de Cookies