Feat/improve error management in core module (#8933)

## Summary
This Pull Request introduces a custom validator for checking forbidden
words in workspaces and refines how exceptions are handled within the
workspace module.

- Introduced `ForbiddenWords` custom class validator for validating
forbidden words against specific fields in `UpdateWorkspaceInput`.
- Added `EnvironmentService` usage in `WorkspaceService` to check
default subdomains.
- New file `workspaceGraphqlApiExceptionHandler` to handle GraphQL API
exceptions with specific error mappings.
- Expanded `WorkspaceExceptionCode` with `SUBDOMAIN_ALREADY_TAKEN`.
- Added new unit tests for validating forbidden words and exception
handler behavior.
This commit is contained in:
Antoine Moreaux
2024-12-07 16:48:53 +01:00
committed by GitHub
parent 99f53a5030
commit 2524d64687
8 changed files with 188 additions and 7 deletions

View File

@ -0,0 +1,38 @@
import { validate } from 'class-validator';
import { ForbiddenWords } from 'src/engine/utils/custom-class-validator/ForbiddenWords';
describe('ForbiddenWordsConstraint', () => {
test('should throw error when word is forbidden', async () => {
class Test {
@ForbiddenWords(['forbidden', 'restricted'])
subdomain: string;
}
const instance = new Test();
instance.subdomain = 'forbidden';
const errors = await validate(instance);
expect(errors.length).toBeGreaterThan(0);
expect(errors[0].constraints).toEqual({
ForbiddenWordsConstraint: 'forbidden, restricted are not allowed',
});
});
test('should pass validation word is not in the list', async () => {
class Test {
@ForbiddenWords(['forbidden', 'restricted'])
subdomain: string;
}
const instance = new Test();
instance.subdomain = 'valid';
const errors = await validate(instance);
expect(errors.length).toEqual(0);
});
});

View File

@ -0,0 +1,39 @@
import {
registerDecorator,
ValidationArguments,
ValidationOptions,
ValidatorConstraint,
ValidatorConstraintInterface,
} from 'class-validator';
@ValidatorConstraint({ async: false })
export class ForbiddenWordsConstraint implements ValidatorConstraintInterface {
private forbiddenWords: Set<string>;
constructor() {}
validate(value: string, validationArguments: ValidationArguments) {
this.forbiddenWords = new Set(validationArguments.constraints[0]);
return !this.forbiddenWords.has(value);
}
defaultMessage() {
return `${Array.from(this.forbiddenWords).join(', ')} are not allowed`;
}
}
export function ForbiddenWords(
forbiddenWords: string[],
validationOptions?: ValidationOptions,
) {
return function (object: object, propertyName: string) {
registerDecorator({
target: object.constructor,
propertyName: propertyName,
options: validationOptions,
constraints: [forbiddenWords],
validator: ForbiddenWordsConstraint,
});
};
}