Permission checks on twentyORM global manager (#11477)

In this PR we are handling permissions when using
twentyORMGlobalManager,
and handling permissions for rest api and api key
This commit is contained in:
Marie
2025-04-23 17:57:48 +02:00
committed by GitHub
parent 28a1354928
commit 4257f30f12
54 changed files with 547 additions and 116 deletions

View File

@ -42,6 +42,7 @@ export class ProcessNestedRelationsV2Helper {
authContext,
dataSource,
roleId,
shouldBypassPermissionChecks,
}: {
objectMetadataMaps: ObjectMetadataMaps;
parentObjectMetadataItem: ObjectMetadataItemWithFieldMaps;
@ -52,6 +53,7 @@ export class ProcessNestedRelationsV2Helper {
limit: number;
authContext: AuthContext;
dataSource: WorkspaceDataSource;
shouldBypassPermissionChecks: boolean;
roleId?: string;
}): Promise<void> {
const processRelationTasks = Object.entries(relations).map(
@ -67,6 +69,7 @@ export class ProcessNestedRelationsV2Helper {
limit,
authContext,
dataSource,
shouldBypassPermissionChecks,
roleId,
}),
);
@ -85,6 +88,7 @@ export class ProcessNestedRelationsV2Helper {
limit,
authContext,
dataSource,
shouldBypassPermissionChecks,
roleId,
}: {
objectMetadataMaps: ObjectMetadataMaps;
@ -97,6 +101,7 @@ export class ProcessNestedRelationsV2Helper {
limit: number;
authContext: AuthContext;
dataSource: WorkspaceDataSource;
shouldBypassPermissionChecks: boolean;
roleId?: string;
}): Promise<void> {
const sourceFieldMetadata =
@ -129,6 +134,7 @@ export class ProcessNestedRelationsV2Helper {
const targetObjectRepository = dataSource.getRepository(
targetObjectMetadata.nameSingular,
shouldBypassPermissionChecks,
roleId,
);
@ -199,6 +205,8 @@ export class ProcessNestedRelationsV2Helper {
limit,
authContext,
dataSource,
shouldBypassPermissionChecks,
roleId,
});
}
}

View File

