mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-21 15:20:34 +00:00
feat: ability to enable/disable email confirmation from env variables
This commit is contained in:
@@ -48,6 +48,9 @@ SIGNUP_DISABLED=false
|
|||||||
SIGNUP_ALLOWED_DOMAINS=
|
SIGNUP_ALLOWED_DOMAINS=
|
||||||
SIGNUP_ALLOWED_EMAILS=
|
SIGNUP_ALLOWED_EMAILS=
|
||||||
|
|
||||||
|
# Sign-up Email Confirmation
|
||||||
|
SIGNUP_EMAIL_CONFIRMATION=false
|
||||||
|
|
||||||
# API rate limit (points,duration,block duration).
|
# API rate limit (points,duration,block duration).
|
||||||
API_RATE_LIMIT=120,60,600
|
API_RATE_LIMIT=120,60,600
|
||||||
|
|
||||||
|
|||||||
@@ -220,11 +220,10 @@ export default class AuthenticationController extends BaseController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* Resends the confirmation email to the user.
|
||||||
* @param {Request} req
|
* @param {Request} req
|
||||||
* @param {Response}| res
|
* @param {Response}| res
|
||||||
* @param {Function} next
|
* @param {Function} next
|
||||||
* @returns
|
|
||||||
*/
|
*/
|
||||||
private async registerVerifyResendMail(
|
private async registerVerifyResendMail(
|
||||||
req: Request,
|
req: Request,
|
||||||
@@ -234,7 +233,7 @@ export default class AuthenticationController extends BaseController {
|
|||||||
const { user } = req;
|
const { user } = req;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const data = await this.authApplication.signUpConfirm(user.id);
|
const data = await this.authApplication.signUpConfirmResend(user.id);
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
type: 'success',
|
type: 'success',
|
||||||
|
|||||||
@@ -153,6 +153,13 @@ module.exports = {
|
|||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sign-up email confirmation
|
||||||
|
*/
|
||||||
|
signupConfirmation: {
|
||||||
|
enabled: parseBoolean<boolean>(process.env.SIGNUP_EMAIL_CONFIRMATION, false),
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Puppeteer remote browserless connection.
|
* Puppeteer remote browserless connection.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Service, Inject, Container } from 'typedi';
|
import { Service, Inject } from 'typedi';
|
||||||
import {
|
import {
|
||||||
IRegisterDTO,
|
IRegisterDTO,
|
||||||
ISystemUser,
|
ISystemUser,
|
||||||
@@ -13,11 +13,6 @@ import { AuthSignupConfirmService } from './AuthSignupConfirm';
|
|||||||
import { SystemUser } from '@/system/models';
|
import { SystemUser } from '@/system/models';
|
||||||
import { AuthSignupConfirmResend } from './AuthSignupResend';
|
import { AuthSignupConfirmResend } from './AuthSignupResend';
|
||||||
|
|
||||||
interface ISignupConfirmDTO {
|
|
||||||
token: string;
|
|
||||||
email: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Service()
|
@Service()
|
||||||
export default class AuthenticationApplication {
|
export default class AuthenticationApplication {
|
||||||
@Inject()
|
@Inject()
|
||||||
@@ -72,13 +67,12 @@ export default class AuthenticationApplication {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* Resends the confirmation email of the given system user.
|
||||||
* @param {string} email
|
* @param {number} userId - System user id.
|
||||||
* @param {string} token
|
* @returns {Promise<void>}
|
||||||
* @returns
|
|
||||||
*/
|
*/
|
||||||
public async signUpConfirmSend(email: string, token: string) {
|
public async signUpConfirmResend(userId: number) {
|
||||||
return this.authSignupConfirmService.signUpConfirm(email, token);
|
return this.authSignUpConfirmResendService.signUpConfirmResend(userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { isEmpty, omit } from 'lodash';
|
import { defaultTo, isEmpty, omit } from 'lodash';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import crypto from 'crypto';
|
import crypto from 'crypto';
|
||||||
import { ServiceError } from '@/exceptions';
|
import { ServiceError } from '@/exceptions';
|
||||||
@@ -42,7 +42,13 @@ export class AuthSignupService {
|
|||||||
await this.validateEmailUniqiness(signupDTO.email);
|
await this.validateEmailUniqiness(signupDTO.email);
|
||||||
|
|
||||||
const hashedPassword = await hashPassword(signupDTO.password);
|
const hashedPassword = await hashPassword(signupDTO.password);
|
||||||
const verifyToken = crypto.randomBytes(64).toString('hex');
|
|
||||||
|
const verifyTokenCrypto = crypto.randomBytes(64).toString('hex');
|
||||||
|
const verifiedEnabed = defaultTo(config.signupConfirmation.enabled, false);
|
||||||
|
const verifyToken = verifiedEnabed ? verifyTokenCrypto : '';
|
||||||
|
const verified = !verifiedEnabed;
|
||||||
|
|
||||||
|
const inviteAcceptedAt = moment().format('YYYY-MM-DD');
|
||||||
|
|
||||||
// Triggers signin up event.
|
// Triggers signin up event.
|
||||||
await this.eventPublisher.emitAsync(events.auth.signingUp, {
|
await this.eventPublisher.emitAsync(events.auth.signingUp, {
|
||||||
@@ -53,10 +59,11 @@ export class AuthSignupService {
|
|||||||
const registeredUser = await systemUserRepository.create({
|
const registeredUser = await systemUserRepository.create({
|
||||||
...omit(signupDTO, 'country'),
|
...omit(signupDTO, 'country'),
|
||||||
verifyToken,
|
verifyToken,
|
||||||
|
verified,
|
||||||
active: true,
|
active: true,
|
||||||
password: hashedPassword,
|
password: hashedPassword,
|
||||||
tenantId: tenant.id,
|
tenantId: tenant.id,
|
||||||
inviteAcceptedAt: moment().format('YYYY-MM-DD'),
|
inviteAcceptedAt,
|
||||||
});
|
});
|
||||||
// Triggers signed up event.
|
// Triggers signed up event.
|
||||||
await this.eventPublisher.emitAsync(events.auth.signUp, {
|
await this.eventPublisher.emitAsync(events.auth.signUp, {
|
||||||
|
|||||||
@@ -52,6 +52,6 @@ export class AuthSignupConfirmService {
|
|||||||
userId,
|
userId,
|
||||||
} as IAuthSignUpVerifiedEventPayload);
|
} as IAuthSignUpVerifiedEventPayload);
|
||||||
|
|
||||||
return updatedUser;
|
return updatedUser as SystemUser;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
|
import { Inject, Service } from 'typedi';
|
||||||
import { ServiceError } from '@/exceptions';
|
import { ServiceError } from '@/exceptions';
|
||||||
import { SystemUser } from '@/system/models';
|
import { SystemUser } from '@/system/models';
|
||||||
import { Inject, Service } from 'typedi';
|
|
||||||
import { ERRORS } from './_constants';
|
import { ERRORS } from './_constants';
|
||||||
|
|
||||||
@Service()
|
@Service()
|
||||||
@@ -9,18 +9,19 @@ export class AuthSignupConfirmResend {
|
|||||||
private agenda: any;
|
private agenda: any;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* Resends the email confirmation of the given user.
|
||||||
* @param {number} tenantId
|
* @param {number} userId - User ID.
|
||||||
* @param {string} email
|
* @returns {Promise<void>}
|
||||||
*/
|
*/
|
||||||
public async signUpConfirmResend(userId: number) {
|
public async signUpConfirmResend(userId: number) {
|
||||||
const user = await SystemUser.query().findById(userId).throwIfNotFound();
|
const user = await SystemUser.query().findById(userId).throwIfNotFound();
|
||||||
|
|
||||||
//
|
// Throw error if the user is already verified.
|
||||||
if (user.verified) {
|
if (user.verified) {
|
||||||
throw new ServiceError(ERRORS.USER_ALREADY_VERIFIED);
|
throw new ServiceError(ERRORS.USER_ALREADY_VERIFIED);
|
||||||
}
|
}
|
||||||
if (user.verifyToken) {
|
// Throw error if the verification token is not exist.
|
||||||
|
if (!user.verifyToken) {
|
||||||
throw new ServiceError(ERRORS.USER_ALREADY_VERIFIED);
|
throw new ServiceError(ERRORS.USER_ALREADY_VERIFIED);
|
||||||
}
|
}
|
||||||
const payload = {
|
const payload = {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import bcrypt from 'bcryptjs';
|
import bcrypt from 'bcryptjs';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import _ from 'lodash';
|
import _, { isEmpty } from 'lodash';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import * as R from 'ramda';
|
import * as R from 'ramda';
|
||||||
|
|
||||||
@@ -329,7 +329,7 @@ const booleanValuesRepresentingTrue: string[] = ['true', '1'];
|
|||||||
const booleanValuesRepresentingFalse: string[] = ['false', '0'];
|
const booleanValuesRepresentingFalse: string[] = ['false', '0'];
|
||||||
|
|
||||||
const normalizeValue = (value: any): string =>
|
const normalizeValue = (value: any): string =>
|
||||||
value.toString().trim().toLowerCase();
|
value?.toString().trim().toLowerCase();
|
||||||
|
|
||||||
const booleanValues: string[] = [
|
const booleanValues: string[] = [
|
||||||
...booleanValuesRepresentingTrue,
|
...booleanValuesRepresentingTrue,
|
||||||
@@ -338,7 +338,7 @@ const booleanValues: string[] = [
|
|||||||
|
|
||||||
export const parseBoolean = <T>(value: any, defaultValue: T): T | boolean => {
|
export const parseBoolean = <T>(value: any, defaultValue: T): T | boolean => {
|
||||||
const normalizedValue = normalizeValue(value);
|
const normalizedValue = normalizeValue(value);
|
||||||
if (booleanValues.indexOf(normalizedValue) === -1) {
|
if (isEmpty(value) || booleanValues.indexOf(normalizedValue) === -1) {
|
||||||
return defaultValue;
|
return defaultValue;
|
||||||
}
|
}
|
||||||
return booleanValuesRepresentingTrue.indexOf(normalizedValue) !== -1;
|
return booleanValuesRepresentingTrue.indexOf(normalizedValue) !== -1;
|
||||||
|
|||||||
Reference in New Issue
Block a user