mirror of
https://github.com/LaCasemate/fab-manager.git
synced 2025-01-18 07:52:23 +01:00
(bug) URL validation regex was wrong
This commit is contained in:
parent
ccd3899ebc
commit
cd612f4c77
@ -3,6 +3,7 @@ import { UseFormRegister, FormState } from 'react-hook-form';
|
||||
import { FieldValues } from 'react-hook-form/dist/types/fields';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { FabOutputCopy } from '../base/fab-output-copy';
|
||||
import ValidationLib from '../../lib/validation';
|
||||
|
||||
interface Oauth2FormProps<TFieldValues> {
|
||||
register: UseFormRegister<TFieldValues>,
|
||||
@ -16,10 +17,6 @@ interface Oauth2FormProps<TFieldValues> {
|
||||
export const Oauth2Form = <TFieldValues extends FieldValues>({ register, strategyName, formState }: Oauth2FormProps<TFieldValues>) => {
|
||||
const { t } = useTranslation('admin');
|
||||
|
||||
// regular expression to validate the input fields
|
||||
const endpointRegex = /^\/?([-._~:?#[\]@!$&'()*+,;=%\w]+\/?)*$/;
|
||||
const urlRegex = /^(https?:\/\/)([^.]+)\.(.{2,30})(\/.*)*\/?$/;
|
||||
|
||||
/**
|
||||
* Build the callback URL, based on the strategy name.
|
||||
*/
|
||||
@ -35,26 +32,26 @@ export const Oauth2Form = <TFieldValues extends FieldValues>({ register, strateg
|
||||
register={register}
|
||||
placeholder="https://sso.example.net..."
|
||||
label={t('app.admin.authentication.oauth2_form.common_url')}
|
||||
rules={{ required: true, pattern: urlRegex }}
|
||||
rules={{ required: true, pattern: ValidationLib.urlRegex }}
|
||||
formState={formState} />
|
||||
<FormInput id="providable_attributes.authorization_endpoint"
|
||||
register={register}
|
||||
placeholder="/oauth2/auth..."
|
||||
label={t('app.admin.authentication.oauth2_form.authorization_endpoint')}
|
||||
rules={{ required: true, pattern: endpointRegex }}
|
||||
rules={{ required: true, pattern: ValidationLib.endpointRegex }}
|
||||
formState={formState} />
|
||||
<FormInput id="providable_attributes.token_endpoint"
|
||||
register={register}
|
||||
placeholder="/oauth2/token..."
|
||||
label={t('app.admin.authentication.oauth2_form.token_acquisition_endpoint')}
|
||||
rules={{ required: true, pattern: endpointRegex }}
|
||||
rules={{ required: true, pattern: ValidationLib.endpointRegex }}
|
||||
formState={formState} />
|
||||
<FormInput id="providable_attributes.profile_url"
|
||||
register={register}
|
||||
placeholder="https://exemple.net/user..."
|
||||
label={t('app.admin.authentication.oauth2_form.profile_edition_url')}
|
||||
tooltip={t('app.admin.authentication.oauth2_form.profile_edition_url_help')}
|
||||
rules={{ required: true, pattern: urlRegex }}
|
||||
rules={{ required: true, pattern: ValidationLib.urlRegex }}
|
||||
formState={formState} />
|
||||
<FormInput id="providable_attributes.client_id"
|
||||
register={register}
|
||||
|
@ -12,6 +12,7 @@ import SsoClient from '../../api/external/sso';
|
||||
import { FieldPathValue } from 'react-hook-form/dist/types/path';
|
||||
import { FormMultiSelect } from '../form/form-multi-select';
|
||||
import { difference } from 'lodash';
|
||||
import ValidationLib from '../../lib/validation';
|
||||
|
||||
interface OpenidConnectFormProps<TFieldValues, TContext extends object> {
|
||||
register: UseFormRegister<TFieldValues>,
|
||||
@ -51,10 +52,6 @@ export const OpenidConnectForm = <TFieldValues extends FieldValues, TContext ext
|
||||
checkForDiscoveryEndpoint({ target: { value: currentFormValues?.issuer } } as React.ChangeEvent<HTMLInputElement>);
|
||||
}, []);
|
||||
|
||||
// regular expression to validate the input fields
|
||||
const endpointRegex = /^\/?([-._~:?#[\]@!$&'()*+,;=%\w]+\/?)*$/;
|
||||
const urlRegex = /^(https?:\/\/)([^.]+)\.(.{2,30})(\/.*)*\/?$/;
|
||||
|
||||
/**
|
||||
* If the discovery endpoint is available, the user will be able to choose to use it or not.
|
||||
* Otherwise, he will need to end the client configuration manually.
|
||||
@ -109,7 +106,7 @@ export const OpenidConnectForm = <TFieldValues extends FieldValues, TContext ext
|
||||
label={t('app.admin.authentication.openid_connect_form.issuer')}
|
||||
placeholder="https://sso.exemple.com"
|
||||
tooltip={t('app.admin.authentication.openid_connect_form.issuer_help')}
|
||||
rules={{ required: true, pattern: urlRegex }}
|
||||
rules={{ required: true, pattern: ValidationLib.urlRegex }}
|
||||
onChange={checkForDiscoveryEndpoint}
|
||||
debounce={400}
|
||||
warning={!discoveryAvailable && { message: t('app.admin.authentication.openid_connect_form.discovery_unavailable') } }
|
||||
@ -161,7 +158,7 @@ export const OpenidConnectForm = <TFieldValues extends FieldValues, TContext ext
|
||||
placeholder="https://sso.exemple.com/my-account"
|
||||
label={t('app.admin.authentication.openid_connect_form.profile_edition_url')}
|
||||
tooltip={t('app.admin.authentication.openid_connect_form.profile_edition_url_help')}
|
||||
rules={{ required: false, pattern: urlRegex }}
|
||||
rules={{ required: false, pattern: ValidationLib.urlRegex }}
|
||||
formState={formState} />
|
||||
<h4>{t('app.admin.authentication.openid_connect_form.client_options')}</h4>
|
||||
<FormInput id="providable_attributes.client__identifier"
|
||||
@ -178,31 +175,31 @@ export const OpenidConnectForm = <TFieldValues extends FieldValues, TContext ext
|
||||
<FormInput id="providable_attributes.client__authorization_endpoint"
|
||||
label={t('app.admin.authentication.openid_connect_form.client__authorization_endpoint')}
|
||||
placeholder="/authorize"
|
||||
rules={{ required: !currentFormValues?.discovery, pattern: endpointRegex }}
|
||||
rules={{ required: !currentFormValues?.discovery, pattern: ValidationLib.endpointRegex }}
|
||||
formState={formState}
|
||||
register={register} />
|
||||
<FormInput id="providable_attributes.client__token_endpoint"
|
||||
label={t('app.admin.authentication.openid_connect_form.client__token_endpoint')}
|
||||
placeholder="/token"
|
||||
rules={{ required: !currentFormValues?.discovery, pattern: endpointRegex }}
|
||||
rules={{ required: !currentFormValues?.discovery, pattern: ValidationLib.endpointRegex }}
|
||||
formState={formState}
|
||||
register={register} />
|
||||
<FormInput id="providable_attributes.client__userinfo_endpoint"
|
||||
label={t('app.admin.authentication.openid_connect_form.client__userinfo_endpoint')}
|
||||
placeholder="/userinfo"
|
||||
rules={{ required: !currentFormValues?.discovery, pattern: endpointRegex }}
|
||||
rules={{ required: !currentFormValues?.discovery, pattern: ValidationLib.endpointRegex }}
|
||||
formState={formState}
|
||||
register={register} />
|
||||
{currentFormValues?.client_auth_method === 'jwks' && <FormInput id="providable_attributes.client__jwks_uri"
|
||||
label={t('app.admin.authentication.openid_connect_form.client__jwks_uri')}
|
||||
rules={{ required: currentFormValues.client_auth_method === 'jwks', pattern: endpointRegex }}
|
||||
rules={{ required: currentFormValues.client_auth_method === 'jwks', pattern: ValidationLib.endpointRegex }}
|
||||
formState={formState}
|
||||
placeholder="/jwk"
|
||||
register={register} />}
|
||||
<FormInput id="providable_attributes.client__end_session_endpoint"
|
||||
label={t('app.admin.authentication.openid_connect_form.client__end_session_endpoint')}
|
||||
tooltip={t('app.admin.authentication.openid_connect_form.client__end_session_endpoint_help')}
|
||||
rules={{ pattern: endpointRegex }}
|
||||
rules={{ pattern: ValidationLib.endpointRegex }}
|
||||
formState={formState}
|
||||
register={register} />
|
||||
</div>}
|
||||
|
@ -5,6 +5,7 @@ import { FormSwitch } from '../form/form-switch';
|
||||
import { FormRichText } from '../form/form-rich-text';
|
||||
import { FormInput } from '../form/form-input';
|
||||
import { SettingName, SettingValue } from '../../models/setting';
|
||||
import ValidationLib from '../../lib/validation';
|
||||
export type EditorialKeys = 'active_text_block' | 'text_block' | 'active_cta' | 'cta_label' | 'cta_url';
|
||||
|
||||
interface EditorialBlockFormProps {
|
||||
@ -15,9 +16,6 @@ interface EditorialBlockFormProps {
|
||||
keys: Record<EditorialKeys, SettingName>
|
||||
}
|
||||
|
||||
// regular expression to validate the input fields
|
||||
const urlRegex = /^(https?:\/\/)([^.]+)\.(.{2,30})(\/.*)*\/?$/;
|
||||
|
||||
/**
|
||||
* Allows to create a formatted text and optional cta button in a form block, to be included in a resource form managed by react-hook-form.
|
||||
*/
|
||||
@ -78,7 +76,7 @@ export const EditorialBlockForm: React.FC<EditorialBlockFormProps> = ({ register
|
||||
formState={formState}
|
||||
rules={{
|
||||
required: { value: isActiveCta, message: t('app.admin.editorial_block_form.url_is_required') },
|
||||
pattern: { value: urlRegex, message: t('app.admin.editorial_block_form.url_must_be_safe') }
|
||||
pattern: { value: ValidationLib.urlRegex, message: t('app.admin.editorial_block_form.url_must_be_safe') }
|
||||
}}
|
||||
label={t('app.admin.editorial_block_form.cta_url')} />
|
||||
</>}
|
||||
|
@ -7,6 +7,7 @@ import Icons from '../../../../images/social-icons.svg';
|
||||
import { FormInput } from '../form/form-input';
|
||||
import { Trash } from 'phosphor-react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import ValidationLib from '../../lib/validation';
|
||||
|
||||
interface EditSocialsProps<TFieldValues> {
|
||||
register: UseFormRegister<TFieldValues>,
|
||||
@ -21,8 +22,6 @@ interface EditSocialsProps<TFieldValues> {
|
||||
*/
|
||||
export const EditSocials = <TFieldValues extends FieldValues>({ register, setValue, networks, formState, disabled }: EditSocialsProps<TFieldValues>) => {
|
||||
const { t } = useTranslation('shared');
|
||||
// regular expression to validate the input fields
|
||||
const urlRegex = /^(https?:\/\/)([^.]+)\.(.{2,30})(\/.*)*\/?$/;
|
||||
|
||||
const initSelectedNetworks = networks.filter(el => !['', null, undefined].includes(el.url));
|
||||
const [selectedNetworks, setSelectedNetworks] = useState(initSelectedNetworks);
|
||||
@ -72,7 +71,7 @@ export const EditSocials = <TFieldValues extends FieldValues>({ register, setVal
|
||||
register={register}
|
||||
rules= {{
|
||||
pattern: {
|
||||
value: urlRegex,
|
||||
value: ValidationLib.urlRegex,
|
||||
message: t('app.shared.edit_socials.website_invalid')
|
||||
}
|
||||
}}
|
||||
|
@ -12,6 +12,7 @@ import Icons from '../../../../images/social-icons.svg';
|
||||
import { Trash } from 'phosphor-react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { FabButton } from '../base/fab-button';
|
||||
import ValidationLib from '../../lib/validation';
|
||||
|
||||
declare const Application: IApplication;
|
||||
|
||||
@ -26,8 +27,6 @@ interface FabSocialsProps {
|
||||
*/
|
||||
export const FabSocials: React.FC<FabSocialsProps> = ({ show = false, onError, onSuccess }) => {
|
||||
const { t } = useTranslation('shared');
|
||||
// regular expression to validate the input fields
|
||||
const urlRegex = /^(https?:\/\/)([\da-z.-]+)\.([-a-z\d.]{2,30})([/\w .-]*)*\/?$/;
|
||||
|
||||
const { handleSubmit, register, setValue, formState } = useForm();
|
||||
|
||||
@ -109,7 +108,7 @@ export const FabSocials: React.FC<FabSocialsProps> = ({ show = false, onError, o
|
||||
register={register}
|
||||
rules={{
|
||||
pattern: {
|
||||
value: urlRegex,
|
||||
value: ValidationLib.urlRegex,
|
||||
message: t('app.shared.fab_socials.website_invalid')
|
||||
}
|
||||
}}
|
||||
|
@ -32,6 +32,7 @@ import { ProfileCustomField } from '../../models/profile-custom-field';
|
||||
import { SettingName } from '../../models/setting';
|
||||
import SettingAPI from '../../api/setting';
|
||||
import { SelectOption } from '../../models/select';
|
||||
import ValidationLib from '../../lib/validation';
|
||||
|
||||
declare const Application: IApplication;
|
||||
|
||||
@ -55,10 +56,6 @@ interface UserProfileFormProps {
|
||||
export const UserProfileForm: React.FC<UserProfileFormProps> = ({ action, size, user, operator, className, onError, onSuccess, showGroupInput, showTermsAndConditionsInput, showTrainingsInput, showTagsInput }) => {
|
||||
const { t } = useTranslation('shared');
|
||||
|
||||
// regular expression to validate the input fields
|
||||
const phoneRegex = /^((00|\+)\d{2,3})?[\d -]{4,14}$/;
|
||||
const urlRegex = /^(https?:\/\/)([^.]+)\.(.{2,30})(\/.*)*\/?$/;
|
||||
|
||||
const { handleSubmit, register, control, formState, setValue, reset } = useForm<User>({ defaultValues: { ...user } });
|
||||
const output = useWatch<User>({ control });
|
||||
|
||||
@ -215,7 +212,7 @@ export const UserProfileForm: React.FC<UserProfileFormProps> = ({ action, size,
|
||||
register={register}
|
||||
rules={{
|
||||
pattern: {
|
||||
value: phoneRegex,
|
||||
value: ValidationLib.phoneRegex,
|
||||
message: t('app.shared.user_profile_form.phone_number_invalid')
|
||||
},
|
||||
required: fieldsSettings.get('phone_required') === 'true'
|
||||
@ -314,7 +311,7 @@ export const UserProfileForm: React.FC<UserProfileFormProps> = ({ action, size,
|
||||
register={register}
|
||||
rules={{
|
||||
pattern: {
|
||||
value: urlRegex,
|
||||
value: ValidationLib.urlRegex,
|
||||
message: t('app.shared.user_profile_form.website_invalid')
|
||||
}
|
||||
}}
|
||||
|
6
app/frontend/src/javascript/lib/validation.ts
Normal file
6
app/frontend/src/javascript/lib/validation.ts
Normal file
@ -0,0 +1,6 @@
|
||||
// Provides regular expressions to validate user inputs
|
||||
export default class ValidationLib {
|
||||
static urlRegex = /^(https?:\/\/)(([^.]+)\.)+(.{2,30})(\/.*)*\/?$/;
|
||||
static endpointRegex = /^\/?([-._~:?#[\]@!$&'()*+,;=%\w]+\/?)*$/;
|
||||
static phoneRegex = /^((00|\+)\d{2,3})?[\d -]{4,14}$/;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user