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:
+4
-5
@@ -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,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
+10
-17
@@ -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,
|
||||
});
|
||||
}
|
||||
|
||||
+6
-11
@@ -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,
|
||||
});
|
||||
}
|
||||
|
||||
+6
-11
@@ -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,
|
||||
});
|
||||
}
|
||||
|
||||
+8
-14
@@ -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,
|
||||
});
|
||||
}
|
||||
|
||||
+4
-6
@@ -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,
|
||||
});
|
||||
}
|
||||
|
||||
+7
-8
@@ -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,
|
||||
|
||||
+1
-7
@@ -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,
|
||||
});
|
||||
}
|
||||
|
||||
+1
-5
@@ -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,
|
||||
});
|
||||
}
|
||||
|
||||
+1
-5
@@ -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,
|
||||
});
|
||||
}
|
||||
|
||||
+1
-5
@@ -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,
|
||||
});
|
||||
}
|
||||
|
||||
+1
-5
@@ -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,
|
||||
});
|
||||
}
|
||||
|
||||
+1
-5
@@ -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,
|
||||
});
|
||||
}
|
||||
|
||||
+1
-5
@@ -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,
|
||||
});
|
||||
}
|
||||
|
||||
+3
-10
@@ -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,
|
||||
});
|
||||
}
|
||||
|
||||
+1
-5
@@ -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,
|
||||
});
|
||||
}
|
||||
|
||||
+1
-5
@@ -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,
|
||||
});
|
||||
}
|
||||
|
||||
+1
-5
@@ -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,
|
||||
});
|
||||
}
|
||||
|
||||
+1
-5
@@ -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 =
|
||||
|
||||
Reference in New Issue
Block a user