UNPKG

keycloakify

Version:

Framework to create custom Keycloak UIs

1,126 lines 46 kB
var __rest = (this && this.__rest) || function (s, e) { var t = {}; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p]; if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]]; } return t; }; import "../../../tools/Array.prototype.every"; import { assert } from "tsafe/assert"; import { formatNumber } from "../../../tools/formatNumber"; import { emailRegexp } from "../../../tools/emailRegExp"; import { unFormatNumberOnSubmit } from "./kcNumberUnFormat"; import { structuredCloneButFunctions } from "../../../tools/structuredCloneButFunctions"; import { id } from "tsafe/id"; assert(); const cachedUserProfileApiByKcContext = new WeakMap(); export function getUserProfileApi(params) { const { kcContext } = params; use_cache: { const userProfileApi_cache = cachedUserProfileApiByKcContext.get(kcContext); if (userProfileApi_cache === undefined) { break use_cache; } return userProfileApi_cache; } const userProfileApi = getUserProfileApi_noCache(params); cachedUserProfileApiByKcContext.set(kcContext, userProfileApi); return userProfileApi; } function getUserProfileApi_noCache(params) { const { kcContext, doMakeUserConfirmPassword } = params; unFormatNumberOnSubmit(); let state = getInitialState({ kcContext }); const callbacks = new Set(); return { dispatchFormAction: action => { state = reducer({ action, kcContext, doMakeUserConfirmPassword, state }); callbacks.forEach(callback => callback()); }, getFormState: () => formStateSelector({ state }), subscribeToFormState: callback => { callbacks.add(callback); return { unsubscribe: () => { callbacks.delete(callback); } }; } }; } function getInitialState(params) { var _a, _b; const { kcContext } = params; const { getErrors } = createGetErrors({ kcContext }); // NOTE: We don't use te kcContext.profile.attributes directly because // they don't includes the password and password confirm fields and we want to add them. // We also want to apply some retro-compatibility and consistency patches. const attributes = (() => { var _a; mock_user_profile_attributes_for_older_keycloak_versions: { if ("profile" in kcContext && "attributesByName" in kcContext.profile && Object.keys(kcContext.profile.attributesByName).length !== 0) { break mock_user_profile_attributes_for_older_keycloak_versions; } if ("register" in kcContext && kcContext.register instanceof Object && "formData" in kcContext.register) { //NOTE: Handle legacy register.ftl page return ["firstName", "lastName", "email", "username"] .filter(name => name !== "username" ? true : !kcContext.realm.registrationEmailAsUsername) .map(name => { var _a; return id({ name: name, displayName: id(`\${${name}}`), required: true, value: (_a = kcContext.register.formData[name]) !== null && _a !== void 0 ? _a : "", html5DataAnnotations: {}, readOnly: false, validators: {}, annotations: {}, autocomplete: (() => { switch (name) { case "email": return "email"; case "username": return "username"; default: return undefined; } })() }); }); } if ("user" in kcContext && kcContext.user instanceof Object) { //NOTE: Handle legacy login-update-profile.ftl return ["username", "email", "firstName", "lastName"] .filter(name => name !== "username" ? true : kcContext.user.editUsernameAllowed) .map(name => { var _a; return id({ name: name, displayName: id(`\${${name}}`), required: true, value: (_a = kcContext.user[name]) !== null && _a !== void 0 ? _a : "", html5DataAnnotations: {}, readOnly: false, validators: {}, annotations: {}, autocomplete: (() => { switch (name) { case "email": return "email"; case "username": return "username"; default: return undefined; } })() }); }); } if ("email" in kcContext && kcContext.email instanceof Object) { //NOTE: Handle legacy update-email.ftl return [ id({ name: "email", displayName: id(`\${email}`), required: true, value: (_a = kcContext.email.value) !== null && _a !== void 0 ? _a : "", html5DataAnnotations: {}, readOnly: false, validators: {}, annotations: {}, autocomplete: "email" }) ]; } assert(false, "Unable to mock user profile from the current kcContext"); } return Object.values(kcContext.profile.attributesByName).map(structuredCloneButFunctions); })(); /* See: https://github.com/keycloak/keycloak/issues/38029 and https://github.com/keycloakify/keycloakify/issues/837 */ add_locale_attribute_for_keycloak_prior_to_26_2_0: { if (kcContext.locale === undefined) { break add_locale_attribute_for_keycloak_prior_to_26_2_0; } if (attributes.find(attribute => attribute.name === "locale") !== undefined) { break add_locale_attribute_for_keycloak_prior_to_26_2_0; } attributes.push(id({ validators: {}, displayName: "locale", values: [], annotations: {}, required: false, html5DataAnnotations: {}, multivalued: false, readOnly: false, name: "locale" })); } // Retro-compatibility and consistency patches attributes.forEach(attribute => { var _a, _b, _c; if (attribute.name === "locale") { assert(kcContext.locale !== undefined); attribute.annotations.inputType = "hidden"; attribute.value = kcContext.locale.currentLanguageTag; delete attribute.values; } patch_legacy_group: { if (typeof attribute.group !== "string") { break patch_legacy_group; } const { group, groupDisplayHeader, groupDisplayDescription, groupAnnotations } = attribute; delete attribute.group; // @ts-expect-error delete attribute.groupDisplayHeader; // @ts-expect-error delete attribute.groupDisplayDescription; // @ts-expect-error delete attribute.groupAnnotations; if (group === "") { break patch_legacy_group; } attribute.group = { name: group, displayHeader: groupDisplayHeader, displayDescription: groupDisplayDescription, annotations: groupAnnotations, html5DataAnnotations: {} }; } // Attributes with options rendered by default as select inputs if (attribute.validators.options !== undefined && attribute.annotations.inputType === undefined) { attribute.annotations.inputType = "select"; } // Consistency patch on values/value property { if (getIsMultivaluedSingleField({ attribute })) { attribute.multivalued = true; } if (attribute.multivalued) { (_a = attribute.values) !== null && _a !== void 0 ? _a : (attribute.values = attribute.value !== undefined ? [attribute.value] : []); delete attribute.value; } else { (_b = attribute.value) !== null && _b !== void 0 ? _b : (attribute.value = (_c = attribute.values) === null || _c === void 0 ? void 0 : _c[0]); delete attribute.values; } } }); add_password_and_password_confirm: { if (!kcContext.passwordRequired) { break add_password_and_password_confirm; } attributes.forEach((attribute, i) => { if (attribute.name !== (kcContext.realm.registrationEmailAsUsername ? "email" : "username")) { // NOTE: We want to add password and password-confirm after the field that identifies the user. // It's either email or username. return; } attributes.splice(i + 1, 0, { name: "password", displayName: id("${password}"), required: true, readOnly: false, validators: {}, annotations: {}, autocomplete: "new-password", html5DataAnnotations: {} }, { name: "password-confirm", displayName: id("${passwordConfirm}"), required: true, readOnly: false, validators: {}, annotations: {}, html5DataAnnotations: {}, autocomplete: "new-password" }); }); } const initialFormFieldState = []; for (const attribute of attributes) { handle_multi_valued_attribute: { if (!attribute.multivalued) { break handle_multi_valued_attribute; } const values = ((_a = attribute.values) === null || _a === void 0 ? void 0 : _a.length) ? attribute.values : [""]; apply_validator_min_range: { if (getIsMultivaluedSingleField({ attribute })) { break apply_validator_min_range; } const validator = attribute.validators.multivalued; if (validator === undefined) { break apply_validator_min_range; } const { min: minStr } = validator; if (!minStr) { break apply_validator_min_range; } const min = parseInt(`${minStr}`); for (let index = values.length; index < min; index++) { values.push(""); } } initialFormFieldState.push({ attribute, valueOrValues: values }); continue; } initialFormFieldState.push({ attribute, valueOrValues: (_b = attribute.value) !== null && _b !== void 0 ? _b : "" }); } const initialState = { formFieldStates: initialFormFieldState.map(({ attribute, valueOrValues }) => ({ attribute, errors: getErrors({ attributeName: attribute.name, formFieldStates: initialFormFieldState }), hasLostFocusAtLeastOnce: valueOrValues instanceof Array && !getIsMultivaluedSingleField({ attribute }) ? valueOrValues.map(() => false) : false, valueOrValues: valueOrValues })) }; return initialState; } const formStateByState = new WeakMap(); function formStateSelector(params) { const { state } = params; use_memoized_value: { const formState = formStateByState.get(state); if (formState === undefined) { break use_memoized_value; } return formState; } return { formFieldStates: state.formFieldStates.map((_a) => { var { errors, hasLostFocusAtLeastOnce: hasLostFocusAtLeastOnceOrArr, attribute } = _a, valueOrValuesWrap = __rest(_a, ["errors", "hasLostFocusAtLeastOnce", "attribute"]); return (Object.assign({ displayableErrors: errors.filter(error => { const hasLostFocusAtLeastOnce = typeof hasLostFocusAtLeastOnceOrArr === "boolean" ? hasLostFocusAtLeastOnceOrArr : error.fieldIndex !== undefined ? hasLostFocusAtLeastOnceOrArr[error.fieldIndex] : hasLostFocusAtLeastOnceOrArr[hasLostFocusAtLeastOnceOrArr.length - 1]; switch (error.source.type) { case "server": return true; case "other": switch (error.source.rule) { case "requiredField": return hasLostFocusAtLeastOnce; case "passwordConfirmMatchesPassword": return hasLostFocusAtLeastOnce; } assert(false); case "passwordPolicy": switch (error.source.name) { case "length": return hasLostFocusAtLeastOnce; case "maxLength": return hasLostFocusAtLeastOnce; case "digits": return hasLostFocusAtLeastOnce; case "lowerCase": return hasLostFocusAtLeastOnce; case "upperCase": return hasLostFocusAtLeastOnce; case "specialChars": return hasLostFocusAtLeastOnce; case "notUsername": return true; case "notEmail": return true; } assert(false); case "validator": switch (error.source.name) { case "length": return hasLostFocusAtLeastOnce; case "pattern": return hasLostFocusAtLeastOnce; case "email": return hasLostFocusAtLeastOnce; case "integer": return hasLostFocusAtLeastOnce; case "multivalued": return hasLostFocusAtLeastOnce; case "options": return hasLostFocusAtLeastOnce; } assert(false); } }), attribute }, valueOrValuesWrap)); }), isFormSubmittable: state.formFieldStates.every(({ errors }) => errors.length === 0) }; } function reducer(params) { const { kcContext, doMakeUserConfirmPassword, action } = params; let { state } = params; const { getErrors } = createGetErrors({ kcContext }); const formFieldState = state.formFieldStates.find(({ attribute }) => attribute.name === action.name); assert(formFieldState !== undefined); (() => { var _a; switch (action.action) { case "update": formFieldState.valueOrValues = action.valueOrValues; apply_formatters: { const { attribute } = formFieldState; const { kcNumberFormat } = (_a = attribute.html5DataAnnotations) !== null && _a !== void 0 ? _a : {}; if (!kcNumberFormat) { break apply_formatters; } if (formFieldState.valueOrValues instanceof Array) { formFieldState.valueOrValues = formFieldState.valueOrValues.map(value => formatNumber(value, kcNumberFormat)); } else { formFieldState.valueOrValues = formatNumber(formFieldState.valueOrValues, kcNumberFormat); } } formFieldState.errors = getErrors({ attributeName: action.name, formFieldStates: state.formFieldStates }); simulate_focus_lost: { const { displayErrorsImmediately = false } = action; if (!displayErrorsImmediately) { break simulate_focus_lost; } for (const fieldIndex of action.valueOrValues instanceof Array ? action.valueOrValues.map((...[, index]) => index) : [undefined]) { state = reducer({ state, kcContext, doMakeUserConfirmPassword, action: { action: "focus lost", name: action.name, fieldIndex } }); } } update_password_confirm: { if (doMakeUserConfirmPassword) { break update_password_confirm; } if (action.name !== "password") { break update_password_confirm; } state = reducer({ state, kcContext, doMakeUserConfirmPassword, action: { action: "update", name: "password-confirm", valueOrValues: action.valueOrValues, displayErrorsImmediately: action.displayErrorsImmediately } }); } trigger_password_confirm_validation_on_password_change: { if (!doMakeUserConfirmPassword) { break trigger_password_confirm_validation_on_password_change; } if (action.name !== "password") { break trigger_password_confirm_validation_on_password_change; } state = reducer({ state, kcContext, doMakeUserConfirmPassword, action: { action: "update", name: "password-confirm", valueOrValues: (() => { const formFieldState = state.formFieldStates.find(({ attribute }) => attribute.name === "password-confirm"); assert(formFieldState !== undefined); return formFieldState.valueOrValues; })(), displayErrorsImmediately: action.displayErrorsImmediately } }); } return; case "focus lost": if (formFieldState.hasLostFocusAtLeastOnce instanceof Array) { const { fieldIndex } = action; assert(fieldIndex !== undefined); formFieldState.hasLostFocusAtLeastOnce[fieldIndex] = true; return; } formFieldState.hasLostFocusAtLeastOnce = true; return; } assert(false); })(); return Object.assign({}, state); } function createGetErrors(params) { const { kcContext } = params; const { messagesPerField, passwordPolicies } = kcContext; function getErrors(params) { var _a, _b; const { attributeName, formFieldStates } = params; const formFieldState = formFieldStates.find(({ attribute }) => attribute.name === attributeName); assert(formFieldState !== undefined); const { attribute } = formFieldState; const valueOrValues = (() => { var _a; let { valueOrValues } = formFieldState; unFormat_number: { const { kcNumberUnFormat } = (_a = attribute.html5DataAnnotations) !== null && _a !== void 0 ? _a : {}; if (!kcNumberUnFormat) { break unFormat_number; } if (valueOrValues instanceof Array) { valueOrValues = valueOrValues.map(value => formatNumber(value, kcNumberUnFormat)); } else { valueOrValues = formatNumber(valueOrValues, kcNumberUnFormat); } } return valueOrValues; })(); assert(attribute !== undefined); server_side_error: { if (attribute.multivalued) { const defaultValues = ((_a = attribute.values) === null || _a === void 0 ? void 0 : _a.length) ? attribute.values : [""]; assert(valueOrValues instanceof Array); const values = valueOrValues; if (JSON.stringify(defaultValues) !== JSON.stringify(values.slice(0, defaultValues.length))) { break server_side_error; } } else { const defaultValue = (_b = attribute.value) !== null && _b !== void 0 ? _b : ""; assert(typeof valueOrValues === "string"); const value = valueOrValues; if (defaultValue !== value) { break server_side_error; } } let doesErrorExist; try { doesErrorExist = messagesPerField.existsError(attributeName); } catch (_c) { break server_side_error; } if (!doesErrorExist) { break server_side_error; } const errorMessageStr = messagesPerField.get(attributeName); return [ { advancedMsgArgs: [errorMessageStr], fieldIndex: undefined, source: { type: "server" } } ]; } handle_multi_valued_multi_fields: { if (!attribute.multivalued) { break handle_multi_valued_multi_fields; } if (getIsMultivaluedSingleField({ attribute })) { break handle_multi_valued_multi_fields; } assert(valueOrValues instanceof Array); const values = valueOrValues; const errors = values .map((...[, index]) => { const specificValueErrors = getErrors({ attributeName, formFieldStates: formFieldStates.map(formFieldState => { if (formFieldState.attribute.name === attributeName) { assert(formFieldState.valueOrValues instanceof Array); return { attribute: Object.assign(Object.assign({}, attribute), { annotations: Object.assign(Object.assign({}, attribute.annotations), { inputType: undefined }), multivalued: false }), valueOrValues: formFieldState.valueOrValues[index] }; } return formFieldState; }) }); return specificValueErrors .filter(error => { if (error.source.type === "other" && error.source.rule === "requiredField") { return false; } return true; }) .map((error) => (Object.assign(Object.assign({}, error), { fieldIndex: index }))); }) .reduce((acc, errors) => [...acc, ...errors], []); required_field: { if (!attribute.required) { break required_field; } if (values.every(value => value !== "")) { break required_field; } errors.push({ advancedMsgArgs: [ "error-user-attribute-required" ], fieldIndex: undefined, source: { type: "other", rule: "requiredField" } }); } return errors; } handle_multi_valued_single_field: { if (!attribute.multivalued) { break handle_multi_valued_single_field; } if (!getIsMultivaluedSingleField({ attribute })) { break handle_multi_valued_single_field; } const validatorName = "multivalued"; const validator = attribute.validators[validatorName]; if (validator === undefined) { return []; } const { min: minStr } = validator; const min = minStr ? parseInt(`${minStr}`) : attribute.required ? 1 : 0; assert(!isNaN(min)); const { max: maxStr } = validator; const max = !maxStr ? Infinity : parseInt(`${maxStr}`); assert(!isNaN(max)); assert(valueOrValues instanceof Array); const values = valueOrValues; if (min <= values.length && values.length <= max) { return []; } return [ { advancedMsgArgs: [ "error-invalid-multivalued-size", `${min}`, `${max}` ], fieldIndex: undefined, source: { type: "validator", name: validatorName } } ]; } assert(typeof valueOrValues === "string"); const value = valueOrValues; const errors = []; check_password_policies: { if (attributeName !== "password") { break check_password_policies; } if (passwordPolicies === undefined) { break check_password_policies; } check_password_policy_x: { const policyName = "length"; const policy = passwordPolicies[policyName]; if (!policy) { break check_password_policy_x; } const minLength = policy; if (value.length >= minLength) { break check_password_policy_x; } errors.push({ advancedMsgArgs: [ "invalidPasswordMinLengthMessage", `${minLength}` ], fieldIndex: undefined, source: { type: "passwordPolicy", name: policyName } }); } check_password_policy_x: { const policyName = "maxLength"; const policy = passwordPolicies[policyName]; if (!policy) { break check_password_policy_x; } const maxLength = policy; if (value.length <= maxLength) { break check_password_policy_x; } errors.push({ advancedMsgArgs: [ "invalidPasswordMaxLengthMessage", `${maxLength}` ], fieldIndex: undefined, source: { type: "passwordPolicy", name: policyName } }); } check_password_policy_x: { const policyName = "digits"; const policy = passwordPolicies[policyName]; if (!policy) { break check_password_policy_x; } const minNumberOfDigits = policy; if (value.split("").filter(char => !isNaN(parseInt(char))).length >= minNumberOfDigits) { break check_password_policy_x; } errors.push({ advancedMsgArgs: [ "invalidPasswordMinDigitsMessage", `${minNumberOfDigits}` ], fieldIndex: undefined, source: { type: "passwordPolicy", name: policyName } }); } check_password_policy_x: { const policyName = "lowerCase"; const policy = passwordPolicies[policyName]; if (!policy) { break check_password_policy_x; } const minNumberOfLowerCaseChar = policy; if (value .split("") .filter(char => char === char.toLowerCase() && char !== char.toUpperCase()).length >= minNumberOfLowerCaseChar) { break check_password_policy_x; } errors.push({ advancedMsgArgs: [ "invalidPasswordMinLowerCaseCharsMessage", `${minNumberOfLowerCaseChar}` ], fieldIndex: undefined, source: { type: "passwordPolicy", name: policyName } }); } check_password_policy_x: { const policyName = "upperCase"; const policy = passwordPolicies[policyName]; if (!policy) { break check_password_policy_x; } const minNumberOfUpperCaseChar = policy; if (value .split("") .filter(char => char === char.toUpperCase() && char !== char.toLowerCase()).length >= minNumberOfUpperCaseChar) { break check_password_policy_x; } errors.push({ advancedMsgArgs: [ "invalidPasswordMinUpperCaseCharsMessage", `${minNumberOfUpperCaseChar}` ], fieldIndex: undefined, source: { type: "passwordPolicy", name: policyName } }); } check_password_policy_x: { const policyName = "specialChars"; const policy = passwordPolicies[policyName]; if (!policy) { break check_password_policy_x; } const minNumberOfSpecialChar = policy; if (value.split("").filter(char => !char.match(/[a-zA-Z0-9]/)).length >= minNumberOfSpecialChar) { break check_password_policy_x; } errors.push({ advancedMsgArgs: [ "invalidPasswordMinSpecialCharsMessage", `${minNumberOfSpecialChar}` ], fieldIndex: undefined, source: { type: "passwordPolicy", name: policyName } }); } check_password_policy_x: { const policyName = "notUsername"; const notUsername = passwordPolicies[policyName]; if (!notUsername) { break check_password_policy_x; } const usernameFormFieldState = formFieldStates.find(formFieldState => formFieldState.attribute.name === "username"); if (!usernameFormFieldState) { break check_password_policy_x; } const usernameValue = (() => { var _a; let { valueOrValues } = usernameFormFieldState; assert(typeof valueOrValues === "string"); unFormat_number: { const { kcNumberUnFormat } = (_a = usernameFormFieldState.attribute.html5DataAnnotations) !== null && _a !== void 0 ? _a : {}; if (!kcNumberUnFormat) { break unFormat_number; } valueOrValues = formatNumber(valueOrValues, kcNumberUnFormat); } return valueOrValues; })(); if (usernameValue === "") { break check_password_policy_x; } if (value !== usernameValue) { break check_password_policy_x; } errors.push({ advancedMsgArgs: [ "invalidPasswordNotUsernameMessage" ], fieldIndex: undefined, source: { type: "passwordPolicy", name: policyName } }); } check_password_policy_x: { const policyName = "notEmail"; const notEmail = passwordPolicies[policyName]; if (!notEmail) { break check_password_policy_x; } const emailFormFieldState = formFieldStates.find(formFieldState => formFieldState.attribute.name === "email"); if (!emailFormFieldState) { break check_password_policy_x; } assert(typeof emailFormFieldState.valueOrValues === "string"); { const emailValue = emailFormFieldState.valueOrValues; if (emailValue === "") { break check_password_policy_x; } if (value !== emailValue) { break check_password_policy_x; } } errors.push({ advancedMsgArgs: [ "invalidPasswordNotEmailMessage" ], fieldIndex: undefined, source: { type: "passwordPolicy", name: policyName } }); } } password_confirm_matches_password: { if (attributeName !== "password-confirm") { break password_confirm_matches_password; } const passwordFormFieldState = formFieldStates.find(formFieldState => formFieldState.attribute.name === "password"); assert(passwordFormFieldState !== undefined); assert(typeof passwordFormFieldState.valueOrValues === "string"); { const passwordValue = passwordFormFieldState.valueOrValues; if (value === passwordValue) { break password_confirm_matches_password; } } errors.push({ advancedMsgArgs: [ "invalidPasswordConfirmMessage" ], fieldIndex: undefined, source: { type: "other", rule: "passwordConfirmMatchesPassword" } }); } const { validators } = attribute; required_field: { if (!attribute.required) { break required_field; } if (value !== "") { break required_field; } errors.push({ advancedMsgArgs: [ "error-user-attribute-required" ], fieldIndex: undefined, source: { type: "other", rule: "requiredField" } }); } validator_x: { const validatorName = "length"; const validator = validators[validatorName]; if (!validator) { break validator_x; } const { "ignore.empty.value": ignoreEmptyValue = false, max, min } = validator; if (ignoreEmptyValue && value === "") { break validator_x; } const source = { type: "validator", name: validatorName }; if (max && value.length > parseInt(`${max}`)) { errors.push({ advancedMsgArgs: [ "error-invalid-length-too-long", `${max}` ], fieldIndex: undefined, source }); } if (min && value.length < parseInt(`${min}`)) { errors.push({ advancedMsgArgs: [ "error-invalid-length-too-short", `${min}` ], fieldIndex: undefined, source }); } } validator_x: { const validatorName = "pattern"; const validator = validators[validatorName]; if (validator === undefined) { break validator_x; } const { "ignore.empty.value": ignoreEmptyValue = false, pattern, "error-message": errorMessageKey } = validator; if (ignoreEmptyValue && value === "") { break validator_x; } if (new RegExp(pattern).test(value)) { break validator_x; } const msgArgs = [ errorMessageKey !== null && errorMessageKey !== void 0 ? errorMessageKey : ("shouldMatchPattern"), pattern ]; errors.push({ advancedMsgArgs: msgArgs, fieldIndex: undefined, source: { type: "validator", name: validatorName } }); } validator_x: { { const lastError = errors[errors.length - 1]; if (lastError !== undefined && lastError.source.type === "validator" && lastError.source.name === "pattern") { break validator_x; } } const validatorName = "email"; const validator = validators[validatorName]; if (validator === undefined) { break validator_x; } const { "ignore.empty.value": ignoreEmptyValue = false } = validator; if (ignoreEmptyValue && value === "") { break validator_x; } if (emailRegexp.test(value)) { break validator_x; } errors.push({ advancedMsgArgs: [ "invalidEmailMessage" ], fieldIndex: undefined, source: { type: "validator", name: validatorName } }); } validator_x: { const validatorName = "integer"; const validator = validators[validatorName]; if (validator === undefined) { break validator_x; } const { "ignore.empty.value": ignoreEmptyValue = false, max, min } = validator; if (ignoreEmptyValue && value === "") { break validator_x; } const intValue = parseInt(value); const source = { type: "validator", name: validatorName }; if (isNaN(intValue)) { const msgArgs = ["mustBeAnInteger"]; errors.push({ advancedMsgArgs: msgArgs, fieldIndex: undefined, source }); break validator_x; } if (max && intValue > parseInt(`${max}`)) { errors.push({ advancedMsgArgs: [ "error-number-out-of-range-too-big", `${max}` ], fieldIndex: undefined, source }); break validator_x; } if (min && intValue < parseInt(`${min}`)) { errors.push({ advancedMsgArgs: [ "error-number-out-of-range-too-small", `${min}` ], fieldIndex: undefined, source }); break validator_x; } } validator_x: { const validatorName = "options"; const validator = validators[validatorName]; if (validator === undefined) { break validator_x; } if (value === "") { break validator_x; } if (validator.options.indexOf(value) >= 0) { break validator_x; } errors.push({ advancedMsgArgs: [ "notAValidOption" ], fieldIndex: undefined, source: { type: "validator", name: validatorName } }); } //TODO: Implement missing validators. See Validators type definition. return errors; } return { getErrors }; } function getIsMultivaluedSingleField(params) { var _a, _b; const { attribute } = params; return (_b = (_a = attribute.annotations.inputType) === null || _a === void 0 ? void 0 : _a.startsWith("multiselect")) !== null && _b !== void 0 ? _b : false; } export function getButtonToDisplayForMultivaluedAttributeField(params) { const { attribute, values, fieldIndex } = params; const hasRemove = (() => { if (values.length === 1) { return false; } const minCount = (() => { const { multivalued } = attribute.validators; if (multivalued === undefined) { return undefined; } const minStr = multivalued.min; if (minStr === undefined) { return undefined; } return parseInt(`${minStr}`); })(); if (minCount === undefined) { return true; } if (values.length === minCount) { return false; } return true; })(); const hasAdd = (() => { if (fieldIndex + 1 !== values.length) { return false; } const maxCount = (() => { const { multivalued } = attribute.validators; if (multivalued === undefined) { return undefined; } const maxStr = multivalued.max; if (maxStr === undefined) { return undefined; } return parseInt(`${maxStr}`); })(); if (maxCount === undefined) { return true; } return values.length !== maxCount; })(); return { hasRemove, hasAdd }; } //# sourceMappingURL=getUserProfileApi.js.map