@backstage/plugin-catalog-backend 0.21.0-next.0 → 0.21.2-next.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,127 @@
1
1
  # @backstage/plugin-catalog-backend
2
2
 
3
+ ## 0.21.2-next.1
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies
8
+ - @backstage/plugin-catalog-common@0.1.2-next.0
9
+ - @backstage/backend-common@0.10.6-next.0
10
+ - @backstage/plugin-permission-node@0.4.2-next.1
11
+
12
+ ## 0.21.2-next.0
13
+
14
+ ### Patch Changes
15
+
16
+ - fac5f112b4: chore(deps): bump `prom-client` from 13.2.0 to 14.0.1
17
+ - 5bbffa60be: Pass authorization token to location service inside location api routes
18
+ - Updated dependencies
19
+ - @backstage/plugin-permission-node@0.4.2-next.0
20
+
21
+ ## 0.21.1
22
+
23
+ ### Patch Changes
24
+
25
+ - 4f5bde47e9: Add support for permissions to the DefaultCatalogCollator.
26
+ - Updated dependencies
27
+ - @backstage/search-common@0.2.2
28
+ - @backstage/backend-common@0.10.5
29
+ - @backstage/plugin-permission-node@0.4.1
30
+
31
+ ## 0.21.0
32
+
33
+ ### Minor Changes
34
+
35
+ - 9f2a8dc423: **BREAKING**: Removed all remnants of the old catalog engine implementation.
36
+
37
+ The old implementation has been deprecated for over half a year. To ensure that
38
+ you are not using the old implementation, check that your
39
+ `packages/backend/src/plugins/catalog.ts` creates the catalog builder using
40
+ `CatalogBuilder.create`. If you instead call `new CatalogBuilder`, you are on
41
+ the old implementation and will experience breakage if you upgrade to this
42
+ version. If you are still on the old version, see [the relevant change log
43
+ entry](https://github.com/backstage/backstage/blob/master/plugins/catalog-backend/CHANGELOG.md#patch-changes-27)
44
+ for migration instructions.
45
+
46
+ The minimal `packages/backend/src/plugins/catalog.ts` file is now:
47
+
48
+ ```ts
49
+ export default async function createPlugin(
50
+ env: PluginEnvironment,
51
+ ): Promise<Router> {
52
+ const builder = await CatalogBuilder.create(env);
53
+ builder.addProcessor(new ScaffolderEntitiesProcessor());
54
+ const { processingEngine, router } = await builder.build();
55
+ await processingEngine.start();
56
+ return router;
57
+ }
58
+ ```
59
+
60
+ The following classes and interfaces have been removed:
61
+
62
+ - The `CatalogBuilder` constructor (see above; use `CatalogBuilder.create`
63
+ instead)
64
+ - `AddLocationResult`
65
+ - `CommonDatabase`
66
+ - `CreateDatabaseOptions`
67
+ - `createNextRouter` (use `createRouter` instead - or preferably, use the
68
+ `router` field returned for you by `catalogBuilder.build()`)
69
+ - `Database`
70
+ - `DatabaseEntitiesCatalog` (use `EntitiesCatalog` instead)
71
+ - `DatabaseLocationsCatalog` (use `LocationService` instead)
72
+ - `DatabaseLocationUpdateLogEvent`
73
+ - `DatabaseLocationUpdateLogStatus`
74
+ - `DatabaseManager`
75
+ - `DbEntitiesRequest`
76
+ - `DbEntitiesResponse`
77
+ - `DbEntityRequest`
78
+ - `DbEntityResponse`
79
+ - `DbLocationsRow`
80
+ - `DbLocationsRowWithStatus`
81
+ - `DbPageInfo`
82
+ - `EntitiesCatalog.batchAddOrUpdateEntities` (was only used by the legacy
83
+ engine)
84
+ - `EntityUpsertRequest`
85
+ - `EntityUpsertResponse`
86
+ - `HigherOrderOperation`
87
+ - `HigherOrderOperations`
88
+ - `LocationReader`
89
+ - `LocationReaders`
90
+ - `LocationResponse`
91
+ - `LocationsCatalog`
92
+ - `LocationUpdateLogEvent`
93
+ - `LocationUpdateStatus`
94
+ - `NextCatalogBuilder` (use `CatalogBuilder.create` instead)
95
+ - `NextRouterOptions` (use `RouterOptions` instead)
96
+ - `ReadLocationEntity`
97
+ - `ReadLocationError`
98
+ - `ReadLocationResult`
99
+ - `Transaction`
100
+
101
+ The `RouterOptions` interface has been un-deprecated, and has instead found use
102
+ for passing into `createRouter`. Its shape has been significantly changed to
103
+ accommodate the new router.
104
+
105
+ ### Patch Changes
106
+
107
+ - e15ce5c16e: Integrate authorization into the delete entities endpoint
108
+ - dce98a92f7: Now when entities are deleted, the parent entity state is updated such that it will "heal" accidental deletes on the next refresh round.
109
+ - 02687954ca: Fixed a typo and made a little clarification to a warning message
110
+ - 48248e2db5: Integrate permissions into entity ancestry endpoint in catalog-backend
111
+ - 68edbbeafd: Fix bug with resource loading in permission integration
112
+ - 7e38acaa9e: Integrate permissions into catalog-backend location endpoints
113
+ - 6680853e0c: Export conditional permission policy helpers from catalog-backend
114
+ - 2b27e49eb1: Internal update to match status field changes in `@backstage/catalog-model`.
115
+ - Updated dependencies
116
+ - @backstage/integration@0.7.2
117
+ - @backstage/plugin-permission-common@0.4.0
118
+ - @backstage/backend-common@0.10.4
119
+ - @backstage/config@0.1.13
120
+ - @backstage/plugin-permission-node@0.4.0
121
+ - @backstage/plugin-catalog-common@0.1.1
122
+ - @backstage/catalog-model@0.9.10
123
+ - @backstage/catalog-client@0.5.5
124
+
3
125
  ## 0.21.0-next.0
4
126
 
5
127
  ### Minor Changes
package/dist/index.cjs.js CHANGED
@@ -21,6 +21,7 @@ var graphql = require('@octokit/graphql');
21
21
  var backendCommon = require('@backstage/backend-common');
22
22
  var yaml = require('yaml');
23
23
  var catalogClient = require('@backstage/catalog-client');
24
+ var pluginCatalogCommon = require('@backstage/plugin-catalog-common');
24
25
  var crypto = require('crypto');
25
26
  var express = require('express');
26
27
  var Router = require('express-promise-router');
@@ -29,7 +30,6 @@ var uuid = require('uuid');
29
30
  var luxon = require('luxon');
30
31
  var promClient = require('prom-client');
31
32
  var stableStringify = require('fast-json-stable-stringify');
32
- var pluginCatalogCommon = require('@backstage/plugin-catalog-common');
33
33
  var pluginPermissionCommon = require('@backstage/plugin-permission-common');
34
34
  var pluginPermissionNode = require('@backstage/plugin-permission-node');
35
35
 
@@ -1930,6 +1930,7 @@ function withLocations(baseUrl, org, entity) {
1930
1930
  class DefaultCatalogCollator {
1931
1931
  constructor(options) {
1932
1932
  this.type = "software-catalog";
1933
+ this.visibilityPermission = pluginCatalogCommon.catalogEntityReadPermission;
1933
1934
  const { discovery, locationTemplate, filter, catalogClient: catalogClient$1, tokenManager } = options;
1934
1935
  this.discovery = discovery;
1935
1936
  this.locationTemplate = locationTemplate || "/catalog/:namespace/:kind/:name";
@@ -1984,7 +1985,10 @@ class DefaultCatalogCollator {
1984
1985
  namespace: entity.metadata.namespace || "default",
1985
1986
  kind: entity.kind,
1986
1987
  lifecycle: ((_d = entity.spec) == null ? void 0 : _d.lifecycle) || "",
1987
- owner: ((_e = entity.spec) == null ? void 0 : _e.owner) || ""
1988
+ owner: ((_e = entity.spec) == null ? void 0 : _e.owner) || "",
1989
+ authorization: {
1990
+ resourceRef: catalogModel.stringifyEntityRef(entity)
1991
+ }
1988
1992
  };
1989
1993
  });
1990
1994
  }
@@ -2662,19 +2666,27 @@ async function createRouter(options) {
2662
2666
  if (!dryRun) {
2663
2667
  disallowReadonlyMode(readonlyEnabled);
2664
2668
  }
2665
- const output = await locationService.createLocation(input, dryRun);
2669
+ const output = await locationService.createLocation(input, dryRun, {
2670
+ authorizationToken: getBearerToken(req.header("authorization"))
2671
+ });
2666
2672
  res.status(201).json(output);
2667
- }).get("/locations", async (_req, res) => {
2668
- const locations = await locationService.listLocations();
2673
+ }).get("/locations", async (req, res) => {
2674
+ const locations = await locationService.listLocations({
2675
+ authorizationToken: getBearerToken(req.header("authorization"))
2676
+ });
2669
2677
  res.status(200).json(locations.map((l) => ({ data: l })));
2670
2678
  }).get("/locations/:id", async (req, res) => {
2671
2679
  const { id } = req.params;
2672
- const output = await locationService.getLocation(id);
2680
+ const output = await locationService.getLocation(id, {
2681
+ authorizationToken: getBearerToken(req.header("authorization"))
2682
+ });
2673
2683
  res.status(200).json(output);
2674
2684
  }).delete("/locations/:id", async (req, res) => {
2675
2685
  disallowReadonlyMode(readonlyEnabled);
2676
2686
  const { id } = req.params;
2677
- await locationService.deleteLocation(id);
2687
+ await locationService.deleteLocation(id, {
2688
+ authorizationToken: getBearerToken(req.header("authorization"))
2689
+ });
2678
2690
  res.status(204).end();
2679
2691
  });
