@reldens/server-utils 0.43.0 → 0.44.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/CLAUDE.md CHANGED
@@ -21,242 +21,74 @@ npm test
21
21
 
22
22
  ## Architecture
23
23
 
24
- ### Core Classes
24
+ See `.claude/package-architecture.md` for detailed information about:
25
+ - Design philosophy and independence principles
26
+ - Callback-based extensibility pattern
27
+ - Available callbacks (onError, onRequestSuccess, onRequestError, onEvent)
28
+ - Integration patterns
25
29
 
26
- **FileHandler** (`lib/file-handler.js`):
27
- - Singleton wrapper for Node.js fs and path modules
28
- - Used instead of direct require('fs') or require('path') throughout Reldens
29
- - Key file operations:
30
- - `exists(filePath)` - Check if file/directory exists
31
- - `readFile(filePath)` - Read file contents
32
- - `writeFile(filePath, content)` - Write file
33
- - `createFolder(folderPath)` - Create directory recursively
34
- - `remove(fullPath)` - Remove file/folder recursively
35
- - `copyFile(from, to)` - Copy file
36
- - `copyFolderSync(from, to)` - Copy folder recursively
37
- - `moveFile(from, to)` - Move/rename file
38
- - Path operations:
39
- - `joinPaths(...paths)` - Join path segments
40
- - `getFileName(filePath)` - Get file name (basename)
41
- - `getFolderName(filePath)` - Get directory name (dirname)
42
- - `getRelativePath(from, to)` - Calculate relative path
43
- - `normalizePath(filePath)` - Normalize path
44
- - `isAbsolutePath(filePath)` - Check if path is absolute
45
- - File inspection:
46
- - `isFile(filePath)` - Check if path is a file
47
- - `isFolder(dirPath)` - Check if path is a folder
48
- - `getFileSize(filePath)` - Get file size in bytes
49
- - `getFileStats(filePath)` - Get file stats
50
- - `getFilesInFolder(dirPath, extensions)` - List files with optional filtering
51
- - `fetchSubFoldersList(folder, options)` - Get subfolder list
52
- - JSON operations:
53
- - `fetchFileJson(filePath)` - Read and parse JSON file
54
- - `isValidJson(filePath)` - Validate JSON file
55
- - Security features:
56
- - `generateSecureFilename(originalName)` - Generate secure random filename
57
- - `validateFileType(filePath, type, allowedTypes, maxSize)` - Validate file
58
- - `detectFileType(filePath)` - Detect MIME type from magic numbers
59
- - `quarantineFile(filePath, reason)` - Move suspicious file to quarantine
60
- - `isValidPath(filePath)` - Validate path for security
61
- - `sanitizePath(filePath)` - Sanitize path string
62
- - Advanced operations:
63
- - `walkDirectory(dirPath, callback)` - Recursively process directory tree
64
- - `getDirectorySize(dirPath)` - Calculate total directory size
65
- - `emptyDirectory(dirPath)` - Remove all contents from directory
66
- - `compareFiles(file1, file2)` - Compare file contents
67
- - `appendToFile(filePath, content)` - Append to file
68
- - `prependToFile(filePath, content)` - Prepend to file
69
- - `replaceInFile(filePath, searchValue, replaceValue)` - Replace in file
70
- - `createReadStream(filePath, options)` - Create readable stream for file
71
- - `getFileModificationTime(filePath)` - Get file last modification time
72
- - All methods include built-in error handling, no need for try/catch
73
- - DO NOT use FileHandler.exists to validate other FileHandler methods
74
- - DO NOT enclose FileHandler methods in try/catch blocks
75
-
76
- **AppServerFactory** (`lib/app-server-factory.js`):
77
- - Creates Express app servers with modular security components
78
- - Supports HTTP, HTTPS, HTTP/2
79
- - Key features:
80
- - Virtual host management with SNI support
81
- - HTTP/2 CDN server integration
82
- - Reverse proxy with WebSocket support
83
- - Development mode detection and configuration
84
- - Custom error handling via onError callback
85
- - Security configurers (modular):
86
- - `DevelopmentModeDetector` - Auto-detect development environment
87
- - `ProtocolEnforcer` - HTTP/HTTPS protocol enforcement
88
- - `SecurityConfigurer` - Helmet integration and XSS protection
89
- - `CorsConfigurer` - CORS with dynamic origin validation
90
- - `RateLimitConfigurer` - Global and endpoint-specific rate limiting
91
- - `ReverseProxyConfigurer` - Domain-based reverse proxy
92
- - Configuration properties:
93
- - `onError` - Custom error handler callback for server errors
94
- - Methods:
95
- - `createAppServer(config)` - Create and configure server
96
- - `addDomain(domainConfig)` - Add virtual host domain
97
- - `addDevelopmentDomain(domain)` - Add development domain
98
- - `enableServeHome(app, callback)` - Enable homepage serving
99
- - `serveStatics(app, staticPath)` - Serve static files
100
- - `enableCSP(cspOptions)` - Enable Content Security Policy
101
- - `listen(port)` - Start server listening
102
- - `close()` - Gracefully close server
30
+ See `.claude/api-reference.md` for complete API documentation of all classes and methods.
103
31
 