@ -46,6 +46,7 @@ export class ProcessNestedRelationsHelper {
authContext,
dataSource,
isNewRelationEnabled,
shouldBypassPermissionChecks,
roleId,
}: {
objectMetadataMaps: ObjectMetadataMaps;
@ -58,6 +59,7 @@ export class ProcessNestedRelationsHelper {
authContext: AuthContext;
dataSource: WorkspaceDataSource;
isNewRelationEnabled: boolean;
shouldBypassPermissionChecks: boolean;
roleId?: string;
}): Promise<void> {
if (isNewRelationEnabled) {
@ -71,6 +73,7 @@ export class ProcessNestedRelationsHelper {
limit,
authContext,
dataSource,
shouldBypassPermissionChecks,
roleId,
});
}
@ -89,6 +92,7 @@ export class ProcessNestedRelationsHelper {
authContext,
dataSource,
isNewRelationEnabled,
shouldBypassPermissionChecks,
roleId,
}),
);
@ -108,6 +112,7 @@ export class ProcessNestedRelationsHelper {
authContext,
dataSource,
isNewRelationEnabled,
shouldBypassPermissionChecks,
roleId,
}: {
objectMetadataMaps: ObjectMetadataMaps;
@ -118,9 +123,10 @@ export class ProcessNestedRelationsHelper {
nestedRelations: any;
aggregate: Record<string, AggregationField>;
limit: number;
authContext: any;
authContext: AuthContext;
dataSource: DataSource;
isNewRelationEnabled: boolean;
shouldBypassPermissionChecks: boolean;
roleId?: string;
}): Promise<void> {
const relationFieldMetadata =
@ -148,6 +154,7 @@ export class ProcessNestedRelationsHelper {
authContext,
dataSource,
isNewRelationEnabled,
shouldBypassPermissionChecks,
roleId,
});
}
@ -164,6 +171,7 @@ export class ProcessNestedRelationsHelper {
authContext,
dataSource,
isNewRelationEnabled,
shouldBypassPermissionChecks,
roleId,
}: {
objectMetadataMaps: ObjectMetadataMaps;
@ -177,6 +185,7 @@ export class ProcessNestedRelationsHelper {
authContext: AuthContext;
dataSource: WorkspaceDataSource;
isNewRelationEnabled: boolean;
shouldBypassPermissionChecks: boolean;
roleId?: string;
}): Promise<void> {
const { inverseRelationName, referenceObjectMetadata } =
@ -188,6 +197,7 @@ export class ProcessNestedRelationsHelper {
const relationRepository = dataSource.getRepository(
referenceObjectMetadata.nameSingular,
shouldBypassPermissionChecks,
roleId,
);
@ -248,6 +258,8 @@ export class ProcessNestedRelationsHelper {
authContext,
dataSource,
isNewRelationEnabled,
shouldBypassPermissionChecks,
roleId,
});
}
}
@ -264,6 +276,7 @@ export class ProcessNestedRelationsHelper {
authContext,
dataSource,
isNewRelationEnabled,
shouldBypassPermissionChecks,
roleId,
}: {
objectMetadataMaps: ObjectMetadataMaps;
@ -277,6 +290,7 @@ export class ProcessNestedRelationsHelper {
authContext: any;
dataSource: WorkspaceDataSource;
isNewRelationEnabled: boolean;
shouldBypassPermissionChecks: boolean;
roleId?: string;
}): Promise<void> {
const { referenceObjectMetadata } = this.getRelationMetadata({
@ -287,6 +301,7 @@ export class ProcessNestedRelationsHelper {
const relationRepository = dataSource.getRepository(
referenceObjectMetadata.nameSingular,
shouldBypassPermissionChecks,
roleId,
);
@ -346,6 +361,8 @@ export class ProcessNestedRelationsHelper {
authContext,
dataSource,
isNewRelationEnabled,
shouldBypassPermissionChecks,
roleId,
});
}
}

View File

@ -45,6 +45,7 @@ export type GraphqlQueryResolverExecutionArgs<Input extends ResolverArgs> = {
repository: WorkspaceRepository<ObjectLiteral>;
graphqlQueryParser: GraphqlQueryParser;
graphqlQuerySelectedFieldsResult: GraphqlQuerySelectedFieldsResult;
isExecutedByApiKey: boolean;
roleId?: string;
};
@ -123,8 +124,12 @@ export abstract class GraphqlQueryBaseResolverService<
workspaceId: authContext.workspace.id,
});
const executedByApiKey = isDefined(authContext.apiKey);
const shouldBypassPermissionChecks = executedByApiKey;
const repository = dataSource.getRepository(
objectMetadataItemWithFieldMaps.nameSingular,
shouldBypassPermissionChecks,
roleId,
);
@ -150,6 +155,7 @@ export abstract class GraphqlQueryBaseResolverService<
repository,
graphqlQueryParser,
graphqlQuerySelectedFieldsResult,
isExecutedByApiKey: executedByApiKey,
roleId,
};

View File

@ -53,12 +53,15 @@ export class GraphqlQueryCreateManyResolverService extends GraphqlQueryBaseResol
objectMetadataItemWithFieldMaps,
);
const shouldBypassPermissionChecks = executionArgs.isExecutedByApiKey;
await this.processNestedRelationsIfNeeded(
executionArgs,
upsertedRecords,
objectMetadataItemWithFieldMaps,
objectMetadataMaps,
featureFlagsMap,
shouldBypassPermissionChecks,
roleId,
);
@ -329,6 +332,7 @@ export class GraphqlQueryCreateManyResolverService extends GraphqlQueryBaseResol
objectMetadataItemWithFieldMaps: ObjectMetadataItemWithFieldMaps,
objectMetadataMaps: ObjectMetadataMaps,
featureFlagsMap: Record<FeatureFlagKey, boolean>,
shouldBypassPermissionChecks: boolean,
roleId?: string,
): Promise<void> {
if (!executionArgs.graphqlQuerySelectedFieldsResult.relations) {
@ -346,6 +350,7 @@ export class GraphqlQueryCreateManyResolverService extends GraphqlQueryBaseResol
isNewRelationEnabled:
featureFlagsMap[FeatureFlagKey.IsNewRelationEnabled],
roleId,
shouldBypassPermissionChecks,
});
}

