From 8246bb69b29f02bfaa600c6776049152bee7c2bc Mon Sep 17 00:00:00 2001 From: Diana Morales Date: Wed, 10 Nov 2021 16:46:39 +0100 Subject: [PATCH] login web endpoint fastify body schema validation (#2653) * feat: add body schema validation to login endpoint #2623 When a request is made, the following error is displayed on log error--- Promise may not be fulfilled with 'undefined' when statusCode is not 204 https://github.com/fastify/fastify/pull/2702 * feat: add body schema validation to resetPassword endpoint Co-authored-by: Juan Picado --- .../core/server/src/routes/web/api/login.ts | 148 +++++++++++------- 1 file changed, 91 insertions(+), 57 deletions(-) diff --git a/packages/core/server/src/routes/web/api/login.ts b/packages/core/server/src/routes/web/api/login.ts index 30ef2aabe..30c0486b6 100644 --- a/packages/core/server/src/routes/web/api/login.ts +++ b/packages/core/server/src/routes/web/api/login.ts @@ -6,70 +6,104 @@ import { JWTSignOptions } from '@verdaccio/types'; import { validatePassword } from '@verdaccio/utils'; const debug = buildDebug('verdaccio:api:login'); +const loginBodySchema = { + body: { + type: 'object', + required: ['username', 'password'], + additionalProperties: false, + properties: { + username: { type: 'string' }, + password: { type: 'string' }, + }, + }, +}; + +const resetPasswordSchema = { + body: { + type: 'object', + required: ['password'], + additionalProperties: false, + properties: { + password: { type: 'string' }, + }, + }, +}; async function loginRoute(fastify: FastifyInstance) { - fastify.post('/login', async (request, reply) => { - // @ts-expect-error - const { username, password } = request.body; - debug('authenticate %o', username); - fastify.auth.authenticate( - username, - password, - async function callbackAuthenticate(err, user): Promise { - if (err) { - const errorCode = err.message - ? fastify.statusCode.UNAUTHORIZED - : fastify.statusCode.INTERNAL_ERROR; - reply.send(fastify.errorUtils.getCode(errorCode, err.message)); - } else { - const jWTSignOptions: JWTSignOptions = fastify.configInstance.security.web.sign; - debug('jwtSignOptions: %o', jWTSignOptions); - const token = await fastify.auth.jwtEncrypt(user, jWTSignOptions); - reply.code(fastify.statusCode.OK).send({ token, username }); - } - } - ); - }); - - fastify.put('/reset_password', async (request, reply) => { - if (_.isNil(request.userRemote.name)) { - reply.send( - fastify.errorUtils.getCode( - fastify.statusCode.UNAUTHORIZED, - fastify.errorUtils.API_ERROR.MUST_BE_LOGGED - ) - ); - } - // @ts-ignore - const { password } = request.body; - const { name } = request.userRemote; - - if (validatePassword(password.new) === false) { - fastify.auth.changePassword( - name as string, - password.old, - password.new, - (err, isUpdated): void => { - if (_.isNil(err) && isUpdated) { - reply.code(fastify.statusCode.OK); + fastify.post( + '/login', + { + schema: loginBodySchema, + }, + async (request, reply) => { + // @ts-expect-error + const { username, password } = request.body; + debug('authenticate %o', username); + fastify.auth.authenticate( + username, + password, + async function callbackAuthenticate(err, user): Promise { + if (err) { + const errorCode = err.message + ? fastify.statusCode.UNAUTHORIZED + : fastify.statusCode.INTERNAL_ERROR; + reply.send(fastify.errorUtils.getCode(errorCode, err.message)); } else { - reply.send( - fastify.errorUtils.getInternalError( - fastify.errorUtils.API_ERROR.INTERNAL_SERVER_ERROR - ) - ); + const jWTSignOptions: JWTSignOptions = fastify.configInstance.security.web.sign; + debug('jwtSignOptions: %o', jWTSignOptions); + const token = await fastify.auth.jwtEncrypt(user, jWTSignOptions); + reply.code(fastify.statusCode.OK).send({ token, username }); } } ); - } else { - reply.send( - fastify.errorUtils.getCode( - fastify.statusCode.BAD_REQUEST, - fastify.errorUtils.APP_ERROR.PASSWORD_VALIDATION - ) - ); } - }); + ); + + fastify.put( + '/reset_password', + { + schema: resetPasswordSchema, + }, + async (request, reply) => { + if (_.isNil(request.userRemote.name)) { + reply.send( + fastify.errorUtils.getCode( + fastify.statusCode.UNAUTHORIZED, + fastify.errorUtils.API_ERROR.MUST_BE_LOGGED + ) + ); + } + // @ts-ignore + const { password } = request.body; + const { name } = request.userRemote; + + if (validatePassword(password.new) === false) { + fastify.auth.changePassword( + name as string, + password.old, + password.new, + (err, isUpdated): void => { + if (_.isNil(err) && isUpdated) { + reply.code(fastify.statusCode.OK); + } else { + reply.send( + fastify.errorUtils.getInternalError( + fastify.errorUtils.API_ERROR.INTERNAL_SERVER_ERROR + ) + ); + } + } + ); + } else { + reply.send( + fastify.errorUtils.getCode( + fastify.statusCode.BAD_REQUEST, + fastify.errorUtils.APP_ERROR.PASSWORD_VALIDATION + ) + ); + } + } + ); // }); } export default loginRoute;