104
- **Encryptor** (`lib/encryptor.js`):
105
- - Singleton for cryptographic operations
106
- - Password hashing:
107
- - `encryptPassword(password)` - Hash password with PBKDF2 (100k iterations, SHA-512)
108
- - `validatePassword(password, storedPassword)` - Validate password against hash
109
- - Data encryption:
110
- - `encryptData(data, key)` - Encrypt data with AES-256-GCM
111
- - `decryptData(encryptedData, key)` - Decrypt AES-256-GCM data
112
- - `generateSecretKey()` - Generate 256-bit secret key
113
- - Token generation:
114
- - `generateSecureToken(length)` - Generate cryptographically secure token
115
- - `generateTOTP(secret, timeStep)` - Generate time-based OTP
116
- - Hashing and verification:
117
- - `hashData(data, algorithm)` - Hash with SHA-256, SHA-512, or MD5
118
- - `generateHMAC(data, secret, algorithm)` - Generate HMAC signature
119
- - `verifyHMAC(data, secret, signature, algorithm)` - Verify HMAC signature
120
- - `constantTimeCompare(a, b)` - Constant-time string comparison
32
+ ## Core Classes Summary
121
33
 
122
- **UploaderFactory** (`lib/uploader-factory.js`):
123
- - File upload handling with Multer
124
- - Multi-level security validation:
125
- - Filename security validation
126
- - MIME type validation
127
- - File extension validation
128
- - File size validation
129
- - Content validation using magic numbers
130
- - Dangerous extension filtering
131
- - Features:
132
- - Multiple file upload support with field mapping
133
- - Secure filename generation option
134
- - Automatic cleanup on validation failure
135
- - Custom error response handling
136
- - Per-field destination mapping
137
- - Methods:
138
- - `createUploader(fields, buckets, allowedFileTypes)` - Create upload middleware
139
- - `validateFilenameSecurity(filename)` - Validate filename
140
- - `validateFile(file, allowedType, callback)` - Validate during upload
141
- - `validateFileContents(file, allowedType)` - Validate after upload
142
- - `convertToRegex(key)` - Convert MIME type patterns to regex
34
+ **FileHandler** - Singleton wrapper for Node.js fs and path modules. Used instead of direct require('fs') or require('path') throughout Reldens.
143
35
 
