Skip to content

Commit 3e38748

Browse files
committed
chore: stricter wildcard variable validation
1 parent 1ede9c6 commit 3e38748

File tree

3 files changed

+53
-33
lines changed

3 files changed

+53
-33
lines changed

packages/backend/src/helpers/__tests__/compute-parameters.test.ts

Lines changed: 20 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -352,53 +352,48 @@ describe('compute parameters', () => {
352352

353353
it.each([
354354
{
355-
testDescription: 'wildcard on empty array',
356-
params: `empty!! {{step.${randomStepID}.emptyArrayProp.*}}`,
357-
expected: 'empty!! ',
358-
},
359-
{
360-
testDescription: 'wildcard on array of values',
361-
params: `{{step.${randomStepID}.arrayProp.*}}`,
362-
expected: 'array value 1, hehe, array value 3',
363-
},
364-
{
365-
testDescription: 'wildcard on array of objects to get strings',
355+
testDescription: 'compute wildcard on array of objects to get strings',
366356
params: `wildcard get strings {{step.${randomStepID}.arrayOfObjectsProp.*.stringProp}}`,
367357
expected:
368358
'wildcard get strings string value 1 in array of objects, string value 2 in array of objects',
369359
},
370360
{
371-
testDescription: 'wildcard on array of objects to get numbers',
361+
testDescription: 'compute wildcard on array of objects to get numbers',
372362
params: `wildcard get numbers {{step.${randomStepID}.arrayOfObjectsProp.*.numberProp}}`,
373363
expected: 'wildcard get numbers 456, 789',
374364
},
375365
{
376-
testDescription: 'wildcard on both strings and numbers',
366+
testDescription: 'compute wildcard on both strings and numbers',
377367
params: `wildcard get strings and numbers {{step.${randomStepID}.arrayOfObjectsProp.*.stringProp}} {{step.${randomStepID}.arrayOfObjectsProp.*.numberProp}}`,
378368
expected:
379369
'wildcard get strings and numbers string value 1 in array of objects, string value 2 in array of objects 456, 789',
380370
},
381371
{
382-
testDescription: 'wildcard on non-existent key',
383-
params: `non-existent key! {{step.${randomStepID}.non-existent-key.*}}`,
372+
testDescription: 'compute wildcard on non-existent key',
373+
params: `non-existent key! {{step.${randomStepID}.non-existent-key.*.id}}`,
384374
expected: 'non-existent key! ',
385375
},
386376
{
387-
testDescription: 'prop name with wildcard',
388-
params: `prop with wildcard {{step.${randomStepID}.stringWith*}}`,
389-
expected: 'prop with wildcard string value',
377+
testDescription: 'compute wildcard on a string',
378+
params: `wildcard on a string!! {{step.${randomStepID}.stringProp.*.id}}`,
379+
expected: 'wildcard on a string!! string value',
390380
},
391381
{
392-
testDescription: 'prop name with space and wildcard',
393-
params: `prop with space and wildcard! {{step.${randomStepID}.string with *}}`,
394-
expected: `prop with space and wildcard! string value 2`,
382+
testDescription: 'ignore wildcard at end of variable',
383+
params: `empty!! {{step.${randomStepID}.emptyArrayProp.*}}`,
384+
expected: `empty!! {{step.${randomStepID}.emptyArrayProp.*}}`,
395385
},
396386
{
397-
testDescription: 'wildcard on a string',
398-
params: `wildcard on a string!! {{step.${randomStepID}.stringProp.*}}`,
399-
expected: 'wildcard on a string!! string value',
387+
testDescription: 'ignore wildcard inside the key',
388+
params: `wildcard inside the key {{step.${randomStepID}.stringProp*}}`,
389+
expected: `wildcard inside the key {{step.${randomStepID}.stringProp*}}`,
390+
},
391+
{
392+
testDescription: 'ignore more than one wildcard inside the variable',
393+
params: `two wildcards inside the key {{step.${randomStepID}.*.stringProp.*}}`,
394+
expected: `two wildcards inside the key {{step.${randomStepID}.*.stringProp.*}}`,
400395
},
401-
])('should handle $testDescription', ({ params, expected }) => {
396+
])('should $testDescription', ({ params, expected }) => {
402397
const executionSteps = [
403398
{
404399
stepId: randomStepID,
@@ -418,8 +413,6 @@ describe('compute parameters', () => {
418413
numberProp: 789,
419414
},
420415
],
421-
'stringWith*': 'string value',
422-
'string with *': 'string value 2',
423416
},
424417
} as unknown as ExecutionStep,
425418
]

packages/backend/src/helpers/check-step-parameters.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { IJSONObject } from '@plumber/types'
22

3-
const VARIABLE_REGEX =
4-
/({{step\.[\da-f]{8}-(?:[\da-f]{4}-){3}[\da-f]{12}(?:\.[\w* -]+)+}})/
3+
import { VARIABLE_REGEX } from './compute-parameters'
4+
55
const GLOBAL_VARIABLE_REGEX = new RegExp(VARIABLE_REGEX, 'g')
66

77
/**

packages/backend/src/helpers/compute-parameters.ts

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,31 @@ import Step from '../models/step'
99

1010
const GET_ALL_SEPARATOR = ','
1111

12-
const variableRegExp =
13-
/({{step\.[\da-f]{8}-(?:[\da-f]{4}-){3}[\da-f]{12}(?:\.[\w* -]+)+}})/g
12+
export const VARIABLE_REGEX =
13+
/({{step\.[\da-f]{8}-(?:[\da-f]{4}-){3}[\da-f]{12}(?:\.(?:[\w -]+|\*))+}})/
14+
15+
function isVariableValid(path: string) {
16+
const rawPath = path.replace(/^{{step\.[^}]+?\./, '').replace(/}}$/, '')
17+
const segments = rawPath.split('.')
18+
const wildcardCount = segments.filter((s) => s === '*').length
19+
20+
if (
21+
wildcardCount > 1 ||
22+
segments[0] === '*' ||
23+
segments[segments.length - 1] === '*'
24+
) {
25+
return false
26+
}
27+
28+
return true
29+
}
1430

1531
function splitAndJoinAroundWildcard(arr: string[]) {
1632
const wildcardIndex = arr.indexOf('*')
33+
if (wildcardIndex === -1) {
34+
console.error("Wildcard '*' not found in array")
35+
return { before: arr.join('.'), after: '' }
36+
}
1737
return {
1838
before: arr.slice(0, wildcardIndex).join('.'),
1939
after: arr.slice(wildcardIndex + 1).join('.'),
@@ -59,11 +79,15 @@ function findAndSubstituteVariables(
5979
return rawValue
6080
}
6181

62-
const parts = rawValue.split(variableRegExp)
82+
const parts = rawValue.split(VARIABLE_REGEX)
6383

6484
return parts
6585
.map((part: string) => {
66-
const isVariable = part.match(variableRegExp)
86+
if (!isVariableValid(part)) {
87+
return part
88+
}
89+
90+
const isVariable = part.match(VARIABLE_REGEX)
6791
if (isVariable) {
6892
const stepIdAndKeyPath = part.replace(/{{step.|}}/g, '') as string
6993
const [stepId, ...keyPaths] = stepIdAndKeyPath.split('.')
@@ -80,6 +104,9 @@ function findAndSubstituteVariables(
80104
if (!base) {
81105
return ''
82106
}
107+
if (typeof base === 'string') {
108+
return base
109+
}
83110

84111
const values = after
85112
? map(base as Record<string, unknown>, after)

0 commit comments

Comments
 (0)