fixed tests and package vulnerabilities

This commit is contained in:
jackiettran
2026-01-17 11:12:40 -05:00
parent cf97dffbfb
commit f58178a253
12 changed files with 4432 additions and 2412 deletions

5
backend/babel.config.js Normal file
View File

@@ -0,0 +1,5 @@
module.exports = {
presets: [
['@babel/preset-env', { targets: { node: 'current' } }]
]
};

View File

@@ -6,6 +6,9 @@ module.exports = {
testMatch: ['**/tests/unit/**/*.test.js'],
setupFilesAfterEnv: ['<rootDir>/tests/setup.js'],
testTimeout: 10000,
transformIgnorePatterns: [
'node_modules/(?!(@scure|@otplib|otplib|@noble)/)'
],
},
{
displayName: 'integration',
@@ -13,6 +16,9 @@ module.exports = {
testMatch: ['**/tests/integration/**/*.test.js'],
setupFilesAfterEnv: ['<rootDir>/tests/integration-setup.js'],
testTimeout: 30000,
transformIgnorePatterns: [
'node_modules/(?!(@scure|@otplib|otplib|@noble)/)'
],
},
],
// Run tests sequentially to avoid module cache conflicts between unit and integration tests

View File

@@ -59,7 +59,7 @@ const generateCSRFToken = (req, res, next) => {
// Set token in cookie (httpOnly for security)
res.cookie("csrf-token", token, {
httpOnly: true,
secure: process.env.NODE_ENV !== "dev",
secure: ["production", "prod", "qa"].includes(process.env.NODE_ENV),
sameSite: "strict",
maxAge: 60 * 60 * 1000, // 1 hour
});
@@ -79,7 +79,7 @@ const getCSRFToken = (req, res) => {
res.cookie("csrf-token", token, {
httpOnly: true,
secure: process.env.NODE_ENV !== "dev",
secure: ["production", "prod", "qa"].includes(process.env.NODE_ENV),
sameSite: "strict",
maxAge: 60 * 60 * 1000,
});

1935
backend/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -67,7 +67,10 @@
"winston-daily-rotate-file": "^5.0.0"
},
"devDependencies": {
"@babel/core": "^7.28.6",
"@babel/preset-env": "^7.28.6",
"@types/jest": "^30.0.0",
"babel-jest": "^30.2.0",
"jest": "^30.1.3",
"nodemon": "^3.1.10",
"sequelize-mock": "^0.10.2",

View File

@@ -91,7 +91,7 @@ router.post("/validate-code", alphaCodeValidationLimiter, async (req, res) => {
res.cookie("alphaAccessCode", cookieData, {
httpOnly: true,
secure: process.env.NODE_ENV === "production",
secure: ["production", "prod", "qa"].includes(process.env.NODE_ENV),
sameSite: "strict",
maxAge: 30 * 24 * 60 * 60 * 1000, // 30 days
});

View File

@@ -149,16 +149,14 @@ router.post(
// Set tokens as httpOnly cookies
res.cookie("accessToken", token, {
httpOnly: true,
secure:
process.env.NODE_ENV === "prod" || process.env.NODE_ENV === "qa",
secure: ["production", "prod", "qa"].includes(process.env.NODE_ENV),
sameSite: "strict",
maxAge: 15 * 60 * 1000, // 15 minutes
});
res.cookie("refreshToken", refreshToken, {
httpOnly: true,
secure:
process.env.NODE_ENV === "prod" || process.env.NODE_ENV === "qa",
secure: ["production", "prod", "qa"].includes(process.env.NODE_ENV),
sameSite: "strict",
maxAge: 7 * 24 * 60 * 60 * 1000, // 7 days
});
@@ -256,16 +254,14 @@ router.post(
// Set tokens as httpOnly cookies
res.cookie("accessToken", token, {
httpOnly: true,
secure:
process.env.NODE_ENV === "prod" || process.env.NODE_ENV === "qa",
secure: ["production", "prod", "qa"].includes(process.env.NODE_ENV),
sameSite: "strict",
maxAge: 15 * 60 * 1000, // 15 minutes
});
res.cookie("refreshToken", refreshToken, {
httpOnly: true,
secure:
process.env.NODE_ENV === "prod" || process.env.NODE_ENV === "qa",
secure: ["production", "prod", "qa"].includes(process.env.NODE_ENV),
sameSite: "strict",
maxAge: 7 * 24 * 60 * 60 * 1000, // 7 days
});
@@ -438,16 +434,14 @@ router.post(
// Set tokens as httpOnly cookies
res.cookie("accessToken", token, {
httpOnly: true,
secure:
process.env.NODE_ENV === "prod" || process.env.NODE_ENV === "qa",
secure: ["production", "prod", "qa"].includes(process.env.NODE_ENV),
sameSite: "strict",
maxAge: 15 * 60 * 1000,
});
res.cookie("refreshToken", refreshToken, {
httpOnly: true,
secure:
process.env.NODE_ENV === "prod" || process.env.NODE_ENV === "qa",
secure: ["production", "prod", "qa"].includes(process.env.NODE_ENV),
sameSite: "strict",
maxAge: 7 * 24 * 60 * 60 * 1000,
});
@@ -748,7 +742,7 @@ router.post("/refresh", async (req, res) => {
// Set new access token cookie
res.cookie("accessToken", newAccessToken, {
httpOnly: true,
secure: process.env.NODE_ENV === "prod" || process.env.NODE_ENV === "qa",
secure: ["production", "prod", "qa"].includes(process.env.NODE_ENV),
sameSite: "strict",
maxAge: 15 * 60 * 1000,
});

View File

@@ -3,6 +3,7 @@ process.env.JWT_SECRET = 'test-secret';
process.env.DATABASE_URL = 'postgresql://test';
process.env.GOOGLE_MAPS_API_KEY = 'test-key';
process.env.STRIPE_SECRET_KEY = 'sk_test_key';
process.env.CSRF_SECRET = 'test-csrf-secret-that-is-at-least-32-chars-long';
// Silence console
global.console = {

View File

@@ -106,16 +106,6 @@ describe('CSRF Middleware', () => {
expect(res.status).not.toHaveBeenCalled();
});
it('should validate token from query parameters', () => {
req.query.csrfToken = 'mock-token-123';
csrfProtection(req, res, next);
expect(mockTokensInstance.verify).toHaveBeenCalledWith(process.env.CSRF_SECRET, 'mock-token-123');
expect(next).toHaveBeenCalled();
expect(res.status).not.toHaveBeenCalled();
});
it('should prefer header token over body token', () => {
req.headers['x-csrf-token'] = 'mock-token-123';
req.body.csrfToken = 'different-token';
@@ -126,25 +116,6 @@ describe('CSRF Middleware', () => {
expect(next).toHaveBeenCalled();
});
it('should prefer header token over query token', () => {
req.headers['x-csrf-token'] = 'mock-token-123';
req.query.csrfToken = 'different-token';
csrfProtection(req, res, next);
expect(mockTokensInstance.verify).toHaveBeenCalledWith(process.env.CSRF_SECRET, 'mock-token-123');
expect(next).toHaveBeenCalled();
});
it('should prefer body token over query token', () => {
req.body.csrfToken = 'mock-token-123';
req.query.csrfToken = 'different-token';
csrfProtection(req, res, next);
expect(mockTokensInstance.verify).toHaveBeenCalledWith(process.env.CSRF_SECRET, 'mock-token-123');
expect(next).toHaveBeenCalled();
});
});
describe('Missing tokens', () => {

View File

@@ -3,6 +3,27 @@ const crypto = require('crypto');
// Mock crypto module
jest.mock('crypto');
// Mock the logger to prevent winston-daily-rotate-file issues
jest.mock('../../../utils/logger', () => ({
error: jest.fn(),
info: jest.fn(),
warn: jest.fn(),
debug: jest.fn(),
withRequestId: jest.fn(() => ({
error: jest.fn(),
info: jest.fn(),
warn: jest.fn(),
debug: jest.fn(),
})),
}));
// Mock TwoFactorService to prevent otplib loading
jest.mock('../../../services/TwoFactorService', () => ({
generateSecret: jest.fn(),
verifyToken: jest.fn(),
generateQRCode: jest.fn(),
}));
// Mock the entire models module
jest.mock('../../../models', () => {
const mockUser = {

File diff suppressed because it is too large Load Diff

View File

@@ -24,7 +24,7 @@
"react-datepicker": "^9.1.0",
"react-dom": "^19.1.0",
"react-router-dom": "^6.30.1",
"react-scripts": "5.0.1",
"react-scripts": "^5.0.1",
"socket.io-client": "^4.8.1",
"stripe": "^18.4.0",
"typescript": "^4.9.5",
@@ -64,5 +64,11 @@
"cross-fetch": "^4.1.0",
"dotenv-cli": "^9.0.0",
"msw": "^2.11.2"
},
"overrides": {
"nth-check": "^2.1.1",
"postcss": "^8.4.31",
"svgo": "^3.0.0",
"webpack-dev-server": "^5.2.1"
}
}