144
- **Http2CdnServer** (`lib/http2-cdn-server.js`):
145
- - HTTP/2 secure server for CDN-like static file serving
146
- - Features:
147
- - Optimized for CSS, JavaScript, images, and fonts
148
- - Dynamic CORS origin validation with regex pattern support
149
- - Configurable cache headers per file extension
150
- - Comprehensive MIME type detection
151
- - HTTP/1.1 fallback support
152
- - Security headers (X-Content-Type-Options, X-Frame-Options, Vary)
153
- - Query string stripping for cache optimization
154
- - Comprehensive error handling (server, TLS, session, stream errors)
155
- - Custom error handler callback support
156
- - Configuration properties:
157
- - `onError` - Custom error handler callback for server errors
158
- - Methods:
159
- - `create()` - Create HTTP/2 secure server
160
- - `listen()` - Start listening on configured port
161
- - `close()` - Gracefully close server
162
- - `handleStream(stream, headers)` - Handle HTTP/2 stream
163
- - `handleHttp1Request(req, res)` - Handle HTTP/1.1 fallback requests
164
- - `resolveFilePath(requestPath)` - Resolve file path from request
165
- - `setupEventHandlers()` - Configure server error event handlers
36
+ **AppServerFactory** - Creates Express app servers with modular security components. Supports HTTP, HTTPS, HTTP/2, virtual hosts, CDN integration, reverse proxy, and callback-based logging.
166
37
 
167
- ### Utility Classes
38
+ **Encryptor** - Singleton for cryptographic operations including password hashing, data encryption, token generation, and HMAC verification.
168
39
 
169
- **ServerErrorHandler** (`lib/server-error-handler.js`):
170
- - Centralized error handling for all server components
171
- - Static class with standardized error handling interface
172
- - Methods:
173
- - `handleError(onErrorCallback, instanceName, instance, key, error, context)` - Handle and delegate errors
174
- - Used by Http2CdnServer, AppServerFactory, and ReverseProxyConfigurer
175
- - Supports custom error callbacks for application-specific error processing
176
- - Provides structured error context with instance details and metadata
40
+ **UploaderFactory** - File upload handling with Multer and multi-level security validation.
177
41
 
178
- **ServerDefaultConfigurations** (`lib/server-default-configurations.js`):
179
- - Static class providing default configurations
180
- - `mimeTypes` - Comprehensive MIME type mappings for common file extensions
181
- - `cacheConfig` - Default cache max-age settings (1 year for CSS/JS/fonts, 30 days for images)
42
+ **Http2CdnServer** - HTTP/2 secure server for CDN-like static file serving with CORS, cache headers, and callback-based logging.
182
43
 
183
- **ServerFactoryUtils** (`lib/server-factory-utils.js`):
184
- - Static utility methods for server operations
185
- - `getCacheConfigForPath(path, cacheConfig)` - Get cache config for file path
186
- - `validateOrigin(origin, corsOrigins, corsAllowAll)` - Validate CORS origin (supports strings and RegExp)
187
- - `stripQueryString(url)` - Remove query string from URL
44
+ ## Utility Classes Summary
188
45
 
189
- **ServerHeaders** (`lib/server-headers.js`):
190
- - Centralized header management
191
- - HTTP/2 headers configuration
192
- - Express security headers
193
- - Cache control headers
194
- - Proxy forwarding headers
195
- - `buildCacheControlHeader(maxAge)` - Build cache control header string
46
+ **RequestLogger** - Express middleware for request logging that invokes callbacks based on status codes.
196
47
 
197
- ### Security Configurers (in `lib/app-server-factory/`)
48
+ **EventDispatcher** - Static utility for dispatching lifecycle events with structured event data.
198
49
 
199
- **DevelopmentModeDetector** (`development-mode-detector.js`):
200
- - Auto-detects development environment
201
- - Checks NODE_ENV, domain patterns, and configured domains
202
- - Built-in patterns: localhost, 127.0.0.1, .local, .test, .dev, .staging, etc.
203
- - `detect(config)` - Detect if in development mode
204
- - `matchesPattern(domain)` - Check if domain matches development pattern
50
+ **ServerErrorHandler** - Centralized error handling with structured error context.
205
51
 
