feathers-authentication-management
Version:
Adds sign up verification, forgotten password reset, and other capabilities to local feathers-authentication
142 lines (124 loc) • 3.27 kB
text/typescript
import { BadRequest } from '@feathersjs/errors';
import makeDebug from 'debug';
import {
ensureObjPropsValid,
ensureValuesAreStrings,
getUserData,
notify,
isDateAfterNow
} from '../helpers';
import type { Id, Params } from '@feathersjs/feathers';
import type {
SanitizedUser,
VerifySignupOptions,
VerifySignupWithShortTokenOptions,
Tokens,
User,
IdentifyUser,
NotifierOptions,
VerifyChanges
} from '../types';
const debug = makeDebug('authLocalMgnt:verifySignup');
export async function verifySignupWithLongToken (
options: VerifySignupOptions,
verifyToken: string,
notifierOptions: NotifierOptions = {},
params?: Params
): Promise<SanitizedUser> {
ensureValuesAreStrings(verifyToken);
const result = await verifySignup(
options,
{ verifyToken },
{ verifyToken },
notifierOptions,
params
);
return result;
}
export async function verifySignupWithShortToken (
options: VerifySignupWithShortTokenOptions,
verifyShortToken: string,
identifyUser: IdentifyUser,
notifierOptions: NotifierOptions = {},
params?: Params
): Promise<SanitizedUser> {
ensureValuesAreStrings(verifyShortToken);
ensureObjPropsValid(identifyUser, options.identifyUserProps);
const result = await verifySignup(
options,
identifyUser,
{ verifyShortToken },
notifierOptions,
params
);
return result;
}
async function verifySignup (
options: VerifySignupOptions,
identifyUser: IdentifyUser,
tokens: Tokens,
notifierOptions: NotifierOptions = {},
params?: Params
): Promise<SanitizedUser> {
debug('verifySignup', identifyUser, tokens);
if (params && "query" in params) {
params = Object.assign({}, params);
delete params.query;
}
const {
app,
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,
}
);
const user = getUserData(users, [
'isNotVerifiedOrHasVerifyChanges',
'verifyNotExpired'
]);
let userErasedVerify: User;
if (!Object.keys(tokens).every(key => tokens[key] === user[key])) {
userErasedVerify = await eraseVerifyProps(user, user.isVerified);
throw new BadRequest(
'Invalid token. Get for a new one. (authLocalMgnt)',
{ errors: { $className: 'badParam' } }
);
} else {
userErasedVerify = await eraseVerifyProps(
user,
isDateAfterNow(user.verifyExpires),
user.verifyChanges || {},
params
);
}
const userResult = await notify(notifier, 'verifySignup', userErasedVerify, notifierOptions);
return sanitizeUserForClient(userResult);
async function eraseVerifyProps (
user: User,
isVerified: boolean,
verifyChanges?: VerifyChanges,
params?: Params
): Promise<User> {
const patchData = Object.assign({}, verifyChanges || {}, {
isVerified,
verifyToken: null,
verifyShortToken: null,
verifyExpires: null,
verifyChanges: {}
});
const result = await usersService.patch(
user[usersServiceId] as Id,
patchData,
Object.assign({}, params)
);
return result;
}
}