mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-19 14:20:31 +00:00
feat: validate country code and phone number in user registration.
This commit is contained in:
@@ -27,6 +27,7 @@
|
|||||||
"bookshelf-modelbase": "^2.10.4",
|
"bookshelf-modelbase": "^2.10.4",
|
||||||
"bookshelf-paranoia": "^0.13.1",
|
"bookshelf-paranoia": "^0.13.1",
|
||||||
"compression": "^1.7.4",
|
"compression": "^1.7.4",
|
||||||
|
"country-codes-list": "^1.6.8",
|
||||||
"crypto-random-string": "^3.2.0",
|
"crypto-random-string": "^3.2.0",
|
||||||
"csurf": "^1.10.0",
|
"csurf": "^1.10.0",
|
||||||
"deep-map": "^2.0.0",
|
"deep-map": "^2.0.0",
|
||||||
@@ -48,6 +49,7 @@
|
|||||||
"knex": "^0.20.3",
|
"knex": "^0.20.3",
|
||||||
"knex-cleaner": "^1.3.0",
|
"knex-cleaner": "^1.3.0",
|
||||||
"knex-db-manager": "^0.6.1",
|
"knex-db-manager": "^0.6.1",
|
||||||
|
"libphonenumber-js": "^1.9.6",
|
||||||
"lodash": "^4.17.15",
|
"lodash": "^4.17.15",
|
||||||
"memory-cache": "^0.2.0",
|
"memory-cache": "^0.2.0",
|
||||||
"moment": "^2.24.0",
|
"moment": "^2.24.0",
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
import { Request, Response, Router } from 'express';
|
import { Request, Response, Router } from 'express';
|
||||||
import { check, ValidationChain } from 'express-validator';
|
import { check, ValidationChain } from 'express-validator';
|
||||||
import { Service, Inject } from 'typedi';
|
import { Service, Inject } from 'typedi';
|
||||||
|
import countries from 'country-codes-list';
|
||||||
|
import parsePhoneNumber from 'libphonenumber-js';
|
||||||
import BaseController from 'api/controllers/BaseController';
|
import BaseController from 'api/controllers/BaseController';
|
||||||
import asyncMiddleware from 'api/middleware/asyncMiddleware';
|
import asyncMiddleware from 'api/middleware/asyncMiddleware';
|
||||||
import AuthenticationService from 'services/Authentication';
|
import AuthenticationService from 'services/Authentication';
|
||||||
@@ -8,6 +10,7 @@ import { ILoginDTO, ISystemUser, IRegisterOTD } from 'interfaces';
|
|||||||
import { ServiceError, ServiceErrors } from "exceptions";
|
import { ServiceError, ServiceErrors } from "exceptions";
|
||||||
import { DATATYPES_LENGTH } from 'data/DataTypes';
|
import { DATATYPES_LENGTH } from 'data/DataTypes';
|
||||||
import LoginThrottlerMiddleware from 'api/middleware/LoginThrottlerMiddleware';
|
import LoginThrottlerMiddleware from 'api/middleware/LoginThrottlerMiddleware';
|
||||||
|
import config from 'config';
|
||||||
|
|
||||||
@Service()
|
@Service()
|
||||||
export default class AuthenticationController extends BaseController{
|
export default class AuthenticationController extends BaseController{
|
||||||
@@ -63,15 +66,84 @@ export default class AuthenticationController extends BaseController{
|
|||||||
*/
|
*/
|
||||||
get registerSchema(): ValidationChain[] {
|
get registerSchema(): ValidationChain[] {
|
||||||
return [
|
return [
|
||||||
check('first_name').exists().isString().trim().escape().isLength({ max: DATATYPES_LENGTH.STRING }),
|
check('first_name')
|
||||||
check('last_name').exists().isString().trim().escape().isLength({ max: DATATYPES_LENGTH.STRING }),
|
.exists()
|
||||||
check('email').exists().isString().isEmail().trim().escape().isLength({ max: DATATYPES_LENGTH.STRING }),
|
.isString()
|
||||||
check('phone_number').exists().isString().trim().escape().isLength({ max: DATATYPES_LENGTH.STRING }),
|
.trim()
|
||||||
check('password').exists().isString().trim().escape().isLength({ max: DATATYPES_LENGTH.STRING }),
|
.escape()
|
||||||
check('country').exists().isString().trim().escape().isLength({ max: DATATYPES_LENGTH.STRING }),
|
.isLength({ max: DATATYPES_LENGTH.STRING }),
|
||||||
|
check('last_name')
|
||||||
|
.exists()
|
||||||
|
.isString()
|
||||||
|
.trim()
|
||||||
|
.escape()
|
||||||
|
.isLength({ max: DATATYPES_LENGTH.STRING }),
|
||||||
|
check('email')
|
||||||
|
.exists()
|
||||||
|
.isString()
|
||||||
|
.isEmail()
|
||||||
|
.trim()
|
||||||
|
.escape()
|
||||||
|
.isLength({ max: DATATYPES_LENGTH.STRING }),
|
||||||
|
check('phone_number')
|
||||||
|
.exists()
|
||||||
|
.isString()
|
||||||
|
.trim()
|
||||||
|
.escape()
|
||||||
|
.custom(this.phoneNumberValidator)
|
||||||
|
.isLength({ max: DATATYPES_LENGTH.STRING }),
|
||||||
|
check('password')
|
||||||
|
.exists()
|
||||||
|
.isString()
|
||||||
|
.trim()
|
||||||
|
.escape()
|
||||||
|
.isLength({ max: DATATYPES_LENGTH.STRING }),
|
||||||
|
check('country')
|
||||||
|
.exists()
|
||||||
|
.isString()
|
||||||
|
.trim()
|
||||||
|
.escape()
|
||||||
|
.custom(this.countryValidator)
|
||||||
|
.isLength({ max: DATATYPES_LENGTH.STRING }),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Country validator.
|
||||||
|
*/
|
||||||
|
countryValidator(value, { req }) {
|
||||||
|
const { countries: { whitelist, blacklist } } = config.registration;
|
||||||
|
const foundCountry = countries.findOne('countryCode', value);
|
||||||
|
|
||||||
|
if (!foundCountry) {
|
||||||
|
throw new Error('The country code is invalid.');
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
// Focus with me! In case whitelist is not empty and the given coutry is not
|
||||||
|
// in whitelist throw the error.
|
||||||
|
//
|
||||||
|
// And in case the blacklist is not empty and the given country exists
|
||||||
|
// in the blacklist throw the goddamn error.
|
||||||
|
(whitelist.length > 0 && whitelist.indexOf(value) === -1) &&
|
||||||
|
(blacklist.length > 0 && blacklist.indexOf(value) !== -1)
|
||||||
|
) {
|
||||||
|
throw new Error('The country code is not supported yet.');
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Phone number validator.
|
||||||
|
*/
|
||||||
|
phoneNumberValidator(value, { req }) {
|
||||||
|
const phoneNumber = parsePhoneNumber(value, req.body.country);
|
||||||
|
|
||||||
|
if (!phoneNumber || !phoneNumber.isValid()) {
|
||||||
|
throw new Error('Phone number is invalid with the given country code.');
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reset password schema.
|
* Reset password schema.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -144,5 +144,17 @@ export default {
|
|||||||
duration: 60,
|
duration: 60,
|
||||||
blockDuration: 60 * 10,
|
blockDuration: 60 * 10,
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Users registeration configuration.
|
||||||
|
*/
|
||||||
|
registration: {
|
||||||
|
countries: {
|
||||||
|
whitelist: [
|
||||||
|
'LY',
|
||||||
|
],
|
||||||
|
blacklist: [],
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Reference in New Issue
Block a user