diff --git a/plugins/scaffolder-backend/api-report.md b/plugins/scaffolder-backend/api-report.md index f0eb714ab3..b4f7a6ee73 100644 --- a/plugins/scaffolder-backend/api-report.md +++ b/plugins/scaffolder-backend/api-report.md @@ -9,6 +9,8 @@ import { ActionContext as ActionContext_2 } from '@backstage/plugin-scaffolder-n import { CatalogApi } from '@backstage/catalog-client'; import { CatalogProcessor } from '@backstage/plugin-catalog-node'; import { CatalogProcessorEmit } from '@backstage/plugin-catalog-node'; +import { ConditionalPolicyDecision } from '@backstage/plugin-permission-common'; +import { Conditions } from '@backstage/plugin-permission-node'; import { Config } from '@backstage/config'; import { createPullRequest } from 'octokit-plugin-create-pull-request'; import { Duration } from 'luxon'; @@ -24,8 +26,14 @@ import { LocationSpec } from '@backstage/plugin-catalog-common'; import { Logger } from 'winston'; import { Observable } from '@backstage/types'; import { Octokit } from 'octokit'; +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 { PluginTaskScheduler } from '@backstage/backend-tasks'; +import { ResourcePermission } from '@backstage/plugin-permission-common'; import { Schema } from 'jsonschema'; import { ScmIntegrationRegistry } from '@backstage/integration'; import { ScmIntegrations } from '@backstage/integration'; @@ -35,6 +43,8 @@ import { TaskSpec } from '@backstage/plugin-scaffolder-common'; import { TaskSpecV1beta3 } from '@backstage/plugin-scaffolder-common'; import { TemplateAction as TemplateAction_2 } from '@backstage/plugin-scaffolder-node'; import { TemplateActionOptions } from '@backstage/plugin-scaffolder-node'; +import { TemplateEntityStepV1beta3 } from '@backstage/plugin-scaffolder-common'; +import { TemplateParameter } from '@backstage/plugin-scaffolder-common'; import { UrlReader } from '@backstage/backend-common'; import { Writable } from 'stream'; import { ZodType } from 'zod'; @@ -518,6 +528,14 @@ export const createPublishGitlabMergeRequestAction: (options: { // @public export function createRouter(options: RouterOptions): Promise; +// @alpha +export const createScaffolderConditionalDecision: ( + permission: ResourcePermission<'scaffolder-template'>, + conditions: PermissionCriteria< + PermissionCondition<'scaffolder-template', PermissionRuleParams> + >, +) => ConditionalPolicyDecision; + // @public @deprecated (undocumented) export const createTemplateAction: < TParams, @@ -656,6 +674,8 @@ export interface RouterOptions { // (undocumented) logger: Logger; // (undocumented) + permissionApi: PermissionEvaluator; + // (undocumented) reader: UrlReader; // (undocumented) scheduler?: PluginTaskScheduler; @@ -673,6 +693,18 @@ export type RunCommandOptions = { logStream?: Writable; }; +// @alpha +export const scaffolderConditions: Conditions<{ + hasTag: PermissionRule< + TemplateParameter | TemplateEntityStepV1beta3, + {}, + 'scaffolder-template', + { + tag: string; + } + >; +}>; + // @public (undocumented) export class ScaffolderEntitiesProcessor implements CatalogProcessor { // (undocumented) diff --git a/plugins/scaffolder-backend/src/service/conditionExports.ts b/plugins/scaffolder-backend/src/service/conditionExports.ts index 70285c8f5f..240cbaf858 100644 --- a/plugins/scaffolder-backend/src/service/conditionExports.ts +++ b/plugins/scaffolder-backend/src/service/conditionExports.ts @@ -18,13 +18,50 @@ import { RESOURCE_TYPE_SCAFFOLDER_TEMPLATE } from '@backstage/plugin-scaffolder- import { createConditionExports } from '@backstage/plugin-permission-node'; import { scaffolderStepRules } from './rules'; -const { - conditions: scaffolderConditions, - createConditionalDecision: createScaffolderConditionalDecision, -} = createConditionExports({ +const { conditions, createConditionalDecision } = createConditionExports({ pluginId: 'scaffolder', resourceType: RESOURCE_TYPE_SCAFFOLDER_TEMPLATE, rules: scaffolderStepRules, }); -export { scaffolderConditions, createScaffolderConditionalDecision }; +/** + * These conditions are used when creating conditional decisions for scaffolder + * templates that are returned by authorization policies. + * + * @alpha + */ +export const scaffolderConditions = conditions; + +/** + * `createScaffolderConditionalDecision` can be used when authoring policies to + * create conditional decisions. It requires a permission of type + * `ResourcePermission<'scaffolder-template'>` to be passed as the first parameter. + * It's recommended that you use the provided `isResourcePermission` and + * `isPermission` helper methods to narrow the type of the permission passed to + * the handle method as shown below. + * + * ``` + * // MyAuthorizationPolicy.ts + * ... + * import { createScaffolderPolicyDecision } from '@backstage/plugin-scaffolder-backend'; + * import { RESOURCE_TYPE_SCAFFOLDER_TEMPLATE } from '@backstage/plugin-scaffolder-common'; + * + * class MyAuthorizationPolicy implements PermissionPolicy { + * async handle(request, user) { + * ... + * + * if (isResourcePermission(request.permission, RESOURCE_TYPE_SCAFFOLDER_TEMPLATE)) { + * return createScaffolderConditionalDecision( + * request.permission, + * { anyOf: [...insert conditions here...] } + * ); + * } + * + * ... + * } + * + * ``` + * + * @alpha + */ +export const createScaffolderConditionalDecision = createConditionalDecision;