@carecard/validate 3.23.0 → 3.25.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/.agents/skills/pkg-validate-validation-library/SKILL.md +16 -14
- package/.github/workflows/ci.yml +1 -1
- package/.github/workflows/publish.yml +56 -56
- package/.nvmrc +1 -0
- package/THIRD_PARTY_NOTICES +31 -0
- package/data/commonPasswords.json +10006 -0
- package/index.d.ts +8 -19
- package/index.js +4 -2
- package/lib/validate.js +21 -46
- package/lib/validateProperties.js +6 -11
- package/package.json +5 -2
- package/readme.md +124 -103
package/index.d.ts
CHANGED
|
@@ -6,9 +6,16 @@
|
|
|
6
6
|
export type ValidatePropertiesInput = Record<string, unknown> | null | undefined;
|
|
7
7
|
export type ValidatePropertiesResult = Record<string, unknown>;
|
|
8
8
|
export type BoolValidator = (input: unknown) => boolean;
|
|
9
|
-
export type FailureMessageValidator = (input: unknown) => string | null;
|
|
10
9
|
export type InStringArrayValidator = (stringArray: readonly string[], input: unknown) => boolean;
|
|
11
10
|
|
|
11
|
+
export type PasswordValidationFailureReason =
|
|
12
|
+
'invalid_type' | 'invalid_unicode' | 'too_short' | 'too_long' | 'blocked';
|
|
13
|
+
export type PasswordValidationResult =
|
|
14
|
+
{ isValid: true; value: string } | { isValid: false; reason: PasswordValidationFailureReason };
|
|
15
|
+
|
|
16
|
+
/** Validates and NFC-normalizes a new password using the CareCard password policy. */
|
|
17
|
+
export function validatePassword(input: unknown): PasswordValidationResult;
|
|
18
|
+
|
|
12
19
|
/**
|
|
13
20
|
* Utility function to validate multiple properties of an object at once.
|
|
14
21
|
*/
|
|
@@ -145,24 +152,12 @@ export const isSafeSearchString: BoolValidator;
|
|
|
145
152
|
export const isEmailString: BoolValidator;
|
|
146
153
|
/** Checks if the string is a valid JWT format. */
|
|
147
154
|
export const isJwtString: BoolValidator;
|
|
148
|
-
/** Checks if the string is a valid strong password. */
|
|
149
|
-
export const isPasswordString: BoolValidator;
|
|
150
|
-
/** Checks if the string is a valid simple password. */
|
|
151
|
-
export const isSimplePasswordString: BoolValidator;
|
|
152
|
-
/** Returns a failure message if the password is not strong enough. */
|
|
153
|
-
export const isPasswordStringFailureMessage: FailureMessageValidator;
|
|
154
|
-
/** Returns a failure message if the password is not valid as a simple password. */
|
|
155
|
-
export const isSimplePasswordStringFailureMessage: FailureMessageValidator;
|
|
156
155
|
/** Checks if the string is a valid username. */
|
|
157
156
|
export const isUsernameString: BoolValidator;
|
|
158
157
|
/** Checks if the string is a valid phone number. */
|
|
159
158
|
export const isPhoneNumber: BoolValidator;
|
|
160
159
|
/** Checks if the string is URL-safe. */
|
|
161
160
|
export const isUrlSafeString: BoolValidator;
|
|
162
|
-
/** Checks if the string length is between 6 and 24 characters. */
|
|
163
|
-
export const isString6To24CharacterLong: BoolValidator;
|
|
164
|
-
/** Checks if the string length is between 6 and 16 characters. */
|
|
165
|
-
export const isString6To16CharacterLong: BoolValidator;
|
|
166
161
|
/** Checks if the string is a valid Canadian province abbreviation (ON, QC). */
|
|
167
162
|
export const isProvinceString: BoolValidator;
|
|
168
163
|
/** Checks if the value is a boolean. */
|
|
@@ -211,15 +206,9 @@ export const validate: {
|
|
|
211
206
|
isSafeSearchString: typeof isSafeSearchString;
|
|
212
207
|
isEmailString: typeof isEmailString;
|
|
213
208
|
isJwtString: typeof isJwtString;
|
|
214
|
-
isPasswordString: typeof isPasswordString;
|
|
215
|
-
isSimplePasswordString: typeof isSimplePasswordString;
|
|
216
|
-
isPasswordStringFailureMessage: typeof isPasswordStringFailureMessage;
|
|
217
|
-
isSimplePasswordStringFailureMessage: typeof isSimplePasswordStringFailureMessage;
|
|
218
209
|
isUsernameString: typeof isUsernameString;
|
|
219
210
|
isPhoneNumber: typeof isPhoneNumber;
|
|
220
211
|
isUrlSafeString: typeof isUrlSafeString;
|
|
221
|
-
isString6To24CharacterLong: typeof isString6To24CharacterLong;
|
|
222
|
-
isString6To16CharacterLong: typeof isString6To16CharacterLong;
|
|
223
212
|
isProvinceString: typeof isProvinceString;
|
|
224
213
|
isBoolValue: typeof isBoolValue;
|
|
225
214
|
isPostalCodeString: typeof isPostalCodeString;
|
package/index.js
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
const validate = require('./lib/validate');
|
|
2
|
+
const { validatePassword, ...legacyValidate } = validate;
|
|
2
3
|
const validateProperties = require('./lib/validateProperties');
|
|
3
4
|
const validateWhitelistProperties = require('./lib/validateWhitelistProperties');
|
|
4
5
|
const validateNewUserRoleRequest = require('./lib/validateNewUserRoleRequest');
|
|
5
6
|
|
|
6
7
|
module.exports = {
|
|
7
|
-
validate,
|
|
8
|
+
validate: legacyValidate,
|
|
9
|
+
validatePassword,
|
|
8
10
|
validateProperties,
|
|
9
11
|
validateWhitelistProperties,
|
|
10
12
|
...validateNewUserRoleRequest,
|
|
11
|
-
...
|
|
13
|
+
...legacyValidate,
|
|
12
14
|
...validateProperties,
|
|
13
15
|
};
|
package/lib/validate.js
CHANGED
|
@@ -100,36 +100,26 @@ const isJwtString = jwt => {
|
|
|
100
100
|
return jwtRegex.test(jwt);
|
|
101
101
|
};
|
|
102
102
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
103
|
+
// Pattern: Policy Function - owns normalization, length, and blocklist decisions for passwords.
|
|
104
|
+
const validatePassword = password => {
|
|
105
|
+
if (typeof password !== 'string') {
|
|
106
|
+
return { isValid: false, reason: 'invalid_type' };
|
|
106
107
|
}
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
};
|
|
110
|
-
|
|
111
|
-
const isSimplePasswordString = password => {
|
|
112
|
-
if (typeof password !== 'string' || password.length === 0 || password.length > 128) {
|
|
113
|
-
return false;
|
|
108
|
+
if (!password.isWellFormed()) {
|
|
109
|
+
return { isValid: false, reason: 'invalid_unicode' };
|
|
114
110
|
}
|
|
115
|
-
const
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
const isPasswordStringFailureMessage = password => {
|
|
120
|
-
if (!isPasswordString(password)) {
|
|
121
|
-
return 'Total 6 to 32 characters, numbers and one of !@#$%^&*_-';
|
|
122
|
-
} else {
|
|
123
|
-
return null;
|
|
111
|
+
const normalizedPassword = password.normalize('NFC');
|
|
112
|
+
const passwordLength = [...normalizedPassword].length;
|
|
113
|
+
if (passwordLength < MINIMUM_PASSWORD_LENGTH) {
|
|
114
|
+
return { isValid: false, reason: 'too_short' };
|
|
124
115
|
}
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
if (
|
|
129
|
-
return
|
|
130
|
-
} else {
|
|
131
|
-
return null;
|
|
116
|
+
if (passwordLength > MAXIMUM_PASSWORD_LENGTH) {
|
|
117
|
+
return { isValid: false, reason: 'too_long' };
|
|
118
|
+
}
|
|
119
|
+
if (commonPasswords.has(normalizedPassword)) {
|
|
120
|
+
return { isValid: false, reason: 'blocked' };
|
|
132
121
|
}
|
|
122
|
+
return { isValid: true, value: normalizedPassword };
|
|
133
123
|
};
|
|
134
124
|
|
|
135
125
|
const isUsernameString = str => {
|
|
@@ -159,20 +149,6 @@ const isUrlSafeString = inputString => {
|
|
|
159
149
|
return urlSafeRegex.test(inputString);
|
|
160
150
|
};
|
|
161
151
|
|
|
162
|
-
const isString6To24CharacterLong = password => {
|
|
163
|
-
if (typeof password !== 'string' || password.length === 0) {
|
|
164
|
-
return false;
|
|
165
|
-
}
|
|
166
|
-
return 6 <= password.length && password.length <= 24;
|
|
167
|
-
};
|
|
168
|
-
|
|
169
|
-
const isString6To16CharacterLong = password => {
|
|
170
|
-
if (typeof password !== 'string' || password.length === 0) {
|
|
171
|
-
return false;
|
|
172
|
-
}
|
|
173
|
-
return 6 <= password.length && password.length <= 16;
|
|
174
|
-
};
|
|
175
|
-
|
|
176
152
|
const isProvinceString = inputString => {
|
|
177
153
|
const provinces = ['on', 'qc'];
|
|
178
154
|
|
|
@@ -356,15 +332,10 @@ module.exports = {
|
|
|
356
332
|
isSafeSearchString,
|
|
357
333
|
isEmailString,
|
|
358
334
|
isJwtString,
|
|
359
|
-
|
|
360
|
-
isSimplePasswordString,
|
|
361
|
-
isPasswordStringFailureMessage,
|
|
362
|
-
isSimplePasswordStringFailureMessage,
|
|
335
|
+
validatePassword,
|
|
363
336
|
isUsernameString,
|
|
364
337
|
isPhoneNumber,
|
|
365
338
|
isUrlSafeString,
|
|
366
|
-
isString6To24CharacterLong,
|
|
367
|
-
isString6To16CharacterLong,
|
|
368
339
|
isProvinceString,
|
|
369
340
|
isBoolValue,
|
|
370
341
|
isPostalCodeString,
|
|
@@ -381,3 +352,7 @@ module.exports = {
|
|
|
381
352
|
isValidUrl,
|
|
382
353
|
isValidArrayOfStrings,
|
|
383
354
|
};
|
|
355
|
+
const commonPasswords = new Set(require('../data/commonPasswords.json'));
|
|
356
|
+
|
|
357
|
+
const MINIMUM_PASSWORD_LENGTH = 15;
|
|
358
|
+
const MAXIMUM_PASSWORD_LENGTH = 128;
|
|
@@ -5,9 +5,7 @@ const {
|
|
|
5
5
|
isUrlSafeString,
|
|
6
6
|
isValidUuidString,
|
|
7
7
|
isCcIdString,
|
|
8
|
-
|
|
9
|
-
isPasswordString,
|
|
10
|
-
isString6To16CharacterLong,
|
|
8
|
+
validatePassword,
|
|
11
9
|
isNameString,
|
|
12
10
|
isSafeSearchString,
|
|
13
11
|
isCharactersString,
|
|
@@ -110,14 +108,11 @@ function validateProperties(obj = {}) {
|
|
|
110
108
|
case 'password':
|
|
111
109
|
case 'new_password':
|
|
112
110
|
case 'newPassword':
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
case 'strongPassword':
|
|
119
|
-
if (isString6To16CharacterLong(value) && isPasswordString(value)) {
|
|
120
|
-
returnObj[key] = value;
|
|
111
|
+
{
|
|
112
|
+
const passwordResult = validatePassword(value);
|
|
113
|
+
if (passwordResult.isValid) {
|
|
114
|
+
returnObj[key] = passwordResult.value;
|
|
115
|
+
}
|
|
121
116
|
}
|
|
122
117
|
break;
|
|
123
118
|
case 'email':
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@carecard/validate",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.25.0",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+https://github.com/CareCard-ca/pkg-validate.git"
|
|
@@ -8,6 +8,9 @@
|
|
|
8
8
|
"description": "Validate data",
|
|
9
9
|
"main": "index.js",
|
|
10
10
|
"types": "index.d.ts",
|
|
11
|
+
"engines": {
|
|
12
|
+
"node": ">=24.20.0 <25"
|
|
13
|
+
},
|
|
11
14
|
"scripts": {
|
|
12
15
|
"test": "node scripts/runPackageTask.mjs test",
|
|
13
16
|
"test:order": "node --test scripts/testOrder/randomizeTestOrder.test.mjs scripts/testParallel/runIndexedMochaTests.test.mjs scripts/packageTaskRunner.test.mjs scripts/canonicalTestCommand.test.mjs",
|
|
@@ -44,7 +47,7 @@
|
|
|
44
47
|
"typescript": "6.0.3"
|
|
45
48
|
},
|
|
46
49
|
"dependencies": {
|
|
47
|
-
"@carecard/common-util": "3.
|
|
50
|
+
"@carecard/common-util": "3.25.0"
|
|
48
51
|
},
|
|
49
52
|
"nyc": {
|
|
50
53
|
"all": true,
|