From cf42f5b2a0780b4dc790135163bc89291833dd90 Mon Sep 17 00:00:00 2001 From: Joseph Garrone Date: Mon, 22 Apr 2024 04:34:54 +0200 Subject: [PATCH] do not use custom validator to check if password confirmation matches password --- src/login/kcContext/KcContext.ts | 6 -- src/login/lib/useUserProfileForm.tsx | 110 +++++++++++---------------- 2 files changed, 43 insertions(+), 73 deletions(-) diff --git a/src/login/kcContext/KcContext.ts b/src/login/kcContext/KcContext.ts index 95e793cf..714e45be 100644 --- a/src/login/kcContext/KcContext.ts +++ b/src/login/kcContext/KcContext.ts @@ -624,12 +624,6 @@ export type Validators = Partial<{ "person-name-prohibited-characters": Validators.DoIgnoreEmpty & Validators.ErrorMessage; uri: Validators.DoIgnoreEmpty; "username-prohibited-characters": Validators.DoIgnoreEmpty & Validators.ErrorMessage; - /** Made up validator that only exists in Keycloakify */ - _compareToOther: Validators.DoIgnoreEmpty & - Validators.ErrorMessage & { - name: string; - shouldBe: "equal" | "different"; - }; options: Validators.Options; multivalued: Validators.DoIgnoreEmpty & Validators.Range; }>; diff --git a/src/login/lib/useUserProfileForm.tsx b/src/login/lib/useUserProfileForm.tsx index f21240a1..2d0125f6 100644 --- a/src/login/lib/useUserProfileForm.tsx +++ b/src/login/lib/useUserProfileForm.tsx @@ -59,8 +59,8 @@ export type KcContextLike = { export type ParamsOfUseUserProfileForm = { kcContext: KcContextLike; passwordValidators?: Validators; - requirePasswordConfirmation?: boolean; i18n: I18n; + passwordConfirmationDisabled?: boolean; }; export type ReturnTypeOfUseUserProfileForm = { @@ -74,7 +74,7 @@ export type ReturnTypeOfUseUserProfileForm = { * artificial password related attributes only if kcContext.passwordRequired === true */ export function useUserProfileForm(params: ParamsOfUseUserProfileForm): ReturnTypeOfUseUserProfileForm { - const { kcContext, passwordValidators = {}, i18n } = params; + const { kcContext, passwordValidators = {}, i18n, passwordConfirmationDisabled = false } = params; const attributesWithPassword = useMemo(() => { const attributesWithPassword: Attribute[] = []; @@ -107,14 +107,7 @@ export function useUserProfileForm(params: ParamsOfUseUserProfileForm): ReturnTy "displayName": id<`\${${MessageKey}}`>("${passwordConfirm}"), "required": true, "readOnly": false, - "validators": { - "_compareToOther": { - "name": "password", - "ignore.empty.value": true, - "shouldBe": "equal", - "error-message": id<`\${${MessageKey}}`>("${invalidPasswordConfirmMessage}") - } - }, + "validators": {}, "annotations": {}, "html5DataAnnotations": {}, "autocomplete": "new-password", @@ -142,7 +135,7 @@ export function useUserProfileForm(params: ParamsOfUseUserProfileForm): ReturnTy type State = FormFieldState_internal[]; const [state, dispatchFormAction] = useReducer( - (state: State, params: FormAction): State => { + function reducer(state: State, params: FormAction): State { if (params.action === "add value to multi-valued attribute") { const formFieldStates = state.filter(({ name }) => name === params.name); @@ -170,6 +163,23 @@ export function useUserProfileForm(params: ParamsOfUseUserProfileForm): ReturnTy formFieldState.hasLostFocusAtLeastOnce = true; return state; case "update value": + update_password_confirm: { + if (params.name !== "password") { + break update_password_confirm; + } + + if (!passwordConfirmationDisabled) { + break update_password_confirm; + } + + state = reducer(state, { + "action": "update value", + "name": "password-confirm", + "index": 0, + "newValue": params.newValue + }); + } + formFieldState.value = params.newValue; formFieldState.errors = getErrors({ "name": params.name, @@ -336,6 +346,28 @@ function useGetErrors(params: { const errors: FormFieldError[] = []; + password_confirm_matches_password: { + if (name !== "password-confirm") { + break password_confirm_matches_password; + } + + const passwordFieldValue = fieldValues.find(fieldValue => fieldValue.name === "password"); + + assert(passwordFieldValue !== undefined); + + if (passwordFieldValue.value === value) { + break password_confirm_matches_password; + } + + const msgArgs = ["invalidPasswordConfirmMessage"] as const; + + errors.push({ + "validatorName": undefined, + "errorMessage": {msg(...msgArgs)}, + "errorMessageStr": msgStr(...msgArgs) + }); + } + const { validators } = attribute; required_field: { @@ -392,62 +424,6 @@ function useGetErrors(params: { } } - validator_x: { - const validatorName = "_compareToOther"; - - const validator = validators[validatorName]; - - if (validator === undefined) { - break validator_x; - } - - const { "ignore.empty.value": ignoreEmptyValue = false, name: otherName, shouldBe, "error-message": errorMessageKey } = validator; - - if (ignoreEmptyValue && value === "") { - break validator_x; - } - - const otherFieldValue = fieldValues.find(fieldValue => fieldValue.name === otherName); - - assert(otherFieldValue !== undefined); - - const isValid = (() => { - switch (shouldBe) { - case "different": - return otherFieldValue.value !== value; - case "equal": - return otherFieldValue.value === value; - } - })(); - - if (isValid) { - break validator_x; - } - - const msgArg = [ - errorMessageKey ?? - id( - (() => { - switch (shouldBe) { - case "equal": - return "shouldBeEqual"; - case "different": - return "shouldBeDifferent"; - } - })() - ), - otherName, - name, - shouldBe - ] as const; - - errors.push({ - validatorName, - "errorMessage": {advancedMsg(...msgArg)}, - "errorMessageStr": advancedMsgStr(...msgArg) - }); - } - validator_x: { const validatorName = "pattern";