2680
2692
  }
@@ -4235,6 +4247,41 @@ class AuthorizedEntitiesCatalog {
4235
4247
  }
4236
4248
  }
4237
4249
 
4250
+ class AuthorizedLocationService {
4251
+ constructor(locationService, permissionApi) {
4252
+ this.locationService = locationService;
4253
+ this.permissionApi = permissionApi;
4254
+ }
4255
+ async createLocation(spec, dryRun, options) {
4256
+ const authorizationResponse = (await this.permissionApi.authorize([{ permission: pluginCatalogCommon.catalogLocationCreatePermission }], { token: options == null ? void 0 : options.authorizationToken }))[0];
4257
+ if (authorizationResponse.result === pluginPermissionCommon.AuthorizeResult.DENY) {
4258
+ throw new errors.NotAllowedError();
4259
+ }
4260
+ return this.locationService.createLocation(spec, dryRun);
4261
+ }
4262
+ async listLocations(options) {
4263
+ const authorizationResponse = (await this.permissionApi.authorize([{ permission: pluginCatalogCommon.catalogLocationReadPermission }], { token: options == null ? void 0 : options.authorizationToken }))[0];
4264
+ if (authorizationResponse.result === pluginPermissionCommon.AuthorizeResult.DENY) {
4265
+ return [];
4266
+ }
4267
+ return this.locationService.listLocations();
4268
+ }
4269
+ async getLocation(id, options) {
4270
+ const authorizationResponse = (await this.permissionApi.authorize([{ permission: pluginCatalogCommon.catalogLocationReadPermission }], { token: options == null ? void 0 : options.authorizationToken }))[0];
4271
+ if (authorizationResponse.result === pluginPermissionCommon.AuthorizeResult.DENY) {
4272
+ throw new errors.NotFoundError(`Found no location with ID ${id}`);
4273
+ }
4274
+ return this.locationService.getLocation(id);
4275
+ }
4276
+ async deleteLocation(id, options) {
4277
+ const authorizationResponse = (await this.permissionApi.authorize([{ permission: pluginCatalogCommon.catalogLocationDeletePermission }], { token: options == null ? void 0 : options.authorizationToken }))[0];
4278
+ if (authorizationResponse.result === pluginPermissionCommon.AuthorizeResult.DENY) {
4279
+ throw new errors.NotAllowedError();
4280
+ }
4281
+ return this.locationService.deleteLocation(id);
4282
+ }
4283
+ }
4284
+
4238
4285
  class CatalogBuilder {
4239
4286
  constructor(env) {
4240
4287
  this.refreshInterval = createRandomRefreshInterval({
@@ -4384,7 +4431,7 @@ class CatalogBuilder {
4384
4431
  const entityProviders = lodash__default["default"].uniqBy([...this.entityProviders, locationStore, configLocationProvider], (provider) => provider.getProviderName());
4385
4432
  const processingEngine = new DefaultCatalogProcessingEngine(logger, processingDatabase, orchestrator, stitcher, () => crypto.createHash("sha1"));
4386
4433
  const locationAnalyzer = (_b = this.locationAnalyzer) != null ? _b : new RepoLocationAnalyzer(logger, integrations);
4387
- const locationService = new DefaultLocationService(locationStore, orchestrator);
4434
+ const locationService = new AuthorizedLocationService(new DefaultLocationService(locationStore, orchestrator), permissions);
4388
4435
  const refreshService = new AuthorizedRefreshService(new DefaultRefreshService({ database: processingDatabase }), permissions);
4389
4436
  const router = await createRouter({
4390
4437
  entitiesCatalog,
@@ -4455,6 +4502,14 @@ class CatalogBuilder {
4455
4502
  }
4456
4503
  }
4457
4504
 
4505
+ const conditionExports = pluginPermissionNode.createConditionExports({
4506
+ pluginId: "catalog",
4507
+ resourceType: pluginCatalogCommon.RESOURCE_TYPE_CATALOG_ENTITY,
4508
+ rules: permissionRules
4509
+ });
4510
+ const catalogConditions = conditionExports.conditions;
4511
+ const createCatalogPolicyDecision = conditionExports.createPolicyDecision;
4512
+
4458
4513
  exports.AnnotateLocationEntityProcessor = AnnotateLocationEntityProcessor;
4459
4514
  exports.AnnotateScmSlugEntityProcessor = AnnotateScmSlugEntityProcessor;
4460
4515
  exports.AwsOrganizationCloudAccountProcessor = AwsOrganizationCloudAccountProcessor;
@@ -4477,7 +4532,9 @@ exports.LocationEntityProcessor = LocationEntityProcessor;
4477
4532
  exports.PlaceholderProcessor = PlaceholderProcessor;
4478
4533
  exports.StaticLocationProcessor = StaticLocationProcessor;
4479
4534
  exports.UrlReaderProcessor = UrlReaderProcessor;
4535
+ exports.catalogConditions = catalogConditions;
4480
4536
  exports.createCatalogPermissionRule = createCatalogPermissionRule;
4537
+ exports.createCatalogPolicyDecision = createCatalogPolicyDecision;
4481
4538
  exports.createRandomRefreshInterval = createRandomRefreshInterval;
4482
4539
  exports.createRouter = createRouter;
4483
4540
  exports.durationText = durationText;