mcp-server-rocketchat-threads 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +332 -0
- package/dist/api/client.d.ts +119 -0
- package/dist/api/client.d.ts.map +1 -0
- package/dist/api/client.js +305 -0
- package/dist/api/client.js.map +1 -0
- package/dist/api/index.d.ts +6 -0
- package/dist/api/index.d.ts.map +1 -0
- package/dist/api/index.js +22 -0
- package/dist/api/index.js.map +1 -0
- package/dist/api/schemas.d.ts +10636 -0
- package/dist/api/schemas.d.ts.map +1 -0
- package/dist/api/schemas.js +267 -0
- package/dist/api/schemas.js.map +1 -0
- package/dist/api/types.d.ts +263 -0
- package/dist/api/types.d.ts.map +1 -0
- package/dist/api/types.js +7 -0
- package/dist/api/types.js.map +1 -0
- package/dist/config/config.d.ts +37 -0
- package/dist/config/config.d.ts.map +1 -0
- package/dist/config/config.js +79 -0
- package/dist/config/config.js.map +1 -0
- package/dist/config/index.d.ts +5 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +21 -0
- package/dist/config/index.js.map +1 -0
- package/dist/di/container.d.ts +101 -0
- package/dist/di/container.d.ts.map +1 -0
- package/dist/di/container.js +214 -0
- package/dist/di/container.js.map +1 -0
- package/dist/di/index.d.ts +6 -0
- package/dist/di/index.d.ts.map +1 -0
- package/dist/di/index.js +12 -0
- package/dist/di/index.js.map +1 -0
- package/dist/formatters/index.d.ts +6 -0
- package/dist/formatters/index.d.ts.map +1 -0
- package/dist/formatters/index.js +22 -0
- package/dist/formatters/index.js.map +1 -0
- package/dist/formatters/message-formatter.d.ts +64 -0
- package/dist/formatters/message-formatter.d.ts.map +1 -0
- package/dist/formatters/message-formatter.js +161 -0
- package/dist/formatters/message-formatter.js.map +1 -0
- package/dist/formatters/response-builder.d.ts +60 -0
- package/dist/formatters/response-builder.d.ts.map +1 -0
- package/dist/formatters/response-builder.js +108 -0
- package/dist/formatters/response-builder.js.map +1 -0
- package/dist/guards/index.d.ts +12 -0
- package/dist/guards/index.d.ts.map +1 -0
- package/dist/guards/index.js +42 -0
- package/dist/guards/index.js.map +1 -0
- package/dist/guards/input-validator.d.ts +89 -0
- package/dist/guards/input-validator.d.ts.map +1 -0
- package/dist/guards/input-validator.js +266 -0
- package/dist/guards/input-validator.js.map +1 -0
- package/dist/guards/rate-limiter.d.ts +115 -0
- package/dist/guards/rate-limiter.d.ts.map +1 -0
- package/dist/guards/rate-limiter.js +226 -0
- package/dist/guards/rate-limiter.js.map +1 -0
- package/dist/guards/sanitizer.d.ts +35 -0
- package/dist/guards/sanitizer.d.ts.map +1 -0
- package/dist/guards/sanitizer.js +111 -0
- package/dist/guards/sanitizer.js.map +1 -0
- package/dist/guards/write-guard.d.ts +33 -0
- package/dist/guards/write-guard.d.ts.map +1 -0
- package/dist/guards/write-guard.js +90 -0
- package/dist/guards/write-guard.js.map +1 -0
- package/dist/http-server.d.ts +9 -0
- package/dist/http-server.d.ts.map +1 -0
- package/dist/http-server.js +190 -0
- package/dist/http-server.js.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +114 -0
- package/dist/index.js.map +1 -0
- package/dist/tools/base.d.ts +85 -0
- package/dist/tools/base.d.ts.map +1 -0
- package/dist/tools/base.js +184 -0
- package/dist/tools/base.js.map +1 -0
- package/dist/tools/channel-tools.d.ts +18 -0
- package/dist/tools/channel-tools.d.ts.map +1 -0
- package/dist/tools/channel-tools.js +151 -0
- package/dist/tools/channel-tools.js.map +1 -0
- package/dist/tools/handler-utils.d.ts +75 -0
- package/dist/tools/handler-utils.d.ts.map +1 -0
- package/dist/tools/handler-utils.js +105 -0
- package/dist/tools/handler-utils.js.map +1 -0
- package/dist/tools/index.d.ts +17 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +40 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/message-tools.d.ts +20 -0
- package/dist/tools/message-tools.d.ts.map +1 -0
- package/dist/tools/message-tools.js +194 -0
- package/dist/tools/message-tools.js.map +1 -0
- package/dist/tools/thread-tools.d.ts +23 -0
- package/dist/tools/thread-tools.d.ts.map +1 -0
- package/dist/tools/thread-tools.js +243 -0
- package/dist/tools/thread-tools.js.map +1 -0
- package/dist/tools/user-tools.d.ts +14 -0
- package/dist/tools/user-tools.d.ts.map +1 -0
- package/dist/tools/user-tools.js +120 -0
- package/dist/tools/user-tools.js.map +1 -0
- package/dist/tools/write-tools.d.ts +15 -0
- package/dist/tools/write-tools.d.ts.map +1 -0
- package/dist/tools/write-tools.js +181 -0
- package/dist/tools/write-tools.js.map +1 -0
- package/dist/utils/cache.d.ts +47 -0
- package/dist/utils/cache.d.ts.map +1 -0
- package/dist/utils/cache.js +116 -0
- package/dist/utils/cache.js.map +1 -0
- package/dist/utils/error-handler.d.ts +64 -0
- package/dist/utils/error-handler.d.ts.map +1 -0
- package/dist/utils/error-handler.js +148 -0
- package/dist/utils/error-handler.js.map +1 -0
- package/dist/utils/index.d.ts +12 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +33 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/logger.d.ts +50 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +118 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/time-parser.d.ts +37 -0
- package/dist/utils/time-parser.d.ts.map +1 -0
- package/dist/utils/time-parser.js +98 -0
- package/dist/utils/time-parser.js.map +1 -0
- package/dist/utils/token-counter.d.ts +42 -0
- package/dist/utils/token-counter.d.ts.map +1 -0
- package/dist/utils/token-counter.js +81 -0
- package/dist/utils/token-counter.js.map +1 -0
- package/package.json +68 -0
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Input Validator - Validates and sanitizes input parameters
|
|
4
|
+
* Provides defense against injection attacks and malformed input
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.escapeHtml = exports.validateOffset = exports.validateLimit = exports.validateEmoji = exports.validateMessageText = exports.validateQuery = exports.validateUsername = exports.validateUserId = exports.validateMessageId = exports.validateRoomId = exports.InputValidator = exports.MAX_LENGTHS = void 0;
|
|
8
|
+
const logger_js_1 = require("../utils/logger.js");
|
|
9
|
+
const logger = (0, logger_js_1.getLogger)('InputValidator');
|
|
10
|
+
/**
|
|
11
|
+
* Maximum lengths for various input types
|
|
12
|
+
*/
|
|
13
|
+
exports.MAX_LENGTHS = {
|
|
14
|
+
roomId: 64,
|
|
15
|
+
messageId: 64,
|
|
16
|
+
threadId: 64,
|
|
17
|
+
userId: 64,
|
|
18
|
+
username: 128,
|
|
19
|
+
query: 500,
|
|
20
|
+
messageText: 10000,
|
|
21
|
+
emoji: 64,
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Patterns for valid input formats
|
|
25
|
+
*/
|
|
26
|
+
const VALID_PATTERNS = {
|
|
27
|
+
// RocketChat IDs are alphanumeric with some special chars
|
|
28
|
+
id: /^[a-zA-Z0-9_-]+$/,
|
|
29
|
+
// Usernames can contain letters, numbers, dots, hyphens, underscores
|
|
30
|
+
username: /^[a-zA-Z0-9._-]+$/,
|
|
31
|
+
// Emoji names are alphanumeric with underscores, wrapped in colons
|
|
32
|
+
emoji: /^:?[a-zA-Z0-9_+-]+:?$/,
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* Dangerous patterns to detect in input
|
|
36
|
+
*/
|
|
37
|
+
const DANGEROUS_PATTERNS = [
|
|
38
|
+
// MongoDB injection patterns
|
|
39
|
+
/\$where/i,
|
|
40
|
+
/\$gt/i,
|
|
41
|
+
/\$lt/i,
|
|
42
|
+
/\$ne/i,
|
|
43
|
+
/\$regex/i,
|
|
44
|
+
/\$or/i,
|
|
45
|
+
/\$and/i,
|
|
46
|
+
// NoSQL injection
|
|
47
|
+
/\{\s*['"]\$[a-z]+['"]/i,
|
|
48
|
+
// Script injection
|
|
49
|
+
/<script\b/i,
|
|
50
|
+
/javascript:/i,
|
|
51
|
+
/on\w+\s*=/i,
|
|
52
|
+
// Command injection
|
|
53
|
+
/[;&|`$]/,
|
|
54
|
+
];
|
|
55
|
+
/**
|
|
56
|
+
* Input validator class
|
|
57
|
+
*/
|
|
58
|
+
class InputValidator {
|
|
59
|
+
/**
|
|
60
|
+
* Validate a room ID
|
|
61
|
+
*/
|
|
62
|
+
static validateRoomId(roomId) {
|
|
63
|
+
if (typeof roomId !== 'string') {
|
|
64
|
+
return { valid: false, error: 'Room ID must be a string' };
|
|
65
|
+
}
|
|
66
|
+
if (!roomId.trim()) {
|
|
67
|
+
return { valid: false, error: 'Room ID cannot be empty' };
|
|
68
|
+
}
|
|
69
|
+
if (roomId.length > exports.MAX_LENGTHS.roomId) {
|
|
70
|
+
return { valid: false, error: `Room ID exceeds maximum length of ${exports.MAX_LENGTHS.roomId}` };
|
|
71
|
+
}
|
|
72
|
+
// Check for dangerous patterns
|
|
73
|
+
if (this.containsDangerousPattern(roomId)) {
|
|
74
|
+
logger.warn('Dangerous pattern detected in room ID', { roomId: roomId.substring(0, 20) });
|
|
75
|
+
return { valid: false, error: 'Room ID contains invalid characters' };
|
|
76
|
+
}
|
|
77
|
+
return { valid: true, sanitized: roomId.trim() };
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Validate a message ID
|
|
81
|
+
*/
|
|
82
|
+
static validateMessageId(messageId) {
|
|
83
|
+
if (typeof messageId !== 'string') {
|
|
84
|
+
return { valid: false, error: 'Message ID must be a string' };
|
|
85
|
+
}
|
|
86
|
+
if (!messageId.trim()) {
|
|
87
|
+
return { valid: false, error: 'Message ID cannot be empty' };
|
|
88
|
+
}
|
|
89
|
+
if (messageId.length > exports.MAX_LENGTHS.messageId) {
|
|
90
|
+
return { valid: false, error: `Message ID exceeds maximum length of ${exports.MAX_LENGTHS.messageId}` };
|
|
91
|
+
}
|
|
92
|
+
if (!VALID_PATTERNS.id.test(messageId)) {
|
|
93
|
+
return { valid: false, error: 'Message ID contains invalid characters' };
|
|
94
|
+
}
|
|
95
|
+
return { valid: true, sanitized: messageId.trim() };
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Validate a user ID
|
|
99
|
+
*/
|
|
100
|
+
static validateUserId(userId) {
|
|
101
|
+
if (typeof userId !== 'string') {
|
|
102
|
+
return { valid: false, error: 'User ID must be a string' };
|
|
103
|
+
}
|
|
104
|
+
if (!userId.trim()) {
|
|
105
|
+
return { valid: false, error: 'User ID cannot be empty' };
|
|
106
|
+
}
|
|
107
|
+
if (userId.length > exports.MAX_LENGTHS.userId) {
|
|
108
|
+
return { valid: false, error: `User ID exceeds maximum length of ${exports.MAX_LENGTHS.userId}` };
|
|
109
|
+
}
|
|
110
|
+
if (!VALID_PATTERNS.id.test(userId)) {
|
|
111
|
+
return { valid: false, error: 'User ID contains invalid characters' };
|
|
112
|
+
}
|
|
113
|
+
return { valid: true, sanitized: userId.trim() };
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Validate a username
|
|
117
|
+
*/
|
|
118
|
+
static validateUsername(username) {
|
|
119
|
+
if (typeof username !== 'string') {
|
|
120
|
+
return { valid: false, error: 'Username must be a string' };
|
|
121
|
+
}
|
|
122
|
+
// Remove @ prefix if present
|
|
123
|
+
const cleaned = username.replace(/^@/, '').trim();
|
|
124
|
+
if (!cleaned) {
|
|
125
|
+
return { valid: false, error: 'Username cannot be empty' };
|
|
126
|
+
}
|
|
127
|
+
if (cleaned.length > exports.MAX_LENGTHS.username) {
|
|
128
|
+
return { valid: false, error: `Username exceeds maximum length of ${exports.MAX_LENGTHS.username}` };
|
|
129
|
+
}
|
|
130
|
+
if (!VALID_PATTERNS.username.test(cleaned)) {
|
|
131
|
+
return { valid: false, error: 'Username contains invalid characters' };
|
|
132
|
+
}
|
|
133
|
+
return { valid: true, sanitized: cleaned };
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Validate a search query
|
|
137
|
+
*/
|
|
138
|
+
static validateQuery(query) {
|
|
139
|
+
if (typeof query !== 'string') {
|
|
140
|
+
return { valid: false, error: 'Search query must be a string' };
|
|
141
|
+
}
|
|
142
|
+
if (!query.trim()) {
|
|
143
|
+
return { valid: false, error: 'Search query cannot be empty' };
|
|
144
|
+
}
|
|
145
|
+
if (query.length > exports.MAX_LENGTHS.query) {
|
|
146
|
+
return { valid: false, error: `Search query exceeds maximum length of ${exports.MAX_LENGTHS.query}` };
|
|
147
|
+
}
|
|
148
|
+
// Don't check for dangerous patterns in queries as they might be searching for code
|
|
149
|
+
// But do sanitize for display
|
|
150
|
+
return { valid: true, sanitized: query.trim() };
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Validate message text
|
|
154
|
+
*/
|
|
155
|
+
static validateMessageText(text) {
|
|
156
|
+
if (typeof text !== 'string') {
|
|
157
|
+
return { valid: false, error: 'Message text must be a string' };
|
|
158
|
+
}
|
|
159
|
+
if (!text.trim()) {
|
|
160
|
+
return { valid: false, error: 'Message text cannot be empty' };
|
|
161
|
+
}
|
|
162
|
+
if (text.length > exports.MAX_LENGTHS.messageText) {
|
|
163
|
+
return { valid: false, error: `Message text exceeds maximum length of ${exports.MAX_LENGTHS.messageText}` };
|
|
164
|
+
}
|
|
165
|
+
return { valid: true, sanitized: text };
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Validate an emoji
|
|
169
|
+
*/
|
|
170
|
+
static validateEmoji(emoji) {
|
|
171
|
+
if (typeof emoji !== 'string') {
|
|
172
|
+
return { valid: false, error: 'Emoji must be a string' };
|
|
173
|
+
}
|
|
174
|
+
const cleaned = emoji.trim();
|
|
175
|
+
if (!cleaned) {
|
|
176
|
+
return { valid: false, error: 'Emoji cannot be empty' };
|
|
177
|
+
}
|
|
178
|
+
if (cleaned.length > exports.MAX_LENGTHS.emoji) {
|
|
179
|
+
return { valid: false, error: `Emoji exceeds maximum length of ${exports.MAX_LENGTHS.emoji}` };
|
|
180
|
+
}
|
|
181
|
+
if (!VALID_PATTERNS.emoji.test(cleaned)) {
|
|
182
|
+
return { valid: false, error: 'Emoji contains invalid characters' };
|
|
183
|
+
}
|
|
184
|
+
return { valid: true, sanitized: cleaned };
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Validate pagination limit
|
|
188
|
+
*/
|
|
189
|
+
static validateLimit(limit, min = 1, max = 100, defaultValue = 50) {
|
|
190
|
+
if (limit === undefined || limit === null) {
|
|
191
|
+
return defaultValue;
|
|
192
|
+
}
|
|
193
|
+
const num = Number(limit);
|
|
194
|
+
if (isNaN(num)) {
|
|
195
|
+
return defaultValue;
|
|
196
|
+
}
|
|
197
|
+
return Math.max(min, Math.min(max, Math.floor(num)));
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Validate pagination offset
|
|
201
|
+
*/
|
|
202
|
+
static validateOffset(offset, defaultValue = 0) {
|
|
203
|
+
if (offset === undefined || offset === null) {
|
|
204
|
+
return defaultValue;
|
|
205
|
+
}
|
|
206
|
+
const num = Number(offset);
|
|
207
|
+
if (isNaN(num) || num < 0) {
|
|
208
|
+
return defaultValue;
|
|
209
|
+
}
|
|
210
|
+
return Math.floor(num);
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Check if string contains dangerous patterns
|
|
214
|
+
*/
|
|
215
|
+
static containsDangerousPattern(input) {
|
|
216
|
+
return DANGEROUS_PATTERNS.some(pattern => pattern.test(input));
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Escape HTML entities for safe display
|
|
220
|
+
*/
|
|
221
|
+
static escapeHtml(text) {
|
|
222
|
+
const htmlEntities = {
|
|
223
|
+
'&': '&',
|
|
224
|
+
'<': '<',
|
|
225
|
+
'>': '>',
|
|
226
|
+
'"': '"',
|
|
227
|
+
"'": ''',
|
|
228
|
+
};
|
|
229
|
+
return text.replace(/[&<>"']/g, char => htmlEntities[char] || char);
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Validate and sanitize a generic string input
|
|
233
|
+
*/
|
|
234
|
+
static validateString(value, fieldName, maxLength, required = true) {
|
|
235
|
+
if (value === undefined || value === null) {
|
|
236
|
+
if (required) {
|
|
237
|
+
return { valid: false, error: `${fieldName} is required` };
|
|
238
|
+
}
|
|
239
|
+
return { valid: true };
|
|
240
|
+
}
|
|
241
|
+
if (typeof value !== 'string') {
|
|
242
|
+
return { valid: false, error: `${fieldName} must be a string` };
|
|
243
|
+
}
|
|
244
|
+
const trimmed = value.trim();
|
|
245
|
+
if (required && !trimmed) {
|
|
246
|
+
return { valid: false, error: `${fieldName} cannot be empty` };
|
|
247
|
+
}
|
|
248
|
+
if (trimmed.length > maxLength) {
|
|
249
|
+
return { valid: false, error: `${fieldName} exceeds maximum length of ${maxLength}` };
|
|
250
|
+
}
|
|
251
|
+
return { valid: true, sanitized: trimmed };
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
exports.InputValidator = InputValidator;
|
|
255
|
+
// Export singleton-like utility functions
|
|
256
|
+
exports.validateRoomId = InputValidator.validateRoomId.bind(InputValidator);
|
|
257
|
+
exports.validateMessageId = InputValidator.validateMessageId.bind(InputValidator);
|
|
258
|
+
exports.validateUserId = InputValidator.validateUserId.bind(InputValidator);
|
|
259
|
+
exports.validateUsername = InputValidator.validateUsername.bind(InputValidator);
|
|
260
|
+
exports.validateQuery = InputValidator.validateQuery.bind(InputValidator);
|
|
261
|
+
exports.validateMessageText = InputValidator.validateMessageText.bind(InputValidator);
|
|
262
|
+
exports.validateEmoji = InputValidator.validateEmoji.bind(InputValidator);
|
|
263
|
+
exports.validateLimit = InputValidator.validateLimit.bind(InputValidator);
|
|
264
|
+
exports.validateOffset = InputValidator.validateOffset.bind(InputValidator);
|
|
265
|
+
exports.escapeHtml = InputValidator.escapeHtml.bind(InputValidator);
|
|
266
|
+
//# sourceMappingURL=input-validator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"input-validator.js","sourceRoot":"","sources":["../../src/guards/input-validator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rate Limiter - Prevents excessive API calls
|
|
3
|
+
* Uses a sliding window algorithm for rate limiting
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Rate limit configuration
|
|
7
|
+
*/
|
|
8
|
+
export interface RateLimitConfig {
|
|
9
|
+
/** Maximum number of requests allowed in the window */
|
|
10
|
+
maxRequests: number;
|
|
11
|
+
/** Window size in milliseconds */
|
|
12
|
+
windowMs: number;
|
|
13
|
+
/** Optional key prefix for namespacing */
|
|
14
|
+
keyPrefix?: string;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Rate limit check result
|
|
18
|
+
*/
|
|
19
|
+
export interface RateLimitResult {
|
|
20
|
+
allowed: boolean;
|
|
21
|
+
remaining: number;
|
|
22
|
+
resetAt: number;
|
|
23
|
+
retryAfterMs?: number;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Default rate limit configurations
|
|
27
|
+
*/
|
|
28
|
+
export declare const DEFAULT_LIMITS: {
|
|
29
|
+
/** General API calls */
|
|
30
|
+
readonly api: {
|
|
31
|
+
readonly maxRequests: 100;
|
|
32
|
+
readonly windowMs: 60000;
|
|
33
|
+
};
|
|
34
|
+
/** Write operations (send message, react) */
|
|
35
|
+
readonly write: {
|
|
36
|
+
readonly maxRequests: 20;
|
|
37
|
+
readonly windowMs: 60000;
|
|
38
|
+
};
|
|
39
|
+
/** Search operations */
|
|
40
|
+
readonly search: {
|
|
41
|
+
readonly maxRequests: 30;
|
|
42
|
+
readonly windowMs: 60000;
|
|
43
|
+
};
|
|
44
|
+
/** Heavy operations (list all, bulk operations) */
|
|
45
|
+
readonly heavy: {
|
|
46
|
+
readonly maxRequests: 10;
|
|
47
|
+
readonly windowMs: 60000;
|
|
48
|
+
};
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* Rate limiter class with sliding window algorithm
|
|
52
|
+
*/
|
|
53
|
+
export declare class RateLimiter {
|
|
54
|
+
private records;
|
|
55
|
+
private config;
|
|
56
|
+
private cleanupInterval;
|
|
57
|
+
constructor(config: RateLimitConfig);
|
|
58
|
+
/**
|
|
59
|
+
* Check if a request is allowed and record it
|
|
60
|
+
*/
|
|
61
|
+
check(key: string): RateLimitResult;
|
|
62
|
+
/**
|
|
63
|
+
* Check without recording (peek)
|
|
64
|
+
*/
|
|
65
|
+
peek(key: string): RateLimitResult;
|
|
66
|
+
/**
|
|
67
|
+
* Reset rate limit for a key
|
|
68
|
+
*/
|
|
69
|
+
reset(key: string): void;
|
|
70
|
+
/**
|
|
71
|
+
* Reset all rate limits
|
|
72
|
+
*/
|
|
73
|
+
resetAll(): void;
|
|
74
|
+
/**
|
|
75
|
+
* Get current configuration
|
|
76
|
+
*/
|
|
77
|
+
getConfig(): RateLimitConfig;
|
|
78
|
+
/**
|
|
79
|
+
* Clean up old records
|
|
80
|
+
*/
|
|
81
|
+
private cleanup;
|
|
82
|
+
/**
|
|
83
|
+
* Stop the cleanup interval
|
|
84
|
+
*/
|
|
85
|
+
destroy(): void;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Rate limiter manager for multiple rate limit types
|
|
89
|
+
*/
|
|
90
|
+
export declare class RateLimiterManager {
|
|
91
|
+
private limiters;
|
|
92
|
+
/**
|
|
93
|
+
* Get or create a rate limiter
|
|
94
|
+
*/
|
|
95
|
+
getLimiter(name: string, config?: RateLimitConfig): RateLimiter;
|
|
96
|
+
/**
|
|
97
|
+
* Check rate limit for a specific limiter type
|
|
98
|
+
*/
|
|
99
|
+
check(limiterName: string, key: string): RateLimitResult;
|
|
100
|
+
/**
|
|
101
|
+
* Reset all limiters
|
|
102
|
+
*/
|
|
103
|
+
resetAll(): void;
|
|
104
|
+
/**
|
|
105
|
+
* Destroy all limiters
|
|
106
|
+
*/
|
|
107
|
+
destroy(): void;
|
|
108
|
+
}
|
|
109
|
+
export declare function getRateLimiterManager(): RateLimiterManager;
|
|
110
|
+
export declare function resetRateLimiterManager(): void;
|
|
111
|
+
export declare function checkRateLimit(limiterName: string, key: string): RateLimitResult;
|
|
112
|
+
export declare function checkApiRateLimit(key: string): RateLimitResult;
|
|
113
|
+
export declare function checkWriteRateLimit(key: string): RateLimitResult;
|
|
114
|
+
export declare function checkSearchRateLimit(key: string): RateLimitResult;
|
|
115
|
+
//# sourceMappingURL=rate-limiter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rate-limiter.d.ts","sourceRoot":"","sources":["../../src/guards/rate-limiter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH;;GAEG;AACH,MAAM,WAAW,eAAe;IAC5B,uDAAuD;IACvD,WAAW,EAAE,MAAM,CAAC;IACpB,kCAAkC;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,0CAA0C;IAC1C,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;GAEG;AACH,eAAO,MAAM,cAAc;IACvB,wBAAwB;;;;;IAExB,6CAA6C;;;;;IAE7C,wBAAwB;;;;;IAExB,mDAAmD;;;;;CAE7C,CAAC;AASX;;GAEG;AACH,qBAAa,WAAW;IACpB,OAAO,CAAC,OAAO,CAAyC;IACxD,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,eAAe,CAA+B;gBAE1C,MAAM,EAAE,eAAe;IAOnC;;OAEG;IACH,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe;IAgDnC;;OAEG;IACH,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe;IA6BlC;;OAEG;IACH,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAKxB;;OAEG;IACH,QAAQ,IAAI,IAAI;IAIhB;;OAEG;IACH,SAAS,IAAI,eAAe;IAI5B;;OAEG;IACH,OAAO,CAAC,OAAO;IAYf;;OAEG;IACH,OAAO,IAAI,IAAI;CAOlB;AAED;;GAEG;AACH,qBAAa,kBAAkB;IAC3B,OAAO,CAAC,QAAQ,CAAuC;IAEvD;;OAEG;IACH,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,eAAe,GAAG,WAAW;IAW/D;;OAEG;IACH,KAAK,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,eAAe;IAKxD;;OAEG;IACH,QAAQ,IAAI,IAAI;IAMhB;;OAEG;IACH,OAAO,IAAI,IAAI;CAMlB;AAKD,wBAAgB,qBAAqB,IAAI,kBAAkB,CAK1D;AAED,wBAAgB,uBAAuB,IAAI,IAAI,CAK9C;AAGD,wBAAgB,cAAc,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,eAAe,CAEhF;AAED,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe,CAE9D;AAED,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe,CAEhE;AAED,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe,CAEjE"}
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Rate Limiter - Prevents excessive API calls
|
|
4
|
+
* Uses a sliding window algorithm for rate limiting
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.RateLimiterManager = exports.RateLimiter = exports.DEFAULT_LIMITS = void 0;
|
|
8
|
+
exports.getRateLimiterManager = getRateLimiterManager;
|
|
9
|
+
exports.resetRateLimiterManager = resetRateLimiterManager;
|
|
10
|
+
exports.checkRateLimit = checkRateLimit;
|
|
11
|
+
exports.checkApiRateLimit = checkApiRateLimit;
|
|
12
|
+
exports.checkWriteRateLimit = checkWriteRateLimit;
|
|
13
|
+
exports.checkSearchRateLimit = checkSearchRateLimit;
|
|
14
|
+
const logger_js_1 = require("../utils/logger.js");
|
|
15
|
+
const logger = (0, logger_js_1.getLogger)('RateLimiter');
|
|
16
|
+
/**
|
|
17
|
+
* Default rate limit configurations
|
|
18
|
+
*/
|
|
19
|
+
exports.DEFAULT_LIMITS = {
|
|
20
|
+
/** General API calls */
|
|
21
|
+
api: { maxRequests: 100, windowMs: 60000 },
|
|
22
|
+
/** Write operations (send message, react) */
|
|
23
|
+
write: { maxRequests: 20, windowMs: 60000 },
|
|
24
|
+
/** Search operations */
|
|
25
|
+
search: { maxRequests: 30, windowMs: 60000 },
|
|
26
|
+
/** Heavy operations (list all, bulk operations) */
|
|
27
|
+
heavy: { maxRequests: 10, windowMs: 60000 },
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Rate limiter class with sliding window algorithm
|
|
31
|
+
*/
|
|
32
|
+
class RateLimiter {
|
|
33
|
+
records = new Map();
|
|
34
|
+
config;
|
|
35
|
+
cleanupInterval = null;
|
|
36
|
+
constructor(config) {
|
|
37
|
+
this.config = config;
|
|
38
|
+
// Cleanup old records every minute
|
|
39
|
+
this.cleanupInterval = setInterval(() => this.cleanup(), 60000);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Check if a request is allowed and record it
|
|
43
|
+
*/
|
|
44
|
+
check(key) {
|
|
45
|
+
const fullKey = this.config.keyPrefix ? `${this.config.keyPrefix}:${key}` : key;
|
|
46
|
+
const now = Date.now();
|
|
47
|
+
const windowStart = now - this.config.windowMs;
|
|
48
|
+
// Get or create record
|
|
49
|
+
let record = this.records.get(fullKey);
|
|
50
|
+
if (!record) {
|
|
51
|
+
record = { timestamps: [] };
|
|
52
|
+
this.records.set(fullKey, record);
|
|
53
|
+
}
|
|
54
|
+
// Remove timestamps outside the window
|
|
55
|
+
record.timestamps = record.timestamps.filter(ts => ts > windowStart);
|
|
56
|
+
const currentCount = record.timestamps.length;
|
|
57
|
+
const remaining = Math.max(0, this.config.maxRequests - currentCount);
|
|
58
|
+
const resetAt = record.timestamps.length > 0
|
|
59
|
+
? record.timestamps[0] + this.config.windowMs
|
|
60
|
+
: now + this.config.windowMs;
|
|
61
|
+
if (currentCount >= this.config.maxRequests) {
|
|
62
|
+
const retryAfterMs = resetAt - now;
|
|
63
|
+
logger.debug('Rate limit exceeded', {
|
|
64
|
+
key: fullKey,
|
|
65
|
+
currentCount,
|
|
66
|
+
maxRequests: this.config.maxRequests,
|
|
67
|
+
retryAfterMs
|
|
68
|
+
});
|
|
69
|
+
return {
|
|
70
|
+
allowed: false,
|
|
71
|
+
remaining: 0,
|
|
72
|
+
resetAt,
|
|
73
|
+
retryAfterMs
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
// Record this request
|
|
77
|
+
record.timestamps.push(now);
|
|
78
|
+
return {
|
|
79
|
+
allowed: true,
|
|
80
|
+
remaining: remaining - 1,
|
|
81
|
+
resetAt
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Check without recording (peek)
|
|
86
|
+
*/
|
|
87
|
+
peek(key) {
|
|
88
|
+
const fullKey = this.config.keyPrefix ? `${this.config.keyPrefix}:${key}` : key;
|
|
89
|
+
const now = Date.now();
|
|
90
|
+
const windowStart = now - this.config.windowMs;
|
|
91
|
+
const record = this.records.get(fullKey);
|
|
92
|
+
if (!record) {
|
|
93
|
+
return {
|
|
94
|
+
allowed: true,
|
|
95
|
+
remaining: this.config.maxRequests,
|
|
96
|
+
resetAt: now + this.config.windowMs
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
const validTimestamps = record.timestamps.filter(ts => ts > windowStart);
|
|
100
|
+
const currentCount = validTimestamps.length;
|
|
101
|
+
const remaining = Math.max(0, this.config.maxRequests - currentCount);
|
|
102
|
+
const resetAt = validTimestamps.length > 0
|
|
103
|
+
? validTimestamps[0] + this.config.windowMs
|
|
104
|
+
: now + this.config.windowMs;
|
|
105
|
+
return {
|
|
106
|
+
allowed: currentCount < this.config.maxRequests,
|
|
107
|
+
remaining,
|
|
108
|
+
resetAt,
|
|
109
|
+
retryAfterMs: currentCount >= this.config.maxRequests ? resetAt - now : undefined
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Reset rate limit for a key
|
|
114
|
+
*/
|
|
115
|
+
reset(key) {
|
|
116
|
+
const fullKey = this.config.keyPrefix ? `${this.config.keyPrefix}:${key}` : key;
|
|
117
|
+
this.records.delete(fullKey);
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Reset all rate limits
|
|
121
|
+
*/
|
|
122
|
+
resetAll() {
|
|
123
|
+
this.records.clear();
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Get current configuration
|
|
127
|
+
*/
|
|
128
|
+
getConfig() {
|
|
129
|
+
return { ...this.config };
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Clean up old records
|
|
133
|
+
*/
|
|
134
|
+
cleanup() {
|
|
135
|
+
const now = Date.now();
|
|
136
|
+
const windowStart = now - this.config.windowMs;
|
|
137
|
+
for (const [key, record] of this.records.entries()) {
|
|
138
|
+
record.timestamps = record.timestamps.filter(ts => ts > windowStart);
|
|
139
|
+
if (record.timestamps.length === 0) {
|
|
140
|
+
this.records.delete(key);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Stop the cleanup interval
|
|
146
|
+
*/
|
|
147
|
+
destroy() {
|
|
148
|
+
if (this.cleanupInterval) {
|
|
149
|
+
clearInterval(this.cleanupInterval);
|
|
150
|
+
this.cleanupInterval = null;
|
|
151
|
+
}
|
|
152
|
+
this.records.clear();
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
exports.RateLimiter = RateLimiter;
|
|
156
|
+
/**
|
|
157
|
+
* Rate limiter manager for multiple rate limit types
|
|
158
|
+
*/
|
|
159
|
+
class RateLimiterManager {
|
|
160
|
+
limiters = new Map();
|
|
161
|
+
/**
|
|
162
|
+
* Get or create a rate limiter
|
|
163
|
+
*/
|
|
164
|
+
getLimiter(name, config) {
|
|
165
|
+
if (this.limiters.has(name)) {
|
|
166
|
+
return this.limiters.get(name);
|
|
167
|
+
}
|
|
168
|
+
const limiterConfig = config || exports.DEFAULT_LIMITS[name] || exports.DEFAULT_LIMITS.api;
|
|
169
|
+
const limiter = new RateLimiter({ ...limiterConfig, keyPrefix: name });
|
|
170
|
+
this.limiters.set(name, limiter);
|
|
171
|
+
return limiter;
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Check rate limit for a specific limiter type
|
|
175
|
+
*/
|
|
176
|
+
check(limiterName, key) {
|
|
177
|
+
const limiter = this.getLimiter(limiterName);
|
|
178
|
+
return limiter.check(key);
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Reset all limiters
|
|
182
|
+
*/
|
|
183
|
+
resetAll() {
|
|
184
|
+
for (const limiter of this.limiters.values()) {
|
|
185
|
+
limiter.resetAll();
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Destroy all limiters
|
|
190
|
+
*/
|
|
191
|
+
destroy() {
|
|
192
|
+
for (const limiter of this.limiters.values()) {
|
|
193
|
+
limiter.destroy();
|
|
194
|
+
}
|
|
195
|
+
this.limiters.clear();
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
exports.RateLimiterManager = RateLimiterManager;
|
|
199
|
+
// Singleton instance
|
|
200
|
+
let managerInstance = null;
|
|
201
|
+
function getRateLimiterManager() {
|
|
202
|
+
if (!managerInstance) {
|
|
203
|
+
managerInstance = new RateLimiterManager();
|
|
204
|
+
}
|
|
205
|
+
return managerInstance;
|
|
206
|
+
}
|
|
207
|
+
function resetRateLimiterManager() {
|
|
208
|
+
if (managerInstance) {
|
|
209
|
+
managerInstance.destroy();
|
|
210
|
+
managerInstance = null;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
// Convenience functions
|
|
214
|
+
function checkRateLimit(limiterName, key) {
|
|
215
|
+
return getRateLimiterManager().check(limiterName, key);
|
|
216
|
+
}
|
|
217
|
+
function checkApiRateLimit(key) {
|
|
218
|
+
return getRateLimiterManager().check('api', key);
|
|
219
|
+
}
|
|
220
|
+
function checkWriteRateLimit(key) {
|
|
221
|
+
return getRateLimiterManager().check('write', key);
|
|
222
|
+
}
|
|
223
|
+
function checkSearchRateLimit(key) {
|
|
224
|
+
return getRateLimiterManager().check('search', key);
|
|
225
|
+
}
|
|
226
|
+
//# sourceMappingURL=rate-limiter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rate-limiter.js","sourceRoot":"","sources":["../../src/guards/rate-limiter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Message Sanitizer - Neutralizes dangerous mentions and patterns
|
|
3
|
+
* Prevents accidental mass notifications (@all, @here, @channel)
|
|
4
|
+
*/
|
|
5
|
+
export interface SanitizeResult {
|
|
6
|
+
text: string;
|
|
7
|
+
modified: boolean;
|
|
8
|
+
neutralized: string[];
|
|
9
|
+
}
|
|
10
|
+
export declare class MessageSanitizer {
|
|
11
|
+
private blockMentions;
|
|
12
|
+
private blockedMentions;
|
|
13
|
+
constructor();
|
|
14
|
+
/**
|
|
15
|
+
* Sanitize message text
|
|
16
|
+
*/
|
|
17
|
+
sanitize(text: string): SanitizeResult;
|
|
18
|
+
/**
|
|
19
|
+
* Check if text contains dangerous patterns without modifying
|
|
20
|
+
*/
|
|
21
|
+
check(text: string): {
|
|
22
|
+
hasDangerousPatterns: boolean;
|
|
23
|
+
patterns: string[];
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Get current configuration
|
|
27
|
+
*/
|
|
28
|
+
getConfig(): {
|
|
29
|
+
blockMentions: boolean;
|
|
30
|
+
blockedMentions: string[];
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
export declare function getSanitizer(): MessageSanitizer;
|
|
34
|
+
export declare function resetSanitizer(): void;
|
|
35
|
+
//# sourceMappingURL=sanitizer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sanitizer.d.ts","sourceRoot":"","sources":["../../src/guards/sanitizer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,MAAM,WAAW,cAAc;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,OAAO,CAAC;IAClB,WAAW,EAAE,MAAM,EAAE,CAAC;CACzB;AAkBD,qBAAa,gBAAgB;IACzB,OAAO,CAAC,aAAa,CAAU;IAC/B,OAAO,CAAC,eAAe,CAAW;;IAQlC;;OAEG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc;IAmCtC;;OAEG;IACH,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG;QAAE,oBAAoB,EAAE,OAAO,CAAC;QAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;KAAE;IAuB1E;;OAEG;IACH,SAAS,IAAI;QAAE,aAAa,EAAE,OAAO,CAAC;QAAC,eAAe,EAAE,MAAM,EAAE,CAAA;KAAE;CAMrE;AAKD,wBAAgB,YAAY,IAAI,gBAAgB,CAK/C;AAED,wBAAgB,cAAc,IAAI,IAAI,CAErC"}
|