-
Notifications
You must be signed in to change notification settings - Fork 0
fix: add attribute name in errors #30
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -185,52 +185,53 @@ interface ValidationConstraints { | |
| */ | ||
| function buildValidationFunction( | ||
| constraints: ValidationConstraints, | ||
| propertyName: string, | ||
| ): ((value: unknown) => boolean) | undefined { | ||
| const checks: string[] = []; | ||
|
|
||
| // String length validation | ||
| if (constraints.minLength !== undefined) { | ||
| checks.push( | ||
| `if (typeof value === "string" && value.length < ${constraints.minLength}) return "Value must be at least ${constraints.minLength} characters"`, | ||
| `if (typeof value === "string" && value.length < ${constraints.minLength}) return "'${propertyName}' must be at least ${constraints.minLength} characters"`, | ||
| ); | ||
| } | ||
| if (constraints.maxLength !== undefined) { | ||
| checks.push( | ||
| `if (typeof value === "string" && value.length > ${constraints.maxLength}) return "Value must be at most ${constraints.maxLength} characters"`, | ||
| `if (typeof value === "string" && value.length > ${constraints.maxLength}) return "'${propertyName}' must be at most ${constraints.maxLength} characters"`, | ||
|
||
| ); | ||
| } | ||
|
|
||
| // Numeric validation | ||
| if (constraints.minValue !== undefined) { | ||
| checks.push( | ||
| `if (typeof value === "number" && value < ${constraints.minValue}) return "Value must be at least ${constraints.minValue}"`, | ||
| `if (typeof value === "number" && value < ${constraints.minValue}) return "'${propertyName}' must be at least ${constraints.minValue}"`, | ||
|
||
| ); | ||
| } | ||
| if (constraints.maxValue !== undefined) { | ||
| checks.push( | ||
| `if (typeof value === "number" && value > ${constraints.maxValue}) return "Value must be at most ${constraints.maxValue}"`, | ||
| `if (typeof value === "number" && value > ${constraints.maxValue}) return "'${propertyName}' must be at most ${constraints.maxValue}"`, | ||
|
||
| ); | ||
| } | ||
|
|
||
| // Integer validation | ||
| if (constraints.isInteger) { | ||
| checks.push( | ||
| `if (typeof value === "number" && !Number.isInteger(value)) return "Value must be an integer"`, | ||
| `if (typeof value === "number" && !Number.isInteger(value)) return "'${propertyName}' must be an integer"`, | ||
|
||
| ); | ||
| } | ||
|
|
||
| // Float validation (ensure it's a finite number) | ||
| if (constraints.isFloat) { | ||
| checks.push( | ||
| `if (typeof value === "number" && !Number.isFinite(value)) return "Value must be a finite number"`, | ||
| `if (typeof value === "number" && !Number.isFinite(value)) return "'${propertyName}' must be a finite number"`, | ||
|
||
| ); | ||
| } | ||
|
|
||
| // Pattern validation | ||
| if (constraints.pattern) { | ||
| const escapedPattern = constraints.pattern.replace(/\\/g, "\\\\"); | ||
| checks.push( | ||
| `if (typeof value === "string" && !new RegExp("${escapedPattern}").test(value)) return "Value must match pattern ${escapedPattern}"`, | ||
| `if (typeof value === "string" && !new RegExp("${escapedPattern}").test(value)) return "'${propertyName}' must match pattern ${escapedPattern}"`, | ||
|
||
| ); | ||
| } | ||
|
|
||
|
|
@@ -239,22 +240,22 @@ function buildValidationFunction( | |
| switch (constraints.dateTimeType) { | ||
| case "utcDateTime": | ||
| checks.push( | ||
| `if (typeof value === "string") { const d = new Date(value); if (isNaN(d.getTime())) return "Value must be a valid UTC date-time string"; }`, | ||
| `if (typeof value === "string") { const d = new Date(value); if (isNaN(d.getTime())) return "'${propertyName}' must be a valid UTC date-time string"; }`, | ||
|
||
| ); | ||
| break; | ||
| case "offsetDateTime": | ||
| checks.push( | ||
| `if (typeof value === "string") { const d = new Date(value); if (isNaN(d.getTime())) return "Value must be a valid offset date-time string"; }`, | ||
| `if (typeof value === "string") { const d = new Date(value); if (isNaN(d.getTime())) return "'${propertyName}' must be a valid offset date-time string"; }`, | ||
|
||
| ); | ||
| break; | ||
| case "plainDate": | ||
| checks.push( | ||
| `if (typeof value === "string" && !/^\\d{4}-\\d{2}-\\d{2}$/.test(value)) return "Value must be a valid date (YYYY-MM-DD)"`, | ||
| `if (typeof value === "string" && !/^\\d{4}-\\d{2}-\\d{2}$/.test(value)) return "'${propertyName}' must be a valid date (YYYY-MM-DD)"`, | ||
|
||
| ); | ||
| break; | ||
| case "plainTime": | ||
| checks.push( | ||
| `if (typeof value === "string" && !/^\\d{2}:\\d{2}(:\\d{2})?(\\.\\d+)?$/.test(value)) return "Value must be a valid time (HH:MM:SS)"`, | ||
| `if (typeof value === "string" && !/^\\d{2}:\\d{2}(:\\d{2})?(\\.\\d+)?$/.test(value)) return "'${propertyName}' must be a valid time (HH:MM:SS)"`, | ||
|
||
| ); | ||
| break; | ||
| } | ||
|
|
@@ -642,7 +643,7 @@ function emitAttribute(ctx: EmitContext, prop: ModelProperty): Attribute { | |
|
|
||
| // Add validation if constraints are present | ||
| const constraints = getValidationConstraints(ctx, prop); | ||
| const validateFn = buildValidationFunction(constraints); | ||
| const validateFn = buildValidationFunction(constraints, prop.name); | ||
| if (validateFn) { | ||
| // @ts-expect-error - validate is a valid ElectroDB attribute property | ||
| attr.validate = validateFn; | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The property name is being directly interpolated into error message strings that are later evaluated using eval(). This creates a potential code injection vulnerability if property names contain single quotes, backslashes, or other special characters. The property name should be escaped before being interpolated into the string to prevent breaking out of the string literal or injecting malicious code.