@backstage/plugin-catalog-backend 1.25.3-next.1 → 1.26.0
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 +61 -0
- package/alpha/package.json +1 -1
- package/dist/alpha.cjs.js +2 -2
- package/dist/cjs/{CatalogBuilder-BQ7aDMTH.cjs.js → CatalogBuilder-CGSl8LEN.cjs.js} +105 -29
- package/dist/cjs/CatalogBuilder-CGSl8LEN.cjs.js.map +1 -0
- package/dist/index.cjs.js +2 -2
- package/package.json +17 -17
- package/dist/cjs/CatalogBuilder-BQ7aDMTH.cjs.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,66 @@
|
|
|
1
1
|
# @backstage/plugin-catalog-backend
|
|
2
2
|
|
|
3
|
+
## 1.26.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 74acf06: Add `dependencyOf` prop to catalog model for Component kind to enable building relationship graphs with both directions using `dependsOn` and `dependencyOf`.
|
|
8
|
+
- 78475c3: Allow offset mode paging in entity list provider
|
|
9
|
+
- bd35cdb: The `analyze-location` endpoint is now protected by the `catalog.location.analyze` permission.
|
|
10
|
+
The `validate-entity` endpoint is now protected by the `catalog.entity.validate` permission.
|
|
11
|
+
|
|
12
|
+
### Patch Changes
|
|
13
|
+
|
|
14
|
+
- 1882cfe: Moved `getEntities` ordering to utilize database instead of having it inside catalog client
|
|
15
|
+
|
|
16
|
+
Please note that the latest version of `@backstage/catalog-client` will not order the entities in the same way as before. This is because the ordering is now done in the database query instead of in the client. If you rely on the ordering of the entities, you may need to update your backend plugin or code to handle this change.
|
|
17
|
+
|
|
18
|
+
- d425fc4: Modules, plugins, and services are now `BackendFeature`, not a function that returns a feature.
|
|
19
|
+
- c2b63ab: Updated dependency `supertest` to `^7.0.0`.
|
|
20
|
+
- 53cce86: Fixed an issue with the by-query call, where ordering by a field that does not exist on all entities led to not all results being returned
|
|
21
|
+
- Updated dependencies
|
|
22
|
+
- @backstage/backend-common@0.25.0
|
|
23
|
+
- @backstage/backend-plugin-api@1.0.0
|
|
24
|
+
- @backstage/catalog-model@1.7.0
|
|
25
|
+
- @backstage/catalog-client@1.7.0
|
|
26
|
+
- @backstage/plugin-search-backend-module-catalog@0.2.2
|
|
27
|
+
- @backstage/plugin-permission-node@0.8.3
|
|
28
|
+
- @backstage/plugin-catalog-common@1.1.0
|
|
29
|
+
- @backstage/plugin-catalog-node@1.13.0
|
|
30
|
+
- @backstage/integration@1.15.0
|
|
31
|
+
- @backstage/backend-openapi-utils@0.1.18
|
|
32
|
+
- @backstage/plugin-events-node@0.4.0
|
|
33
|
+
- @backstage/config@1.2.0
|
|
34
|
+
- @backstage/errors@1.2.4
|
|
35
|
+
- @backstage/types@1.1.1
|
|
36
|
+
- @backstage/plugin-permission-common@0.8.1
|
|
37
|
+
|
|
38
|
+
## 1.26.0-next.2
|
|
39
|
+
|
|
40
|
+
### Minor Changes
|
|
41
|
+
|
|
42
|
+
- 78475c3: Allow offset mode paging in entity list provider
|
|
43
|
+
|
|
44
|
+
### Patch Changes
|
|
45
|
+
|
|
46
|
+
- c2b63ab: Updated dependency `supertest` to `^7.0.0`.
|
|
47
|
+
- Updated dependencies
|
|
48
|
+
- @backstage/backend-common@0.25.0-next.2
|
|
49
|
+
- @backstage/backend-plugin-api@1.0.0-next.2
|
|
50
|
+
- @backstage/catalog-client@1.7.0-next.1
|
|
51
|
+
- @backstage/integration@1.15.0-next.0
|
|
52
|
+
- @backstage/backend-openapi-utils@0.1.18-next.2
|
|
53
|
+
- @backstage/plugin-permission-node@0.8.3-next.2
|
|
54
|
+
- @backstage/catalog-model@1.6.0
|
|
55
|
+
- @backstage/config@1.2.0
|
|
56
|
+
- @backstage/errors@1.2.4
|
|
57
|
+
- @backstage/types@1.1.1
|
|
58
|
+
- @backstage/plugin-catalog-common@1.0.26
|
|
59
|
+
- @backstage/plugin-catalog-node@1.12.7-next.2
|
|
60
|
+
- @backstage/plugin-events-node@0.4.0-next.2
|
|
61
|
+
- @backstage/plugin-permission-common@0.8.1
|
|
62
|
+
- @backstage/plugin-search-backend-module-catalog@0.2.2-next.2
|
|
63
|
+
|
|
3
64
|
## 1.25.3-next.1
|
|
4
65
|
|
|
5
66
|
### Patch Changes
|
package/alpha/package.json
CHANGED
package/dist/alpha.cjs.js
CHANGED
|
@@ -4,7 +4,7 @@ Object.defineProperty(exports, '__esModule', { value: true });
|
|
|
4
4
|
|
|
5
5
|
var alpha = require('@backstage/plugin-catalog-common/alpha');
|
|
6
6
|
var pluginPermissionNode = require('@backstage/plugin-permission-node');
|
|
7
|
-
var CatalogBuilder = require('./cjs/CatalogBuilder-
|
|
7
|
+
var CatalogBuilder = require('./cjs/CatalogBuilder-CGSl8LEN.cjs.js');
|
|
8
8
|
var backendPluginApi = require('@backstage/backend-plugin-api');
|
|
9
9
|
var pluginEventsNode = require('@backstage/plugin-events-node');
|
|
10
10
|
var alpha$1 = require('@backstage/plugin-catalog-node/alpha');
|
|
@@ -25,6 +25,7 @@ require('util');
|
|
|
25
25
|
require('yaml');
|
|
26
26
|
require('p-limit');
|
|
27
27
|
require('uuid');
|
|
28
|
+
require('@backstage/plugin-permission-common');
|
|
28
29
|
require('luxon');
|
|
29
30
|
require('prom-client');
|
|
30
31
|
require('@opentelemetry/api');
|
|
@@ -36,7 +37,6 @@ require('@backstage/types');
|
|
|
36
37
|
require('@backstage/catalog-client');
|
|
37
38
|
require('yn');
|
|
38
39
|
require('@backstage/backend-openapi-utils');
|
|
39
|
-
require('@backstage/plugin-permission-common');
|
|
40
40
|
require('minimatch');
|
|
41
41
|
require('@backstage/config');
|
|
42
42
|
|
|
@@ -17,6 +17,8 @@ var util = require('util');
|
|
|
17
17
|
var yaml = require('yaml');
|
|
18
18
|
var limiterFactory = require('p-limit');
|
|
19
19
|
var uuid = require('uuid');
|
|
20
|
+
var alpha = require('@backstage/plugin-catalog-common/alpha');
|
|
21
|
+
var pluginPermissionCommon = require('@backstage/plugin-permission-common');
|
|
20
22
|
var backendPluginApi = require('@backstage/backend-plugin-api');
|
|
21
23
|
var luxon = require('luxon');
|
|
22
24
|
var promClient = require('prom-client');
|
|
@@ -29,8 +31,6 @@ var types = require('@backstage/types');
|
|
|
29
31
|
var catalogClient = require('@backstage/catalog-client');
|
|
30
32
|
var yn = require('yn');
|
|
31
33
|
var backendOpenapiUtils = require('@backstage/backend-openapi-utils');
|
|
32
|
-
var alpha = require('@backstage/plugin-catalog-common/alpha');
|
|
33
|
-
var pluginPermissionCommon = require('@backstage/plugin-permission-common');
|
|
34
34
|
var minimatch = require('minimatch');
|
|
35
35
|
var config = require('@backstage/config');
|
|
36
36
|
var pluginPermissionNode = require('@backstage/plugin-permission-node');
|
|
@@ -317,6 +317,12 @@ class BuiltinKindsEntityProcessor {
|
|
|
317
317
|
catalogModel.RELATION_DEPENDS_ON,
|
|
318
318
|
catalogModel.RELATION_DEPENDENCY_OF
|
|
319
319
|
);
|
|
320
|
+
doEmit(
|
|
321
|
+
component.spec.dependencyOf,
|
|
322
|
+
{ defaultNamespace: selfRef.namespace },
|
|
323
|
+
catalogModel.RELATION_DEPENDENCY_OF,
|
|
324
|
+
catalogModel.RELATION_DEPENDS_ON
|
|
325
|
+
);
|
|
320
326
|
doEmit(
|
|
321
327
|
component.spec.system,
|
|
322
328
|
{ defaultKind: "System", defaultNamespace: selfRef.namespace },
|
|
@@ -1045,6 +1051,27 @@ class RepoLocationAnalyzer {
|
|
|
1045
1051
|
}
|
|
1046
1052
|
}
|
|
1047
1053
|
|
|
1054
|
+
class AuthorizedLocationAnalyzer {
|
|
1055
|
+
constructor(service, permissionApi) {
|
|
1056
|
+
this.service = service;
|
|
1057
|
+
this.permissionApi = permissionApi;
|
|
1058
|
+
}
|
|
1059
|
+
async analyzeLocation(request, credentials) {
|
|
1060
|
+
const authorizeDecision = (await this.permissionApi.authorize(
|
|
1061
|
+
[
|
|
1062
|
+
{
|
|
1063
|
+
permission: alpha.catalogLocationAnalyzePermission
|
|
1064
|
+
}
|
|
1065
|
+
],
|
|
1066
|
+
{ credentials }
|
|
1067
|
+
))[0];
|
|
1068
|
+
if (authorizeDecision.result !== pluginPermissionCommon.AuthorizeResult.ALLOW) {
|
|
1069
|
+
throw new errors.NotAllowedError();
|
|
1070
|
+
}
|
|
1071
|
+
return this.service.analyzeLocation(request, credentials);
|
|
1072
|
+
}
|
|
1073
|
+
}
|
|
1074
|
+
|
|
1048
1075
|
function timestampToDateTime(input) {
|
|
1049
1076
|
try {
|
|
1050
1077
|
if (typeof input === "object") {
|
|
@@ -2579,6 +2606,9 @@ class DefaultEntitiesCatalog {
|
|
|
2579
2606
|
}
|
|
2580
2607
|
]);
|
|
2581
2608
|
}
|
|
2609
|
+
if (isQueryEntitiesInitialRequest(request) && request.offset !== void 0) {
|
|
2610
|
+
dbQuery.offset(request.offset);
|
|
2611
|
+
}
|
|
2582
2612
|
dbQuery.limit(isFetchingBackwards ? limit : limit + 1);
|
|
2583
2613
|
countQuery.count("final_entities.entity_id", { as: "count" });
|
|
2584
2614
|
const [rows, [{ count }]] = await Promise.all([
|
|
@@ -3765,7 +3795,7 @@ function parseEntityFilterString(filterString) {
|
|
|
3765
3795
|
if (!statements.length) {
|
|
3766
3796
|
return void 0;
|
|
3767
3797
|
}
|
|
3768
|
-
const filtersByKey =
|
|
3798
|
+
const filtersByKey = /* @__PURE__ */ new Map();
|
|
3769
3799
|
for (const statement of statements) {
|
|
3770
3800
|
const equalsIndex = statement.indexOf("=");
|
|
3771
3801
|
const key = equalsIndex === -1 ? statement : statement.substring(0, equalsIndex).trim();
|
|
@@ -3775,13 +3805,17 @@ function parseEntityFilterString(filterString) {
|
|
|
3775
3805
|
`Invalid filter, '${statement}' is not a valid statement (expected a string on the form a=b or a= or a)`
|
|
3776
3806
|
);
|
|
3777
3807
|
}
|
|
3778
|
-
|
|
3808
|
+
let f = filtersByKey.get(key);
|
|
3809
|
+
if (!f) {
|
|
3810
|
+
f = { key };
|
|
3811
|
+
filtersByKey.set(key, f);
|
|
3812
|
+
}
|
|
3779
3813
|
if (value !== void 0) {
|
|
3780
3814
|
f.values = f.values || [];
|
|
3781
3815
|
f.values.push(value);
|
|
3782
3816
|
}
|
|
3783
3817
|
}
|
|
3784
|
-
return
|
|
3818
|
+
return Array.from(filtersByKey.values());
|
|
3785
3819
|
}
|
|
3786
3820
|
|
|
3787
3821
|
function getPathArrayAndValue(input, field) {
|
|
@@ -4986,6 +5020,9 @@ const spec = {
|
|
|
4986
5020
|
{
|
|
4987
5021
|
$ref: "#/components/parameters/limit"
|
|
4988
5022
|
},
|
|
5023
|
+
{
|
|
5024
|
+
$ref: "#/components/parameters/offset"
|
|
5025
|
+
},
|
|
4989
5026
|
{
|
|
4990
5027
|
$ref: "#/components/parameters/orderField"
|
|
4991
5028
|
},
|
|
@@ -5459,6 +5496,27 @@ function parseEntityPaginationParams({
|
|
|
5459
5496
|
};
|
|
5460
5497
|
}
|
|
5461
5498
|
|
|
5499
|
+
class AuthorizedValidationService {
|
|
5500
|
+
constructor(service, permissionApi) {
|
|
5501
|
+
this.service = service;
|
|
5502
|
+
this.permissionApi = permissionApi;
|
|
5503
|
+
}
|
|
5504
|
+
async process(request, credentials) {
|
|
5505
|
+
const authorizeDecision = (await this.permissionApi.authorize(
|
|
5506
|
+
[
|
|
5507
|
+
{
|
|
5508
|
+
permission: alpha.catalogEntityValidatePermission
|
|
5509
|
+
}
|
|
5510
|
+
],
|
|
5511
|
+
{ credentials }
|
|
5512
|
+
))[0];
|
|
5513
|
+
if (authorizeDecision.result !== pluginPermissionCommon.AuthorizeResult.ALLOW) {
|
|
5514
|
+
throw new errors.NotAllowedError();
|
|
5515
|
+
}
|
|
5516
|
+
return this.service.process(request);
|
|
5517
|
+
}
|
|
5518
|
+
}
|
|
5519
|
+
|
|
5462
5520
|
async function createRouter(options) {
|
|
5463
5521
|
const router = await createOpenApiRouter({
|
|
5464
5522
|
validatorOptions: {
|
|
@@ -5476,6 +5534,7 @@ async function createRouter(options) {
|
|
|
5476
5534
|
config,
|
|
5477
5535
|
logger,
|
|
5478
5536
|
permissionIntegrationRouter,
|
|
5537
|
+
permissionsService,
|
|
5479
5538
|
auth,
|
|
5480
5539
|
httpAuth
|
|
5481
5540
|
} = options;
|
|
@@ -5516,6 +5575,7 @@ async function createRouter(options) {
|
|
|
5516
5575
|
}).get("/entities/by-query", async (req, res) => {
|
|
5517
5576
|
const { items, pageInfo, totalItems } = await entitiesCatalog.queryEntities({
|
|
5518
5577
|
limit: req.query.limit,
|
|
5578
|
+
offset: req.query.offset,
|
|
5519
5579
|
...parseQueryEntitiesParams(req.query),
|
|
5520
5580
|
credentials: await httpAuth.credentials(req)
|
|
5521
5581
|
});
|
|
@@ -5642,9 +5702,13 @@ async function createRouter(options) {
|
|
|
5642
5702
|
location: locationInput,
|
|
5643
5703
|
catalogFilename: zod.z.string().optional()
|
|
5644
5704
|
});
|
|
5705
|
+
const credentials = await httpAuth.credentials(req);
|
|
5645
5706
|
const parsedBody = schema.parse(body);
|
|
5646
5707
|
try {
|
|
5647
|
-
const output = await locationAnalyzer.analyzeLocation(
|
|
5708
|
+
const output = await locationAnalyzer.analyzeLocation(
|
|
5709
|
+
parsedBody,
|
|
5710
|
+
credentials
|
|
5711
|
+
);
|
|
5648
5712
|
res.status(200).json(output);
|
|
5649
5713
|
} catch (err) {
|
|
5650
5714
|
if (
|
|
@@ -5679,19 +5743,27 @@ async function createRouter(options) {
|
|
|
5679
5743
|
errors: [errors.serializeError(err)]
|
|
5680
5744
|
});
|
|
5681
5745
|
}
|
|
5682
|
-
const
|
|
5683
|
-
|
|
5684
|
-
|
|
5685
|
-
|
|
5686
|
-
|
|
5687
|
-
|
|
5688
|
-
|
|
5689
|
-
|
|
5690
|
-
|
|
5746
|
+
const credentials = await httpAuth.credentials(req);
|
|
5747
|
+
const authorizedValidationService = new AuthorizedValidationService(
|
|
5748
|
+
orchestrator,
|
|
5749
|
+
permissionsService
|
|
5750
|
+
);
|
|
5751
|
+
const processingResult = await authorizedValidationService.process(
|
|
5752
|
+
{
|
|
5753
|
+
entity: {
|
|
5754
|
+
...entity,
|
|
5755
|
+
metadata: {
|
|
5756
|
+
...entity.metadata,
|
|
5757
|
+
annotations: {
|
|
5758
|
+
[catalogModel.ANNOTATION_LOCATION]: body.location,
|
|
5759
|
+
[catalogModel.ANNOTATION_ORIGIN_LOCATION]: body.location,
|
|
5760
|
+
...entity.metadata.annotations
|
|
5761
|
+
}
|
|
5691
5762
|
}
|
|
5692
5763
|
}
|
|
5693
|
-
}
|
|
5694
|
-
|
|
5764
|
+
},
|
|
5765
|
+
credentials
|
|
5766
|
+
);
|
|
5695
5767
|
if (!processingResult.ok)
|
|
5696
5768
|
res.status(400).json({
|
|
5697
5769
|
errors: processingResult.errors.map((e) => errors.serializeError(e))
|
|
@@ -7009,15 +7081,6 @@ class CatalogBuilder {
|
|
|
7009
7081
|
});
|
|
7010
7082
|
const integrations = integration.ScmIntegrations.fromConfig(config);
|
|
7011
7083
|
const rulesEnforcer = DefaultCatalogRulesEnforcer.fromConfig(config);
|
|
7012
|
-
const orchestrator = new DefaultCatalogProcessingOrchestrator({
|
|
7013
|
-
processors,
|
|
7014
|
-
integrations,
|
|
7015
|
-
rulesEnforcer,
|
|
7016
|
-
logger,
|
|
7017
|
-
parser,
|
|
7018
|
-
policy,
|
|
7019
|
-
legacySingleProcessorValidation: this.legacySingleProcessorValidation
|
|
7020
|
-
});
|
|
7021
7084
|
const unauthorizedEntitiesCatalog = new DefaultEntitiesCatalog({
|
|
7022
7085
|
database: dbClient,
|
|
7023
7086
|
logger,
|
|
@@ -7032,6 +7095,15 @@ class CatalogBuilder {
|
|
|
7032
7095
|
);
|
|
7033
7096
|
permissionsService = pluginPermissionCommon.toPermissionEvaluator(permissions);
|
|
7034
7097
|
}
|
|
7098
|
+
const orchestrator = new DefaultCatalogProcessingOrchestrator({
|
|
7099
|
+
processors,
|
|
7100
|
+
integrations,
|
|
7101
|
+
rulesEnforcer,
|
|
7102
|
+
logger,
|
|
7103
|
+
parser,
|
|
7104
|
+
policy,
|
|
7105
|
+
legacySingleProcessorValidation: this.legacySingleProcessorValidation
|
|
7106
|
+
});
|
|
7035
7107
|
const entitiesCatalog = new AuthorizedEntitiesCatalog(
|
|
7036
7108
|
unauthorizedEntitiesCatalog,
|
|
7037
7109
|
permissionsService,
|
|
@@ -7082,7 +7154,10 @@ class CatalogBuilder {
|
|
|
7082
7154
|
},
|
|
7083
7155
|
eventBroker: this.eventBroker
|
|
7084
7156
|
});
|
|
7085
|
-
const locationAnalyzer = this.locationAnalyzer ?? new
|
|
7157
|
+
const locationAnalyzer = this.locationAnalyzer ?? new AuthorizedLocationAnalyzer(
|
|
7158
|
+
new RepoLocationAnalyzer(logger, integrations, this.locationAnalyzers),
|
|
7159
|
+
permissionsService
|
|
7160
|
+
);
|
|
7086
7161
|
const locationService = new AuthorizedLocationService(
|
|
7087
7162
|
new DefaultLocationService(locationStore, orchestrator, {
|
|
7088
7163
|
allowedLocationTypes: this.allowedLocationType
|
|
@@ -7103,7 +7178,8 @@ class CatalogBuilder {
|
|
|
7103
7178
|
config,
|
|
7104
7179
|
permissionIntegrationRouter,
|
|
7105
7180
|
auth,
|
|
7106
|
-
httpAuth
|
|
7181
|
+
httpAuth,
|
|
7182
|
+
permissionsService
|
|
7107
7183
|
});
|
|
7108
7184
|
await connectEntityProviders(providerDatabase, entityProviders);
|
|
7109
7185
|
return {
|
|
@@ -7296,4 +7372,4 @@ exports.createCatalogPermissionRule = createCatalogPermissionRule;
|
|
|
7296
7372
|
exports.createRandomProcessingInterval = createRandomProcessingInterval;
|
|
7297
7373
|
exports.parseEntityYaml = parseEntityYaml;
|
|
7298
7374
|
exports.permissionRules = permissionRules;
|
|
7299
|
-
//# sourceMappingURL=CatalogBuilder-
|
|
7375
|
+
//# sourceMappingURL=CatalogBuilder-CGSl8LEN.cjs.js.map
|