Fix select default value not in options (#11622)

Also fixing a bunch of places where validation exceptions were not
properly handled
This commit is contained in:
Weiko
2025-04-17 18:34:31 +02:00
committed by GitHub
parent dd1ac4deee
commit 3fe12cd8b5
6 changed files with 141 additions and 26 deletions
@@ -1,9 +1,12 @@
import { BadRequestException, UnauthorizedException } from '@nestjs/common';
import { Test, TestingModule } from '@nestjs/testing';
import { i18n } from '@lingui/core';
import { UpdateOneInputType } from '@ptc-org/nestjs-query-graphql';
import {
ForbiddenError,
ValidationError,
} from 'src/engine/core-modules/graphql/utils/graphql-errors.util';
import { UpdateFieldInput } from 'src/engine/metadata-modules/field-metadata/dtos/update-field.input';
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
import { FieldMetadataService } from 'src/engine/metadata-modules/field-metadata/field-metadata.service';
@@ -48,7 +51,7 @@ describe('BeforeUpdateOneField', () => {
jest.clearAllMocks();
});
it('should throw UnauthorizedException if workspaceId is not provided', async () => {
it('should throw ForbiddenError if workspaceId is not provided', async () => {
const instance: UpdateOneInputType<UpdateFieldInputForTest> = {
id: mockFieldId,
update: {
@@ -61,10 +64,10 @@ describe('BeforeUpdateOneField', () => {
workspaceId: '',
locale: undefined,
}),
).rejects.toThrow(UnauthorizedException);
).rejects.toThrow(ForbiddenError);
});
it('should throw BadRequestException if field does not exist', async () => {
it('should throw ValidationError if field does not exist', async () => {
const instance: UpdateOneInputType<UpdateFieldInputForTest> = {
id: mockFieldId,
update: {
@@ -81,7 +84,7 @@ describe('BeforeUpdateOneField', () => {
workspaceId: mockWorkspaceId,
locale: undefined,
}),
).rejects.toThrow(BadRequestException);
).rejects.toThrow(ValidationError);
});
it('should not affect custom fields', async () => {
@@ -113,7 +116,7 @@ describe('BeforeUpdateOneField', () => {
expect(result).toEqual(instance);
});
it('should throw BadRequestException when trying to update non-updatable fields on standard fields', async () => {
it('should throw ValidationError when trying to update non-updatable fields on standard fields', async () => {
const instance: UpdateOneInputType<UpdateFieldInputForTest> = {
id: mockFieldId,
update: {
@@ -135,10 +138,10 @@ describe('BeforeUpdateOneField', () => {
workspaceId: mockWorkspaceId,
locale: undefined,
}),
).rejects.toThrow(BadRequestException);
).rejects.toThrow(ValidationError);
});
it('should throw BadRequestException when trying to update label when it is synced with name', async () => {
it('should throw ValidationError when trying to update label when it is synced with name', async () => {
const instance: UpdateOneInputType<UpdateFieldInputForTest> = {
id: mockFieldId,
update: {
@@ -162,7 +165,7 @@ describe('BeforeUpdateOneField', () => {
workspaceId: mockWorkspaceId,
locale: undefined,
}),
).rejects.toThrow(BadRequestException);
).rejects.toThrow(ValidationError);
});
it('should handle isActive updates for standard fields', async () => {
@@ -1,8 +1,4 @@
import {
BadRequestException,
Injectable,
UnauthorizedException,
} from '@nestjs/common';
import { Injectable } from '@nestjs/common';
import { i18n } from '@lingui/core';
import {
@@ -12,6 +8,10 @@ import {
import { APP_LOCALES, SOURCE_LOCALE } from 'twenty-shared/translations';
import { isDefined } from 'twenty-shared/utils';
import {
ForbiddenError,
ValidationError,
} from 'src/engine/core-modules/graphql/utils/graphql-errors.util';
import { generateMessageId } from 'src/engine/core-modules/i18n/utils/generateMessageId';
import { FieldStandardOverridesDTO } from 'src/engine/metadata-modules/field-metadata/dtos/field-standard-overrides.dto';
import { UpdateFieldInput } from 'src/engine/metadata-modules/field-metadata/dtos/update-field.input';
@@ -39,7 +39,7 @@ export class BeforeUpdateOneField<T extends UpdateFieldInput>
},
): Promise<UpdateOneInputType<T>> {
if (!workspaceId) {
throw new UnauthorizedException();
throw new ForbiddenError('Could not retrieve workspace ID');
}
const fieldMetadata = await this.getFieldMetadata(instance, workspaceId);
@@ -63,7 +63,7 @@ export class BeforeUpdateOneField<T extends UpdateFieldInput>
});
if (!fieldMetadata) {
throw new BadRequestException('Field does not exist');
throw new ValidationError('Field does not exist');
}
return fieldMetadata;
@@ -96,13 +96,13 @@ export class BeforeUpdateOneField<T extends UpdateFieldInput>
instance.update.label !== fieldMetadata.label;
if (isUpdatingLabelWhenSynced) {
throw new BadRequestException(
throw new ValidationError(
'Cannot update label when it is synced with name',
);
}
if (nonUpdatableFields.length > 0) {
throw new BadRequestException(
throw new ValidationError(
`Only isActive, isLabelSyncedWithName, label, icon, description and defaultValue fields can be updated for standard fields. Invalid fields: ${nonUpdatableFields.join(', ')}`,
);
}