From 0c8045d02529632b9c7bfe582c05c0ff31dda49c Mon Sep 17 00:00:00 2001 From: Cailyn Sinclair Date: Mon, 13 Jul 2026 18:48:21 -0700 Subject: [PATCH] Fix Mongoose session authentication Use promise-based Mongoose queries for Passport deserialization and WCA profile persistence so Mongoose 8 no longer rejects callback query APIs during login. --- server/auth/index.js | 22 ++++++++++++++-------- server/auth/index.test.js | 27 +++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 8 deletions(-) create mode 100644 server/auth/index.test.js diff --git a/server/auth/index.js b/server/auth/index.js index 405ace2..9a1d907 100644 --- a/server/auth/index.js +++ b/server/auth/index.js @@ -13,6 +13,14 @@ const checkStatus = async (res) => { throw await res.json(); }; +const deserializeUser = async (userModel, id, done) => { + try { + done(null, await userModel.findOne({ id })); + } catch (error) { + done(error); + } +}; + module.exports = (app, passport) => { const router = express.Router(); const config = app.get('config'); @@ -80,15 +88,15 @@ module.exports = (app, passport) => { const profile = meRes.me; - User.findOneAndUpdate({ + const user = await User.findOneAndUpdate({ id: +profile.id, }, buildWcaUserUpdate(profile, tokenRes.access_token), { upsert: true, useFindAndModify: false, new: true, - }, (err, user) => { - done(err, user.toObject()); }); + + done(null, user.toObject()); } catch (e) { done(e); } @@ -98,11 +106,7 @@ module.exports = (app, passport) => { done(null, user.id); }); - passport.deserializeUser((id, done) => { - User.findOne({ id }, (err, user) => { - done(err, user); - }); - }); + passport.deserializeUser((id, done) => deserializeUser(User, id, done)); router.post('/code', (req, res, next) => { @@ -144,3 +148,5 @@ module.exports = (app, passport) => { return router; }; + +module.exports.deserializeUser = deserializeUser; diff --git a/server/auth/index.test.js b/server/auth/index.test.js new file mode 100644 index 0000000..da5774a --- /dev/null +++ b/server/auth/index.test.js @@ -0,0 +1,27 @@ +/** @jest-environment node */ +/* eslint-env jest */ + +const { deserializeUser } = require('./index'); + +describe('session user deserialization', () => { + it('uses the Mongoose promise API and returns the loaded user', async () => { + const user = { id: 990001 }; + const User = { findOne: jest.fn().mockResolvedValue(user) }; + const done = jest.fn(); + + await deserializeUser(User, 990001, done); + + expect(User.findOne).toHaveBeenCalledWith({ id: 990001 }); + expect(done).toHaveBeenCalledWith(null, user); + }); + + it('passes persistence errors to Passport', async () => { + const error = new Error('database unavailable'); + const User = { findOne: jest.fn().mockRejectedValue(error) }; + const done = jest.fn(); + + await deserializeUser(User, 990001, done); + + expect(done).toHaveBeenCalledWith(error); + }); +});