@@ -40,6 +40,7 @@ import { PermissionCondition } from '@backstage/plugin-permission-common';
|
||||
import { PermissionCriteria } from '@backstage/plugin-permission-common';
|
||||
import { PermissionEvaluator } from '@backstage/plugin-permission-common';
|
||||
import { PermissionRule } from '@backstage/plugin-permission-node';
|
||||
import { PermissionRuleParams } from '@backstage/plugin-permission-common';
|
||||
import { PluginDatabaseManager } from '@backstage/backend-common';
|
||||
import { PluginEndpointDiscovery } from '@backstage/backend-common';
|
||||
import { processingResult } from '@backstage/plugin-catalog-node';
|
||||
@@ -177,37 +178,52 @@ export const catalogConditions: Conditions<{
|
||||
Entity,
|
||||
EntitiesSearchFilter,
|
||||
'catalog-entity',
|
||||
[annotation: string, value?: string | undefined]
|
||||
{
|
||||
annotation: string;
|
||||
value: string | undefined;
|
||||
}
|
||||
>;
|
||||
hasLabel: PermissionRule<
|
||||
Entity,
|
||||
EntitiesSearchFilter,
|
||||
'catalog-entity',
|
||||
[label: string]
|
||||
{
|
||||
label: string;
|
||||
}
|
||||
>;
|
||||
hasMetadata: PermissionRule<
|
||||
Entity,
|
||||
EntitiesSearchFilter,
|
||||
'catalog-entity',
|
||||
[key: string, value?: string | undefined]
|
||||
{
|
||||
key: string;
|
||||
value: string | undefined;
|
||||
}
|
||||
>;
|
||||
hasSpec: PermissionRule<
|
||||
Entity,
|
||||
EntitiesSearchFilter,
|
||||
'catalog-entity',
|
||||
[key: string, value?: string | undefined]
|
||||
{
|
||||
key: string;
|
||||
value: string | undefined;
|
||||
}
|
||||
>;
|
||||
isEntityKind: PermissionRule<
|
||||
Entity,
|
||||
EntitiesSearchFilter,
|
||||
'catalog-entity',
|
||||
[kinds: string[]]
|
||||
{
|
||||
kinds: string[];
|
||||
}
|
||||
>;
|
||||
isEntityOwner: PermissionRule<
|
||||
Entity,
|
||||
EntitiesSearchFilter,
|
||||
'catalog-entity',
|
||||
[claims: string[]]
|
||||
{
|
||||
claims: string[];
|
||||
}
|
||||
>;
|
||||
}>;
|
||||
|
||||
@@ -221,8 +237,9 @@ export type CatalogEnvironment = {
|
||||
};
|
||||
|
||||
// @alpha
|
||||
export type CatalogPermissionRule<TParams extends unknown[] = unknown[]> =
|
||||
PermissionRule<Entity, EntitiesSearchFilter, 'catalog-entity', TParams>;
|
||||
export type CatalogPermissionRule<
|
||||
TParams extends PermissionRuleParams = PermissionRuleParams,
|
||||
> = PermissionRule<Entity, EntitiesSearchFilter, 'catalog-entity', TParams>;
|
||||
|
||||
// @alpha
|
||||
export const catalogPlugin: (options?: undefined) => BackendFeature;
|
||||
@@ -280,12 +297,14 @@ export class CodeOwnersProcessor implements CatalogProcessor {
|
||||
export const createCatalogConditionalDecision: (
|
||||
permission: ResourcePermission<'catalog-entity'>,
|
||||
conditions: PermissionCriteria<
|
||||
PermissionCondition<'catalog-entity', unknown[]>
|
||||
PermissionCondition<'catalog-entity', PermissionRuleParams>
|
||||
>,
|
||||
) => ConditionalPolicyDecision;
|
||||
|
||||
// @alpha
|
||||
export const createCatalogPermissionRule: <TParams extends unknown[]>(
|
||||
export const createCatalogPermissionRule: <
|
||||
TParams extends PermissionRuleParams = PermissionRuleParams,
|
||||
>(
|
||||
rule: PermissionRule<Entity, EntitiesSearchFilter, 'catalog-entity', TParams>,
|
||||
) => PermissionRule<Entity, EntitiesSearchFilter, 'catalog-entity', TParams>;
|
||||
|
||||
@@ -448,37 +467,52 @@ export const permissionRules: {
|
||||
Entity,
|
||||
EntitiesSearchFilter,
|
||||
'catalog-entity',
|
||||
[annotation: string, value?: string | undefined]
|
||||
{
|
||||
annotation: string;
|
||||
value: string | undefined;
|
||||
}
|
||||
>;
|
||||
hasLabel: PermissionRule<
|
||||
Entity,
|
||||
EntitiesSearchFilter,
|
||||
'catalog-entity',
|
||||
[label: string]
|
||||
{
|
||||
label: string;
|
||||
}
|
||||
>;
|
||||
hasMetadata: PermissionRule<
|
||||
Entity,
|
||||
EntitiesSearchFilter,
|
||||
'catalog-entity',
|
||||
[key: string, value?: string | undefined]
|
||||
{
|
||||
key: string;
|
||||
value: string | undefined;
|
||||
}
|
||||
>;
|
||||
hasSpec: PermissionRule<
|
||||
Entity,
|
||||
EntitiesSearchFilter,
|
||||
'catalog-entity',
|
||||
[key: string, value?: string | undefined]
|
||||
{
|
||||
key: string;
|
||||
value: string | undefined;
|
||||
}
|
||||
>;
|
||||
isEntityKind: PermissionRule<
|
||||
Entity,
|
||||
EntitiesSearchFilter,
|
||||
'catalog-entity',
|
||||
[kinds: string[]]
|
||||
{
|
||||
kinds: string[];
|
||||
}
|
||||
>;
|
||||
isEntityOwner: PermissionRule<
|
||||
Entity,
|
||||
EntitiesSearchFilter,
|
||||
'catalog-entity',
|
||||
[claims: string[]]
|
||||
{
|
||||
claims: string[];
|
||||
}
|
||||
>;
|
||||
};
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
```ts
|
||||
import { Config } from '@backstage/config';
|
||||
import { JsonPrimitive } from '@backstage/types';
|
||||
|
||||
// @public
|
||||
export type AllOfCriteria<TQuery> = {
|
||||
@@ -172,7 +173,7 @@ export class PermissionClient implements PermissionEvaluator {
|
||||
// @public
|
||||
export type PermissionCondition<
|
||||
TResourceType extends string = string,
|
||||
TParams extends unknown[] = unknown[],
|
||||
TParams extends PermissionRuleParams = PermissionRuleParams,
|
||||
> = {
|
||||
resourceType: TResourceType;
|
||||
rule: string;
|
||||
@@ -203,6 +204,12 @@ export type PermissionMessageBatch<T> = {
|
||||
items: IdentifiedPermissionMessage<T>[];
|
||||
};
|
||||
|
||||
// @public
|
||||
export type PermissionRuleParam = undefined | JsonPrimitive | JsonPrimitive[];
|
||||
|
||||
// @public
|
||||
export type PermissionRuleParams = Record<string, PermissionRuleParam>;
|
||||
|
||||
// @public
|
||||
export type PolicyDecision =
|
||||
| DefinitivePolicyDecision
|
||||
|
||||
@@ -151,11 +151,15 @@ export type PermissionCriteria<TQuery> =
|
||||
|
||||
/**
|
||||
* A parameter to a permission rule.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export type PermissionRuleParam = undefined | JsonPrimitive | JsonPrimitive[];
|
||||
|
||||
/**
|
||||
* Types that can be used as parameters to permission rules.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export type PermissionRuleParams = Record<string, PermissionRuleParam>;
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ import { Permission } from '@backstage/plugin-permission-common';
|
||||
import { PermissionCondition } from '@backstage/plugin-permission-common';
|
||||
import { PermissionCriteria } from '@backstage/plugin-permission-common';
|
||||
import { PermissionEvaluator } from '@backstage/plugin-permission-common';
|
||||
import { PermissionRuleParams } from '@backstage/plugin-permission-common';
|
||||
import { PluginEndpointDiscovery } from '@backstage/backend-common';
|
||||
import { PolicyDecision } from '@backstage/plugin-permission-common';
|
||||
import { QueryPermissionRequest } from '@backstage/plugin-permission-common';
|
||||
@@ -54,7 +55,7 @@ export type Condition<TRule> = TRule extends PermissionRule<
|
||||
infer TResourceType,
|
||||
infer TParams
|
||||
>
|
||||
? (...params: TParams) => PermissionCondition<TResourceType, TParams>
|
||||
? (params: TParams) => PermissionCondition<TResourceType, TParams>
|
||||
: never;
|
||||
|
||||
// @public
|
||||
@@ -75,7 +76,7 @@ export const createConditionExports: <
|
||||
TResource,
|
||||
TRules extends Record<
|
||||
string,
|
||||
PermissionRule<TResource, any, TResourceType, unknown[]>
|
||||
PermissionRule<TResource, any, TResourceType, PermissionRuleParams>
|
||||
>,
|
||||
>(options: {
|
||||
pluginId: string;
|
||||
@@ -86,7 +87,7 @@ export const createConditionExports: <
|
||||
createConditionalDecision: (
|
||||
permission: ResourcePermission<TResourceType>,
|
||||
conditions: PermissionCriteria<
|
||||
PermissionCondition<TResourceType, unknown[]>
|
||||
PermissionCondition<TResourceType, PermissionRuleParams>
|
||||
>,
|
||||
) => ConditionalPolicyDecision;
|
||||
};
|
||||
@@ -94,15 +95,15 @@ export const createConditionExports: <
|
||||
// @public
|
||||
export const createConditionFactory: <
|
||||
TResourceType extends string,
|
||||
TParams extends any[],
|
||||
TParams extends PermissionRuleParams = PermissionRuleParams,
|
||||
>(
|
||||
rule: PermissionRule<unknown, unknown, TResourceType, TParams>,
|
||||
) => (...params: TParams) => PermissionCondition<TResourceType, TParams>;
|
||||
) => (params: TParams) => PermissionCondition<TResourceType, TParams>;
|
||||
|
||||
// @public
|
||||
export const createConditionTransformer: <
|
||||
TQuery,
|
||||
TRules extends PermissionRule<any, TQuery, string, unknown[]>[],
|
||||
TRules extends PermissionRule<any, TQuery, string, PermissionRuleParams>[],
|
||||
>(
|
||||
permissionRules: [...TRules],
|
||||
) => ConditionTransformer<TQuery>;
|
||||
@@ -114,7 +115,12 @@ export const createPermissionIntegrationRouter: <
|
||||
>(options: {
|
||||
resourceType: TResourceType;
|
||||
permissions?: Permission[] | undefined;
|
||||
rules: PermissionRule<TResource, any, NoInfer<TResourceType>, unknown[]>[];
|
||||
rules: PermissionRule<
|
||||
TResource,
|
||||
any,
|
||||
NoInfer<TResourceType>,
|
||||
PermissionRuleParams
|
||||
>[];
|
||||
getResources: (resourceRefs: string[]) => Promise<(TResource | undefined)[]>;
|
||||
}) => express.Router;
|
||||
|
||||
@@ -123,7 +129,7 @@ export const createPermissionRule: <
|
||||
TResource,
|
||||
TQuery,
|
||||
TResourceType extends string,
|
||||
TParams extends unknown[],
|
||||
TParams extends PermissionRuleParams = PermissionRuleParams,
|
||||
>(
|
||||
rule: PermissionRule<TResource, TQuery, TResourceType, TParams>,
|
||||
) => PermissionRule<TResource, TQuery, TResourceType, TParams>;
|
||||
@@ -148,7 +154,7 @@ export const makeCreatePermissionRule: <
|
||||
TResource,
|
||||
TQuery,
|
||||
TResourceType extends string,
|
||||
>() => <TParams extends unknown[]>(
|
||||
>() => <TParams extends PermissionRuleParams = PermissionRuleParams>(
|
||||
rule: PermissionRule<TResource, TQuery, TResourceType, TParams>,
|
||||
) => PermissionRule<TResource, TQuery, TResourceType, TParams>;
|
||||
|
||||
@@ -166,16 +172,28 @@ export type PermissionRule<
|
||||
TResource,
|
||||
TQuery,
|
||||
TResourceType extends string,
|
||||
TParams extends unknown[] = unknown[],
|
||||
TParams extends PermissionRuleParams = PermissionRuleParams,
|
||||
> = {
|
||||
name: string;
|
||||
description: string;
|
||||
resourceType: TResourceType;
|
||||
schema: z.ZodSchema<TParams>;
|
||||
apply(resource: TResource, ...params: TParams): boolean;
|
||||
toQuery(...params: TParams): PermissionCriteria<TQuery>;
|
||||
schema: PermissionRuleSchema<TParams>;
|
||||
apply(
|
||||
resource: TResource,
|
||||
params: NoInfer<z.input<PermissionRuleSchema<TParams>>>,
|
||||
): boolean;
|
||||
toQuery(
|
||||
params: NoInfer<z.input<PermissionRuleSchema<TParams>>>,
|
||||
): PermissionCriteria<TQuery>;
|
||||
};
|
||||
|
||||
// @public
|
||||
export type PermissionRuleSchema<TParams> = z.ZodObject<{
|
||||
[P in keyof TParams]-?: TParams[P] extends undefined
|
||||
? z.ZodOptionalType<z.ZodType<TParams[P]>>
|
||||
: z.ZodType<TParams[P]>;
|
||||
}>;
|
||||
|
||||
// @public
|
||||
export type PolicyQuery = {
|
||||
permission: Permission;
|
||||
|
||||
@@ -28,8 +28,9 @@ import {
|
||||
PermissionCondition,
|
||||
PermissionCriteria,
|
||||
} from '@backstage/plugin-permission-common';
|
||||
import { NoInfer, PermissionRule } from '../types';
|
||||
import { PermissionRule } from '../types';
|
||||
import {
|
||||
NoInfer,
|
||||
createGetRule,
|
||||
isAndCriteria,
|
||||
isNotCriteria,
|
||||
|
||||
@@ -22,6 +22,14 @@ import {
|
||||
} from '@backstage/plugin-permission-common';
|
||||
import { PermissionRule } from '../types';
|
||||
|
||||
/**
|
||||
* Prevent use of type parameter from contributing to type inference.
|
||||
*
|
||||
* https://github.com/Microsoft/TypeScript/issues/14829#issuecomment-980401795
|
||||
* @ignore
|
||||
*/
|
||||
export type NoInfer<T> = T extends infer S ? S : never;
|
||||
|
||||
/**
|
||||
* Utility function used to parse a PermissionCriteria
|
||||
* @param criteria - a PermissionCriteria
|
||||
|
||||
@@ -19,14 +19,23 @@ import type {
|
||||
PermissionRuleParams,
|
||||
} from '@backstage/plugin-permission-common';
|
||||
import { z } from 'zod';
|
||||
import { NoInfer } from './integration/util';
|
||||
|
||||
/**
|
||||
* Prevent use of type parameter from contributing to type inference.
|
||||
* A ZodSchema that reflects the structure of the parameters that are passed to
|
||||
* into a {@link PermissionRule}.
|
||||
*
|
||||
* https://github.com/Microsoft/TypeScript/issues/14829#issuecomment-980401795
|
||||
* @ignore
|
||||
* @public
|
||||
*/
|
||||
export type NoInfer<T> = T extends infer S ? S : never;
|
||||
export type PermissionRuleSchema<TParams> = z.ZodObject<{
|
||||
// Parameters can be optional, however we we want to make sure that the
|
||||
// parameters are always present in the schema, even if they are undefined.
|
||||
// We remove the optional flag from the schema, and then add it back in
|
||||
// with an optional zod type.
|
||||
[P in keyof TParams]-?: TParams[P] extends undefined
|
||||
? z.ZodOptionalType<z.ZodType<TParams[P]>>
|
||||
: z.ZodType<TParams[P]>;
|
||||
}>;
|
||||
|
||||
/**
|
||||
* A conditional rule that can be provided in an
|
||||
@@ -49,15 +58,6 @@ export type PermissionRule<
|
||||
TQuery,
|
||||
TResourceType extends string,
|
||||
TParams extends PermissionRuleParams = PermissionRuleParams,
|
||||
TSchema extends z.ZodType = z.ZodObject<{
|
||||
// Parameters can be optional, however we we want to make sure that the
|
||||
// parameters are always present in the schema, even if they are undefined.
|
||||
// We remove the optional flag from the schema, and then add it back in
|
||||
// with an optional zod type.
|
||||
[P in keyof TParams]-?: TParams[P] extends undefined
|
||||
? z.ZodOptionalType<z.ZodType<TParams[P]>>
|
||||
: z.ZodType<TParams[P]>;
|
||||
}>,
|
||||
> = {
|
||||
name: string;
|
||||
description: string;
|
||||
@@ -66,19 +66,24 @@ export type PermissionRule<
|
||||
/**
|
||||
* A ZodSchema that documents the parameters that this rule accepts.
|
||||
*/
|
||||
schema: TSchema;
|
||||
schema: PermissionRuleSchema<TParams>;
|
||||
|
||||
/**
|
||||
* Apply this rule to a resource already loaded from a backing data source. The params are
|
||||
* arguments supplied for the rule; for example, a rule could be `isOwner` with entityRefs as the
|
||||
* params.
|
||||
*/
|
||||
apply(resource: TResource, params: NoInfer<z.input<TSchema>>): boolean;
|
||||
apply(
|
||||
resource: TResource,
|
||||
params: NoInfer<z.input<PermissionRuleSchema<TParams>>>,
|
||||
): boolean;
|
||||
|
||||
/**
|
||||
* Translate this rule to criteria suitable for use in querying a backing data store. The criteria
|
||||
* can be used for loading a collection of resources efficiently with conditional criteria already
|
||||
* applied.
|
||||
*/
|
||||
toQuery(params: NoInfer<z.input<TSchema>>): PermissionCriteria<TQuery>;
|
||||
toQuery(
|
||||
params: NoInfer<z.input<PermissionRuleSchema<TParams>>>,
|
||||
): PermissionCriteria<TQuery>;
|
||||
};
|
||||
|
||||
@@ -15,6 +15,7 @@ import { PermissionCriteria } from '@backstage/plugin-permission-common';
|
||||
import { PermissionEvaluator } from '@backstage/plugin-permission-common';
|
||||
import { PermissionPolicy } from '@backstage/plugin-permission-node';
|
||||
import { PermissionRule } from '@backstage/plugin-permission-node';
|
||||
import { PermissionRuleParams } from '@backstage/plugin-permission-common';
|
||||
import { PlaylistMetadata } from '@backstage/plugin-playlist-common';
|
||||
import { PluginDatabaseManager } from '@backstage/backend-common';
|
||||
import { PluginEndpointDiscovery } from '@backstage/backend-common';
|
||||
@@ -26,7 +27,7 @@ import { ResourcePermission } from '@backstage/plugin-permission-common';
|
||||
export const createPlaylistConditionalDecision: (
|
||||
permission: ResourcePermission<'playlist-list'>,
|
||||
conditions: PermissionCriteria<
|
||||
PermissionCondition<'playlist-list', unknown[]>
|
||||
PermissionCondition<'playlist-list', PermissionRuleParams>
|
||||
>,
|
||||
) => ConditionalPolicyDecision;
|
||||
|
||||
@@ -70,13 +71,15 @@ export const playlistConditions: Conditions<{
|
||||
PlaylistMetadata,
|
||||
ListPlaylistsFilter,
|
||||
'playlist-list',
|
||||
[userOwnershipRefs: string[]]
|
||||
{
|
||||
owners: string[];
|
||||
}
|
||||
>;
|
||||
isPublic: PermissionRule<
|
||||
PlaylistMetadata,
|
||||
ListPlaylistsFilter,
|
||||
'playlist-list',
|
||||
[]
|
||||
PermissionRuleParams
|
||||
>;
|
||||
}>;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user