diff --git a/plugins/catalog-backend/api-report.md b/plugins/catalog-backend/api-report.md index 33f0fab18e..aafff2a22e 100644 --- a/plugins/catalog-backend/api-report.md +++ b/plugins/catalog-backend/api-report.md @@ -529,6 +529,11 @@ export class CommonDatabase implements Database { ): Promise; } +// @public +export const createCatalogPermissionRule: ( + rule: PermissionRule, +) => PermissionRule; + // Warning: (ae-missing-release-tag) "CreateDatabaseOptions" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public @deprecated (undocumented) @@ -1397,12 +1402,28 @@ export function parseEntityYaml( // @public export const permissionRules: { - hasAnnotation: CatalogPermissionRule<[annotation: string]>; - hasLabel: CatalogPermissionRule<[label: string]>; - hasMetadata: CatalogPermissionRule<[key: string, value?: string | undefined]>; - hasSpec: CatalogPermissionRule<[key: string, value?: string | undefined]>; - isEntityKind: CatalogPermissionRule<[kinds: string[]]>; - isEntityOwner: CatalogPermissionRule<[claims: string[]]>; + hasAnnotation: PermissionRule< + Entity, + EntitiesSearchFilter, + [annotation: string] + >; + hasLabel: PermissionRule; + hasMetadata: PermissionRule< + Entity, + EntitiesSearchFilter, + [key: string, value?: string | undefined] + >; + hasSpec: PermissionRule< + Entity, + EntitiesSearchFilter, + [key: string, value?: string | undefined] + >; + isEntityKind: PermissionRule; + isEntityOwner: PermissionRule< + Entity, + EntitiesSearchFilter, + [claims: string[]] + >; }; // Warning: (ae-missing-release-tag) "PlaceholderProcessor" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) diff --git a/plugins/catalog-backend/src/permissions/rules/createPropertyRule.ts b/plugins/catalog-backend/src/permissions/rules/createPropertyRule.ts index 254eb164da..27a6033362 100644 --- a/plugins/catalog-backend/src/permissions/rules/createPropertyRule.ts +++ b/plugins/catalog-backend/src/permissions/rules/createPropertyRule.ts @@ -14,15 +14,12 @@ * limitations under the License. */ -import { Entity } from '@backstage/catalog-model'; -import { EntitiesSearchFilter } from '../../catalog/types'; -import { CatalogPermissionRule } from '../types'; import { get } from 'lodash'; +import { Entity } from '@backstage/catalog-model'; +import { createCatalogPermissionRule } from './util'; -export function createPropertyRule( - propertyType: 'metadata' | 'spec', -): CatalogPermissionRule<[key: string, value?: string]> { - return { +export const createPropertyRule = (propertyType: 'metadata' | 'spec') => + createCatalogPermissionRule({ name: `HAS_${propertyType.toUpperCase()}`, description: `Allow entities which have the specified ${propertyType} subfield.`, apply: (resource: Entity, key: string, value?: string) => { @@ -32,9 +29,8 @@ export function createPropertyRule( } return !!foundValue; }, - toQuery: (key: string, value?: string): EntitiesSearchFilter => ({ + toQuery: (key: string, value?: string) => ({ key: `${propertyType}.${key}`, ...(value !== undefined && { values: [value] }), }), - }; -} + }); diff --git a/plugins/catalog-backend/src/permissions/rules/hasAnnotation.ts b/plugins/catalog-backend/src/permissions/rules/hasAnnotation.ts index baab28d838..f82ace6580 100644 --- a/plugins/catalog-backend/src/permissions/rules/hasAnnotation.ts +++ b/plugins/catalog-backend/src/permissions/rules/hasAnnotation.ts @@ -15,21 +15,20 @@ */ import { Entity } from '@backstage/catalog-model'; -import { EntitiesSearchFilter } from '../../catalog/types'; -import { CatalogPermissionRule } from '../types'; +import { createCatalogPermissionRule } from './util'; /** * A {@link CatalogPermissionRule} which filters for the presence of an * annotation on a given entity. * @public */ -export const hasAnnotation: CatalogPermissionRule<[annotation: string]> = { +export const hasAnnotation = createCatalogPermissionRule({ name: 'HAS_ANNOTATION', description: 'Allow entities which are annotated with the specified annotation', apply: (resource: Entity, annotation: string) => !!resource.metadata.annotations?.hasOwnProperty(annotation), - toQuery: (annotation: string): EntitiesSearchFilter => ({ + toQuery: (annotation: string) => ({ key: `metadata.annotations.${annotation}`, }), -}; +}); diff --git a/plugins/catalog-backend/src/permissions/rules/hasLabel.ts b/plugins/catalog-backend/src/permissions/rules/hasLabel.ts index a790f1441f..8e5a3341d7 100644 --- a/plugins/catalog-backend/src/permissions/rules/hasLabel.ts +++ b/plugins/catalog-backend/src/permissions/rules/hasLabel.ts @@ -15,20 +15,19 @@ */ import { Entity } from '@backstage/catalog-model'; -import { EntitiesSearchFilter } from '../../catalog/types'; -import { CatalogPermissionRule } from '../types'; +import { createCatalogPermissionRule } from './util'; /** * A {@link CatalogPermissionRule} which filters for entities with a specified * label in its metadata. * @public */ -export const hasLabel: CatalogPermissionRule<[label: string]> = { +export const hasLabel = createCatalogPermissionRule({ name: 'HAS_LABEL', description: 'Allow entities which have the specified label metadata.', apply: (resource: Entity, label: string) => !!resource.metadata.labels?.hasOwnProperty(label), - toQuery: (label: string): EntitiesSearchFilter => ({ + toQuery: (label: string) => ({ key: `metadata.labels.${label}`, }), -}; +}); diff --git a/plugins/catalog-backend/src/permissions/rules/index.ts b/plugins/catalog-backend/src/permissions/rules/index.ts index 68d1e38715..4eec796c74 100644 --- a/plugins/catalog-backend/src/permissions/rules/index.ts +++ b/plugins/catalog-backend/src/permissions/rules/index.ts @@ -34,3 +34,5 @@ export const permissionRules = { isEntityKind, isEntityOwner, }; + +export { createCatalogPermissionRule } from './util'; diff --git a/plugins/catalog-backend/src/permissions/rules/isEntityKind.ts b/plugins/catalog-backend/src/permissions/rules/isEntityKind.ts index 024188939f..ddaecd314e 100644 --- a/plugins/catalog-backend/src/permissions/rules/isEntityKind.ts +++ b/plugins/catalog-backend/src/permissions/rules/isEntityKind.ts @@ -15,14 +15,14 @@ */ import { Entity } from '@backstage/catalog-model'; import { EntitiesSearchFilter } from '../../catalog/types'; -import { CatalogPermissionRule } from '../types'; +import { createCatalogPermissionRule } from './util'; /** * A {@link CatalogPermissionRule} which filters for entities with a specified * kind. * @public */ -export const isEntityKind: CatalogPermissionRule<[kinds: string[]]> = { +export const isEntityKind = createCatalogPermissionRule({ name: 'IS_ENTITY_KIND', description: 'Allow entities with the specified kind', apply(resource: Entity, kinds: string[]) { @@ -35,4 +35,4 @@ export const isEntityKind: CatalogPermissionRule<[kinds: string[]]> = { values: kinds.map(kind => kind.toLocaleLowerCase('en-US')), }; }, -}; +}); diff --git a/plugins/catalog-backend/src/permissions/rules/isEntityOwner.ts b/plugins/catalog-backend/src/permissions/rules/isEntityOwner.ts index e450cdf721..a7413c4941 100644 --- a/plugins/catalog-backend/src/permissions/rules/isEntityOwner.ts +++ b/plugins/catalog-backend/src/permissions/rules/isEntityOwner.ts @@ -19,15 +19,14 @@ import { RELATION_OWNED_BY, stringifyEntityRef, } from '@backstage/catalog-model'; -import { EntitiesSearchFilter } from '../../catalog/types'; -import { CatalogPermissionRule } from '../types'; +import { createCatalogPermissionRule } from './util'; /** * A {@link CatalogPermissionRule} which filters for entities with a specified * owner. * @public */ -export const isEntityOwner: CatalogPermissionRule<[claims: string[]]> = { +export const isEntityOwner = createCatalogPermissionRule({ name: 'IS_ENTITY_OWNER', description: 'Allow entities owned by the current user', apply: (resource: Entity, claims: string[]) => { @@ -39,8 +38,8 @@ export const isEntityOwner: CatalogPermissionRule<[claims: string[]]> = { .filter(relation => relation.type === RELATION_OWNED_BY) .some(relation => claims.includes(stringifyEntityRef(relation.target))); }, - toQuery: (claims: string[]): EntitiesSearchFilter => ({ + toQuery: (claims: string[]) => ({ key: 'relations.ownedBy', values: claims, }), -}; +}); diff --git a/plugins/catalog-backend/src/permissions/rules/util.ts b/plugins/catalog-backend/src/permissions/rules/util.ts new file mode 100644 index 0000000000..7ef0ca3546 --- /dev/null +++ b/plugins/catalog-backend/src/permissions/rules/util.ts @@ -0,0 +1,31 @@ +/* + * Copyright 2022 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Entity } from '@backstage/catalog-model'; +import { makeCreatePermissionRule } from '@backstage/plugin-permission-node'; +import { EntitiesSearchFilter } from '../../catalog/types'; + +/** + * Helper function for creating correctly-typed + * {@link @backstage/plugin-permission-node#PermissionRule}s for the + * catalog-backend. + * + * @public + */ +export const createCatalogPermissionRule = makeCreatePermissionRule< + Entity, + EntitiesSearchFilter +>();