@carecard/validate 3.22.0 → 3.24.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 +20 -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,25 @@ const isJwtString = jwt => {
|
|
|
100
100
|
return jwtRegex.test(jwt);
|
|
101
101
|
};
|
|
102
102
|
|
|
103
|
-
const
|
|
104
|
-
if (typeof password !== 'string'
|
|
105
|
-
return false;
|
|
103
|
+
const validatePassword = password => {
|
|
104
|
+
if (typeof password !== 'string') {
|
|
105
|
+
return { isValid: false, reason: 'invalid_type' };
|
|
106
106
|
}
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
};
|
|
110
|
-
|
|
111
|
-
const isSimplePasswordString = password => {
|
|
112
|
-
if (typeof password !== 'string' || password.length === 0 || password.length > 128) {
|
|
113
|
-
return false;
|
|
107
|
+
if (!password.isWellFormed()) {
|
|
108
|
+
return { isValid: false, reason: 'invalid_unicode' };
|
|
114
109
|
}
|
|
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;
|
|
110
|
+
const normalizedPassword = password.normalize('NFC');
|
|
111
|
+
const passwordLength = [...normalizedPassword].length;
|
|
112
|
+
if (passwordLength < MINIMUM_PASSWORD_LENGTH) {
|
|
113
|
+
return { isValid: false, reason: 'too_short' };
|
|
124
114
|
}
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
if (
|
|
129
|
-
return
|
|
130
|
-
} else {
|
|
131
|
-
return null;
|
|
115
|
+
if (passwordLength > MAXIMUM_PASSWORD_LENGTH) {
|
|
116
|
+
return { isValid: false, reason: 'too_long' };
|
|
117
|
+
}
|
|
118
|
+
if (commonPasswords.has(normalizedPassword)) {
|
|
119
|
+
return { isValid: false, reason: 'blocked' };
|
|
132
120
|
}
|
|
121
|
+
return { isValid: true, value: normalizedPassword };
|
|
133
122
|
};
|
|
134
123
|
|
|
135
124
|
const isUsernameString = str => {
|
|
@@ -159,20 +148,6 @@ const isUrlSafeString = inputString => {
|
|
|
159
148
|
return urlSafeRegex.test(inputString);
|
|
160
149
|
};
|
|
161
150
|
|
|
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
151
|
const isProvinceString = inputString => {
|
|
177
152
|
const provinces = ['on', 'qc'];
|
|
178
153
|
|
|
@@ -356,15 +331,10 @@ module.exports = {
|
|
|
356
331
|
isSafeSearchString,
|
|
357
332
|
isEmailString,
|
|
358
333
|
isJwtString,
|
|
359
|
-
|
|
360
|
-
isSimplePasswordString,
|
|
361
|
-
isPasswordStringFailureMessage,
|
|
362
|
-
isSimplePasswordStringFailureMessage,
|
|
334
|
+
validatePassword,
|
|
363
335
|
isUsernameString,
|
|
364
336
|
isPhoneNumber,
|
|
365
337
|
isUrlSafeString,
|
|
366
|
-
isString6To24CharacterLong,
|
|
367
|
-
isString6To16CharacterLong,
|
|
368
338
|
isProvinceString,
|
|
369
339
|
isBoolValue,
|
|
370
340
|
isPostalCodeString,
|
|
@@ -381,3 +351,7 @@ module.exports = {
|
|
|
381
351
|
isValidUrl,
|
|
382
352
|
isValidArrayOfStrings,
|
|
383
353
|
};
|
|
354
|
+
const commonPasswords = new Set(require('../data/commonPasswords.json'));
|
|
355
|
+
|
|
356
|
+
const MINIMUM_PASSWORD_LENGTH = 15;
|
|
357
|
+
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.24.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.24.0"
|
|
48
51
|
},
|
|
49
52
|
"nyc": {
|
|
50
53
|
"all": true,
|