From 1bf8a8c0984f58f2e6002f7c1ad6e7f1f91753ff Mon Sep 17 00:00:00 2001 From: adarshm11 Date: Tue, 25 Aug 2026 12:10:01 -0700 Subject: [PATCH] remove door codes for expired memberships --- api/main_endpoints/routes/Auth.js | 15 ++++++++++++++- api/main_endpoints/util/userHelpers.js | 26 ++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/api/main_endpoints/routes/Auth.js b/api/main_endpoints/routes/Auth.js index f73899e5d..7b40d348f 100644 --- a/api/main_endpoints/routes/Auth.js +++ b/api/main_endpoints/routes/Auth.js @@ -24,7 +24,12 @@ const { const membershipState = require('../../util/constants').MEMBERSHIP_STATE; const PASSWORD_RESET_EXPIRATION = require('../../util/constants').PASSWORD_RESET_EXPIRATION; const { sendVerificationEmail, sendPasswordReset } = require('../util/emailHelpers'); -const { userWithEmailExists, checkIfPageCountResets, findPasswordReset } = require('../util/userHelpers'); +const { + userWithEmailExists, + checkIfPageCountResets, + findPasswordReset, + expireMembershipIfLapsed +} = require('../util/userHelpers'); const AuditLogActions = require('../util/auditLogActions.js'); const AuditLog = require('../models/AuditLog.js'); @@ -170,6 +175,10 @@ router.post('/login', async (req, res) => { return res.status(UNAUTHORIZED).send({ message: `Account ${email} is banned lol` }); } + // Nothing else expires memberships, so catch a lapsed one here and strip + // the door code before it can be handed back out on the profile page + const membershipLapsed = expireMembershipIfLapsed(user); + // Handle Page Reset if (checkIfPageCountResets(user.lastLogin)) { user.pagesPrinted = 0; @@ -177,6 +186,10 @@ router.post('/login', async (req, res) => { user.lastLogin = new Date(); await user.save(); + if (membershipLapsed) { + logger.info('Membership lapsed, revoked door code for user:', String(user._id)); + } + const token = jwt.sign({ _id: user._id, accessLevel: user.accessLevel, diff --git a/api/main_endpoints/util/userHelpers.js b/api/main_endpoints/util/userHelpers.js index 49aedc0f4..d23aaf35f 100644 --- a/api/main_endpoints/util/userHelpers.js +++ b/api/main_endpoints/util/userHelpers.js @@ -228,9 +228,35 @@ async function updateMembershipDetails(userId, numberOfSemestersToSignUpFor, doo } } +/** + * Revoke a member's benefits once their membership has lapsed. Officers and + * above aren't subject to membership expiration, so they keep their door code. + * Mutates the document in place; the caller is responsible for saving it. + * @param {Object} user - The user document to check + * @returns {Boolean} whether the membership had lapsed + */ +function expireMembershipIfLapsed(user) { + if (!user || user.accessLevel !== membershipState.MEMBER) { + return false; + } + if (!user.membershipValidUntil) { + return false; + } + // `$gt` is how getNewPaidMembersThisSemester counts active members, so an + // expiration landing exactly on now counts as lapsed here too + if (new Date(user.membershipValidUntil) > new Date()) { + return false; + } + + user.accessLevel = membershipState.NON_MEMBER; + user.doorCode = undefined; + return true; +} + module.exports = { registerUser, getMemberExpirationDate, + expireMembershipIfLapsed, testPasswordStrength, hashPassword, userWithEmailExists,