object level override form (#11672)
This commit is contained in:
@ -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()
|
||||
@ -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,
|
||||
|
||||
@ -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({
|
||||
|
||||
@ -72,19 +72,12 @@ describe('roles permissions', () => {
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
const disablePermissionsQuery = updateFeatureFlagFactory(
|
||||
SEED_APPLE_WORKSPACE_ID,
|
||||
'IsPermissionsEnabled',
|
||||
false,
|
||||
);
|
||||
|
||||
const disablePermissionsV2Query = updateFeatureFlagFactory(
|
||||
SEED_APPLE_WORKSPACE_ID,
|
||||
'IsPermissionsV2Enabled',
|
||||
false,
|
||||
);
|
||||
|
||||
await makeGraphqlAPIRequest(disablePermissionsQuery);
|
||||
await makeGraphqlAPIRequest(disablePermissionsV2Query);
|
||||
});
|
||||
|
||||
@ -480,9 +473,10 @@ describe('roles permissions', () => {
|
||||
roleId: string;
|
||||
}) => `
|
||||
mutation UpsertObjectPermissions {
|
||||
upsertOneObjectPermission(upsertObjectPermissionInput: {objectMetadataId: "${objectMetadataId}", roleId: "${roleId}", canUpdateObjectRecords: true}) {
|
||||
upsertObjectPermissions(upsertObjectPermissionsInput: { roleId: "${roleId}", objectPermissions: [{objectMetadataId: "${objectMetadataId}", canUpdateObjectRecords: true}]}) {
|
||||
id
|
||||
roleId
|
||||
objectMetadataId
|
||||
canUpdateObjectRecords
|
||||
}
|
||||
}
|
||||
@ -540,12 +534,15 @@ describe('roles permissions', () => {
|
||||
.expect((res) => {
|
||||
expect(res.body.data).toBeDefined();
|
||||
expect(res.body.errors).toBeUndefined();
|
||||
expect(res.body.data.upsertOneObjectPermission.roleId).toBe(
|
||||
createdEditableRoleId,
|
||||
expect(res.body.data.upsertObjectPermissions).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
roleId: createdEditableRoleId,
|
||||
objectMetadataId: listingObjectId,
|
||||
canUpdateObjectRecords: true,
|
||||
}),
|
||||
]),
|
||||
);
|
||||
expect(
|
||||
res.body.data.upsertOneObjectPermission.canUpdateObjectRecords,
|
||||
).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user