@backstage/plugin-catalog-backend 1.0.1-next.0 → 1.1.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 +53 -0
- package/alpha/package.json +1 -1
- package/dist/index.alpha.d.ts +59 -32
- package/dist/index.beta.d.ts +14 -11
- package/dist/index.cjs.js +123 -110
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +14 -11
- package/package.json +11 -11
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,56 @@
|
|
|
1
1
|
# @backstage/plugin-catalog-backend
|
|
2
2
|
|
|
3
|
+
## 1.1.0-next.1
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 8012ac46a0: **BREAKING (alpha api):** Replace `createCatalogPolicyDecision` export with `createCatalogConditionalDecision`, which accepts a permission parameter of type `ResourcePermission<'catalog-entity'>` along with conditions. The permission passed is expected to be the handled permission in `PermissionPolicy#handle`, whose type must first be narrowed using methods like `isPermission` and `isResourcePermission`:
|
|
8
|
+
|
|
9
|
+
```typescript
|
|
10
|
+
class TestPermissionPolicy implements PermissionPolicy {
|
|
11
|
+
async handle(
|
|
12
|
+
request: PolicyQuery<Permission>,
|
|
13
|
+
_user?: BackstageIdentityResponse,
|
|
14
|
+
): Promise<PolicyDecision> {
|
|
15
|
+
if (
|
|
16
|
+
// Narrow type of `request.permission` to `ResourcePermission<'catalog-entity'>
|
|
17
|
+
isResourcePermission(request.permission, RESOURCE_TYPE_CATALOG_ENTITY)
|
|
18
|
+
) {
|
|
19
|
+
return createCatalogConditionalDecision(
|
|
20
|
+
request.permission,
|
|
21
|
+
catalogConditions.isEntityOwner(
|
|
22
|
+
_user?.identity.ownershipEntityRefs ?? [],
|
|
23
|
+
),
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return {
|
|
28
|
+
result: AuthorizeResult.ALLOW,
|
|
29
|
+
};
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
- 8012ac46a0: **BREAKING:** Mark CatalogBuilder#addPermissionRules as @alpha.
|
|
33
|
+
- fb02d2d94d: export `locationSpecToLocationEntity`
|
|
34
|
+
|
|
35
|
+
### Patch Changes
|
|
36
|
+
|
|
37
|
+
- ada4446733: Specify type of `visibilityPermission` property on collators and collator factories.
|
|
38
|
+
- 1691c6c5c2: Clarify that config locations that emit User and Group kinds now need to declare so in the `catalog.locations.[].rules`
|
|
39
|
+
- 8012ac46a0: Handle changes to @alpha permission-related types.
|
|
40
|
+
|
|
41
|
+
- All exported permission rules and conditions now have a `resourceType`.
|
|
42
|
+
- `createCatalogConditionalDecision` now expects supplied conditions to have the appropriate `resourceType`.
|
|
43
|
+
- `createCatalogPermissionRule` now expects `resourceType` as part of the supplied rule object.
|
|
44
|
+
- Introduce new `CatalogPermissionRule` convenience type.
|
|
45
|
+
|
|
46
|
+
- Updated dependencies
|
|
47
|
+
- @backstage/integration@1.1.0-next.1
|
|
48
|
+
- @backstage/plugin-permission-common@0.6.0-next.0
|
|
49
|
+
- @backstage/plugin-permission-node@0.6.0-next.1
|
|
50
|
+
- @backstage/plugin-catalog-common@1.0.1-next.1
|
|
51
|
+
- @backstage/backend-common@0.13.2-next.1
|
|
52
|
+
- @backstage/plugin-search-common@0.3.3-next.1
|
|
53
|
+
|
|
3
54
|
## 1.0.1-next.0
|
|
4
55
|
|
|
5
56
|
### Patch Changes
|
|
@@ -1394,6 +1445,8 @@
|
|
|
1394
1445
|
locations:
|
|
1395
1446
|
- type: github-multi-org
|
|
1396
1447
|
target: https://github.myorg.com
|
|
1448
|
+
rules:
|
|
1449
|
+
- allow: [User, Group]
|
|
1397
1450
|
|
|
1398
1451
|
processors:
|
|
1399
1452
|
githubMultiOrg:
|
package/alpha/package.json
CHANGED
package/dist/index.alpha.d.ts
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
import { CatalogApi } from '@backstage/catalog-client';
|
|
10
10
|
import { CatalogEntityDocument } from '@backstage/plugin-catalog-common';
|
|
11
11
|
import { CompoundEntityRef } from '@backstage/catalog-model';
|
|
12
|
-
import { ConditionalPolicyDecision } from '@backstage/plugin-permission-
|
|
12
|
+
import { ConditionalPolicyDecision } from '@backstage/plugin-permission-common';
|
|
13
13
|
import { Conditions } from '@backstage/plugin-permission-node';
|
|
14
14
|
import { Config } from '@backstage/config';
|
|
15
15
|
import { DocumentCollatorFactory } from '@backstage/plugin-search-common';
|
|
@@ -17,6 +17,7 @@ import { Entity } from '@backstage/catalog-model';
|
|
|
17
17
|
import { EntityPolicy } from '@backstage/catalog-model';
|
|
18
18
|
import { GetEntitiesRequest } from '@backstage/catalog-client';
|
|
19
19
|
import { JsonValue } from '@backstage/types';
|
|
20
|
+
import { LocationEntityV1alpha1 } from '@backstage/catalog-model';
|
|
20
21
|
import { Logger } from 'winston';
|
|
21
22
|
import { Permission } from '@backstage/plugin-permission-common';
|
|
22
23
|
import { PermissionAuthorizer } from '@backstage/plugin-permission-common';
|
|
@@ -26,6 +27,7 @@ import { PermissionRule } from '@backstage/plugin-permission-node';
|
|
|
26
27
|
import { PluginDatabaseManager } from '@backstage/backend-common';
|
|
27
28
|
import { PluginEndpointDiscovery } from '@backstage/backend-common';
|
|
28
29
|
import { Readable } from 'stream';
|
|
30
|
+
import { ResourcePermission } from '@backstage/plugin-permission-common';
|
|
29
31
|
import { Router } from 'express';
|
|
30
32
|
import { ScmIntegrationRegistry } from '@backstage/integration';
|
|
31
33
|
import { TokenManager } from '@backstage/backend-common';
|
|
@@ -269,8 +271,9 @@ export declare class CatalogBuilder {
|
|
|
269
271
|
* {@link @backstage/plugin-permission-node#PermissionRule}.
|
|
270
272
|
*
|
|
271
273
|
* @param permissionRules - Additional permission rules
|
|
274
|
+
* @alpha
|
|
272
275
|
*/
|
|
273
|
-
addPermissionRules(...permissionRules:
|
|
276
|
+
addPermissionRules(...permissionRules: CatalogPermissionRule[]): void;
|
|
274
277
|
/**
|
|
275
278
|
* Wires up and returns all of the component parts of the catalog
|
|
276
279
|
*/
|
|
@@ -285,18 +288,18 @@ export declare class CatalogBuilder {
|
|
|
285
288
|
}
|
|
286
289
|
|
|
287
290
|
/**
|
|
288
|
-
* These conditions are used when creating conditional decisions
|
|
289
|
-
* by authorization policies.
|
|
291
|
+
* These conditions are used when creating conditional decisions for catalog
|
|
292
|
+
* entities that are returned by authorization policies.
|
|
290
293
|
*
|
|
291
294
|
* @alpha
|
|
292
295
|
*/
|
|
293
296
|
export declare const catalogConditions: Conditions< {
|
|
294
|
-
hasAnnotation: PermissionRule<Entity, EntitiesSearchFilter, [annotation: string]>;
|
|
295
|
-
hasLabel: PermissionRule<Entity, EntitiesSearchFilter, [label: string]>;
|
|
296
|
-
hasMetadata: PermissionRule<Entity, EntitiesSearchFilter, [key: string, value?: string | undefined]>;
|
|
297
|
-
hasSpec: PermissionRule<Entity, EntitiesSearchFilter, [key: string, value?: string | undefined]>;
|
|
298
|
-
isEntityKind: PermissionRule<Entity, EntitiesSearchFilter, [kinds: string[]]>;
|
|
299
|
-
isEntityOwner: PermissionRule<Entity, EntitiesSearchFilter, [claims: string[]]>;
|
|
297
|
+
hasAnnotation: PermissionRule<Entity, EntitiesSearchFilter, "catalog-entity", [annotation: string]>;
|
|
298
|
+
hasLabel: PermissionRule<Entity, EntitiesSearchFilter, "catalog-entity", [label: string]>;
|
|
299
|
+
hasMetadata: PermissionRule<Entity, EntitiesSearchFilter, "catalog-entity", [key: string, value?: string | undefined]>;
|
|
300
|
+
hasSpec: PermissionRule<Entity, EntitiesSearchFilter, "catalog-entity", [key: string, value?: string | undefined]>;
|
|
301
|
+
isEntityKind: PermissionRule<Entity, EntitiesSearchFilter, "catalog-entity", [kinds: string[]]>;
|
|
302
|
+
isEntityOwner: PermissionRule<Entity, EntitiesSearchFilter, "catalog-entity", [claims: string[]]>;
|
|
300
303
|
}>;
|
|
301
304
|
|
|
302
305
|
/** @public */
|
|
@@ -308,6 +311,15 @@ export declare type CatalogEnvironment = {
|
|
|
308
311
|
permissions: PermissionAuthorizer;
|
|
309
312
|
};
|
|
310
313
|
|
|
314
|
+
/**
|
|
315
|
+
* Convenience type for {@link @backstage/plugin-permission-node#PermissionRule}
|
|
316
|
+
* instances with the correct resource type, resource, and filter to work with
|
|
317
|
+
* the catalog.
|
|
318
|
+
*
|
|
319
|
+
* @alpha
|
|
320
|
+
*/
|
|
321
|
+
export declare type CatalogPermissionRule<TParams extends unknown[] = unknown[]> = PermissionRule<Entity, EntitiesSearchFilter, 'catalog-entity', TParams>;
|
|
322
|
+
|
|
311
323
|
/** @public */
|
|
312
324
|
export declare interface CatalogProcessingEngine {
|
|
313
325
|
start(): Promise<void>;
|
|
@@ -465,37 +477,46 @@ export declare class CodeOwnersProcessor implements CatalogProcessor {
|
|
|
465
477
|
}
|
|
466
478
|
|
|
467
479
|
/**
|
|
468
|
-
*
|
|
469
|
-
*
|
|
470
|
-
* catalog-
|
|
471
|
-
*
|
|
472
|
-
*
|
|
473
|
-
|
|
474
|
-
export declare const createCatalogPermissionRule: <TParams extends unknown[]>(rule: PermissionRule<Entity, EntitiesSearchFilter, TParams>) => PermissionRule<Entity, EntitiesSearchFilter, TParams>;
|
|
475
|
-
|
|
476
|
-
/**
|
|
477
|
-
* `createCatalogPolicyDecision` can be used when authoring policies to create
|
|
478
|
-
* conditional decisions.
|
|
480
|
+
* `createCatalogConditionalDecision` can be used when authoring policies to
|
|
481
|
+
* create conditional decisions. It requires a permission of type
|
|
482
|
+
* `ResourcePermission<'catalog-entity'>` to be passed as the first parameter.
|
|
483
|
+
* It's recommended that you use the provided `isResourcePermission` and
|
|
484
|
+
* `isPermission` helper methods to narrow the type of the permission passed to
|
|
485
|
+
* the handle method as shown below.
|
|
479
486
|
*
|
|
480
487
|
* ```
|
|
481
488
|
* // MyAuthorizationPolicy.ts
|
|
482
489
|
* ...
|
|
483
490
|
* import { createCatalogPolicyDecision } from '@backstage/plugin-catalog-backend';
|
|
491
|
+
* import { RESOURCE_TYPE_CATALOG_ENTITY } from '@backstage/plugin-catalog-common';
|
|
484
492
|
*
|
|
485
493
|
* class MyAuthorizationPolicy implements PermissionPolicy {
|
|
486
494
|
* async handle(request, user) {
|
|
487
495
|
* ...
|
|
488
496
|
*
|
|
489
|
-
*
|
|
490
|
-
*
|
|
491
|
-
*
|
|
492
|
-
*
|
|
497
|
+
* if (isResourcePermission(request.permission, RESOURCE_TYPE_CATALOG_ENTITY)) {
|
|
498
|
+
* return createCatalogConditionalDecision(
|
|
499
|
+
* request.permission,
|
|
500
|
+
* { anyOf: [...insert conditions here...] }
|
|
501
|
+
* );
|
|
502
|
+
* }
|
|
503
|
+
*
|
|
504
|
+
* ...
|
|
493
505
|
* }
|
|
494
506
|
* ```
|
|
495
507
|
*
|
|
496
508
|
* @alpha
|
|
497
509
|
*/
|
|
498
|
-
export declare const
|
|
510
|
+
export declare const createCatalogConditionalDecision: (permission: ResourcePermission<"catalog-entity">, conditions: PermissionCriteria<PermissionCondition<"catalog-entity", unknown[]>>) => ConditionalPolicyDecision;
|
|
511
|
+
|
|
512
|
+
/**
|
|
513
|
+
* Helper function for creating correctly-typed
|
|
514
|
+
* {@link @backstage/plugin-permission-node#PermissionRule}s for the
|
|
515
|
+
* catalog-backend.
|
|
516
|
+
*
|
|
517
|
+
* @alpha
|
|
518
|
+
*/
|
|
519
|
+
export declare const createCatalogPermissionRule: <TParams extends unknown[]>(rule: PermissionRule<Entity, EntitiesSearchFilter, "catalog-entity", TParams>) => PermissionRule<Entity, EntitiesSearchFilter, "catalog-entity", TParams>;
|
|
499
520
|
|
|
500
521
|
/**
|
|
501
522
|
* Creates a function that returns a random processing interval between minSeconds and maxSeconds.
|
|
@@ -716,6 +737,12 @@ export declare type LocationSpec = {
|
|
|
716
737
|
presence?: 'optional' | 'required';
|
|
717
738
|
};
|
|
718
739
|
|
|
740
|
+
/** @public */
|
|
741
|
+
export declare function locationSpecToLocationEntity(opts: {
|
|
742
|
+
location: LocationSpec;
|
|
743
|
+
parentEntity?: Entity;
|
|
744
|
+
}): LocationEntityV1alpha1;
|
|
745
|
+
|
|
719
746
|
/** @public */
|
|
720
747
|
export declare function parseEntityYaml(data: Buffer, location: LocationSpec): Iterable<CatalogProcessorResult>;
|
|
721
748
|
|
|
@@ -726,12 +753,12 @@ export declare function parseEntityYaml(data: Buffer, location: LocationSpec): I
|
|
|
726
753
|
* @alpha
|
|
727
754
|
*/
|
|
728
755
|
export declare const permissionRules: {
|
|
729
|
-
hasAnnotation: PermissionRule<Entity, EntitiesSearchFilter, [annotation: string]>;
|
|
730
|
-
hasLabel: PermissionRule<Entity, EntitiesSearchFilter, [label: string]>;
|
|
731
|
-
hasMetadata: PermissionRule<Entity, EntitiesSearchFilter, [key: string, value?: string | undefined]>;
|
|
732
|
-
hasSpec: PermissionRule<Entity, EntitiesSearchFilter, [key: string, value?: string | undefined]>;
|
|
733
|
-
isEntityKind: PermissionRule<Entity, EntitiesSearchFilter, [kinds: string[]]>;
|
|
734
|
-
isEntityOwner: PermissionRule<Entity, EntitiesSearchFilter, [claims: string[]]>;
|
|
756
|
+
hasAnnotation: PermissionRule<Entity, EntitiesSearchFilter, "catalog-entity", [annotation: string]>;
|
|
757
|
+
hasLabel: PermissionRule<Entity, EntitiesSearchFilter, "catalog-entity", [label: string]>;
|
|
758
|
+
hasMetadata: PermissionRule<Entity, EntitiesSearchFilter, "catalog-entity", [key: string, value?: string | undefined]>;
|
|
759
|
+
hasSpec: PermissionRule<Entity, EntitiesSearchFilter, "catalog-entity", [key: string, value?: string | undefined]>;
|
|
760
|
+
isEntityKind: PermissionRule<Entity, EntitiesSearchFilter, "catalog-entity", [kinds: string[]]>;
|
|
761
|
+
isEntityOwner: PermissionRule<Entity, EntitiesSearchFilter, "catalog-entity", [claims: string[]]>;
|
|
735
762
|
};
|
|
736
763
|
|
|
737
764
|
/**
|
package/dist/index.beta.d.ts
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
import { CatalogApi } from '@backstage/catalog-client';
|
|
10
10
|
import { CatalogEntityDocument } from '@backstage/plugin-catalog-common';
|
|
11
11
|
import { CompoundEntityRef } from '@backstage/catalog-model';
|
|
12
|
-
import { ConditionalPolicyDecision } from '@backstage/plugin-permission-
|
|
12
|
+
import { ConditionalPolicyDecision } from '@backstage/plugin-permission-common';
|
|
13
13
|
import { Conditions } from '@backstage/plugin-permission-node';
|
|
14
14
|
import { Config } from '@backstage/config';
|
|
15
15
|
import { DocumentCollatorFactory } from '@backstage/plugin-search-common';
|
|
@@ -17,6 +17,7 @@ import { Entity } from '@backstage/catalog-model';
|
|
|
17
17
|
import { EntityPolicy } from '@backstage/catalog-model';
|
|
18
18
|
import { GetEntitiesRequest } from '@backstage/catalog-client';
|
|
19
19
|
import { JsonValue } from '@backstage/types';
|
|
20
|
+
import { LocationEntityV1alpha1 } from '@backstage/catalog-model';
|
|
20
21
|
import { Logger } from 'winston';
|
|
21
22
|
import { Permission } from '@backstage/plugin-permission-common';
|
|
22
23
|
import { PermissionAuthorizer } from '@backstage/plugin-permission-common';
|
|
@@ -26,6 +27,7 @@ import { PermissionRule } from '@backstage/plugin-permission-node';
|
|
|
26
27
|
import { PluginDatabaseManager } from '@backstage/backend-common';
|
|
27
28
|
import { PluginEndpointDiscovery } from '@backstage/backend-common';
|
|
28
29
|
import { Readable } from 'stream';
|
|
30
|
+
import { ResourcePermission } from '@backstage/plugin-permission-common';
|
|
29
31
|
import { Router } from 'express';
|
|
30
32
|
import { ScmIntegrationRegistry } from '@backstage/integration';
|
|
31
33
|
import { TokenManager } from '@backstage/backend-common';
|
|
@@ -263,14 +265,7 @@ export declare class CatalogBuilder {
|
|
|
263
265
|
* @param parser - The custom parser
|
|
264
266
|
*/
|
|
265
267
|
setEntityDataParser(parser: CatalogProcessorParser): CatalogBuilder;
|
|
266
|
-
|
|
267
|
-
* Adds additional permission rules. Permission rules are used to evaluate
|
|
268
|
-
* catalog resources against queries. See
|
|
269
|
-
* {@link @backstage/plugin-permission-node#PermissionRule}.
|
|
270
|
-
*
|
|
271
|
-
* @param permissionRules - Additional permission rules
|
|
272
|
-
*/
|
|
273
|
-
addPermissionRules(...permissionRules: PermissionRule<Entity, EntitiesSearchFilter, unknown[]>[]): void;
|
|
268
|
+
/* Excluded from this release type: addPermissionRules */
|
|
274
269
|
/**
|
|
275
270
|
* Wires up and returns all of the component parts of the catalog
|
|
276
271
|
*/
|
|
@@ -295,6 +290,8 @@ export declare type CatalogEnvironment = {
|
|
|
295
290
|
permissions: PermissionAuthorizer;
|
|
296
291
|
};
|
|
297
292
|
|
|
293
|
+
/* Excluded from this release type: CatalogPermissionRule */
|
|
294
|
+
|
|
298
295
|
/** @public */
|
|
299
296
|
export declare interface CatalogProcessingEngine {
|
|
300
297
|
start(): Promise<void>;
|
|
@@ -451,9 +448,9 @@ export declare class CodeOwnersProcessor implements CatalogProcessor {
|
|
|
451
448
|
preProcessEntity(entity: Entity, location: LocationSpec): Promise<Entity>;
|
|
452
449
|
}
|
|
453
450
|
|
|
454
|
-
/* Excluded from this release type:
|
|
451
|
+
/* Excluded from this release type: createCatalogConditionalDecision */
|
|
455
452
|
|
|
456
|
-
/* Excluded from this release type:
|
|
453
|
+
/* Excluded from this release type: createCatalogPermissionRule */
|
|
457
454
|
|
|
458
455
|
/**
|
|
459
456
|
* Creates a function that returns a random processing interval between minSeconds and maxSeconds.
|
|
@@ -674,6 +671,12 @@ export declare type LocationSpec = {
|
|
|
674
671
|
presence?: 'optional' | 'required';
|
|
675
672
|
};
|
|
676
673
|
|
|
674
|
+
/** @public */
|
|
675
|
+
export declare function locationSpecToLocationEntity(opts: {
|
|
676
|
+
location: LocationSpec;
|
|
677
|
+
parentEntity?: Entity;
|
|
678
|
+
}): LocationEntityV1alpha1;
|
|
679
|
+
|
|
677
680
|
/** @public */
|
|
678
681
|
export declare function parseEntityYaml(data: Buffer, location: LocationSpec): Iterable<CatalogProcessorResult>;
|
|
679
682
|
|
package/dist/index.cjs.js
CHANGED
|
@@ -16,8 +16,9 @@ var path = require('path');
|
|
|
16
16
|
var util = require('util');
|
|
17
17
|
var yaml = require('yaml');
|
|
18
18
|
var limiterFactory = require('p-limit');
|
|
19
|
-
var catalogClient = require('@backstage/catalog-client');
|
|
20
19
|
var pluginCatalogCommon = require('@backstage/plugin-catalog-common');
|
|
20
|
+
var pluginPermissionNode = require('@backstage/plugin-permission-node');
|
|
21
|
+
var catalogClient = require('@backstage/catalog-client');
|
|
21
22
|
var stream = require('stream');
|
|
22
23
|
var crypto = require('crypto');
|
|
23
24
|
var uuid = require('uuid');
|
|
@@ -30,7 +31,6 @@ var Router = require('express-promise-router');
|
|
|
30
31
|
var yn = require('yn');
|
|
31
32
|
var zod = require('zod');
|
|
32
33
|
var pluginPermissionCommon = require('@backstage/plugin-permission-common');
|
|
33
|
-
var pluginPermissionNode = require('@backstage/plugin-permission-node');
|
|
34
34
|
|
|
35
35
|
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
36
36
|
|
|
@@ -676,6 +676,111 @@ const defaultEntityDataParser = async function* defaultEntityDataParser2({ data,
|
|
|
676
676
|
}
|
|
677
677
|
};
|
|
678
678
|
|
|
679
|
+
const createCatalogPermissionRule = pluginPermissionNode.makeCreatePermissionRule();
|
|
680
|
+
|
|
681
|
+
const hasAnnotation = createCatalogPermissionRule({
|
|
682
|
+
name: "HAS_ANNOTATION",
|
|
683
|
+
description: "Allow entities which are annotated with the specified annotation",
|
|
684
|
+
resourceType: pluginCatalogCommon.RESOURCE_TYPE_CATALOG_ENTITY,
|
|
685
|
+
apply: (resource, annotation) => {
|
|
686
|
+
var _a;
|
|
687
|
+
return !!((_a = resource.metadata.annotations) == null ? void 0 : _a.hasOwnProperty(annotation));
|
|
688
|
+
},
|
|
689
|
+
toQuery: (annotation) => ({
|
|
690
|
+
key: `metadata.annotations.${annotation}`
|
|
691
|
+
})
|
|
692
|
+
});
|
|
693
|
+
|
|
694
|
+
const isEntityKind = createCatalogPermissionRule({
|
|
695
|
+
name: "IS_ENTITY_KIND",
|
|
696
|
+
description: "Allow entities with the specified kind",
|
|
697
|
+
resourceType: pluginCatalogCommon.RESOURCE_TYPE_CATALOG_ENTITY,
|
|
698
|
+
apply(resource, kinds) {
|
|
699
|
+
const resourceKind = resource.kind.toLocaleLowerCase("en-US");
|
|
700
|
+
return kinds.some((kind) => kind.toLocaleLowerCase("en-US") === resourceKind);
|
|
701
|
+
},
|
|
702
|
+
toQuery(kinds) {
|
|
703
|
+
return {
|
|
704
|
+
key: "kind",
|
|
705
|
+
values: kinds.map((kind) => kind.toLocaleLowerCase("en-US"))
|
|
706
|
+
};
|
|
707
|
+
}
|
|
708
|
+
});
|
|
709
|
+
|
|
710
|
+
const isEntityOwner = createCatalogPermissionRule({
|
|
711
|
+
name: "IS_ENTITY_OWNER",
|
|
712
|
+
description: "Allow entities owned by the current user",
|
|
713
|
+
resourceType: pluginCatalogCommon.RESOURCE_TYPE_CATALOG_ENTITY,
|
|
714
|
+
apply: (resource, claims) => {
|
|
715
|
+
if (!resource.relations) {
|
|
716
|
+
return false;
|
|
717
|
+
}
|
|
718
|
+
return resource.relations.filter((relation) => relation.type === catalogModel.RELATION_OWNED_BY).some((relation) => claims.includes(relation.targetRef));
|
|
719
|
+
},
|
|
720
|
+
toQuery: (claims) => ({
|
|
721
|
+
key: "relations.ownedBy",
|
|
722
|
+
values: claims
|
|
723
|
+
})
|
|
724
|
+
});
|
|
725
|
+
|
|
726
|
+
const hasLabel = createCatalogPermissionRule({
|
|
727
|
+
name: "HAS_LABEL",
|
|
728
|
+
description: "Allow entities which have the specified label metadata.",
|
|
729
|
+
resourceType: pluginCatalogCommon.RESOURCE_TYPE_CATALOG_ENTITY,
|
|
730
|
+
apply: (resource, label) => {
|
|
731
|
+
var _a;
|
|
732
|
+
return !!((_a = resource.metadata.labels) == null ? void 0 : _a.hasOwnProperty(label));
|
|
733
|
+
},
|
|
734
|
+
toQuery: (label) => ({
|
|
735
|
+
key: `metadata.labels.${label}`
|
|
736
|
+
})
|
|
737
|
+
});
|
|
738
|
+
|
|
739
|
+
const createPropertyRule = (propertyType) => createCatalogPermissionRule({
|
|
740
|
+
name: `HAS_${propertyType.toUpperCase()}`,
|
|
741
|
+
description: `Allow entities which have the specified ${propertyType} subfield.`,
|
|
742
|
+
resourceType: pluginCatalogCommon.RESOURCE_TYPE_CATALOG_ENTITY,
|
|
743
|
+
apply: (resource, key, value) => {
|
|
744
|
+
const foundValue = lodash.get(resource[propertyType], key);
|
|
745
|
+
if (value !== void 0) {
|
|
746
|
+
return value === foundValue;
|
|
747
|
+
}
|
|
748
|
+
return !!foundValue;
|
|
749
|
+
},
|
|
750
|
+
toQuery: (key, value) => ({
|
|
751
|
+
key: `${propertyType}.${key}`,
|
|
752
|
+
...value !== void 0 && { values: [value] }
|
|
753
|
+
})
|
|
754
|
+
});
|
|
755
|
+
|
|
756
|
+
const hasMetadata = createPropertyRule("metadata");
|
|
757
|
+
|
|
758
|
+
const hasSpec = createPropertyRule("spec");
|
|
759
|
+
|
|
760
|
+
const permissionRules = {
|
|
761
|
+
hasAnnotation,
|
|
762
|
+
hasLabel,
|
|
763
|
+
hasMetadata,
|
|
764
|
+
hasSpec,
|
|
765
|
+
isEntityKind,
|
|
766
|
+
isEntityOwner
|
|
767
|
+
};
|
|
768
|
+
|
|
769
|
+
const { conditions, createConditionalDecision } = pluginPermissionNode.createConditionExports({
|
|
770
|
+
pluginId: "catalog",
|
|
771
|
+
resourceType: pluginCatalogCommon.RESOURCE_TYPE_CATALOG_ENTITY,
|
|
772
|
+
rules: permissionRules
|
|
773
|
+
});
|
|
774
|
+
const catalogConditions = conditions;
|
|
775
|
+
const createCatalogConditionalDecision = createConditionalDecision;
|
|
776
|
+
|
|
777
|
+
function createRandomProcessingInterval(options) {
|
|
778
|
+
const { minSeconds, maxSeconds } = options;
|
|
779
|
+
return () => {
|
|
780
|
+
return Math.random() * (maxSeconds - minSeconds) + minSeconds;
|
|
781
|
+
};
|
|
782
|
+
}
|
|
783
|
+
|
|
679
784
|
class DefaultCatalogCollatorFactory {
|
|
680
785
|
constructor(options) {
|
|
681
786
|
this.type = "software-catalog";
|
|
@@ -828,13 +933,6 @@ class DefaultCatalogCollator {
|
|
|
828
933
|
}
|
|
829
934
|
}
|
|
830
935
|
|
|
831
|
-
function createRandomProcessingInterval(options) {
|
|
832
|
-
const { minSeconds, maxSeconds } = options;
|
|
833
|
-
return () => {
|
|
834
|
-
return Math.random() * (maxSeconds - minSeconds) + minSeconds;
|
|
835
|
-
};
|
|
836
|
-
}
|
|
837
|
-
|
|
838
936
|
function isLocationEntity(entity) {
|
|
839
937
|
return entity.kind === "Location";
|
|
840
938
|
}
|
|
@@ -884,8 +982,10 @@ function locationSpecToMetadataName(location) {
|
|
|
884
982
|
const hash = crypto.createHash("sha1").update(`${location.type}:${location.target}`).digest("hex");
|
|
885
983
|
return `generated-${hash}`;
|
|
886
984
|
}
|
|
887
|
-
function locationSpecToLocationEntity(
|
|
985
|
+
function locationSpecToLocationEntity(opts) {
|
|
888
986
|
var _a, _b;
|
|
987
|
+
const location = opts.location;
|
|
988
|
+
const parentEntity = opts.parentEntity;
|
|
889
989
|
let ownLocation;
|
|
890
990
|
let originLocation;
|
|
891
991
|
if (parentEntity) {
|
|
@@ -957,8 +1057,10 @@ class ConfigLocationEntityProvider {
|
|
|
957
1057
|
const type = location.getString("type");
|
|
958
1058
|
const target = location.getString("target");
|
|
959
1059
|
const entity = locationSpecToLocationEntity({
|
|
960
|
-
|
|
961
|
-
|
|
1060
|
+
location: {
|
|
1061
|
+
type,
|
|
1062
|
+
target: type === "file" ? path__default["default"].resolve(target) : target
|
|
1063
|
+
}
|
|
962
1064
|
});
|
|
963
1065
|
const locationKey = getEntityLocationRef(entity);
|
|
964
1066
|
return { entity, locationKey };
|
|
@@ -988,7 +1090,7 @@ class DefaultLocationStore {
|
|
|
988
1090
|
await tx("locations").insert(inner);
|
|
989
1091
|
return inner;
|
|
990
1092
|
});
|
|
991
|
-
const entity = locationSpecToLocationEntity(location);
|
|
1093
|
+
const entity = locationSpecToLocationEntity({ location });
|
|
992
1094
|
await this.connection.applyMutation({
|
|
993
1095
|
type: "delta",
|
|
994
1096
|
added: [{ entity, locationKey: getEntityLocationRef(entity) }],
|
|
@@ -1018,7 +1120,7 @@ class DefaultLocationStore {
|
|
|
1018
1120
|
await tx("locations").where({ id }).del();
|
|
1019
1121
|
return location;
|
|
1020
1122
|
});
|
|
1021
|
-
const entity = locationSpecToLocationEntity(deleted);
|
|
1123
|
+
const entity = locationSpecToLocationEntity({ location: deleted });
|
|
1022
1124
|
await this.connection.applyMutation({
|
|
1023
1125
|
type: "delta",
|
|
1024
1126
|
added: [],
|
|
@@ -1035,7 +1137,7 @@ class DefaultLocationStore {
|
|
|
1035
1137
|
this._connection = connection;
|
|
1036
1138
|
const locations = await this.locations();
|
|
1037
1139
|
const entities = locations.map((location) => {
|
|
1038
|
-
const entity = locationSpecToLocationEntity(location);
|
|
1140
|
+
const entity = locationSpecToLocationEntity({ location });
|
|
1039
1141
|
return { entity, locationKey: getEntityLocationRef(entity) };
|
|
1040
1142
|
});
|
|
1041
1143
|
await this.connection.applyMutation({
|
|
@@ -2136,7 +2238,10 @@ class ProcessorOutputCollector {
|
|
|
2136
2238
|
}
|
|
2137
2239
|
this.deferredEntities.push({ entity, locationKey: location });
|
|
2138
2240
|
} else if (i.type === "location") {
|
|
2139
|
-
const entity = locationSpecToLocationEntity(
|
|
2241
|
+
const entity = locationSpecToLocationEntity({
|
|
2242
|
+
location: i.location,
|
|
2243
|
+
parentEntity: this.parentEntity
|
|
2244
|
+
});
|
|
2140
2245
|
const locationKey = getEntityLocationRef(entity);
|
|
2141
2246
|
this.deferredEntities.push({ entity, locationKey });
|
|
2142
2247
|
} else if (i.type === "relation") {
|
|
@@ -3067,91 +3172,6 @@ async function connectEntityProviders(db, providers) {
|
|
|
3067
3172
|
}));
|
|
3068
3173
|
}
|
|
3069
3174
|
|
|
3070
|
-
const createCatalogPermissionRule = pluginPermissionNode.makeCreatePermissionRule();
|
|
3071
|
-
|
|
3072
|
-
const hasAnnotation = createCatalogPermissionRule({
|
|
3073
|
-
name: "HAS_ANNOTATION",
|
|
3074
|
-
description: "Allow entities which are annotated with the specified annotation",
|
|
3075
|
-
apply: (resource, annotation) => {
|
|
3076
|
-
var _a;
|
|
3077
|
-
return !!((_a = resource.metadata.annotations) == null ? void 0 : _a.hasOwnProperty(annotation));
|
|
3078
|
-
},
|
|
3079
|
-
toQuery: (annotation) => ({
|
|
3080
|
-
key: `metadata.annotations.${annotation}`
|
|
3081
|
-
})
|
|
3082
|
-
});
|
|
3083
|
-
|
|
3084
|
-
const isEntityKind = createCatalogPermissionRule({
|
|
3085
|
-
name: "IS_ENTITY_KIND",
|
|
3086
|
-
description: "Allow entities with the specified kind",
|
|
3087
|
-
apply(resource, kinds) {
|
|
3088
|
-
const resourceKind = resource.kind.toLocaleLowerCase("en-US");
|
|
3089
|
-
return kinds.some((kind) => kind.toLocaleLowerCase("en-US") === resourceKind);
|
|
3090
|
-
},
|
|
3091
|
-
toQuery(kinds) {
|
|
3092
|
-
return {
|
|
3093
|
-
key: "kind",
|
|
3094
|
-
values: kinds.map((kind) => kind.toLocaleLowerCase("en-US"))
|
|
3095
|
-
};
|
|
3096
|
-
}
|
|
3097
|
-
});
|
|
3098
|
-
|
|
3099
|
-
const isEntityOwner = createCatalogPermissionRule({
|
|
3100
|
-
name: "IS_ENTITY_OWNER",
|
|
3101
|
-
description: "Allow entities owned by the current user",
|
|
3102
|
-
apply: (resource, claims) => {
|
|
3103
|
-
if (!resource.relations) {
|
|
3104
|
-
return false;
|
|
3105
|
-
}
|
|
3106
|
-
return resource.relations.filter((relation) => relation.type === catalogModel.RELATION_OWNED_BY).some((relation) => claims.includes(relation.targetRef));
|
|
3107
|
-
},
|
|
3108
|
-
toQuery: (claims) => ({
|
|
3109
|
-
key: "relations.ownedBy",
|
|
3110
|
-
values: claims
|
|
3111
|
-
})
|
|
3112
|
-
});
|
|
3113
|
-
|
|
3114
|
-
const hasLabel = createCatalogPermissionRule({
|
|
3115
|
-
name: "HAS_LABEL",
|
|
3116
|
-
description: "Allow entities which have the specified label metadata.",
|
|
3117
|
-
apply: (resource, label) => {
|
|
3118
|
-
var _a;
|
|
3119
|
-
return !!((_a = resource.metadata.labels) == null ? void 0 : _a.hasOwnProperty(label));
|
|
3120
|
-
},
|
|
3121
|
-
toQuery: (label) => ({
|
|
3122
|
-
key: `metadata.labels.${label}`
|
|
3123
|
-
})
|
|
3124
|
-
});
|
|
3125
|
-
|
|
3126
|
-
const createPropertyRule = (propertyType) => createCatalogPermissionRule({
|
|
3127
|
-
name: `HAS_${propertyType.toUpperCase()}`,
|
|
3128
|
-
description: `Allow entities which have the specified ${propertyType} subfield.`,
|
|
3129
|
-
apply: (resource, key, value) => {
|
|
3130
|
-
const foundValue = lodash.get(resource[propertyType], key);
|
|
3131
|
-
if (value !== void 0) {
|
|
3132
|
-
return value === foundValue;
|
|
3133
|
-
}
|
|
3134
|
-
return !!foundValue;
|
|
3135
|
-
},
|
|
3136
|
-
toQuery: (key, value) => ({
|
|
3137
|
-
key: `${propertyType}.${key}`,
|
|
3138
|
-
...value !== void 0 && { values: [value] }
|
|
3139
|
-
})
|
|
3140
|
-
});
|
|
3141
|
-
|
|
3142
|
-
const hasMetadata = createPropertyRule("metadata");
|
|
3143
|
-
|
|
3144
|
-
const hasSpec = createPropertyRule("spec");
|
|
3145
|
-
|
|
3146
|
-
const permissionRules = {
|
|
3147
|
-
hasAnnotation,
|
|
3148
|
-
hasLabel,
|
|
3149
|
-
hasMetadata,
|
|
3150
|
-
hasSpec,
|
|
3151
|
-
isEntityKind,
|
|
3152
|
-
isEntityOwner
|
|
3153
|
-
};
|
|
3154
|
-
|
|
3155
3175
|
class AuthorizedEntitiesCatalog {
|
|
3156
3176
|
constructor(entitiesCatalog, permissionApi, transformConditions) {
|
|
3157
3177
|
this.entitiesCatalog = entitiesCatalog;
|
|
@@ -3515,14 +3535,6 @@ class CatalogBuilder {
|
|
|
3515
3535
|
}
|
|
3516
3536
|
}
|
|
3517
3537
|
|
|
3518
|
-
const conditionExports = pluginPermissionNode.createConditionExports({
|
|
3519
|
-
pluginId: "catalog",
|
|
3520
|
-
resourceType: pluginCatalogCommon.RESOURCE_TYPE_CATALOG_ENTITY,
|
|
3521
|
-
rules: permissionRules
|
|
3522
|
-
});
|
|
3523
|
-
const catalogConditions = conditionExports.conditions;
|
|
3524
|
-
const createCatalogPolicyDecision = conditionExports.createPolicyDecision;
|
|
3525
|
-
|
|
3526
3538
|
exports.AnnotateLocationEntityProcessor = AnnotateLocationEntityProcessor;
|
|
3527
3539
|
exports.AnnotateScmSlugEntityProcessor = AnnotateScmSlugEntityProcessor;
|
|
3528
3540
|
exports.BuiltinKindsEntityProcessor = BuiltinKindsEntityProcessor;
|
|
@@ -3535,9 +3547,10 @@ exports.LocationEntityProcessor = LocationEntityProcessor;
|
|
|
3535
3547
|
exports.PlaceholderProcessor = PlaceholderProcessor;
|
|
3536
3548
|
exports.UrlReaderProcessor = UrlReaderProcessor;
|
|
3537
3549
|
exports.catalogConditions = catalogConditions;
|
|
3550
|
+
exports.createCatalogConditionalDecision = createCatalogConditionalDecision;
|
|
3538
3551
|
exports.createCatalogPermissionRule = createCatalogPermissionRule;
|
|
3539
|
-
exports.createCatalogPolicyDecision = createCatalogPolicyDecision;
|
|
3540
3552
|
exports.createRandomProcessingInterval = createRandomProcessingInterval;
|
|
3553
|
+
exports.locationSpecToLocationEntity = locationSpecToLocationEntity;
|
|
3541
3554
|
exports.parseEntityYaml = parseEntityYaml;
|
|
3542
3555
|
exports.permissionRules = permissionRules;
|
|
3543
3556
|
exports.processingResult = processingResult;
|