Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 20 additions & 2 deletions api/main_endpoints/routes/MembershipPayment.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ const {
SERVER_ERROR,
NOT_FOUND,
OK,
UNAUTHORIZED
UNAUTHORIZED,
TOO_MANY_REQUESTS
} = require('../../util/constants').STATUS_CODES;
const membershipState = require('../../util/constants').MEMBERSHIP_STATE;
const { updateMembershipExpiration } = require('../util/userHelpers');
Expand All @@ -21,6 +22,10 @@ const logger = require('../../util/logger');
const AuditLogActions = require('../util/auditLogActions');
const AuditLog = require('../models/AuditLog');

const attemptCount = new Map();
const MAX_ATTEMPTS = 5;


router.post('/verifyMembership', async (req, res) => {
const decoded = await decodeToken(req, membershipState.PENDING);
if (decoded.status !== OK) {
Expand All @@ -29,6 +34,14 @@ router.post('/verifyMembership', async (req, res) => {

const { confirmationCode } = req.body;
const userId = decoded.token._id;
const attempts = attemptCount.get(userId) ?? 0;

if (attempts >= MAX_ATTEMPTS){
logger.error(`User ${userId} has made too many verification attempts.`);
return res.status(TOO_MANY_REQUESTS).json({
remainingAttempts: 0
});
}

if (!confirmationCode) {
logger.error('Confirmation code missing from verifyMembership request');
Expand All @@ -37,8 +50,11 @@ router.post('/verifyMembership', async (req, res) => {

const paymentDocument = await findVerifyPayment(confirmationCode, userId);
if (!paymentDocument) {
attemptCount.set(userId, attempts + 1);
logger.error('Error verifying payment for user:', userId);
return res.status(NOT_FOUND).send('Error verifying payment.');
return res.status(NOT_FOUND).json({
remainingAttempts: MAX_ATTEMPTS - (attempts + 1)
});
}

const { amount } = paymentDocument;
Expand All @@ -53,6 +69,8 @@ router.post('/verifyMembership', async (req, res) => {
logger.error('Error updating membership expiration for user:', decoded.token._id);
return res.status(SERVER_ERROR).send('Error updating membership expiration.');
}

attemptCount.delete(userId);
logger.info('Membership verified and updated for user:', decoded.token._id);
AuditLog.create({
userId: decoded.token._id,
Expand Down
1 change: 1 addition & 0 deletions api/util/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ const STATUS_CODES = {
FORBIDDEN: 403,
NOT_FOUND: 404,
CONFLICT: 409,
TOO_MANY_REQUESTS: 429,
SERVER_ERROR: 500,
};

Expand Down
10 changes: 8 additions & 2 deletions src/APIFunctions/MembershipPayment.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { ApiResponse } from './ApiResponses';
import { BASE_API_URL } from '../Enums';
const TOO_MANY_ATTEMPTS = 429;

export async function verifyMembershipFromDb(token, confirmationCode) {
let status = new ApiResponse();
Expand All @@ -13,8 +14,13 @@ export async function verifyMembershipFromDb(token, confirmationCode) {
},
body: JSON.stringify({ confirmationCode })
});
status.responseData = res.status;
status.error = !res.ok;
if (res.status == TOO_MANY_ATTEMPTS) {
const data = await res.json();
status.responseData = data;
status.error = false;
} else {
status.error = !res.ok;
}
} catch (err) {
status.error = true;
status.responseData = err;
Expand Down
4 changes: 4 additions & 0 deletions src/Pages/Profile/MemberView/VerifyMembershipModal.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ export default function VerifyMembershipModal(props) {
user.token,
confirmationCode,
);
if (apiResponse.remainingAttempts !== undefined){
bannerCallback(`Wrong Code - You have ${apiResponse.remainingAttempts} left.`);
return;
}
if (apiResponse.error) {
bannerCallback(`Unable to verify membership. Please try again later. Status Code: ${apiResponse.responseData || 500}`, 'red');
return;
Expand Down