feat: multi role permission intersection (#15150)

Implements permission intersection (AND logic) to prevent permission
escalation when agents act on behalf of users.

### Changes:
- **Permission Intersection**: Operations requiring both user AND agent
permissions
- **RoleContext Type**: Unified type supporting single `roleId` or
multiple `roleIds` for intersection
- **CRUD Services**: Updated to accept `roleContext` for granular
permission control
- **Agent Integration**: Chat agents now use user + agent role
intersection for all operations
- **ORM Layer**: Enhanced `getRepository` to support multi-role
permission checks

### Related:
- Part 2 of ["Acting on behalf of user" concept
PR](https://github.com/twentyhq/twenty/pull/15103)

[Closes #1661](https://github.com/twentyhq/core-team-issues/issues/1661)

---------

Co-authored-by: Félix Malfait <felix.malfait@gmail.com>
This commit is contained in:
Abdul Rahman
2025-10-19 13:00:05 +05:30
committed by GitHub
parent f6d133f285
commit 3bec43696f
75 changed files with 909 additions and 489 deletions
@@ -79,19 +79,18 @@ export abstract class CommonBaseQueryRunnerService {
workspace.id,
);
const rolePermissionConfig = { unionOf: [roleId] };
const repository = workspaceDataSource.getRepository(
objectMetadataItemWithFieldMaps.nameSingular,
false,
roleId,
rolePermissionConfig,
authContext,
);
return {
workspaceDataSource,
repository,
isExecutedByApiKey: isDefined(authContext.apiKey),
roleId,
shouldBypassPermissionChecks: false,
rolePermissionConfig,
};
}
@@ -31,6 +31,7 @@ import { ObjectMetadataItemWithFieldMaps } from 'src/engine/metadata-modules/typ
import { ObjectMetadataMaps } from 'src/engine/metadata-modules/types/object-metadata-maps';
import { WorkspaceDataSource } from 'src/engine/twenty-orm/datasource/workspace.datasource';
import { WorkspaceRepository } from 'src/engine/twenty-orm/repository/workspace.repository';
import { type RolePermissionConfig } from 'src/engine/twenty-orm/types/role-permission-config';
@Injectable()
export class CommonCreateManyQueryRunnerService extends CommonBaseQueryRunnerService {
@@ -62,15 +63,11 @@ export class CommonCreateManyQueryRunnerService extends CommonBaseQueryRunnerSer
}
});
const {
workspaceDataSource,
repository,
roleId,
shouldBypassPermissionChecks,
} = await this.prepareQueryRunnerContext({
authContext,
objectMetadataItemWithFieldMaps,
});
const { workspaceDataSource, repository, rolePermissionConfig } =
await this.prepareQueryRunnerContext({
authContext,
objectMetadataItemWithFieldMaps,
});
const processedArgs = await this.processQueryArgs({
authContext,
@@ -98,10 +95,9 @@ export class CommonCreateManyQueryRunnerService extends CommonBaseQueryRunnerSer
records: upsertedRecords,
objectMetadataItemWithFieldMaps,
objectMetadataMaps,
roleId,
rolePermissionConfig,
authContext,
workspaceDataSource,
shouldBypassPermissionChecks,
});
return upsertedRecords;
@@ -371,19 +367,17 @@ export class CommonCreateManyQueryRunnerService extends CommonBaseQueryRunnerSer
records,
objectMetadataItemWithFieldMaps,
objectMetadataMaps,
roleId,
rolePermissionConfig,
authContext,
workspaceDataSource,
shouldBypassPermissionChecks,
}: {
args: CreateManyQueryArgs;
records: ObjectRecord[];
objectMetadataItemWithFieldMaps: ObjectMetadataItemWithFieldMaps;
objectMetadataMaps: ObjectMetadataMaps;
roleId?: string;
rolePermissionConfig?: RolePermissionConfig;
authContext: AuthContext;
workspaceDataSource: WorkspaceDataSource;
shouldBypassPermissionChecks: boolean;
}): Promise<void> {
if (!args.selectedFieldsResult.relations) {
return;
@@ -401,8 +395,7 @@ export class CommonCreateManyQueryRunnerService extends CommonBaseQueryRunnerSer
limit: QUERY_MAX_RECORDS,
authContext,
workspaceDataSource,
roleId,
shouldBypassPermissionChecks,
rolePermissionConfig,
selectedFields: args.selectedFieldsResult.select,
});
}
@@ -60,15 +60,11 @@ export class CommonFindManyQueryRunnerService extends CommonBaseQueryRunnerServi
);
}
const {
workspaceDataSource,
repository,
roleId,
shouldBypassPermissionChecks,
} = await this.prepareQueryRunnerContext({
authContext,
objectMetadataItemWithFieldMaps,
});
const { workspaceDataSource, repository, rolePermissionConfig } =
await this.prepareQueryRunnerContext({
authContext,
objectMetadataItemWithFieldMaps,
});
const processedArgs = await this.processQueryArgs({
authContext,
@@ -195,8 +191,7 @@ export class CommonFindManyQueryRunnerService extends CommonBaseQueryRunnerServi
limit: QUERY_MAX_RECORDS,
authContext,
workspaceDataSource,
roleId,
shouldBypassPermissionChecks,
rolePermissionConfig,
selectedFields: processedArgs.selectedFieldsResult.select,
});
}
@@ -46,15 +46,11 @@ export class CommonFindOneQueryRunnerService extends CommonBaseQueryRunnerServic
);
}
const {
workspaceDataSource,
repository,
roleId,
shouldBypassPermissionChecks,
} = await this.prepareQueryRunnerContext({
authContext,
objectMetadataItemWithFieldMaps,
});
const { workspaceDataSource, repository, rolePermissionConfig } =
await this.prepareQueryRunnerContext({
authContext,
objectMetadataItemWithFieldMaps,
});
const processedArgs = await this.processQueryArgs({
authContext,
@@ -128,8 +124,7 @@ export class CommonFindOneQueryRunnerService extends CommonBaseQueryRunnerServic
limit: QUERY_MAX_RECORDS,
authContext,
workspaceDataSource,
roleId,
shouldBypassPermissionChecks,
rolePermissionConfig,
selectedFields: args.selectedFieldsResult.select,
});
}
@@ -20,6 +20,7 @@ import { type ObjectMetadataMaps } from 'src/engine/metadata-modules/types/objec
import { getObjectMetadataMapItemByNameSingular } from 'src/engine/metadata-modules/utils/get-object-metadata-map-item-by-name-singular.util';
import { type WorkspaceDataSource } from 'src/engine/twenty-orm/datasource/workspace.datasource';
import { type WorkspaceSelectQueryBuilder } from 'src/engine/twenty-orm/repository/workspace-select-query-builder';
import { type RolePermissionConfig } from 'src/engine/twenty-orm/types/role-permission-config';
import { isFieldMetadataEntityOfType } from 'src/engine/utils/is-field-metadata-of-type.util';
@Injectable()
@@ -36,8 +37,7 @@ export class ProcessNestedRelationsV2Helper {
limit,
authContext,
workspaceDataSource,
roleId,
shouldBypassPermissionChecks,
rolePermissionConfig,
selectedFields,
}: {
objectMetadataMaps: ObjectMetadataMaps;
@@ -50,10 +50,9 @@ export class ProcessNestedRelationsV2Helper {
limit: number;
authContext: AuthContext;
workspaceDataSource: WorkspaceDataSource;
shouldBypassPermissionChecks: boolean;
rolePermissionConfig?: RolePermissionConfig;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
selectedFields: Record<string, any>;
roleId?: string;
}): Promise<void> {
const processRelationTasks = Object.entries(relations).map(
([sourceFieldName, nestedRelations]) =>
@@ -68,8 +67,7 @@ export class ProcessNestedRelationsV2Helper {
limit,
authContext,
workspaceDataSource,
shouldBypassPermissionChecks,
roleId,
rolePermissionConfig,
selectedFields:
selectedFields[sourceFieldName] instanceof Object
? selectedFields[sourceFieldName]
@@ -91,8 +89,7 @@ export class ProcessNestedRelationsV2Helper {
limit,
authContext,
workspaceDataSource,
shouldBypassPermissionChecks,
roleId,
rolePermissionConfig,
selectedFields,
}: {
objectMetadataMaps: ObjectMetadataMaps;
@@ -106,8 +103,7 @@ export class ProcessNestedRelationsV2Helper {
limit: number;
authContext: AuthContext;
workspaceDataSource: WorkspaceDataSource;
shouldBypassPermissionChecks: boolean;
roleId?: string;
rolePermissionConfig?: RolePermissionConfig;
selectedFields: Record<string, unknown>;
}): Promise<void> {
const sourceFieldMetadata = getFieldMetadataFromGraphQLField({
@@ -147,8 +143,7 @@ export class ProcessNestedRelationsV2Helper {
const targetObjectRepository = workspaceDataSource.getRepository(
targetObjectMetadata.nameSingular,
shouldBypassPermissionChecks,
roleId,
rolePermissionConfig,
);
const targetObjectNameSingular = targetObjectMetadata.nameSingular;
@@ -240,8 +235,7 @@ export class ProcessNestedRelationsV2Helper {
limit,
authContext,
workspaceDataSource,
shouldBypassPermissionChecks,
roleId,
rolePermissionConfig,
selectedFields,
});
}
@@ -9,6 +9,7 @@ import { type AuthContext } from 'src/engine/core-modules/auth/types/auth-contex
import { type ObjectMetadataItemWithFieldMaps } from 'src/engine/metadata-modules/types/object-metadata-item-with-field-maps';
import { type ObjectMetadataMaps } from 'src/engine/metadata-modules/types/object-metadata-maps';
import { type WorkspaceDataSource } from 'src/engine/twenty-orm/datasource/workspace.datasource';
import { type RolePermissionConfig } from 'src/engine/twenty-orm/types/role-permission-config';
@Injectable()
export class ProcessNestedRelationsHelper {
@@ -26,8 +27,7 @@ export class ProcessNestedRelationsHelper {
limit,
authContext,
workspaceDataSource,
shouldBypassPermissionChecks,
roleId,
rolePermissionConfig,
selectedFields,
}: {
objectMetadataMaps: ObjectMetadataMaps;
@@ -40,10 +40,9 @@ export class ProcessNestedRelationsHelper {
limit: number;
authContext: AuthContext;
workspaceDataSource: WorkspaceDataSource;
shouldBypassPermissionChecks: boolean;
rolePermissionConfig?: RolePermissionConfig;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
selectedFields: Record<string, any>;
roleId?: string;
}): Promise<void> {
return this.processNestedRelationsV2Helper.processNestedRelations({
objectMetadataMaps,
@@ -55,8 +54,7 @@ export class ProcessNestedRelationsHelper {
limit,
authContext,
workspaceDataSource,
shouldBypassPermissionChecks,
roleId,
rolePermissionConfig,
selectedFields,
});
}
@@ -40,6 +40,7 @@ import { UserRoleService } from 'src/engine/metadata-modules/user-role/user-role
import { type WorkspaceDataSource } from 'src/engine/twenty-orm/datasource/workspace.datasource';
import { type WorkspaceRepository } from 'src/engine/twenty-orm/repository/workspace.repository';
import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager';
import { type RolePermissionConfig } from 'src/engine/twenty-orm/types/role-permission-config';
export type GraphqlQueryResolverExecutionArgs<Input extends ResolverArgs> = {
args: Input;
@@ -49,8 +50,7 @@ export type GraphqlQueryResolverExecutionArgs<Input extends ResolverArgs> = {
graphqlQueryParser: GraphqlQueryParser;
graphqlQuerySelectedFieldsResult: GraphqlQuerySelectedFieldsResult;
isExecutedByApiKey: boolean;
roleId?: string;
shouldBypassPermissionChecks: boolean;
rolePermissionConfig?: RolePermissionConfig;
};
@Injectable()
@@ -120,7 +120,6 @@ export abstract class GraphqlQueryBaseResolverService<
)) as Input;
let roleId: string | undefined;
let shouldBypassPermissionChecks = false;
if (isDefined(authContext.apiKey)) {
roleId = await this.apiKeyRoleService.getRoleIdForApiKey(
@@ -152,11 +151,12 @@ export abstract class GraphqlQueryBaseResolverService<
PermissionsExceptionCode.NO_AUTHENTICATION_CONTEXT,
);
}
const rolePermissionConfig: RolePermissionConfig | undefined = roleId
? { unionOf: [roleId] }
: undefined;
const repository = workspaceDataSource.getRepository(
objectMetadataItemWithFieldMaps.nameSingular,
shouldBypassPermissionChecks,
roleId,
rolePermissionConfig,
authContext,
);
@@ -182,8 +182,7 @@ export abstract class GraphqlQueryBaseResolverService<
graphqlQueryParser,
graphqlQuerySelectedFieldsResult,
isExecutedByApiKey: isDefined(authContext.apiKey),
roleId,
shouldBypassPermissionChecks,
rolePermissionConfig,
};
const results = await this.resolve(
graphqlQueryResolverExecutionArgs,
@@ -55,8 +55,6 @@ export class GraphqlQueryCreateManyResolverService extends GraphqlQueryBaseResol
const { objectMetadataItemWithFieldMaps, objectMetadataMaps } =
executionArgs.options;
const { roleId } = executionArgs;
const objectRecords = await this.insertOrUpsertRecords(executionArgs);
const upsertedRecords = await this.fetchUpsertedRecords(
@@ -71,7 +69,6 @@ export class GraphqlQueryCreateManyResolverService extends GraphqlQueryBaseResol
records: upsertedRecords,
objectMetadataItemWithFieldMaps,
objectMetadataMaps,
roleId,
});
return this.formatRecordsForResponse(
@@ -462,13 +459,11 @@ export class GraphqlQueryCreateManyResolverService extends GraphqlQueryBaseResol
records,
objectMetadataItemWithFieldMaps,
objectMetadataMaps,
roleId,
}: {
executionArgs: GraphqlQueryResolverExecutionArgs<CreateManyResolverArgs>;
records: ObjectRecord[];
objectMetadataItemWithFieldMaps: ObjectMetadataItemWithFieldMaps;
objectMetadataMaps: ObjectMetadataMaps;
roleId?: string;
}): Promise<void> {
if (!executionArgs.graphqlQuerySelectedFieldsResult.relations) {
return;
@@ -482,8 +477,7 @@ export class GraphqlQueryCreateManyResolverService extends GraphqlQueryBaseResol
limit: QUERY_MAX_RECORDS,
authContext: executionArgs.options.authContext,
workspaceDataSource: executionArgs.workspaceDataSource,
roleId,
shouldBypassPermissionChecks: executionArgs.shouldBypassPermissionChecks,
rolePermissionConfig: executionArgs.rolePermissionConfig,
selectedFields: executionArgs.graphqlQuerySelectedFieldsResult.select,
});
}
@@ -27,8 +27,6 @@ export class GraphqlQueryDeleteManyResolverService extends GraphqlQueryBaseResol
const { authContext, objectMetadataItemWithFieldMaps, objectMetadataMaps } =
executionArgs.options;
const { roleId } = executionArgs;
const queryBuilder = executionArgs.repository.createQueryBuilder(
objectMetadataItemWithFieldMaps.nameSingular,
);
@@ -66,9 +64,7 @@ export class GraphqlQueryDeleteManyResolverService extends GraphqlQueryBaseResol
limit: QUERY_MAX_RECORDS,
authContext,
workspaceDataSource: executionArgs.workspaceDataSource,
roleId,
shouldBypassPermissionChecks:
executionArgs.shouldBypassPermissionChecks,
rolePermissionConfig: executionArgs.rolePermissionConfig,
selectedFields: executionArgs.graphqlQuerySelectedFieldsResult.select,
});
}
@@ -30,8 +30,6 @@ export class GraphqlQueryDeleteOneResolverService extends GraphqlQueryBaseResolv
const { authContext, objectMetadataItemWithFieldMaps, objectMetadataMaps } =
executionArgs.options;
const { roleId } = executionArgs;
const queryBuilder = executionArgs.repository.createQueryBuilder(
objectMetadataItemWithFieldMaps.nameSingular,
);
@@ -67,9 +65,7 @@ export class GraphqlQueryDeleteOneResolverService extends GraphqlQueryBaseResolv
limit: QUERY_MAX_RECORDS,
authContext,
workspaceDataSource: executionArgs.workspaceDataSource,
roleId,
shouldBypassPermissionChecks:
executionArgs.shouldBypassPermissionChecks,
rolePermissionConfig: executionArgs.rolePermissionConfig,
selectedFields: executionArgs.graphqlQuerySelectedFieldsResult.select,
});
}
@@ -24,8 +24,6 @@ export class GraphqlQueryDestroyManyResolverService extends GraphqlQueryBaseReso
const { authContext, objectMetadataItemWithFieldMaps, objectMetadataMaps } =
executionArgs.options;
const { roleId } = executionArgs;
const queryBuilder = executionArgs.repository.createQueryBuilder(
objectMetadataItemWithFieldMaps.nameSingular,
);
@@ -58,9 +56,7 @@ export class GraphqlQueryDestroyManyResolverService extends GraphqlQueryBaseReso
limit: QUERY_MAX_RECORDS,
authContext,
workspaceDataSource: executionArgs.workspaceDataSource,
roleId,
shouldBypassPermissionChecks:
executionArgs.shouldBypassPermissionChecks,
rolePermissionConfig: executionArgs.rolePermissionConfig,
selectedFields: executionArgs.graphqlQuerySelectedFieldsResult.select,
});
}
@@ -28,8 +28,6 @@ export class GraphqlQueryDestroyOneResolverService extends GraphqlQueryBaseResol
const { authContext, objectMetadataItemWithFieldMaps, objectMetadataMaps } =
executionArgs.options;
const { roleId } = executionArgs;
const queryBuilder = executionArgs.repository.createQueryBuilder(
objectMetadataItemWithFieldMaps.nameSingular,
);
@@ -64,9 +62,7 @@ export class GraphqlQueryDestroyOneResolverService extends GraphqlQueryBaseResol
limit: QUERY_MAX_RECORDS,
authContext,
workspaceDataSource: executionArgs.workspaceDataSource,
roleId,
shouldBypassPermissionChecks:
executionArgs.shouldBypassPermissionChecks,
rolePermissionConfig: executionArgs.rolePermissionConfig,
selectedFields: executionArgs.graphqlQuerySelectedFieldsResult.select,
});
}
@@ -47,8 +47,6 @@ export class GraphqlQueryFindManyResolverService extends GraphqlQueryBaseResolve
const objectMetadataNameSingular =
objectMetadataItemWithFieldMaps.nameSingular;
const { roleId } = executionArgs;
const queryBuilder = executionArgs.repository.createQueryBuilder(
objectMetadataNameSingular,
);
@@ -163,9 +161,7 @@ export class GraphqlQueryFindManyResolverService extends GraphqlQueryBaseResolve
limit: QUERY_MAX_RECORDS,
authContext,
workspaceDataSource: executionArgs.workspaceDataSource,
roleId,
shouldBypassPermissionChecks:
executionArgs.shouldBypassPermissionChecks,
rolePermissionConfig: executionArgs.rolePermissionConfig,
selectedFields: executionArgs.graphqlQuerySelectedFieldsResult.select,
});
}
@@ -34,8 +34,6 @@ export class GraphqlQueryFindOneResolverService extends GraphqlQueryBaseResolver
const { authContext, objectMetadataItemWithFieldMaps, objectMetadataMaps } =
executionArgs.options;
const { roleId } = executionArgs;
const queryBuilder = executionArgs.repository.createQueryBuilder(
objectMetadataItemWithFieldMaps.nameSingular,
);
@@ -82,9 +80,7 @@ export class GraphqlQueryFindOneResolverService extends GraphqlQueryBaseResolver
limit: QUERY_MAX_RECORDS,
authContext,
workspaceDataSource: executionArgs.workspaceDataSource,
roleId,
shouldBypassPermissionChecks:
executionArgs.shouldBypassPermissionChecks,
rolePermissionConfig: executionArgs.rolePermissionConfig,
selectedFields: executionArgs.graphqlQuerySelectedFieldsResult.select,
});
}
@@ -47,7 +47,6 @@ export class GraphqlQueryMergeManyResolverService extends GraphqlQueryBaseResolv
const { authContext, objectMetadataItemWithFieldMaps, objectMetadataMaps } =
executionArgs.options;
const { ids, conflictPriorityIndex, dryRun } = executionArgs.args;
const { roleId } = executionArgs;
const recordsToMerge = await this.fetchRecordsToMerge(executionArgs, ids);
@@ -96,12 +95,11 @@ export class GraphqlQueryMergeManyResolverService extends GraphqlQueryBaseResolv
mergedData,
);
if (roleId) {
if (executionArgs.rolePermissionConfig) {
await this.processNestedRelations({
executionArgs,
updatedRecords: [updatedRecord],
authContext,
roleId,
});
}
@@ -335,8 +333,7 @@ export class GraphqlQueryMergeManyResolverService extends GraphqlQueryBaseResolv
try {
const repository = executionArgs.workspaceDataSource.getRepository(
relationField.objectMetadata.nameSingular,
executionArgs.isExecutedByApiKey,
executionArgs.roleId,
executionArgs.rolePermissionConfig,
);
const whereCondition = { [relationField.joinColumnName]: In(fromIds) };
@@ -363,12 +360,10 @@ export class GraphqlQueryMergeManyResolverService extends GraphqlQueryBaseResolv
executionArgs,
updatedRecords,
authContext,
roleId,
}: {
executionArgs: GraphqlQueryResolverExecutionArgs<MergeManyResolverArgs>;
updatedRecords: ObjectRecord[];
authContext: AuthContext;
roleId: string;
}): Promise<void> {
const { objectMetadataMaps, objectMetadataItemWithFieldMaps } =
executionArgs.options;
@@ -382,9 +377,7 @@ export class GraphqlQueryMergeManyResolverService extends GraphqlQueryBaseResolv
limit: QUERY_MAX_RECORDS,
authContext,
workspaceDataSource: executionArgs.workspaceDataSource,
roleId,
shouldBypassPermissionChecks:
executionArgs.shouldBypassPermissionChecks,
rolePermissionConfig: executionArgs.rolePermissionConfig,
selectedFields: executionArgs.graphqlQuerySelectedFieldsResult.select,
});
}
@@ -27,8 +27,6 @@ export class GraphqlQueryRestoreManyResolverService extends GraphqlQueryBaseReso
const { authContext, objectMetadataItemWithFieldMaps, objectMetadataMaps } =
executionArgs.options;
const { roleId } = executionArgs;
const queryBuilder = executionArgs.repository.createQueryBuilder(
objectMetadataItemWithFieldMaps.nameSingular,
);
@@ -66,9 +64,7 @@ export class GraphqlQueryRestoreManyResolverService extends GraphqlQueryBaseReso
limit: QUERY_MAX_RECORDS,
authContext,
workspaceDataSource: executionArgs.workspaceDataSource,
roleId,
shouldBypassPermissionChecks:
executionArgs.shouldBypassPermissionChecks,
rolePermissionConfig: executionArgs.rolePermissionConfig,
selectedFields: executionArgs.graphqlQuerySelectedFieldsResult.select,
});
}
@@ -30,8 +30,6 @@ export class GraphqlQueryRestoreOneResolverService extends GraphqlQueryBaseResol
const { authContext, objectMetadataItemWithFieldMaps, objectMetadataMaps } =
executionArgs.options;
const { roleId } = executionArgs;
const queryBuilder = executionArgs.repository.createQueryBuilder(
objectMetadataItemWithFieldMaps.nameSingular,
);
@@ -68,9 +66,7 @@ export class GraphqlQueryRestoreOneResolverService extends GraphqlQueryBaseResol
limit: QUERY_MAX_RECORDS,
authContext,
workspaceDataSource: executionArgs.workspaceDataSource,
roleId,
shouldBypassPermissionChecks:
executionArgs.shouldBypassPermissionChecks,
rolePermissionConfig: executionArgs.rolePermissionConfig,
selectedFields: executionArgs.graphqlQuerySelectedFieldsResult.select,
});
}
@@ -27,8 +27,6 @@ export class GraphqlQueryUpdateManyResolverService extends GraphqlQueryBaseResol
const { authContext, objectMetadataItemWithFieldMaps, objectMetadataMaps } =
executionArgs.options;
const { roleId } = executionArgs;
const queryBuilder = executionArgs.repository.createQueryBuilder(
objectMetadataItemWithFieldMaps.nameSingular,
);
@@ -67,9 +65,7 @@ export class GraphqlQueryUpdateManyResolverService extends GraphqlQueryBaseResol
limit: QUERY_MAX_RECORDS,
authContext,
workspaceDataSource: executionArgs.workspaceDataSource,
roleId,
shouldBypassPermissionChecks:
executionArgs.shouldBypassPermissionChecks,
rolePermissionConfig: executionArgs.rolePermissionConfig,
selectedFields: executionArgs.graphqlQuerySelectedFieldsResult.select,
});
}
@@ -30,8 +30,6 @@ export class GraphqlQueryUpdateOneResolverService extends GraphqlQueryBaseResolv
const { authContext, objectMetadataItemWithFieldMaps, objectMetadataMaps } =
executionArgs.options;
const { roleId } = executionArgs;
const queryBuilder = executionArgs.repository.createQueryBuilder(
objectMetadataItemWithFieldMaps.nameSingular,
);
@@ -68,9 +66,7 @@ export class GraphqlQueryUpdateOneResolverService extends GraphqlQueryBaseResolv
limit: QUERY_MAX_RECORDS,
authContext,
workspaceDataSource: executionArgs.workspaceDataSource,
roleId,
shouldBypassPermissionChecks:
executionArgs.shouldBypassPermissionChecks,
rolePermissionConfig: executionArgs.rolePermissionConfig,
selectedFields: executionArgs.graphqlQuerySelectedFieldsResult.select,
});
}
@@ -175,8 +175,9 @@ export abstract class RestApiBaseHandler {
const repository = workspaceDataSource.getRepository<ObjectRecord>(
objectMetadataNameSingular,
false,
roleId,
{
unionOf: [roleId],
},
);
const objectMetadataPermissions =