object level override form (#11672)

This commit is contained in:
Weiko
2025-04-24 18:15:43 +02:00
committed by GitHub
parent 48e2581581
commit e55ecb4dcd
25 changed files with 708 additions and 196 deletions

View File

@ -1,14 +1,30 @@
import { Field, InputType } from '@nestjs/graphql';
import { IsBoolean, IsNotEmpty, IsOptional, IsUUID } from 'class-validator';
import {
ArrayMinSize,
IsArray,
IsBoolean,
IsNotEmpty,
IsOptional,
IsUUID,
} from 'class-validator';
@InputType()
export class UpsertObjectPermissionInput {
export class UpsertObjectPermissionsInput {
@IsUUID()
@IsNotEmpty()
@Field()
roleId: string;
@IsArray()
@ArrayMinSize(1)
@IsNotEmpty()
@Field(() => [ObjectPermissionInput])
objectPermissions: ObjectPermissionInput[];
}
@InputType()
export class ObjectPermissionInput {
@IsUUID()
@IsNotEmpty()
@Field()

View File

@ -1,10 +1,10 @@
import { InjectRepository } from '@nestjs/typeorm';
import { isDefined } from 'twenty-shared/utils';
import { Repository } from 'typeorm';
import { In, Repository } from 'typeorm';
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
import { UpsertObjectPermissionInput } from 'src/engine/metadata-modules/object-permission/dtos/upsert-object-permission-input';
import { UpsertObjectPermissionsInput } from 'src/engine/metadata-modules/object-permission/dtos/upsert-object-permissions.input';
import { ObjectPermissionEntity } from 'src/engine/metadata-modules/object-permission/object-permission.entity';
import {
PermissionsException,
@ -25,24 +25,29 @@ export class ObjectPermissionService {
private readonly workspacePermissionsCacheService: WorkspacePermissionsCacheService,
) {}
public async upsertObjectPermission({
public async upsertObjectPermissions({
workspaceId,
input,
}: {
workspaceId: string;
input: UpsertObjectPermissionInput;
}): Promise<ObjectPermissionEntity | null> {
input: UpsertObjectPermissionsInput;
}): Promise<ObjectPermissionEntity[]> {
try {
await this.validateRoleIsEditableOrThrow({
roleId: input.roleId,
workspaceId,
});
const result = await this.objectPermissionRepository.upsert(
{
const objectPermissions = input.objectPermissions.map(
(objectPermission) => ({
...objectPermission,
roleId: input.roleId,
workspaceId,
...input,
},
}),
);
const result = await this.objectPermissionRepository.upsert(
objectPermissions,
{
conflictPaths: ['objectMetadataId', 'roleId'],
},
@ -61,9 +66,14 @@ export class ObjectPermissionService {
},
);
return this.objectPermissionRepository.findOne({
return this.objectPermissionRepository.find({
where: {
id: objectPermissionId,
roleId: input.roleId,
objectMetadataId: In(
input.objectPermissions.map(
(objectPermission) => objectPermission.objectMetadataId,
),
),
},
});
} catch (error) {
@ -71,7 +81,9 @@ export class ObjectPermissionService {
error,
roleId: input.roleId,
workspaceId,
objectMetadataId: input.objectMetadataId,
objectMetadataIds: input.objectPermissions.map(
(objectPermission) => objectPermission.objectMetadataId,
),
});
throw error;
@ -82,12 +94,12 @@ export class ObjectPermissionService {
error,
roleId,
workspaceId,
objectMetadataId,
objectMetadataIds,
}: {
error: Error;
roleId: string;
workspaceId: string;
objectMetadataId: string;
objectMetadataIds: string[];
}) {
if (error.message.includes('violates foreign key constraint')) {
const role = await this.roleRepository.findOne({
@ -104,14 +116,14 @@ export class ObjectPermissionService {
);
}
const objectMetadata = await this.objectMetadataRepository.findOne({
const objectMetadata = await this.objectMetadataRepository.find({
where: {
workspaceId,
id: objectMetadataId,
id: In(objectMetadataIds),
},
});
if (!isDefined(objectMetadata)) {
if (objectMetadata.length !== objectMetadataIds.length) {
throw new PermissionsException(
PermissionsExceptionMessage.OBJECT_METADATA_NOT_FOUND,
PermissionsExceptionCode.OBJECT_METADATA_NOT_FOUND,

View File

@ -17,7 +17,7 @@ import { AuthWorkspaceMemberId } from 'src/engine/decorators/auth/auth-workspace
import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorator';
import { SettingsPermissionsGuard } from 'src/engine/guards/settings-permissions.guard';
import { ObjectPermissionDTO } from 'src/engine/metadata-modules/object-permission/dtos/object-permission.dto';
import { UpsertObjectPermissionInput } from 'src/engine/metadata-modules/object-permission/dtos/upsert-object-permission-input';
import { UpsertObjectPermissionsInput } from 'src/engine/metadata-modules/object-permission/dtos/upsert-object-permissions.input';
import { ObjectPermissionService } from 'src/engine/metadata-modules/object-permission/object-permission.service';
import { SettingPermissionType } from 'src/engine/metadata-modules/permissions/constants/setting-permission-type.constants';
import {
@ -147,21 +147,18 @@ export class RoleResolver {
return deletedRoleId;
}
@Mutation(() => ObjectPermissionDTO)
async upsertOneObjectPermission(
@Mutation(() => [ObjectPermissionDTO])
async upsertObjectPermissions(
@AuthWorkspace() workspace: Workspace,
@Args('upsertObjectPermissionInput')
upsertObjectPermissionInput: UpsertObjectPermissionInput,
) {
@Args('upsertObjectPermissionsInput')
upsertObjectPermissionsInput: UpsertObjectPermissionsInput,
): Promise<ObjectPermissionDTO[]> {
await this.validatePermissionsV2EnabledOrThrow(workspace);
const objectPermission =
await this.objectPermissionService.upsertObjectPermission({
workspaceId: workspace.id,
input: upsertObjectPermissionInput,
});
return objectPermission;
return this.objectPermissionService.upsertObjectPermissions({
workspaceId: workspace.id,
input: upsertObjectPermissionsInput,
});
}
@Mutation(() => [SettingPermissionDTO])
@ -169,7 +166,7 @@ export class RoleResolver {
@AuthWorkspace() workspace: Workspace,
@Args('upsertSettingPermissionsInput')
upsertSettingPermissionsInput: UpsertSettingPermissionsInput,
) {
): Promise<SettingPermissionDTO[]> {
await this.validatePermissionsV2EnabledOrThrow(workspace);
return this.settingPermissionService.upsertSettingPermissions({