Add settings permissions check on FE (#11425)
## Context Now that we can update role settings permissions, we need to reflect that on the FE as well (hiding/showing nav items + redirection logic). Feature flag check here is not really needed because since not having any setting permission will result in the same behavior as Permission V1. This PR updates the resolvers to return settings permissions of the current user
This commit is contained in:
@ -190,7 +190,7 @@ export abstract class GraphqlQueryBaseResolverService<
|
||||
const userHasPermission =
|
||||
await this.permissionsService.userHasWorkspaceSettingPermission({
|
||||
userWorkspaceId: authContext.userWorkspaceId,
|
||||
_setting: permissionRequired,
|
||||
setting: permissionRequired,
|
||||
workspaceId: authContext.workspace.id,
|
||||
isExecutedByApiKey: isDefined(authContext.apiKey),
|
||||
});
|
||||
|
||||
@ -163,7 +163,7 @@ export class BillingResolver {
|
||||
await this.permissionsService.userHasWorkspaceSettingPermission({
|
||||
userWorkspaceId,
|
||||
workspaceId,
|
||||
_setting: SettingPermissionType.WORKSPACE,
|
||||
setting: SettingPermissionType.WORKSPACE,
|
||||
isExecutedByApiKey,
|
||||
});
|
||||
|
||||
|
||||
@ -441,7 +441,7 @@ export class WorkspaceService extends TypeOrmQueryService<Workspace> {
|
||||
const userHasPermission =
|
||||
await this.permissionsService.userHasWorkspaceSettingPermission({
|
||||
userWorkspaceId,
|
||||
_setting: SettingPermissionType.SECURITY,
|
||||
setting: SettingPermissionType.SECURITY,
|
||||
workspaceId: workspaceId,
|
||||
isExecutedByApiKey: isDefined(apiKey),
|
||||
});
|
||||
@ -480,7 +480,7 @@ export class WorkspaceService extends TypeOrmQueryService<Workspace> {
|
||||
await this.permissionsService.userHasWorkspaceSettingPermission({
|
||||
userWorkspaceId,
|
||||
workspaceId,
|
||||
_setting: SettingPermissionType.WORKSPACE,
|
||||
setting: SettingPermissionType.WORKSPACE,
|
||||
isExecutedByApiKey: isDefined(apiKey),
|
||||
});
|
||||
|
||||
|
||||
@ -32,7 +32,7 @@ export const SettingsPermissionsGuard = (
|
||||
const hasPermission =
|
||||
await this.permissionsService.userHasWorkspaceSettingPermission({
|
||||
userWorkspaceId,
|
||||
_setting: requiredPermission,
|
||||
setting: requiredPermission,
|
||||
workspaceId,
|
||||
isExecutedByApiKey: isDefined(ctx.getContext().req.apiKey),
|
||||
});
|
||||
|
||||
@ -7,6 +7,7 @@ import { UserWorkspace } from 'src/engine/core-modules/user-workspace/user-works
|
||||
import { PermissionsService } from 'src/engine/metadata-modules/permissions/permissions.service';
|
||||
import { RoleEntity } from 'src/engine/metadata-modules/role/role.entity';
|
||||
import { UserWorkspaceRoleEntity } from 'src/engine/metadata-modules/role/user-workspace-role.entity';
|
||||
import { SettingPermissionEntity } from 'src/engine/metadata-modules/setting-permission/setting-permission.entity';
|
||||
import { UserRoleModule } from 'src/engine/metadata-modules/user-role/user-role.module';
|
||||
|
||||
@Module({
|
||||
@ -16,6 +17,7 @@ import { UserRoleModule } from 'src/engine/metadata-modules/user-role/user-role.
|
||||
TypeOrmModule.forFeature([UserWorkspace], 'core'),
|
||||
EnvironmentModule,
|
||||
UserRoleModule,
|
||||
TypeOrmModule.forFeature([SettingPermissionEntity], 'metadata'),
|
||||
],
|
||||
providers: [PermissionsService],
|
||||
exports: [PermissionsService],
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
|
||||
import { PermissionsOnAllObjectRecords } from 'twenty-shared/constants';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { Repository } from 'typeorm';
|
||||
|
||||
import {
|
||||
AuthException,
|
||||
@ -15,6 +17,7 @@ import {
|
||||
PermissionsExceptionMessage,
|
||||
} from 'src/engine/metadata-modules/permissions/permissions.exception';
|
||||
import { RoleEntity } from 'src/engine/metadata-modules/role/role.entity';
|
||||
import { SettingPermissionEntity } from 'src/engine/metadata-modules/setting-permission/setting-permission.entity';
|
||||
import { UserRoleService } from 'src/engine/metadata-modules/user-role/user-role.service';
|
||||
|
||||
@Injectable()
|
||||
@ -22,6 +25,8 @@ export class PermissionsService {
|
||||
constructor(
|
||||
private readonly environmentService: EnvironmentService,
|
||||
private readonly userRoleService: UserRoleService,
|
||||
@InjectRepository(SettingPermissionEntity, 'metadata')
|
||||
private readonly settingPermissionRepository: Repository<SettingPermissionEntity>,
|
||||
) {}
|
||||
|
||||
public async getUserWorkspacePermissions({
|
||||
@ -43,14 +48,27 @@ export class PermissionsService {
|
||||
|
||||
let hasPermissionOnSettingFeature = false;
|
||||
|
||||
if (roleOfUserWorkspace?.canUpdateAllSettings === true) {
|
||||
if (!isDefined(roleOfUserWorkspace)) {
|
||||
throw new PermissionsException(
|
||||
PermissionsExceptionMessage.NO_ROLE_FOUND_FOR_USER_WORKSPACE,
|
||||
PermissionsExceptionCode.NO_ROLE_FOUND_FOR_USER_WORKSPACE,
|
||||
);
|
||||
}
|
||||
|
||||
if (roleOfUserWorkspace.canUpdateAllSettings === true) {
|
||||
hasPermissionOnSettingFeature = true;
|
||||
}
|
||||
|
||||
const settingPermissions = roleOfUserWorkspace.settingPermissions ?? [];
|
||||
|
||||
const settingsPermissionsMap = Object.keys(SettingPermissionType).reduce(
|
||||
(acc, feature) => ({
|
||||
...acc,
|
||||
[feature]: hasPermissionOnSettingFeature,
|
||||
[feature]:
|
||||
hasPermissionOnSettingFeature ||
|
||||
settingPermissions.some(
|
||||
(settingPermission) => settingPermission.setting === feature,
|
||||
),
|
||||
}),
|
||||
{} as Record<SettingPermissionType, boolean>,
|
||||
);
|
||||
@ -60,13 +78,13 @@ export class PermissionsService {
|
||||
boolean
|
||||
> = {
|
||||
[PermissionsOnAllObjectRecords.READ_ALL_OBJECT_RECORDS]:
|
||||
roleOfUserWorkspace?.canReadAllObjectRecords ?? false,
|
||||
roleOfUserWorkspace.canReadAllObjectRecords ?? false,
|
||||
[PermissionsOnAllObjectRecords.UPDATE_ALL_OBJECT_RECORDS]:
|
||||
roleOfUserWorkspace?.canUpdateAllObjectRecords ?? false,
|
||||
roleOfUserWorkspace.canUpdateAllObjectRecords ?? false,
|
||||
[PermissionsOnAllObjectRecords.SOFT_DELETE_ALL_OBJECT_RECORDS]:
|
||||
roleOfUserWorkspace?.canSoftDeleteAllObjectRecords ?? false,
|
||||
roleOfUserWorkspace.canSoftDeleteAllObjectRecords ?? false,
|
||||
[PermissionsOnAllObjectRecords.DESTROY_ALL_OBJECT_RECORDS]:
|
||||
roleOfUserWorkspace?.canDestroyAllObjectRecords ?? false,
|
||||
roleOfUserWorkspace.canDestroyAllObjectRecords ?? false,
|
||||
};
|
||||
|
||||
return {
|
||||
@ -78,12 +96,12 @@ export class PermissionsService {
|
||||
public async userHasWorkspaceSettingPermission({
|
||||
userWorkspaceId,
|
||||
workspaceId,
|
||||
_setting,
|
||||
setting,
|
||||
isExecutedByApiKey,
|
||||
}: {
|
||||
userWorkspaceId?: string;
|
||||
workspaceId: string;
|
||||
_setting: SettingPermissionType;
|
||||
setting: SettingPermissionType;
|
||||
isExecutedByApiKey: boolean;
|
||||
}): Promise<boolean> {
|
||||
if (isExecutedByApiKey) {
|
||||
@ -104,11 +122,22 @@ export class PermissionsService {
|
||||
})
|
||||
.then((roles) => roles?.get(userWorkspaceId) ?? []);
|
||||
|
||||
if (roleOfUserWorkspace?.canUpdateAllSettings === true) {
|
||||
if (!isDefined(roleOfUserWorkspace)) {
|
||||
throw new PermissionsException(
|
||||
PermissionsExceptionMessage.NO_ROLE_FOUND_FOR_USER_WORKSPACE,
|
||||
PermissionsExceptionCode.NO_ROLE_FOUND_FOR_USER_WORKSPACE,
|
||||
);
|
||||
}
|
||||
|
||||
if (roleOfUserWorkspace.canUpdateAllSettings === true) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
const settingPermissions = roleOfUserWorkspace.settingPermissions ?? [];
|
||||
|
||||
return settingPermissions.some(
|
||||
(settingPermission) => settingPermission.setting === setting,
|
||||
);
|
||||
}
|
||||
|
||||
public async userHasObjectRecordsPermission({
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
|
||||
import { In, Not, Repository } from 'typeorm';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { In, Not, Repository } from 'typeorm';
|
||||
|
||||
import { UserWorkspace } from 'src/engine/core-modules/user-workspace/user-workspace.entity';
|
||||
import { ADMIN_ROLE_LABEL } from 'src/engine/metadata-modules/permissions/constants/admin-role-label.constants';
|
||||
@ -75,7 +75,9 @@ export class UserRoleService {
|
||||
workspaceId,
|
||||
},
|
||||
relations: {
|
||||
role: true,
|
||||
role: {
|
||||
settingPermissions: true,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@ -54,7 +54,7 @@ export class WorkspaceMemberPreQueryHookService {
|
||||
await this.permissionsService.userHasWorkspaceSettingPermission({
|
||||
userWorkspaceId,
|
||||
workspaceId,
|
||||
_setting: SettingPermissionType.WORKSPACE_MEMBERS,
|
||||
setting: SettingPermissionType.WORKSPACE_MEMBERS,
|
||||
isExecutedByApiKey: isDefined(apiKey),
|
||||
})
|
||||
) {
|
||||
|
||||
Reference in New Issue
Block a user