mcp-wordpress 1.2.2 → 1.3.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 +210 -182
- package/dist/cache/CacheInvalidation.d.ts +3 -3
- package/dist/cache/CacheInvalidation.d.ts.map +1 -1
- package/dist/cache/CacheInvalidation.js +119 -119
- package/dist/cache/CacheInvalidation.js.map +1 -1
- package/dist/cache/CacheManager.d.ts +5 -0
- package/dist/cache/CacheManager.d.ts.map +1 -1
- package/dist/cache/CacheManager.js +26 -16
- package/dist/cache/CacheManager.js.map +1 -1
- package/dist/cache/HttpCacheWrapper.d.ts +1 -1
- package/dist/cache/HttpCacheWrapper.d.ts.map +1 -1
- package/dist/cache/HttpCacheWrapper.js +29 -29
- package/dist/cache/HttpCacheWrapper.js.map +1 -1
- package/dist/cache/__tests__/CacheInvalidation.test.js +96 -94
- package/dist/cache/__tests__/CacheInvalidation.test.js.map +1 -1
- package/dist/cache/__tests__/CacheManager.test.js +113 -113
- package/dist/cache/__tests__/CacheManager.test.js.map +1 -1
- package/dist/cache/__tests__/CachedWordPressClient.test.js +102 -99
- package/dist/cache/__tests__/CachedWordPressClient.test.js.map +1 -1
- package/dist/cache/__tests__/HttpCacheWrapper.test.js +98 -95
- package/dist/cache/__tests__/HttpCacheWrapper.test.js.map +1 -1
- package/dist/cache/index.d.ts +7 -7
- package/dist/cache/index.d.ts.map +1 -1
- package/dist/cache/index.js +4 -4
- package/dist/cache/index.js.map +1 -1
- package/dist/client/CachedWordPressClient.d.ts +4 -4
- package/dist/client/CachedWordPressClient.d.ts.map +1 -1
- package/dist/client/CachedWordPressClient.js +55 -51
- package/dist/client/CachedWordPressClient.js.map +1 -1
- package/dist/client/api.d.ts +10 -10
- package/dist/client/api.js +158 -158
- package/dist/client/api.js.map +1 -1
- package/dist/client/auth.d.ts +2 -2
- package/dist/client/auth.js +72 -72
- package/dist/client/managers/AuthenticationManager.d.ts +2 -2
- package/dist/client/managers/AuthenticationManager.js +46 -46
- package/dist/client/managers/BaseManager.d.ts +1 -1
- package/dist/client/managers/BaseManager.js +9 -9
- package/dist/client/managers/RequestManager.d.ts +5 -3
- package/dist/client/managers/RequestManager.d.ts.map +1 -1
- package/dist/client/managers/RequestManager.js +39 -19
- package/dist/client/managers/RequestManager.js.map +1 -1
- package/dist/client/managers/index.d.ts +3 -3
- package/dist/client/managers/index.js +3 -3
- package/dist/config/ConfigurationSchema.d.ts +2 -2
- package/dist/config/ConfigurationSchema.d.ts.map +1 -1
- package/dist/config/ConfigurationSchema.js +40 -40
- package/dist/config/ConfigurationSchema.js.map +1 -1
- package/dist/config/ServerConfiguration.d.ts +2 -2
- package/dist/config/ServerConfiguration.js +35 -35
- package/dist/config/ServerConfiguration.js.map +1 -1
- package/dist/docs/DocumentationGenerator.d.ts.map +1 -1
- package/dist/docs/DocumentationGenerator.js +296 -255
- package/dist/docs/DocumentationGenerator.js.map +1 -1
- package/dist/docs/MarkdownFormatter.d.ts +1 -1
- package/dist/docs/MarkdownFormatter.d.ts.map +1 -1
- package/dist/docs/MarkdownFormatter.js +60 -51
- package/dist/docs/MarkdownFormatter.js.map +1 -1
- package/dist/docs/index.d.ts +3 -3
- package/dist/docs/index.d.ts.map +1 -1
- package/dist/docs/index.js +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +16 -16
- package/dist/index.js.map +1 -1
- package/dist/mcp-wordpress-1.3.0.tgz +0 -0
- package/dist/performance/MetricsCollector.d.ts +3 -3
- package/dist/performance/MetricsCollector.d.ts.map +1 -1
- package/dist/performance/MetricsCollector.js +33 -27
- package/dist/performance/MetricsCollector.js.map +1 -1
- package/dist/performance/PerformanceAnalytics.d.ts +12 -12
- package/dist/performance/PerformanceAnalytics.d.ts.map +1 -1
- package/dist/performance/PerformanceAnalytics.js +200 -154
- package/dist/performance/PerformanceAnalytics.js.map +1 -1
- package/dist/performance/PerformanceMonitor.d.ts +5 -5
- package/dist/performance/PerformanceMonitor.d.ts.map +1 -1
- package/dist/performance/PerformanceMonitor.js +53 -52
- package/dist/performance/PerformanceMonitor.js.map +1 -1
- package/dist/performance/index.d.ts +6 -6
- package/dist/performance/index.d.ts.map +1 -1
- package/dist/performance/index.js +3 -3
- package/dist/security/InputValidator.d.ts +1 -1
- package/dist/security/InputValidator.d.ts.map +1 -1
- package/dist/security/InputValidator.js +111 -88
- package/dist/security/InputValidator.js.map +1 -1
- package/dist/security/SecurityConfig.d.ts +5 -5
- package/dist/security/SecurityConfig.js +92 -92
- package/dist/security/SecurityConfig.js.map +1 -1
- package/dist/server/ConnectionTester.d.ts +1 -1
- package/dist/server/ConnectionTester.d.ts.map +1 -1
- package/dist/server/ConnectionTester.js +4 -4
- 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 +35 -32
- package/dist/server/ToolRegistry.js.map +1 -1
- package/dist/server.d.ts +2 -2
- package/dist/server.js +2 -2
- package/dist/tools/BaseToolManager.js +5 -5
- package/dist/tools/auth.d.ts +2 -2
- package/dist/tools/auth.d.ts.map +1 -1
- package/dist/tools/auth.js +32 -31
- package/dist/tools/auth.js.map +1 -1
- package/dist/tools/cache.d.ts +1 -1
- package/dist/tools/cache.d.ts.map +1 -1
- package/dist/tools/cache.js +71 -71
- package/dist/tools/cache.js.map +1 -1
- package/dist/tools/comments.d.ts +2 -2
- package/dist/tools/comments.d.ts.map +1 -1
- package/dist/tools/comments.js +79 -79
- package/dist/tools/comments.js.map +1 -1
- package/dist/tools/index.d.ts +10 -10
- package/dist/tools/index.js +10 -10
- package/dist/tools/media.d.ts +2 -2
- package/dist/tools/media.js +80 -80
- package/dist/tools/pages.d.ts +2 -2
- package/dist/tools/pages.d.ts.map +1 -1
- package/dist/tools/pages.js +75 -75
- package/dist/tools/pages.js.map +1 -1
- package/dist/tools/performance.d.ts +1 -1
- package/dist/tools/performance.d.ts.map +1 -1
- package/dist/tools/performance.js +311 -287
- package/dist/tools/performance.js.map +1 -1
- package/dist/tools/posts.d.ts +2 -2
- package/dist/tools/posts.d.ts.map +1 -1
- package/dist/tools/posts.js +94 -94
- package/dist/tools/posts.js.map +1 -1
- package/dist/tools/site.d.ts +2 -2
- package/dist/tools/site.d.ts.map +1 -1
- package/dist/tools/site.js +60 -60
- package/dist/tools/site.js.map +1 -1
- package/dist/tools/taxonomies.d.ts +2 -2
- package/dist/tools/taxonomies.js +89 -89
- package/dist/tools/users.d.ts +2 -2
- package/dist/tools/users.js +68 -68
- package/dist/tools/users.js.map +1 -1
- package/dist/types/client.d.ts +13 -13
- package/dist/types/client.d.ts.map +1 -1
- package/dist/types/client.js +12 -12
- package/dist/types/client.js.map +1 -1
- package/dist/types/index.d.ts +19 -19
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +3 -3
- package/dist/types/mcp.d.ts +7 -7
- package/dist/types/wordpress.d.ts +21 -21
- package/dist/types/wordpress.d.ts.map +1 -1
- package/dist/utils/debug.d.ts +2 -2
- package/dist/utils/debug.js +28 -28
- package/dist/utils/error.d.ts.map +1 -1
- package/dist/utils/error.js +13 -13
- package/dist/utils/error.js.map +1 -1
- package/dist/utils/toolWrapper.d.ts.map +1 -1
- package/dist/utils/toolWrapper.js +5 -5
- package/dist/utils/toolWrapper.js.map +1 -1
- package/dist/utils/validation.d.ts.map +1 -1
- package/dist/utils/validation.js +41 -31
- package/dist/utils/validation.js.map +1 -1
- package/docs/CACHING.md +36 -2
- package/docs/DOCKER.md +24 -18
- package/docs/PERFORMANCE_MONITORING.md +49 -1
- package/docs/SECURITY_TESTING.md +30 -1
- package/docs/api/README.md +9 -1
- package/docs/api/summary.json +1 -1
- package/docs/contract-testing.md +24 -3
- package/docs/developer/GITHUB_ACTIONS_SETUP.md +8 -2
- package/docs/developer/MAINTENANCE.md +29 -3
- package/docs/developer/MIGRATION_GUIDE.md +13 -1
- package/docs/developer/NPM_AUTH_SETUP.md +13 -2
- package/docs/developer/REFACTORING.md +31 -1
- package/docs/releases/COMMUNITY_ANNOUNCEMENT_v1.1.2.md +18 -7
- package/docs/releases/RELEASE_NOTES_v1.1.2.md +31 -5
- package/docs/user-guides/DOCKER_SETUP.md +264 -0
- package/docs/user-guides/DTX_SETUP.md +327 -0
- package/docs/user-guides/NPM_SETUP.md +109 -0
- package/docs/user-guides/NPX_SETUP.md +281 -0
- package/docs/wordpress-rest-api-authentication-troubleshooting.md +13 -2
- package/package.json +27 -8
- package/src/cache/CacheInvalidation.ts +140 -132
- package/src/cache/CacheManager.ts +40 -29
- package/src/cache/HttpCacheWrapper.ts +105 -68
- package/src/cache/__tests__/CacheInvalidation.test.ts +123 -118
- package/src/cache/__tests__/CacheManager.test.ts +156 -152
- package/src/cache/__tests__/CachedWordPressClient.test.ts +131 -116
- package/src/cache/__tests__/HttpCacheWrapper.test.ts +118 -115
- package/src/cache/index.ts +13 -13
- package/src/client/CachedWordPressClient.ts +90 -80
- package/src/client/api.ts +205 -205
- package/src/client/auth.ts +80 -80
- package/src/client/managers/AuthenticationManager.ts +61 -61
- package/src/client/managers/BaseManager.ts +11 -11
- package/src/client/managers/RequestManager.ts +79 -47
- package/src/client/managers/index.ts +3 -3
- package/src/config/ConfigurationSchema.ts +44 -44
- package/src/config/ServerConfiguration.ts +39 -39
- package/src/docs/DocumentationGenerator.ts +402 -295
- package/src/docs/MarkdownFormatter.ts +94 -69
- package/src/docs/index.ts +4 -4
- package/src/index.ts +24 -21
- package/src/performance/MetricsCollector.ts +90 -58
- package/src/performance/PerformanceAnalytics.ts +386 -262
- package/src/performance/PerformanceMonitor.ts +152 -118
- package/src/performance/index.ts +9 -9
- package/src/security/InputValidator.ts +148 -91
- package/src/security/SecurityConfig.ts +94 -94
- package/src/server/ConnectionTester.ts +21 -15
- package/src/server/ToolRegistry.ts +64 -51
- package/src/server.ts +2 -2
- package/src/tools/BaseToolManager.ts +6 -6
- package/src/tools/auth.ts +42 -37
- package/src/tools/cache.ts +85 -81
- package/src/tools/comments.ts +93 -91
- package/src/tools/index.ts +10 -10
- package/src/tools/media.ts +89 -89
- package/src/tools/pages.ts +89 -87
- package/src/tools/performance.ts +443 -352
- package/src/tools/posts.ts +109 -107
- package/src/tools/site.ts +86 -77
- package/src/tools/taxonomies.ts +102 -102
- package/src/tools/users.ts +77 -77
- package/src/types/client.ts +157 -60
- package/src/types/index.ts +49 -27
- package/src/types/mcp.ts +15 -15
- package/src/types/wordpress.ts +57 -29
- package/src/utils/debug.ts +37 -37
- package/src/utils/error.ts +47 -25
- package/src/utils/toolWrapper.ts +12 -8
- package/src/utils/validation.ts +116 -65
- package/dist/client/WordPressClient.d.ts +0 -81
- package/dist/client/WordPressClient.d.ts.map +0 -1
- package/dist/client/WordPressClient.js +0 -354
- package/dist/client/WordPressClient.js.map +0 -1
- package/dist/performance/AnomalyDetector.d.ts +0 -63
- package/dist/performance/AnomalyDetector.d.ts.map +0 -1
- package/dist/performance/AnomalyDetector.js +0 -222
- package/dist/performance/AnomalyDetector.js.map +0 -1
- package/dist/performance/BenchmarkAnalyzer.d.ts +0 -67
- package/dist/performance/BenchmarkAnalyzer.d.ts.map +0 -1
- package/dist/performance/BenchmarkAnalyzer.js +0 -301
- package/dist/performance/BenchmarkAnalyzer.js.map +0 -1
- package/dist/performance/TrendAnalyzer.d.ts +0 -69
- package/dist/performance/TrendAnalyzer.d.ts.map +0 -1
- package/dist/performance/TrendAnalyzer.js +0 -203
- package/dist/performance/TrendAnalyzer.js.map +0 -1
- package/dist/tools/BaseToolClass.d.ts +0 -76
- package/dist/tools/BaseToolClass.d.ts.map +0 -1
- package/dist/tools/BaseToolClass.js +0 -104
- package/dist/tools/BaseToolClass.js.map +0 -1
- package/dist/tools/base.d.ts +0 -37
- package/dist/tools/base.d.ts.map +0 -1
- package/dist/tools/base.js +0 -60
- package/dist/tools/base.js.map +0 -1
- package/docs/user-guides/CLAUDE_DESKTOP_SETUP.md +0 -187
package/src/utils/validation.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import * as path from
|
|
2
|
-
import { WordPressAPIError } from
|
|
1
|
+
import * as path from "path";
|
|
2
|
+
import { WordPressAPIError } from "../types/client.js";
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Security-focused validation utilities for MCP WordPress
|
|
@@ -8,10 +8,14 @@ import { WordPressAPIError } from '../types/client.js';
|
|
|
8
8
|
/**
|
|
9
9
|
* Validates and sanitizes numeric IDs
|
|
10
10
|
*/
|
|
11
|
-
export function validateId(id: any, fieldName: string =
|
|
11
|
+
export function validateId(id: any, fieldName: string = "id"): number {
|
|
12
12
|
const numId = parseInt(String(id), 10);
|
|
13
13
|
if (isNaN(numId) || numId <= 0) {
|
|
14
|
-
throw new WordPressAPIError(
|
|
14
|
+
throw new WordPressAPIError(
|
|
15
|
+
`Invalid ${fieldName}: must be a positive number`,
|
|
16
|
+
400,
|
|
17
|
+
"INVALID_PARAMETER",
|
|
18
|
+
);
|
|
15
19
|
}
|
|
16
20
|
return numId;
|
|
17
21
|
}
|
|
@@ -20,40 +24,51 @@ export function validateId(id: any, fieldName: string = 'id'): number {
|
|
|
20
24
|
* Validates string length within bounds
|
|
21
25
|
*/
|
|
22
26
|
export function validateString(
|
|
23
|
-
value: any,
|
|
24
|
-
fieldName: string,
|
|
25
|
-
minLength: number = 1,
|
|
26
|
-
maxLength: number = 1000
|
|
27
|
+
value: any,
|
|
28
|
+
fieldName: string,
|
|
29
|
+
minLength: number = 1,
|
|
30
|
+
maxLength: number = 1000,
|
|
27
31
|
): string {
|
|
28
|
-
if (typeof value !==
|
|
29
|
-
throw new WordPressAPIError(
|
|
32
|
+
if (typeof value !== "string") {
|
|
33
|
+
throw new WordPressAPIError(
|
|
34
|
+
`Invalid ${fieldName}: must be a string`,
|
|
35
|
+
400,
|
|
36
|
+
"INVALID_PARAMETER",
|
|
37
|
+
);
|
|
30
38
|
}
|
|
31
|
-
|
|
39
|
+
|
|
32
40
|
const trimmed = value.trim();
|
|
33
41
|
if (trimmed.length < minLength || trimmed.length > maxLength) {
|
|
34
42
|
throw new WordPressAPIError(
|
|
35
43
|
`Invalid ${fieldName}: length must be between ${minLength} and ${maxLength} characters`,
|
|
36
44
|
400,
|
|
37
|
-
|
|
45
|
+
"INVALID_PARAMETER",
|
|
38
46
|
);
|
|
39
47
|
}
|
|
40
|
-
|
|
48
|
+
|
|
41
49
|
return trimmed;
|
|
42
50
|
}
|
|
43
51
|
|
|
44
52
|
/**
|
|
45
53
|
* Validates and sanitizes file paths to prevent directory traversal
|
|
46
54
|
*/
|
|
47
|
-
export function validateFilePath(
|
|
55
|
+
export function validateFilePath(
|
|
56
|
+
userPath: string,
|
|
57
|
+
allowedBasePath: string,
|
|
58
|
+
): string {
|
|
48
59
|
// Normalize the path to remove ../ and other dangerous patterns
|
|
49
60
|
const normalizedPath = path.normalize(userPath);
|
|
50
61
|
const resolvedPath = path.resolve(allowedBasePath, normalizedPath);
|
|
51
|
-
|
|
62
|
+
|
|
52
63
|
// Ensure the resolved path is within the allowed directory
|
|
53
64
|
if (!resolvedPath.startsWith(path.resolve(allowedBasePath))) {
|
|
54
|
-
throw new WordPressAPIError(
|
|
65
|
+
throw new WordPressAPIError(
|
|
66
|
+
"Invalid file path: access denied",
|
|
67
|
+
403,
|
|
68
|
+
"PATH_TRAVERSAL_ATTEMPT",
|
|
69
|
+
);
|
|
55
70
|
}
|
|
56
|
-
|
|
71
|
+
|
|
57
72
|
return resolvedPath;
|
|
58
73
|
}
|
|
59
74
|
|
|
@@ -61,12 +76,20 @@ export function validateFilePath(userPath: string, allowedBasePath: string): str
|
|
|
61
76
|
* Validates WordPress post status values
|
|
62
77
|
*/
|
|
63
78
|
export function validatePostStatus(status: string): string {
|
|
64
|
-
const validStatuses = [
|
|
79
|
+
const validStatuses = [
|
|
80
|
+
"publish",
|
|
81
|
+
"draft",
|
|
82
|
+
"pending",
|
|
83
|
+
"private",
|
|
84
|
+
"future",
|
|
85
|
+
"auto-draft",
|
|
86
|
+
"trash",
|
|
87
|
+
];
|
|
65
88
|
if (!validStatuses.includes(status)) {
|
|
66
89
|
throw new WordPressAPIError(
|
|
67
|
-
`Invalid status: must be one of ${validStatuses.join(
|
|
90
|
+
`Invalid status: must be one of ${validStatuses.join(", ")}`,
|
|
68
91
|
400,
|
|
69
|
-
|
|
92
|
+
"INVALID_PARAMETER",
|
|
70
93
|
);
|
|
71
94
|
}
|
|
72
95
|
return status;
|
|
@@ -75,29 +98,36 @@ export function validatePostStatus(status: string): string {
|
|
|
75
98
|
/**
|
|
76
99
|
* Validates and sanitizes URLs
|
|
77
100
|
*/
|
|
78
|
-
export function validateUrl(url: string, fieldName: string =
|
|
101
|
+
export function validateUrl(url: string, fieldName: string = "url"): string {
|
|
79
102
|
try {
|
|
80
103
|
const urlObj = new URL(url);
|
|
81
104
|
// Only allow http and https protocols
|
|
82
|
-
if (![
|
|
83
|
-
throw new Error(
|
|
105
|
+
if (!["http:", "https:"].includes(urlObj.protocol)) {
|
|
106
|
+
throw new Error("Invalid protocol");
|
|
84
107
|
}
|
|
85
108
|
return urlObj.toString();
|
|
86
109
|
} catch {
|
|
87
|
-
throw new WordPressAPIError(
|
|
110
|
+
throw new WordPressAPIError(
|
|
111
|
+
`Invalid ${fieldName}: must be a valid URL`,
|
|
112
|
+
400,
|
|
113
|
+
"INVALID_PARAMETER",
|
|
114
|
+
);
|
|
88
115
|
}
|
|
89
116
|
}
|
|
90
117
|
|
|
91
118
|
/**
|
|
92
119
|
* Validates file size
|
|
93
120
|
*/
|
|
94
|
-
export function validateFileSize(
|
|
121
|
+
export function validateFileSize(
|
|
122
|
+
sizeInBytes: number,
|
|
123
|
+
maxSizeInMB: number = 10,
|
|
124
|
+
): void {
|
|
95
125
|
const maxSizeInBytes = maxSizeInMB * 1024 * 1024;
|
|
96
126
|
if (sizeInBytes > maxSizeInBytes) {
|
|
97
127
|
throw new WordPressAPIError(
|
|
98
128
|
`File size exceeds maximum allowed size of ${maxSizeInMB}MB`,
|
|
99
129
|
413,
|
|
100
|
-
|
|
130
|
+
"FILE_TOO_LARGE",
|
|
101
131
|
);
|
|
102
132
|
}
|
|
103
133
|
}
|
|
@@ -105,12 +135,15 @@ export function validateFileSize(sizeInBytes: number, maxSizeInMB: number = 10):
|
|
|
105
135
|
/**
|
|
106
136
|
* Validates MIME types for file uploads
|
|
107
137
|
*/
|
|
108
|
-
export function validateMimeType(
|
|
138
|
+
export function validateMimeType(
|
|
139
|
+
mimeType: string,
|
|
140
|
+
allowedTypes: string[],
|
|
141
|
+
): void {
|
|
109
142
|
if (!allowedTypes.includes(mimeType)) {
|
|
110
143
|
throw new WordPressAPIError(
|
|
111
|
-
`Invalid file type: ${mimeType}. Allowed types: ${allowedTypes.join(
|
|
144
|
+
`Invalid file type: ${mimeType}. Allowed types: ${allowedTypes.join(", ")}`,
|
|
112
145
|
415,
|
|
113
|
-
|
|
146
|
+
"UNSUPPORTED_MEDIA_TYPE",
|
|
114
147
|
);
|
|
115
148
|
}
|
|
116
149
|
}
|
|
@@ -122,17 +155,20 @@ export function validateMimeType(mimeType: string, allowedTypes: string[]): void
|
|
|
122
155
|
*/
|
|
123
156
|
export function sanitizeHtml(html: string): string {
|
|
124
157
|
// Remove script tags and their content
|
|
125
|
-
let sanitized = html.replace(
|
|
126
|
-
|
|
158
|
+
let sanitized = html.replace(
|
|
159
|
+
/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,
|
|
160
|
+
"",
|
|
161
|
+
);
|
|
162
|
+
|
|
127
163
|
// Remove event handlers
|
|
128
|
-
sanitized = sanitized.replace(/\s*on\w+\s*=\s*["'][^"']*["']/gi,
|
|
129
|
-
|
|
164
|
+
sanitized = sanitized.replace(/\s*on\w+\s*=\s*["'][^"']*["']/gi, "");
|
|
165
|
+
|
|
130
166
|
// Remove javascript: protocol
|
|
131
|
-
sanitized = sanitized.replace(/javascript:/gi,
|
|
132
|
-
|
|
167
|
+
sanitized = sanitized.replace(/javascript:/gi, "");
|
|
168
|
+
|
|
133
169
|
// Remove data: protocol (can be used for XSS)
|
|
134
|
-
sanitized = sanitized.replace(/data:text\/html/gi,
|
|
135
|
-
|
|
170
|
+
sanitized = sanitized.replace(/data:text\/html/gi, "");
|
|
171
|
+
|
|
136
172
|
return sanitized;
|
|
137
173
|
}
|
|
138
174
|
|
|
@@ -143,20 +179,24 @@ export function validateArray<T>(
|
|
|
143
179
|
value: any,
|
|
144
180
|
fieldName: string,
|
|
145
181
|
minItems: number = 0,
|
|
146
|
-
maxItems: number = 100
|
|
182
|
+
maxItems: number = 100,
|
|
147
183
|
): T[] {
|
|
148
184
|
if (!Array.isArray(value)) {
|
|
149
|
-
throw new WordPressAPIError(
|
|
185
|
+
throw new WordPressAPIError(
|
|
186
|
+
`Invalid ${fieldName}: must be an array`,
|
|
187
|
+
400,
|
|
188
|
+
"INVALID_PARAMETER",
|
|
189
|
+
);
|
|
150
190
|
}
|
|
151
|
-
|
|
191
|
+
|
|
152
192
|
if (value.length < minItems || value.length > maxItems) {
|
|
153
193
|
throw new WordPressAPIError(
|
|
154
194
|
`Invalid ${fieldName}: array must contain between ${minItems} and ${maxItems} items`,
|
|
155
195
|
400,
|
|
156
|
-
|
|
196
|
+
"INVALID_PARAMETER",
|
|
157
197
|
);
|
|
158
198
|
}
|
|
159
|
-
|
|
199
|
+
|
|
160
200
|
return value;
|
|
161
201
|
}
|
|
162
202
|
|
|
@@ -166,7 +206,11 @@ export function validateArray<T>(
|
|
|
166
206
|
export function validateEmail(email: string): string {
|
|
167
207
|
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
168
208
|
if (!emailRegex.test(email)) {
|
|
169
|
-
throw new WordPressAPIError(
|
|
209
|
+
throw new WordPressAPIError(
|
|
210
|
+
"Invalid email address format",
|
|
211
|
+
400,
|
|
212
|
+
"INVALID_PARAMETER",
|
|
213
|
+
);
|
|
170
214
|
}
|
|
171
215
|
return email.toLowerCase();
|
|
172
216
|
}
|
|
@@ -179,20 +223,20 @@ export function validateUsername(username: string): string {
|
|
|
179
223
|
const usernameRegex = /^[a-zA-Z0-9 _.\-@]+$/;
|
|
180
224
|
if (!usernameRegex.test(username)) {
|
|
181
225
|
throw new WordPressAPIError(
|
|
182
|
-
|
|
226
|
+
"Invalid username: can only contain letters, numbers, spaces, and _.-@ symbols",
|
|
183
227
|
400,
|
|
184
|
-
|
|
228
|
+
"INVALID_PARAMETER",
|
|
185
229
|
);
|
|
186
230
|
}
|
|
187
|
-
|
|
231
|
+
|
|
188
232
|
if (username.length < 3 || username.length > 60) {
|
|
189
233
|
throw new WordPressAPIError(
|
|
190
|
-
|
|
234
|
+
"Invalid username: must be between 3 and 60 characters",
|
|
191
235
|
400,
|
|
192
|
-
|
|
236
|
+
"INVALID_PARAMETER",
|
|
193
237
|
);
|
|
194
238
|
}
|
|
195
|
-
|
|
239
|
+
|
|
196
240
|
return username;
|
|
197
241
|
}
|
|
198
242
|
|
|
@@ -201,34 +245,38 @@ export function validateUsername(username: string): string {
|
|
|
201
245
|
* For production, use Redis or similar
|
|
202
246
|
*/
|
|
203
247
|
class RateLimiter {
|
|
204
|
-
private attempts: Map<string, { count: number; resetTime: number }> =
|
|
205
|
-
|
|
248
|
+
private attempts: Map<string, { count: number; resetTime: number }> =
|
|
249
|
+
new Map();
|
|
250
|
+
|
|
206
251
|
constructor(
|
|
207
252
|
private maxAttempts: number = 5,
|
|
208
|
-
private windowMs: number = 60000 // 1 minute
|
|
253
|
+
private windowMs: number = 60000, // 1 minute
|
|
209
254
|
) {}
|
|
210
|
-
|
|
255
|
+
|
|
211
256
|
check(identifier: string): void {
|
|
212
257
|
const now = Date.now();
|
|
213
258
|
const record = this.attempts.get(identifier);
|
|
214
|
-
|
|
259
|
+
|
|
215
260
|
if (!record || record.resetTime < now) {
|
|
216
|
-
this.attempts.set(identifier, {
|
|
261
|
+
this.attempts.set(identifier, {
|
|
262
|
+
count: 1,
|
|
263
|
+
resetTime: now + this.windowMs,
|
|
264
|
+
});
|
|
217
265
|
return;
|
|
218
266
|
}
|
|
219
|
-
|
|
267
|
+
|
|
220
268
|
if (record.count >= this.maxAttempts) {
|
|
221
269
|
const waitTime = Math.ceil((record.resetTime - now) / 1000);
|
|
222
270
|
throw new WordPressAPIError(
|
|
223
271
|
`Rate limit exceeded. Please wait ${waitTime} seconds before trying again.`,
|
|
224
272
|
429,
|
|
225
|
-
|
|
273
|
+
"RATE_LIMIT_EXCEEDED",
|
|
226
274
|
);
|
|
227
275
|
}
|
|
228
|
-
|
|
276
|
+
|
|
229
277
|
record.count++;
|
|
230
278
|
}
|
|
231
|
-
|
|
279
|
+
|
|
232
280
|
reset(identifier: string): void {
|
|
233
281
|
this.attempts.delete(identifier);
|
|
234
282
|
}
|
|
@@ -243,17 +291,20 @@ export const authRateLimiter = new RateLimiter(5, 300000); // 5 attempts per 5 m
|
|
|
243
291
|
export function validateSearchQuery(query: string): string {
|
|
244
292
|
// Remove potentially dangerous characters while preserving search functionality
|
|
245
293
|
let sanitized = query.trim();
|
|
246
|
-
|
|
294
|
+
|
|
247
295
|
// Limit length to prevent DoS
|
|
248
296
|
if (sanitized.length > 200) {
|
|
249
297
|
sanitized = sanitized.substring(0, 200);
|
|
250
298
|
}
|
|
251
|
-
|
|
299
|
+
|
|
252
300
|
// Remove SQL-like patterns (basic protection)
|
|
253
|
-
sanitized = sanitized.replace(
|
|
254
|
-
|
|
301
|
+
sanitized = sanitized.replace(
|
|
302
|
+
/(\b(union|select|insert|update|delete|drop|create)\b)/gi,
|
|
303
|
+
"",
|
|
304
|
+
);
|
|
305
|
+
|
|
255
306
|
// Remove special characters that might be used for injection
|
|
256
|
-
sanitized = sanitized.replace(/[<>'"`;\\]/g,
|
|
257
|
-
|
|
307
|
+
sanitized = sanitized.replace(/[<>'"`;\\]/g, "");
|
|
308
|
+
|
|
258
309
|
return sanitized;
|
|
259
310
|
}
|
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Refactored WordPress API Client
|
|
3
|
-
* Uses composition pattern with specialized managers
|
|
4
|
-
*/
|
|
5
|
-
import type { IWordPressClient, WordPressClientConfig, ClientStats } from "../types/client.js";
|
|
6
|
-
import type { WordPressPost, WordPressPage, WordPressMedia, WordPressUser, WordPressComment, WordPressSiteSettings, WordPressApplicationPassword, PostQueryParams, MediaQueryParams, UserQueryParams, CreatePostRequest, UpdatePostRequest, CreatePageRequest, UpdatePageRequest, CreateUserRequest, UpdateUserRequest, UploadMediaRequest } from "../types/wordpress.js";
|
|
7
|
-
export declare class WordPressClient implements IWordPressClient {
|
|
8
|
-
private authManager;
|
|
9
|
-
private requestManager;
|
|
10
|
-
private clientConfig;
|
|
11
|
-
constructor(options?: Partial<WordPressClientConfig>);
|
|
12
|
-
get config(): WordPressClientConfig;
|
|
13
|
-
get isAuthenticated(): boolean;
|
|
14
|
-
get stats(): ClientStats;
|
|
15
|
-
initialize(): Promise<void>;
|
|
16
|
-
authenticate(): Promise<boolean>;
|
|
17
|
-
disconnect(): Promise<void>;
|
|
18
|
-
request<T = any>(method: any, endpoint: string, data?: any, options?: any): Promise<T>;
|
|
19
|
-
get<T = any>(endpoint: string, options?: any): Promise<T>;
|
|
20
|
-
post<T = any>(endpoint: string, data?: any, options?: any): Promise<T>;
|
|
21
|
-
put<T = any>(endpoint: string, data?: any, options?: any): Promise<T>;
|
|
22
|
-
patch<T = any>(endpoint: string, data?: any, options?: any): Promise<T>;
|
|
23
|
-
delete<T = any>(endpoint: string, options?: any): Promise<T>;
|
|
24
|
-
testAuthentication(): Promise<{
|
|
25
|
-
success: boolean;
|
|
26
|
-
user?: WordPressUser;
|
|
27
|
-
}>;
|
|
28
|
-
private authenticatedRequest;
|
|
29
|
-
getPosts(params?: PostQueryParams): Promise<WordPressPost[]>;
|
|
30
|
-
getPost(id: number): Promise<WordPressPost>;
|
|
31
|
-
createPost(data: CreatePostRequest): Promise<WordPressPost>;
|
|
32
|
-
updatePost(data: UpdatePostRequest): Promise<WordPressPost>;
|
|
33
|
-
deletePost(id: number, force?: boolean): Promise<{
|
|
34
|
-
deleted: boolean;
|
|
35
|
-
previous?: WordPressPost;
|
|
36
|
-
}>;
|
|
37
|
-
getPostRevisions(id: number): Promise<WordPressPost[]>;
|
|
38
|
-
getPages(params?: any): Promise<WordPressPage[]>;
|
|
39
|
-
getPage(id: number): Promise<WordPressPage>;
|
|
40
|
-
createPage(data: CreatePageRequest): Promise<WordPressPage>;
|
|
41
|
-
updatePage(data: UpdatePageRequest): Promise<WordPressPage>;
|
|
42
|
-
deletePage(id: number, force?: boolean): Promise<{
|
|
43
|
-
deleted: boolean;
|
|
44
|
-
previous?: WordPressPage;
|
|
45
|
-
}>;
|
|
46
|
-
getPageRevisions(id: number): Promise<WordPressPage[]>;
|
|
47
|
-
getMedia(params?: MediaQueryParams): Promise<WordPressMedia[]>;
|
|
48
|
-
getMediaItem(id: number, context?: 'view' | 'embed' | 'edit'): Promise<WordPressMedia>;
|
|
49
|
-
uploadFile(fileData: Buffer, filename: string, mimeType: string, meta?: Partial<UploadMediaRequest>, options?: any): Promise<WordPressMedia>;
|
|
50
|
-
getUsers(params?: UserQueryParams): Promise<WordPressUser[]>;
|
|
51
|
-
getUser(id: number | string): Promise<WordPressUser>;
|
|
52
|
-
getCurrentUser(): Promise<WordPressUser>;
|
|
53
|
-
createUser(data: CreateUserRequest): Promise<WordPressUser>;
|
|
54
|
-
updateUser(data: UpdateUserRequest): Promise<WordPressUser>;
|
|
55
|
-
deleteUser(id: number, reassign?: number): Promise<{
|
|
56
|
-
deleted: boolean;
|
|
57
|
-
previous?: WordPressUser;
|
|
58
|
-
}>;
|
|
59
|
-
approveComment(id: number): Promise<WordPressComment>;
|
|
60
|
-
rejectComment(id: number): Promise<WordPressComment>;
|
|
61
|
-
spamComment(id: number): Promise<WordPressComment>;
|
|
62
|
-
getSiteSettings(): Promise<WordPressSiteSettings>;
|
|
63
|
-
updateSiteSettings(settings: Partial<WordPressSiteSettings>): Promise<WordPressSiteSettings>;
|
|
64
|
-
getSiteInfo(): Promise<any>;
|
|
65
|
-
getApplicationPasswords(userId: number): Promise<WordPressApplicationPassword[]>;
|
|
66
|
-
createApplicationPassword(userId: number | 'me', name: string, appId?: string): Promise<WordPressApplicationPassword>;
|
|
67
|
-
deleteApplicationPassword(userId: number, uuid: string): Promise<{
|
|
68
|
-
deleted: boolean;
|
|
69
|
-
}>;
|
|
70
|
-
search(query: string, types?: string[], subtype?: string): Promise<Array<{
|
|
71
|
-
id: number;
|
|
72
|
-
title: string;
|
|
73
|
-
url: string;
|
|
74
|
-
type: string;
|
|
75
|
-
subtype: string;
|
|
76
|
-
}>>;
|
|
77
|
-
ping(): Promise<boolean>;
|
|
78
|
-
private buildConfig;
|
|
79
|
-
private validateConfig;
|
|
80
|
-
}
|
|
81
|
-
//# sourceMappingURL=WordPressClient.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"WordPressClient.d.ts","sourceRoot":"","sources":["../../src/client/WordPressClient.ts"],"names":[],"mappings":"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"}
|