379 lines
13 KiB
JavaScript
379 lines
13 KiB
JavaScript
"use strict";
|
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
};
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.healthMetricsRateLimit = exports.errorReportRateLimit = exports.eventSubmissionRateLimit = exports.profilePasswordRateLimit = exports.profilePhotoRateLimit = exports.profileEditRateLimit = exports.profileViewRateLimit = exports.docsCommentFetchRateLimit = exports.docsCommentAuthRateLimit = exports.docsCommentAnonRateLimit = exports.docsAnalyticsRateLimit = exports.observabilityRateLimit = exports.authRateLimit = exports.quickJoinRateLimit = exports.adTrackingRateLimit = exports.canvassGeocodeRateLimit = exports.gpsTrackingRateLimit = exports.canvassBulkVisitRateLimit = exports.canvassVisitRateLimit = exports.shiftSignupRateLimit = exports.responseRateLimit = exports.emailRateLimit = exports.globalRateLimit = void 0;
|
|
const express_rate_limit_1 = __importDefault(require("express-rate-limit"));
|
|
const rate_limit_redis_1 = __importDefault(require("rate-limit-redis"));
|
|
const redis_1 = require("../config/redis");
|
|
const env_1 = require("../config/env");
|
|
exports.globalRateLimit = (0, express_rate_limit_1.default)({
|
|
windowMs: env_1.env.RATE_LIMIT_WINDOW_MS,
|
|
max: env_1.env.RATE_LIMIT_MAX,
|
|
standardHeaders: true,
|
|
legacyHeaders: false,
|
|
store: new rate_limit_redis_1.default({
|
|
sendCommand: (command, ...args) => redis_1.redis.call(command, ...args),
|
|
prefix: 'rl:global:',
|
|
}),
|
|
message: {
|
|
error: {
|
|
message: 'Too many requests, please try again later',
|
|
code: 'RATE_LIMIT_EXCEEDED',
|
|
},
|
|
},
|
|
});
|
|
exports.emailRateLimit = (0, express_rate_limit_1.default)({
|
|
windowMs: 60 * 60 * 1000, // 1 hour
|
|
max: 30,
|
|
standardHeaders: true,
|
|
legacyHeaders: false,
|
|
store: new rate_limit_redis_1.default({
|
|
sendCommand: (command, ...args) => redis_1.redis.call(command, ...args),
|
|
prefix: 'rl:email:',
|
|
}),
|
|
message: {
|
|
error: {
|
|
message: 'Too many email requests, please try again later',
|
|
code: 'EMAIL_RATE_LIMIT_EXCEEDED',
|
|
},
|
|
},
|
|
});
|
|
exports.responseRateLimit = (0, express_rate_limit_1.default)({
|
|
windowMs: 60 * 60 * 1000, // 1 hour
|
|
max: 10,
|
|
standardHeaders: true,
|
|
legacyHeaders: false,
|
|
store: new rate_limit_redis_1.default({
|
|
sendCommand: (command, ...args) => redis_1.redis.call(command, ...args),
|
|
prefix: 'rl:response:',
|
|
}),
|
|
message: {
|
|
error: {
|
|
message: 'Too many response submissions, please try again later',
|
|
code: 'RESPONSE_RATE_LIMIT_EXCEEDED',
|
|
},
|
|
},
|
|
});
|
|
exports.shiftSignupRateLimit = (0, express_rate_limit_1.default)({
|
|
windowMs: 60 * 60 * 1000, // 1 hour
|
|
max: 10,
|
|
standardHeaders: true,
|
|
legacyHeaders: false,
|
|
store: new rate_limit_redis_1.default({
|
|
sendCommand: (command, ...args) => redis_1.redis.call(command, ...args),
|
|
prefix: 'rl:shift-signup:',
|
|
}),
|
|
message: {
|
|
error: {
|
|
message: 'Too many signup attempts, please try again later',
|
|
code: 'SHIFT_SIGNUP_RATE_LIMIT_EXCEEDED',
|
|
},
|
|
},
|
|
});
|
|
exports.canvassVisitRateLimit = (0, express_rate_limit_1.default)({
|
|
windowMs: 60 * 1000, // 1 minute
|
|
max: 30,
|
|
standardHeaders: true,
|
|
legacyHeaders: false,
|
|
store: new rate_limit_redis_1.default({
|
|
sendCommand: (command, ...args) => redis_1.redis.call(command, ...args),
|
|
prefix: 'rl:canvass-visit:',
|
|
}),
|
|
message: {
|
|
error: {
|
|
message: 'Too many visit recordings, please slow down',
|
|
code: 'CANVASS_VISIT_RATE_LIMIT_EXCEEDED',
|
|
},
|
|
},
|
|
});
|
|
exports.canvassBulkVisitRateLimit = (0, express_rate_limit_1.default)({
|
|
windowMs: 60 * 1000, // 1 minute
|
|
max: 5, // Stricter limit for bulk operations
|
|
standardHeaders: true,
|
|
legacyHeaders: false,
|
|
store: new rate_limit_redis_1.default({
|
|
sendCommand: (command, ...args) => redis_1.redis.call(command, ...args),
|
|
prefix: 'rl:canvass-visit-bulk:',
|
|
}),
|
|
message: {
|
|
error: {
|
|
message: 'Too many bulk visit recordings, please slow down',
|
|
code: 'CANVASS_BULK_VISIT_RATE_LIMIT_EXCEEDED',
|
|
},
|
|
},
|
|
});
|
|
exports.gpsTrackingRateLimit = (0, express_rate_limit_1.default)({
|
|
windowMs: 60 * 1000, // 1 minute
|
|
max: 6,
|
|
standardHeaders: true,
|
|
legacyHeaders: false,
|
|
store: new rate_limit_redis_1.default({
|
|
sendCommand: (command, ...args) => redis_1.redis.call(command, ...args),
|
|
prefix: 'rl:gps-tracking:',
|
|
}),
|
|
message: {
|
|
error: {
|
|
message: 'Too many GPS tracking requests, please slow down',
|
|
code: 'GPS_TRACKING_RATE_LIMIT_EXCEEDED',
|
|
},
|
|
},
|
|
});
|
|
exports.canvassGeocodeRateLimit = (0, express_rate_limit_1.default)({
|
|
windowMs: 60 * 1000, // 1 minute
|
|
max: 10,
|
|
standardHeaders: true,
|
|
legacyHeaders: false,
|
|
store: new rate_limit_redis_1.default({
|
|
sendCommand: (command, ...args) => redis_1.redis.call(command, ...args),
|
|
prefix: 'rl:canvass-geocode:',
|
|
}),
|
|
message: {
|
|
error: {
|
|
message: 'Too many geocode requests, please slow down',
|
|
code: 'CANVASS_GEOCODE_RATE_LIMIT_EXCEEDED',
|
|
},
|
|
},
|
|
});
|
|
exports.adTrackingRateLimit = (0, express_rate_limit_1.default)({
|
|
windowMs: 60 * 1000, // 1 minute
|
|
max: 60, // 60 events/min per IP (generous for scroll-heavy gallery pages)
|
|
standardHeaders: true,
|
|
legacyHeaders: false,
|
|
store: new rate_limit_redis_1.default({
|
|
sendCommand: (command, ...args) => redis_1.redis.call(command, ...args),
|
|
prefix: 'rl:ad-track:',
|
|
}),
|
|
message: {
|
|
error: {
|
|
message: 'Too many tracking requests',
|
|
code: 'RATE_LIMIT_EXCEEDED',
|
|
},
|
|
},
|
|
});
|
|
exports.quickJoinRateLimit = (0, express_rate_limit_1.default)({
|
|
windowMs: 60 * 60 * 1000, // 1 hour
|
|
max: 10,
|
|
standardHeaders: true,
|
|
legacyHeaders: false,
|
|
store: new rate_limit_redis_1.default({
|
|
sendCommand: (command, ...args) => redis_1.redis.call(command, ...args),
|
|
prefix: 'rl:quick-join:',
|
|
}),
|
|
message: {
|
|
error: {
|
|
message: 'Too many join attempts, please try again later',
|
|
code: 'QUICK_JOIN_RATE_LIMIT_EXCEEDED',
|
|
},
|
|
},
|
|
});
|
|
exports.authRateLimit = (0, express_rate_limit_1.default)({
|
|
windowMs: 15 * 60 * 1000,
|
|
max: 10, // Reduced from 20 to prevent brute force attacks
|
|
standardHeaders: true,
|
|
legacyHeaders: false,
|
|
store: new rate_limit_redis_1.default({
|
|
sendCommand: (command, ...args) => redis_1.redis.call(command, ...args),
|
|
prefix: 'rl:auth:',
|
|
}),
|
|
message: {
|
|
error: {
|
|
message: 'Too many authentication attempts, please try again later',
|
|
code: 'AUTH_RATE_LIMIT_EXCEEDED',
|
|
},
|
|
},
|
|
});
|
|
exports.observabilityRateLimit = (0, express_rate_limit_1.default)({
|
|
windowMs: 60 * 1000, // 1 minute
|
|
max: 20, // 20 requests per minute (stricter than global 500/min)
|
|
standardHeaders: true,
|
|
legacyHeaders: false,
|
|
store: new rate_limit_redis_1.default({
|
|
sendCommand: (command, ...args) => redis_1.redis.call(command, ...args),
|
|
prefix: 'rl:observability:',
|
|
}),
|
|
message: {
|
|
error: {
|
|
message: 'Too many observability requests, please try again later',
|
|
code: 'OBSERVABILITY_RATE_LIMIT_EXCEEDED',
|
|
},
|
|
},
|
|
});
|
|
exports.docsAnalyticsRateLimit = (0, express_rate_limit_1.default)({
|
|
windowMs: 60 * 1000, // 1 minute
|
|
max: 60, // 60 requests/min per IP
|
|
standardHeaders: true,
|
|
legacyHeaders: false,
|
|
store: new rate_limit_redis_1.default({
|
|
sendCommand: (command, ...args) => redis_1.redis.call(command, ...args),
|
|
prefix: 'rl:docs-analytics:',
|
|
}),
|
|
message: {
|
|
error: {
|
|
message: 'Too many tracking requests, please slow down',
|
|
code: 'DOCS_ANALYTICS_RATE_LIMIT_EXCEEDED',
|
|
},
|
|
},
|
|
});
|
|
exports.docsCommentAnonRateLimit = (0, express_rate_limit_1.default)({
|
|
windowMs: 60 * 60 * 1000, // 1 hour
|
|
max: 5,
|
|
standardHeaders: true,
|
|
legacyHeaders: false,
|
|
store: new rate_limit_redis_1.default({
|
|
sendCommand: (command, ...args) => redis_1.redis.call(command, ...args),
|
|
prefix: 'rl:docs-comment-anon:',
|
|
}),
|
|
message: {
|
|
error: {
|
|
message: 'Too many anonymous comments, please try again later',
|
|
code: 'DOCS_COMMENT_ANON_RATE_LIMIT_EXCEEDED',
|
|
},
|
|
},
|
|
});
|
|
exports.docsCommentAuthRateLimit = (0, express_rate_limit_1.default)({
|
|
windowMs: 60 * 60 * 1000, // 1 hour
|
|
max: 30,
|
|
standardHeaders: true,
|
|
legacyHeaders: false,
|
|
store: new rate_limit_redis_1.default({
|
|
sendCommand: (command, ...args) => redis_1.redis.call(command, ...args),
|
|
prefix: 'rl:docs-comment-auth:',
|
|
}),
|
|
message: {
|
|
error: {
|
|
message: 'Too many comments, please try again later',
|
|
code: 'DOCS_COMMENT_AUTH_RATE_LIMIT_EXCEEDED',
|
|
},
|
|
},
|
|
});
|
|
exports.docsCommentFetchRateLimit = (0, express_rate_limit_1.default)({
|
|
windowMs: 60 * 1000, // 1 minute
|
|
max: 60,
|
|
standardHeaders: true,
|
|
legacyHeaders: false,
|
|
store: new rate_limit_redis_1.default({
|
|
sendCommand: (command, ...args) => redis_1.redis.call(command, ...args),
|
|
prefix: 'rl:docs-comment-fetch:',
|
|
}),
|
|
message: {
|
|
error: {
|
|
message: 'Too many comment fetch requests, please slow down',
|
|
code: 'DOCS_COMMENT_FETCH_RATE_LIMIT_EXCEEDED',
|
|
},
|
|
},
|
|
});
|
|
exports.profileViewRateLimit = (0, express_rate_limit_1.default)({
|
|
windowMs: 60 * 1000, // 1 minute
|
|
max: 60, // 60 requests per minute (shared across profile, photo, activity endpoints)
|
|
standardHeaders: true,
|
|
legacyHeaders: false,
|
|
store: new rate_limit_redis_1.default({
|
|
sendCommand: (command, ...args) => redis_1.redis.call(command, ...args),
|
|
prefix: 'rl:profile-view:',
|
|
}),
|
|
message: {
|
|
error: {
|
|
message: 'Too many profile requests, please try again later',
|
|
code: 'PROFILE_VIEW_RATE_LIMIT_EXCEEDED',
|
|
},
|
|
},
|
|
});
|
|
exports.profileEditRateLimit = (0, express_rate_limit_1.default)({
|
|
windowMs: 60 * 60 * 1000, // 1 hour
|
|
max: 20,
|
|
standardHeaders: true,
|
|
legacyHeaders: false,
|
|
store: new rate_limit_redis_1.default({
|
|
sendCommand: (command, ...args) => redis_1.redis.call(command, ...args),
|
|
prefix: 'rl:profile-edit:',
|
|
}),
|
|
message: {
|
|
error: {
|
|
message: 'Too many profile edit requests, please try again later',
|
|
code: 'PROFILE_EDIT_RATE_LIMIT_EXCEEDED',
|
|
},
|
|
},
|
|
});
|
|
exports.profilePhotoRateLimit = (0, express_rate_limit_1.default)({
|
|
windowMs: 60 * 60 * 1000, // 1 hour
|
|
max: 5,
|
|
standardHeaders: true,
|
|
legacyHeaders: false,
|
|
store: new rate_limit_redis_1.default({
|
|
sendCommand: (command, ...args) => redis_1.redis.call(command, ...args),
|
|
prefix: 'rl:profile-photo:',
|
|
}),
|
|
message: {
|
|
error: {
|
|
message: 'Too many photo uploads, please try again later',
|
|
code: 'PROFILE_PHOTO_RATE_LIMIT_EXCEEDED',
|
|
},
|
|
},
|
|
});
|
|
exports.profilePasswordRateLimit = (0, express_rate_limit_1.default)({
|
|
windowMs: 15 * 60 * 1000, // 15 minutes
|
|
max: 5, // Stricter than auth (10/15min) — profile passwords may be simpler
|
|
standardHeaders: true,
|
|
legacyHeaders: false,
|
|
store: new rate_limit_redis_1.default({
|
|
sendCommand: (command, ...args) => redis_1.redis.call(command, ...args),
|
|
prefix: 'rl:profile-password:',
|
|
}),
|
|
message: {
|
|
error: {
|
|
message: 'Too many password attempts, please try again later',
|
|
code: 'PROFILE_PASSWORD_RATE_LIMIT_EXCEEDED',
|
|
},
|
|
},
|
|
});
|
|
exports.eventSubmissionRateLimit = (0, express_rate_limit_1.default)({
|
|
windowMs: 60 * 60 * 1000, // 1 hour
|
|
max: 5,
|
|
standardHeaders: true,
|
|
legacyHeaders: false,
|
|
store: new rate_limit_redis_1.default({
|
|
sendCommand: (command, ...args) => redis_1.redis.call(command, ...args),
|
|
prefix: 'rl:event-submit:',
|
|
}),
|
|
message: {
|
|
error: {
|
|
message: 'Too many event submissions, please try again later',
|
|
code: 'EVENT_SUBMISSION_RATE_LIMIT_EXCEEDED',
|
|
},
|
|
},
|
|
});
|
|
exports.errorReportRateLimit = (0, express_rate_limit_1.default)({
|
|
windowMs: 60 * 60 * 1000, // 1 hour
|
|
max: 5,
|
|
standardHeaders: true,
|
|
legacyHeaders: false,
|
|
store: new rate_limit_redis_1.default({
|
|
sendCommand: (command, ...args) => redis_1.redis.call(command, ...args),
|
|
prefix: 'rl:error-report:',
|
|
}),
|
|
message: {
|
|
error: {
|
|
message: 'Too many error reports, please try again later',
|
|
code: 'ERROR_REPORT_RATE_LIMIT_EXCEEDED',
|
|
},
|
|
},
|
|
});
|
|
exports.healthMetricsRateLimit = (0, express_rate_limit_1.default)({
|
|
windowMs: 60 * 1000, // 1 minute
|
|
max: 30, // 30 requests per minute
|
|
standardHeaders: true,
|
|
legacyHeaders: false,
|
|
store: new rate_limit_redis_1.default({
|
|
sendCommand: (command, ...args) => redis_1.redis.call(command, ...args),
|
|
prefix: 'rl:health-metrics:',
|
|
}),
|
|
message: {
|
|
error: {
|
|
message: 'Too many health check requests, please try again later',
|
|
code: 'HEALTH_METRICS_RATE_LIMIT_EXCEEDED',
|
|
},
|
|
},
|
|
});
|
|
//# sourceMappingURL=rate-limit.js.map
|