Use MongoDB Regexes to query case insensitive username/password

This commit is contained in:
Cassie Tarakajian 2020-04-06 19:01:37 -04:00
parent 86e299c936
commit ef4a8d7ea1
3 changed files with 11 additions and 10 deletions

View file

@ -24,7 +24,7 @@ passport.deserializeUser((id, done) => {
* Sign in using Email/Username and Password. * Sign in using Email/Username and Password.
*/ */
passport.use(new LocalStrategy({ usernameField: 'email' }, (email, password, done) => { passport.use(new LocalStrategy({ usernameField: 'email' }, (email, password, done) => {
User.findByMailOrName(email.toLowerCase()) User.findByMailOrName(email)
.then((user) => { // eslint-disable-line consistent-return .then((user) => { // eslint-disable-line consistent-return
if (!user) { if (!user) {
return done(null, false, { msg: `Email ${email} not found.` }); return done(null, false, { msg: `Email ${email} not found.` });

View file

@ -1,5 +1,6 @@
import crypto from 'crypto'; import crypto from 'crypto';
import async from 'async'; import async from 'async';
import escapeStringRegexp from 'escape-string-regexp';
import User from '../models/user'; import User from '../models/user';
import mail from '../utils/mail'; import mail from '../utils/mail';
@ -41,12 +42,11 @@ export function findUserByUsername(username, cb) {
export function createUser(req, res, next) { export function createUser(req, res, next) {
const { username, email } = req.body; const { username, email } = req.body;
const { password } = req.body; const { password } = req.body;
const usernameLowerCase = username.toLowerCase();
const emailLowerCase = email.toLowerCase(); const emailLowerCase = email.toLowerCase();
const EMAIL_VERIFY_TOKEN_EXPIRY_TIME = Date.now() + (3600000 * 24); // 24 hours const EMAIL_VERIFY_TOKEN_EXPIRY_TIME = Date.now() + (3600000 * 24); // 24 hours
random((tokenError, token) => { random((tokenError, token) => {
const user = new User({ const user = new User({
username: usernameLowerCase, username: username,
email: emailLowerCase, email: emailLowerCase,
password, password,
verified: User.EmailConfirmation.Sent, verified: User.EmailConfirmation.Sent,
@ -57,8 +57,8 @@ export function createUser(req, res, next) {
User.findOne( User.findOne(
{ {
$or: [ $or: [
{ email: { $in: [ email, emailLowerCase ]} }, { email: new RegExp(`^${escapeStringRegexp(email)}$`, 'i') },
{ username: { $in: [ username, usernameLowerCase ]} } { username: new RegExp(`^${escapeStringRegexp(username)}$`, 'i') }
] ]
}, },
(err, existingUser) => { (err, existingUser) => {
@ -106,7 +106,7 @@ export function duplicateUserCheck(req, res) {
const checkType = req.query.check_type; const checkType = req.query.check_type;
const value = req.query[checkType]; const value = req.query[checkType];
const query = {}; const query = {};
query[checkType] = value; query[checkType] = new RegExp(`^${escapeStringRegexp(value)}$`, 'i');
User.findOne(query, (err, user) => { User.findOne(query, (err, user) => {
if (user) { if (user) {
return res.json({ return res.json({
@ -151,7 +151,7 @@ export function resetPasswordInitiate(req, res) {
async.waterfall([ async.waterfall([
random, random,
(token, done) => { (token, done) => {
User.findOne({ email: req.body.email }, (err, user) => { User.findOne({ email: req.body.email.toLowerCase() }, (err, user) => {
if (!user) { if (!user) {
res.json({ success: true, message: 'If the email is registered with the editor, an email has been sent.' }); res.json({ success: true, message: 'If the email is registered with the editor, an email has been sent.' });
return; return;
@ -281,7 +281,7 @@ export function updatePassword(req, res) {
} }
export function userExists(username, callback) { export function userExists(username, callback) {
User.findOne({ username }, (err, user) => ( User.findOne({ username: new RegExp(`^${escapeStringRegexp(username)}$`, 'i') }, (err, user) => (
user ? callback(true) : callback(false) user ? callback(true) : callback(false)
)); ));
} }

View file

@ -1,4 +1,5 @@
import mongoose from 'mongoose'; import mongoose from 'mongoose';
import escapeStringRegexp from 'escape-string-regexp';
const bcrypt = require('bcrypt-nodejs'); const bcrypt = require('bcrypt-nodejs');
@ -144,9 +145,9 @@ userSchema.methods.findMatchingKey = function findMatchingKey(candidateKey, cb)
userSchema.statics.findByMailOrName = function findByMailOrName(email) { userSchema.statics.findByMailOrName = function findByMailOrName(email) {
const query = { const query = {
$or: [{ $or: [{
email, email: new RegExp(`^${escapeStringRegexp(email)}$`, 'i'),
}, { }, {
username: email, username: new RegExp(`^${escapeStringRegexp(email)}$`, 'i'),
}], }],
}; };
return this.findOne(query).exec(); return this.findOne(query).exec();