mirror of
https://github.com/Unleash/unleash.git
synced 2025-05-26 01:17:00 +02: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) => {
|
||||||
try {
|
const disallowedStrings = [
|
||||||
new RegExp(regex);
|
' ',
|
||||||
setFeatureNamingPattern && setFeatureNamingPattern(regex);
|
'\\t',
|
||||||
delete errors.featureNamingPattern;
|
'\\s',
|
||||||
} catch (e) {
|
'\\n',
|
||||||
errors.featureNamingPattern = 'Invalid regular expression';
|
'\\r',
|
||||||
setFeatureNamingPattern && setFeatureNamingPattern(regex);
|
'\\f',
|
||||||
|
'\\v',
|
||||||
|
];
|
||||||
|
if (
|
||||||
|
disallowedStrings.some(blockedString =>
|
||||||
|
regex.includes(blockedString)
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
errors.featureNamingPattern =
|
||||||
|
'Whitespace is not allowed in the expression';
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
new RegExp(regex);
|
||||||
|
delete errors.featureNamingPattern;
|
||||||
|
} catch (e) {
|
||||||
|
errors.featureNamingPattern = 'Invalid regular expression';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
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,22 +10,38 @@ 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 = [
|
||||||
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 "$".`,
|
'\\t',
|
||||||
);
|
'\\s',
|
||||||
}
|
'\\n',
|
||||||
|
'\\r',
|
||||||
|
'\\f',
|
||||||
|
'\\v',
|
||||||
|
];
|
||||||
|
|
||||||
if (!pattern && example) {
|
if (pattern) {
|
||||||
errors.push(
|
if (disallowedStrings.some((str) => pattern.includes(str))) {
|
||||||
"You've provided a feature flag naming example, but no feature flag naming pattern. You must specify a pattern to use an example.",
|
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(
|
||||||
|
`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 (example) {
|
||||||
|
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.",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
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;
|
||||||
|
Loading…
Reference in New Issue
Block a user