diff --git a/.changeset/big-days-press.md b/.changeset/big-days-press.md new file mode 100644 index 0000000000..7dec7d6288 --- /dev/null +++ b/.changeset/big-days-press.md @@ -0,0 +1,7 @@ +--- +'@backstage/plugin-scaffolder-backend': minor +--- + +Expose both types of scaffolder permissions and rules through the metadata endpoint. + +The metadata endpoint now correctly exposes both types of scaffolder permissions and rules (for both the template and action resource types) through the metadata endpoint. diff --git a/.changeset/spicy-spies-warn.md b/.changeset/spicy-spies-warn.md new file mode 100644 index 0000000000..3ed26a2cc3 --- /dev/null +++ b/.changeset/spicy-spies-warn.md @@ -0,0 +1,7 @@ +--- +'@backstage/plugin-scaffolder-common': minor +--- + +Expose scaffolder permissions in new sub-aggregations. + +In addition to exporting a list of all scaffolder permissions in `scaffolderPermissions`, scaffolder-common now exports `scaffolderTemplatePermissions` and `scaffolderActionPermissions`, which contain subsets of the scaffolder permissions separated by resource type. diff --git a/plugins/scaffolder-backend/api-report.md b/plugins/scaffolder-backend/api-report.md index a6fd41a29e..c87521151b 100644 --- a/plugins/scaffolder-backend/api-report.md +++ b/plugins/scaffolder-backend/api-report.md @@ -29,6 +29,7 @@ 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 { RESOURCE_TYPE_SCAFFOLDER_ACTION } from '@backstage/plugin-scaffolder-common/alpha'; import { RESOURCE_TYPE_SCAFFOLDER_TEMPLATE } from '@backstage/plugin-scaffolder-common/alpha'; import { Schema } from 'jsonschema'; import { ScmIntegrationRegistry } from '@backstage/integration'; @@ -49,6 +50,16 @@ import { ZodTypeDef } from 'zod'; // @public @deprecated (undocumented) export type ActionContext = ActionContext_2; +// @public (undocumented) +export type ActionPermissionRuleInput< + TParams extends PermissionRuleParams = PermissionRuleParams, +> = PermissionRule< + TemplateEntityStepV1beta3 | TemplateParametersV1beta3, + {}, + typeof RESOURCE_TYPE_SCAFFOLDER_ACTION, + TParams +>; + // @public export const createBuiltinActions: ( options: CreateBuiltInActionsOptions, @@ -763,7 +774,9 @@ export interface RouterOptions { // (undocumented) logger: Logger; // (undocumented) - permissionRules?: TemplatePermissionRuleInput[]; + permissionRules?: Array< + TemplatePermissionRuleInput | ActionPermissionRuleInput + >; // (undocumented) permissions?: PermissionEvaluator; // (undocumented) diff --git a/plugins/scaffolder-backend/src/service/router.ts b/plugins/scaffolder-backend/src/service/router.ts index deff4392d6..1771067367 100644 --- a/plugins/scaffolder-backend/src/service/router.ts +++ b/plugins/scaffolder-backend/src/service/router.ts @@ -36,8 +36,10 @@ import { TemplateEntityStepV1beta3, } from '@backstage/plugin-scaffolder-common'; import { + RESOURCE_TYPE_SCAFFOLDER_ACTION, RESOURCE_TYPE_SCAFFOLDER_TEMPLATE, - scaffolderPermissions, + scaffolderActionPermissions, + scaffolderTemplatePermissions, templateParameterReadPermission, templateStepReadPermission, } from '@backstage/plugin-scaffolder-common/alpha'; @@ -71,7 +73,7 @@ import { createPermissionIntegrationRouter, PermissionRule, } from '@backstage/plugin-permission-node'; -import { scaffolderTemplateRules } from './rules'; +import { scaffolderActionRules, scaffolderTemplateRules } from './rules'; /** * @@ -85,6 +87,29 @@ export type TemplatePermissionRuleInput< typeof RESOURCE_TYPE_SCAFFOLDER_TEMPLATE, TParams >; +function isTemplatePermissionRuleInput( + permissionRule: TemplatePermissionRuleInput | ActionPermissionRuleInput, +): permissionRule is TemplatePermissionRuleInput { + return permissionRule.resourceType === RESOURCE_TYPE_SCAFFOLDER_TEMPLATE; +} + +/** + * + * @public + */ +export type ActionPermissionRuleInput< + TParams extends PermissionRuleParams = PermissionRuleParams, +> = PermissionRule< + TemplateEntityStepV1beta3 | TemplateParametersV1beta3, + {}, + typeof RESOURCE_TYPE_SCAFFOLDER_ACTION, + TParams +>; +function isActionPermissionRuleInput( + permissionRule: TemplatePermissionRuleInput | ActionPermissionRuleInput, +): permissionRule is ActionPermissionRuleInput { + return permissionRule.resourceType === RESOURCE_TYPE_SCAFFOLDER_ACTION; +} /** * RouterOptions @@ -113,7 +138,9 @@ export interface RouterOptions { additionalTemplateFilters?: Record; additionalTemplateGlobals?: Record; permissions?: PermissionEvaluator; - permissionRules?: TemplatePermissionRuleInput[]; + permissionRules?: Array< + TemplatePermissionRuleInput | ActionPermissionRuleInput + >; identity?: IdentityApi; } @@ -290,17 +317,32 @@ export async function createRouter( const templateRules: TemplatePermissionRuleInput[] = Object.values( scaffolderTemplateRules, ); + const actionRules: ActionPermissionRuleInput[] = Object.values( + scaffolderActionRules, + ); if (permissionRules) { - templateRules.push(...permissionRules); + templateRules.push( + ...permissionRules.filter(isTemplatePermissionRuleInput), + ); + actionRules.push(...permissionRules.filter(isActionPermissionRuleInput)); } const isAuthorized = createConditionAuthorizer(Object.values(templateRules)); const permissionIntegrationRouter = createPermissionIntegrationRouter({ - resourceType: RESOURCE_TYPE_SCAFFOLDER_TEMPLATE, - permissions: scaffolderPermissions, - rules: templateRules, + resources: [ + { + resourceType: RESOURCE_TYPE_SCAFFOLDER_TEMPLATE, + permissions: scaffolderTemplatePermissions, + rules: templateRules, + }, + { + resourceType: RESOURCE_TYPE_SCAFFOLDER_ACTION, + permissions: scaffolderActionPermissions, + rules: actionRules, + }, + ], }); router.use(permissionIntegrationRouter); diff --git a/plugins/scaffolder-common/alpha-api-report.md b/plugins/scaffolder-common/alpha-api-report.md index d6e746026a..de9dffd1b9 100644 --- a/plugins/scaffolder-common/alpha-api-report.md +++ b/plugins/scaffolder-common/alpha-api-report.md @@ -14,12 +14,18 @@ export const RESOURCE_TYPE_SCAFFOLDER_ACTION = 'scaffolder-action'; // @alpha export const RESOURCE_TYPE_SCAFFOLDER_TEMPLATE = 'scaffolder-template'; +// @alpha +export const scaffolderActionPermissions: ResourcePermission<'scaffolder-action'>[]; + // @alpha export const scaffolderPermissions: ( | ResourcePermission<'scaffolder-action'> | ResourcePermission<'scaffolder-template'> )[]; +// @alpha +export const scaffolderTemplatePermissions: ResourcePermission<'scaffolder-template'>[]; + // @alpha export const templateParameterReadPermission: ResourcePermission<'scaffolder-template'>; diff --git a/plugins/scaffolder-common/src/permissions.ts b/plugins/scaffolder-common/src/permissions.ts index f06d7984f2..5c4c367889 100644 --- a/plugins/scaffolder-common/src/permissions.ts +++ b/plugins/scaffolder-common/src/permissions.ts @@ -87,3 +87,18 @@ export const scaffolderPermissions = [ templateParameterReadPermission, templateStepReadPermission, ]; + +/** + * List of the scaffolder permissions that are associated with template steps and parameters. + * @alpha + */ +export const scaffolderTemplatePermissions = [ + templateParameterReadPermission, + templateStepReadPermission, +]; + +/** + * List of the scaffolder permissions that are associated with scaffolder actions. + * @alpha + */ +export const scaffolderActionPermissions = [actionExecutePermission];