206
- **ProtocolEnforcer** (`protocol-enforcer.js`):
207
- - Enforces HTTP/HTTPS protocol consistency
208
- - Development mode awareness
209
- - Automatic redirects when protocol doesn't match configuration
210
- - `setup(app, config)` - Setup protocol enforcement middleware
52
+ **ServerDefaultConfigurations** - Static class providing MIME types and cache configurations.
211
53
 
212
- **SecurityConfigurer** (`security-configurer.js`):
213
- - Helmet integration with CSP management
214
- - XSS protection with request body sanitization
215
- - Development-friendly CSP configuration
216
- - Supports CSP directive merging or override
217
- - `setupHelmet(app, config)` - Setup Helmet middleware
218
- - `setupXssProtection(app, config)` - Setup XSS protection
219
- - `enableCSP(app, cspOptions)` - Enable Content Security Policy
220
- - `addExternalDomainsToCsp(directives, externalDomains)` - Add external domains to CSP
54
+ **ServerFactoryUtils** - Static utility methods for cache config, CORS validation, and URL manipulation.
221
55
 
222
- **CorsConfigurer** (`cors-configurer.js`):
223
- - Dynamic CORS origin validation
224
- - Development domain support with automatic port variations
225
- - Credential support configuration
226
- - `setup(app, config)` - Setup CORS middleware
227
- - `extractDevelopmentOrigins(domainMapping)` - Extract development origins
228
- - `normalizeHost(originOrHost)` - Normalize host string
56
+ **ServerHeaders** - Centralized header management for HTTP/2, security, cache, and proxy headers.
229
57
 
230
- **RateLimitConfigurer** (`rate-limit-configurer.js`):
231
- - Global and endpoint-specific rate limiting
232
- - Development mode multiplier for lenient limits
233
- - IP-based key generation option
234
- - `setup(app, config)` - Setup global rate limiting
235
- - `createHomeLimiter()` - Create homepage-specific limiter
58
+ ## Security Configurers Summary
236
59
 
237
- **ReverseProxyConfigurer** (`reverse-proxy-configurer.js`):
238
- - Domain-based reverse proxy routing
239
- - WebSocket support
240
- - SSL termination
241
- - Header preservation (X-Forwarded-For, X-Forwarded-Proto, X-Forwarded-Host)
242
- - Virtual host integration
243
- - Comprehensive error handling with proper HTTP status codes:
244
- - 502 Bad Gateway for ECONNREFUSED errors
245
- - 504 Gateway Timeout for ETIMEDOUT/ESOCKETTIMEDOUT errors
246
- - 500 Internal Server Error for other proxy errors
247
- - Custom error callback support via ServerErrorHandler
248
- - Methods:
249
- - `setup(app, config)` - Setup reverse proxy
250
- - `createProxyMiddleware(rule)` - Create proxy middleware for rule
251
- - `handleProxyError(err, req, res)` - Handle proxy errors with status codes
252
- - `validateProxyRule(rule)` - Validate proxy rule configuration
253
- - `extractHostname(req)` - Extract hostname from request
60
+ Located in `lib/app-server-factory/`:
61
+ - **DevelopmentModeDetector** - Auto-detect development environment
62
+ - **ProtocolEnforcer** - HTTP/HTTPS protocol enforcement
63
+ - **SecurityConfigurer** - Helmet integration and XSS protection
64
+ - **CorsConfigurer** - CORS with dynamic origin validation
65
+ - **RateLimitConfigurer** - Global and endpoint-specific rate limiting
66
+ - **ReverseProxyConfigurer** - Domain-based reverse proxy with WebSocket support
254
67
 
255
68
  ## Important Notes
256
69
 
70
+ ### FileHandler Usage
257
71
  - **ALWAYS use FileHandler** instead of Node.js fs/path modules
258
72
  - FileHandler methods have built-in error handling - no try/catch needed
259
73
  - DO NOT enclose FileHandler methods in try/catch blocks
260
74
  - DO NOT use FileHandler.exists to validate other FileHandler methods (e.g., before createFolder)
