diff --git a/packages/manager/.changeset/pr-12771-upcoming-features-1756215443845.md b/packages/manager/.changeset/pr-12771-upcoming-features-1756215443845.md new file mode 100644 index 00000000000..06bfaa03cb8 --- /dev/null +++ b/packages/manager/.changeset/pr-12771-upcoming-features-1756215443845.md @@ -0,0 +1,5 @@ +--- +"@linode/manager": Upcoming Features +--- + +ACLP-Metrics,Alerts: enforce validation for 100 characters for TextField components ([#12771](https://github.com/linode/manager/pull/12771)) diff --git a/packages/manager/src/features/CloudPulse/Alerts/CreateAlert/Criteria/DimensionFilterValue/ValueSchemas.ts b/packages/manager/src/features/CloudPulse/Alerts/CreateAlert/Criteria/DimensionFilterValue/ValueSchemas.ts index 26e9c868b7a..00c4e54cc25 100644 --- a/packages/manager/src/features/CloudPulse/Alerts/CreateAlert/Criteria/DimensionFilterValue/ValueSchemas.ts +++ b/packages/manager/src/features/CloudPulse/Alerts/CreateAlert/Criteria/DimensionFilterValue/ValueSchemas.ts @@ -6,7 +6,6 @@ import { PORTS_HELPER_TEXT, PORTS_LEADING_COMMA_ERROR_MESSAGE, PORTS_LEADING_ZERO_ERROR_MESSAGE, - PORTS_LIMIT_ERROR_MESSAGE, PORTS_RANGE_ERROR_MESSAGE, } from 'src/features/CloudPulse/Utils/constants'; @@ -19,16 +18,16 @@ import { PORTS_TRAILING_COMMA_ERROR_MESSAGE, } from '../../../constants'; +const LENGTH_ERROR_MESSAGE = 'Value must be 100 characters or less.'; const fieldErrorMessage = 'This field is required.'; const DECIMAL_PORT_REGEX = /^[1-9]\d{0,4}$/; const LEADING_ZERO_PORT_REGEX = /^0\d+/; const CONFIG_NUMBER_REGEX = /^\d+$/; // Validation schema for a single input port -const singlePortSchema = string().test( - 'validate-single-port', - PORT_HELPER_TEXT, - function (value) { +const singlePortSchema = string() + .max(100, LENGTH_ERROR_MESSAGE) + .test('validate-single-port', PORT_HELPER_TEXT, function (value) { if (!value || typeof value !== 'string') { return this.createError({ message: fieldErrorMessage }); } @@ -38,7 +37,6 @@ const singlePortSchema = string().test( message: PORTS_LEADING_ZERO_ERROR_MESSAGE, }); } - if (!DECIMAL_PORT_REGEX.test(value)) { return this.createError({ message: PORTS_RANGE_ERROR_MESSAGE }); } @@ -48,14 +46,12 @@ const singlePortSchema = string().test( } return true; - } -); + }); // Validation schema for a multiple comma-separated ports -const commaSeparatedPortListSchema = string().test( - 'validate-port-list', - PORTS_HELPER_TEXT, - function (value) { +const commaSeparatedPortListSchema = string() + .max(100, LENGTH_ERROR_MESSAGE) + .test('validate-port-list', PORTS_HELPER_TEXT, function (value) { if (!value || typeof value !== 'string') { return this.createError({ message: fieldErrorMessage }); } @@ -87,11 +83,6 @@ const commaSeparatedPortListSchema = string().test( const ports = rawSegments.map((p) => p.trim()); - if (ports.length > 15) { - return this.createError({ - message: PORTS_LIMIT_ERROR_MESSAGE, - }); - } for (const port of ports) { const trimmedPort = port.trim(); @@ -111,10 +102,9 @@ const commaSeparatedPortListSchema = string().test( } return true; - } -); + }); const singleConfigSchema = string() - .max(100, 'Value must be 100 characters or less.') + .max(100, LENGTH_ERROR_MESSAGE) .test( 'validate-single-config-schema', CONFIG_ERROR_MESSAGE, @@ -131,7 +121,7 @@ const singleConfigSchema = string() ); const multipleConfigSchema = string() - .max(100, 'Value must be 100 characters or less.') + .max(100, LENGTH_ERROR_MESSAGE) .test( 'validate-multi-config-schema', CONFIGS_ERROR_MESSAGE, @@ -204,6 +194,8 @@ export const getDimensionFilterValueSchema = ({ operator === 'in' ? multipleConfigSchema : singleConfigSchema; return configSchema.concat(baseValueSchema); } - + if (['endswith', 'startswith'].includes(operator)) { + return baseValueSchema.concat(string().max(100, LENGTH_ERROR_MESSAGE)); + } return baseValueSchema; }; diff --git a/packages/manager/src/features/CloudPulse/Alerts/CreateAlert/Criteria/DimensionFilterValue/constants.ts b/packages/manager/src/features/CloudPulse/Alerts/CreateAlert/Criteria/DimensionFilterValue/constants.ts index 2a9304ff064..c112a2bf212 100644 --- a/packages/manager/src/features/CloudPulse/Alerts/CreateAlert/Criteria/DimensionFilterValue/constants.ts +++ b/packages/manager/src/features/CloudPulse/Alerts/CreateAlert/Criteria/DimensionFilterValue/constants.ts @@ -148,12 +148,16 @@ export const valueFieldConfig: ValueFieldConfigMap = { eq_neq: { type: 'textfield', inputType: 'number', + min: 0, + max: Number.MAX_SAFE_INTEGER, placeholder: CONFIG_ID_PLACEHOLDER_TEXT, helperText: CONFIG_ERROR_MESSAGE, }, startswith_endswith: { type: 'textfield', inputType: 'number', + min: 0, + max: Number.MAX_SAFE_INTEGER, placeholder: CONFIG_ID_PLACEHOLDER_TEXT, helperText: CONFIG_ERROR_MESSAGE, }, diff --git a/packages/manager/src/features/CloudPulse/Utils/constants.ts b/packages/manager/src/features/CloudPulse/Utils/constants.ts index 032cb3bb59a..786a4795805 100644 --- a/packages/manager/src/features/CloudPulse/Utils/constants.ts +++ b/packages/manager/src/features/CloudPulse/Utils/constants.ts @@ -58,7 +58,8 @@ export const PORTS_CONSECUTIVE_COMMAS_ERROR_MESSAGE = export const PORTS_LEADING_COMMA_ERROR_MESSAGE = 'First character must be an integer.'; -export const PORTS_LIMIT_ERROR_MESSAGE = 'Enter a maximum of 15 port numbers'; +export const PORTS_LIMIT_ERROR_MESSAGE = + 'Port list must be 100 characters or less.'; export const PORTS_PLACEHOLDER_TEXT = 'e.g., 80,443,3000'; @@ -75,7 +76,7 @@ export const INTERFACE_IDS_LEADING_COMMA_ERROR_MESSAGE = 'First character must be an integer.'; export const INTERFACE_IDS_LIMIT_ERROR_MESSAGE = - 'Enter a maximum of 15 interface ID numbers'; + 'Interface IDs list must be 100 characters or less.'; export const INTERFACE_IDS_PLACEHOLDER_TEXT = 'e.g., 1234,5678'; diff --git a/packages/manager/src/features/CloudPulse/Utils/utils.test.ts b/packages/manager/src/features/CloudPulse/Utils/utils.test.ts index 2ca235bbeba..3a01bc2b14d 100644 --- a/packages/manager/src/features/CloudPulse/Utils/utils.test.ts +++ b/packages/manager/src/features/CloudPulse/Utils/utils.test.ts @@ -64,10 +64,17 @@ describe('arePortsValid', () => { expect(arePortsValid('abc')).toBe(PORTS_ERROR_MESSAGE); }); - it('should return invalid for more than 15 ports', () => { - const ports = Array.from({ length: 16 }, (_, i) => i + 1).join(','); - const result = arePortsValid(ports); - expect(result).toBe(PORTS_LIMIT_ERROR_MESSAGE); + it('should return invalid for input length more than 100 characters', () => { + expect( + arePortsValid( + '12345,23456,34567,45678,56789,123,456,789,1111,2222,3333,4444,5555,6666,7777,8888,9999,12,34,56,1055' + ) + ).toBe(undefined); + expect( + arePortsValid( + '12345,23456,34567,45678,56789,123,456,789,1111,2222,3333,4444,5555,6666,7777,8888,9999,12,34,56,10455' + ) + ).toBe(PORTS_LIMIT_ERROR_MESSAGE); }); }); @@ -93,10 +100,17 @@ describe('areValidInterfaceIds', () => { expect(areValidInterfaceIds('abc')).toBe(INTERFACE_IDS_ERROR_MESSAGE); }); - it('should return invalid for more than 15 interface ids', () => { - const interfaceIds = Array.from({ length: 16 }, (_, i) => i + 1).join(','); - const result = areValidInterfaceIds(interfaceIds); - expect(result).toBe(INTERFACE_IDS_LIMIT_ERROR_MESSAGE); + it('should return invalid for input length more than 100 characters', () => { + expect( + areValidInterfaceIds( + '12345,23456,34567,45678,56789,123,456,789,1111,2222,3333,4444,5555,6666,7777,8888,9999,12,34,56,1455' + ) + ).toBe(undefined); + expect( + areValidInterfaceIds( + '12345,23456,34567,45678,56789,123,456,789,1111,2222,3333,4444,5555,6666,7777,8888,9999,12,34,56,14055' + ) + ).toBe(INTERFACE_IDS_LIMIT_ERROR_MESSAGE); }); }); diff --git a/packages/manager/src/features/CloudPulse/Utils/utils.ts b/packages/manager/src/features/CloudPulse/Utils/utils.ts index e19a3cbd0e8..8916d7fedce 100644 --- a/packages/manager/src/features/CloudPulse/Utils/utils.ts +++ b/packages/manager/src/features/CloudPulse/Utils/utils.ts @@ -305,6 +305,10 @@ export const arePortsValid = (ports: string): string | undefined => { return undefined; } + if (ports.length > 100) { + return PORTS_LIMIT_ERROR_MESSAGE; + } + if (ports.startsWith(',')) { return PORTS_LEADING_COMMA_ERROR_MESSAGE; } @@ -318,18 +322,12 @@ export const arePortsValid = (ports: string): string | undefined => { } const portList = ports.split(','); - let portLimitCount = 0; for (const port of portList) { const result = isValidPort(port); if (result !== undefined) { return result; } - portLimitCount++; - } - - if (portLimitCount > 15) { - return PORTS_LIMIT_ERROR_MESSAGE; } return undefined; @@ -347,6 +345,10 @@ export const areValidInterfaceIds = ( return undefined; } + if (interfaceIds.length > 100) { + return INTERFACE_IDS_LIMIT_ERROR_MESSAGE; + } + if (interfaceIds.startsWith(',')) { return INTERFACE_IDS_LEADING_COMMA_ERROR_MESSAGE; } @@ -358,13 +360,6 @@ export const areValidInterfaceIds = ( return INTERFACE_IDS_ERROR_MESSAGE; } - const interfaceIdList = interfaceIds.split(','); - const interfaceIdLimitCount = interfaceIdList.length; - - if (interfaceIdLimitCount > 15) { - return INTERFACE_IDS_LIMIT_ERROR_MESSAGE; - } - return undefined; };