catalog-backend: use createPermissionRule helper instead of manually typing rules

Signed-off-by: MT Lewis <mtlewis@users.noreply.github.com>
This commit is contained in:
MT Lewis
2022-01-07 11:47:14 +00:00
parent 9db1b86f32
commit 82cfdc8d02
8 changed files with 81 additions and 34 deletions
+27 -6
View File
@@ -529,6 +529,11 @@ export class CommonDatabase implements Database {
): Promise<DbEntityResponse>;
}
// @public
export const createCatalogPermissionRule: <TParams extends unknown[]>(
rule: PermissionRule<Entity, EntitiesSearchFilter, TParams>,
) => PermissionRule<Entity, EntitiesSearchFilter, TParams>;
// 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<Entity, EntitiesSearchFilter, [label: string]>;
hasMetadata: PermissionRule<
Entity,
EntitiesSearchFilter,
[key: string, value?: string | undefined]
>;
hasSpec: PermissionRule<
Entity,
EntitiesSearchFilter,
[key: string, value?: string | undefined]
>;
isEntityKind: PermissionRule<Entity, EntitiesSearchFilter, [kinds: string[]]>;
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)
@@ -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] }),
}),
};
}
});
@@ -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}`,
}),
};
});
@@ -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}`,
}),
};
});
@@ -34,3 +34,5 @@ export const permissionRules = {
isEntityKind,
isEntityOwner,
};
export { createCatalogPermissionRule } from './util';
@@ -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')),
};
},
};
});
@@ -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,
}),
};
});
@@ -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
>();