From 8e322285d61b4d7df4506d5137fe28a2d96b19f8 Mon Sep 17 00:00:00 2001 From: ScottAgirs Date: Tue, 31 Mar 2020 00:51:15 -0400 Subject: [PATCH] [add] changePassword mutation Signed-off-by: ScottAgirs --- packages/strapi-admin/config/routes.json | 5 ++ packages/strapi-admin/controllers/Auth.js | 84 +++++++++++++++++++ .../config/routes.json | 14 ++++ .../controllers/Auth.js | 77 ++++++++++++++++- 4 files changed, 176 insertions(+), 4 deletions(-) diff --git a/packages/strapi-admin/config/routes.json b/packages/strapi-admin/config/routes.json index 9963242794..185c86d731 100644 --- a/packages/strapi-admin/config/routes.json +++ b/packages/strapi-admin/config/routes.json @@ -69,6 +69,11 @@ "path": "/auth/forgot-password", "handler": "Auth.forgotPassword" }, + { + "method": "POST", + "path": "/auth/change-password", + "handler": "Auth.changePassword" + }, { "method": "POST", "path": "/auth/reset-password", diff --git a/packages/strapi-admin/controllers/Auth.js b/packages/strapi-admin/controllers/Auth.js index 6ed9bfc835..02d5629659 100644 --- a/packages/strapi-admin/controllers/Auth.js +++ b/packages/strapi-admin/controllers/Auth.js @@ -199,6 +199,90 @@ module.exports = { } }, + async changePassword(ctx) { + const id = ctx.state.user && ctx.state.user.id; + if (!id) { + return ctx.badRequest( + null, + formatError({ + id: 'Auth.form.error.user.not-exist', + message: 'Must be logged in.', + }) + ); + } + + const admin = await strapi.query('administrator', 'admin').findOne({ id }); + + const { password, passwordConfirmation, currentPassword } = { + ...ctx.request.body, + ...ctx.params, + }; + + if (!password) { + return ctx.badRequest( + null, + formatError({ + id: 'missing.password', + message: 'Missing password', + }) + ); + } + + if (!passwordConfirmation) { + return ctx.badRequest( + formatError({ + id: 'missing.passwordConfirmation', + message: 'Missing passwordConfirmation', + }) + ); + } + + if (!currentPassword) { + return ctx.badRequest( + null, + formatError({ + id: 'missing.currentPassword', + message: 'Missing current password', + }) + ); + } + + if (password !== passwordConfirmation) { + return ctx.badRequest( + null, + formatError({ + id: 'Auth.form.error.password.matching', + message: 'Passwords do not match.', + }) + ); + } + + const validPassword = await strapi.plugins['users-permissions'].services.user.validatePassword( + currentPassword, + admin.password + ); + + if (!validPassword) { + return ctx.badRequest( + null, + formatError({ + id: 'Auth.form.error.invalid', + message: 'Identifier or password invalid.', + }) + ); + } + + const data = { + password: await strapi.admin.services.auth.hashPassword(currentPassword), + }; + + await strapi.query('administrator', 'admin').update({ id: admin.id }, data); + + return ctx.send({ + ok: true, + }); + }, + async resetPassword(ctx) { const { password, passwordConfirmation, code } = { ...ctx.request.body, diff --git a/packages/strapi-plugin-users-permissions/config/routes.json b/packages/strapi-plugin-users-permissions/config/routes.json index a06e65ff71..2e31f96f63 100644 --- a/packages/strapi-plugin-users-permissions/config/routes.json +++ b/packages/strapi-plugin-users-permissions/config/routes.json @@ -257,6 +257,20 @@ } } }, + { + "method": "POST", + "path": "/auth/change-password", + "handler": "Auth.changePassword", + "config": { + "policies": ["plugins::users-permissions.ratelimit"], + "prefix": "", + "description": "Change user password. Verifies with current password", + "tag": { + "plugin": "users-permissions", + "name": "User" + } + } + }, { "method": "POST", "path": "/auth/reset-password", diff --git a/packages/strapi-plugin-users-permissions/controllers/Auth.js b/packages/strapi-plugin-users-permissions/controllers/Auth.js index eeb729d4d5..362059ed36 100644 --- a/packages/strapi-plugin-users-permissions/controllers/Auth.js +++ b/packages/strapi-plugin-users-permissions/controllers/Auth.js @@ -177,6 +177,75 @@ module.exports = { } }, + async changePassword(ctx) { + const params = _.assign({}, ctx.request.body, ctx.params); + + if ( + params.password && + params.passwordConfirmation && + params.password === params.passwordConfirmation && + params.currentPassword + ) { + const id = ctx.state.user && ctx.state.user.id; + if (!id) { + return ctx.badRequest( + null, + formatError({ + id: 'Auth.form.error.user.not-exist', + message: 'Must be logged in.', + }) + ); + } + + const user = await strapi.plugins['users-permissions'].services.user.fetch({ id }); + + const validPassword = await strapi.plugins[ + 'users-permissions' + ].services.user.validatePassword(params.currentPassword, user.password); + + if (!validPassword) { + return ctx.badRequest( + null, + formatError({ + id: 'Auth.form.error.invalid', + message: 'Identifier or password invalid.', + }) + ); + } else { + // Hash and Replace current password with the new one in the user object. + user.password = await strapi.plugins['users-permissions'].services.user.hashPassword({ + password: params.password, + }); + + // Update the user. + await strapi.query('user', 'users-permissions').update({ id: user.id }, user); + + ctx.send({ + ok: true, + }); + } + } else if ( + params.password && + params.passwordConfirmation && + params.password !== params.passwordConfirmation + ) { + return ctx.badRequest( + null, + formatError({ + id: 'Auth.form.error.password.matching', + message: 'Passwords do not match.', + }) + ); + } else { + return ctx.badRequest( + null, + formatError({ + id: 'Auth.form.error.params.provide', + message: 'Incorrect params provided.', + }) + ); + } + }, async resetPassword(ctx) { const params = _.assign({}, ctx.request.body, ctx.params); @@ -580,14 +649,14 @@ module.exports = { { confirmed: true } ); - if(returnUser) { + if (returnUser) { ctx.send({ jwt: strapi.plugins['users-permissions'].services.jwt.issue({ - id: user.id + id: user.id, }), user: sanitizeEntity(user.toJSON ? user.toJSON() : user, { - model: strapi.query('user', 'users-permissions').model - }) + model: strapi.query('user', 'users-permissions').model, + }), }); } else { const settings = await strapi