diff --git a/apps/assisted-ui/deploy/nginx.conf b/apps/assisted-ui/deploy/nginx.conf index 0afebff26a..3e8b7dc66a 100644 --- a/apps/assisted-ui/deploy/nginx.conf +++ b/apps/assisted-ui/deploy/nginx.conf @@ -11,6 +11,7 @@ location /api { proxy_send_timeout 120; proxy_read_timeout 120; send_timeout 120; + client_max_body_size 2M; } location / { diff --git a/apps/assisted-ui/deploy/nginx_ssl.conf b/apps/assisted-ui/deploy/nginx_ssl.conf index 545c967e01..880bf193ca 100644 --- a/apps/assisted-ui/deploy/nginx_ssl.conf +++ b/apps/assisted-ui/deploy/nginx_ssl.conf @@ -10,6 +10,7 @@ events { } http { + client_max_body_size 2M; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; diff --git a/libs/ui-lib/lib/common/configurations.ts b/libs/ui-lib/lib/common/configurations.ts new file mode 100644 index 0000000000..717201b165 --- /dev/null +++ b/libs/ui-lib/lib/common/configurations.ts @@ -0,0 +1,2 @@ +export const MAX_FILE_SIZE_BYTES = 1024 ** 2; +export const MAX_FILE_SIZE_OFFSET_FACTOR = 2; diff --git a/libs/ui-lib/lib/common/index.ts b/libs/ui-lib/lib/common/index.ts index 5a1c7ff700..6f15c87502 100644 --- a/libs/ui-lib/lib/common/index.ts +++ b/libs/ui-lib/lib/common/index.ts @@ -1,3 +1,4 @@ +import './configurations.ts'; import './styles.css'; import './utils'; diff --git a/libs/ui-lib/lib/common/utils.ts b/libs/ui-lib/lib/common/utils.ts index 39a7ca7ff4..0d5c3c59f5 100644 --- a/libs/ui-lib/lib/common/utils.ts +++ b/libs/ui-lib/lib/common/utils.ts @@ -1,5 +1,12 @@ import isString from 'lodash-es/isString.js'; import { load } from 'js-yaml'; +import { MAX_FILE_SIZE_BYTES, MAX_FILE_SIZE_OFFSET_FACTOR } from './configurations'; +import { fileSize } from './components/hosts/utils'; + +export const FILENAME_REGEX = /^[^\/]*\.(yaml|yml|json)$/; +export const FILE_TYPE_MESSAGE = 'Unsupported file type. Please provide a valid YAML file.'; +export const INCORRECT_TYPE_FILE_MESSAGE = + 'File type is not supported. File type must be yaml, yml or json.'; export const getErrorMessage = (error: unknown): string => { if (error instanceof Error) { @@ -40,11 +47,17 @@ export const isStringValidJSON = (input: string): boolean => { } }; -export const validateFileSize = (value: string, fileSize: number): boolean => { +export const validateFileSize = (value: string): boolean => { const contentFile = new Blob([value], { type: 'text/plain;charset=utf-8' }); - return contentFile.size <= fileSize; + return contentFile.size <= MAX_FILE_SIZE_BYTES * MAX_FILE_SIZE_OFFSET_FACTOR; }; -export const getMaxFileSizeMessage = (fileSize: number): string => { - return `File size is too big. Upload a new ${fileSize / 1000} kB or less.`; +export const getMaxFileSizeMessage = `File size is too big. The file size must be less than ${fileSize( + MAX_FILE_SIZE_BYTES, + 0, + 'si', +)}.`; + +export const validateFileName = (fileName: string) => { + return new RegExp(FILENAME_REGEX).test(fileName || ''); }; diff --git a/libs/ui-lib/lib/ocm/components/clusterConfiguration/manifestsConfiguration/components/customManifestsValidationSchema.tsx b/libs/ui-lib/lib/ocm/components/clusterConfiguration/manifestsConfiguration/components/customManifestsValidationSchema.tsx index 3630ac9635..f4871f400a 100644 --- a/libs/ui-lib/lib/ocm/components/clusterConfiguration/manifestsConfiguration/components/customManifestsValidationSchema.tsx +++ b/libs/ui-lib/lib/ocm/components/clusterConfiguration/manifestsConfiguration/components/customManifestsValidationSchema.tsx @@ -3,15 +3,13 @@ import { UniqueStringArrayExtractor } from '../../staticIp/commonValidationSchem import { CustomManifestValues, ManifestFormData } from '../data/dataTypes'; import { getMaxFileSizeMessage, - isStringValidYAML, - isStringValidJSON, validateFileSize, + validateFileName, + validateFileType, + INCORRECT_TYPE_FILE_MESSAGE, } from '../../../../../common/utils'; - -const MAX_FILE_SIZE = 100000; //100 kb -const FILENAME_REGEX = /^[^/]*\.(yaml|yml|json)$/; const INCORRECT_FILENAME = 'Must have a yaml, yml or json extension and can not contain /.'; -const INCORRECT_TYPE_FILE = 'File type is not supported. File type must be yaml, yml or json.'; + const UNIQUE_FOLDER_FILENAME = 'Ensure unique file names within each folder to avoid conflicts and errors.'; @@ -42,34 +40,22 @@ export const getUniqueValidationSchema = ( const getAllManifests: UniqueStringArrayExtractor = (values: ManifestFormData) => values.manifests.map((manifest) => `${manifest.folder}_${manifest.filename}`); -export const getFormViewManifestsValidationSchema = Yup.lazy(() => - Yup.object().shape({ - manifests: Yup.array().of( - Yup.object().shape({ - folder: Yup.mixed().required('Required').concat(getUniqueValidationSchema(getAllManifests)), - filename: Yup.string() - .required('Required') - .min(1, 'Number of characters must be 1-255') - .max(255, 'Number of characters must be 1-255') - .test('not-correct-filename', INCORRECT_FILENAME, (value: string) => { - return validateFileName(value); - }) - .concat(getUniqueValidationSchema(getAllManifests)), - manifestYaml: Yup.string() - .required('Required') - .test('not-big-file', getMaxFileSizeMessage(MAX_FILE_SIZE), (value: string) => - validateFileSize(value, MAX_FILE_SIZE), - ) - .test('not-valid-file', INCORRECT_TYPE_FILE, validateFileType), - }), - ), - }), -); - -const validateFileName = (fileName: string) => { - return new RegExp(FILENAME_REGEX).test((fileName || '').toString()); -}; - -const validateFileType = (value: string) => { - return isStringValidYAML(value) || isStringValidJSON(value); -}; +export const getFormViewManifestsValidationSchema = Yup.object().shape({ + manifests: Yup.array().of( + Yup.object().shape({ + folder: Yup.mixed().required('Required').concat(getUniqueValidationSchema(getAllManifests)), + filename: Yup.string() + .required('Required') + .min(1, 'Number of characters must be 1-255') + .max(255, 'Number of characters must be 1-255') + .test('not-correct-filename', INCORRECT_FILENAME, (value: string) => { + return validateFileName(value); + }) + .concat(getUniqueValidationSchema(getAllManifests)), + manifestYaml: Yup.string() + .required('Required') + .test('not-big-file', getMaxFileSizeMessage, validateFileSize) + .test('not-valid-file', INCORRECT_TYPE_FILE_MESSAGE, validateFileType), + }), + ), +}); diff --git a/libs/ui-lib/lib/ocm/components/clusterConfiguration/manifestsConfiguration/components/propTypes.ts b/libs/ui-lib/lib/ocm/components/clusterConfiguration/manifestsConfiguration/components/propTypes.ts index 165cdd8535..6dcd71c745 100644 --- a/libs/ui-lib/lib/ocm/components/clusterConfiguration/manifestsConfiguration/components/propTypes.ts +++ b/libs/ui-lib/lib/ocm/components/clusterConfiguration/manifestsConfiguration/components/propTypes.ts @@ -17,7 +17,9 @@ export type CustomManifestsFormProps = { showEmptyValues: boolean; getInitialValues(customManifests: ListManifestsExtended): ManifestFormData; getEmptyValues(): ManifestFormData; - validationSchema: Yup.Schema; + validationSchema: Yup.ObjectSchema<{ + manifests: object[]; + }>; cluster: Cluster; }; diff --git a/libs/ui-lib/lib/ocm/components/clusterConfiguration/staticIp/components/YamlView/yamlViewValidationSchema.tsx b/libs/ui-lib/lib/ocm/components/clusterConfiguration/staticIp/components/YamlView/yamlViewValidationSchema.tsx index 9a08ecf5d1..efda064661 100644 --- a/libs/ui-lib/lib/ocm/components/clusterConfiguration/staticIp/components/YamlView/yamlViewValidationSchema.tsx +++ b/libs/ui-lib/lib/ocm/components/clusterConfiguration/staticIp/components/YamlView/yamlViewValidationSchema.tsx @@ -11,26 +11,18 @@ import { UniqueStringArrayExtractor, } from '../../commonValidationSchemas'; import { + INCORRECT_TYPE_FILE_MESSAGE, getMaxFileSizeMessage, - isStringValidJSON, - isStringValidYAML, validateFileSize, + validateFileType, } from '../../../../../../common/utils'; -const MAX_FILE_SIZE = 100000; //100 kb const requiredMsg = 'A value is required'; -const FILE_TYPE_MESSAGE = 'Unsupported file type. Please provide a valid YAML file.'; const networkYamlValidationSchema = Yup.string() .required(requiredMsg) - .test( - 'file-type-yaml', - FILE_TYPE_MESSAGE, - (value: string) => isStringValidYAML(value) && !isStringValidJSON(value), - ) - .test('file-size-limit', getMaxFileSizeMessage(MAX_FILE_SIZE), (value: string) => - validateFileSize(value, MAX_FILE_SIZE), - ); + .test('file-size-limit', getMaxFileSizeMessage, validateFileSize) + .test('file-type-yaml', INCORRECT_TYPE_FILE_MESSAGE, validateFileType); const getAllMacAddresses: UniqueStringArrayExtractor = ( values: YamlViewValues,