mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-19 14:20:31 +00:00
feat(server): remove phone number from authentication process
This commit is contained in:
@@ -0,0 +1,130 @@
|
||||
import { Inject, Service } from 'typedi';
|
||||
import uniqid from 'uniqid';
|
||||
import moment from 'moment';
|
||||
import config from '@/config';
|
||||
import {
|
||||
IAuthResetedPasswordEventPayload,
|
||||
IAuthSendedResetPassword,
|
||||
IAuthSendingResetPassword,
|
||||
IPasswordReset,
|
||||
ISystemUser,
|
||||
} from '@/interfaces';
|
||||
import { EventPublisher } from '@/lib/EventPublisher/EventPublisher';
|
||||
import events from '@/subscribers/events';
|
||||
import { PasswordReset } from '@/system/models';
|
||||
import { ERRORS } from './_constants';
|
||||
import { ServiceError } from '@/exceptions';
|
||||
import { hashPassword } from '@/utils';
|
||||
|
||||
@Service()
|
||||
export class AuthSendResetPassword {
|
||||
@Inject()
|
||||
private eventPublisher: EventPublisher;
|
||||
|
||||
@Inject('repositories')
|
||||
private sysRepositories: any;
|
||||
|
||||
/**
|
||||
* Generates and retrieve password reset token for the given user email.
|
||||
* @param {string} email
|
||||
* @return {<Promise<IPasswordReset>}
|
||||
*/
|
||||
public async sendResetPassword(email: string): Promise<PasswordReset> {
|
||||
const user = await this.validateEmailExistance(email);
|
||||
|
||||
const token: string = uniqid();
|
||||
|
||||
// Triggers sending reset password event.
|
||||
await this.eventPublisher.emitAsync(events.auth.sendingResetPassword, {
|
||||
user,
|
||||
token,
|
||||
} as IAuthSendingResetPassword);
|
||||
|
||||
// Delete all stored tokens of reset password that associate to the give email.
|
||||
this.deletePasswordResetToken(email);
|
||||
|
||||
// Creates a new password reset row with unique token.
|
||||
const passwordReset = await PasswordReset.query().insert({ email, token });
|
||||
|
||||
// Triggers sent reset password event.
|
||||
await this.eventPublisher.emitAsync(events.auth.sendResetPassword, {
|
||||
user,
|
||||
token,
|
||||
} as IAuthSendedResetPassword);
|
||||
|
||||
return passwordReset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets a user password from given token.
|
||||
* @param {string} token - Password reset token.
|
||||
* @param {string} password - New Password.
|
||||
* @return {Promise<void>}
|
||||
*/
|
||||
public async resetPassword(token: string, password: string): Promise<void> {
|
||||
const { systemUserRepository } = this.sysRepositories;
|
||||
|
||||
// Finds the password reset token.
|
||||
const tokenModel: IPasswordReset = await PasswordReset.query().findOne(
|
||||
'token',
|
||||
token
|
||||
);
|
||||
// In case the password reset token not found throw token invalid error..
|
||||
if (!tokenModel) {
|
||||
throw new ServiceError(ERRORS.TOKEN_INVALID);
|
||||
}
|
||||
// Different between tokne creation datetime and current time.
|
||||
if (
|
||||
moment().diff(tokenModel.createdAt, 'seconds') >
|
||||
config.resetPasswordSeconds
|
||||
) {
|
||||
// Deletes the expired token by expired token email.
|
||||
await this.deletePasswordResetToken(tokenModel.email);
|
||||
throw new ServiceError(ERRORS.TOKEN_EXPIRED);
|
||||
}
|
||||
const user = await systemUserRepository.findOneByEmail(tokenModel.email);
|
||||
|
||||
if (!user) {
|
||||
throw new ServiceError(ERRORS.USER_NOT_FOUND);
|
||||
}
|
||||
const hashedPassword = await hashPassword(password);
|
||||
|
||||
await systemUserRepository.update(
|
||||
{ password: hashedPassword },
|
||||
{ id: user.id }
|
||||
);
|
||||
// Deletes the used token.
|
||||
await this.deletePasswordResetToken(tokenModel.email);
|
||||
|
||||
// Triggers `onResetPassword` event.
|
||||
await this.eventPublisher.emitAsync(events.auth.resetPassword, {
|
||||
user,
|
||||
token,
|
||||
password,
|
||||
} as IAuthResetedPasswordEventPayload);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the password reset token by the given email.
|
||||
* @param {string} email
|
||||
* @returns {Promise}
|
||||
*/
|
||||
private async deletePasswordResetToken(email: string) {
|
||||
return PasswordReset.query().where('email', email).delete();
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the given email existance on the storage.
|
||||
* @throws {ServiceError}
|
||||
* @param {string} email - email address.
|
||||
*/
|
||||
private async validateEmailExistance(email: string): Promise<ISystemUser> {
|
||||
const { systemUserRepository } = this.sysRepositories;
|
||||
const userByEmail = await systemUserRepository.findOneByEmail(email);
|
||||
|
||||
if (!userByEmail) {
|
||||
throw new ServiceError(ERRORS.EMAIL_NOT_FOUND);
|
||||
}
|
||||
return userByEmail;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user