UNPKG

feathers-authentication-management

Version:

Adds sign up verification, forgotten password reset, and other capabilities to local feathers-authentication

175 lines (154 loc) 4.26 kB
import { BadRequest } from '@feathersjs/errors'; import makeDebug from 'debug'; import { ensureObjPropsValid, ensureValuesAreStrings, getUserData, hashPassword, isDateAfterNow, notify } from '../helpers'; import type { Id, Params } from '@feathersjs/feathers'; import type { VerifyChanges } from '..'; import type { IdentifyUser, SanitizedUser, Tokens, User, VerifySignupSetPasswordOptions, VerifySignupSetPasswordWithShortTokenOptions, NotifierOptions } from '../types'; const debug = makeDebug('authLocalMgnt:verifySignupSetPassword'); export async function verifySignupSetPasswordWithLongToken ( options: VerifySignupSetPasswordOptions, verifyToken: string, password: string, notifierOptions: NotifierOptions = {}, params?: Params ): Promise<SanitizedUser> { ensureValuesAreStrings(verifyToken, password); const result = await verifySignupSetPassword( options, { verifyToken }, { verifyToken }, password, notifierOptions, params ); return result; } export async function verifySignupSetPasswordWithShortToken ( options: VerifySignupSetPasswordWithShortTokenOptions, verifyShortToken: string, identifyUser: IdentifyUser, password: string, notifierOptions: NotifierOptions = {}, params?: Params ): Promise<SanitizedUser> { ensureValuesAreStrings(verifyShortToken, password); ensureObjPropsValid(identifyUser, options.identifyUserProps); const result = await verifySignupSetPassword( options, identifyUser, { verifyShortToken }, password, notifierOptions, params ); return result; } async function verifySignupSetPassword ( options: VerifySignupSetPasswordOptions, identifyUser: IdentifyUser, tokens: Tokens, password: string, notifierOptions: NotifierOptions = {}, params?: Params ): Promise<SanitizedUser> { debug('verifySignupSetPassword', identifyUser, tokens, password); if (params && "query" in params) { params = Object.assign({}, params); delete params.query; } const { app, passwordField, skipPasswordHash, sanitizeUserForClient, service, notifier } = options; const usersService = app.service(service); const usersServiceId = usersService.id; const users = await usersService.find({ ...params, query: { ...identifyUser, $limit: 2 }, paginate: false, }) as User[]; const user = getUserData(users, [ 'isNotVerifiedOrHasVerifyChanges', 'verifyNotExpired' ]); if (!Object.keys(tokens).every((key) => tokens[key] === user[key])) { await eraseVerifyProps(user, user.isVerified, params); throw new BadRequest( 'Invalid token. Get for a new one. (authLocalMgnt)', { errors: { $className: 'badParam' } } ); } const userErasedVerify = await eraseVerifyPropsSetPassword( user, isDateAfterNow(user.verifyExpires), user.verifyChanges || {}, password, skipPasswordHash, params ); const userResult = await notify(notifier, 'verifySignupSetPassword', userErasedVerify, notifierOptions); return sanitizeUserForClient(userResult); async function eraseVerifyProps ( user: User, isVerified: boolean, params?: Params ): Promise<User> { const patchData = Object.assign({}, { isVerified, verifyToken: null, verifyShortToken: null, verifyExpires: null, verifyChanges: {}, }); const result = await usersService.patch( user[usersServiceId] as Id, patchData, Object.assign({}, params) ) as User; return result; } async function eraseVerifyPropsSetPassword ( user: User, isVerified: boolean, verifyChanges: VerifyChanges, password: string, skipPasswordHash: boolean, params?: Params ): Promise<User> { const patchData = Object.assign({}, verifyChanges || {}, { isVerified, verifyToken: null, verifyShortToken: null, verifyExpires: null, verifyChanges: {}, [passwordField]: skipPasswordHash ? password : await hashPassword(app, password, passwordField) }); const result = await usersService.patch( user[usersServiceId] as Id, patchData, Object.assign({}, params) ) as User; return result; } }