75
+
76
+ ### Callback System
77
+ - Package provides callback hooks (onError, onRequestSuccess, onRequestError, onEvent)
78
+ - Applications provide implementations via configuration
79
+ - Package does NOT import @reldens/utils Logger
80
+ - Applications wire callbacks to their own logging/monitoring systems
81
+
82
+ ### Server Configuration
261
83
  - AppServerFactory handles all Express server configuration
262
84
  - All server utilities support both HTTP and HTTPS
85
+ - Virtual hosts with SNI support for multiple domains
86
+ - HTTP/2 CDN server integration for static file serving
87
+ - Reverse proxy with WebSocket support
88
+
89
+ ### Security
90
+ - Multi-level validation for file uploads
91
+ - XSS protection with request body sanitization
92
+ - CSP management with Helmet integration
93
+ - CORS with dynamic origin validation (supports strings and RegExp)
94
+ - Rate limiting with development mode awareness
@@ -5,6 +5,7 @@
5
5
  */
6
6
 
7
7
  const cors = require('cors');
8
+ const { EventDispatcher } = require('../event-dispatcher');
8
9
 
9
10
  class CorsConfigurer
10
11
  {
@@ -18,6 +19,7 @@ class CorsConfigurer
18
19
  this.corsHeaders = ['Content-Type','Authorization'];
19
20
  this.developmentCorsOrigins = [];
20
21
  this.developmentPorts = [];
22
+ this.onEvent = null;
21
23
  }
22
24
 
23
25
  setup(app, config)
@@ -28,6 +30,7 @@ class CorsConfigurer
28
30
  this.corsMethods = config.corsMethods || this.corsMethods;
29
31
  this.corsHeaders = config.corsHeaders || this.corsHeaders;
30
32
  this.developmentPorts = config.developmentPorts || this.developmentPorts;
33
+ this.onEvent = config.onEvent || null;
31
34
  if(!this.useCors){
32
35
  return;
33
36
  }
@@ -58,6 +61,13 @@ class CorsConfigurer
58
61
  };
59
62
  }
60
63
  app.use(cors(corsOptions));
64
+ EventDispatcher.dispatch(
65
+ this.onEvent,
66
+ 'cors-configured',
67
+ 'corsConfigurer',
68
+ this,
69
+ {useCors: this.useCors, isDevelopmentMode: this.isDevelopmentMode, corsOrigin: this.corsOrigin}
70
+ );
61
71
  }
62
72
 
63
73
  extractDevelopmentOrigins(domainMapping)
@@ -4,6 +4,8 @@
4
4
  *
5
5
  */
6
6
 
7
+ const { EventDispatcher } = require('../event-dispatcher');
8
+
7
9
  class DevelopmentModeDetector
8
10
  {
9
11
 
@@ -27,10 +29,12 @@ class DevelopmentModeDetector
27
29
  ];
28
30
  this.developmentEnvironments = ['development', 'dev', 'test'];
29
31
  this.env = process?.env?.NODE_ENV || 'production';
32
+ this.onEvent = null;
30
33
  }
31
34
 
32
35
  detect(config = {})
33
36
  {
37
+ this.onEvent = config.onEvent || null;
34
38
  if(config.developmentPatterns){
35
39
  this.developmentPatterns = config.developmentPatterns;
36
40
  }
@@ -38,11 +42,25 @@ class DevelopmentModeDetector
38
42
  this.developmentEnvironments = config.developmentEnvironments;
39
43
  }
40
44
  if(this.developmentEnvironments.includes(this.env)){
45
+ EventDispatcher.dispatch(
46
+ this.onEvent,
47
+ 'development-mode-detected',
48
+ 'developmentModeDetector',
49
+ this,
50
+ {detectionMethod: 'environment', env: this.env}
51
+ );
41
52
  return true;
42
53
  }
