mirror of
				https://github.com/Unleash/unleash.git
				synced 2025-10-27 11:02:16 +01:00 
			
		
		
		
	feat: stop regexes with whitespace (#4681)
This PR stops regexes with whitespace from being added as feature naming patterns.
This commit is contained in:
		
							parent
							
								
									bf451f6549
								
							
						
					
					
						commit
						9bdee12ad9
					
				| @ -210,14 +210,31 @@ const ProjectForm: React.FC<IProjectForm> = ({ | |||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     const onSetFeatureNamingPattern = (regex: string) => { |     const onSetFeatureNamingPattern = (regex: string) => { | ||||||
|  |         const disallowedStrings = [ | ||||||
|  |             ' ', | ||||||
|  |             '\\t', | ||||||
|  |             '\\s', | ||||||
|  |             '\\n', | ||||||
|  |             '\\r', | ||||||
|  |             '\\f', | ||||||
|  |             '\\v', | ||||||
|  |         ]; | ||||||
|  |         if ( | ||||||
|  |             disallowedStrings.some(blockedString => | ||||||
|  |                 regex.includes(blockedString) | ||||||
|  |             ) | ||||||
|  |         ) { | ||||||
|  |             errors.featureNamingPattern = | ||||||
|  |                 'Whitespace is not allowed in the expression'; | ||||||
|  |         } else { | ||||||
|             try { |             try { | ||||||
|                 new RegExp(regex); |                 new RegExp(regex); | ||||||
|             setFeatureNamingPattern && setFeatureNamingPattern(regex); |  | ||||||
|                 delete errors.featureNamingPattern; |                 delete errors.featureNamingPattern; | ||||||
|             } catch (e) { |             } catch (e) { | ||||||
|                 errors.featureNamingPattern = 'Invalid regular expression'; |                 errors.featureNamingPattern = 'Invalid regular expression'; | ||||||
|             setFeatureNamingPattern && setFeatureNamingPattern(regex); |  | ||||||
|             } |             } | ||||||
|  |         } | ||||||
|  |         setFeatureNamingPattern && setFeatureNamingPattern(regex); | ||||||
|         updateNamingExampleError({ |         updateNamingExampleError({ | ||||||
|             pattern: regex, |             pattern: regex, | ||||||
|             example: featureNamingExample || '', |             example: featureNamingExample || '', | ||||||
|  | |||||||
| @ -61,6 +61,19 @@ describe('validate incoming feature naming data', () => { | |||||||
|         } |         } | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|  |     test.each([' ', '\\t', '\\n'])( | ||||||
|  |         'patterns with illegal characters (%s) are invalid', | ||||||
|  |         (string) => { | ||||||
|  |             const pattern = `-${string}[0-9]+`; | ||||||
|  | 
 | ||||||
|  |             expect( | ||||||
|  |                 checkFeatureNamingData({ | ||||||
|  |                     pattern, | ||||||
|  |                 }), | ||||||
|  |             ).toMatchObject({ state: 'invalid' }); | ||||||
|  |         }, | ||||||
|  |     ); | ||||||
|  | 
 | ||||||
|     test('feature naming data with a non-empty example but an empty pattern is invalid', () => { |     test('feature naming data with a non-empty example but an empty pattern is invalid', () => { | ||||||
|         expect( |         expect( | ||||||
|             checkFeatureNamingData({ |             checkFeatureNamingData({ | ||||||
| @ -78,6 +91,19 @@ describe('validate incoming feature naming data', () => { | |||||||
|             }), |             }), | ||||||
|         ).toMatchObject({ state: 'invalid' }); |         ).toMatchObject({ state: 'invalid' }); | ||||||
|     }); |     }); | ||||||
|  | 
 | ||||||
|  |     test('if the pattern contains disallowed characters, a match is not attempted against the example', () => { | ||||||
|  |         const result = checkFeatureNamingData({ | ||||||
|  |             pattern: 'a. [0-9]+', | ||||||
|  |             example: 'obviously-not-a-match', | ||||||
|  |         }); | ||||||
|  | 
 | ||||||
|  |         if (result.state === 'valid') { | ||||||
|  |             fail('Expected invalid result'); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         expect(result.reasons.length).toBe(1); | ||||||
|  |     }); | ||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
| describe('validate feature flag names against a pattern', () => { | describe('validate feature flag names against a pattern', () => { | ||||||
|  | |||||||
| @ -10,23 +10,39 @@ export const checkFeatureNamingData = ( | |||||||
|     if (featureNaming) { |     if (featureNaming) { | ||||||
|         const { pattern, example, description } = featureNaming; |         const { pattern, example, description } = featureNaming; | ||||||
|         const errors: string[] = []; |         const errors: string[] = []; | ||||||
|         if (pattern && example && !example.match(compileRegex(pattern))) { |         const disallowedStrings = [ | ||||||
|  |             ' ', | ||||||
|  |             '\\t', | ||||||
|  |             '\\s', | ||||||
|  |             '\\n', | ||||||
|  |             '\\r', | ||||||
|  |             '\\f', | ||||||
|  |             '\\v', | ||||||
|  |         ]; | ||||||
|  | 
 | ||||||
|  |         if (pattern) { | ||||||
|  |             if (disallowedStrings.some((str) => pattern.includes(str))) { | ||||||
|  |                 errors.push( | ||||||
|  |                     `Feature flag names can not contain whitespace. You've provided a feature flag naming pattern that contains a whitespace character: "${pattern}". Remove any whitespace characters from your pattern.`, | ||||||
|  |                 ); | ||||||
|  |             } else if (example && !example.match(compileRegex(pattern))) { | ||||||
|                 errors.push( |                 errors.push( | ||||||
|                     `You've provided a feature flag naming example ("${example}") that doesn't match your feature flag naming pattern ("${pattern}"). Please provide an example that matches your supplied pattern. Bear in mind that the pattern must match the whole example, as if it were surrounded by '^' and "$".`, |                     `You've provided a feature flag naming example ("${example}") that doesn't match your feature flag naming pattern ("${pattern}"). Please provide an example that matches your supplied pattern. Bear in mind that the pattern must match the whole example, as if it were surrounded by '^' and "$".`, | ||||||
|                 ); |                 ); | ||||||
|             } |             } | ||||||
| 
 |         } else { | ||||||
|         if (!pattern && example) { |             if (example) { | ||||||
|                 errors.push( |                 errors.push( | ||||||
|                     "You've provided a feature flag naming example, but no feature flag naming pattern. You must specify a pattern to use an example.", |                     "You've provided a feature flag naming example, but no feature flag naming pattern. You must specify a pattern to use an example.", | ||||||
|                 ); |                 ); | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|         if (!pattern && description) { |             if (description) { | ||||||
|                 errors.push( |                 errors.push( | ||||||
|                     "You've provided a feature flag naming pattern description, but no feature flag naming pattern. You must have a pattern to use a description.", |                     "You've provided a feature flag naming pattern description, but no feature flag naming pattern. You must have a pattern to use a description.", | ||||||
|                 ); |                 ); | ||||||
|             } |             } | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         const [first, ...rest] = errors; |         const [first, ...rest] = errors; | ||||||
|         if (first) { |         if (first) { | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user