From 8b6d785c72c966c9d388ec9c5e73f1ac44923913 Mon Sep 17 00:00:00 2001 From: Ildar Kamalov Date: Wed, 5 Feb 2025 17:52:45 +0300 Subject: [PATCH] fix encryption validation --- .gitignore | 8 +- .../components/Settings/Encryption/Form.tsx | 74 +++++++++---------- .../components/Settings/Encryption/index.tsx | 40 +++++++--- .../components/ui/Controls/Checkbox/index.tsx | 7 +- 4 files changed, 74 insertions(+), 55 deletions(-) diff --git a/.gitignore b/.gitignore index 5fd6dc60..a9598645 100644 --- a/.gitignore +++ b/.gitignore @@ -19,6 +19,10 @@ /agh-backup/ /bin/ /build/* +/client/blob-report/ +/client/playwright-report/ +/client/playwright/.cache/ +/client/test-results/ /data/ /dist/ /filtering/tests/filtering.TestLotsOfRules*.pprof @@ -33,9 +37,5 @@ AdGuardHome.exe AdGuardHome.yaml* coverage.txt node_modules/ -/client/blob-report/ -/client/playwright-report/ -/client/playwright/.cache/ -/client/test-results/ !/build/gitkeep diff --git a/client/src/components/Settings/Encryption/Form.tsx b/client/src/components/Settings/Encryption/Form.tsx index 7968cc3e..be03433d 100644 --- a/client/src/components/Settings/Encryption/Form.tsx +++ b/client/src/components/Settings/Encryption/Form.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useRef } from 'react'; +import React from 'react'; import { Trans, useTranslation } from 'react-i18next'; @@ -92,19 +92,7 @@ export type EncryptionFormValues = { type Props = { initialValues: EncryptionFormValues; - processingConfig: boolean; - processingValidate: boolean; - status_key?: string; - not_after?: string; - warning_validation?: string; - valid_chain?: boolean; - valid_key?: boolean; - valid_cert?: boolean; - valid_pair?: boolean; - dns_names?: string[]; - key_type?: string; - issuer?: string; - subject?: string; + encryption: EncryptionData; onSubmit: (values: EncryptionFormValues) => void; debouncedConfigValidation: (values: EncryptionFormValues) => void; setTlsConfig: (values: Partial) => void; @@ -130,24 +118,28 @@ const defaultValues = { export const Form = ({ initialValues, - processingConfig, - processingValidate, - not_after, - valid_chain, - valid_key, - valid_cert, - valid_pair, - dns_names, - key_type, - issuer, - subject, - warning_validation, + encryption, onSubmit, setTlsConfig, + debouncedConfigValidation, validateTlsConfig, }: Props) => { const { t } = useTranslation(); - const previousValuesRef = useRef(initialValues); + + const { + not_after, + valid_chain, + valid_key, + valid_cert, + valid_pair, + dns_names, + key_type, + issuer, + subject, + warning_validation, + processingConfig, + processingValidate, + } = encryption; const { control, @@ -166,8 +158,6 @@ export const Form = ({ mode: 'onBlur', }); - const watchedValues = watch(); - const { enabled: isEnabled, serve_plain_dns: servePlainDns, @@ -178,16 +168,11 @@ export const Form = ({ private_key_saved: privateKeySaved, certificate_path: certificatePath, certificate_source: certificateSource, - } = watchedValues; + } = watch(); - useEffect(() => { - const previousValues = previousValuesRef.current; - - if (JSON.stringify(previousValues) !== JSON.stringify(watchedValues)) { - // TODO(ik) onChange TLS config validation - previousValuesRef.current = watchedValues; - } - }, [watchedValues]); + const handleBlur = () => { + debouncedConfigValidation(getValues()); + }; const isSavingDisabled = () => { const processing = isSubmitting || processingConfig || processingValidate; @@ -243,7 +228,9 @@ export const Form = ({ } + render={({ field }) => ( + + )} /> @@ -288,6 +275,7 @@ export const Form = ({ placeholder={t('encryption_server_enter')} error={fieldState.error?.message} disabled={!isEnabled} + onBlur={handleBlur} /> )} /> @@ -337,6 +325,7 @@ export const Form = ({ const { value } = e.target; field.onChange(toNumber(value)); }} + onBlur={handleBlur} /> )} /> @@ -368,6 +357,7 @@ export const Form = ({ const { value } = e.target; field.onChange(toNumber(value)); }} + onBlur={handleBlur} /> )} /> @@ -399,6 +389,7 @@ export const Form = ({ const { value } = e.target; field.onChange(toNumber(value)); }} + onBlur={handleBlur} /> )} /> @@ -457,6 +448,7 @@ export const Form = ({ placeholder={t('encryption_certificates_input')} disabled={!isEnabled} error={fieldState.error?.message} + onBlur={handleBlur} /> )} /> @@ -471,6 +463,7 @@ export const Form = ({ placeholder={t('encryption_certificate_path')} error={fieldState.error?.message} disabled={!isEnabled} + onBlur={handleBlur} /> )} /> @@ -527,6 +520,7 @@ export const Form = ({ } field.onChange(checked); }} + onBlur={handleBlur} /> )} /> @@ -540,6 +534,7 @@ export const Form = ({ placeholder={t('encryption_key_input')} disabled={!isEnabled || privateKeySaved} error={fieldState.error?.message} + onBlur={handleBlur} /> )} /> @@ -555,6 +550,7 @@ export const Form = ({ placeholder={t('encryption_private_key_path')} error={fieldState.error?.message} disabled={!isEnabled} + onBlur={handleBlur} /> )} /> diff --git a/client/src/components/Settings/Encryption/index.tsx b/client/src/components/Settings/Encryption/index.tsx index 67c99842..a8c5dcda 100644 --- a/client/src/components/Settings/Encryption/index.tsx +++ b/client/src/components/Settings/Encryption/index.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useCallback, useMemo } from 'react'; +import React, { useCallback, useMemo } from 'react'; import { useTranslation } from 'react-i18next'; import { debounce } from 'lodash'; import { DEBOUNCE_TIMEOUT, ENCRYPTION_SOURCE } from '../../../helpers/constants'; @@ -18,19 +18,37 @@ type Props = { export const Encryption = ({ encryption, setTlsConfig, validateTlsConfig }: Props) => { const { t } = useTranslation(); - useEffect(() => { - if (encryption.enabled) { - validateTlsConfig(encryption); - } - }, [encryption, validateTlsConfig]); - const initialValues = useMemo((): EncryptionFormValues => { - const { certificate_chain, private_key, private_key_saved } = encryption; + const { + enabled, + serve_plain_dns, + server_name, + force_https, + port_https, + port_dns_over_tls, + port_dns_over_quic, + certificate_chain, + private_key, + certificate_path, + private_key_path, + private_key_saved, + } = encryption; const certificate_source = certificate_chain ? ENCRYPTION_SOURCE.CONTENT : ENCRYPTION_SOURCE.PATH; const key_source = private_key || private_key_saved ? ENCRYPTION_SOURCE.CONTENT : ENCRYPTION_SOURCE.PATH; return { - ...encryption, + enabled, + serve_plain_dns, + server_name, + force_https, + port_https, + port_dns_over_tls, + port_dns_over_quic, + certificate_chain, + private_key, + certificate_path, + private_key_path, + private_key_saved, certificate_source, key_source, }; @@ -75,7 +93,7 @@ export const Encryption = ({ encryption, setTlsConfig, validateTlsConfig }: Prop } }, []); - const debouncedConfigValidation = useCallback(debounce(validateConfig, DEBOUNCE_TIMEOUT), [validateConfig]); + const debouncedConfigValidation = useMemo(() => debounce(validateConfig, DEBOUNCE_TIMEOUT), [validateConfig]); return (
@@ -94,7 +112,7 @@ export const Encryption = ({ encryption, setTlsConfig, validateTlsConfig }: Prop debouncedConfigValidation={debouncedConfigValidation} setTlsConfig={setTlsConfig} validateTlsConfig={validateTlsConfig} - {...encryption} + encryption={encryption} /> )} diff --git a/client/src/components/ui/Controls/Checkbox/index.tsx b/client/src/components/ui/Controls/Checkbox/index.tsx index 32a97fba..09ed43fa 100644 --- a/client/src/components/ui/Controls/Checkbox/index.tsx +++ b/client/src/components/ui/Controls/Checkbox/index.tsx @@ -12,10 +12,14 @@ type Props = { className?: string; error?: string; onChange: (value: boolean) => void; + onBlur?: () => void; }; export const Checkbox = forwardRef( - ({ title, subtitle, value, name, disabled, error, className = 'checkbox--form', onChange, ...rest }, ref) => ( + ( + { title, subtitle, value, name, disabled, error, className = 'checkbox--form', onChange, onBlur, ...rest }, + ref, + ) => ( <>