43
54
  if(config.developmentDomains && 0 < config.developmentDomains.length){
44
55
  for(let domain of config.developmentDomains){
45
56
  if(this.matchesPattern(domain)){
57
+ EventDispatcher.dispatch(
58
+ this.onEvent,
59
+ 'development-mode-detected',
60
+ 'developmentModeDetector',
61
+ this,
62
+ {detectionMethod: 'developmentDomain', domain: domain}
63
+ );
46
64
  return true;
47
65
  }
48
66
  }
@@ -53,6 +71,13 @@ class DevelopmentModeDetector
53
71
  continue;
54
72
  }
55
73
  if(this.matchesPattern(domainConfig.hostname)){
74
+ EventDispatcher.dispatch(
75
+ this.onEvent,
76
+ 'development-mode-detected',
77
+ 'developmentModeDetector',
78
+ this,
79
+ {detectionMethod: 'domainPattern', hostname: domainConfig.hostname}
80
+ );
56
81
  return true;
57
82
  }
58
83
  }
@@ -4,6 +4,8 @@
4
4
  *
5
5
  */
6
6
 
7
+ const { EventDispatcher } = require('../event-dispatcher');
8
+
7
9
  class ProtocolEnforcer
8
10
  {
9
11
 
@@ -12,6 +14,7 @@ class ProtocolEnforcer
12
14
  this.isDevelopmentMode = false;
13
15
  this.useHttps = false;
14
16
  this.enforceProtocol = true;
17
+ this.onEvent = null;
15
18
  }
16
19
 
17
20
  setup(app, config)
@@ -19,6 +22,7 @@ class ProtocolEnforcer
19
22
  this.isDevelopmentMode = config.isDevelopmentMode || false;
20
23
  this.useHttps = config.useHttps || false;
21
24
  this.enforceProtocol = config.enforceProtocol !== false;
25
+ this.onEvent = config.onEvent || null;
22
26
  app.use((req, res, next) => {
23
27
  let forwardedProto = req.get('X-Forwarded-Proto');
24
28
  let protocol = (forwardedProto || req.protocol || '').toLowerCase();
@@ -41,6 +45,13 @@ class ProtocolEnforcer
41
45
  res.set('X-Forwarded-Proto', protocol);
42
46
  next();
43
47
  });
48
+ EventDispatcher.dispatch(
49
+ this.onEvent,
50
+ 'protocol-enforcement-enabled',
51
+ 'protocolEnforcer',
52
+ this,
53
+ {isDevelopmentMode: this.isDevelopmentMode, useHttps: this.useHttps, enforceProtocol: this.enforceProtocol}
54
+ );
44
55
  }
45
56
 
46
57
  }
@@ -5,6 +5,7 @@
5
5
  */
6
6
 
7
7
  const rateLimit = require('express-rate-limit');
8
+ const { EventDispatcher } = require('../event-dispatcher');
8
9
 
9
10
  class RateLimitConfigurer
10
11
  {
@@ -19,6 +20,7 @@ class RateLimitConfigurer
19
20
  this.applyKeyGenerator = false;
20
21
  this.tooManyRequestsMessage = 'Too many requests, please try again later.';
21
22
  this.rateLimit = rateLimit;
23
+ this.onEvent = null;
22
24
  }
23
25
 
24
26
  setup(app, config)
@@ -30,6 +32,7 @@ class RateLimitConfigurer
30
32
  this.developmentMultiplier = Number(config.developmentMultiplier || this.developmentMultiplier);
31
33
  this.applyKeyGenerator = config.applyKeyGenerator || false;
32
34
  this.tooManyRequestsMessage = config.tooManyRequestsMessage || this.tooManyRequestsMessage;
35
+ this.onEvent = config.onEvent || null;
33
36
  if(!this.globalRateLimit){
34
37
  return;
35
38
  }
@@ -49,6 +52,13 @@ class RateLimitConfigurer
49
52
  };
50
53
  }
51
54
  app.use(this.rateLimit(limiterParams));
