@rnaga/wp-node 1.2.3 → 1.2.6

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.
@@ -1 +1 @@
1
- {"version":3,"file":"password.d.ts","sourceRoot":"","sources":["../../src/common/password.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,YAAY,GAAI,WAAW,MAAM,WAG7C,CAAC;AAEF,eAAO,MAAM,aAAa,GAAI,WAAW,MAAM,EAAE,YAAY,MAAM,YAGlE,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAC3B,SAAQ,MAAW,EACnB,eAAc,OAAc,EAC5B,oBAAmB,OAAe,KACjC,MAmBF,CAAC"}
1
+ {"version":3,"file":"password.d.ts","sourceRoot":"","sources":["../../src/common/password.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,YAAY,GAAI,WAAW,MAAM,WAG7C,CAAC;AAEF,eAAO,MAAM,aAAa,GAAI,WAAW,MAAM,EAAE,YAAY,MAAM,YAGlE,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAC3B,SAAQ,MAAW,EACnB,eAAc,OAAc,EAC5B,oBAAmB,OAAe,KACjC,MAmBF,CAAC"}
@@ -32,9 +32,13 @@ var __importStar = (this && this.__importStar) || (function () {
32
32
  return result;
33
33
  };
34
34
  })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
35
38
  Object.defineProperty(exports, "__esModule", { value: true });
36
39
  exports.generatePassword = exports.checkPassword = exports.hashPassword = void 0;
37
40
  const crypto = __importStar(require("crypto"));
41
+ const bcryptjs_1 = __importDefault(require("bcryptjs"));
38
42
  const hashPassword = (plainText) => {
39
43
  const passwordHash = new PasswordHash(8, true);
40
44
  return passwordHash.hashPassword(plainText);
@@ -207,18 +211,84 @@ class PasswordHash {
207
211
  }
208
212
  return "*";
209
213
  }
214
+ // https://github.com/WordPress/wordpress-develop/blob/063a74f93f0a89d1d92fac1f25c49a379ab3476b/src/wp-includes/pluggable.php#L2740
210
215
  checkPassword(password, storedHash) {
216
+ // Passwords longer than 4096 characters are not supported
211
217
  if (password.length > 4096) {
212
218
  return false;
213
219
  }
214
- let hash = this.cryptPrivate(password, storedHash);
215
- if (hash[0] === "*") {
216
- hash = crypto
217
- .createHash("md5")
218
- .update(password, "binary")
219
- .digest("binary");
220
- hash = this.cryptPrivate(password, storedHash);
220
+ // Check the hash using md5 regardless of the current hashing mechanism (legacy support)
221
+ if (storedHash.length <= 32) {
222
+ const md5Hash = crypto.createHash("md5").update(password).digest("hex");
223
+ return this.hashEquals(storedHash, md5Hash);
224
+ }
225
+ // Check the password using the current WordPress prefixed hash ($wp$ prefix)
226
+ if (storedHash.startsWith("$wp$")) {
227
+ try {
228
+ // WordPress 6.8+ uses SHA384 HMAC preprocessing before bcrypt
229
+ const passwordToVerify = crypto
230
+ .createHmac("sha384", "wp-sha384")
231
+ .update(password)
232
+ .digest("base64");
233
+ const bcryptHash = storedHash.substring(3); // Remove "$wp" prefix
234
+ return this.verifyPassword(passwordToVerify, bcryptHash);
235
+ }
236
+ catch (err) {
237
+ console.error("Error verifying WordPress prefixed hash:", err);
238
+ return false;
239
+ }
240
+ }
241
+ // Check the password using phpass ($P$ prefix)
242
+ if (storedHash.startsWith("$P$")) {
243
+ let hash = this.cryptPrivate(password, storedHash);
244
+ if (hash[0] === "*") {
245
+ hash = crypto
246
+ .createHash("md5")
247
+ .update(password, "binary")
248
+ .digest("binary");
249
+ hash = this.cryptPrivate(password, storedHash);
250
+ }
251
+ return hash === storedHash;
252
+ }
253
+ // Check the password using compat support for any non-prefixed hash (bcrypt, Argon2, etc.)
254
+ try {
255
+ return this.verifyPassword(password, storedHash);
256
+ }
257
+ catch (err) {
258
+ console.error("Error verifying non-prefixed hash:", err);
259
+ return false;
260
+ }
261
+ }
262
+ /**
263
+ * Secure hash comparison to prevent timing attacks
264
+ */
265
+ hashEquals(hash1, hash2) {
266
+ if (hash1.length !== hash2.length) {
267
+ return false;
268
+ }
269
+ let result = 0;
270
+ for (let i = 0; i < hash1.length; i++) {
271
+ result |= hash1.charCodeAt(i) ^ hash2.charCodeAt(i);
272
+ }
273
+ return result === 0;
274
+ }
275
+ /**
276
+ * Verify password using modern hashing algorithms (bcrypt, Argon2, etc.)
277
+ */
278
+ verifyPassword(password, hash) {
279
+ try {
280
+ // Try bcrypt first (most common)
281
+ if (hash.match(/^\$2[axyb]\$/)) {
282
+ return bcryptjs_1.default.compareSync(password, hash);
283
+ }
284
+ // For other algorithms, we would need additional libraries
285
+ // For now, we'll just try bcrypt and return false for unsupported formats
286
+ console.warn(`Unsupported hash format: ${hash.substring(0, 10)}...`);
287
+ return false;
288
+ }
289
+ catch (err) {
290
+ console.error("Error in password verification:", err);
291
+ return false;
221
292
  }
222
- return hash === storedHash;
223
293
  }
224
294
  }
package/crud/error.d.ts CHANGED
@@ -13,8 +13,7 @@ export declare class StatusCodeMapper {
13
13
  }
14
14
  declare class CustomError extends Error {
15
15
  statusCode: StatusCode;
16
- isOperational: boolean;
17
- constructor(message: string, statusMessage: StatusMessage, isOperational?: boolean, stack?: string);
16
+ constructor(message: string, statusMessage: StatusMessage);
18
17
  }
19
18
  export declare class CrudError extends CustomError {
20
19
  constructor(statusMessage: StatusMessage | undefined, detail: string);
@@ -1 +1 @@
1
- {"version":3,"file":"error.d.ts","sourceRoot":"","sources":["../../src/crud/error.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,UAAU,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;AAE/C,oBAAY,aAAa;IACvB,WAAW,gBAAgB;IAC3B,YAAY,iBAAiB;IAC7B,SAAS,cAAc;IACvB,qBAAqB,0BAA0B;CAChD;AAED,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,MAAM,CAAC,SAAS,CAKb;IAEX,OAAO,CAAC,MAAM,CAAC,gBAAgB,CAMU;WAE3B,OAAO,CAAC,OAAO,EAAE,aAAa,GAAG,UAAU;WAI3C,UAAU,CAAC,UAAU,EAAE,UAAU,GAAG,aAAa;CAKhE;AAED,cAAM,WAAY,SAAQ,KAAK;IACtB,UAAU,EAAE,UAAU,CAAC;IACvB,aAAa,EAAE,OAAO,CAAC;gBAG5B,OAAO,EAAE,MAAM,EACf,aAAa,EAAE,aAAa,EAC5B,aAAa,GAAE,OAAc,EAC7B,KAAK,SAAK;CAWb;AAED,qBAAa,SAAU,SAAQ,WAAW;gBAEtC,aAAa,EAAE,aAAa,YAAsC,EAClE,MAAM,EAAE,MAAM;CAKjB"}
1
+ {"version":3,"file":"error.d.ts","sourceRoot":"","sources":["../../src/crud/error.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,UAAU,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;AAE/C,oBAAY,aAAa;IACvB,WAAW,gBAAgB;IAC3B,YAAY,iBAAiB;IAC7B,SAAS,cAAc;IACvB,qBAAqB,0BAA0B;CAChD;AAED,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,MAAM,CAAC,SAAS,CAKb;IAEX,OAAO,CAAC,MAAM,CAAC,gBAAgB,CAMU;WAE3B,OAAO,CAAC,OAAO,EAAE,aAAa,GAAG,UAAU;WAI3C,UAAU,CAAC,UAAU,EAAE,UAAU,GAAG,aAAa;CAKhE;AAED,cAAM,WAAY,SAAQ,KAAK;IACtB,UAAU,EAAE,UAAU,CAAC;gBAElB,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,aAAa;CAK1D;AAED,qBAAa,SAAU,SAAQ,WAAW;gBAEtC,aAAa,EAAE,aAAa,YAAsC,EAClE,MAAM,EAAE,MAAM;CAKjB"}
package/crud/error.js CHANGED
@@ -29,22 +29,15 @@ class StatusCodeMapper {
29
29
  exports.StatusCodeMapper = StatusCodeMapper;
30
30
  class CustomError extends Error {
31
31
  statusCode;
32
- isOperational;
33
- constructor(message, statusMessage, isOperational = true, stack = "") {
32
+ constructor(message, statusMessage) {
34
33
  super(message);
35
34
  this.statusCode = StatusCodeMapper.getCode(statusMessage);
36
- this.isOperational = isOperational;
37
- if (stack) {
38
- this.stack = stack;
39
- }
40
- else {
41
- Error.captureStackTrace(this, this.constructor);
42
- }
35
+ Error.captureStackTrace(this, this.constructor);
43
36
  }
44
37
  }
45
38
  class CrudError extends CustomError {
46
39
  constructor(statusMessage = StatusMessage.INTERNAL_SERVER_ERROR, detail) {
47
- super(`Error: ${detail}`, statusMessage, true);
40
+ super(`Error: ${detail}`, statusMessage);
48
41
  Object.setPrototypeOf(this, CrudError.prototype);
49
42
  }
50
43
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rnaga/wp-node",
3
- "version": "1.2.3",
3
+ "version": "1.2.6",
4
4
  "description": "",
5
5
  "scripts": {
6
6
  "build": "rm -rf ./dist && tsc --project tsconfig.build.json && npm run copyfiles && cp package.json ./dist/",
@@ -23,11 +23,12 @@
23
23
  "@types/node": "^22",
24
24
  "copyfiles": "^2.4.1",
25
25
  "ts-node": "^10.9.1",
26
- "typescript": "^5.8.3",
26
+ "typescript": "^5.9",
27
27
  "wordpress-hash-node": "^1.0.0"
28
28
  },
29
29
  "dependencies": {
30
- "bcryptjs": "^3.0.0",
30
+ "@types/bcryptjs": "^2.4.6",
31
+ "bcryptjs": "^3.0.2",
31
32
  "deep-object-diff": "^1.1.9",
32
33
  "knex": "^3.1.0",
33
34
  "moment-timezone": "^0.6.0",
@@ -1,18 +1,18 @@
1
1
  export declare const termUpdate: import("zod").ZodObject<{
2
- parent: import("zod").ZodDefault<import("zod").ZodNumber>;
3
2
  taxonomy: import("zod").ZodDefault<import("zod").ZodString>;
4
3
  name: import("zod").ZodString;
5
4
  term_id: import("zod").ZodDefault<import("zod").ZodNumber>;
6
5
  term_taxonomy_id: import("zod").ZodNumber;
7
6
  description: import("zod").ZodDefault<import("zod").ZodString>;
7
+ parent: import("zod").ZodDefault<import("zod").ZodNumber>;
8
8
  slug: import("zod").ZodPipe<import("zod").ZodString, import("zod").ZodTransform<string, string>>;
9
9
  term_group: import("zod").ZodDefault<import("zod").ZodNumber>;
10
10
  }, import("zod/v4/core").$strip>;
11
11
  export declare const termInsert: import("zod").ZodObject<{
12
- parent: import("zod").ZodDefault<import("zod").ZodNumber>;
13
12
  taxonomy: import("zod").ZodDefault<import("zod").ZodString>;
14
13
  name: import("zod").ZodString;
15
14
  description: import("zod").ZodDefault<import("zod").ZodString>;
15
+ parent: import("zod").ZodDefault<import("zod").ZodNumber>;
16
16
  slug: import("zod").ZodPipe<import("zod").ZodString, import("zod").ZodTransform<string, string>>;
17
17
  term_group: import("zod").ZodDefault<import("zod").ZodNumber>;
18
18
  }, import("zod/v4/core").$strip>;