From 48374f5f3ae320ce9aacfd4b128ce82e7b7b491d Mon Sep 17 00:00:00 2001 From: Filipe Deschamps Date: Mon, 15 Aug 2022 23:50:14 +0000 Subject: [PATCH] feat(middleware): mimic `GET` behavior on `/api/v1/sessions` and log requests --- errors/index.js | 3 +- .../rate-limit-reached-sessions.public.js | 59 ++++++++++++++++++- .../_responses/rate-limit-reached.public.js | 16 ++++- 3 files changed, 73 insertions(+), 5 deletions(-) diff --git a/errors/index.js b/errors/index.js index c86b91cbf..4fe6cbe75 100644 --- a/errors/index.js +++ b/errors/index.js @@ -115,11 +115,12 @@ export class ForbiddenError extends BaseError { } export class TooManyRequestsError extends BaseError { - constructor({ message, action, stack, errorLocationCode }) { + constructor({ message, action, context, stack, errorLocationCode }) { super({ message: message || 'Você realizou muitas requisições recentemente.', action: action || 'Tente novamente mais tarde ou contate o suporte caso acredite que isso seja um erro.', statusCode: 429, + context: context, stack: stack, errorLocationCode: errorLocationCode, }); diff --git a/pages/api/v1/_responses/rate-limit-reached-sessions.public.js b/pages/api/v1/_responses/rate-limit-reached-sessions.public.js index 8121a52db..aab82fc58 100644 --- a/pages/api/v1/_responses/rate-limit-reached-sessions.public.js +++ b/pages/api/v1/_responses/rate-limit-reached-sessions.public.js @@ -1,8 +1,63 @@ -import { UnauthorizedError } from 'errors/index.js'; +import nextConnect from 'next-connect'; import { v4 as uuidV4 } from 'uuid'; import snakeize from 'snakeize'; +import logger from 'infra/logger.js'; +import controller from 'models/controller.js'; +import validator from 'models/validator.js'; +import { UnauthorizedError, ForbiddenError, TooManyRequestsError } from 'errors/index.js'; -export default async function handler(request, response) { +export default nextConnect({ + onError: controller.onErrorHandler, +}) + .use(controller.injectRequestMetadata) + .use(logRequest) + .get(getValidationHandler, getHandler) + .post(postValidationHandler, postHandler); + +function getValidationHandler(request, response) { + validator(request.cookies, { + session_id: 'required', + }); + + next(); +} + +function logRequest(request, response, next) { + const error = new TooManyRequestsError({ + context: { + method: request.method, + url: request.url, + body: request.body, + }, + }); + + logger.error(snakeize(error)); + + next(); +} + +function getHandler(request, response) { + const error = new ForbiddenError({ + message: 'Usuário não pode executar esta operação.', + action: 'Verifique se este usuário possui a feature "read:session".', + requestId: uuidV4(), + errorId: uuidV4(), + errorLocationCode: 'MODEL:AUTHORIZATION:CAN_REQUEST:FEATURE_NOT_FOUND', + }); + + response.status(error.statusCode).json(snakeize(error)); +} + +function postValidationHandler(request, response, next) { + validator(request.body, { + email: 'required', + password: 'required', + }); + + next(); +} + +async function postHandler(request, response) { const error = new UnauthorizedError({ message: 'Dados não conferem.', action: 'Verifique se os dados enviados estão corretos.', diff --git a/pages/api/v1/_responses/rate-limit-reached.public.js b/pages/api/v1/_responses/rate-limit-reached.public.js index e4c9ac1a6..c5614711a 100644 --- a/pages/api/v1/_responses/rate-limit-reached.public.js +++ b/pages/api/v1/_responses/rate-limit-reached.public.js @@ -1,6 +1,18 @@ +import snakeize from 'snakeize'; +import logger from 'infra/logger.js'; import { TooManyRequestsError } from 'errors/index.js'; export default function handler(request, response) { - const error = new TooManyRequestsError({}); - response.status(error.statusCode).json(error); + const error = new TooManyRequestsError({ + context: { + method: request.method, + url: request.url, + body: request.body, + }, + }); + + logger.error(snakeize(error)); + delete error.context; + + response.status(error.statusCode).json(snakeize(error)); }