55
+ EventDispatcher.dispatch(
56
+ this.onEvent,
57
+ 'rate-limiting-configured',
58
+ 'rateLimitConfigurer',
59
+ this,
60
+ {globalRateLimit: this.globalRateLimit, maxRequests: limiterParams.limit, windowMs: this.windowMs}
61
+ );
52
62
  }
53
63
 
54
64
  createHomeLimiter()
@@ -7,6 +7,7 @@
7
7
  const { createProxyMiddleware } = require('http-proxy-middleware');
8
8
  const { ServerHeaders } = require('../server-headers');
9
9
  const { ServerErrorHandler } = require('../server-error-handler');
10
+ const { EventDispatcher } = require('../event-dispatcher');
10
11
 
11
12
  class ReverseProxyConfigurer
12
13
  {
@@ -24,6 +25,7 @@ class ReverseProxyConfigurer
24
25
  };
25
26
  this.serverHeaders = new ServerHeaders();
26
27
  this.onError = null;
28
+ this.onEvent = null;
27
29
  }
28
30
 
29
31
  setup(app, config)
@@ -33,10 +35,18 @@ class ReverseProxyConfigurer
33
35
  this.reverseProxyRules = config.reverseProxyRules || [];
34
36
  this.reverseProxyOptions = config.reverseProxyOptions || this.reverseProxyOptions;
35
37
  this.onError = config.onError || null;
38
+ this.onEvent = config.onEvent || null;
36
39
  if(0 === this.reverseProxyRules.length){
37
40
  return;
38
41
  }
39
42
  this.applyRules(app);
43
+ EventDispatcher.dispatch(
44
+ this.onEvent,
45
+ 'reverse-proxy-configured',
46
+ 'reverseProxyConfigurer',
47
+ this,
48
+ {rulesCount: this.reverseProxyRules.length, useVirtualHosts: this.useVirtualHosts}
49
+ );
40
50
  }
41
51
 
42
52
  applyRules(app)
@@ -6,6 +6,7 @@
6
6
 
7
7
  const helmet = require('helmet');
8
8
  const sanitizeHtml = require('sanitize-html');
9
+ const { EventDispatcher } = require('../event-dispatcher');
9
10
 
10
11
  class SecurityConfigurer
11
12
  {
@@ -18,15 +19,24 @@ class SecurityConfigurer
18
19
  this.helmetConfig = false;
19
20
  this.helmetOptions = {};
20
21
  this.sanitizeOptions = {allowedTags: [], allowedAttributes: {}};
22
+ this.onEvent = null;
21
23
  }
22
24
 
23
25
  setupHelmet(app, config)
24
26
  {
25
27
  this.useHelmet = config.useHelmet !== false;
28
+ this.onEvent = config.onEvent || null;
26
29
  if(!this.useHelmet){
27
30
  return;
28
31
  }
29
32
  app.use(helmet(this.mapHelmetOptions(config)));
33
+ EventDispatcher.dispatch(
34
+ this.onEvent,
35
+ 'helmet-configured',
36
+ 'securityConfigurer',
37
+ this,
38
+ {useHelmet: this.useHelmet, isDevelopmentMode: this.isDevelopmentMode}
39
+ );
30
40
  }
31
41
 
32
42
  mapHelmetOptions(config)
@@ -131,6 +141,7 @@ class SecurityConfigurer
131
141
  {
132
142
  this.useXssProtection = config.useXssProtection !== false;
133
143
  this.sanitizeOptions = config.sanitizeOptions || this.sanitizeOptions;
144
+ this.onEvent = config.onEvent || null;
134
145
  if(!this.useXssProtection){
135
146
  return;
136
147
  }
@@ -143,6 +154,13 @@ class SecurityConfigurer
143
154
  }
144
155
  next();
145
156
  });
157
+ EventDispatcher.dispatch(
158
+ this.onEvent,
159
+ 'xss-protection-enabled',
160
+ 'securityConfigurer',
161
+ this,
162
+ {useXssProtection: this.useXssProtection}
163
+ );
146
164
  }
147
165
 
148
166
  sanitizeRequestBody(body)