@backstage/plugin-catalog-backend 1.3.1-next.2 → 1.4.0-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 +52 -0
- package/alpha/package.json +1 -1
- package/dist/index.alpha.d.ts +10 -3
- package/dist/index.beta.d.ts +9 -2
- package/dist/index.cjs.js +57 -16
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +9 -2
- package/package.json +17 -17
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,57 @@
|
|
|
1
1
|
# @backstage/plugin-catalog-backend
|
|
2
2
|
|
|
3
|
+
## 1.4.0-next.1
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- dd395335bc: Allow unknown typed location from being registered via the location service by configuration settings
|
|
8
|
+
- 651c9d6800: The search index now does retain fields that have a very long value, but in the form of just a null. This makes it possible to at least filter for their existence.
|
|
9
|
+
|
|
10
|
+
### Patch Changes
|
|
11
|
+
|
|
12
|
+
- ce77e78c93: Fixes a bug to be able to utilize refresh keys after the entity is loaded from cache
|
|
13
|
+
- 679f7c5e95: Include entity ref into error message when catalog policies fail
|
|
14
|
+
- Updated dependencies
|
|
15
|
+
- @backstage/plugin-permission-node@0.6.5-next.1
|
|
16
|
+
- @backstage/backend-common@0.15.1-next.1
|
|
17
|
+
|
|
18
|
+
## 1.3.2-next.0
|
|
19
|
+
|
|
20
|
+
### Patch Changes
|
|
21
|
+
|
|
22
|
+
- 243533ecdc: Added support to mysql on some raw queries
|
|
23
|
+
- bf5e9030eb: Updated dependency `msw` to `^0.45.0`.
|
|
24
|
+
- 62788b2ee8: The experimental `CatalogProcessingExtensionPoint` now accepts multiple providers and processors at once.
|
|
25
|
+
- Updated dependencies
|
|
26
|
+
- @backstage/backend-common@0.15.1-next.0
|
|
27
|
+
- @backstage/backend-plugin-api@0.1.2-next.0
|
|
28
|
+
- @backstage/catalog-client@1.0.5-next.0
|
|
29
|
+
- @backstage/integration@1.3.1-next.0
|
|
30
|
+
- @backstage/plugin-permission-common@0.6.4-next.0
|
|
31
|
+
- @backstage/plugin-permission-node@0.6.5-next.0
|
|
32
|
+
- @backstage/plugin-scaffolder-common@1.2.0-next.0
|
|
33
|
+
- @backstage/plugin-catalog-node@1.0.2-next.0
|
|
34
|
+
- @backstage/plugin-catalog-common@1.0.6-next.0
|
|
35
|
+
- @backstage/plugin-search-common@1.0.1-next.0
|
|
36
|
+
|
|
37
|
+
## 1.3.1
|
|
38
|
+
|
|
39
|
+
### Patch Changes
|
|
40
|
+
|
|
41
|
+
- 56e1b4b89c: Fixed typos in alpha types.
|
|
42
|
+
- e3d3018531: Fix issue for conditional decisions based on properties stored as arrays, like tags.
|
|
43
|
+
|
|
44
|
+
Before this change, having a permission policy returning conditional decisions based on metadata like tags, such like `createCatalogConditionalDecision(permission, catalogConditions.hasMetadata('tags', 'java'),)`, was producing wrong results. The issue occurred when authorizing entities already loaded from the database, for example when authorizing `catalogEntityDeletePermission`.
|
|
45
|
+
|
|
46
|
+
- 059ae348b4: Use the non-deprecated form of table.unique in knex
|
|
47
|
+
- Updated dependencies
|
|
48
|
+
- @backstage/backend-common@0.15.0
|
|
49
|
+
- @backstage/backend-plugin-api@0.1.1
|
|
50
|
+
- @backstage/plugin-catalog-node@1.0.1
|
|
51
|
+
- @backstage/integration@1.3.0
|
|
52
|
+
- @backstage/plugin-catalog-common@1.0.5
|
|
53
|
+
- @backstage/plugin-permission-node@0.6.4
|
|
54
|
+
|
|
3
55
|
## 1.3.1-next.2
|
|
4
56
|
|
|
5
57
|
### Patch Changes
|
package/alpha/package.json
CHANGED
package/dist/index.alpha.d.ts
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
/// <reference types="node" />
|
|
8
8
|
|
|
9
|
-
import {
|
|
9
|
+
import { BackendFeature } from '@backstage/backend-plugin-api';
|
|
10
10
|
import { CatalogApi } from '@backstage/catalog-client';
|
|
11
11
|
import { CatalogEntityDocument } from '@backstage/plugin-catalog-common';
|
|
12
12
|
import { CatalogProcessor } from '@backstage/plugin-catalog-node';
|
|
@@ -171,7 +171,8 @@ export declare class CatalogBuilder {
|
|
|
171
171
|
private onProcessingError?;
|
|
172
172
|
private processingInterval;
|
|
173
173
|
private locationAnalyzer;
|
|
174
|
-
private permissionRules;
|
|
174
|
+
private readonly permissionRules;
|
|
175
|
+
private allowedLocationType;
|
|
175
176
|
/**
|
|
176
177
|
* Creates a catalog builder.
|
|
177
178
|
*/
|
|
@@ -293,6 +294,12 @@ export declare class CatalogBuilder {
|
|
|
293
294
|
* @alpha
|
|
294
295
|
*/
|
|
295
296
|
addPermissionRules(...permissionRules: Array<CatalogPermissionRule | Array<CatalogPermissionRule>>): void;
|
|
297
|
+
/**
|
|
298
|
+
* Sets up the allowed location types from being registered via the location service.
|
|
299
|
+
*
|
|
300
|
+
* @param allowedLocationTypes - the allowed location types
|
|
301
|
+
*/
|
|
302
|
+
setAllowedLocationTypes(allowedLocationTypes: string[]): CatalogBuilder;
|
|
296
303
|
/**
|
|
297
304
|
* Wires up and returns all of the component parts of the catalog
|
|
298
305
|
*/
|
|
@@ -349,7 +356,7 @@ export declare type CatalogPermissionRule<TParams extends unknown[] = unknown[]>
|
|
|
349
356
|
* Catalog plugin
|
|
350
357
|
* @alpha
|
|
351
358
|
*/
|
|
352
|
-
export declare const catalogPlugin: (
|
|
359
|
+
export declare const catalogPlugin: (options?: unknown) => BackendFeature;
|
|
353
360
|
|
|
354
361
|
/** @public */
|
|
355
362
|
export declare interface CatalogProcessingEngine {
|
package/dist/index.beta.d.ts
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
/// <reference types="node" />
|
|
8
8
|
|
|
9
|
-
import {
|
|
9
|
+
import { BackendFeature } from '@backstage/backend-plugin-api';
|
|
10
10
|
import { CatalogApi } from '@backstage/catalog-client';
|
|
11
11
|
import { CatalogEntityDocument } from '@backstage/plugin-catalog-common';
|
|
12
12
|
import { CatalogProcessor } from '@backstage/plugin-catalog-node';
|
|
@@ -171,7 +171,8 @@ export declare class CatalogBuilder {
|
|
|
171
171
|
private onProcessingError?;
|
|
172
172
|
private processingInterval;
|
|
173
173
|
private locationAnalyzer;
|
|
174
|
-
private permissionRules;
|
|
174
|
+
private readonly permissionRules;
|
|
175
|
+
private allowedLocationType;
|
|
175
176
|
/**
|
|
176
177
|
* Creates a catalog builder.
|
|
177
178
|
*/
|
|
@@ -285,6 +286,12 @@ export declare class CatalogBuilder {
|
|
|
285
286
|
*/
|
|
286
287
|
setEntityDataParser(parser: CatalogProcessorParser): CatalogBuilder;
|
|
287
288
|
/* Excluded from this release type: addPermissionRules */
|
|
289
|
+
/**
|
|
290
|
+
* Sets up the allowed location types from being registered via the location service.
|
|
291
|
+
*
|
|
292
|
+
* @param allowedLocationTypes - the allowed location types
|
|
293
|
+
*/
|
|
294
|
+
setAllowedLocationTypes(allowedLocationTypes: string[]): CatalogBuilder;
|
|
288
295
|
/**
|
|
289
296
|
* Wires up and returns all of the component parts of the catalog
|
|
290
297
|
*/
|
package/dist/index.cjs.js
CHANGED
|
@@ -754,6 +754,7 @@ class UrlReaderProcessor {
|
|
|
754
754
|
for (const parseResult of cacheItem.value) {
|
|
755
755
|
emit(parseResult);
|
|
756
756
|
}
|
|
757
|
+
emit(pluginCatalogNode.processingResult.refresh(`${location.type}:${location.target}`));
|
|
757
758
|
} else if (error.name === "NotFoundError") {
|
|
758
759
|
if (!optional) {
|
|
759
760
|
emit(pluginCatalogNode.processingResult.notFoundError(location, message));
|
|
@@ -1506,7 +1507,7 @@ class DefaultProcessingDatabase {
|
|
|
1506
1507
|
sourceEntityRef
|
|
1507
1508
|
});
|
|
1508
1509
|
let previousRelationRows;
|
|
1509
|
-
if (tx.client.config.client.includes("sqlite3")) {
|
|
1510
|
+
if (tx.client.config.client.includes("sqlite3") || tx.client.config.client.includes("mysql")) {
|
|
1510
1511
|
previousRelationRows = await tx("relations").select("*").where({ originating_entity_id: id });
|
|
1511
1512
|
await tx("relations").where({ originating_entity_id: id }).delete();
|
|
1512
1513
|
} else {
|
|
@@ -1558,6 +1559,12 @@ class DefaultProcessingDatabase {
|
|
|
1558
1559
|
const { toAdd, toUpsert, toRemove } = await this.createDelta(tx, options);
|
|
1559
1560
|
if (toRemove.length) {
|
|
1560
1561
|
let removedCount = 0;
|
|
1562
|
+
const rootId = () => {
|
|
1563
|
+
if (tx.client.config.client.includes("mysql")) {
|
|
1564
|
+
return tx.raw("CAST(NULL as UNSIGNED INT)", []);
|
|
1565
|
+
}
|
|
1566
|
+
return tx.raw("CAST(NULL as INT)", []);
|
|
1567
|
+
};
|
|
1561
1568
|
for (const refs of lodash__default["default"].chunk(toRemove, 1e3)) {
|
|
1562
1569
|
removedCount += await tx("refresh_state").whereIn("entity_ref", function orphanedEntityRefs(orphans) {
|
|
1563
1570
|
return orphans.withRecursive("descendants", function descendants(outer) {
|
|
@@ -1571,7 +1578,7 @@ class DefaultProcessingDatabase {
|
|
|
1571
1578
|
});
|
|
1572
1579
|
}).withRecursive("ancestors", function ancestors(outer) {
|
|
1573
1580
|
return outer.select({
|
|
1574
|
-
root_id:
|
|
1581
|
+
root_id: rootId(),
|
|
1575
1582
|
via_entity_ref: "entity_ref",
|
|
1576
1583
|
to_entity_ref: "entity_ref"
|
|
1577
1584
|
}).from("descendants").union(function recursive(inner) {
|
|
@@ -1695,11 +1702,20 @@ class DefaultProcessingDatabase {
|
|
|
1695
1702
|
}
|
|
1696
1703
|
const items = await itemsQuery.where("next_update_at", "<=", tx.fn.now()).limit(request.processBatchSize).orderBy("next_update_at", "asc");
|
|
1697
1704
|
const interval = this.options.refreshInterval();
|
|
1705
|
+
const nextUpdateAt = (refreshInterval) => {
|
|
1706
|
+
if (tx.client.config.client.includes("sqlite3")) {
|
|
1707
|
+
return tx.raw(`datetime('now', ?)`, [`${refreshInterval} seconds`]);
|
|
1708
|
+
}
|
|
1709
|
+
if (tx.client.config.client.includes("mysql")) {
|
|
1710
|
+
return tx.raw(`now() + interval ${refreshInterval} second`);
|
|
1711
|
+
}
|
|
1712
|
+
return tx.raw(`now() + interval '${refreshInterval} seconds'`);
|
|
1713
|
+
};
|
|
1698
1714
|
await tx("refresh_state").whereIn(
|
|
1699
1715
|
"entity_ref",
|
|
1700
1716
|
items.map((i) => i.entity_ref)
|
|
1701
1717
|
).update({
|
|
1702
|
-
next_update_at:
|
|
1718
|
+
next_update_at: nextUpdateAt(interval)
|
|
1703
1719
|
});
|
|
1704
1720
|
return {
|
|
1705
1721
|
items: items.map(
|
|
@@ -2246,13 +2262,20 @@ function progressTracker() {
|
|
|
2246
2262
|
}
|
|
2247
2263
|
|
|
2248
2264
|
class DefaultLocationService {
|
|
2249
|
-
constructor(store, orchestrator
|
|
2265
|
+
constructor(store, orchestrator, options = {
|
|
2266
|
+
allowedLocationTypes: ["url"]
|
|
2267
|
+
}) {
|
|
2250
2268
|
this.store = store;
|
|
2251
2269
|
this.orchestrator = orchestrator;
|
|
2270
|
+
this.options = options;
|
|
2252
2271
|
}
|
|
2253
2272
|
async createLocation(input, dryRun) {
|
|
2254
|
-
if (input.type
|
|
2255
|
-
throw new errors.InputError(
|
|
2273
|
+
if (!this.options.allowedLocationTypes.includes(input.type)) {
|
|
2274
|
+
throw new errors.InputError(
|
|
2275
|
+
`Registered locations must be of an allowed type ${JSON.stringify(
|
|
2276
|
+
this.options.allowedLocationTypes
|
|
2277
|
+
)}`
|
|
2278
|
+
);
|
|
2256
2279
|
}
|
|
2257
2280
|
if (dryRun) {
|
|
2258
2281
|
return this.dryRunCreateLocation(input);
|
|
@@ -2808,10 +2831,17 @@ class DefaultCatalogProcessingOrchestrator {
|
|
|
2808
2831
|
try {
|
|
2809
2832
|
policyEnforcedEntity = await this.options.policy.enforce(entity);
|
|
2810
2833
|
} catch (e) {
|
|
2811
|
-
throw new errors.InputError(
|
|
2834
|
+
throw new errors.InputError(
|
|
2835
|
+
`Policy check failed for ${catalogModel.stringifyEntityRef(entity)}`,
|
|
2836
|
+
e
|
|
2837
|
+
);
|
|
2812
2838
|
}
|
|
2813
2839
|
if (!policyEnforcedEntity) {
|
|
2814
|
-
throw new Error(
|
|
2840
|
+
throw new Error(
|
|
2841
|
+
`Policy unexpectedly returned no data for ${catalogModel.stringifyEntityRef(
|
|
2842
|
+
entity
|
|
2843
|
+
)}`
|
|
2844
|
+
);
|
|
2815
2845
|
}
|
|
2816
2846
|
return policyEnforcedEntity;
|
|
2817
2847
|
}
|
|
@@ -2981,8 +3011,12 @@ function mapToRows(input, entityId) {
|
|
|
2981
3011
|
result.push({ entity_id: entityId, key, value: null });
|
|
2982
3012
|
} else {
|
|
2983
3013
|
const value = String(rawValue).toLocaleLowerCase("en-US");
|
|
2984
|
-
if (key.length <= MAX_KEY_LENGTH
|
|
2985
|
-
result.push({
|
|
3014
|
+
if (key.length <= MAX_KEY_LENGTH) {
|
|
3015
|
+
result.push({
|
|
3016
|
+
entity_id: entityId,
|
|
3017
|
+
key,
|
|
3018
|
+
value: value.length <= MAX_VALUE_LENGTH ? value : null
|
|
3019
|
+
});
|
|
2986
3020
|
}
|
|
2987
3021
|
}
|
|
2988
3022
|
}
|
|
@@ -3905,6 +3939,7 @@ class CatalogBuilder {
|
|
|
3905
3939
|
this.processorsReplace = false;
|
|
3906
3940
|
this.parser = void 0;
|
|
3907
3941
|
this.permissionRules = Object.values(permissionRules);
|
|
3942
|
+
this.allowedLocationType = ["url"];
|
|
3908
3943
|
}
|
|
3909
3944
|
static create(env) {
|
|
3910
3945
|
return new CatalogBuilder(env);
|
|
@@ -3971,6 +4006,10 @@ class CatalogBuilder {
|
|
|
3971
4006
|
addPermissionRules(...permissionRules) {
|
|
3972
4007
|
this.permissionRules.push(...permissionRules.flat());
|
|
3973
4008
|
}
|
|
4009
|
+
setAllowedLocationTypes(allowedLocationTypes) {
|
|
4010
|
+
this.allowedLocationType = allowedLocationTypes;
|
|
4011
|
+
return this;
|
|
4012
|
+
}
|
|
3974
4013
|
async build() {
|
|
3975
4014
|
var _a, _b;
|
|
3976
4015
|
const { config, database, logger, permissions } = this.env;
|
|
@@ -4056,7 +4095,9 @@ class CatalogBuilder {
|
|
|
4056
4095
|
);
|
|
4057
4096
|
const locationAnalyzer = (_b = this.locationAnalyzer) != null ? _b : new RepoLocationAnalyzer(logger, integrations);
|
|
4058
4097
|
const locationService = new AuthorizedLocationService(
|
|
4059
|
-
new DefaultLocationService(locationStore, orchestrator
|
|
4098
|
+
new DefaultLocationService(locationStore, orchestrator, {
|
|
4099
|
+
allowedLocationTypes: this.allowedLocationType
|
|
4100
|
+
}),
|
|
4060
4101
|
permissionEvaluator
|
|
4061
4102
|
);
|
|
4062
4103
|
const refreshService = new AuthorizedRefreshService(
|
|
@@ -4234,11 +4275,11 @@ class CatalogExtensionPointImpl {
|
|
|
4234
4275
|
__privateAdd(this, _processors, new Array());
|
|
4235
4276
|
__privateAdd(this, _entityProviders, new Array());
|
|
4236
4277
|
}
|
|
4237
|
-
addProcessor(
|
|
4238
|
-
__privateGet(this, _processors).push(
|
|
4278
|
+
addProcessor(...processors) {
|
|
4279
|
+
__privateGet(this, _processors).push(...processors.flat());
|
|
4239
4280
|
}
|
|
4240
|
-
addEntityProvider(
|
|
4241
|
-
__privateGet(this, _entityProviders).push(
|
|
4281
|
+
addEntityProvider(...providers) {
|
|
4282
|
+
__privateGet(this, _entityProviders).push(...providers.flat());
|
|
4242
4283
|
}
|
|
4243
4284
|
get processors() {
|
|
4244
4285
|
return __privateGet(this, _processors);
|
|
@@ -4254,7 +4295,7 @@ const catalogPlugin = backendPluginApi.createBackendPlugin({
|
|
|
4254
4295
|
register(env) {
|
|
4255
4296
|
const processingExtensions = new CatalogExtensionPointImpl();
|
|
4256
4297
|
env.registerExtensionPoint(
|
|
4257
|
-
pluginCatalogNode.
|
|
4298
|
+
pluginCatalogNode.catalogProcessingExtensionPoint,
|
|
4258
4299
|
processingExtensions
|
|
4259
4300
|
);
|
|
4260
4301
|
env.registerInit({
|