Fix ftl template not correctly parsing numbers

This commit is contained in:
Joseph Garrone 2024-05-11 16:06:42 +02:00
parent 632641a067
commit 18c82a58a7
4 changed files with 53 additions and 49 deletions

View File

@ -528,12 +528,23 @@
<#return '"' + object?datetime?iso_utc + '"'> <#return '"' + object?datetime?iso_utc + '"'>
</#if> </#if>
<#local isNumber = "">
<#attempt>
<#local isNumber = object?is_number>
<#recover>
<#return "ABORT: Can't test if it's a number">
</#attempt>
<#if isNumber>
<#return object?c>
</#if>
<#attempt> <#attempt>
<#return '"' + object?js_string + '"'>; <#return '"' + object?js_string + '"'>;
<#recover> <#recover>
</#attempt> </#attempt>
<#return "ABORT: Couldn't convert into string non hash, non method, non boolean, non enumerable object"> <#return "ABORT: Couldn't convert into string non hash, non method, non boolean, non number, non enumerable object">
</#function> </#function>
<#function is_subpath path searchedPath> <#function is_subpath path searchedPath>

View File

@ -332,9 +332,13 @@ function InputTag(props: InputFiledByTypeProps & { fieldIndex: number | undefine
autoComplete={attribute.autocomplete} autoComplete={attribute.autocomplete}
placeholder={attribute.annotations.inputTypePlaceholder} placeholder={attribute.annotations.inputTypePlaceholder}
pattern={attribute.annotations.inputTypePattern} pattern={attribute.annotations.inputTypePattern}
size={attribute.annotations.inputTypeSize === undefined ? undefined : parseInt(attribute.annotations.inputTypeSize)} size={attribute.annotations.inputTypeSize === undefined ? undefined : parseInt(`${attribute.annotations.inputTypeSize}`)}
maxLength={attribute.annotations.inputTypeMaxlength === undefined ? undefined : parseInt(attribute.annotations.inputTypeMaxlength)} maxLength={
minLength={attribute.annotations.inputTypeMinlength === undefined ? undefined : parseInt(attribute.annotations.inputTypeMinlength)} attribute.annotations.inputTypeMaxlength === undefined ? undefined : parseInt(`${attribute.annotations.inputTypeMaxlength}`)
}
minLength={
attribute.annotations.inputTypeMinlength === undefined ? undefined : parseInt(`${attribute.annotations.inputTypeMinlength}`)
}
max={attribute.annotations.inputTypeMax} max={attribute.annotations.inputTypeMax}
min={attribute.annotations.inputTypeMin} min={attribute.annotations.inputTypeMin}
step={attribute.annotations.inputTypeStep} step={attribute.annotations.inputTypeStep}
@ -428,7 +432,7 @@ function AddRemoveButtonsMultiValuedAttribute(props: {
return undefined; return undefined;
} }
return parseInt(minStr); return parseInt(`${minStr}`);
})(); })();
if (minCount === undefined) { if (minCount === undefined) {
@ -460,7 +464,7 @@ function AddRemoveButtonsMultiValuedAttribute(props: {
return undefined; return undefined;
} }
return parseInt(maxStr); return parseInt(`${maxStr}`);
})(); })();
if (maxCount === undefined) { if (maxCount === undefined) {
@ -635,9 +639,9 @@ function TextareaTag(props: InputFiledByTypeProps) {
className={getClassName("kcInputClass")} className={getClassName("kcInputClass")}
aria-invalid={displayableErrors.length !== 0} aria-invalid={displayableErrors.length !== 0}
disabled={attribute.readOnly} disabled={attribute.readOnly}
cols={attribute.annotations.inputTypeCols === undefined ? undefined : parseInt(attribute.annotations.inputTypeCols)} cols={attribute.annotations.inputTypeCols === undefined ? undefined : parseInt(`${attribute.annotations.inputTypeCols}`)}
rows={attribute.annotations.inputTypeRows === undefined ? undefined : parseInt(attribute.annotations.inputTypeRows)} rows={attribute.annotations.inputTypeRows === undefined ? undefined : parseInt(`${attribute.annotations.inputTypeRows}`)}
maxLength={attribute.annotations.inputTypeMaxlength === undefined ? undefined : parseInt(attribute.annotations.inputTypeMaxlength)} maxLength={attribute.annotations.inputTypeMaxlength === undefined ? undefined : parseInt(`${attribute.annotations.inputTypeMaxlength}`)}
value={value} value={value}
onChange={event => onChange={event =>
formValidationDispatch({ formValidationDispatch({
@ -672,7 +676,7 @@ function SelectTag(props: InputFiledByTypeProps) {
aria-invalid={displayableErrors.length !== 0} aria-invalid={displayableErrors.length !== 0}
disabled={attribute.readOnly} disabled={attribute.readOnly}
multiple={isMultiple} multiple={isMultiple}
size={attribute.annotations.inputTypeSize === undefined ? undefined : parseInt(attribute.annotations.inputTypeSize)} size={attribute.annotations.inputTypeSize === undefined ? undefined : parseInt(`${attribute.annotations.inputTypeSize}`)}
value={valueOrValues} value={valueOrValues}
onChange={event => onChange={event =>
formValidationDispatch({ formValidationDispatch({

View File

@ -556,18 +556,18 @@ export type Attribute = {
validators: Validators; validators: Validators;
annotations: { annotations: {
inputType?: string; inputType?: string;
inputTypeSize?: `${number}`; inputTypeSize?: `${number}` | number;
inputOptionsFromValidation?: string; inputOptionsFromValidation?: string;
inputOptionLabels?: Record<string, string | undefined>; inputOptionLabels?: Record<string, string | undefined>;
inputOptionLabelsI18nPrefix?: string; inputOptionLabelsI18nPrefix?: string;
inputTypeCols?: `${number}`; inputTypeCols?: `${number}` | number;
inputTypeRows?: `${number}`; inputTypeRows?: `${number}` | number;
inputTypeMaxlength?: `${number}`; inputTypeMaxlength?: `${number}` | number;
inputHelperTextBefore?: string; inputHelperTextBefore?: string;
inputHelperTextAfter?: string; inputHelperTextAfter?: string;
inputTypePlaceholder?: string; inputTypePlaceholder?: string;
inputTypePattern?: string; inputTypePattern?: string;
inputTypeMinlength?: `${number}`; inputTypeMinlength?: `${number}` | number;
inputTypeMax?: string; inputTypeMax?: string;
inputTypeMin?: string; inputTypeMin?: string;
inputTypeStep?: string; inputTypeStep?: string;
@ -666,9 +666,8 @@ export declare namespace Validators {
}; };
export type Range = { export type Range = {
/** "0", "1", "2"... yeah I know, don't tell me */ min?: `${number}` | number;
min?: `${number}`; max?: `${number}` | number;
max?: `${number}`;
}; };
export type Options = { export type Options = {
options: string[]; options: string[];
@ -688,15 +687,15 @@ export declare namespace Validators {
export type PasswordPolicies = { export type PasswordPolicies = {
/** The minimum length of the password */ /** The minimum length of the password */
length?: `${number}`; length?: number;
/** The minimum number of digits required in the password */ /** The minimum number of digits required in the password */
digits?: `${number}`; digits?: number;
/** The minimum number of lowercase characters required in the password */ /** The minimum number of lowercase characters required in the password */
lowerCase?: `${number}`; lowerCase?: number;
/** The minimum number of uppercase characters required in the password */ /** The minimum number of uppercase characters required in the password */
upperCase?: `${number}`; upperCase?: number;
/** The minimum number of special characters required in the password */ /** The minimum number of special characters required in the password */
specialChars?: `${number}`; specialChars?: number;
/** Whether the password can be the username */ /** Whether the password can be the username */
notUsername?: boolean; notUsername?: boolean;
/** Whether the password can be the email address */ /** Whether the password can be the email address */

View File

@ -315,7 +315,7 @@ export function useUserProfileForm(params: ParamsOfUseUserProfileForm): ReturnTy
break apply_validator_min_range; break apply_validator_min_range;
} }
const min = parseInt(minStr); const min = parseInt(`${minStr}`);
for (let index = values.length; index < min; index++) { for (let index = values.length; index < min; index++) {
values.push(""); values.push("");
@ -674,13 +674,13 @@ function useGetErrors(params: { kcContext: Pick<KcContextLike, "messagesPerField
const { min: minStr } = validator; const { min: minStr } = validator;
const min = minStr !== undefined ? parseInt(minStr) : attribute.required ? 1 : 0; const min = minStr !== undefined ? parseInt(`${minStr}`) : attribute.required ? 1 : 0;
assert(!isNaN(min)); assert(!isNaN(min));
const { max: maxStr } = validator; const { max: maxStr } = validator;
const max = maxStr === undefined ? Infinity : parseInt(maxStr); const max = maxStr === undefined ? Infinity : parseInt(`${maxStr}`);
assert(!isNaN(max)); assert(!isNaN(max));
@ -731,9 +731,7 @@ function useGetErrors(params: { kcContext: Pick<KcContextLike, "messagesPerField
break check_password_policy_x; break check_password_policy_x;
} }
const minLength = parseInt(policy); const minLength = policy;
assert(!isNaN(minLength));
if (value.length >= minLength) { if (value.length >= minLength) {
break check_password_policy_x; break check_password_policy_x;
@ -761,9 +759,7 @@ function useGetErrors(params: { kcContext: Pick<KcContextLike, "messagesPerField
break check_password_policy_x; break check_password_policy_x;
} }
const minNumberOfDigits = parseInt(policy); const minNumberOfDigits = policy;
assert(!isNaN(minNumberOfDigits));
if (value.split("").filter(char => !isNaN(parseInt(char))).length >= minNumberOfDigits) { if (value.split("").filter(char => !isNaN(parseInt(char))).length >= minNumberOfDigits) {
break check_password_policy_x; break check_password_policy_x;
@ -791,9 +787,7 @@ function useGetErrors(params: { kcContext: Pick<KcContextLike, "messagesPerField
break check_password_policy_x; break check_password_policy_x;
} }
const minNumberOfLowerCaseChar = parseInt(policy); const minNumberOfLowerCaseChar = policy;
assert(!isNaN(minNumberOfLowerCaseChar));
if ( if (
value.split("").filter(char => char === char.toLowerCase() && char !== char.toUpperCase()).length >= minNumberOfLowerCaseChar value.split("").filter(char => char === char.toLowerCase() && char !== char.toUpperCase()).length >= minNumberOfLowerCaseChar
@ -823,9 +817,7 @@ function useGetErrors(params: { kcContext: Pick<KcContextLike, "messagesPerField
break check_password_policy_x; break check_password_policy_x;
} }
const minNumberOfUpperCaseChar = parseInt(policy); const minNumberOfUpperCaseChar = policy;
assert(!isNaN(minNumberOfUpperCaseChar));
if ( if (
value.split("").filter(char => char === char.toUpperCase() && char !== char.toLowerCase()).length >= minNumberOfUpperCaseChar value.split("").filter(char => char === char.toUpperCase() && char !== char.toLowerCase()).length >= minNumberOfUpperCaseChar
@ -855,9 +847,7 @@ function useGetErrors(params: { kcContext: Pick<KcContextLike, "messagesPerField
break check_password_policy_x; break check_password_policy_x;
} }
const minNumberOfSpecialChar = parseInt(policy); const minNumberOfSpecialChar = policy;
assert(!isNaN(minNumberOfSpecialChar));
if (value.split("").filter(char => !char.match(/[a-zA-Z0-9]/)).length >= minNumberOfSpecialChar) { if (value.split("").filter(char => !char.match(/[a-zA-Z0-9]/)).length >= minNumberOfSpecialChar) {
break check_password_policy_x; break check_password_policy_x;
@ -1041,8 +1031,8 @@ function useGetErrors(params: { kcContext: Pick<KcContextLike, "messagesPerField
"name": validatorName "name": validatorName
}; };
if (max !== undefined && value.length > parseInt(max)) { if (max !== undefined && value.length > parseInt(`${max}`)) {
const msgArgs = ["error-invalid-length-too-long", max] as const; const msgArgs = ["error-invalid-length-too-long", `${max}`] as const;
errors.push({ errors.push({
"errorMessage": <Fragment key={`${attributeName}-${errors.length}`}>{msg(...msgArgs)}</Fragment>, "errorMessage": <Fragment key={`${attributeName}-${errors.length}`}>{msg(...msgArgs)}</Fragment>,
@ -1052,8 +1042,8 @@ function useGetErrors(params: { kcContext: Pick<KcContextLike, "messagesPerField
}); });
} }
if (min !== undefined && value.length < parseInt(min)) { if (min !== undefined && value.length < parseInt(`${min}`)) {
const msgArgs = ["error-invalid-length-too-short", min] as const; const msgArgs = ["error-invalid-length-too-short", `${min}`] as const;
errors.push({ errors.push({
"errorMessage": <Fragment key={`${attributeName}-${errors.length}`}>{msg(...msgArgs)}</Fragment>, "errorMessage": <Fragment key={`${attributeName}-${errors.length}`}>{msg(...msgArgs)}</Fragment>,
@ -1170,8 +1160,8 @@ function useGetErrors(params: { kcContext: Pick<KcContextLike, "messagesPerField
break validator_x; break validator_x;
} }
if (max !== undefined && intValue > parseInt(max)) { if (max !== undefined && intValue > parseInt(`${max}`)) {
const msgArgs = ["error-number-out-of-range-too-big", max] as const; const msgArgs = ["error-number-out-of-range-too-big", `${max}`] as const;
errors.push({ errors.push({
"errorMessage": <Fragment key={`${attributeName}-${errors.length}`}>{msg(...msgArgs)}</Fragment>, "errorMessage": <Fragment key={`${attributeName}-${errors.length}`}>{msg(...msgArgs)}</Fragment>,
@ -1183,8 +1173,8 @@ function useGetErrors(params: { kcContext: Pick<KcContextLike, "messagesPerField
break validator_x; break validator_x;
} }
if (min !== undefined && intValue < parseInt(min)) { if (min !== undefined && intValue < parseInt(`${min}`)) {
const msgArgs = ["error-number-out-of-range-too-small", min] as const; const msgArgs = ["error-number-out-of-range-too-small", `${min}`] as const;
errors.push({ errors.push({
"errorMessage": <Fragment key={`${attributeName}-${errors.length}`}>{msg(...msgArgs)}</Fragment>, "errorMessage": <Fragment key={`${attributeName}-${errors.length}`}>{msg(...msgArgs)}</Fragment>,