feat: validate country code and phone number in user registration.

This commit is contained in:
a.bouhuolia
2020-12-16 15:37:12 +02:00
parent ddf31feb72
commit 17a38eafd1
3 changed files with 92 additions and 6 deletions

View File

@@ -27,6 +27,7 @@
"bookshelf-modelbase": "^2.10.4",
"bookshelf-paranoia": "^0.13.1",
"compression": "^1.7.4",
"country-codes-list": "^1.6.8",
"crypto-random-string": "^3.2.0",
"csurf": "^1.10.0",
"deep-map": "^2.0.0",
@@ -48,6 +49,7 @@
"knex": "^0.20.3",
"knex-cleaner": "^1.3.0",
"knex-db-manager": "^0.6.1",
"libphonenumber-js": "^1.9.6",
"lodash": "^4.17.15",
"memory-cache": "^0.2.0",
"moment": "^2.24.0",

View File

@@ -1,6 +1,8 @@
import { Request, Response, Router } from 'express';
import { check, ValidationChain } from 'express-validator';
import { Service, Inject } from 'typedi';
import countries from 'country-codes-list';
import parsePhoneNumber from 'libphonenumber-js';
import BaseController from 'api/controllers/BaseController';
import asyncMiddleware from 'api/middleware/asyncMiddleware';
import AuthenticationService from 'services/Authentication';
@@ -8,6 +10,7 @@ import { ILoginDTO, ISystemUser, IRegisterOTD } from 'interfaces';
import { ServiceError, ServiceErrors } from "exceptions";
import { DATATYPES_LENGTH } from 'data/DataTypes';
import LoginThrottlerMiddleware from 'api/middleware/LoginThrottlerMiddleware';
import config from 'config';
@Service()
export default class AuthenticationController extends BaseController{
@@ -63,15 +66,84 @@ export default class AuthenticationController extends BaseController{
*/
get registerSchema(): ValidationChain[] {
return [
check('first_name').exists().isString().trim().escape().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().isLength({ max: DATATYPES_LENGTH.STRING }),
check('password').exists().isString().trim().escape().isLength({ max: DATATYPES_LENGTH.STRING }),
check('country').exists().isString().trim().escape().isLength({ max: DATATYPES_LENGTH.STRING }),
check('first_name')
.exists()
.isString()
.trim()
.escape()
.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.
*/

View File

@@ -144,5 +144,17 @@ export default {
duration: 60,
blockDuration: 60 * 10,
}
},
/**
* Users registeration configuration.
*/
registration: {
countries: {
whitelist: [
'LY',
],
blacklist: [],
}
}
};