Fix missing name validation on object names at update (#5434)
## Context as per title ## How was it tested? local (/metadata + in product)
This commit is contained in:
@ -0,0 +1,63 @@
|
||||
import { UpdateObjectPayload } from 'src/engine/metadata-modules/object-metadata/dtos/update-object.input';
|
||||
import { validateObjectMetadataInputOrThrow } from 'src/engine/metadata-modules/object-metadata/utils/validate-object-metadata-input.util';
|
||||
|
||||
const validObjectInput: UpdateObjectPayload = {
|
||||
labelPlural: 'Car',
|
||||
labelSingular: 'Cars',
|
||||
nameSingular: 'car',
|
||||
namePlural: 'cars',
|
||||
};
|
||||
|
||||
const reservedKeyword = 'user';
|
||||
|
||||
describe('validateObjectName', () => {
|
||||
it('should not throw if names are valid', () => {
|
||||
expect(() =>
|
||||
validateObjectMetadataInputOrThrow(validObjectInput),
|
||||
).not.toThrow();
|
||||
});
|
||||
|
||||
it('should throw is nameSingular has invalid characters', () => {
|
||||
const invalidObjectInput = {
|
||||
...validObjectInput,
|
||||
nameSingular: 'μ',
|
||||
};
|
||||
|
||||
expect(() =>
|
||||
validateObjectMetadataInputOrThrow(invalidObjectInput),
|
||||
).toThrow();
|
||||
});
|
||||
|
||||
it('should throw is namePlural has invalid characters', () => {
|
||||
const invalidObjectInput = {
|
||||
...validObjectInput,
|
||||
namePlural: 'μ',
|
||||
};
|
||||
|
||||
expect(() =>
|
||||
validateObjectMetadataInputOrThrow(invalidObjectInput),
|
||||
).toThrow();
|
||||
});
|
||||
|
||||
it('should throw if nameSingular is a reserved keyword', async () => {
|
||||
const invalidObjectInput = {
|
||||
...validObjectInput,
|
||||
nameSingular: reservedKeyword,
|
||||
};
|
||||
|
||||
expect(() =>
|
||||
validateObjectMetadataInputOrThrow(invalidObjectInput),
|
||||
).toThrow();
|
||||
});
|
||||
|
||||
it('should throw if namePlural is a reserved keyword', async () => {
|
||||
const invalidObjectInput = {
|
||||
...validObjectInput,
|
||||
namePlural: reservedKeyword,
|
||||
};
|
||||
|
||||
expect(() =>
|
||||
validateObjectMetadataInputOrThrow(invalidObjectInput),
|
||||
).toThrow();
|
||||
});
|
||||
});
|
||||
@ -1,27 +1,70 @@
|
||||
import { BadRequestException } from '@nestjs/common';
|
||||
import { BadRequestException, ForbiddenException } from '@nestjs/common';
|
||||
|
||||
import { InvalidStringException } from 'src/engine/metadata-modules/errors/InvalidStringException';
|
||||
import { CreateObjectInput } from 'src/engine/metadata-modules/object-metadata/dtos/create-object.input';
|
||||
import { UpdateObjectPayload } from 'src/engine/metadata-modules/object-metadata/dtos/update-object.input';
|
||||
import { validateMetadataName } from 'src/engine/metadata-modules/utils/validate-metadata-name.utils';
|
||||
|
||||
export const validateObjectMetadataInput = <
|
||||
const coreObjectNames = [
|
||||
'appToken',
|
||||
'billingSubscription',
|
||||
'billingSubscriptions',
|
||||
'billingSubscriptionItem',
|
||||
'billingSubscriptionItems',
|
||||
'featureFlag',
|
||||
'user',
|
||||
'users',
|
||||
'userWorkspace',
|
||||
'userWorkspaces',
|
||||
'workspace',
|
||||
'workspaces',
|
||||
];
|
||||
|
||||
const reservedKeywords = [
|
||||
...coreObjectNames,
|
||||
'event',
|
||||
'events',
|
||||
'field',
|
||||
'fields',
|
||||
'link',
|
||||
'links',
|
||||
'currency',
|
||||
'currencies',
|
||||
'fullName',
|
||||
'fullNames',
|
||||
'address',
|
||||
'addresses',
|
||||
];
|
||||
|
||||
export const validateObjectMetadataInputOrThrow = <
|
||||
T extends UpdateObjectPayload | CreateObjectInput,
|
||||
>(
|
||||
objectMetadataInput: T,
|
||||
): void => {
|
||||
try {
|
||||
if (objectMetadataInput.nameSingular) {
|
||||
validateMetadataName(objectMetadataInput.nameSingular);
|
||||
}
|
||||
validateNameCharactersOrThrow(objectMetadataInput.nameSingular);
|
||||
validateNameCharactersOrThrow(objectMetadataInput.namePlural);
|
||||
|
||||
if (objectMetadataInput.namePlural) {
|
||||
validateMetadataName(objectMetadataInput.namePlural);
|
||||
validateNameIsNotReservedKeywordOrThrow(objectMetadataInput.nameSingular);
|
||||
validateNameIsNotReservedKeywordOrThrow(objectMetadataInput.namePlural);
|
||||
};
|
||||
|
||||
const validateNameIsNotReservedKeywordOrThrow = (name?: string) => {
|
||||
if (name) {
|
||||
if (reservedKeywords.includes(name)) {
|
||||
throw new ForbiddenException(`The name "${name}" is not available`);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const validateNameCharactersOrThrow = (name?: string) => {
|
||||
try {
|
||||
if (name) {
|
||||
validateMetadataName(name);
|
||||
}
|
||||
} catch (error) {
|
||||
if (error instanceof InvalidStringException) {
|
||||
throw new BadRequestException(
|
||||
`Characters used in name "${objectMetadataInput.nameSingular}" or "${objectMetadataInput.namePlural}" are not supported`,
|
||||
`Characters used in name "${name}" are not supported`,
|
||||
);
|
||||
} else {
|
||||
throw error;
|
||||
|
||||
Reference in New Issue
Block a user