@backstage/plugin-permission-common 0.0.0-nightly-20220324023116 → 0.0.0-nightly-20220327022954

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,6 +1,19 @@
1
1
  # @backstage/plugin-permission-common
2
2
 
3
- ## 0.0.0-nightly-20220324023116
3
+ ## 0.0.0-nightly-20220327022954
4
+
5
+ ### Minor Changes
6
+
7
+ - c98d271466: Refactor api types into more specific, decoupled names.
8
+
9
+ - **BREAKING:**
10
+ - Renamed `AuthorizeDecision` to `EvaluatePermissionResponse`
11
+ - Renamed `AuthorizeQuery` to `EvaluatePermissionRequest`
12
+ - Renamed `AuthorizeRequest` to `EvaluatePermissionRequestBatch`
13
+ - Renamed `AuthorizeResponse` to `EvaluatePermissionResponseBatch`
14
+ - Renamed `Identified` to `IdentifiedPermissionMessage`
15
+ - Add `PermissionMessageBatch` helper type
16
+ - Add `ConditionalPolicyDecision`, `DefinitivePolicyDecision`, and `PolicyDecision` types from `@backstage/plugin-permission-node`
4
17
 
5
18
  ### Patch Changes
6
19
 
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs.js","sources":["../src/types/api.ts","../src/permissions/util.ts","../src/permissions/createPermission.ts","../src/PermissionClient.ts"],"sourcesContent":["/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Permission } from './permission';\n\n/**\n * A request with a UUID identifier, so that batched responses can be matched up with the original\n * requests.\n * @public\n */\nexport type Identified<T> = T & { id: string };\n\n/**\n * The result of an authorization request.\n * @public\n */\nexport enum AuthorizeResult {\n /**\n * The authorization request is denied.\n */\n DENY = 'DENY',\n /**\n * The authorization request is allowed.\n */\n ALLOW = 'ALLOW',\n /**\n * The authorization request is allowed if the provided conditions are met.\n */\n CONDITIONAL = 'CONDITIONAL',\n}\n\n/**\n * An individual authorization request for {@link PermissionClient#authorize}.\n * @public\n */\nexport type AuthorizeQuery = {\n permission: Permission;\n resourceRef?: string;\n};\n\n/**\n * A batch of authorization requests from {@link PermissionClient#authorize}.\n * @public\n */\nexport type AuthorizeRequest = {\n items: Identified<AuthorizeQuery>[];\n};\n\n/**\n * A condition returned with a CONDITIONAL authorization response.\n *\n * Conditions are a reference to a rule defined by a plugin, and parameters to apply the rule. For\n * example, a rule might be `isOwner` from the catalog-backend, and params may be a list of entity\n * claims from a identity token.\n * @public\n */\nexport type PermissionCondition<TParams extends unknown[] = unknown[]> = {\n rule: string;\n params: TParams;\n};\n\n/**\n * Utility type to represent an array with 1 or more elements.\n * @ignore\n */\ntype NonEmptyArray<T> = [T, ...T[]];\n\n/**\n * Represents a logical AND for the provided criteria.\n * @public\n */\nexport type AllOfCriteria<TQuery> = {\n allOf: NonEmptyArray<PermissionCriteria<TQuery>>;\n};\n\n/**\n * Represents a logical OR for the provided criteria.\n * @public\n */\nexport type AnyOfCriteria<TQuery> = {\n anyOf: NonEmptyArray<PermissionCriteria<TQuery>>;\n};\n\n/**\n * Represents a negation of the provided criteria.\n * @public\n */\nexport type NotCriteria<TQuery> = {\n not: PermissionCriteria<TQuery>;\n};\n\n/**\n * Composes several {@link PermissionCondition}s as criteria with a nested AND/OR structure.\n * @public\n */\nexport type PermissionCriteria<TQuery> =\n | AllOfCriteria<TQuery>\n | AnyOfCriteria<TQuery>\n | NotCriteria<TQuery>\n | TQuery;\n\n/**\n * An individual authorization response from {@link PermissionClient#authorize}.\n * @public\n */\nexport type AuthorizeDecision =\n | { result: AuthorizeResult.ALLOW | AuthorizeResult.DENY }\n | {\n result: AuthorizeResult.CONDITIONAL;\n conditions: PermissionCriteria<PermissionCondition>;\n };\n\n/**\n * A batch of authorization responses from {@link PermissionClient#authorize}.\n * @public\n */\nexport type AuthorizeResponse = {\n items: Identified<AuthorizeDecision>[];\n};\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Permission, ResourcePermission } from '../types';\n\n/**\n * Check if a given permission is a {@link ResourcePermission}. When\n * `resourceType` is supplied as the second parameter, also checks if\n * the permission has the specified resource type.\n * @public\n */\nexport function isResourcePermission<T extends string = string>(\n permission: Permission,\n resourceType?: T,\n): permission is ResourcePermission<T> {\n if (!('resourceType' in permission)) {\n return false;\n }\n\n return !resourceType || permission.resourceType === resourceType;\n}\n\n/**\n * Check if a given permission is related to a create action.\n * @public\n */\nexport function isCreatePermission(permission: Permission) {\n return permission.attributes.action === 'create';\n}\n\n/**\n * Check if a given permission is related to a read action.\n * @public\n */\nexport function isReadPermission(permission: Permission) {\n return permission.attributes.action === 'read';\n}\n\n/**\n * Check if a given permission is related to an update action.\n * @public\n */\nexport function isUpdatePermission(permission: Permission) {\n return permission.attributes.action === 'update';\n}\n\n/**\n * Check if a given permission is related to a delete action.\n * @public\n */\nexport function isDeletePermission(permission: Permission) {\n return permission.attributes.action === 'delete';\n}\n","/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n BasicPermission,\n Permission,\n PermissionAttributes,\n ResourcePermission,\n} from '../types';\n\n/**\n * Utility function for creating a valid {@link ResourcePermission}, inferring\n * the appropriate type and resource type parameter.\n *\n * @public\n */\nexport function createPermission<TResourceType extends string>(input: {\n name: string;\n attributes: PermissionAttributes;\n resourceType: TResourceType;\n}): ResourcePermission<TResourceType>;\n/**\n * Utility function for creating a valid {@link BasicPermission}.\n *\n * @public\n */\nexport function createPermission(input: {\n name: string;\n attributes: PermissionAttributes;\n}): BasicPermission;\nexport function createPermission({\n name,\n attributes,\n resourceType,\n}: {\n name: string;\n attributes: PermissionAttributes;\n resourceType?: string;\n}): Permission {\n if (resourceType) {\n return {\n type: 'resource',\n name,\n attributes,\n resourceType,\n };\n }\n\n return {\n type: 'basic',\n name,\n attributes,\n };\n}\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Config } from '@backstage/config';\nimport { ResponseError } from '@backstage/errors';\nimport fetch from 'cross-fetch';\nimport * as uuid from 'uuid';\nimport { z } from 'zod';\nimport {\n AuthorizeResult,\n AuthorizeQuery,\n AuthorizeDecision,\n Identified,\n PermissionCriteria,\n PermissionCondition,\n AuthorizeResponse,\n AuthorizeRequest,\n} from './types/api';\nimport { DiscoveryApi } from './types/discovery';\nimport {\n PermissionAuthorizer,\n AuthorizeRequestOptions,\n} from './types/permission';\n\nconst permissionCriteriaSchema: z.ZodSchema<\n PermissionCriteria<PermissionCondition>\n> = z.lazy(() =>\n z\n .object({\n rule: z.string(),\n params: z.array(z.unknown()),\n })\n .strict()\n .or(\n z\n .object({ anyOf: z.array(permissionCriteriaSchema).nonempty() })\n .strict(),\n )\n .or(\n z\n .object({ allOf: z.array(permissionCriteriaSchema).nonempty() })\n .strict(),\n )\n .or(z.object({ not: permissionCriteriaSchema }).strict()),\n);\n\nconst responseSchema = z.object({\n items: z.array(\n z\n .object({\n id: z.string(),\n result: z\n .literal(AuthorizeResult.ALLOW)\n .or(z.literal(AuthorizeResult.DENY)),\n })\n .or(\n z.object({\n id: z.string(),\n result: z.literal(AuthorizeResult.CONDITIONAL),\n conditions: permissionCriteriaSchema,\n }),\n ),\n ),\n});\n\n/**\n * An isomorphic client for requesting authorization for Backstage permissions.\n * @public\n */\nexport class PermissionClient implements PermissionAuthorizer {\n private readonly enabled: boolean;\n private readonly discovery: DiscoveryApi;\n\n constructor(options: { discovery: DiscoveryApi; config: Config }) {\n this.discovery = options.discovery;\n this.enabled =\n options.config.getOptionalBoolean('permission.enabled') ?? false;\n }\n\n /**\n * Request authorization from the permission-backend for the given set of permissions.\n *\n * Authorization requests check that a given Backstage user can perform a protected operation,\n * potentially for a specific resource (such as a catalog entity). The Backstage identity token\n * should be included in the `options` if available.\n *\n * Permissions can be imported from plugins exposing them, such as `catalogEntityReadPermission`.\n *\n * The response will be either ALLOW or DENY when either the permission has no resourceType, or a\n * resourceRef is provided in the request. For permissions with a resourceType, CONDITIONAL may be\n * returned if no resourceRef is provided in the request. Conditional responses are intended only\n * for backends which have access to the data source for permissioned resources, so that filters\n * can be applied when loading collections of resources.\n * @public\n */\n async authorize(\n queries: AuthorizeQuery[],\n options?: AuthorizeRequestOptions,\n ): Promise<AuthorizeDecision[]> {\n // TODO(permissions): it would be great to provide some kind of typing guarantee that\n // conditional responses will only ever be returned for requests containing a resourceType\n // but no resourceRef. That way clients who aren't prepared to handle filtering according\n // to conditions can be guaranteed that they won't unexpectedly get a CONDITIONAL response.\n\n if (!this.enabled) {\n return queries.map(_ => ({ result: AuthorizeResult.ALLOW }));\n }\n\n const request: AuthorizeRequest = {\n items: queries.map(query => ({\n id: uuid.v4(),\n ...query,\n })),\n };\n\n const permissionApi = await this.discovery.getBaseUrl('permission');\n const response = await fetch(`${permissionApi}/authorize`, {\n method: 'POST',\n body: JSON.stringify(request),\n headers: {\n ...this.getAuthorizationHeader(options?.token),\n 'content-type': 'application/json',\n },\n });\n if (!response.ok) {\n throw await ResponseError.fromResponse(response);\n }\n\n const responseBody = await response.json();\n this.assertValidResponse(request, responseBody);\n\n const responsesById = responseBody.items.reduce((acc, r) => {\n acc[r.id] = r;\n return acc;\n }, {} as Record<string, Identified<AuthorizeDecision>>);\n\n return request.items.map(query => responsesById[query.id]);\n }\n\n private getAuthorizationHeader(token?: string): Record<string, string> {\n return token ? { Authorization: `Bearer ${token}` } : {};\n }\n\n private assertValidResponse(\n request: AuthorizeRequest,\n json: any,\n ): asserts json is AuthorizeResponse {\n const authorizedResponses = responseSchema.parse(json);\n const responseIds = authorizedResponses.items.map(r => r.id);\n const hasAllRequestIds = request.items.every(r =>\n responseIds.includes(r.id),\n );\n if (!hasAllRequestIds) {\n throw new Error(\n 'Unexpected authorization response from permission-backend',\n );\n }\n }\n}\n"],"names":["z","uuid","fetch","ResponseError"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6BY,IAAA,eAAA,qBAAA,gBAAL,KAAA;AAIL,EAAO,gBAAA,CAAA,MAAA,CAAA,GAAA,MAAA,CAAA;AAIP,EAAQ,gBAAA,CAAA,OAAA,CAAA,GAAA,OAAA,CAAA;AAIR,EAAc,gBAAA,CAAA,aAAA,CAAA,GAAA,aAAA,CAAA;AAZJ,EAAA,OAAA,gBAAA,CAAA;AAAA,CAAA,EAAA,eAAA,IAAA,EAAA;;ACLL,SAAA,oBAAA,CACL,YACA,YACqC,EAAA;AACrC,EAAI,IAAA,oBAAoB,UAAa,CAAA,EAAA;AACnC,IAAO,OAAA,KAAA,CAAA;AAAA,GACT;AAEA,EAAO,OAAA,CAAC,YAAgB,IAAA,UAAA,CAAW,YAAiB,KAAA,YAAA,CAAA;AACtD,CAAA;AAMO,SAAA,kBAAA,CAA4B,UAAwB,EAAA;AACzD,EAAO,OAAA,UAAA,CAAW,WAAW,MAAW,KAAA,QAAA,CAAA;AAC1C,CAAA;AAMO,SAAA,gBAAA,CAA0B,UAAwB,EAAA;AACvD,EAAO,OAAA,UAAA,CAAW,WAAW,MAAW,KAAA,MAAA,CAAA;AAC1C,CAAA;AAMO,SAAA,kBAAA,CAA4B,UAAwB,EAAA;AACzD,EAAO,OAAA,UAAA,CAAW,WAAW,MAAW,KAAA,QAAA,CAAA;AAC1C,CAAA;AAMO,SAAA,kBAAA,CAA4B,UAAwB,EAAA;AACzD,EAAO,OAAA,UAAA,CAAW,WAAW,MAAW,KAAA,QAAA,CAAA;AAC1C;;ACtBiC,SAAA,gBAAA,CAAA;AAAA,EAC/B,IAAA;AAAA,EACA,UAAA;AAAA,EACA,YAAA;AAAA,CAKa,EAAA;AACb,EAAA,IAAI,YAAc,EAAA;AAChB,IAAO,OAAA;AAAA,MACL,IAAM,EAAA,UAAA;AAAA,MACN,IAAA;AAAA,MACA,UAAA;AAAA,MACA,YAAA;AAAA,KACF,CAAA;AAAA,GACF;AAEA,EAAO,OAAA;AAAA,IACL,IAAM,EAAA,OAAA;AAAA,IACN,IAAA;AAAA,IACA,UAAA;AAAA,GACF,CAAA;AACF;;AC7BA,MAAM,wBAEF,GAAAA,KAAA,CAAE,IAAK,CAAA,MACTA,MACG,MAAO,CAAA;AAAA,EACN,IAAA,EAAMA,MAAE,MAAO,EAAA;AAAA,EACf,MAAQ,EAAAA,KAAA,CAAE,KAAM,CAAAA,KAAA,CAAE,SAAS,CAAA;AAC7B,CAAC,CAAA,CACA,QACA,CAAA,EAAA,CACCA,MACG,MAAO,CAAA,EAAE,OAAOA,KAAE,CAAA,KAAA,CAAM,wBAAwB,CAAE,CAAA,QAAA,IAAY,CAAA,CAC9D,QACL,CAAA,CACC,GACCA,KACG,CAAA,MAAA,CAAO,EAAE,KAAO,EAAAA,KAAA,CAAE,MAAM,wBAAwB,CAAA,CAAE,UAAW,EAAC,EAC9D,MAAO,EACZ,EACC,EAAG,CAAAA,KAAA,CAAE,OAAO,EAAE,GAAA,EAAK,0BAA0B,CAAA,CAAE,MAAO,EAAC,CAC5D,CAAA,CAAA;AAEA,MAAM,cAAA,GAAiBA,MAAE,MAAO,CAAA;AAAA,EAC9B,KAAO,EAAAA,KAAA,CAAE,KACP,CAAAA,KAAA,CACG,MAAO,CAAA;AAAA,IACN,EAAA,EAAIA,MAAE,MAAO,EAAA;AAAA,IACb,MAAA,EAAQA,KACL,CAAA,OAAA,CAAQ,eAAgB,CAAA,KAAK,CAC7B,CAAA,EAAA,CAAGA,KAAE,CAAA,OAAA,CAAQ,eAAgB,CAAA,IAAI,CAAC,CAAA;AAAA,GACtC,CAAA,CACA,EACC,CAAAA,KAAA,CAAE,MAAO,CAAA;AAAA,IACP,EAAA,EAAIA,MAAE,MAAO,EAAA;AAAA,IACb,MAAQ,EAAAA,KAAA,CAAE,OAAQ,CAAA,eAAA,CAAgB,WAAW,CAAA;AAAA,IAC7C,UAAY,EAAA,wBAAA;AAAA,GACb,CACH,CACJ,CAAA;AACF,CAAC,CAAA,CAAA;AAMM,MAAM,gBAAiD,CAAA;AAAA,EAI5D,YAAY,OAAsD,EAAA;AAtFpE,IAAA,IAAA,EAAA,CAAA;AAuFI,IAAA,IAAA,CAAK,YAAY,OAAQ,CAAA,SAAA,CAAA;AACzB,IAAA,IAAA,CAAK,UACH,CAAQ,EAAA,GAAA,OAAA,CAAA,MAAA,CAAO,kBAAmB,CAAA,oBAAoB,MAAtD,IAA2D,GAAA,EAAA,GAAA,KAAA,CAAA;AAAA,GAC/D;AAAA,EAkBM,MAAA,SAAA,CACJ,SACA,OAC8B,EAAA;AAM9B,IAAI,IAAA,CAAC,KAAK,OAAS,EAAA;AACjB,MAAA,OAAO,QAAQ,GAAI,CAAA,CAAA,CAAA,QAAQ,MAAQ,EAAA,eAAA,CAAgB,OAAQ,CAAA,CAAA,CAAA;AAAA,KAC7D;AAEA,IAAA,MAAM,OAA4B,GAAA;AAAA,MAChC,KAAA,EAAO,OAAQ,CAAA,GAAA,CAAI,CAAU,KAAA,MAAA;AAAA,QAC3B,EAAA,EAAIC,gBAAK,EAAG,EAAA;AAAA,QACT,GAAA,KAAA;AAAA,OACH,CAAA,CAAA;AAAA,KACJ,CAAA;AAEA,IAAA,MAAM,aAAgB,GAAA,MAAM,IAAK,CAAA,SAAA,CAAU,WAAW,YAAY,CAAA,CAAA;AAClE,IAAA,MAAM,QAAW,GAAA,MAAMC,yBAAM,CAAA,CAAA,EAAG,aAA2B,CAAA,UAAA,CAAA,EAAA;AAAA,MACzD,MAAQ,EAAA,MAAA;AAAA,MACR,IAAA,EAAM,IAAK,CAAA,SAAA,CAAU,OAAO,CAAA;AAAA,MAC5B,OAAS,EAAA;AAAA,QACJ,GAAA,IAAA,CAAK,sBAAuB,CAAA,OAAA,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,OAAA,CAAS,KAAK,CAAA;AAAA,QAC7C,cAAgB,EAAA,kBAAA;AAAA,OAClB;AAAA,KACD,CAAA,CAAA;AACD,IAAI,IAAA,CAAC,SAAS,EAAI,EAAA;AAChB,MAAM,MAAA,MAAMC,oBAAc,CAAA,YAAA,CAAa,QAAQ,CAAA,CAAA;AAAA,KACjD;AAEA,IAAM,MAAA,YAAA,GAAe,MAAM,QAAA,CAAS,IAAK,EAAA,CAAA;AACzC,IAAK,IAAA,CAAA,mBAAA,CAAoB,SAAS,YAAY,CAAA,CAAA;AAE9C,IAAA,MAAM,gBAAgB,YAAa,CAAA,KAAA,CAAM,MAAO,CAAA,CAAC,KAAK,CAAM,KAAA;AAC1D,MAAA,GAAA,CAAI,EAAE,EAAM,CAAA,GAAA,CAAA,CAAA;AACZ,MAAO,OAAA,GAAA,CAAA;AAAA,KACT,EAAG,EAAmD,CAAA,CAAA;AAEtD,IAAA,OAAO,QAAQ,KAAM,CAAA,GAAA,CAAI,CAAS,KAAA,KAAA,aAAA,CAAc,MAAM,EAAG,CAAA,CAAA,CAAA;AAAA,GAC3D;AAAA,EAEQ,uBAAuB,KAAwC,EAAA;AACrE,IAAA,OAAO,QAAQ,EAAE,aAAA,EAAe,CAAU,OAAA,EAAA,KAAA,CAAA,CAAA,KAAY,EAAC,CAAA;AAAA,GACzD;AAAA,EAEQ,mBAAA,CACN,SACA,IACmC,EAAA;AACnC,IAAM,MAAA,mBAAA,GAAsB,cAAe,CAAA,KAAA,CAAM,IAAI,CAAA,CAAA;AACrD,IAAA,MAAM,cAAc,mBAAoB,CAAA,KAAA,CAAM,GAAI,CAAA,CAAA,CAAA,KAAK,EAAE,EAAE,CAAA,CAAA;AAC3D,IAAM,MAAA,gBAAA,GAAmB,QAAQ,KAAM,CAAA,KAAA,CAAM,OAC3C,WAAY,CAAA,QAAA,CAAS,CAAE,CAAA,EAAE,CAC3B,CAAA,CAAA;AACA,IAAA,IAAI,CAAC,gBAAkB,EAAA;AACrB,MAAM,MAAA,IAAI,MACR,2DACF,CAAA,CAAA;AAAA,KACF;AAAA,GACF;AACF;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.cjs.js","sources":["../src/types/api.ts","../src/permissions/util.ts","../src/permissions/createPermission.ts","../src/PermissionClient.ts"],"sourcesContent":["/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Permission } from './permission';\n\n/**\n * A request with a UUID identifier, so that batched responses can be matched up with the original\n * requests.\n * @public\n */\nexport type IdentifiedPermissionMessage<T> = T & { id: string };\n\n/**\n * A batch of request or response items.\n * @public\n */\nexport type PermissionMessageBatch<T> = {\n items: IdentifiedPermissionMessage<T>[];\n};\n\n/**\n * The result of an authorization request.\n * @public\n */\nexport enum AuthorizeResult {\n /**\n * The authorization request is denied.\n */\n DENY = 'DENY',\n /**\n * The authorization request is allowed.\n */\n ALLOW = 'ALLOW',\n /**\n * The authorization request is allowed if the provided conditions are met.\n */\n CONDITIONAL = 'CONDITIONAL',\n}\n\n/**\n * A definitive decision returned by the {@link @backstage/plugin-permission-node#PermissionPolicy}.\n *\n * @remarks\n *\n * This indicates that the policy unconditionally allows (or denies) the request.\n *\n * @public\n */\nexport type DefinitivePolicyDecision = {\n result: AuthorizeResult.ALLOW | AuthorizeResult.DENY;\n};\n\n/**\n * A conditional decision returned by the {@link @backstage/plugin-permission-node#PermissionPolicy}.\n *\n * @remarks\n *\n * This indicates that the policy allows authorization for the request, given that the returned\n * conditions hold when evaluated. The conditions will be evaluated by the corresponding plugin\n * which knows about the referenced permission rules.\n *\n * @public\n */\nexport type ConditionalPolicyDecision = {\n result: AuthorizeResult.CONDITIONAL;\n pluginId: string;\n resourceType: string;\n conditions: PermissionCriteria<PermissionCondition>;\n};\n\n/**\n * A decision returned by the {@link @backstage/plugin-permission-node#PermissionPolicy}.\n *\n * @public\n */\nexport type PolicyDecision =\n | DefinitivePolicyDecision\n | ConditionalPolicyDecision;\n\n/**\n * A condition returned with a CONDITIONAL authorization response.\n *\n * Conditions are a reference to a rule defined by a plugin, and parameters to apply the rule. For\n * example, a rule might be `isOwner` from the catalog-backend, and params may be a list of entity\n * claims from a identity token.\n * @public\n */\nexport type PermissionCondition<TParams extends unknown[] = unknown[]> = {\n rule: string;\n params: TParams;\n};\n\n/**\n * Utility type to represent an array with 1 or more elements.\n * @ignore\n */\ntype NonEmptyArray<T> = [T, ...T[]];\n\n/**\n * Represents a logical AND for the provided criteria.\n * @public\n */\nexport type AllOfCriteria<TQuery> = {\n allOf: NonEmptyArray<PermissionCriteria<TQuery>>;\n};\n\n/**\n * Represents a logical OR for the provided criteria.\n * @public\n */\nexport type AnyOfCriteria<TQuery> = {\n anyOf: NonEmptyArray<PermissionCriteria<TQuery>>;\n};\n\n/**\n * Represents a negation of the provided criteria.\n * @public\n */\nexport type NotCriteria<TQuery> = {\n not: PermissionCriteria<TQuery>;\n};\n\n/**\n * Composes several {@link PermissionCondition}s as criteria with a nested AND/OR structure.\n * @public\n */\nexport type PermissionCriteria<TQuery> =\n | AllOfCriteria<TQuery>\n | AnyOfCriteria<TQuery>\n | NotCriteria<TQuery>\n | TQuery;\n\n/**\n * An individual request sent to the permission backend.\n * @public\n */\nexport type EvaluatePermissionRequest = {\n permission: Permission;\n resourceRef?: string;\n};\n\n/**\n * A batch of requests sent to the permission backend.\n * @public\n */\nexport type EvaluatePermissionRequestBatch =\n PermissionMessageBatch<EvaluatePermissionRequest>;\n\n/**\n * An individual response from the permission backend.\n *\n * @remarks\n *\n * This response type is an alias of {@link PolicyDecision} to maintain separation between the\n * {@link @backstage/plugin-permission-node#PermissionPolicy} interface and the permission backend\n * api. They may diverge at some point in the future. The response\n *\n * @public\n */\nexport type EvaluatePermissionResponse = PolicyDecision;\n\n/**\n * A batch of responses from the permission backend.\n * @public\n */\nexport type EvaluatePermissionResponseBatch =\n PermissionMessageBatch<EvaluatePermissionResponse>;\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Permission, ResourcePermission } from '../types';\n\n/**\n * Check if a given permission is a {@link ResourcePermission}. When\n * `resourceType` is supplied as the second parameter, also checks if\n * the permission has the specified resource type.\n * @public\n */\nexport function isResourcePermission<T extends string = string>(\n permission: Permission,\n resourceType?: T,\n): permission is ResourcePermission<T> {\n if (!('resourceType' in permission)) {\n return false;\n }\n\n return !resourceType || permission.resourceType === resourceType;\n}\n\n/**\n * Check if a given permission is related to a create action.\n * @public\n */\nexport function isCreatePermission(permission: Permission) {\n return permission.attributes.action === 'create';\n}\n\n/**\n * Check if a given permission is related to a read action.\n * @public\n */\nexport function isReadPermission(permission: Permission) {\n return permission.attributes.action === 'read';\n}\n\n/**\n * Check if a given permission is related to an update action.\n * @public\n */\nexport function isUpdatePermission(permission: Permission) {\n return permission.attributes.action === 'update';\n}\n\n/**\n * Check if a given permission is related to a delete action.\n * @public\n */\nexport function isDeletePermission(permission: Permission) {\n return permission.attributes.action === 'delete';\n}\n","/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n BasicPermission,\n Permission,\n PermissionAttributes,\n ResourcePermission,\n} from '../types';\n\n/**\n * Utility function for creating a valid {@link ResourcePermission}, inferring\n * the appropriate type and resource type parameter.\n *\n * @public\n */\nexport function createPermission<TResourceType extends string>(input: {\n name: string;\n attributes: PermissionAttributes;\n resourceType: TResourceType;\n}): ResourcePermission<TResourceType>;\n/**\n * Utility function for creating a valid {@link BasicPermission}.\n *\n * @public\n */\nexport function createPermission(input: {\n name: string;\n attributes: PermissionAttributes;\n}): BasicPermission;\nexport function createPermission({\n name,\n attributes,\n resourceType,\n}: {\n name: string;\n attributes: PermissionAttributes;\n resourceType?: string;\n}): Permission {\n if (resourceType) {\n return {\n type: 'resource',\n name,\n attributes,\n resourceType,\n };\n }\n\n return {\n type: 'basic',\n name,\n attributes,\n };\n}\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Config } from '@backstage/config';\nimport { ResponseError } from '@backstage/errors';\nimport fetch from 'cross-fetch';\nimport * as uuid from 'uuid';\nimport { z } from 'zod';\nimport {\n AuthorizeResult,\n EvaluatePermissionRequest,\n EvaluatePermissionResponse,\n IdentifiedPermissionMessage,\n PermissionCriteria,\n PermissionCondition,\n EvaluatePermissionResponseBatch,\n EvaluatePermissionRequestBatch,\n} from './types/api';\nimport { DiscoveryApi } from './types/discovery';\nimport {\n PermissionAuthorizer,\n AuthorizeRequestOptions,\n} from './types/permission';\n\nconst permissionCriteriaSchema: z.ZodSchema<\n PermissionCriteria<PermissionCondition>\n> = z.lazy(() =>\n z\n .object({\n rule: z.string(),\n params: z.array(z.unknown()),\n })\n .strict()\n .or(\n z\n .object({ anyOf: z.array(permissionCriteriaSchema).nonempty() })\n .strict(),\n )\n .or(\n z\n .object({ allOf: z.array(permissionCriteriaSchema).nonempty() })\n .strict(),\n )\n .or(z.object({ not: permissionCriteriaSchema }).strict()),\n);\n\nconst responseSchema = z.object({\n items: z.array(\n z\n .object({\n id: z.string(),\n result: z\n .literal(AuthorizeResult.ALLOW)\n .or(z.literal(AuthorizeResult.DENY)),\n })\n .or(\n z.object({\n id: z.string(),\n result: z.literal(AuthorizeResult.CONDITIONAL),\n conditions: permissionCriteriaSchema,\n }),\n ),\n ),\n});\n\n/**\n * An isomorphic client for requesting authorization for Backstage permissions.\n * @public\n */\nexport class PermissionClient implements PermissionAuthorizer {\n private readonly enabled: boolean;\n private readonly discovery: DiscoveryApi;\n\n constructor(options: { discovery: DiscoveryApi; config: Config }) {\n this.discovery = options.discovery;\n this.enabled =\n options.config.getOptionalBoolean('permission.enabled') ?? false;\n }\n\n /**\n * Request authorization from the permission-backend for the given set of permissions.\n *\n * Authorization requests check that a given Backstage user can perform a protected operation,\n * potentially for a specific resource (such as a catalog entity). The Backstage identity token\n * should be included in the `options` if available.\n *\n * Permissions can be imported from plugins exposing them, such as `catalogEntityReadPermission`.\n *\n * The response will be either ALLOW or DENY when either the permission has no resourceType, or a\n * resourceRef is provided in the request. For permissions with a resourceType, CONDITIONAL may be\n * returned if no resourceRef is provided in the request. Conditional responses are intended only\n * for backends which have access to the data source for permissioned resources, so that filters\n * can be applied when loading collections of resources.\n * @public\n */\n async authorize(\n queries: EvaluatePermissionRequest[],\n options?: AuthorizeRequestOptions,\n ): Promise<EvaluatePermissionResponse[]> {\n // TODO(permissions): it would be great to provide some kind of typing guarantee that\n // conditional responses will only ever be returned for requests containing a resourceType\n // but no resourceRef. That way clients who aren't prepared to handle filtering according\n // to conditions can be guaranteed that they won't unexpectedly get a CONDITIONAL response.\n\n if (!this.enabled) {\n return queries.map(_ => ({ result: AuthorizeResult.ALLOW }));\n }\n\n const request: EvaluatePermissionRequestBatch = {\n items: queries.map(query => ({\n id: uuid.v4(),\n ...query,\n })),\n };\n\n const permissionApi = await this.discovery.getBaseUrl('permission');\n const response = await fetch(`${permissionApi}/authorize`, {\n method: 'POST',\n body: JSON.stringify(request),\n headers: {\n ...this.getAuthorizationHeader(options?.token),\n 'content-type': 'application/json',\n },\n });\n if (!response.ok) {\n throw await ResponseError.fromResponse(response);\n }\n\n const responseBody = await response.json();\n this.assertValidResponse(request, responseBody);\n\n const responsesById = responseBody.items.reduce((acc, r) => {\n acc[r.id] = r;\n return acc;\n }, {} as Record<string, IdentifiedPermissionMessage<EvaluatePermissionResponse>>);\n\n return request.items.map(query => responsesById[query.id]);\n }\n\n private getAuthorizationHeader(token?: string): Record<string, string> {\n return token ? { Authorization: `Bearer ${token}` } : {};\n }\n\n private assertValidResponse(\n request: EvaluatePermissionRequestBatch,\n json: any,\n ): asserts json is EvaluatePermissionResponseBatch {\n const authorizedResponses = responseSchema.parse(json);\n const responseIds = authorizedResponses.items.map(r => r.id);\n const hasAllRequestIds = request.items.every(r =>\n responseIds.includes(r.id),\n );\n if (!hasAllRequestIds) {\n throw new Error(\n 'Unexpected authorization response from permission-backend',\n );\n }\n }\n}\n"],"names":["z","uuid","fetch","ResponseError"],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -68,7 +68,7 @@ declare type ResourcePermission<TResourceType extends string = string> = Permiss
68
68
  * @public
69
69
  */
70
70
  interface PermissionAuthorizer {
71
- authorize(queries: AuthorizeQuery[], options?: AuthorizeRequestOptions): Promise<AuthorizeDecision[]>;
71
+ authorize(requests: EvaluatePermissionRequest[], options?: AuthorizeRequestOptions): Promise<EvaluatePermissionResponse[]>;
72
72
  }
73
73
  /**
74
74
  * Options for authorization requests.
@@ -83,9 +83,16 @@ declare type AuthorizeRequestOptions = {
83
83
  * requests.
84
84
  * @public
85
85
  */
86
- declare type Identified<T> = T & {
86
+ declare type IdentifiedPermissionMessage<T> = T & {
87
87
  id: string;
88
88
  };
89
+ /**
90
+ * A batch of request or response items.
91
+ * @public
92
+ */
93
+ declare type PermissionMessageBatch<T> = {
94
+ items: IdentifiedPermissionMessage<T>[];
95
+ };
89
96
  /**
90
97
  * The result of an authorization request.
91
98
  * @public
@@ -105,20 +112,40 @@ declare enum AuthorizeResult {
105
112
  CONDITIONAL = "CONDITIONAL"
106
113
  }
107
114
  /**
108
- * An individual authorization request for {@link PermissionClient#authorize}.
115
+ * A definitive decision returned by the {@link @backstage/plugin-permission-node#PermissionPolicy}.
116
+ *
117
+ * @remarks
118
+ *
119
+ * This indicates that the policy unconditionally allows (or denies) the request.
120
+ *
109
121
  * @public
110
122
  */
111
- declare type AuthorizeQuery = {
112
- permission: Permission;
113
- resourceRef?: string;
123
+ declare type DefinitivePolicyDecision = {
124
+ result: AuthorizeResult.ALLOW | AuthorizeResult.DENY;
114
125
  };
115
126
  /**
116
- * A batch of authorization requests from {@link PermissionClient#authorize}.
127
+ * A conditional decision returned by the {@link @backstage/plugin-permission-node#PermissionPolicy}.
128
+ *
129
+ * @remarks
130
+ *
131
+ * This indicates that the policy allows authorization for the request, given that the returned
132
+ * conditions hold when evaluated. The conditions will be evaluated by the corresponding plugin
133
+ * which knows about the referenced permission rules.
134
+ *
117
135
  * @public
118
136
  */
119
- declare type AuthorizeRequest = {
120
- items: Identified<AuthorizeQuery>[];
137
+ declare type ConditionalPolicyDecision = {
138
+ result: AuthorizeResult.CONDITIONAL;
139
+ pluginId: string;
140
+ resourceType: string;
141
+ conditions: PermissionCriteria<PermissionCondition>;
121
142
  };
143
+ /**
144
+ * A decision returned by the {@link @backstage/plugin-permission-node#PermissionPolicy}.
145
+ *
146
+ * @public
147
+ */
148
+ declare type PolicyDecision = DefinitivePolicyDecision | ConditionalPolicyDecision;
122
149
  /**
123
150
  * A condition returned with a CONDITIONAL authorization response.
124
151
  *
@@ -163,22 +190,35 @@ declare type NotCriteria<TQuery> = {
163
190
  */
164
191
  declare type PermissionCriteria<TQuery> = AllOfCriteria<TQuery> | AnyOfCriteria<TQuery> | NotCriteria<TQuery> | TQuery;
165
192
  /**
166
- * An individual authorization response from {@link PermissionClient#authorize}.
193
+ * An individual request sent to the permission backend.
167
194
  * @public
168
195
  */
169
- declare type AuthorizeDecision = {
170
- result: AuthorizeResult.ALLOW | AuthorizeResult.DENY;
171
- } | {
172
- result: AuthorizeResult.CONDITIONAL;
173
- conditions: PermissionCriteria<PermissionCondition>;
196
+ declare type EvaluatePermissionRequest = {
197
+ permission: Permission;
198
+ resourceRef?: string;
174
199
  };
175
200
  /**
176
- * A batch of authorization responses from {@link PermissionClient#authorize}.
201
+ * A batch of requests sent to the permission backend.
177
202
  * @public
178
203
  */
179
- declare type AuthorizeResponse = {
180
- items: Identified<AuthorizeDecision>[];
181
- };
204
+ declare type EvaluatePermissionRequestBatch = PermissionMessageBatch<EvaluatePermissionRequest>;
205
+ /**
206
+ * An individual response from the permission backend.
207
+ *
208
+ * @remarks
209
+ *
210
+ * This response type is an alias of {@link PolicyDecision} to maintain separation between the
211
+ * {@link @backstage/plugin-permission-node#PermissionPolicy} interface and the permission backend
212
+ * api. They may diverge at some point in the future. The response
213
+ *
214
+ * @public
215
+ */
216
+ declare type EvaluatePermissionResponse = PolicyDecision;
217
+ /**
218
+ * A batch of responses from the permission backend.
219
+ * @public
220
+ */
221
+ declare type EvaluatePermissionResponseBatch = PermissionMessageBatch<EvaluatePermissionResponse>;
182
222
 
183
223
  /**
184
224
  * This is a copy of the core DiscoveryApi, to avoid importing core.
@@ -265,9 +305,9 @@ declare class PermissionClient implements PermissionAuthorizer {
265
305
  * can be applied when loading collections of resources.
266
306
  * @public
267
307
  */
268
- authorize(queries: AuthorizeQuery[], options?: AuthorizeRequestOptions): Promise<AuthorizeDecision[]>;
308
+ authorize(queries: EvaluatePermissionRequest[], options?: AuthorizeRequestOptions): Promise<EvaluatePermissionResponse[]>;
269
309
  private getAuthorizationHeader;
270
310
  private assertValidResponse;
271
311
  }
272
312
 
273
- export { AllOfCriteria, AnyOfCriteria, AuthorizeDecision, AuthorizeQuery, AuthorizeRequest, AuthorizeRequestOptions, AuthorizeResponse, AuthorizeResult, BasicPermission, DiscoveryApi, Identified, NotCriteria, Permission, PermissionAttributes, PermissionAuthorizer, PermissionBase, PermissionClient, PermissionCondition, PermissionCriteria, ResourcePermission, createPermission, isCreatePermission, isDeletePermission, isReadPermission, isResourcePermission, isUpdatePermission };
313
+ export { AllOfCriteria, AnyOfCriteria, AuthorizeRequestOptions, AuthorizeResult, BasicPermission, ConditionalPolicyDecision, DefinitivePolicyDecision, DiscoveryApi, EvaluatePermissionRequest, EvaluatePermissionRequestBatch, EvaluatePermissionResponse, EvaluatePermissionResponseBatch, IdentifiedPermissionMessage, NotCriteria, Permission, PermissionAttributes, PermissionAuthorizer, PermissionBase, PermissionClient, PermissionCondition, PermissionCriteria, PermissionMessageBatch, PolicyDecision, ResourcePermission, createPermission, isCreatePermission, isDeletePermission, isReadPermission, isResourcePermission, isUpdatePermission };
@@ -1 +1 @@
1
- {"version":3,"file":"index.esm.js","sources":["../src/types/api.ts","../src/permissions/util.ts","../src/permissions/createPermission.ts","../src/PermissionClient.ts"],"sourcesContent":["/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Permission } from './permission';\n\n/**\n * A request with a UUID identifier, so that batched responses can be matched up with the original\n * requests.\n * @public\n */\nexport type Identified<T> = T & { id: string };\n\n/**\n * The result of an authorization request.\n * @public\n */\nexport enum AuthorizeResult {\n /**\n * The authorization request is denied.\n */\n DENY = 'DENY',\n /**\n * The authorization request is allowed.\n */\n ALLOW = 'ALLOW',\n /**\n * The authorization request is allowed if the provided conditions are met.\n */\n CONDITIONAL = 'CONDITIONAL',\n}\n\n/**\n * An individual authorization request for {@link PermissionClient#authorize}.\n * @public\n */\nexport type AuthorizeQuery = {\n permission: Permission;\n resourceRef?: string;\n};\n\n/**\n * A batch of authorization requests from {@link PermissionClient#authorize}.\n * @public\n */\nexport type AuthorizeRequest = {\n items: Identified<AuthorizeQuery>[];\n};\n\n/**\n * A condition returned with a CONDITIONAL authorization response.\n *\n * Conditions are a reference to a rule defined by a plugin, and parameters to apply the rule. For\n * example, a rule might be `isOwner` from the catalog-backend, and params may be a list of entity\n * claims from a identity token.\n * @public\n */\nexport type PermissionCondition<TParams extends unknown[] = unknown[]> = {\n rule: string;\n params: TParams;\n};\n\n/**\n * Utility type to represent an array with 1 or more elements.\n * @ignore\n */\ntype NonEmptyArray<T> = [T, ...T[]];\n\n/**\n * Represents a logical AND for the provided criteria.\n * @public\n */\nexport type AllOfCriteria<TQuery> = {\n allOf: NonEmptyArray<PermissionCriteria<TQuery>>;\n};\n\n/**\n * Represents a logical OR for the provided criteria.\n * @public\n */\nexport type AnyOfCriteria<TQuery> = {\n anyOf: NonEmptyArray<PermissionCriteria<TQuery>>;\n};\n\n/**\n * Represents a negation of the provided criteria.\n * @public\n */\nexport type NotCriteria<TQuery> = {\n not: PermissionCriteria<TQuery>;\n};\n\n/**\n * Composes several {@link PermissionCondition}s as criteria with a nested AND/OR structure.\n * @public\n */\nexport type PermissionCriteria<TQuery> =\n | AllOfCriteria<TQuery>\n | AnyOfCriteria<TQuery>\n | NotCriteria<TQuery>\n | TQuery;\n\n/**\n * An individual authorization response from {@link PermissionClient#authorize}.\n * @public\n */\nexport type AuthorizeDecision =\n | { result: AuthorizeResult.ALLOW | AuthorizeResult.DENY }\n | {\n result: AuthorizeResult.CONDITIONAL;\n conditions: PermissionCriteria<PermissionCondition>;\n };\n\n/**\n * A batch of authorization responses from {@link PermissionClient#authorize}.\n * @public\n */\nexport type AuthorizeResponse = {\n items: Identified<AuthorizeDecision>[];\n};\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Permission, ResourcePermission } from '../types';\n\n/**\n * Check if a given permission is a {@link ResourcePermission}. When\n * `resourceType` is supplied as the second parameter, also checks if\n * the permission has the specified resource type.\n * @public\n */\nexport function isResourcePermission<T extends string = string>(\n permission: Permission,\n resourceType?: T,\n): permission is ResourcePermission<T> {\n if (!('resourceType' in permission)) {\n return false;\n }\n\n return !resourceType || permission.resourceType === resourceType;\n}\n\n/**\n * Check if a given permission is related to a create action.\n * @public\n */\nexport function isCreatePermission(permission: Permission) {\n return permission.attributes.action === 'create';\n}\n\n/**\n * Check if a given permission is related to a read action.\n * @public\n */\nexport function isReadPermission(permission: Permission) {\n return permission.attributes.action === 'read';\n}\n\n/**\n * Check if a given permission is related to an update action.\n * @public\n */\nexport function isUpdatePermission(permission: Permission) {\n return permission.attributes.action === 'update';\n}\n\n/**\n * Check if a given permission is related to a delete action.\n * @public\n */\nexport function isDeletePermission(permission: Permission) {\n return permission.attributes.action === 'delete';\n}\n","/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n BasicPermission,\n Permission,\n PermissionAttributes,\n ResourcePermission,\n} from '../types';\n\n/**\n * Utility function for creating a valid {@link ResourcePermission}, inferring\n * the appropriate type and resource type parameter.\n *\n * @public\n */\nexport function createPermission<TResourceType extends string>(input: {\n name: string;\n attributes: PermissionAttributes;\n resourceType: TResourceType;\n}): ResourcePermission<TResourceType>;\n/**\n * Utility function for creating a valid {@link BasicPermission}.\n *\n * @public\n */\nexport function createPermission(input: {\n name: string;\n attributes: PermissionAttributes;\n}): BasicPermission;\nexport function createPermission({\n name,\n attributes,\n resourceType,\n}: {\n name: string;\n attributes: PermissionAttributes;\n resourceType?: string;\n}): Permission {\n if (resourceType) {\n return {\n type: 'resource',\n name,\n attributes,\n resourceType,\n };\n }\n\n return {\n type: 'basic',\n name,\n attributes,\n };\n}\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Config } from '@backstage/config';\nimport { ResponseError } from '@backstage/errors';\nimport fetch from 'cross-fetch';\nimport * as uuid from 'uuid';\nimport { z } from 'zod';\nimport {\n AuthorizeResult,\n AuthorizeQuery,\n AuthorizeDecision,\n Identified,\n PermissionCriteria,\n PermissionCondition,\n AuthorizeResponse,\n AuthorizeRequest,\n} from './types/api';\nimport { DiscoveryApi } from './types/discovery';\nimport {\n PermissionAuthorizer,\n AuthorizeRequestOptions,\n} from './types/permission';\n\nconst permissionCriteriaSchema: z.ZodSchema<\n PermissionCriteria<PermissionCondition>\n> = z.lazy(() =>\n z\n .object({\n rule: z.string(),\n params: z.array(z.unknown()),\n })\n .strict()\n .or(\n z\n .object({ anyOf: z.array(permissionCriteriaSchema).nonempty() })\n .strict(),\n )\n .or(\n z\n .object({ allOf: z.array(permissionCriteriaSchema).nonempty() })\n .strict(),\n )\n .or(z.object({ not: permissionCriteriaSchema }).strict()),\n);\n\nconst responseSchema = z.object({\n items: z.array(\n z\n .object({\n id: z.string(),\n result: z\n .literal(AuthorizeResult.ALLOW)\n .or(z.literal(AuthorizeResult.DENY)),\n })\n .or(\n z.object({\n id: z.string(),\n result: z.literal(AuthorizeResult.CONDITIONAL),\n conditions: permissionCriteriaSchema,\n }),\n ),\n ),\n});\n\n/**\n * An isomorphic client for requesting authorization for Backstage permissions.\n * @public\n */\nexport class PermissionClient implements PermissionAuthorizer {\n private readonly enabled: boolean;\n private readonly discovery: DiscoveryApi;\n\n constructor(options: { discovery: DiscoveryApi; config: Config }) {\n this.discovery = options.discovery;\n this.enabled =\n options.config.getOptionalBoolean('permission.enabled') ?? false;\n }\n\n /**\n * Request authorization from the permission-backend for the given set of permissions.\n *\n * Authorization requests check that a given Backstage user can perform a protected operation,\n * potentially for a specific resource (such as a catalog entity). The Backstage identity token\n * should be included in the `options` if available.\n *\n * Permissions can be imported from plugins exposing them, such as `catalogEntityReadPermission`.\n *\n * The response will be either ALLOW or DENY when either the permission has no resourceType, or a\n * resourceRef is provided in the request. For permissions with a resourceType, CONDITIONAL may be\n * returned if no resourceRef is provided in the request. Conditional responses are intended only\n * for backends which have access to the data source for permissioned resources, so that filters\n * can be applied when loading collections of resources.\n * @public\n */\n async authorize(\n queries: AuthorizeQuery[],\n options?: AuthorizeRequestOptions,\n ): Promise<AuthorizeDecision[]> {\n // TODO(permissions): it would be great to provide some kind of typing guarantee that\n // conditional responses will only ever be returned for requests containing a resourceType\n // but no resourceRef. That way clients who aren't prepared to handle filtering according\n // to conditions can be guaranteed that they won't unexpectedly get a CONDITIONAL response.\n\n if (!this.enabled) {\n return queries.map(_ => ({ result: AuthorizeResult.ALLOW }));\n }\n\n const request: AuthorizeRequest = {\n items: queries.map(query => ({\n id: uuid.v4(),\n ...query,\n })),\n };\n\n const permissionApi = await this.discovery.getBaseUrl('permission');\n const response = await fetch(`${permissionApi}/authorize`, {\n method: 'POST',\n body: JSON.stringify(request),\n headers: {\n ...this.getAuthorizationHeader(options?.token),\n 'content-type': 'application/json',\n },\n });\n if (!response.ok) {\n throw await ResponseError.fromResponse(response);\n }\n\n const responseBody = await response.json();\n this.assertValidResponse(request, responseBody);\n\n const responsesById = responseBody.items.reduce((acc, r) => {\n acc[r.id] = r;\n return acc;\n }, {} as Record<string, Identified<AuthorizeDecision>>);\n\n return request.items.map(query => responsesById[query.id]);\n }\n\n private getAuthorizationHeader(token?: string): Record<string, string> {\n return token ? { Authorization: `Bearer ${token}` } : {};\n }\n\n private assertValidResponse(\n request: AuthorizeRequest,\n json: any,\n ): asserts json is AuthorizeResponse {\n const authorizedResponses = responseSchema.parse(json);\n const responseIds = authorizedResponses.items.map(r => r.id);\n const hasAllRequestIds = request.items.every(r =>\n responseIds.includes(r.id),\n );\n if (!hasAllRequestIds) {\n throw new Error(\n 'Unexpected authorization response from permission-backend',\n );\n }\n }\n}\n"],"names":[],"mappings":";;;;;AA6BY,IAAA,eAAA,qBAAA,gBAAL,KAAA;AAIL,EAAO,gBAAA,CAAA,MAAA,CAAA,GAAA,MAAA,CAAA;AAIP,EAAQ,gBAAA,CAAA,OAAA,CAAA,GAAA,OAAA,CAAA;AAIR,EAAc,gBAAA,CAAA,aAAA,CAAA,GAAA,aAAA,CAAA;AAZJ,EAAA,OAAA,gBAAA,CAAA;AAAA,CAAA,EAAA,eAAA,IAAA,EAAA;;ACLL,SAAA,oBAAA,CACL,YACA,YACqC,EAAA;AACrC,EAAI,IAAA,oBAAoB,UAAa,CAAA,EAAA;AACnC,IAAO,OAAA,KAAA,CAAA;AAAA,GACT;AAEA,EAAO,OAAA,CAAC,YAAgB,IAAA,UAAA,CAAW,YAAiB,KAAA,YAAA,CAAA;AACtD,CAAA;AAMO,SAAA,kBAAA,CAA4B,UAAwB,EAAA;AACzD,EAAO,OAAA,UAAA,CAAW,WAAW,MAAW,KAAA,QAAA,CAAA;AAC1C,CAAA;AAMO,SAAA,gBAAA,CAA0B,UAAwB,EAAA;AACvD,EAAO,OAAA,UAAA,CAAW,WAAW,MAAW,KAAA,MAAA,CAAA;AAC1C,CAAA;AAMO,SAAA,kBAAA,CAA4B,UAAwB,EAAA;AACzD,EAAO,OAAA,UAAA,CAAW,WAAW,MAAW,KAAA,QAAA,CAAA;AAC1C,CAAA;AAMO,SAAA,kBAAA,CAA4B,UAAwB,EAAA;AACzD,EAAO,OAAA,UAAA,CAAW,WAAW,MAAW,KAAA,QAAA,CAAA;AAC1C;;ACtBiC,SAAA,gBAAA,CAAA;AAAA,EAC/B,IAAA;AAAA,EACA,UAAA;AAAA,EACA,YAAA;AAAA,CAKa,EAAA;AACb,EAAA,IAAI,YAAc,EAAA;AAChB,IAAO,OAAA;AAAA,MACL,IAAM,EAAA,UAAA;AAAA,MACN,IAAA;AAAA,MACA,UAAA;AAAA,MACA,YAAA;AAAA,KACF,CAAA;AAAA,GACF;AAEA,EAAO,OAAA;AAAA,IACL,IAAM,EAAA,OAAA;AAAA,IACN,IAAA;AAAA,IACA,UAAA;AAAA,GACF,CAAA;AACF;;AC7BA,MAAM,wBAEF,GAAA,CAAA,CAAE,IAAK,CAAA,MACT,EACG,MAAO,CAAA;AAAA,EACN,IAAA,EAAM,EAAE,MAAO,EAAA;AAAA,EACf,MAAQ,EAAA,CAAA,CAAE,KAAM,CAAA,CAAA,CAAE,SAAS,CAAA;AAC7B,CAAC,CAAA,CACA,QACA,CAAA,EAAA,CACC,EACG,MAAO,CAAA,EAAE,OAAO,CAAE,CAAA,KAAA,CAAM,wBAAwB,CAAE,CAAA,QAAA,IAAY,CAAA,CAC9D,QACL,CAAA,CACC,GACC,CACG,CAAA,MAAA,CAAO,EAAE,KAAO,EAAA,CAAA,CAAE,MAAM,wBAAwB,CAAA,CAAE,UAAW,EAAC,EAC9D,MAAO,EACZ,EACC,EAAG,CAAA,CAAA,CAAE,OAAO,EAAE,GAAA,EAAK,0BAA0B,CAAA,CAAE,MAAO,EAAC,CAC5D,CAAA,CAAA;AAEA,MAAM,cAAA,GAAiB,EAAE,MAAO,CAAA;AAAA,EAC9B,KAAO,EAAA,CAAA,CAAE,KACP,CAAA,CAAA,CACG,MAAO,CAAA;AAAA,IACN,EAAA,EAAI,EAAE,MAAO,EAAA;AAAA,IACb,MAAA,EAAQ,CACL,CAAA,OAAA,CAAQ,eAAgB,CAAA,KAAK,CAC7B,CAAA,EAAA,CAAG,CAAE,CAAA,OAAA,CAAQ,eAAgB,CAAA,IAAI,CAAC,CAAA;AAAA,GACtC,CAAA,CACA,EACC,CAAA,CAAA,CAAE,MAAO,CAAA;AAAA,IACP,EAAA,EAAI,EAAE,MAAO,EAAA;AAAA,IACb,MAAQ,EAAA,CAAA,CAAE,OAAQ,CAAA,eAAA,CAAgB,WAAW,CAAA;AAAA,IAC7C,UAAY,EAAA,wBAAA;AAAA,GACb,CACH,CACJ,CAAA;AACF,CAAC,CAAA,CAAA;AAMM,MAAM,gBAAiD,CAAA;AAAA,EAI5D,YAAY,OAAsD,EAAA;AAtFpE,IAAA,IAAA,EAAA,CAAA;AAuFI,IAAA,IAAA,CAAK,YAAY,OAAQ,CAAA,SAAA,CAAA;AACzB,IAAA,IAAA,CAAK,UACH,CAAQ,EAAA,GAAA,OAAA,CAAA,MAAA,CAAO,kBAAmB,CAAA,oBAAoB,MAAtD,IAA2D,GAAA,EAAA,GAAA,KAAA,CAAA;AAAA,GAC/D;AAAA,EAkBM,MAAA,SAAA,CACJ,SACA,OAC8B,EAAA;AAM9B,IAAI,IAAA,CAAC,KAAK,OAAS,EAAA;AACjB,MAAA,OAAO,QAAQ,GAAI,CAAA,CAAA,CAAA,QAAQ,MAAQ,EAAA,eAAA,CAAgB,OAAQ,CAAA,CAAA,CAAA;AAAA,KAC7D;AAEA,IAAA,MAAM,OAA4B,GAAA;AAAA,MAChC,KAAA,EAAO,OAAQ,CAAA,GAAA,CAAI,CAAU,KAAA,MAAA;AAAA,QAC3B,EAAA,EAAI,KAAK,EAAG,EAAA;AAAA,QACT,GAAA,KAAA;AAAA,OACH,CAAA,CAAA;AAAA,KACJ,CAAA;AAEA,IAAA,MAAM,aAAgB,GAAA,MAAM,IAAK,CAAA,SAAA,CAAU,WAAW,YAAY,CAAA,CAAA;AAClE,IAAA,MAAM,QAAW,GAAA,MAAM,KAAM,CAAA,CAAA,EAAG,aAA2B,CAAA,UAAA,CAAA,EAAA;AAAA,MACzD,MAAQ,EAAA,MAAA;AAAA,MACR,IAAA,EAAM,IAAK,CAAA,SAAA,CAAU,OAAO,CAAA;AAAA,MAC5B,OAAS,EAAA;AAAA,QACJ,GAAA,IAAA,CAAK,sBAAuB,CAAA,OAAA,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,OAAA,CAAS,KAAK,CAAA;AAAA,QAC7C,cAAgB,EAAA,kBAAA;AAAA,OAClB;AAAA,KACD,CAAA,CAAA;AACD,IAAI,IAAA,CAAC,SAAS,EAAI,EAAA;AAChB,MAAM,MAAA,MAAM,aAAc,CAAA,YAAA,CAAa,QAAQ,CAAA,CAAA;AAAA,KACjD;AAEA,IAAM,MAAA,YAAA,GAAe,MAAM,QAAA,CAAS,IAAK,EAAA,CAAA;AACzC,IAAK,IAAA,CAAA,mBAAA,CAAoB,SAAS,YAAY,CAAA,CAAA;AAE9C,IAAA,MAAM,gBAAgB,YAAa,CAAA,KAAA,CAAM,MAAO,CAAA,CAAC,KAAK,CAAM,KAAA;AAC1D,MAAA,GAAA,CAAI,EAAE,EAAM,CAAA,GAAA,CAAA,CAAA;AACZ,MAAO,OAAA,GAAA,CAAA;AAAA,KACT,EAAG,EAAmD,CAAA,CAAA;AAEtD,IAAA,OAAO,QAAQ,KAAM,CAAA,GAAA,CAAI,CAAS,KAAA,KAAA,aAAA,CAAc,MAAM,EAAG,CAAA,CAAA,CAAA;AAAA,GAC3D;AAAA,EAEQ,uBAAuB,KAAwC,EAAA;AACrE,IAAA,OAAO,QAAQ,EAAE,aAAA,EAAe,CAAU,OAAA,EAAA,KAAA,CAAA,CAAA,KAAY,EAAC,CAAA;AAAA,GACzD;AAAA,EAEQ,mBAAA,CACN,SACA,IACmC,EAAA;AACnC,IAAM,MAAA,mBAAA,GAAsB,cAAe,CAAA,KAAA,CAAM,IAAI,CAAA,CAAA;AACrD,IAAA,MAAM,cAAc,mBAAoB,CAAA,KAAA,CAAM,GAAI,CAAA,CAAA,CAAA,KAAK,EAAE,EAAE,CAAA,CAAA;AAC3D,IAAM,MAAA,gBAAA,GAAmB,QAAQ,KAAM,CAAA,KAAA,CAAM,OAC3C,WAAY,CAAA,QAAA,CAAS,CAAE,CAAA,EAAE,CAC3B,CAAA,CAAA;AACA,IAAA,IAAI,CAAC,gBAAkB,EAAA;AACrB,MAAM,MAAA,IAAI,MACR,2DACF,CAAA,CAAA;AAAA,KACF;AAAA,GACF;AACF;;;;"}
1
+ {"version":3,"file":"index.esm.js","sources":["../src/types/api.ts","../src/permissions/util.ts","../src/permissions/createPermission.ts","../src/PermissionClient.ts"],"sourcesContent":["/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Permission } from './permission';\n\n/**\n * A request with a UUID identifier, so that batched responses can be matched up with the original\n * requests.\n * @public\n */\nexport type IdentifiedPermissionMessage<T> = T & { id: string };\n\n/**\n * A batch of request or response items.\n * @public\n */\nexport type PermissionMessageBatch<T> = {\n items: IdentifiedPermissionMessage<T>[];\n};\n\n/**\n * The result of an authorization request.\n * @public\n */\nexport enum AuthorizeResult {\n /**\n * The authorization request is denied.\n */\n DENY = 'DENY',\n /**\n * The authorization request is allowed.\n */\n ALLOW = 'ALLOW',\n /**\n * The authorization request is allowed if the provided conditions are met.\n */\n CONDITIONAL = 'CONDITIONAL',\n}\n\n/**\n * A definitive decision returned by the {@link @backstage/plugin-permission-node#PermissionPolicy}.\n *\n * @remarks\n *\n * This indicates that the policy unconditionally allows (or denies) the request.\n *\n * @public\n */\nexport type DefinitivePolicyDecision = {\n result: AuthorizeResult.ALLOW | AuthorizeResult.DENY;\n};\n\n/**\n * A conditional decision returned by the {@link @backstage/plugin-permission-node#PermissionPolicy}.\n *\n * @remarks\n *\n * This indicates that the policy allows authorization for the request, given that the returned\n * conditions hold when evaluated. The conditions will be evaluated by the corresponding plugin\n * which knows about the referenced permission rules.\n *\n * @public\n */\nexport type ConditionalPolicyDecision = {\n result: AuthorizeResult.CONDITIONAL;\n pluginId: string;\n resourceType: string;\n conditions: PermissionCriteria<PermissionCondition>;\n};\n\n/**\n * A decision returned by the {@link @backstage/plugin-permission-node#PermissionPolicy}.\n *\n * @public\n */\nexport type PolicyDecision =\n | DefinitivePolicyDecision\n | ConditionalPolicyDecision;\n\n/**\n * A condition returned with a CONDITIONAL authorization response.\n *\n * Conditions are a reference to a rule defined by a plugin, and parameters to apply the rule. For\n * example, a rule might be `isOwner` from the catalog-backend, and params may be a list of entity\n * claims from a identity token.\n * @public\n */\nexport type PermissionCondition<TParams extends unknown[] = unknown[]> = {\n rule: string;\n params: TParams;\n};\n\n/**\n * Utility type to represent an array with 1 or more elements.\n * @ignore\n */\ntype NonEmptyArray<T> = [T, ...T[]];\n\n/**\n * Represents a logical AND for the provided criteria.\n * @public\n */\nexport type AllOfCriteria<TQuery> = {\n allOf: NonEmptyArray<PermissionCriteria<TQuery>>;\n};\n\n/**\n * Represents a logical OR for the provided criteria.\n * @public\n */\nexport type AnyOfCriteria<TQuery> = {\n anyOf: NonEmptyArray<PermissionCriteria<TQuery>>;\n};\n\n/**\n * Represents a negation of the provided criteria.\n * @public\n */\nexport type NotCriteria<TQuery> = {\n not: PermissionCriteria<TQuery>;\n};\n\n/**\n * Composes several {@link PermissionCondition}s as criteria with a nested AND/OR structure.\n * @public\n */\nexport type PermissionCriteria<TQuery> =\n | AllOfCriteria<TQuery>\n | AnyOfCriteria<TQuery>\n | NotCriteria<TQuery>\n | TQuery;\n\n/**\n * An individual request sent to the permission backend.\n * @public\n */\nexport type EvaluatePermissionRequest = {\n permission: Permission;\n resourceRef?: string;\n};\n\n/**\n * A batch of requests sent to the permission backend.\n * @public\n */\nexport type EvaluatePermissionRequestBatch =\n PermissionMessageBatch<EvaluatePermissionRequest>;\n\n/**\n * An individual response from the permission backend.\n *\n * @remarks\n *\n * This response type is an alias of {@link PolicyDecision} to maintain separation between the\n * {@link @backstage/plugin-permission-node#PermissionPolicy} interface and the permission backend\n * api. They may diverge at some point in the future. The response\n *\n * @public\n */\nexport type EvaluatePermissionResponse = PolicyDecision;\n\n/**\n * A batch of responses from the permission backend.\n * @public\n */\nexport type EvaluatePermissionResponseBatch =\n PermissionMessageBatch<EvaluatePermissionResponse>;\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Permission, ResourcePermission } from '../types';\n\n/**\n * Check if a given permission is a {@link ResourcePermission}. When\n * `resourceType` is supplied as the second parameter, also checks if\n * the permission has the specified resource type.\n * @public\n */\nexport function isResourcePermission<T extends string = string>(\n permission: Permission,\n resourceType?: T,\n): permission is ResourcePermission<T> {\n if (!('resourceType' in permission)) {\n return false;\n }\n\n return !resourceType || permission.resourceType === resourceType;\n}\n\n/**\n * Check if a given permission is related to a create action.\n * @public\n */\nexport function isCreatePermission(permission: Permission) {\n return permission.attributes.action === 'create';\n}\n\n/**\n * Check if a given permission is related to a read action.\n * @public\n */\nexport function isReadPermission(permission: Permission) {\n return permission.attributes.action === 'read';\n}\n\n/**\n * Check if a given permission is related to an update action.\n * @public\n */\nexport function isUpdatePermission(permission: Permission) {\n return permission.attributes.action === 'update';\n}\n\n/**\n * Check if a given permission is related to a delete action.\n * @public\n */\nexport function isDeletePermission(permission: Permission) {\n return permission.attributes.action === 'delete';\n}\n","/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n BasicPermission,\n Permission,\n PermissionAttributes,\n ResourcePermission,\n} from '../types';\n\n/**\n * Utility function for creating a valid {@link ResourcePermission}, inferring\n * the appropriate type and resource type parameter.\n *\n * @public\n */\nexport function createPermission<TResourceType extends string>(input: {\n name: string;\n attributes: PermissionAttributes;\n resourceType: TResourceType;\n}): ResourcePermission<TResourceType>;\n/**\n * Utility function for creating a valid {@link BasicPermission}.\n *\n * @public\n */\nexport function createPermission(input: {\n name: string;\n attributes: PermissionAttributes;\n}): BasicPermission;\nexport function createPermission({\n name,\n attributes,\n resourceType,\n}: {\n name: string;\n attributes: PermissionAttributes;\n resourceType?: string;\n}): Permission {\n if (resourceType) {\n return {\n type: 'resource',\n name,\n attributes,\n resourceType,\n };\n }\n\n return {\n type: 'basic',\n name,\n attributes,\n };\n}\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Config } from '@backstage/config';\nimport { ResponseError } from '@backstage/errors';\nimport fetch from 'cross-fetch';\nimport * as uuid from 'uuid';\nimport { z } from 'zod';\nimport {\n AuthorizeResult,\n EvaluatePermissionRequest,\n EvaluatePermissionResponse,\n IdentifiedPermissionMessage,\n PermissionCriteria,\n PermissionCondition,\n EvaluatePermissionResponseBatch,\n EvaluatePermissionRequestBatch,\n} from './types/api';\nimport { DiscoveryApi } from './types/discovery';\nimport {\n PermissionAuthorizer,\n AuthorizeRequestOptions,\n} from './types/permission';\n\nconst permissionCriteriaSchema: z.ZodSchema<\n PermissionCriteria<PermissionCondition>\n> = z.lazy(() =>\n z\n .object({\n rule: z.string(),\n params: z.array(z.unknown()),\n })\n .strict()\n .or(\n z\n .object({ anyOf: z.array(permissionCriteriaSchema).nonempty() })\n .strict(),\n )\n .or(\n z\n .object({ allOf: z.array(permissionCriteriaSchema).nonempty() })\n .strict(),\n )\n .or(z.object({ not: permissionCriteriaSchema }).strict()),\n);\n\nconst responseSchema = z.object({\n items: z.array(\n z\n .object({\n id: z.string(),\n result: z\n .literal(AuthorizeResult.ALLOW)\n .or(z.literal(AuthorizeResult.DENY)),\n })\n .or(\n z.object({\n id: z.string(),\n result: z.literal(AuthorizeResult.CONDITIONAL),\n conditions: permissionCriteriaSchema,\n }),\n ),\n ),\n});\n\n/**\n * An isomorphic client for requesting authorization for Backstage permissions.\n * @public\n */\nexport class PermissionClient implements PermissionAuthorizer {\n private readonly enabled: boolean;\n private readonly discovery: DiscoveryApi;\n\n constructor(options: { discovery: DiscoveryApi; config: Config }) {\n this.discovery = options.discovery;\n this.enabled =\n options.config.getOptionalBoolean('permission.enabled') ?? false;\n }\n\n /**\n * Request authorization from the permission-backend for the given set of permissions.\n *\n * Authorization requests check that a given Backstage user can perform a protected operation,\n * potentially for a specific resource (such as a catalog entity). The Backstage identity token\n * should be included in the `options` if available.\n *\n * Permissions can be imported from plugins exposing them, such as `catalogEntityReadPermission`.\n *\n * The response will be either ALLOW or DENY when either the permission has no resourceType, or a\n * resourceRef is provided in the request. For permissions with a resourceType, CONDITIONAL may be\n * returned if no resourceRef is provided in the request. Conditional responses are intended only\n * for backends which have access to the data source for permissioned resources, so that filters\n * can be applied when loading collections of resources.\n * @public\n */\n async authorize(\n queries: EvaluatePermissionRequest[],\n options?: AuthorizeRequestOptions,\n ): Promise<EvaluatePermissionResponse[]> {\n // TODO(permissions): it would be great to provide some kind of typing guarantee that\n // conditional responses will only ever be returned for requests containing a resourceType\n // but no resourceRef. That way clients who aren't prepared to handle filtering according\n // to conditions can be guaranteed that they won't unexpectedly get a CONDITIONAL response.\n\n if (!this.enabled) {\n return queries.map(_ => ({ result: AuthorizeResult.ALLOW }));\n }\n\n const request: EvaluatePermissionRequestBatch = {\n items: queries.map(query => ({\n id: uuid.v4(),\n ...query,\n })),\n };\n\n const permissionApi = await this.discovery.getBaseUrl('permission');\n const response = await fetch(`${permissionApi}/authorize`, {\n method: 'POST',\n body: JSON.stringify(request),\n headers: {\n ...this.getAuthorizationHeader(options?.token),\n 'content-type': 'application/json',\n },\n });\n if (!response.ok) {\n throw await ResponseError.fromResponse(response);\n }\n\n const responseBody = await response.json();\n this.assertValidResponse(request, responseBody);\n\n const responsesById = responseBody.items.reduce((acc, r) => {\n acc[r.id] = r;\n return acc;\n }, {} as Record<string, IdentifiedPermissionMessage<EvaluatePermissionResponse>>);\n\n return request.items.map(query => responsesById[query.id]);\n }\n\n private getAuthorizationHeader(token?: string): Record<string, string> {\n return token ? { Authorization: `Bearer ${token}` } : {};\n }\n\n private assertValidResponse(\n request: EvaluatePermissionRequestBatch,\n json: any,\n ): asserts json is EvaluatePermissionResponseBatch {\n const authorizedResponses = responseSchema.parse(json);\n const responseIds = authorizedResponses.items.map(r => r.id);\n const hasAllRequestIds = request.items.every(r =>\n responseIds.includes(r.id),\n );\n if (!hasAllRequestIds) {\n throw new Error(\n 'Unexpected authorization response from permission-backend',\n );\n }\n }\n}\n"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@backstage/plugin-permission-common",
3
3
  "description": "Isomorphic types and client for Backstage permissions and authorization",
4
- "version": "0.0.0-nightly-20220324023116",
4
+ "version": "0.0.0-nightly-20220327022954",
5
5
  "main": "dist/index.cjs.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "publishConfig": {
@@ -48,7 +48,7 @@
48
48
  "zod": "^3.11.6"
49
49
  },
50
50
  "devDependencies": {
51
- "@backstage/cli": "^0.0.0-nightly-20220324023116",
51
+ "@backstage/cli": "^0.0.0-nightly-20220327022954",
52
52
  "@types/jest": "^26.0.7",
53
53
  "msw": "^0.35.0"
54
54
  },