|
const { Strategy: PassportLocalStrategy } = require('passport-local'); |
|
const User = require('../models/User'); |
|
const { loginSchema, errorsToString } = require('./validators'); |
|
const logger = require('../utils/logger'); |
|
|
|
async function validateLoginRequest(req) { |
|
const { error } = loginSchema.safeParse(req.body); |
|
return error ? errorsToString(error.errors) : null; |
|
} |
|
|
|
async function findUserByEmail(email) { |
|
return User.findOne({ email: email.trim() }); |
|
} |
|
|
|
async function comparePassword(user, password) { |
|
return new Promise((resolve, reject) => { |
|
user.comparePassword(password, function (err, isMatch) { |
|
if (err) { |
|
return reject(err); |
|
} |
|
resolve(isMatch); |
|
}); |
|
}); |
|
} |
|
|
|
async function passportLogin(req, email, password, done) { |
|
try { |
|
const validationError = await validateLoginRequest(req); |
|
if (validationError) { |
|
logError('Passport Local Strategy - Validation Error', { reqBody: req.body }); |
|
logger.error(`[Login] [Login failed] [Username: ${email}] [Request-IP: ${req.ip}]`); |
|
return done(null, false, { message: validationError }); |
|
} |
|
|
|
const user = await findUserByEmail(email); |
|
if (!user) { |
|
logError('Passport Local Strategy - User Not Found', { email }); |
|
logger.error(`[Login] [Login failed] [Username: ${email}] [Request-IP: ${req.ip}]`); |
|
return done(null, false, { message: 'Email does not exist.' }); |
|
} |
|
|
|
const isMatch = await comparePassword(user, password); |
|
if (!isMatch) { |
|
logError('Passport Local Strategy - Password does not match', { isMatch }); |
|
logger.error(`[Login] [Login failed] [Username: ${email}] [Request-IP: ${req.ip}]`); |
|
return done(null, false, { message: 'Incorrect password.' }); |
|
} |
|
|
|
logger.info(`[Login] [Login successful] [Username: ${email}] [Request-IP: ${req.ip}]`); |
|
return done(null, user); |
|
} catch (err) { |
|
return done(err); |
|
} |
|
} |
|
|
|
function logError(title, parameters) { |
|
const entries = Object.entries(parameters).map(([name, value]) => ({ name, value })); |
|
logger.error(title, { parameters: entries }); |
|
} |
|
|
|
module.exports = () => |
|
new PassportLocalStrategy( |
|
{ |
|
usernameField: 'email', |
|
passwordField: 'password', |
|
session: false, |
|
passReqToCallback: true, |
|
}, |
|
passportLogin, |
|
); |
|
|