add settings permissions update (#11377)
Fixes https://github.com/twentyhq/core-team-issues/issues/710
This commit is contained in:
@ -4,6 +4,7 @@ import { Relation } from 'typeorm';
|
||||
|
||||
import { WorkspaceMember } from 'src/engine/core-modules/user/dtos/workspace-member.dto';
|
||||
import { UserWorkspaceRoleEntity } from 'src/engine/metadata-modules/role/user-workspace-role.entity';
|
||||
import { SettingPermissionDTO } from 'src/engine/metadata-modules/setting-permission/dtos/setting-permission.dto';
|
||||
|
||||
@ObjectType('Role')
|
||||
export class RoleDTO {
|
||||
@ -42,4 +43,7 @@ export class RoleDTO {
|
||||
|
||||
@Field({ nullable: false })
|
||||
canDestroyAllObjectRecords: boolean;
|
||||
|
||||
@Field(() => [SettingPermissionDTO], { nullable: true })
|
||||
settingPermissions?: SettingPermissionDTO[];
|
||||
}
|
||||
|
||||
@ -31,7 +31,7 @@ import { RoleDTO } from 'src/engine/metadata-modules/role/dtos/role.dto';
|
||||
import { UpdateRoleInput } from 'src/engine/metadata-modules/role/dtos/update-role-input.dto';
|
||||
import { RoleService } from 'src/engine/metadata-modules/role/role.service';
|
||||
import { SettingPermissionDTO } from 'src/engine/metadata-modules/setting-permission/dtos/setting-permission.dto';
|
||||
import { UpsertSettingPermissionInput } from 'src/engine/metadata-modules/setting-permission/dtos/upsert-setting-permission-input';
|
||||
import { UpsertSettingPermissionsInput } from 'src/engine/metadata-modules/setting-permission/dtos/upsert-setting-permission-input';
|
||||
import { SettingPermissionService } from 'src/engine/metadata-modules/setting-permission/setting-permission.service';
|
||||
import { UserRoleService } from 'src/engine/metadata-modules/user-role/user-role.service';
|
||||
import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity';
|
||||
@ -154,17 +154,17 @@ export class RoleResolver {
|
||||
});
|
||||
}
|
||||
|
||||
@Mutation(() => SettingPermissionDTO)
|
||||
async upsertOneSettingPermission(
|
||||
@Mutation(() => [SettingPermissionDTO])
|
||||
async upsertSettingPermissions(
|
||||
@AuthWorkspace() workspace: Workspace,
|
||||
@Args('upsertSettingPermissionInput')
|
||||
upsertSettingPermissionInput: UpsertSettingPermissionInput,
|
||||
@Args('upsertSettingPermissionsInput')
|
||||
upsertSettingPermissionsInput: UpsertSettingPermissionsInput,
|
||||
) {
|
||||
await this.validatePermissionsV2EnabledOrThrow(workspace);
|
||||
|
||||
return this.settingPermissionService.upsertSettingPermission({
|
||||
return this.settingPermissionService.upsertSettingPermissions({
|
||||
workspaceId: workspace.id,
|
||||
input: upsertSettingPermissionInput,
|
||||
input: upsertSettingPermissionsInput,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -37,7 +37,7 @@ export class RoleService {
|
||||
where: {
|
||||
workspaceId,
|
||||
},
|
||||
relations: ['userWorkspaceRoles'],
|
||||
relations: ['userWorkspaceRoles', 'settingPermissions'],
|
||||
});
|
||||
}
|
||||
|
||||
@ -50,7 +50,7 @@ export class RoleService {
|
||||
id,
|
||||
workspaceId,
|
||||
},
|
||||
relations: ['userWorkspaceRoles'],
|
||||
relations: ['userWorkspaceRoles', 'settingPermissions'],
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -12,7 +12,4 @@ export class SettingPermissionDTO {
|
||||
|
||||
@Field({ nullable: false })
|
||||
setting: SettingPermissionType;
|
||||
|
||||
@Field({ nullable: true })
|
||||
canUpdateSetting?: boolean;
|
||||
}
|
||||
|
||||
@ -1,29 +1,18 @@
|
||||
import { Field, InputType } from '@nestjs/graphql';
|
||||
|
||||
import {
|
||||
IsBoolean,
|
||||
IsNotEmpty,
|
||||
IsOptional,
|
||||
IsString,
|
||||
IsUUID,
|
||||
} from 'class-validator';
|
||||
import { IsArray, IsEnum, IsNotEmpty, IsUUID } from 'class-validator';
|
||||
|
||||
import { SettingPermissionType } from 'src/engine/metadata-modules/permissions/constants/setting-permission-type.constants';
|
||||
|
||||
@InputType()
|
||||
export class UpsertSettingPermissionInput {
|
||||
export class UpsertSettingPermissionsInput {
|
||||
@IsUUID()
|
||||
@IsNotEmpty()
|
||||
@Field()
|
||||
roleId: string;
|
||||
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
@Field({ nullable: false })
|
||||
setting: SettingPermissionType;
|
||||
|
||||
@IsBoolean()
|
||||
@IsOptional()
|
||||
@Field({ nullable: true })
|
||||
canUpdateSetting?: boolean;
|
||||
@IsArray()
|
||||
@IsEnum(SettingPermissionType, { each: true })
|
||||
@Field(() => [SettingPermissionType])
|
||||
settingPermissionKeys: SettingPermissionType[];
|
||||
}
|
||||
|
||||
@ -31,9 +31,6 @@ export class SettingPermissionEntity {
|
||||
@Column({ nullable: false, type: 'varchar' })
|
||||
setting: SettingPermissionType;
|
||||
|
||||
@Column({ nullable: true, type: 'boolean' })
|
||||
canUpdateSetting?: boolean;
|
||||
|
||||
@Column({ nullable: false, type: 'uuid' })
|
||||
workspaceId: string;
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
import { InjectDataSource, InjectRepository } from '@nestjs/typeorm';
|
||||
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { Repository } from 'typeorm';
|
||||
import { DataSource, In, Repository } from 'typeorm';
|
||||
|
||||
import { SettingPermissionType } from 'src/engine/metadata-modules/permissions/constants/setting-permission-type.constants';
|
||||
import {
|
||||
@ -10,7 +10,7 @@ import {
|
||||
PermissionsExceptionMessage,
|
||||
} from 'src/engine/metadata-modules/permissions/permissions.exception';
|
||||
import { RoleEntity } from 'src/engine/metadata-modules/role/role.entity';
|
||||
import { UpsertSettingPermissionInput } from 'src/engine/metadata-modules/setting-permission/dtos/upsert-setting-permission-input';
|
||||
import { UpsertSettingPermissionsInput } from 'src/engine/metadata-modules/setting-permission/dtos/upsert-setting-permission-input';
|
||||
import { SettingPermissionEntity } from 'src/engine/metadata-modules/setting-permission/setting-permission.entity';
|
||||
|
||||
export class SettingPermissionService {
|
||||
@ -19,55 +19,90 @@ export class SettingPermissionService {
|
||||
private readonly settingPermissionRepository: Repository<SettingPermissionEntity>,
|
||||
@InjectRepository(RoleEntity, 'metadata')
|
||||
private readonly roleRepository: Repository<RoleEntity>,
|
||||
@InjectDataSource('metadata')
|
||||
private readonly metadataDataSource: DataSource,
|
||||
) {}
|
||||
|
||||
public async upsertSettingPermission({
|
||||
public async upsertSettingPermissions({
|
||||
workspaceId,
|
||||
input,
|
||||
}: {
|
||||
workspaceId: string;
|
||||
input: UpsertSettingPermissionInput;
|
||||
}): Promise<SettingPermissionEntity | null | undefined> {
|
||||
input: UpsertSettingPermissionsInput;
|
||||
}): Promise<SettingPermissionEntity[]> {
|
||||
await this.validateRoleIsEditableOrThrow({
|
||||
roleId: input.roleId,
|
||||
workspaceId,
|
||||
});
|
||||
|
||||
if (!Object.values(SettingPermissionType).includes(input.setting)) {
|
||||
const invalidSettings = input.settingPermissionKeys.filter(
|
||||
(setting) => !Object.values(SettingPermissionType).includes(setting),
|
||||
);
|
||||
|
||||
if (invalidSettings.length > 0) {
|
||||
throw new PermissionsException(
|
||||
PermissionsExceptionMessage.INVALID_SETTING,
|
||||
`${PermissionsExceptionMessage.INVALID_SETTING}: ${invalidSettings.join(', ')}`,
|
||||
PermissionsExceptionCode.INVALID_SETTING,
|
||||
);
|
||||
}
|
||||
|
||||
const queryRunner = this.metadataDataSource.createQueryRunner();
|
||||
|
||||
await queryRunner.connect();
|
||||
await queryRunner.startTransaction();
|
||||
|
||||
try {
|
||||
const result = await this.settingPermissionRepository.upsert(
|
||||
const existingPermissions = await queryRunner.manager.find(
|
||||
SettingPermissionEntity,
|
||||
{
|
||||
workspaceId,
|
||||
...input,
|
||||
},
|
||||
{
|
||||
conflictPaths: ['setting', 'roleId'],
|
||||
where: {
|
||||
roleId: input.roleId,
|
||||
workspaceId,
|
||||
},
|
||||
},
|
||||
);
|
||||
const existingSettings = new Set(
|
||||
existingPermissions.map((p) => p.setting),
|
||||
);
|
||||
const inputSettings = new Set(input.settingPermissionKeys);
|
||||
|
||||
const settingPermissionId = result.generatedMaps?.[0]?.id;
|
||||
const settingsToAdd = input.settingPermissionKeys.filter(
|
||||
(setting) => !existingSettings.has(setting),
|
||||
);
|
||||
const permissionsToRemove = existingPermissions.filter(
|
||||
(permission) => !inputSettings.has(permission.setting),
|
||||
);
|
||||
|
||||
if (!isDefined(settingPermissionId)) {
|
||||
throw new Error('Failed to upsert setting permission');
|
||||
if (permissionsToRemove.length > 0) {
|
||||
await queryRunner.manager.delete(SettingPermissionEntity, {
|
||||
id: In(permissionsToRemove.map((p) => p.id)),
|
||||
});
|
||||
}
|
||||
|
||||
return this.settingPermissionRepository.findOne({
|
||||
where: {
|
||||
id: settingPermissionId,
|
||||
},
|
||||
if (settingsToAdd.length > 0) {
|
||||
const newPermissions = settingsToAdd.map((setting) =>
|
||||
queryRunner.manager.create(SettingPermissionEntity, {
|
||||
workspaceId,
|
||||
roleId: input.roleId,
|
||||
setting,
|
||||
}),
|
||||
);
|
||||
|
||||
await queryRunner.manager.save(SettingPermissionEntity, newPermissions);
|
||||
}
|
||||
|
||||
await queryRunner.commitTransaction();
|
||||
|
||||
return queryRunner.manager.find(SettingPermissionEntity, {
|
||||
where: { roleId: input.roleId, workspaceId },
|
||||
order: { setting: 'ASC' },
|
||||
});
|
||||
} catch (error) {
|
||||
await queryRunner.rollbackTransaction();
|
||||
|
||||
if (error.message.includes('violates foreign key constraint')) {
|
||||
const role = await this.roleRepository.findOne({
|
||||
where: {
|
||||
id: input.roleId,
|
||||
},
|
||||
where: { id: input.roleId },
|
||||
});
|
||||
|
||||
if (!isDefined(role)) {
|
||||
@ -77,8 +112,9 @@ export class SettingPermissionService {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
throw error;
|
||||
} finally {
|
||||
await queryRunner.release();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user