diff --git a/.changeset/funny-ladybugs-pump.md b/.changeset/funny-ladybugs-pump.md new file mode 100644 index 0000000000..2b3f17e974 --- /dev/null +++ b/.changeset/funny-ladybugs-pump.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-backend': patch +--- + +Improved performance when applying conditional decisions to entities within the permission framework. diff --git a/plugins/catalog-backend/src/service/CatalogBuilder.ts b/plugins/catalog-backend/src/service/CatalogBuilder.ts index ddf4b5d185..79121c86c5 100644 --- a/plugins/catalog-backend/src/service/CatalogBuilder.ts +++ b/plugins/catalog-backend/src/service/CatalogBuilder.ts @@ -26,9 +26,7 @@ import { FieldFormatEntityPolicy, makeValidator, NoForeignRootFieldsEntityPolicy, - parseEntityRef, SchemaValidEntityPolicy, - stringifyEntityRef, Validators, } from '@backstage/catalog-model'; import { ScmIntegrations } from '@backstage/integration'; @@ -116,7 +114,6 @@ import { createRouter } from './createRouter'; import { DefaultEntitiesCatalog } from './DefaultEntitiesCatalog'; import { DefaultLocationService } from './DefaultLocationService'; import { DefaultRefreshService } from './DefaultRefreshService'; -import { basicEntityFilter } from './request'; import { entitiesResponseToObjects } from './response'; import { catalogEntityPermissionResourceRef } from '@backstage/plugin-catalog-node/alpha'; @@ -381,7 +378,7 @@ export class CatalogBuilder { return [ new FileReaderProcessor(), - new UrlReaderProcessor({ reader, logger, config }), + new UrlReaderProcessor({ reader, logger }), CodeOwnersProcessor.fromConfig(config, { logger, reader }), new AnnotateLocationEntityProcessor({ integrations }), ]; @@ -559,60 +556,35 @@ export class CatalogBuilder { const entitiesCatalog = new AuthorizedEntitiesCatalog( unauthorizedEntitiesCatalog, permissionsService, - permissionsRegistry - ? createConditionTransformer( - permissionsRegistry.getPermissionRuleset( - catalogEntityPermissionResourceRef, - ), - ) - : createConditionTransformer(this.permissionRules), + createConditionTransformer(this.permissionRules), ); - const catalogPermissionResource = { - resourceType: RESOURCE_TYPE_CATALOG_ENTITY, - getResources: async (resourceRefs: string[]) => { - const { entities } = await unauthorizedEntitiesCatalog.entities({ - credentials: await auth.getOwnServiceCredentials(), - filter: { - anyOf: resourceRefs.map(resourceRef => { - const { kind, namespace, name } = parseEntityRef(resourceRef); + const getResources = async (resourceRefs: string[]) => { + const { items } = await unauthorizedEntitiesCatalog.entitiesBatch({ + credentials: await auth.getOwnServiceCredentials(), + entityRefs: resourceRefs, + }); - return basicEntityFilter({ - kind, - 'metadata.namespace': namespace, - 'metadata.name': name, - }); - }), - }, - }); - - const entitiesByRef = Object.fromEntries( - entitiesResponseToObjects(entities) - .filter((x): x is Entity => Boolean(x)) - .map(entity => [stringifyEntityRef(entity), entity]), - ); - - return resourceRefs.map( - resourceRef => - entitiesByRef[stringifyEntityRef(parseEntityRef(resourceRef))], - ); - }, - permissions: this.permissions, - rules: this.permissionRules, - } as const; + return entitiesResponseToObjects(items).map(e => e || undefined); + }; let permissionIntegrationRouter: | ReturnType | undefined; if (permissionsRegistry) { permissionsRegistry.addResourceType({ - ...catalogPermissionResource, resourceRef: catalogEntityPermissionResourceRef, + getResources, + permissions: this.permissions, + rules: this.permissionRules, }); } else { - permissionIntegrationRouter = createPermissionIntegrationRouter( - catalogPermissionResource, - ); + permissionIntegrationRouter = createPermissionIntegrationRouter({ + resourceType: RESOURCE_TYPE_CATALOG_ENTITY, + getResources, + permissions: this.permissions, + rules: this.permissionRules, + }); } const locationStore = new DefaultLocationStore(dbClient);