View File

@ -74,6 +74,7 @@ export class GraphqlQueryCreateOneResolverService extends GraphqlQueryBaseResolv
isNewRelationEnabled:
featureFlagsMap[FeatureFlagKey.IsNewRelationEnabled],
roleId,
shouldBypassPermissionChecks: executionArgs.isExecutedByApiKey,
});
}

View File

@ -75,6 +75,7 @@ export class GraphqlQueryDeleteManyResolverService extends GraphqlQueryBaseResol
isNewRelationEnabled:
featureFlagsMap[FeatureFlagKey.IsNewRelationEnabled],
roleId,
shouldBypassPermissionChecks: executionArgs.isExecutedByApiKey,
});
}

View File

@ -77,6 +77,7 @@ export class GraphqlQueryDeleteOneResolverService extends GraphqlQueryBaseResolv
isNewRelationEnabled:
featureFlagsMap[FeatureFlagKey.IsNewRelationEnabled],
roleId,
shouldBypassPermissionChecks: executionArgs.isExecutedByApiKey,
});
}

View File

@ -73,6 +73,7 @@ export class GraphqlQueryDestroyManyResolverService extends GraphqlQueryBaseReso
isNewRelationEnabled:
featureFlagsMap[FeatureFlagKey.IsNewRelationEnabled],
roleId,
shouldBypassPermissionChecks: executionArgs.isExecutedByApiKey,
});
}

View File

@ -73,6 +73,7 @@ export class GraphqlQueryDestroyOneResolverService extends GraphqlQueryBaseResol
isNewRelationEnabled:
featureFlagsMap[FeatureFlagKey.IsNewRelationEnabled],
roleId,
shouldBypassPermissionChecks: executionArgs.isExecutedByApiKey,
});
}

View File

@ -160,6 +160,7 @@ export class GraphqlQueryFindManyResolverService extends GraphqlQueryBaseResolve
isNewRelationEnabled:
featureFlagsMap[FeatureFlagKey.IsNewRelationEnabled],
roleId,
shouldBypassPermissionChecks: executionArgs.isExecutedByApiKey,
});
}

View File

@ -83,6 +83,7 @@ export class GraphqlQueryFindOneResolverService extends GraphqlQueryBaseResolver
isNewRelationEnabled:
featureFlagsMap[FeatureFlagKey.IsNewRelationEnabled],
roleId,
shouldBypassPermissionChecks: executionArgs.isExecutedByApiKey,
});
}

View File

@ -75,6 +75,7 @@ export class GraphqlQueryRestoreManyResolverService extends GraphqlQueryBaseReso
isNewRelationEnabled:
featureFlagsMap[FeatureFlagKey.IsNewRelationEnabled],
roleId,
shouldBypassPermissionChecks: executionArgs.isExecutedByApiKey,
});
}

View File

@ -77,6 +77,7 @@ export class GraphqlQueryRestoreOneResolverService extends GraphqlQueryBaseResol
isNewRelationEnabled:
featureFlagsMap[FeatureFlagKey.IsNewRelationEnabled],
roleId,
shouldBypassPermissionChecks: executionArgs.isExecutedByApiKey,
});
}

View File

@ -113,6 +113,7 @@ export class GraphqlQueryUpdateManyResolverService extends GraphqlQueryBaseResol
isNewRelationEnabled:
featureFlagsMap[FeatureFlagKey.IsNewRelationEnabled],
roleId,
shouldBypassPermissionChecks: executionArgs.isExecutedByApiKey,
});
}

View File

@ -107,6 +107,7 @@ export class GraphqlQueryUpdateOneResolverService extends GraphqlQueryBaseResolv
isNewRelationEnabled:
featureFlagsMap[FeatureFlagKey.IsNewRelationEnabled],
roleId,
shouldBypassPermissionChecks: executionArgs.isExecutedByApiKey,
});
}