UNPKG

@dreesq/serpent

Version:

An express wrapper for developing fast web applications

134 lines (112 loc) 3.78 kB
const {config, getPlugins} = require('../index'); const {config: configPlugin} = getPlugins(); const {error, success, makeToken, hookRunner} = require('../utils'); const bcrypt = require('bcryptjs'); const moment = require('moment'); const { ACTION_REQUEST, ACTION_HANDLE, TOKEN_TYPE_RESET, RESET_TOKEN_EXPIRY, TOKEN_TYPE_REFRESH } = require('../constants'); config({ name: 'resetPassword', input: { action: 'required|number', email: 'email|when:action,0', token: 'when:action,1|min:64', password: 'when:action,1|min:10' }, enabled: configPlugin.get('plugins.auth.reset') })( /** * Confirm user account * @param db * @param input * @param i18n * @param mail * @param config * @param utils * @param options * @param crypto * @returns {Promise<void>} */ async ({db, input, i18n, config, mail, utils, options, crypto}) => { const {User, Token} = db; const runner = hookRunner(options); /** * When requesting password reset */ if (+input.action === ACTION_REQUEST) { const user = await User.findOne({email: input.email}); runner('before', user, input); if (!user) { return error(i18n.translate('errors.invalidEmail')); } const token = await makeToken(); await Token.create({ userId: user._id, type: TOKEN_TYPE_RESET, token: await crypto.hash(token) }); const t = i18n.translator(user.locale).translate; await mail({ to: input.email, subject: t('emails.resetAccount.subject'), html: t('emails.resetAccount.html', { url: utils.url('reset', {token}), user }) }); runner('after', user, input); return success(t('messages.resetRequested')); } /** * When requesting password update */ if (+input.action === ACTION_HANDLE) { const token = await Token.findOne({ token: await crypto.hash(input.token), type: TOKEN_TYPE_RESET }); if (!token) { return error(i18n.translate('errors.invalidToken')); } const diff = moment().diff(moment(token.createdAt), 'days'); if (diff > RESET_TOKEN_EXPIRY) { return error(i18n.translate('errors.expiredToken')); } const user = await User.findOne({_id: token.userId}); runner('before', user, input); const t = i18n.translator(user.locale).translate; if (!user) { await token.remove(); return error(t('errors.invalidUser')); } user.password = await bcrypt.hash(input.password, 10); user.ts = moment().unix(); await user.save(); await Token.deleteMany({ userId: user._id, type: { $in: [ TOKEN_TYPE_RESET, TOKEN_TYPE_REFRESH ] } }); if (config.get('plugins.auth.notify')) { await mail({ to: input.email, subject: t('emails.accountReset.subject'), html: t('emails.accountReset.html', { user }) }); } runner('after', user, input); return success(t('messages.resetDone')); } } );