diff --git a/test/api/v4/user/POST-user_reset.test.js b/test/api/v4/user/POST-user_reset.test.js index c96e30f93a..2aba79baff 100644 --- a/test/api/v4/user/POST-user_reset.test.js +++ b/test/api/v4/user/POST-user_reset.test.js @@ -21,7 +21,9 @@ describe('POST /user/reset', () => { type: 'habit', }); - await user.post('/user/reset'); + await user.post('/user/reset', { + password: 'password', + }); await user.sync(); await expect(user.get(`/tasks/${task._id}`)).to.eventually.be.rejected.and.eql({ @@ -39,7 +41,9 @@ describe('POST /user/reset', () => { type: 'daily', }); - await user.post('/user/reset'); + await user.post('/user/reset', { + password: 'password', + }); await user.sync(); await expect(user.get(`/tasks/${task._id}`)).to.eventually.be.rejected.and.eql({ @@ -57,7 +61,9 @@ describe('POST /user/reset', () => { type: 'todo', }); - await user.post('/user/reset'); + await user.post('/user/reset', { + password: 'password', + }); await user.sync(); await expect(user.get(`/tasks/${task._id}`)).to.eventually.be.rejected.and.eql({ @@ -75,7 +81,9 @@ describe('POST /user/reset', () => { type: 'reward', }); - await user.post('/user/reset'); + await user.post('/user/reset', { + password: 'password', + }); await user.sync(); await expect(user.get(`/tasks/${task._id}`)).to.eventually.be.rejected.and.eql({ @@ -87,6 +95,26 @@ describe('POST /user/reset', () => { expect(user.tasksOrder.rewards).to.be.empty; }); + it('does not allow to reset if the password is missing', async () => { + await expect(user.post('/user/reset', { + password: '', + })).to.eventually.be.rejected.and.eql({ + code: 400, + error: 'BadRequest', + message: t('missingPassword'), + }); + }); + + it('does not allow to reset if the password is wrong', async () => { + await expect(user.post('/user/reset', { + password: 'passdw', + })).to.eventually.be.rejected.and.eql({ + code: 401, + error: 'NotAuthorized', + message: t('wrongPassword'), + }); + }); + it('does not delete challenge or group tasks', async () => { const guild = await generateGroup(user, {}, { 'purchased.plan.customerId': 'group-unlimited' }); const challenge = await generateChallenge(user, guild); @@ -102,7 +130,9 @@ describe('POST /user/reset', () => { }); await user.post(`/tasks/${groupTask._id}/assign`, [user._id]); - await user.post('/user/reset'); + await user.post('/user/reset', { + password: 'password', + }); await user.sync(); await user.put('/user', { @@ -133,7 +163,9 @@ describe('POST /user/reset', () => { }, }); - await hero.post('/user/reset'); + await user.post('/user/reset', { + password: 'password', + }); const heroRes = await admin.get(`/hall/heroes/${hero.auth.local.username}`); diff --git a/website/client/src/pages/settings/inlineSettings/resetAccount.vue b/website/client/src/pages/settings/inlineSettings/resetAccount.vue index c376d7fe25..807ff3a5b7 100644 --- a/website/client/src/pages/settings/inlineSettings/resetAccount.vue +++ b/website/client/src/pages/settings/inlineSettings/resetAccount.vue @@ -59,7 +59,6 @@
- Todo Password Check for Reset (Missing in the API) window.location.reload(true), 100); }, diff --git a/website/server/controllers/api-v4/user.js b/website/server/controllers/api-v4/user.js index b0e6e59773..52b5e6d895 100644 --- a/website/server/controllers/api-v4/user.js +++ b/website/server/controllers/api-v4/user.js @@ -3,6 +3,8 @@ import * as userLib from '../../libs/user'; import { verifyDisplayName } from '../../libs/user/validation'; import common from '../../../common'; import { TransactionModel as Transaction } from '../../models/transaction'; +import { BadRequest, NotAuthorized } from '../../libs/errors'; +import * as passwordUtils from '../../libs/password'; const api = {}; @@ -60,7 +62,7 @@ const api = {}; * } * } * -*/ + */ api.getUser = { method: 'GET', middlewares: [authWithHeaders()], @@ -193,6 +195,8 @@ api.userReroll = { * @apiName UserReset * @apiGroup User * + * @apiParam (Body) {String} password The user's password + * * @apiSuccess {Object} data.user * @apiSuccess {Array} data.tasksToRemove IDs of removed tasks * @apiSuccess {String} message Success message @@ -214,6 +218,17 @@ api.userReset = { middlewares: [authWithHeaders()], url: '/user/reset', async handler (req, res) { + const { user } = res.locals; + const { password } = req.body; + if (!password) { + throw new BadRequest(res.t('missingPassword')); + } + + const isValidPassword = await passwordUtils.compare(user, password); + if (!isValidPassword) { + throw new NotAuthorized(res.t('wrongPassword')); + } + await userLib.reset(req, res, { isV3: false }); }, };