'Sanitize email using express-validator only if it is an email, otherwise ignore

I am making an API in which I am taking username and password as req.body so that I can authenticate user.
(In short login functionality)
User can enter email or username or mobile number. At backend I want to normalize username if it is email. I am doing so because I am normalizing email at the time of Registration, therefore I need to check it with normalized email.

Want to do something like this: (A short pseudo-code)

username <- take input from request  
check if username is email:   
  if yes then *sanitize* username

My Login Rest API For Now:

// Login user
router.post(
  "/login",
  [
    check("username").not().isEmpty().escape(),
    check("password").not().isEmpty().escape(),
  ],
  (req, res, next) => {
    // Finds validation errors and return error object
    const errors = validationResult(req);
    if (!errors.isEmpty()) {
      return res.status(400).json({ errors: errors.array() });
    }
    let { username, password } = req.body;
    // Do authentication part
  }
);

The above code will work fine if the input is a username but I want to normalize email also.

Database content looks like this

user : [
  {
    username: 'SOME_MOBILE',
    password: 'SLDUS##$##KDJ'
  },
  {
    username: 'SOME_EMAIL',
    password: 'SLDU$%%##$2342423DJ'
  },
  {
    username: 'my_username',
    password: 'SLDUS##$#fssKDJ'
  }
]

Please help!
Thanks



Solution 1:[1]

If you want your username to be an email check like this:

[body("username").notEmpty().escape().if(body("username").isEmail()).nomalizeEmail(), 
body("password").notEmpty().escape()]

Solution 2:[2]

You can use @hapi/joi package for your validations. So, try something like this:

const schema = Joi.object().keys({
    username: Joi.string().required(),
    email: Joi.string().email().required()
});

Complete-sample:

const Joi = require('@hapi/joi');

const schema = Joi.object().keys({

    username: Joi.string().required(),
    email: Joi.string().email().required()
});

let username = 'Roger Brown';
let email = 'roger@example';

let data = { username, email };

Joi.validate(data, schema, (err, value) => {

    if (err) {

        console.log(err.details);

    } else {

        console.log(value);
    }
});

If you won't use any third-party packages using regex like this:

function validateEmail(email) {
    const re = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
    return re.test(String(email).toLowerCase());
}

Solution 3:[3]

May be you want to add something else like this:

.stripLow()   //Remove some unwanted ascii codes.
.trim()       //Always trim after removing things.
.notEmpty()   
.escape()     //escape after removing.
.isLength({max: 50 })  //check length after adding things.
.normalizeEmail()      //After all normalize and check if it is a email.
.isEmail(),

For normal strings i use:

check('name', 'Name must be at least 2 characters long, max 35 characters.')
    .stripLow() //Lowest ascii command codes.
    .trim() //trim after taking out things.
    .notEmpty() //check empty.
    .isLength({ min: 2, max: 35 }) //length before and after adding escapes.
    .escape()
    .isLength({ min: 2, max: 35 }), //length before and after adding escapes.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2
Solution 3 Jonathan Orrego