serverest 2.25.3 → 2.26.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +56 -0
- package/README.md +35 -5
- package/docs/swagger.json +1 -1
- package/package.json +5 -2
- package/src/app.js +12 -1
- package/src/controllers/carrinhos-controller.js +22 -33
- package/src/middlewares/error-handler.js +6 -2
- package/src/middlewares/rate-limiter.js +23 -4
- package/src/services/carrinhos-service.js +29 -2
- package/src/services/produtos-service.js +22 -0
- package/src/utils/ambiente.js +9 -1
- package/src/utils/constants.js +1 -0
- package/src/utils/logger.js +1 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,61 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [2.26.1](https://github.com/ServeRest/ServeRest/compare/v2.26.0...v2.26.1) (2022-07-08)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Bug Fixes
|
|
7
|
+
|
|
8
|
+
* show user that request ended with timeout ([1f432c4](https://github.com/ServeRest/ServeRest/commit/1f432c429647c871b2075dc8a4259ab52e714e04))
|
|
9
|
+
|
|
10
|
+
# [2.26.0](https://github.com/ServeRest/ServeRest/compare/v2.25.4...v2.26.0) (2022-06-19)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### Chores
|
|
14
|
+
|
|
15
|
+
* avoid action unpublished version ([15fab7f](https://github.com/ServeRest/ServeRest/commit/15fab7f4565ef46350cc8959669e1430f02aec03)), closes [#310](https://github.com/ServeRest/ServeRest/issues/310)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
### Continuous Integration
|
|
19
|
+
|
|
20
|
+
* run mutation test only when files in src/ dir change ([0ed60ad](https://github.com/ServeRest/ServeRest/commit/0ed60ad04bf0db573c7ba23c1ba8826708f29711))
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
### Features
|
|
24
|
+
|
|
25
|
+
* allow load test and route /status to get infos ([7098bff](https://github.com/ServeRest/ServeRest/commit/7098bffed401ec001a1d5eef0406a406a6fd6e97))
|
|
26
|
+
|
|
27
|
+
## [2.25.4](https://github.com/ServeRest/ServeRest/compare/v2.25.3...v2.25.4) (2022-06-19)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
### Chores
|
|
31
|
+
|
|
32
|
+
* **terratest:** remove specific version that prevents docker build ([7e18f99](https://github.com/ServeRest/ServeRest/commit/7e18f994acd306eb31bbd37c9f6efe80a231f440))
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
### Code Refactoring
|
|
36
|
+
|
|
37
|
+
* **dockerfile:** split multi-stage docker on 2 files to improve docker build time ([0971a56](https://github.com/ServeRest/ServeRest/commit/0971a56ccb5360770c511374b2fe83e84b6d7096))
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
### Continuous Integration
|
|
41
|
+
|
|
42
|
+
* automatic deploy to staging and prod, e2e test and rollback ([10948da](https://github.com/ServeRest/ServeRest/commit/10948dab55428981a425502a7db0f2a02fac4167))
|
|
43
|
+
* cancelar execução anterior em um novo git push ([461eba0](https://github.com/ServeRest/ServeRest/commit/461eba0af5ff5ee43855b396b88e579971e64e95))
|
|
44
|
+
* **e2e:** e2e test must be mandatory for guarantee the release quality ([f239f6d](https://github.com/ServeRest/ServeRest/commit/f239f6d0960b78d564689963161d79bf170238d3))
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
### Documentation
|
|
48
|
+
|
|
49
|
+
* **contributing:** info about continous delivery and about validations ([14d12b5](https://github.com/ServeRest/ServeRest/commit/14d12b5a77af1de14148f364fb39e5515e421c7a))
|
|
50
|
+
* **serverest:** allow import collection to postman ([c5e9bc8](https://github.com/ServeRest/ServeRest/commit/c5e9bc8779f4d20a152fed50cac2ebbee99cb149))
|
|
51
|
+
* **serverest:** show correct version on swagger instead 2.x.x ([75cf178](https://github.com/ServeRest/ServeRest/commit/75cf178c884825d9bb5d215261039ad604efb554))
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
### Tests
|
|
55
|
+
|
|
56
|
+
* **docs:** validate that documentation is accessible - [#202](https://github.com/ServeRest/ServeRest/issues/202) ([7ba01cf](https://github.com/ServeRest/ServeRest/commit/7ba01cf654e0c7d0e138655d7df1b435246213bb))
|
|
57
|
+
* **e2e:** allow E2E testing of production application ([f8c28cf](https://github.com/ServeRest/ServeRest/commit/f8c28cf54eeaf2e8452a474453e45822fcc5c9c7))
|
|
58
|
+
|
|
3
59
|
## [2.25.3](https://github.com/ServeRest/ServeRest/compare/v2.25.2...v2.25.3) (2022-03-18)
|
|
4
60
|
|
|
5
61
|
|
package/README.md
CHANGED
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
|
|
26
26
|
_ServeRest_ permite o estudo de:
|
|
27
27
|
- Verbos *GET, POST, PUT* e *DELETE* com persistência de dados
|
|
28
|
+
- [Teste de carga](#teste-de-carga)
|
|
28
29
|
- Autenticação no header
|
|
29
30
|
- Query string
|
|
30
31
|
- Teste de schema json
|
|
@@ -52,7 +53,7 @@ Todas essas opções possuem as mesmas rotas, regras, dados pré-cadastrados e d
|
|
|
52
53
|
|
|
53
54
|
No ambiente online os dados cadastrados são removidos diariamente, enquanto que no local basta reiniciar o ServeRest.
|
|
54
55
|
|
|
55
|
-
Prefira a opção de ambiente local caso precise que os dados não sejam alterados por outro usuário.
|
|
56
|
+
> Prefira a opção de ambiente local caso precise que os dados não sejam alterados por outro usuário.
|
|
56
57
|
|
|
57
58
|
### Online
|
|
58
59
|
|
|
@@ -60,10 +61,7 @@ Acesse **<https://serverest.dev>** para visualizar a documentação e as rotas d
|
|
|
60
61
|
|
|
61
62
|
> Essa é a melhor opção para quem não possui NPM e Docker na máquina ou não quer preocupar em gerenciar ambiente.
|
|
62
63
|
|
|
63
|
-
A base de dados volta ao estado original [diariamente às 3h](https://github.com/ServeRest/ServeRest/actions?query=workflow%3A%22Clean+serverest.dev+database%22).
|
|
64
|
-
|
|
65
64
|
O ServeRest online possui monitoramento constante do status e tempo de atividade para garantir que esteja sempre disponível.
|
|
66
|
-
Acesse [ServeRest Status](https://status.serverest.dev/) para ver detalhes do uptime.
|
|
67
65
|
|
|
68
66
|
### Localmente com NPM
|
|
69
67
|
|
|
@@ -127,6 +125,28 @@ Em ambos os comandos de subida de ambiente local será utilizado a última vers
|
|
|
127
125
|
|
|
128
126
|
Você pode encontrar as versões disponíveis na [lista de tags no Docker Hub](https://hub.docker.com/r/paulogoncalvesbh/serverest/tags) e na [lista de versões do NPM](https://www.npmjs.com/package/serverest).
|
|
129
127
|
|
|
128
|
+
## Teste de carga
|
|
129
|
+
|
|
130
|
+
### IMPORTANTE
|
|
131
|
+
|
|
132
|
+
1. É obrigatório enviar o header `monitor: false` em todas as requisições do seu teste de carga.
|
|
133
|
+
2. O teste de carga deve ser executado apenas em ambiente local (disponibilizado via [NPM](#localmente-com-npm) ou [Docker](#localmente-com-docker) e acessível via <http://localhost:3000>).
|
|
134
|
+
|
|
135
|
+
> O não seguimento dos 2 tópicos acimas vai acarretar em prejuízo para o projeto open source e gratuito e irá impactar o estudo de outras pessoas.
|
|
136
|
+
|
|
137
|
+
### Acesso ao status
|
|
138
|
+
|
|
139
|
+
Para acompanhar o comportamento do ServeRest diante dos seus testes você pode acessar a página <http://localhost:3000/status>, que contém informações como:
|
|
140
|
+
|
|
141
|
+
- Uso de CPU.
|
|
142
|
+
- Uso da memória.
|
|
143
|
+
- Tempo de resposta.
|
|
144
|
+
- RPS (Requisições por segundo).
|
|
145
|
+
|
|
146
|
+
A página de status (_/status_) está disponível apenas localmente.
|
|
147
|
+
|
|
148
|
+
> Fez teste de carga? O que acha de compartilhar com o autor do projeto o repositório e o relatório final contendo dados de RPS para auxiliar o ServeRest a entender o comportamento de sua infra?
|
|
149
|
+
|
|
130
150
|
## Badge
|
|
131
151
|
|
|
132
152
|
Criou repositório utilizando o ServeRest? Adicione o código abaixo no topo do README.md para ter a badge do projeto.
|
|
@@ -158,7 +178,15 @@ Sua empresa usa o ServeRest? Pergunte ao seu gerente ou equipe de marketing se s
|
|
|
158
178
|
1. Subdomínio próprio (_nome-escolhido.serverest.dev_)
|
|
159
179
|
1. Acesso a todas as requests e respostas feitas nos últimos 7 dias no subdomínio
|
|
160
180
|
|
|
161
|
-
[](https://opencollective.com/serverest)
|
|
182
|
+
|
|
183
|
+
Empresas que apoiam o ServeRest:
|
|
184
|
+
|
|
185
|
+
<p align="center">
|
|
186
|
+
<img alt="Logo da EBAC" src="https://user-images.githubusercontent.com/29241659/177436481-2a6a3324-1b0e-4d28-8a40-d885f54291c0.png#gh-light-mode-only" height="120">
|
|
187
|
+
<img alt="Logo da EBAC" src="https://user-images.githubusercontent.com/29241659/177436489-5d2f50f8-2fb3-4091-b822-446d24c83722.png#gh-dark-mode-only" height="120">
|
|
188
|
+
<img alt="Logo da Agilizei" src="https://user-images.githubusercontent.com/29241659/177436678-8187f90f-bb4a-4978-87ab-a03f2f80820f.png" height="124">
|
|
189
|
+
</p>
|
|
162
190
|
|
|
163
191
|
### Individuais
|
|
164
192
|
|
|
@@ -190,6 +218,8 @@ Veja aqui [como você pode contribuir](https://github.com/ServeRest/ServeRest/bl
|
|
|
190
218
|
<td align="center"><a href="https://about.me/rustnnes"><img src="https://avatars1.githubusercontent.com/u/638445?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Diego Bandeira</b></sub></a><br /><a href="#infra-rustnnes" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a></td>
|
|
191
219
|
<td align="center"><a href="https://github.com/maximilianoalves"><img src="https://avatars3.githubusercontent.com/u/11561118?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Maximiliano Alves</b></sub></a><br /><a href="#talk-maximilianoalves" title="Talks">📢</a></td>
|
|
192
220
|
<td align="center"><a href="https://github.com/murilomaiaa"><img src="https://avatars.githubusercontent.com/u/56596799?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Murilo Maia</b></sub></a><br /><a href="https://github.com/ServeRest/ServeRest/commits?author=murilomaiaa" title="Code">💻</a></td>
|
|
221
|
+
<td align="center"><a href="https://github.com/crisnazario"><img src="https://avatars.githubusercontent.com/u/37200398?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Cristina Nazário</b></sub></a><br /><a href="#ideas-crisnazario" title="Ideas, Planning, & Feedback">🤔</a></td>
|
|
222
|
+
<td align="center"><a href="http://www.eduardosantos.dev"><img src="https://avatars.githubusercontent.com/u/10568807?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Eduardo Santos</b></sub></a><br /><a href="https://github.com/ServeRest/ServeRest/commits?author=edumaxsantos" title="Code">💻</a></td>
|
|
193
223
|
</tr>
|
|
194
224
|
</table>
|
|
195
225
|
|
package/docs/swagger.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"swagger": "2.0",
|
|
3
3
|
"info": {
|
|
4
|
-
"description": "**O ServeRest é uma API REST que simula uma loja virtual com intuito de servir de material de estudos de testes de API.**\n\
|
|
4
|
+
"description": "**O ServeRest é uma API REST gratuita que simula uma loja virtual com intuito de servir de material de estudos de testes de API.**\n\n**Não deixe de seguir o [autor do projeto](https://github.com/PauloGoncalvesBH) e deixar um star no repositório: [github.com/ServeRest/ServeRest](https://github.com/ServeRest/ServeRest)**\n\nEssa página documenta todas as rotas e como acessá-las. Para mais detalhes do ServeRest (como executar localmente utilizando Docker ou NPM, alterar timeout de autenticação, etc) acesse [o repositório do ServeRest](https://github.com/serverest/serverest).\n\nEstá utilizando Postman? Importe o [JSON do Swagger](https://raw.githubusercontent.com/ServeRest/ServeRest/trunk/docs/swagger.json) para ter acesso às collections.\n\nVai fazer teste de carga? Leia a seção '[Teste de Carga](https://github.com/ServeRest/ServeRest#teste-de-carga)'.\n\n\nMuito obrigado ♥ a todos que apoiam o projeto [financeiramente](https://opencollective.com/serverest#section-contributors) ou [com código, ideias e divulgação](https://github.com/ServeRest/ServeRest#contribuidores-), graças a vocês **mais de R$ 2000,00 foram doados para a ONG [Todas as letras](https://todasasletras.org/)** até o momento.\n\nO ServeRest possui um front, com status em beta, não deixe de conhecer: [front.serverest.dev](https://front.serverest.dev).\n\nPrecisa de apoio? [Abra uma issue](https://github.com/ServeRest/ServeRest/issues) ou contate o mantenedor do projeto:\n",
|
|
5
5
|
"version": "2.X.X",
|
|
6
6
|
"title": "ServeRest",
|
|
7
7
|
"contact": {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "serverest",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.26.1",
|
|
4
4
|
"description": "Servidor REST local de forma rápida e simples para estudo de testes de API",
|
|
5
5
|
"author": "Paulo Gonçalves <paulorochag@hotmail.com> (https://www.linkedin.com/in/paulo-goncalves/)",
|
|
6
6
|
"license": "GPL-3.0",
|
|
@@ -34,8 +34,10 @@
|
|
|
34
34
|
"dev": "nodemon --legacy-watch -e json,js ./src/server.js --nodoc",
|
|
35
35
|
"test:mutation": "stryker run ./test/stryker.conf.js",
|
|
36
36
|
"test:mutation:diff": "stryker-diff-runner --path ./test/stryker.conf.js --branch trunk",
|
|
37
|
-
"test:unit": "nyc --report-dir ./coverage-unit mocha --config test/unit/.mocharc.js",
|
|
37
|
+
"test:unit": "nyc --report-dir ./coverage-unit --check-coverage false mocha --config test/unit/.mocharc.js",
|
|
38
38
|
"test:integration": "nyc --report-dir ./coverage-integration mocha --config test/integration/.mocharc.js",
|
|
39
|
+
"test:e2e": "mocha --config test/integration/.mocharc.js --fgrep @skipE2E --invert",
|
|
40
|
+
"test:smoke": "mocha --config test/integration/.mocharc.js --grep @smokeE2E",
|
|
39
41
|
"merge-lcov": "npx lcov-result-merger@3.1.0 'coverage-**/lcov.info' 'lcov.info'",
|
|
40
42
|
"lint": "standard",
|
|
41
43
|
"lint:fix": "standard --fix",
|
|
@@ -50,6 +52,7 @@
|
|
|
50
52
|
"express": "^4.17.1",
|
|
51
53
|
"express-async-errors": "^3.1.1",
|
|
52
54
|
"express-query-int": "^3.0.0",
|
|
55
|
+
"express-status-monitor": "1.3.4",
|
|
53
56
|
"express-validation": "^3.0.8",
|
|
54
57
|
"is-ci": "^3.0.0",
|
|
55
58
|
"jsonwebtoken": "^8.5.1",
|
package/src/app.js
CHANGED
|
@@ -10,13 +10,14 @@ const timeout = require('connect-timeout')
|
|
|
10
10
|
const { join } = require('path')
|
|
11
11
|
const swaggerUi = require('swagger-ui-express')
|
|
12
12
|
|
|
13
|
-
const { formaDeExecucao, urlDocumentacao } = require('./utils/ambiente')
|
|
13
|
+
const { aplicacaoExecutandoLocalmente, formaDeExecucao, urlDocumentacao } = require('./utils/ambiente')
|
|
14
14
|
const { conf } = require('./utils/conf')
|
|
15
15
|
const errorHandler = require('./middlewares/error-handler')
|
|
16
16
|
const logger = require('./utils/logger')
|
|
17
17
|
const { version } = require('../package.json')
|
|
18
18
|
const swaggerDocument = require('../docs/swagger.json')
|
|
19
19
|
const rateLimiter = require('./middlewares/rate-limiter')
|
|
20
|
+
const packageJson = require('../package.json')
|
|
20
21
|
|
|
21
22
|
const ehAmbienteDeTestes = process.env.NODE_ENV === 'serverest-test'
|
|
22
23
|
|
|
@@ -46,6 +47,11 @@ if (!conf.semHeaderDeSeguranca) {
|
|
|
46
47
|
})
|
|
47
48
|
}
|
|
48
49
|
|
|
50
|
+
/* istanbul ignore next */
|
|
51
|
+
if (aplicacaoExecutandoLocalmente() && !ehAmbienteDeTestes) {
|
|
52
|
+
app.use(require('express-status-monitor')({ title: 'ServeRest Status' }))
|
|
53
|
+
}
|
|
54
|
+
|
|
49
55
|
logger(app)
|
|
50
56
|
|
|
51
57
|
/* istanbul ignore next */
|
|
@@ -53,11 +59,16 @@ switch (formaDeExecucao()) {
|
|
|
53
59
|
case 'serverest.dev':
|
|
54
60
|
swaggerDocument.host = 'serverest.dev'
|
|
55
61
|
break
|
|
62
|
+
case 'staging.serverest.dev':
|
|
63
|
+
swaggerDocument.host = 'staging.serverest.dev'
|
|
64
|
+
break
|
|
56
65
|
case 'agilizei':
|
|
57
66
|
swaggerDocument.host = 'agilizei.serverest.dev'
|
|
58
67
|
break
|
|
59
68
|
}
|
|
60
69
|
|
|
70
|
+
swaggerDocument.info.version = packageJson.version
|
|
71
|
+
|
|
61
72
|
const uiOptions = {
|
|
62
73
|
customSiteTitle: 'ServeRest',
|
|
63
74
|
customfavIcon: '/favicon.ico',
|
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const authService = require('../services/auth-service')
|
|
4
3
|
const constant = require('../utils/constants')
|
|
5
4
|
const produtosService = require('../services/produtos-service')
|
|
6
5
|
const service = require('../services/carrinhos-service')
|
|
7
|
-
const usuariosService = require('../services/usuarios-service')
|
|
8
6
|
|
|
9
7
|
exports.get = async (req, res) => {
|
|
10
8
|
const carrinhos = await service.getAll(req.query)
|
|
@@ -21,53 +19,40 @@ exports.getOne = async (req, res) => {
|
|
|
21
19
|
}
|
|
22
20
|
|
|
23
21
|
exports.post = async (req, res) => {
|
|
24
|
-
const {
|
|
25
|
-
|
|
26
|
-
const usuarioJaPossuiCarrinho = await service.existeCarrinho({ idUsuario: _id })
|
|
27
|
-
if (usuarioJaPossuiCarrinho) {
|
|
22
|
+
const { idUsuario, possuiCarrinho } = await service.usuarioJaPossuiCarrinho(req.headers.authorization)
|
|
23
|
+
if (possuiCarrinho) {
|
|
28
24
|
return res.status(400).send({ message: constant.LIMITE_1_CARRINHO })
|
|
29
25
|
}
|
|
30
26
|
|
|
31
27
|
const idProdutosDuplicados = service.extrairProdutosDuplicados(req.body.produtos)
|
|
32
|
-
const temProdutosDuplicados =
|
|
28
|
+
const temProdutosDuplicados = isNotUndefined(idProdutosDuplicados[0])
|
|
33
29
|
if (temProdutosDuplicados) {
|
|
34
30
|
return res.status(400).send({ message: constant.CARRINHO_COM_PRODUTO_DUPLICADO, idProdutosDuplicados })
|
|
35
31
|
}
|
|
36
32
|
|
|
37
|
-
const produtos = req.body
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
const {
|
|
41
|
-
if (
|
|
42
|
-
|
|
33
|
+
const { produtos } = req.body
|
|
34
|
+
const produtosComPrecoUnitario = []
|
|
35
|
+
for (const produto of produtos) {
|
|
36
|
+
const { precoUnitario: preco, error } = await produtosService.getPrecoUnitarioOuErro(produto)
|
|
37
|
+
if (error) {
|
|
38
|
+
const index = produtos.indexOf(produto)
|
|
39
|
+
const item = { ...error.item, index }
|
|
40
|
+
return res.status(error.statusCode).send({ message: error.message, item })
|
|
43
41
|
}
|
|
44
|
-
|
|
45
|
-
const { quantidade: quantidadeEstoque, preco } = await produtosService.getDadosDoProduto({ _id: idProduto })
|
|
46
|
-
if (quantidade > quantidadeEstoque) {
|
|
47
|
-
return res.status(400).send({ message: constant.ESTOQUE_INSUFICIENTE, item: { index, idProduto, quantidade, quantidadeEstoque } })
|
|
48
|
-
}
|
|
49
|
-
Object.assign(produtos[index], { precoUnitario: preco })
|
|
50
|
-
}
|
|
51
|
-
let precoTotal = 0
|
|
52
|
-
let quantidadeTotal = 0
|
|
53
|
-
for (let index = 0; index < produtos.length; index++) {
|
|
54
|
-
const { idProduto, quantidade } = produtos[index]
|
|
55
|
-
const { quantidade: quantidadeEmEstoque, preco } = await produtosService.getDadosDoProduto({ _id: idProduto })
|
|
56
|
-
const novaQuantidade = quantidadeEmEstoque - quantidade
|
|
57
|
-
await produtosService.updateById(idProduto, { $set: { quantidade: novaQuantidade } })
|
|
58
|
-
precoTotal += preco * quantidade
|
|
59
|
-
quantidadeTotal += quantidade
|
|
42
|
+
produtosComPrecoUnitario.push({ ...produto, precoUnitario: preco })
|
|
60
43
|
}
|
|
44
|
+
const precoTotal = await service.precoTotal(produtosComPrecoUnitario)
|
|
45
|
+
const quantidadeTotal = await service.quantidadeTotal(produtosComPrecoUnitario)
|
|
61
46
|
|
|
62
|
-
|
|
47
|
+
const carrinho = { produtos: produtosComPrecoUnitario, precoTotal, quantidadeTotal, idUsuario }
|
|
63
48
|
|
|
64
|
-
const dadosCadastrados = await service.criarCarrinho(
|
|
49
|
+
const dadosCadastrados = await service.criarCarrinho(carrinho)
|
|
65
50
|
res.status(201).send({ message: constant.POST_SUCESS, _id: dadosCadastrados._id })
|
|
66
51
|
}
|
|
67
52
|
|
|
68
53
|
exports.cancelarCompra = async (req, res) => {
|
|
69
54
|
const carrinhoDoUsuario = await service.getCarrinhoDoUsuario(req.headers.authorization)
|
|
70
|
-
const usuarioTemCarrinho =
|
|
55
|
+
const usuarioTemCarrinho = isNotUndefined(carrinhoDoUsuario[0])
|
|
71
56
|
|
|
72
57
|
if (usuarioTemCarrinho) {
|
|
73
58
|
const produtos = carrinhoDoUsuario[0].produtos
|
|
@@ -87,10 +72,14 @@ exports.cancelarCompra = async (req, res) => {
|
|
|
87
72
|
|
|
88
73
|
exports.concluirCompra = async (req, res) => {
|
|
89
74
|
const carrinhoDoUsuario = await service.getCarrinhoDoUsuario(req.headers.authorization)
|
|
90
|
-
const usuarioTemCarrinho =
|
|
75
|
+
const usuarioTemCarrinho = isNotUndefined(carrinhoDoUsuario[0])
|
|
91
76
|
if (usuarioTemCarrinho) {
|
|
92
77
|
await service.deleteById(carrinhoDoUsuario[0]._id)
|
|
93
78
|
return res.status(200).send({ message: constant.DELETE_SUCESS })
|
|
94
79
|
}
|
|
95
80
|
res.status(200).send({ message: constant.SEM_CARRINHO })
|
|
96
81
|
}
|
|
82
|
+
|
|
83
|
+
const isUndefined = (object) => typeof object === 'undefined'
|
|
84
|
+
|
|
85
|
+
const isNotUndefined = (object) => !isUndefined(object)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const { INTERNAL_ERROR } = require('../utils/constants')
|
|
1
|
+
const { INTERNAL_ERROR, TIMEOUT } = require('../utils/constants')
|
|
2
2
|
const montarMensagemDeErroDeSchema = require('../utils/montarMensagemDeErroDeSchema')
|
|
3
3
|
|
|
4
4
|
function errorHandler (error, _req, res, _next) {
|
|
@@ -10,9 +10,13 @@ function errorHandler (error, _req, res, _next) {
|
|
|
10
10
|
if (error.type === 'entity.parse.failed') {
|
|
11
11
|
console.log('Erro 500')
|
|
12
12
|
return res.status(500).json({
|
|
13
|
-
message: 'Adicione aspas em todos os valores.
|
|
13
|
+
message: 'Adicione aspas em todos os valores. Para mais informações acesse a issue https://github.com/ServeRest/ServeRest/issues/225'
|
|
14
14
|
})
|
|
15
15
|
}
|
|
16
|
+
/* istanbul ignore if */
|
|
17
|
+
if (error.code === 'ETIMEDOUT') {
|
|
18
|
+
return res.status(408).json({ message: TIMEOUT })
|
|
19
|
+
}
|
|
16
20
|
return res.status(500).json({ message: INTERNAL_ERROR, error })
|
|
17
21
|
}
|
|
18
22
|
|
|
@@ -2,17 +2,36 @@
|
|
|
2
2
|
|
|
3
3
|
const { RateLimiterMemory } = require('rate-limiter-flexible')
|
|
4
4
|
|
|
5
|
+
const { aplicacaoExecutandoLocalmente } = require('../utils/ambiente')
|
|
6
|
+
|
|
5
7
|
const rateLimiter = new RateLimiterMemory({
|
|
6
|
-
points:
|
|
7
|
-
duration:
|
|
8
|
+
points: 250, // requests
|
|
9
|
+
duration: 2 // segundo por IP
|
|
8
10
|
})
|
|
9
11
|
|
|
10
|
-
//
|
|
12
|
+
// Irá retornar mensagem de erro se o teste de carga:
|
|
13
|
+
// 1. Estiver sendo executado em localhost sem o header 'monitor'.
|
|
14
|
+
// 2. Estiver sendo executado fora de localhost.
|
|
11
15
|
module.exports = async (req, res, next) => {
|
|
16
|
+
const reqContainsHeaderMonitor = req.rawHeaders.includes('monitor')
|
|
17
|
+
|
|
18
|
+
const messageLoadTest = 'Foi detectado comportamento equivalente a teste de carga'
|
|
19
|
+
const messageAdjust = 'Leia a seção sobre teste de carga https://github.com/ServeRest/ServeRest#teste-de-carga e faça o ajuste necessário.'
|
|
20
|
+
|
|
12
21
|
await rateLimiter.consume(req.ip)
|
|
13
22
|
.then(() => next())
|
|
14
23
|
.catch(() => {
|
|
15
|
-
|
|
24
|
+
if (aplicacaoExecutandoLocalmente()) {
|
|
25
|
+
if (!reqContainsHeaderMonitor) {
|
|
26
|
+
return res.status(429).send({
|
|
27
|
+
message: `${messageLoadTest} com ausência do header 'monitor'. ${messageAdjust}`
|
|
28
|
+
})
|
|
29
|
+
}
|
|
30
|
+
} else {
|
|
31
|
+
return res.status(429).send({
|
|
32
|
+
message: `${messageLoadTest}. ${messageAdjust}`
|
|
33
|
+
})
|
|
34
|
+
}
|
|
16
35
|
next()
|
|
17
36
|
})
|
|
18
37
|
}
|
|
@@ -6,6 +6,7 @@ const { join } = require('path')
|
|
|
6
6
|
const alterarValoresParaRegex = require('../utils/alterarValoresParaRegex')
|
|
7
7
|
const authService = require('../services/auth-service')
|
|
8
8
|
const usuariosService = require('../services/usuarios-service')
|
|
9
|
+
const produtosService = require('../services/produtos-service')
|
|
9
10
|
|
|
10
11
|
const datastore = Datastore.create({ filename: join(__dirname, '../data/carrinhos.db'), autoload: true })
|
|
11
12
|
|
|
@@ -42,7 +43,33 @@ exports.deleteById = async id => {
|
|
|
42
43
|
}
|
|
43
44
|
|
|
44
45
|
exports.getCarrinhoDoUsuario = async (authorization) => {
|
|
46
|
+
const _id = await idUsuario(authorization)
|
|
47
|
+
return this.getAll({ idUsuario: _id })
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
exports.usuarioJaPossuiCarrinho = async (authorization) => {
|
|
51
|
+
const _id = await idUsuario(authorization)
|
|
52
|
+
return {
|
|
53
|
+
idUsuario: _id,
|
|
54
|
+
possuiCarrinho: await this.existeCarrinho({ idUsuario: _id })
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
exports.precoTotal = async (produtos) => {
|
|
59
|
+
return produtos.reduce(async (precoAnterior, produto) => {
|
|
60
|
+
return (await precoAnterior) + produto.precoUnitario * produto.quantidade
|
|
61
|
+
}, Promise.resolve(0))
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
exports.quantidadeTotal = async (produtos) => {
|
|
65
|
+
return produtos.reduce(async (quantidadeAnterior, produto) => {
|
|
66
|
+
await produtosService.updateQuantidade(produto)
|
|
67
|
+
return (await quantidadeAnterior) + produto.quantidade
|
|
68
|
+
}, Promise.resolve(0))
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const idUsuario = async (authorization) => {
|
|
45
72
|
const { email, password } = authService.verifyToken(authorization)
|
|
46
|
-
const { _id
|
|
47
|
-
return
|
|
73
|
+
const { _id } = await usuariosService.getDadosDoUsuario({ email, password })
|
|
74
|
+
return _id
|
|
48
75
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
+
const constant = require('../utils/constants')
|
|
3
4
|
const Datastore = require('nedb-promises')
|
|
4
5
|
const { join } = require('path')
|
|
5
6
|
|
|
@@ -24,11 +25,32 @@ exports.existeProduto = pesquisa => {
|
|
|
24
25
|
return datastore.count(pesquisa)
|
|
25
26
|
}
|
|
26
27
|
|
|
28
|
+
exports.updateQuantidade = async ({ idProduto, quantidade }) => {
|
|
29
|
+
const { quantidade: quantidadeEmEstoque } = await this.getDadosDoProduto({ _id: idProduto })
|
|
30
|
+
const novaQuantidade = quantidadeEmEstoque - quantidade
|
|
31
|
+
await this.updateById(idProduto, { $set: { quantidade: novaQuantidade } })
|
|
32
|
+
}
|
|
33
|
+
|
|
27
34
|
exports.criarProduto = async body => {
|
|
28
35
|
body = formatarValores(body)
|
|
29
36
|
return datastore.insert(body)
|
|
30
37
|
}
|
|
31
38
|
|
|
39
|
+
exports.getPrecoUnitarioOuErro = async (produto) => {
|
|
40
|
+
const quantidade = parseInt(produto.quantidade)
|
|
41
|
+
const { idProduto } = produto
|
|
42
|
+
const existePedido = await this.existeProduto({ _id: idProduto })
|
|
43
|
+
if (!existePedido) {
|
|
44
|
+
return { error: { statusCode: 400, message: constant.IDPRODUTO_INVALIDO, item: { idProduto, quantidade } } }
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const { quantidade: quantidadeEstoque, preco } = await this.getDadosDoProduto({ _id: idProduto })
|
|
48
|
+
if (quantidade > quantidadeEstoque) {
|
|
49
|
+
return { error: { statusCode: 400, message: constant.ESTOQUE_INSUFICIENTE, item: { idProduto, quantidade, quantidadeEstoque } } }
|
|
50
|
+
}
|
|
51
|
+
return { precoUnitario: preco }
|
|
52
|
+
}
|
|
53
|
+
|
|
32
54
|
exports.deleteById = async id => {
|
|
33
55
|
return datastore.remove({ _id: id }, {})
|
|
34
56
|
}
|
package/src/utils/ambiente.js
CHANGED
|
@@ -5,24 +5,32 @@ const { conf } = require('./conf')
|
|
|
5
5
|
function formaDeExecucao () {
|
|
6
6
|
if (process.env.USERNAME === 'docker' ||
|
|
7
7
|
process.env.USERNAME === 'serverest.dev' ||
|
|
8
|
+
process.env.USERNAME === 'staging.serverest.dev' ||
|
|
8
9
|
process.env.USERNAME === 'agilizei') {
|
|
9
10
|
return process.env.USERNAME
|
|
10
11
|
}
|
|
11
12
|
return 'npm'
|
|
12
13
|
}
|
|
13
14
|
|
|
15
|
+
const aplicacaoExecutandoLocalmente = () => {
|
|
16
|
+
return (formaDeExecucao() === 'npm' || formaDeExecucao() === 'docker')
|
|
17
|
+
}
|
|
18
|
+
|
|
14
19
|
function urlDocumentacao () {
|
|
15
20
|
switch (formaDeExecucao()) {
|
|
16
21
|
case 'serverest.dev':
|
|
17
22
|
return 'https://serverest.dev'
|
|
23
|
+
case 'staging.serverest.dev':
|
|
24
|
+
return 'https://staging.serverest.dev'
|
|
18
25
|
case 'agilizei':
|
|
19
|
-
return 'https://serverest
|
|
26
|
+
return 'https://agilizei.serverest.dev'
|
|
20
27
|
default:
|
|
21
28
|
return `http://localhost:${conf.porta}`
|
|
22
29
|
}
|
|
23
30
|
}
|
|
24
31
|
|
|
25
32
|
module.exports = {
|
|
33
|
+
aplicacaoExecutandoLocalmente,
|
|
26
34
|
formaDeExecucao,
|
|
27
35
|
urlDocumentacao
|
|
28
36
|
}
|
package/src/utils/constants.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
module.exports = {
|
|
4
4
|
INTERNAL_ERROR: 'Abra uma issue informando essa resposta. https://github.com/ServeRest/ServeRest/issues',
|
|
5
|
+
TIMEOUT: 'Timeout da requisição atingido',
|
|
5
6
|
POST_SUCESS: 'Cadastro realizado com sucesso',
|
|
6
7
|
DELETE_SUCESS: 'Registro excluído com sucesso',
|
|
7
8
|
DELETE_NONE: 'Nenhum registro excluído',
|
package/src/utils/logger.js
CHANGED
|
@@ -38,6 +38,7 @@ module.exports = async app => {
|
|
|
38
38
|
req.originalUrl === '/swagger-ui-bundle.js.map' ||
|
|
39
39
|
req.headers.monitor ||
|
|
40
40
|
(formaDeExecucao() === 'serverest.dev' && req.originalUrl === '/') ||
|
|
41
|
+
(formaDeExecucao() === 'staging.serverest.dev' && req.originalUrl === '/') ||
|
|
41
42
|
(formaDeExecucao() === 'agilizei' && req.originalUrl === '/')) {
|
|
42
43
|
return true
|
|
43
44
|
}
|