migrate to dataloader for batch permissions fetching

Signed-off-by: aramissennyeydd <aramis.sennyey@doordash.com>
This commit is contained in:
aramissennyeydd
2026-03-11 09:42:56 -04:00
committed by Patrik Oldsberg
parent ce97558e11
commit 10f8fa1df8
4 changed files with 33 additions and 12 deletions
+13
View File
@@ -426,6 +426,17 @@ const RestrictedCard = PermissionExampleCardBlueprint.make({
if: { permissions: { $contains: 'catalog.entity.create' } },
});
// Feature flag-gated card — only instantiated when the user has
// the experimental-card FF enabled.
const FeatureFlagCard = PermissionExampleCardBlueprint.make({
name: 'feature-flag',
params: {
title: 'Feature Flagged Card',
description: 'Visible only with the experimental-card FF active.',
},
if: { featureFlags: { $contains: 'experimental-card' } },
});
// Example: Page enabled only when the user is allowed to create catalog entities.
//
// The `if` predicate is evaluated once at app startup (after sign-in),
@@ -479,6 +490,7 @@ export const pagesPlugin = createFrontendPlugin({
{ name: 'experimental-features' },
{ name: 'advanced-features' },
{ name: 'beta-access' },
{ name: 'experimental-card' },
],
extensions: [
IndexPage,
@@ -491,5 +503,6 @@ export const pagesPlugin = createFrontendPlugin({
PublicCard,
RestrictedCard,
PermissionGatedPage,
FeatureFlagCard,
],
});
+1
View File
@@ -45,6 +45,7 @@
"@backstage/config": "workspace:^",
"@backstage/core-plugin-api": "workspace:^",
"@backstage/plugin-permission-common": "workspace:^",
"dataloader": "^2.0.0",
"swr": "^2.0.0"
},
"devDependencies": {
@@ -14,6 +14,7 @@
* limitations under the License.
*/
import DataLoader from 'dataloader';
import { DiscoveryApi, IdentityApi } from '@backstage/core-plugin-api';
import { PermissionApi } from './PermissionApi';
import {
@@ -24,20 +25,27 @@ import {
import { Config } from '@backstage/config';
/**
* The default implementation of the PermissionApi, which simply calls the authorize method of the given
* {@link @backstage/plugin-permission-common#PermissionClient}.
* The default implementation of the PermissionApi, which batches calls to
* {@link @backstage/plugin-permission-common#PermissionClient} that are made
* within the same microtask into a single HTTP request.
* @public
*/
export class IdentityPermissionApi implements PermissionApi {
private readonly permissionClient: PermissionClient;
private readonly identityApi: IdentityApi;
private readonly loader: DataLoader<
AuthorizePermissionRequest,
AuthorizePermissionResponse
>;
private constructor(
permissionClient: PermissionClient,
identityApi: IdentityApi,
) {
this.permissionClient = permissionClient;
this.identityApi = identityApi;
this.loader = new DataLoader(
async (requests: readonly AuthorizePermissionRequest[]) => {
const credentials = await identityApi.getCredentials();
return permissionClient.authorize([...requests], credentials);
},
);
}
static create(options: {
@@ -59,11 +67,9 @@ export class IdentityPermissionApi implements PermissionApi {
async authorize(
request: AuthorizePermissionRequest | AuthorizePermissionRequest[],
): Promise<AuthorizePermissionResponse | AuthorizePermissionResponse[]> {
const requests = Array.isArray(request) ? request : [request];
const responses = await this.permissionClient.authorize(
requests,
await this.identityApi.getCredentials(),
);
return Array.isArray(request) ? responses : responses[0];
if (Array.isArray(request)) {
return Promise.all(request.map(r => this.loader.load(r)));
}
return this.loader.load(request);
}
}
+1
View File
@@ -6454,6 +6454,7 @@ __metadata:
"@testing-library/jest-dom": "npm:^6.0.0"
"@testing-library/react": "npm:^16.0.0"
"@types/react": "npm:^18.0.0"
dataloader: "npm:^2.0.0"
react: "npm:^18.0.2"
react-dom: "npm:^18.0.2"
react-router-dom: "npm:^6.30.2"