diff --git a/src/lib/services/feature-toggle-service.ts b/src/lib/services/feature-toggle-service.ts index 3445a7629a..80f4c8d984 100644 --- a/src/lib/services/feature-toggle-service.ts +++ b/src/lib/services/feature-toggle-service.ts @@ -165,6 +165,14 @@ class FeatureToggleService { } } + async validateConstraints(constraints: IConstraint[]): Promise { + const validations = constraints.map((constraint) => { + return this.validateConstraint(constraint); + }); + + await Promise.all(validations); + } + async validateConstraint(constraint: IConstraint): Promise { const { operator } = constraint; await constraintSchema.validateAsync(constraint); @@ -272,6 +280,11 @@ class FeatureToggleService { ): Promise { const { featureName, projectId, environment } = context; await this.validateFeatureContext(context); + + if (strategyConfig.constraints?.length > 0) { + await this.validateConstraints(strategyConfig.constraints); + } + try { const newFeatureStrategy = await this.featureStrategiesStore.createStrategyFeatureEnv({ @@ -334,6 +347,10 @@ class FeatureToggleService { updates, ); + if (updates.constraints?.length > 0) { + await this.validateConstraints(updates.constraints); + } + // Store event! const tags = await this.tagStore.getAllTagsForFeature(featureName); const data = this.featureStrategyToPublic(strategy); diff --git a/src/lib/util/validators/constraint-types.test.ts b/src/lib/util/validators/constraint-types.test.ts index 74945e27b2..3a73824c6f 100644 --- a/src/lib/util/validators/constraint-types.test.ts +++ b/src/lib/util/validators/constraint-types.test.ts @@ -39,6 +39,19 @@ test('semver validation should fail partial semver', () => { } }); +test('semver validation should fail with leading v', () => { + const leadingV = 'v1.2.0'; + expect.assertions(1); + + try { + validateSemver(leadingV); + } catch (e) { + expect(e.message).toBe( + `the provided value is not a valid semver format. The value provided was: ${leadingV}`, + ); + } +}); + /* Legal values tests */ test('should fail validation if value does not exist in single legal value', () => { const legalValues = ['100', '200', '300']; diff --git a/src/lib/util/validators/constraint-types.ts b/src/lib/util/validators/constraint-types.ts index 6cbf56e704..588dd38e4b 100644 --- a/src/lib/util/validators/constraint-types.ts +++ b/src/lib/util/validators/constraint-types.ts @@ -16,9 +16,11 @@ export const validateString = async (value: unknown): Promise => { }; export const validateSemver = (value: unknown): void => { + const cleanValue = semver.clean(value) === value; + const result = semver.valid(value); - if (result) return; + if (result && cleanValue) return; throw new BadDataError( `the provided value is not a valid semver format. The value provided was: ${value}`, );