mcp-wordpress 2.4.2 → 2.5.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/README.md +114 -48
- package/dist/ajv-patch.js +34 -0
- package/dist/cache/CacheInvalidation.d.ts +3 -1
- package/dist/cache/CacheInvalidation.d.ts.map +1 -1
- package/dist/cache/CacheInvalidation.js +10 -4
- package/dist/cache/CacheInvalidation.js.map +1 -1
- package/dist/cache/CacheManager.d.ts +3 -2
- package/dist/cache/CacheManager.d.ts.map +1 -1
- package/dist/cache/CacheManager.js +11 -3
- package/dist/cache/CacheManager.js.map +1 -1
- package/dist/cache/HttpCacheWrapper.d.ts +7 -6
- package/dist/cache/HttpCacheWrapper.d.ts.map +1 -1
- package/dist/cache/HttpCacheWrapper.js +8 -5
- package/dist/cache/HttpCacheWrapper.js.map +1 -1
- package/dist/cache/__tests__/HttpCacheWrapper.test.js +6 -5
- package/dist/cache/__tests__/HttpCacheWrapper.test.js.map +1 -1
- package/dist/cache/index.d.ts +3 -3
- package/dist/cache/index.d.ts.map +1 -1
- package/dist/cache/index.js +1 -1
- package/dist/cache/index.js.map +1 -1
- package/dist/client/CachedWordPressClient.d.ts +23 -9
- package/dist/client/CachedWordPressClient.d.ts.map +1 -1
- package/dist/client/CachedWordPressClient.js +4 -1
- package/dist/client/CachedWordPressClient.js.map +1 -1
- package/dist/client/MockWordPressClient.d.ts +2 -1
- package/dist/client/MockWordPressClient.d.ts.map +1 -1
- package/dist/client/MockWordPressClient.js +3 -1
- package/dist/client/MockWordPressClient.js.map +1 -1
- package/dist/client/api.d.ts +17 -13
- package/dist/client/api.d.ts.map +1 -1
- package/dist/client/api.js +135 -30
- package/dist/client/api.js.map +1 -1
- package/dist/client/auth.d.ts.map +1 -1
- package/dist/client/auth.js +2 -3
- package/dist/client/auth.js.map +1 -1
- package/dist/client/managers/AuthenticationManager.d.ts +55 -2
- package/dist/client/managers/AuthenticationManager.d.ts.map +1 -1
- package/dist/client/managers/AuthenticationManager.js +269 -71
- package/dist/client/managers/AuthenticationManager.js.map +1 -1
- package/dist/client/managers/BaseManager.d.ts +3 -3
- package/dist/client/managers/BaseManager.d.ts.map +1 -1
- package/dist/client/managers/BaseManager.js +11 -5
- package/dist/client/managers/BaseManager.js.map +1 -1
- package/dist/client/managers/RequestManager.d.ts +2 -2
- package/dist/client/managers/RequestManager.d.ts.map +1 -1
- package/dist/client/managers/RequestManager.js +25 -12
- package/dist/client/managers/RequestManager.js.map +1 -1
- package/dist/config/Config.d.ts +155 -0
- package/dist/config/Config.d.ts.map +1 -0
- package/dist/config/Config.js +215 -0
- package/dist/config/Config.js.map +1 -0
- package/dist/config/ConfigurationSchema.d.ts +21 -21
- package/dist/config/ConfigurationSchema.d.ts.map +1 -1
- package/dist/config/ConfigurationSchema.js +19 -2
- package/dist/config/ConfigurationSchema.js.map +1 -1
- package/dist/config/ServerConfiguration.d.ts +2 -1
- package/dist/config/ServerConfiguration.d.ts.map +1 -1
- package/dist/config/ServerConfiguration.js +50 -41
- package/dist/config/ServerConfiguration.js.map +1 -1
- package/dist/docs/DocumentationGenerator.d.ts +9 -8
- package/dist/docs/DocumentationGenerator.d.ts.map +1 -1
- package/dist/docs/DocumentationGenerator.js +10 -7
- package/dist/docs/DocumentationGenerator.js.map +1 -1
- package/dist/docs/MarkdownFormatter.d.ts.map +1 -1
- package/dist/docs/MarkdownFormatter.js +3 -2
- package/dist/docs/MarkdownFormatter.js.map +1 -1
- package/dist/dxt-entry.cjs +81 -0
- package/dist/dxt-entry.js +15 -14
- package/dist/dxt-entry.js.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +37 -21
- package/dist/index.js.map +1 -1
- package/dist/performance/MetricsCollector.d.ts +13 -7
- package/dist/performance/MetricsCollector.d.ts.map +1 -1
- package/dist/performance/MetricsCollector.js +69 -27
- package/dist/performance/MetricsCollector.js.map +1 -1
- package/dist/performance/PerformanceAnalytics.d.ts +8 -2
- package/dist/performance/PerformanceAnalytics.d.ts.map +1 -1
- package/dist/performance/PerformanceAnalytics.js +17 -47
- package/dist/performance/PerformanceAnalytics.js.map +1 -1
- package/dist/performance/PerformanceMonitor.d.ts +2 -1
- package/dist/performance/PerformanceMonitor.d.ts.map +1 -1
- package/dist/performance/PerformanceMonitor.js +12 -13
- package/dist/performance/PerformanceMonitor.js.map +1 -1
- package/dist/performance/index.d.ts +2 -2
- package/dist/performance/index.d.ts.map +1 -1
- package/dist/security/AISecurityScanner.d.ts +1 -0
- package/dist/security/AISecurityScanner.d.ts.map +1 -1
- package/dist/security/AISecurityScanner.js +22 -12
- package/dist/security/AISecurityScanner.js.map +1 -1
- package/dist/security/AutomatedRemediation.d.ts +4 -3
- package/dist/security/AutomatedRemediation.d.ts.map +1 -1
- package/dist/security/AutomatedRemediation.js +46 -15
- package/dist/security/AutomatedRemediation.js.map +1 -1
- package/dist/security/InputValidator.d.ts +13 -9
- package/dist/security/InputValidator.d.ts.map +1 -1
- package/dist/security/InputValidator.js +4 -2
- package/dist/security/InputValidator.js.map +1 -1
- package/dist/security/SecurityCIPipeline.d.ts +1 -1
- package/dist/security/SecurityCIPipeline.d.ts.map +1 -1
- package/dist/security/SecurityCIPipeline.js +38 -29
- package/dist/security/SecurityCIPipeline.js.map +1 -1
- package/dist/security/SecurityConfig.d.ts +3 -3
- package/dist/security/SecurityConfig.d.ts.map +1 -1
- package/dist/security/SecurityConfig.js +13 -9
- package/dist/security/SecurityConfig.js.map +1 -1
- package/dist/security/SecurityConfigManager.d.ts +2 -2
- package/dist/security/SecurityConfigManager.d.ts.map +1 -1
- package/dist/security/SecurityConfigManager.js +20 -15
- package/dist/security/SecurityConfigManager.js.map +1 -1
- package/dist/security/SecurityMonitoring.d.ts +2 -2
- package/dist/security/SecurityMonitoring.d.ts.map +1 -1
- package/dist/security/SecurityMonitoring.js +19 -17
- package/dist/security/SecurityMonitoring.js.map +1 -1
- package/dist/security/SecurityReviewer.d.ts.map +1 -1
- package/dist/security/SecurityReviewer.js +10 -7
- package/dist/security/SecurityReviewer.js.map +1 -1
- package/dist/security/index.d.ts +24 -23
- package/dist/security/index.d.ts.map +1 -1
- package/dist/security/index.js +52 -23
- package/dist/security/index.js.map +1 -1
- package/dist/server/ConnectionTester.d.ts +12 -4
- package/dist/server/ConnectionTester.d.ts.map +1 -1
- package/dist/server/ConnectionTester.js +96 -22
- package/dist/server/ConnectionTester.js.map +1 -1
- package/dist/server/ToolRegistry.d.ts +2 -2
- package/dist/server/ToolRegistry.d.ts.map +1 -1
- package/dist/server/ToolRegistry.js +10 -5
- package/dist/server/ToolRegistry.js.map +1 -1
- package/dist/tools/BaseToolManager.d.ts +47 -11
- package/dist/tools/BaseToolManager.d.ts.map +1 -1
- package/dist/tools/BaseToolManager.js +168 -29
- package/dist/tools/BaseToolManager.js.map +1 -1
- package/dist/tools/auth.d.ts +16 -10
- package/dist/tools/auth.d.ts.map +1 -1
- package/dist/tools/auth.js +3 -2
- package/dist/tools/auth.js.map +1 -1
- package/dist/tools/cache.d.ts +30 -30
- package/dist/tools/cache.d.ts.map +1 -1
- package/dist/tools/cache.js +1 -6
- package/dist/tools/cache.js.map +1 -1
- package/dist/tools/comments.d.ts +20 -20
- package/dist/tools/comments.d.ts.map +1 -1
- package/dist/tools/comments.js +16 -9
- package/dist/tools/comments.js.map +1 -1
- package/dist/tools/media.d.ts +18 -16
- package/dist/tools/media.d.ts.map +1 -1
- package/dist/tools/media.js +16 -15
- package/dist/tools/media.js.map +1 -1
- package/dist/tools/pages.d.ts +19 -17
- package/dist/tools/pages.d.ts.map +1 -1
- package/dist/tools/pages.js +16 -12
- package/dist/tools/pages.js.map +1 -1
- package/dist/tools/performance.d.ts +11 -1
- package/dist/tools/performance.d.ts.map +1 -1
- package/dist/tools/performance.js +67 -34
- package/dist/tools/performance.js.map +1 -1
- package/dist/tools/posts/PostHandlers.d.ts +46 -0
- package/dist/tools/posts/PostHandlers.d.ts.map +1 -0
- package/dist/tools/posts/PostHandlers.js +400 -0
- package/dist/tools/posts/PostHandlers.js.map +1 -0
- package/dist/tools/posts/PostToolDefinitions.d.ts +37 -0
- package/dist/tools/posts/PostToolDefinitions.d.ts.map +1 -0
- package/dist/tools/posts/PostToolDefinitions.js +236 -0
- package/dist/tools/posts/PostToolDefinitions.js.map +1 -0
- package/dist/tools/posts/index.d.ts +138 -0
- package/dist/tools/posts/index.d.ts.map +1 -0
- package/dist/tools/posts/index.js +163 -0
- package/dist/tools/posts/index.js.map +1 -0
- package/dist/tools/posts.d.ts +10 -246
- package/dist/tools/posts.d.ts.map +1 -1
- package/dist/tools/posts.js +11 -723
- package/dist/tools/posts.js.map +1 -1
- package/dist/tools/site.d.ts +19 -18
- package/dist/tools/site.d.ts.map +1 -1
- package/dist/tools/site.js +14 -10
- package/dist/tools/site.js.map +1 -1
- package/dist/tools/taxonomies.d.ts +23 -24
- package/dist/tools/taxonomies.d.ts.map +1 -1
- package/dist/tools/taxonomies.js +24 -18
- package/dist/tools/taxonomies.js.map +1 -1
- package/dist/tools/users.d.ts +20 -15
- package/dist/tools/users.d.ts.map +1 -1
- package/dist/tools/users.js +12 -8
- package/dist/tools/users.js.map +1 -1
- package/dist/types/client.d.ts +48 -41
- package/dist/types/client.d.ts.map +1 -1
- package/dist/types/client.js +30 -5
- package/dist/types/client.js.map +1 -1
- package/dist/types/enhanced.d.ts +237 -0
- package/dist/types/enhanced.d.ts.map +1 -0
- package/dist/types/enhanced.js +49 -0
- package/dist/types/enhanced.js.map +1 -0
- package/dist/types/index.d.ts +15 -12
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +2 -0
- package/dist/types/index.js.map +1 -1
- package/dist/types/mcp.d.ts +12 -12
- package/dist/types/mcp.d.ts.map +1 -1
- package/dist/types/requests.d.ts +322 -0
- package/dist/types/requests.d.ts.map +1 -0
- package/dist/types/requests.js +8 -0
- package/dist/types/requests.js.map +1 -0
- package/dist/types/tools.d.ts +506 -0
- package/dist/types/tools.d.ts.map +1 -0
- package/dist/types/tools.js +8 -0
- package/dist/types/tools.js.map +1 -0
- package/dist/types/wordpress.d.ts +43 -15
- package/dist/types/wordpress.d.ts.map +1 -1
- package/dist/types/wordpress.js +8 -1
- package/dist/types/wordpress.js.map +1 -1
- package/dist/utils/debug.d.ts +19 -11
- package/dist/utils/debug.d.ts.map +1 -1
- package/dist/utils/debug.js +46 -10
- package/dist/utils/debug.js.map +1 -1
- package/dist/utils/enhancedError.d.ts +8 -8
- package/dist/utils/enhancedError.d.ts.map +1 -1
- package/dist/utils/enhancedError.js.map +1 -1
- package/dist/utils/error.d.ts +2 -4
- package/dist/utils/error.d.ts.map +1 -1
- package/dist/utils/error.js +42 -5
- package/dist/utils/error.js.map +1 -1
- package/dist/utils/logger.d.ts +106 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +280 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/streaming.d.ts +9 -9
- package/dist/utils/streaming.d.ts.map +1 -1
- package/dist/utils/streaming.js +71 -52
- package/dist/utils/streaming.js.map +1 -1
- package/dist/utils/toolWrapper.d.ts +9 -7
- package/dist/utils/toolWrapper.d.ts.map +1 -1
- package/dist/utils/toolWrapper.js.map +1 -1
- package/dist/utils/validation/core.d.ts +21 -0
- package/dist/utils/validation/core.d.ts.map +1 -0
- package/dist/utils/validation/core.js +71 -0
- package/dist/utils/validation/core.js.map +1 -0
- package/dist/utils/validation/index.d.ts +25 -0
- package/dist/utils/validation/index.d.ts.map +1 -0
- package/dist/utils/validation/index.js +29 -0
- package/dist/utils/validation/index.js.map +1 -0
- package/dist/utils/validation/network.d.ts +19 -0
- package/dist/utils/validation/network.d.ts.map +1 -0
- package/dist/utils/validation/network.js +93 -0
- package/dist/utils/validation/network.js.map +1 -0
- package/dist/utils/validation/rateLimit.d.ts +21 -0
- package/dist/utils/validation/rateLimit.d.ts.map +1 -0
- package/dist/utils/validation/rateLimit.js +43 -0
- package/dist/utils/validation/rateLimit.js.map +1 -0
- package/dist/utils/validation/security.d.ts +29 -0
- package/dist/utils/validation/security.d.ts.map +1 -0
- package/dist/utils/validation/security.js +327 -0
- package/dist/utils/validation/security.js.map +1 -0
- package/dist/utils/validation/wordpress.d.ts +31 -0
- package/dist/utils/validation/wordpress.d.ts.map +1 -0
- package/dist/utils/validation/wordpress.js +146 -0
- package/dist/utils/validation/wordpress.js.map +1 -0
- package/dist/utils/validation.d.ts +13 -82
- package/dist/utils/validation.d.ts.map +1 -1
- package/dist/utils/validation.js +25 -343
- package/dist/utils/validation.js.map +1 -1
- package/docs/BADGE_UPDATES.md +132 -0
- package/docs/CI_CD_IMPROVEMENTS.md +191 -0
- package/docs/INCREMENTAL_COVERAGE.md +183 -0
- package/docs/api/README.md +3 -1
- package/docs/api/openapi.json +5 -1
- package/docs/api/summary.json +1 -1
- package/docs/api/tools/wp_create_post.md +12 -14
- package/docs/examples/claude-desktop-config.md +1 -1
- package/docs/examples/docker-production.md +100 -93
- package/docs/examples/multi-site-setup.md +5 -4
- package/docs/examples/single-site-setup.md +3 -4
- package/docs/examples/use-case-workflows.md +4 -5
- package/docs/integrations/claude-desktop.md +31 -31
- package/docs/integrations/cline.md +4 -4
- package/docs/integrations/vs-code.md +9 -8
- package/docs/user-guides/SMITHERY_SETUP.md +10 -10
- package/package.json +44 -25
- package/src/cache/CacheInvalidation.ts +12 -5
- package/src/cache/CacheManager.ts +18 -15
- package/src/cache/HttpCacheWrapper.ts +30 -59
- package/src/cache/__tests__/HttpCacheWrapper.test.ts +6 -5
- package/src/cache/index.ts +3 -14
- package/src/client/CachedWordPressClient.ts +32 -30
- package/src/client/MockWordPressClient.ts +4 -2
- package/src/client/api.ts +186 -64
- package/src/client/auth.ts +15 -40
- package/src/client/managers/AuthenticationManager.ts +337 -77
- package/src/client/managers/BaseManager.ts +18 -30
- package/src/client/managers/RequestManager.ts +39 -44
- package/src/config/Config.ts +308 -0
- package/src/config/ConfigurationSchema.ts +23 -2
- package/src/config/ServerConfiguration.ts +51 -47
- package/src/docs/DocumentationGenerator.ts +50 -39
- package/src/docs/MarkdownFormatter.ts +19 -29
- package/src/dxt-entry.cjs +26 -16
- package/src/dxt-entry.ts +17 -27
- package/src/index.ts +42 -28
- package/src/performance/MetricsCollector.ts +108 -86
- package/src/performance/PerformanceAnalytics.ts +69 -164
- package/src/performance/PerformanceMonitor.ts +32 -47
- package/src/performance/index.ts +2 -10
- package/src/security/AISecurityScanner.ts +22 -12
- package/src/security/AutomatedRemediation.ts +49 -18
- package/src/security/InputValidator.ts +9 -6
- package/src/security/SecurityCIPipeline.ts +53 -37
- package/src/security/SecurityConfig.ts +22 -22
- package/src/security/SecurityConfigManager.ts +23 -19
- package/src/security/SecurityMonitoring.ts +24 -21
- package/src/security/SecurityReviewer.ts +10 -7
- package/src/security/index.ts +64 -29
- package/src/server/ConnectionTester.ts +120 -31
- package/src/server/ToolRegistry.ts +31 -21
- package/src/tools/BaseToolManager.ts +286 -33
- package/src/tools/auth.ts +20 -8
- package/src/tools/cache.ts +5 -15
- package/src/tools/comments.ts +34 -48
- package/src/tools/media.ts +41 -53
- package/src/tools/pages.ts +32 -54
- package/src/tools/performance.ts +141 -176
- package/src/tools/posts/PostHandlers.ts +474 -0
- package/src/tools/posts/PostToolDefinitions.ts +250 -0
- package/src/tools/posts/index.ts +192 -0
- package/src/tools/posts.ts +24 -780
- package/src/tools/site.ts +34 -19
- package/src/tools/taxonomies.ts +41 -57
- package/src/tools/users.ts +28 -16
- package/src/types/client.ts +114 -138
- package/src/types/enhanced.ts +318 -0
- package/src/types/index.ts +51 -30
- package/src/types/mcp.ts +20 -42
- package/src/types/requests.ts +378 -0
- package/src/types/tools.ts +608 -0
- package/src/types/wordpress.ts +56 -34
- package/src/utils/debug.ts +77 -59
- package/src/utils/enhancedError.ts +8 -8
- package/src/utils/error.ts +53 -31
- package/src/utils/logger.ts +351 -0
- package/src/utils/streaming.ts +86 -68
- package/src/utils/toolWrapper.ts +10 -12
- package/src/utils/validation/core.ts +108 -0
- package/src/utils/validation/index.ts +36 -0
- package/src/utils/validation/network.ts +132 -0
- package/src/utils/validation/rateLimit.ts +54 -0
- package/src/utils/validation/security.ts +361 -0
- package/src/utils/validation/wordpress.ts +180 -0
- package/src/utils/validation.ts +47 -470
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rate Limiting Utilities
|
|
3
|
+
*
|
|
4
|
+
* Simple in-memory rate limiting for authentication and API requests.
|
|
5
|
+
* For production, consider using Redis or similar distributed cache.
|
|
6
|
+
*/
|
|
7
|
+
import { WordPressAPIError } from "../../types/client.js";
|
|
8
|
+
/**
|
|
9
|
+
* Rate limiting tracker (simple in-memory implementation)
|
|
10
|
+
* For production, use Redis or similar
|
|
11
|
+
*/
|
|
12
|
+
class RateLimiter {
|
|
13
|
+
maxAttempts;
|
|
14
|
+
windowMs;
|
|
15
|
+
attempts = new Map();
|
|
16
|
+
constructor(maxAttempts = 5, windowMs = 60000) {
|
|
17
|
+
this.maxAttempts = maxAttempts;
|
|
18
|
+
this.windowMs = windowMs;
|
|
19
|
+
}
|
|
20
|
+
check(identifier) {
|
|
21
|
+
const now = Date.now();
|
|
22
|
+
const record = this.attempts.get(identifier);
|
|
23
|
+
if (!record || record.resetTime < now) {
|
|
24
|
+
this.attempts.set(identifier, {
|
|
25
|
+
count: 1,
|
|
26
|
+
resetTime: now + this.windowMs,
|
|
27
|
+
});
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
if (record.count >= this.maxAttempts) {
|
|
31
|
+
const waitTime = Math.ceil((record.resetTime - now) / 1000);
|
|
32
|
+
throw new WordPressAPIError(`Rate limit exceeded. Please wait ${waitTime} seconds before trying again.`, 429, "RATE_LIMIT_EXCEEDED");
|
|
33
|
+
}
|
|
34
|
+
record.count++;
|
|
35
|
+
}
|
|
36
|
+
reset(identifier) {
|
|
37
|
+
this.attempts.delete(identifier);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
// Export a default rate limiter for authentication attempts
|
|
41
|
+
export const authRateLimiter = new RateLimiter(5, 300000); // 5 attempts per 5 minutes
|
|
42
|
+
export { RateLimiter };
|
|
43
|
+
//# sourceMappingURL=rateLimit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rateLimit.js","sourceRoot":"","sources":["../../../src/utils/validation/rateLimit.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAE1D;;;GAGG;AACH,MAAM,WAAW;IAIL;IACA;IAJF,QAAQ,GAAsD,IAAI,GAAG,EAAE,CAAC;IAEhF,YACU,cAAsB,CAAC,EACvB,WAAmB,KAAK;QADxB,gBAAW,GAAX,WAAW,CAAY;QACvB,aAAQ,GAAR,QAAQ,CAAgB;IAC/B,CAAC;IAEJ,KAAK,CAAC,UAAkB;QACtB,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QAE7C,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,SAAS,GAAG,GAAG,EAAE,CAAC;YACtC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,UAAU,EAAE;gBAC5B,KAAK,EAAE,CAAC;gBACR,SAAS,EAAE,GAAG,GAAG,IAAI,CAAC,QAAQ;aAC/B,CAAC,CAAC;YACH,OAAO;QACT,CAAC;QAED,IAAI,MAAM,CAAC,KAAK,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;YACrC,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,SAAS,GAAG,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC;YAC5D,MAAM,IAAI,iBAAiB,CACzB,oCAAoC,QAAQ,+BAA+B,EAC3E,GAAG,EACH,qBAAqB,CACtB,CAAC;QACJ,CAAC;QAED,MAAM,CAAC,KAAK,EAAE,CAAC;IACjB,CAAC;IAED,KAAK,CAAC,UAAkB;QACtB,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IACnC,CAAC;CACF;AAED,4DAA4D;AAC5D,MAAM,CAAC,MAAM,eAAe,GAAG,IAAI,WAAW,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,2BAA2B;AAEtF,OAAO,EAAE,WAAW,EAAE,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Security Validation Utilities
|
|
3
|
+
*
|
|
4
|
+
* Validation functions focused on security concerns including file path validation,
|
|
5
|
+
* file size limits, MIME type validation, and HTML sanitization.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Validates and sanitizes file paths to prevent directory traversal
|
|
9
|
+
*/
|
|
10
|
+
export declare function validateFilePath(userPath: string, allowedBasePath: string): string;
|
|
11
|
+
/**
|
|
12
|
+
* Validates file size
|
|
13
|
+
*/
|
|
14
|
+
export declare function validateFileSize(sizeInBytes: number, maxSizeInMB?: number): void;
|
|
15
|
+
/**
|
|
16
|
+
* Validates MIME types for file uploads
|
|
17
|
+
*/
|
|
18
|
+
export declare function validateMimeType(mimeType: string, allowedTypes: string[]): void;
|
|
19
|
+
/**
|
|
20
|
+
* Sanitizes HTML content to prevent XSS attacks using a whitelist-based approach
|
|
21
|
+
*
|
|
22
|
+
* This implementation satisfies GitHub Advanced Security requirements by:
|
|
23
|
+
* 1. Using character-by-character parsing instead of potentially vulnerable regex patterns
|
|
24
|
+
* 2. Implementing a strict whitelist of allowed elements and attributes
|
|
25
|
+
* 3. Properly handling all edge cases that bypass traditional regex sanitization
|
|
26
|
+
* 4. Providing complete protection against script injection, event handlers, and dangerous protocols
|
|
27
|
+
*/
|
|
28
|
+
export declare function sanitizeHtml(html: string): string;
|
|
29
|
+
//# sourceMappingURL=security.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"security.d.ts","sourceRoot":"","sources":["../../../src/utils/validation/security.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,GAAG,MAAM,CAWlF;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,MAAM,EAAE,WAAW,GAAE,MAAW,GAAG,IAAI,CAKpF;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,GAAG,IAAI,CAQ/E;AAED;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CA2HjD"}
|
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Security Validation Utilities
|
|
3
|
+
*
|
|
4
|
+
* Validation functions focused on security concerns including file path validation,
|
|
5
|
+
* file size limits, MIME type validation, and HTML sanitization.
|
|
6
|
+
*/
|
|
7
|
+
import * as path from "path";
|
|
8
|
+
import { WordPressAPIError } from "../../types/client.js";
|
|
9
|
+
/**
|
|
10
|
+
* Validates and sanitizes file paths to prevent directory traversal
|
|
11
|
+
*/
|
|
12
|
+
export function validateFilePath(userPath, allowedBasePath) {
|
|
13
|
+
// Normalize the path to remove ../ and other dangerous patterns
|
|
14
|
+
const normalizedPath = path.normalize(userPath);
|
|
15
|
+
const resolvedPath = path.resolve(allowedBasePath, normalizedPath);
|
|
16
|
+
// Ensure the resolved path is within the allowed directory
|
|
17
|
+
if (!resolvedPath.startsWith(path.resolve(allowedBasePath))) {
|
|
18
|
+
throw new WordPressAPIError("Invalid file path: access denied", 403, "PATH_TRAVERSAL_ATTEMPT");
|
|
19
|
+
}
|
|
20
|
+
return resolvedPath;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Validates file size
|
|
24
|
+
*/
|
|
25
|
+
export function validateFileSize(sizeInBytes, maxSizeInMB = 10) {
|
|
26
|
+
const maxSizeInBytes = maxSizeInMB * 1024 * 1024;
|
|
27
|
+
if (sizeInBytes > maxSizeInBytes) {
|
|
28
|
+
throw new WordPressAPIError(`File size exceeds maximum allowed size of ${maxSizeInMB}MB`, 413, "FILE_TOO_LARGE");
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Validates MIME types for file uploads
|
|
33
|
+
*/
|
|
34
|
+
export function validateMimeType(mimeType, allowedTypes) {
|
|
35
|
+
if (!allowedTypes.includes(mimeType)) {
|
|
36
|
+
throw new WordPressAPIError(`Invalid file type: ${mimeType}. Allowed types: ${allowedTypes.join(", ")}`, 415, "UNSUPPORTED_MEDIA_TYPE");
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Sanitizes HTML content to prevent XSS attacks using a whitelist-based approach
|
|
41
|
+
*
|
|
42
|
+
* This implementation satisfies GitHub Advanced Security requirements by:
|
|
43
|
+
* 1. Using character-by-character parsing instead of potentially vulnerable regex patterns
|
|
44
|
+
* 2. Implementing a strict whitelist of allowed elements and attributes
|
|
45
|
+
* 3. Properly handling all edge cases that bypass traditional regex sanitization
|
|
46
|
+
* 4. Providing complete protection against script injection, event handlers, and dangerous protocols
|
|
47
|
+
*/
|
|
48
|
+
export function sanitizeHtml(html) {
|
|
49
|
+
if (!html || typeof html !== "string") {
|
|
50
|
+
return "";
|
|
51
|
+
}
|
|
52
|
+
// Whitelist of allowed HTML elements (safe for WordPress content)
|
|
53
|
+
const allowedElements = new Set([
|
|
54
|
+
"p",
|
|
55
|
+
"br",
|
|
56
|
+
"strong",
|
|
57
|
+
"b",
|
|
58
|
+
"em",
|
|
59
|
+
"i",
|
|
60
|
+
"u",
|
|
61
|
+
"span",
|
|
62
|
+
"div",
|
|
63
|
+
"h1",
|
|
64
|
+
"h2",
|
|
65
|
+
"h3",
|
|
66
|
+
"h4",
|
|
67
|
+
"h5",
|
|
68
|
+
"h6",
|
|
69
|
+
"ul",
|
|
70
|
+
"ol",
|
|
71
|
+
"li",
|
|
72
|
+
"dl",
|
|
73
|
+
"dt",
|
|
74
|
+
"dd",
|
|
75
|
+
"blockquote",
|
|
76
|
+
"pre",
|
|
77
|
+
"code",
|
|
78
|
+
"a",
|
|
79
|
+
"img",
|
|
80
|
+
"table",
|
|
81
|
+
"thead",
|
|
82
|
+
"tbody",
|
|
83
|
+
"tfoot",
|
|
84
|
+
"tr",
|
|
85
|
+
"td",
|
|
86
|
+
"th",
|
|
87
|
+
"hr",
|
|
88
|
+
]);
|
|
89
|
+
// Whitelist of allowed attributes per element
|
|
90
|
+
const allowedAttributes = {
|
|
91
|
+
a: new Set(["href", "title", "target"]),
|
|
92
|
+
img: new Set(["src", "alt", "title", "width", "height"]),
|
|
93
|
+
div: new Set(["class", "id"]),
|
|
94
|
+
span: new Set(["class", "id"]),
|
|
95
|
+
p: new Set(["class", "id"]),
|
|
96
|
+
h1: new Set(["class", "id"]),
|
|
97
|
+
h2: new Set(["class", "id"]),
|
|
98
|
+
h3: new Set(["class", "id"]),
|
|
99
|
+
h4: new Set(["class", "id"]),
|
|
100
|
+
h5: new Set(["class", "id"]),
|
|
101
|
+
h6: new Set(["class", "id"]),
|
|
102
|
+
table: new Set(["class", "id"]),
|
|
103
|
+
td: new Set(["class", "id", "colspan", "rowspan"]),
|
|
104
|
+
th: new Set(["class", "id", "colspan", "rowspan"]),
|
|
105
|
+
};
|
|
106
|
+
// Safe URL protocols
|
|
107
|
+
const safeProtocols = new Set(["http:", "https:", "mailto:", "tel:", "ftp:"]);
|
|
108
|
+
let result = "";
|
|
109
|
+
let i = 0;
|
|
110
|
+
while (i < html.length) {
|
|
111
|
+
if (html[i] === "<") {
|
|
112
|
+
// Found a potential HTML tag
|
|
113
|
+
const tagMatch = parseHtmlTag(html, i);
|
|
114
|
+
if (tagMatch) {
|
|
115
|
+
const { tagName, attributes, isClosing, isSelfClosing, endIndex } = tagMatch;
|
|
116
|
+
// Check if this is an allowed element
|
|
117
|
+
if (allowedElements.has(tagName.toLowerCase())) {
|
|
118
|
+
// Build sanitized tag
|
|
119
|
+
let sanitizedTag = "<";
|
|
120
|
+
if (isClosing)
|
|
121
|
+
sanitizedTag += "/";
|
|
122
|
+
sanitizedTag += tagName.toLowerCase();
|
|
123
|
+
// Process attributes if not a closing tag
|
|
124
|
+
if (!isClosing && attributes.length > 0) {
|
|
125
|
+
const allowedAttrs = allowedAttributes[tagName.toLowerCase()] || new Set();
|
|
126
|
+
for (const attr of attributes) {
|
|
127
|
+
if (allowedAttrs.has(attr.name.toLowerCase())) {
|
|
128
|
+
// Additional validation for URL attributes
|
|
129
|
+
if ((attr.name.toLowerCase() === "href" || attr.name.toLowerCase() === "src") && attr.value) {
|
|
130
|
+
if (isValidUrl(attr.value, safeProtocols)) {
|
|
131
|
+
sanitizedTag += ` ${attr.name.toLowerCase()}="${escapeAttributeValue(attr.value)}"`;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
else if (attr.value !== null) {
|
|
135
|
+
// Other safe attributes
|
|
136
|
+
sanitizedTag += ` ${attr.name.toLowerCase()}="${escapeAttributeValue(attr.value)}"`;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
if (isSelfClosing)
|
|
142
|
+
sanitizedTag += " /";
|
|
143
|
+
sanitizedTag += ">";
|
|
144
|
+
result += sanitizedTag;
|
|
145
|
+
}
|
|
146
|
+
// If element not allowed, skip the entire tag
|
|
147
|
+
i = endIndex;
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
150
|
+
// Not a valid tag, treat as text
|
|
151
|
+
result += escapeHtmlChar(html[i]);
|
|
152
|
+
i++;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
else {
|
|
156
|
+
// Regular text content
|
|
157
|
+
result += escapeHtmlChar(html[i]);
|
|
158
|
+
i++;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
// Final cleanup: normalize whitespace
|
|
162
|
+
return result.replace(/\s+/g, " ").trim();
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Parses an HTML tag starting at the given position
|
|
166
|
+
* Returns tag information or null if not a valid tag
|
|
167
|
+
*/
|
|
168
|
+
function parseHtmlTag(html, startIndex) {
|
|
169
|
+
if (html[startIndex] !== "<")
|
|
170
|
+
return null;
|
|
171
|
+
let i = startIndex + 1;
|
|
172
|
+
let isClosing = false;
|
|
173
|
+
// Skip whitespace
|
|
174
|
+
while (i < html.length && /\s/.test(html[i]))
|
|
175
|
+
i++;
|
|
176
|
+
// Check for closing tag
|
|
177
|
+
if (i < html.length && html[i] === "/") {
|
|
178
|
+
isClosing = true;
|
|
179
|
+
i++;
|
|
180
|
+
while (i < html.length && /\s/.test(html[i]))
|
|
181
|
+
i++;
|
|
182
|
+
}
|
|
183
|
+
// Parse tag name
|
|
184
|
+
const tagNameStart = i;
|
|
185
|
+
while (i < html.length && /[a-zA-Z0-9]/.test(html[i]))
|
|
186
|
+
i++;
|
|
187
|
+
if (i === tagNameStart)
|
|
188
|
+
return null; // No valid tag name
|
|
189
|
+
const tagName = html.substring(tagNameStart, i);
|
|
190
|
+
const attributes = [];
|
|
191
|
+
// Parse attributes (only for opening tags)
|
|
192
|
+
if (!isClosing) {
|
|
193
|
+
while (i < html.length && html[i] !== ">") {
|
|
194
|
+
// Skip whitespace
|
|
195
|
+
while (i < html.length && /\s/.test(html[i]))
|
|
196
|
+
i++;
|
|
197
|
+
if (i >= html.length || html[i] === ">")
|
|
198
|
+
break;
|
|
199
|
+
// Check for self-closing
|
|
200
|
+
if (html[i] === "/") {
|
|
201
|
+
i++;
|
|
202
|
+
while (i < html.length && /\s/.test(html[i]))
|
|
203
|
+
i++;
|
|
204
|
+
if (i < html.length && html[i] === ">") {
|
|
205
|
+
return {
|
|
206
|
+
tagName,
|
|
207
|
+
attributes,
|
|
208
|
+
isClosing: false,
|
|
209
|
+
isSelfClosing: true,
|
|
210
|
+
endIndex: i + 1,
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
break;
|
|
214
|
+
}
|
|
215
|
+
// Parse attribute name
|
|
216
|
+
const attrNameStart = i;
|
|
217
|
+
while (i < html.length && /[a-zA-Z0-9-_]/.test(html[i]))
|
|
218
|
+
i++;
|
|
219
|
+
if (i === attrNameStart)
|
|
220
|
+
break; // Invalid attribute name
|
|
221
|
+
const attrName = html.substring(attrNameStart, i);
|
|
222
|
+
let attrValue = null;
|
|
223
|
+
// Skip whitespace
|
|
224
|
+
while (i < html.length && /\s/.test(html[i]))
|
|
225
|
+
i++;
|
|
226
|
+
// Check for attribute value
|
|
227
|
+
if (i < html.length && html[i] === "=") {
|
|
228
|
+
i++;
|
|
229
|
+
while (i < html.length && /\s/.test(html[i]))
|
|
230
|
+
i++;
|
|
231
|
+
if (i < html.length) {
|
|
232
|
+
if (html[i] === '"' || html[i] === "'") {
|
|
233
|
+
// Quoted value
|
|
234
|
+
const quote = html[i];
|
|
235
|
+
i++;
|
|
236
|
+
const valueStart = i;
|
|
237
|
+
while (i < html.length && html[i] !== quote)
|
|
238
|
+
i++;
|
|
239
|
+
if (i < html.length) {
|
|
240
|
+
attrValue = html.substring(valueStart, i);
|
|
241
|
+
i++; // Skip closing quote
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
else {
|
|
245
|
+
// Unquoted value
|
|
246
|
+
const valueStart = i;
|
|
247
|
+
while (i < html.length && !/[\s>]/.test(html[i]))
|
|
248
|
+
i++;
|
|
249
|
+
attrValue = html.substring(valueStart, i);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
attributes.push({ name: attrName, value: attrValue });
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
// Find closing >
|
|
257
|
+
while (i < html.length && html[i] !== ">")
|
|
258
|
+
i++;
|
|
259
|
+
if (i >= html.length)
|
|
260
|
+
return null; // Unclosed tag
|
|
261
|
+
return {
|
|
262
|
+
tagName,
|
|
263
|
+
attributes,
|
|
264
|
+
isClosing,
|
|
265
|
+
isSelfClosing: false,
|
|
266
|
+
endIndex: i + 1,
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Validates URL safety
|
|
271
|
+
*/
|
|
272
|
+
function isValidUrl(url, safeProtocols) {
|
|
273
|
+
if (!url || typeof url !== "string")
|
|
274
|
+
return false;
|
|
275
|
+
// Remove whitespace
|
|
276
|
+
url = url.trim();
|
|
277
|
+
if (!url)
|
|
278
|
+
return false;
|
|
279
|
+
// Allow relative URLs
|
|
280
|
+
if (url.startsWith("/") || url.startsWith("./") || url.startsWith("../")) {
|
|
281
|
+
return true;
|
|
282
|
+
}
|
|
283
|
+
// Allow fragment URLs
|
|
284
|
+
if (url.startsWith("#")) {
|
|
285
|
+
return true;
|
|
286
|
+
}
|
|
287
|
+
// Check protocol
|
|
288
|
+
const protocolMatch = url.match(/^([a-z][a-z0-9+.-]*:)/i);
|
|
289
|
+
if (protocolMatch) {
|
|
290
|
+
return safeProtocols.has(protocolMatch[1].toLowerCase());
|
|
291
|
+
}
|
|
292
|
+
// No protocol specified, treat as relative
|
|
293
|
+
return true;
|
|
294
|
+
}
|
|
295
|
+
/**
|
|
296
|
+
* Escapes attribute values
|
|
297
|
+
*/
|
|
298
|
+
function escapeAttributeValue(value) {
|
|
299
|
+
if (!value)
|
|
300
|
+
return "";
|
|
301
|
+
return value
|
|
302
|
+
.replace(/&/g, "&")
|
|
303
|
+
.replace(/"/g, """)
|
|
304
|
+
.replace(/'/g, "'")
|
|
305
|
+
.replace(/</g, "<")
|
|
306
|
+
.replace(/>/g, ">");
|
|
307
|
+
}
|
|
308
|
+
/**
|
|
309
|
+
* Escapes individual HTML characters
|
|
310
|
+
*/
|
|
311
|
+
function escapeHtmlChar(char) {
|
|
312
|
+
switch (char) {
|
|
313
|
+
case "&":
|
|
314
|
+
return "&";
|
|
315
|
+
case "<":
|
|
316
|
+
return "<";
|
|
317
|
+
case ">":
|
|
318
|
+
return ">";
|
|
319
|
+
case '"':
|
|
320
|
+
return """;
|
|
321
|
+
case "'":
|
|
322
|
+
return "'";
|
|
323
|
+
default:
|
|
324
|
+
return char;
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
//# sourceMappingURL=security.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"security.js","sourceRoot":"","sources":["../../../src/utils/validation/security.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WordPress-Specific Validation Utilities
|
|
3
|
+
*
|
|
4
|
+
* Validation functions specific to WordPress data structures including post parameters,
|
|
5
|
+
* pagination, search queries, and status validation.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Validates WordPress post status values
|
|
9
|
+
*/
|
|
10
|
+
export declare function validatePostStatus(status: string): string;
|
|
11
|
+
/**
|
|
12
|
+
* Validates and sanitizes search queries
|
|
13
|
+
*/
|
|
14
|
+
export declare function validateSearchQuery(query: string): string;
|
|
15
|
+
/**
|
|
16
|
+
* Validates pagination parameters as a set
|
|
17
|
+
*/
|
|
18
|
+
export declare function validatePaginationParams(params: {
|
|
19
|
+
page?: unknown;
|
|
20
|
+
per_page?: unknown;
|
|
21
|
+
offset?: unknown;
|
|
22
|
+
}): {
|
|
23
|
+
page?: number;
|
|
24
|
+
per_page?: number;
|
|
25
|
+
offset?: number;
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* Validates complex post creation parameters
|
|
29
|
+
*/
|
|
30
|
+
export declare function validatePostParams(params: unknown): Record<string, unknown>;
|
|
31
|
+
//# sourceMappingURL=wordpress.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wordpress.d.ts","sourceRoot":"","sources":["../../../src/utils/validation/wordpress.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAOH;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAMzD;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAgBzD;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE;IAAE,IAAI,CAAC,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG;IAC1G,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAiDA;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CA0E3E"}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WordPress-Specific Validation Utilities
|
|
3
|
+
*
|
|
4
|
+
* Validation functions specific to WordPress data structures including post parameters,
|
|
5
|
+
* pagination, search queries, and status validation.
|
|
6
|
+
*/
|
|
7
|
+
import { WordPressAPIError } from "../../types/client.js";
|
|
8
|
+
import { validateId } from "./core.js";
|
|
9
|
+
import { validateString, validateArray } from "./core.js";
|
|
10
|
+
import { sanitizeHtml } from "./security.js";
|
|
11
|
+
/**
|
|
12
|
+
* Validates WordPress post status values
|
|
13
|
+
*/
|
|
14
|
+
export function validatePostStatus(status) {
|
|
15
|
+
const validStatuses = ["publish", "draft", "pending", "private", "future", "auto-draft", "trash"];
|
|
16
|
+
if (!validStatuses.includes(status)) {
|
|
17
|
+
throw new WordPressAPIError(`Invalid status: must be one of ${validStatuses.join(", ")}`, 400, "INVALID_PARAMETER");
|
|
18
|
+
}
|
|
19
|
+
return status;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Validates and sanitizes search queries
|
|
23
|
+
*/
|
|
24
|
+
export function validateSearchQuery(query) {
|
|
25
|
+
// Remove potentially dangerous characters while preserving search functionality
|
|
26
|
+
let sanitized = query.trim();
|
|
27
|
+
// Limit length to prevent DoS
|
|
28
|
+
if (sanitized.length > 200) {
|
|
29
|
+
sanitized = sanitized.substring(0, 200);
|
|
30
|
+
}
|
|
31
|
+
// Remove SQL-like patterns (basic protection)
|
|
32
|
+
sanitized = sanitized.replace(/(\b(union|select|insert|update|delete|drop|create)\b)/gi, "");
|
|
33
|
+
// Remove special characters that might be used for injection
|
|
34
|
+
sanitized = sanitized.replace(/[<>'"`;\\]/g, "");
|
|
35
|
+
return sanitized;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Validates pagination parameters as a set
|
|
39
|
+
*/
|
|
40
|
+
export function validatePaginationParams(params) {
|
|
41
|
+
const validated = {};
|
|
42
|
+
// Validate page
|
|
43
|
+
if (params.page !== undefined) {
|
|
44
|
+
const page = parseInt(String(params.page), 10);
|
|
45
|
+
if (isNaN(page) || page < 1) {
|
|
46
|
+
throw new WordPressAPIError("Page must be a positive integer", 400, "INVALID_PARAMETER");
|
|
47
|
+
}
|
|
48
|
+
if (page > 10000) {
|
|
49
|
+
throw new WordPressAPIError("Page number too high (max 10000)", 400, "INVALID_PARAMETER");
|
|
50
|
+
}
|
|
51
|
+
validated.page = page;
|
|
52
|
+
}
|
|
53
|
+
// Validate per_page
|
|
54
|
+
if (params.per_page !== undefined) {
|
|
55
|
+
const perPage = parseInt(String(params.per_page), 10);
|
|
56
|
+
if (isNaN(perPage) || perPage < 1) {
|
|
57
|
+
throw new WordPressAPIError("Per page must be a positive integer", 400, "INVALID_PARAMETER");
|
|
58
|
+
}
|
|
59
|
+
if (perPage > 100) {
|
|
60
|
+
throw new WordPressAPIError(`Per page exceeds maximum allowed (100), got ${perPage}`, 400, "INVALID_PARAMETER");
|
|
61
|
+
}
|
|
62
|
+
validated.per_page = perPage;
|
|
63
|
+
}
|
|
64
|
+
// Validate offset
|
|
65
|
+
if (params.offset !== undefined) {
|
|
66
|
+
const offset = parseInt(String(params.offset), 10);
|
|
67
|
+
if (isNaN(offset) || offset < 0) {
|
|
68
|
+
throw new WordPressAPIError("Offset must be a non-negative integer", 400, "INVALID_PARAMETER");
|
|
69
|
+
}
|
|
70
|
+
if (offset > 1000000) {
|
|
71
|
+
throw new WordPressAPIError("Offset too large (max 1000000)", 400, "INVALID_PARAMETER");
|
|
72
|
+
}
|
|
73
|
+
validated.offset = offset;
|
|
74
|
+
}
|
|
75
|
+
// Check for conflicting parameters
|
|
76
|
+
if (validated.page && validated.offset) {
|
|
77
|
+
throw new WordPressAPIError("Cannot use both 'page' and 'offset' parameters together", 400, "CONFLICTING_PARAMETERS");
|
|
78
|
+
}
|
|
79
|
+
return validated;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Validates complex post creation parameters
|
|
83
|
+
*/
|
|
84
|
+
export function validatePostParams(params) {
|
|
85
|
+
const validated = {};
|
|
86
|
+
// Type guard to ensure params is an object
|
|
87
|
+
if (typeof params !== "object" || params === null || Array.isArray(params)) {
|
|
88
|
+
throw new WordPressAPIError("Post parameters must be an object", 400, "INVALID_PARAMETER");
|
|
89
|
+
}
|
|
90
|
+
const typedParams = params;
|
|
91
|
+
// Title validation
|
|
92
|
+
if (!typedParams.title || typeof typedParams.title !== "string") {
|
|
93
|
+
throw new WordPressAPIError("Post title is required and must be a string", 400, "INVALID_PARAMETER");
|
|
94
|
+
}
|
|
95
|
+
validated.title = validateString(typedParams.title, "title", 1, 200);
|
|
96
|
+
// Content validation
|
|
97
|
+
if (typedParams.content !== undefined) {
|
|
98
|
+
validated.content = sanitizeHtml(String(typedParams.content));
|
|
99
|
+
}
|
|
100
|
+
// Status validation with context
|
|
101
|
+
if (typedParams.status) {
|
|
102
|
+
if (typeof typedParams.status !== "string") {
|
|
103
|
+
throw new WordPressAPIError("Status must be a string", 400, "INVALID_PARAMETER");
|
|
104
|
+
}
|
|
105
|
+
validated.status = validatePostStatus(typedParams.status);
|
|
106
|
+
// Future posts need a date
|
|
107
|
+
if (validated.status === "future" && !typedParams.date) {
|
|
108
|
+
throw new WordPressAPIError("Future posts require a 'date' parameter", 400, "MISSING_PARAMETER");
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
// Categories and tags validation
|
|
112
|
+
if (typedParams.categories) {
|
|
113
|
+
const categories = validateArray(typedParams.categories, "categories", 0, 50);
|
|
114
|
+
validated.categories = categories.map((id) => validateId(id, "category ID"));
|
|
115
|
+
}
|
|
116
|
+
if (typedParams.tags) {
|
|
117
|
+
const tags = validateArray(typedParams.tags, "tags", 0, 100);
|
|
118
|
+
validated.tags = tags.map((id) => validateId(id, "tag ID"));
|
|
119
|
+
}
|
|
120
|
+
// Featured media validation
|
|
121
|
+
if (typedParams.featured_media !== undefined) {
|
|
122
|
+
if (typedParams.featured_media === null || typedParams.featured_media === 0) {
|
|
123
|
+
// Allow null or 0 to remove featured media
|
|
124
|
+
validated.featured_media = 0;
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
validated.featured_media = validateId(typedParams.featured_media, "featured_media");
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
// Date validation for scheduled posts
|
|
131
|
+
if (typedParams.date) {
|
|
132
|
+
try {
|
|
133
|
+
const date = new Date(String(typedParams.date));
|
|
134
|
+
if (isNaN(date.getTime())) {
|
|
135
|
+
throw new Error("Invalid date");
|
|
136
|
+
}
|
|
137
|
+
// WordPress expects ISO 8601 format
|
|
138
|
+
validated.date = date.toISOString();
|
|
139
|
+
}
|
|
140
|
+
catch {
|
|
141
|
+
throw new WordPressAPIError("Invalid date format. Use ISO 8601 format (YYYY-MM-DDTHH:mm:ss)", 400, "INVALID_PARAMETER");
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
return validated;
|
|
145
|
+
}
|
|
146
|
+
//# sourceMappingURL=wordpress.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wordpress.js","sourceRoot":"","sources":["../../../src/utils/validation/wordpress.ts"],"names":[],"mappings":"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"}
|