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, );