@backstage/plugin-permission-common 0.9.0-next.0 → 0.9.0

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,5 +1,20 @@
1
1
  # @backstage/plugin-permission-common
2
2
 
3
+ ## 0.9.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 4da2965: Fixed an issue causing the `PermissionClient` to exhaust the request body size limit too quickly when making many requests.
8
+
9
+ ### Patch Changes
10
+
11
+ - 37328b1: Fixed an issue causing `PermissionClient` to throw an error when authorizing basic permissions with the `permission.EXPERIMENTAL_enableBatchedRequests` config enabled.
12
+ - 72d019d: Removed various typos
13
+ - Updated dependencies
14
+ - @backstage/config@1.3.2
15
+ - @backstage/errors@1.2.7
16
+ - @backstage/types@1.2.1
17
+
3
18
  ## 0.9.0-next.0
4
19
 
5
20
  ### Minor Changes
@@ -47,7 +47,7 @@ const authorizePermissionResponseBatchSchema = zod.z.object({
47
47
  zod.z.literal(api.AuthorizeResult.DENY)
48
48
  ])
49
49
  )
50
- });
50
+ }).or(authorizePermissionResponseSchema);
51
51
  const queryPermissionResponseSchema = zod.z.union([
52
52
  zod.z.object({
53
53
  result: zod.z.literal(api.AuthorizeResult.ALLOW).or(zod.z.literal(api.AuthorizeResult.DENY))
@@ -160,9 +160,12 @@ class PermissionClient {
160
160
  return queries.map((query) => {
161
161
  const { id } = request[query.permission.name];
162
162
  const item = responsesById[id];
163
- return {
164
- result: query.resourceRef ? item.result.shift() : item.result[0]
165
- };
163
+ if (Array.isArray(item.result)) {
164
+ return {
165
+ result: query.resourceRef ? item.result.shift() : item.result[0]
166
+ };
167
+ }
168
+ return { result: item.result };
166
169
  });
167
170
  }
168
171
  async makeRawRequest(request, itemSchema, options) {
@@ -1 +1 @@
1
- {"version":3,"file":"PermissionClient.cjs.js","sources":["../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 { 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 PermissionMessageBatch,\n PermissionCriteria,\n PermissionCondition,\n PermissionEvaluator,\n QueryPermissionRequest,\n AuthorizePermissionRequest,\n AuthorizePermissionResponse,\n QueryPermissionResponse,\n IdentifiedPermissionMessage,\n} from './types/api';\nimport { DiscoveryApi } from './types/discovery';\nimport {\n AuthorizeRequestOptions,\n BasicPermission,\n ResourcePermission,\n} from './types/permission';\nimport { isResourcePermission } from './permissions';\n\nconst permissionCriteriaSchema: z.ZodSchema<\n PermissionCriteria<PermissionCondition>\n> = z.lazy(() =>\n z\n .object({\n rule: z.string(),\n resourceType: z.string(),\n params: z.record(z.any()).optional(),\n })\n .or(z.object({ anyOf: z.array(permissionCriteriaSchema).nonempty() }))\n .or(z.object({ allOf: z.array(permissionCriteriaSchema).nonempty() }))\n .or(z.object({ not: permissionCriteriaSchema })),\n);\n\nconst authorizePermissionResponseSchema: z.ZodSchema<AuthorizePermissionResponse> =\n z.object({\n result: z\n .literal(AuthorizeResult.ALLOW)\n .or(z.literal(AuthorizeResult.DENY)),\n });\n\nconst authorizePermissionResponseBatchSchema = z.object({\n result: z.array(\n z.union([\n z.literal(AuthorizeResult.ALLOW),\n z.literal(AuthorizeResult.DENY),\n ]),\n ),\n});\n\nconst queryPermissionResponseSchema: z.ZodSchema<QueryPermissionResponse> =\n z.union([\n z.object({\n result: z\n .literal(AuthorizeResult.ALLOW)\n .or(z.literal(AuthorizeResult.DENY)),\n }),\n z.object({\n result: z.literal(AuthorizeResult.CONDITIONAL),\n pluginId: z.string(),\n resourceType: z.string(),\n conditions: permissionCriteriaSchema,\n }),\n ]);\n\nconst responseSchema = <T>(\n itemSchema: z.ZodSchema<T>,\n ids: Set<string>,\n): z.ZodSchema<PermissionMessageBatch<T>> =>\n z.object({\n items: z\n .array(\n z.intersection(\n z.object({\n id: z.string(),\n }),\n itemSchema,\n ),\n )\n .refine(\n items =>\n items.length === ids.size && items.every(({ id }) => ids.has(id)),\n {\n message: 'Items in response do not match request',\n },\n ),\n });\n\n/**\n * Options for {@link PermissionClient} requests.\n *\n * @public\n */\nexport type PermissionClientRequestOptions = {\n token?: string;\n};\n\n/**\n * An isomorphic client for requesting authorization for Backstage permissions.\n * @public\n */\nexport class PermissionClient implements PermissionEvaluator {\n private readonly enabled: boolean;\n private readonly discovery: DiscoveryApi;\n private readonly enableBatchedRequests: boolean;\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 this.enableBatchedRequests =\n options.config.getOptionalBoolean(\n 'permission.EXPERIMENTAL_enableBatchedRequests',\n ) ?? false;\n }\n\n /**\n * {@inheritdoc PermissionEvaluator.authorize}\n */\n async authorize(\n requests: AuthorizePermissionRequest[],\n options?: PermissionClientRequestOptions,\n ): Promise<AuthorizePermissionResponse[]> {\n if (!this.enabled) {\n return requests.map(_ => ({ result: AuthorizeResult.ALLOW as const }));\n }\n\n if (this.enableBatchedRequests) {\n return this.makeBatchedRequest(requests, options);\n }\n\n return this.makeRequest(\n requests,\n authorizePermissionResponseSchema,\n options,\n );\n }\n\n /**\n * {@inheritdoc PermissionEvaluator.authorizeConditional}\n */\n async authorizeConditional(\n queries: QueryPermissionRequest[],\n options?: PermissionClientRequestOptions,\n ): Promise<QueryPermissionResponse[]> {\n if (!this.enabled) {\n return queries.map(_ => ({ result: AuthorizeResult.ALLOW as const }));\n }\n\n return this.makeRequest(queries, queryPermissionResponseSchema, options);\n }\n\n private async makeRequest<TQuery, TResult>(\n queries: TQuery[],\n itemSchema: z.ZodSchema<TResult>,\n options?: AuthorizeRequestOptions,\n ) {\n const request: PermissionMessageBatch<TQuery> = {\n items: queries.map(query => ({\n id: uuid.v4(),\n ...query,\n })),\n };\n\n const parsedResponse = await this.makeRawRequest(\n request,\n itemSchema,\n options,\n );\n\n const responsesById = parsedResponse.items.reduce((acc, r) => {\n acc[r.id] = r;\n return acc;\n }, {} as Record<string, z.infer<typeof itemSchema>>);\n\n return request.items.map(query => responsesById[query.id]);\n }\n\n private async makeBatchedRequest(\n queries: AuthorizePermissionRequest[],\n options?: AuthorizeRequestOptions,\n ) {\n const request: Record<string, BatchedAuthorizePermissionRequest> = {};\n\n for (const query of queries) {\n const { permission, resourceRef } = query;\n\n if (isResourcePermission(permission)) {\n request[permission.name] ||= {\n permission,\n resourceRef: [],\n id: uuid.v4(),\n };\n\n if (resourceRef) {\n request[permission.name].resourceRef?.push(resourceRef);\n }\n } else {\n request[permission.name] ||= {\n permission,\n id: uuid.v4(),\n };\n }\n }\n\n const parsedResponse = await this.makeRawRequest(\n { items: Object.values(request) },\n authorizePermissionResponseBatchSchema,\n options,\n );\n\n const responsesById = parsedResponse.items.reduce((acc, r) => {\n acc[r.id] = r;\n return acc;\n }, {} as Record<string, (typeof parsedResponse)['items'][number]>);\n\n return queries.map(query => {\n const { id } = request[query.permission.name];\n\n const item = responsesById[id];\n return {\n result: query.resourceRef ? item.result.shift()! : item.result[0],\n };\n });\n }\n\n private async makeRawRequest<TQuery, TResult>(\n request: PermissionMessageBatch<TQuery>,\n itemSchema: z.ZodSchema<TResult>,\n options?: AuthorizeRequestOptions,\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\n return responseSchema(\n itemSchema,\n new Set(request.items.map(({ id }) => id)),\n ).parse(responseBody);\n }\n\n private getAuthorizationHeader(token?: string): Record<string, string> {\n return token ? { Authorization: `Bearer ${token}` } : {};\n }\n}\n\n/**\n * @internal\n */\nexport type BatchedAuthorizePermissionRequest = IdentifiedPermissionMessage<\n | {\n permission: BasicPermission;\n resourceRef?: undefined;\n }\n | { permission: ResourcePermission; resourceRef: string[] }\n>;\n"],"names":["z","AuthorizeResult","uuid","isResourcePermission","fetch","ResponseError"],"mappings":"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"}
1
+ {"version":3,"file":"PermissionClient.cjs.js","sources":["../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 { 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 PermissionMessageBatch,\n PermissionCriteria,\n PermissionCondition,\n PermissionEvaluator,\n QueryPermissionRequest,\n AuthorizePermissionRequest,\n AuthorizePermissionResponse,\n QueryPermissionResponse,\n IdentifiedPermissionMessage,\n} from './types/api';\nimport { DiscoveryApi } from './types/discovery';\nimport {\n AuthorizeRequestOptions,\n BasicPermission,\n ResourcePermission,\n} from './types/permission';\nimport { isResourcePermission } from './permissions';\n\nconst permissionCriteriaSchema: z.ZodSchema<\n PermissionCriteria<PermissionCondition>\n> = z.lazy(() =>\n z\n .object({\n rule: z.string(),\n resourceType: z.string(),\n params: z.record(z.any()).optional(),\n })\n .or(z.object({ anyOf: z.array(permissionCriteriaSchema).nonempty() }))\n .or(z.object({ allOf: z.array(permissionCriteriaSchema).nonempty() }))\n .or(z.object({ not: permissionCriteriaSchema })),\n);\n\nconst authorizePermissionResponseSchema: z.ZodSchema<AuthorizePermissionResponse> =\n z.object({\n result: z\n .literal(AuthorizeResult.ALLOW)\n .or(z.literal(AuthorizeResult.DENY)),\n });\n\nconst authorizePermissionResponseBatchSchema = z\n .object({\n result: z.array(\n z.union([\n z.literal(AuthorizeResult.ALLOW),\n z.literal(AuthorizeResult.DENY),\n ]),\n ),\n })\n .or(authorizePermissionResponseSchema);\n\nconst queryPermissionResponseSchema: z.ZodSchema<QueryPermissionResponse> =\n z.union([\n z.object({\n result: z\n .literal(AuthorizeResult.ALLOW)\n .or(z.literal(AuthorizeResult.DENY)),\n }),\n z.object({\n result: z.literal(AuthorizeResult.CONDITIONAL),\n pluginId: z.string(),\n resourceType: z.string(),\n conditions: permissionCriteriaSchema,\n }),\n ]);\n\nconst responseSchema = <T>(\n itemSchema: z.ZodSchema<T>,\n ids: Set<string>,\n): z.ZodSchema<PermissionMessageBatch<T>> =>\n z.object({\n items: z\n .array(\n z.intersection(\n z.object({\n id: z.string(),\n }),\n itemSchema,\n ),\n )\n .refine(\n items =>\n items.length === ids.size && items.every(({ id }) => ids.has(id)),\n {\n message: 'Items in response do not match request',\n },\n ),\n });\n\n/**\n * Options for {@link PermissionClient} requests.\n *\n * @public\n */\nexport type PermissionClientRequestOptions = {\n token?: string;\n};\n\n/**\n * An isomorphic client for requesting authorization for Backstage permissions.\n * @public\n */\nexport class PermissionClient implements PermissionEvaluator {\n private readonly enabled: boolean;\n private readonly discovery: DiscoveryApi;\n private readonly enableBatchedRequests: boolean;\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 this.enableBatchedRequests =\n options.config.getOptionalBoolean(\n 'permission.EXPERIMENTAL_enableBatchedRequests',\n ) ?? false;\n }\n\n /**\n * {@inheritdoc PermissionEvaluator.authorize}\n */\n async authorize(\n requests: AuthorizePermissionRequest[],\n options?: PermissionClientRequestOptions,\n ): Promise<AuthorizePermissionResponse[]> {\n if (!this.enabled) {\n return requests.map(_ => ({ result: AuthorizeResult.ALLOW as const }));\n }\n\n if (this.enableBatchedRequests) {\n return this.makeBatchedRequest(requests, options);\n }\n\n return this.makeRequest(\n requests,\n authorizePermissionResponseSchema,\n options,\n );\n }\n\n /**\n * {@inheritdoc PermissionEvaluator.authorizeConditional}\n */\n async authorizeConditional(\n queries: QueryPermissionRequest[],\n options?: PermissionClientRequestOptions,\n ): Promise<QueryPermissionResponse[]> {\n if (!this.enabled) {\n return queries.map(_ => ({ result: AuthorizeResult.ALLOW as const }));\n }\n\n return this.makeRequest(queries, queryPermissionResponseSchema, options);\n }\n\n private async makeRequest<TQuery, TResult>(\n queries: TQuery[],\n itemSchema: z.ZodSchema<TResult>,\n options?: AuthorizeRequestOptions,\n ) {\n const request: PermissionMessageBatch<TQuery> = {\n items: queries.map(query => ({\n id: uuid.v4(),\n ...query,\n })),\n };\n\n const parsedResponse = await this.makeRawRequest(\n request,\n itemSchema,\n options,\n );\n\n const responsesById = parsedResponse.items.reduce((acc, r) => {\n acc[r.id] = r;\n return acc;\n }, {} as Record<string, z.infer<typeof itemSchema>>);\n\n return request.items.map(query => responsesById[query.id]);\n }\n\n private async makeBatchedRequest(\n queries: AuthorizePermissionRequest[],\n options?: AuthorizeRequestOptions,\n ) {\n const request: Record<string, BatchedAuthorizePermissionRequest> = {};\n\n for (const query of queries) {\n const { permission, resourceRef } = query;\n\n if (isResourcePermission(permission)) {\n request[permission.name] ||= {\n permission,\n resourceRef: [],\n id: uuid.v4(),\n };\n\n if (resourceRef) {\n request[permission.name].resourceRef?.push(resourceRef);\n }\n } else {\n request[permission.name] ||= {\n permission,\n id: uuid.v4(),\n };\n }\n }\n\n const parsedResponse = await this.makeRawRequest(\n { items: Object.values(request) },\n authorizePermissionResponseBatchSchema,\n options,\n );\n\n const responsesById = parsedResponse.items.reduce((acc, r) => {\n acc[r.id] = r;\n return acc;\n }, {} as Record<string, (typeof parsedResponse)['items'][number]>);\n\n return queries.map(query => {\n const { id } = request[query.permission.name];\n\n const item = responsesById[id];\n\n if (Array.isArray(item.result)) {\n return {\n result: query.resourceRef ? item.result.shift()! : item.result[0],\n };\n }\n return { result: item.result };\n });\n }\n\n private async makeRawRequest<TQuery, TResult>(\n request: PermissionMessageBatch<TQuery>,\n itemSchema: z.ZodSchema<TResult>,\n options?: AuthorizeRequestOptions,\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\n return responseSchema(\n itemSchema,\n new Set(request.items.map(({ id }) => id)),\n ).parse(responseBody);\n }\n\n private getAuthorizationHeader(token?: string): Record<string, string> {\n return token ? { Authorization: `Bearer ${token}` } : {};\n }\n}\n\n/**\n * @internal\n */\nexport type BatchedAuthorizePermissionRequest = IdentifiedPermissionMessage<\n | {\n permission: BasicPermission;\n resourceRef?: undefined;\n }\n | { permission: ResourcePermission; resourceRef: string[] }\n>;\n"],"names":["z","AuthorizeResult","uuid","isResourcePermission","fetch","ResponseError"],"mappings":"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"}
@@ -22,7 +22,7 @@ const authorizePermissionResponseBatchSchema = z.object({
22
22
  z.literal(AuthorizeResult.DENY)
23
23
  ])
24
24
  )
25
- });
25
+ }).or(authorizePermissionResponseSchema);
26
26
  const queryPermissionResponseSchema = z.union([
27
27
  z.object({
28
28
  result: z.literal(AuthorizeResult.ALLOW).or(z.literal(AuthorizeResult.DENY))
@@ -135,9 +135,12 @@ class PermissionClient {
135
135
  return queries.map((query) => {
136
136
  const { id } = request[query.permission.name];
137
137
  const item = responsesById[id];
138
- return {
139
- result: query.resourceRef ? item.result.shift() : item.result[0]
140
- };
138
+ if (Array.isArray(item.result)) {
139
+ return {
140
+ result: query.resourceRef ? item.result.shift() : item.result[0]
141
+ };
142
+ }
143
+ return { result: item.result };
141
144
  });
142
145
  }
143
146
  async makeRawRequest(request, itemSchema, options) {
@@ -1 +1 @@
1
- {"version":3,"file":"PermissionClient.esm.js","sources":["../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 { 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 PermissionMessageBatch,\n PermissionCriteria,\n PermissionCondition,\n PermissionEvaluator,\n QueryPermissionRequest,\n AuthorizePermissionRequest,\n AuthorizePermissionResponse,\n QueryPermissionResponse,\n IdentifiedPermissionMessage,\n} from './types/api';\nimport { DiscoveryApi } from './types/discovery';\nimport {\n AuthorizeRequestOptions,\n BasicPermission,\n ResourcePermission,\n} from './types/permission';\nimport { isResourcePermission } from './permissions';\n\nconst permissionCriteriaSchema: z.ZodSchema<\n PermissionCriteria<PermissionCondition>\n> = z.lazy(() =>\n z\n .object({\n rule: z.string(),\n resourceType: z.string(),\n params: z.record(z.any()).optional(),\n })\n .or(z.object({ anyOf: z.array(permissionCriteriaSchema).nonempty() }))\n .or(z.object({ allOf: z.array(permissionCriteriaSchema).nonempty() }))\n .or(z.object({ not: permissionCriteriaSchema })),\n);\n\nconst authorizePermissionResponseSchema: z.ZodSchema<AuthorizePermissionResponse> =\n z.object({\n result: z\n .literal(AuthorizeResult.ALLOW)\n .or(z.literal(AuthorizeResult.DENY)),\n });\n\nconst authorizePermissionResponseBatchSchema = z.object({\n result: z.array(\n z.union([\n z.literal(AuthorizeResult.ALLOW),\n z.literal(AuthorizeResult.DENY),\n ]),\n ),\n});\n\nconst queryPermissionResponseSchema: z.ZodSchema<QueryPermissionResponse> =\n z.union([\n z.object({\n result: z\n .literal(AuthorizeResult.ALLOW)\n .or(z.literal(AuthorizeResult.DENY)),\n }),\n z.object({\n result: z.literal(AuthorizeResult.CONDITIONAL),\n pluginId: z.string(),\n resourceType: z.string(),\n conditions: permissionCriteriaSchema,\n }),\n ]);\n\nconst responseSchema = <T>(\n itemSchema: z.ZodSchema<T>,\n ids: Set<string>,\n): z.ZodSchema<PermissionMessageBatch<T>> =>\n z.object({\n items: z\n .array(\n z.intersection(\n z.object({\n id: z.string(),\n }),\n itemSchema,\n ),\n )\n .refine(\n items =>\n items.length === ids.size && items.every(({ id }) => ids.has(id)),\n {\n message: 'Items in response do not match request',\n },\n ),\n });\n\n/**\n * Options for {@link PermissionClient} requests.\n *\n * @public\n */\nexport type PermissionClientRequestOptions = {\n token?: string;\n};\n\n/**\n * An isomorphic client for requesting authorization for Backstage permissions.\n * @public\n */\nexport class PermissionClient implements PermissionEvaluator {\n private readonly enabled: boolean;\n private readonly discovery: DiscoveryApi;\n private readonly enableBatchedRequests: boolean;\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 this.enableBatchedRequests =\n options.config.getOptionalBoolean(\n 'permission.EXPERIMENTAL_enableBatchedRequests',\n ) ?? false;\n }\n\n /**\n * {@inheritdoc PermissionEvaluator.authorize}\n */\n async authorize(\n requests: AuthorizePermissionRequest[],\n options?: PermissionClientRequestOptions,\n ): Promise<AuthorizePermissionResponse[]> {\n if (!this.enabled) {\n return requests.map(_ => ({ result: AuthorizeResult.ALLOW as const }));\n }\n\n if (this.enableBatchedRequests) {\n return this.makeBatchedRequest(requests, options);\n }\n\n return this.makeRequest(\n requests,\n authorizePermissionResponseSchema,\n options,\n );\n }\n\n /**\n * {@inheritdoc PermissionEvaluator.authorizeConditional}\n */\n async authorizeConditional(\n queries: QueryPermissionRequest[],\n options?: PermissionClientRequestOptions,\n ): Promise<QueryPermissionResponse[]> {\n if (!this.enabled) {\n return queries.map(_ => ({ result: AuthorizeResult.ALLOW as const }));\n }\n\n return this.makeRequest(queries, queryPermissionResponseSchema, options);\n }\n\n private async makeRequest<TQuery, TResult>(\n queries: TQuery[],\n itemSchema: z.ZodSchema<TResult>,\n options?: AuthorizeRequestOptions,\n ) {\n const request: PermissionMessageBatch<TQuery> = {\n items: queries.map(query => ({\n id: uuid.v4(),\n ...query,\n })),\n };\n\n const parsedResponse = await this.makeRawRequest(\n request,\n itemSchema,\n options,\n );\n\n const responsesById = parsedResponse.items.reduce((acc, r) => {\n acc[r.id] = r;\n return acc;\n }, {} as Record<string, z.infer<typeof itemSchema>>);\n\n return request.items.map(query => responsesById[query.id]);\n }\n\n private async makeBatchedRequest(\n queries: AuthorizePermissionRequest[],\n options?: AuthorizeRequestOptions,\n ) {\n const request: Record<string, BatchedAuthorizePermissionRequest> = {};\n\n for (const query of queries) {\n const { permission, resourceRef } = query;\n\n if (isResourcePermission(permission)) {\n request[permission.name] ||= {\n permission,\n resourceRef: [],\n id: uuid.v4(),\n };\n\n if (resourceRef) {\n request[permission.name].resourceRef?.push(resourceRef);\n }\n } else {\n request[permission.name] ||= {\n permission,\n id: uuid.v4(),\n };\n }\n }\n\n const parsedResponse = await this.makeRawRequest(\n { items: Object.values(request) },\n authorizePermissionResponseBatchSchema,\n options,\n );\n\n const responsesById = parsedResponse.items.reduce((acc, r) => {\n acc[r.id] = r;\n return acc;\n }, {} as Record<string, (typeof parsedResponse)['items'][number]>);\n\n return queries.map(query => {\n const { id } = request[query.permission.name];\n\n const item = responsesById[id];\n return {\n result: query.resourceRef ? item.result.shift()! : item.result[0],\n };\n });\n }\n\n private async makeRawRequest<TQuery, TResult>(\n request: PermissionMessageBatch<TQuery>,\n itemSchema: z.ZodSchema<TResult>,\n options?: AuthorizeRequestOptions,\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\n return responseSchema(\n itemSchema,\n new Set(request.items.map(({ id }) => id)),\n ).parse(responseBody);\n }\n\n private getAuthorizationHeader(token?: string): Record<string, string> {\n return token ? { Authorization: `Bearer ${token}` } : {};\n }\n}\n\n/**\n * @internal\n */\nexport type BatchedAuthorizePermissionRequest = IdentifiedPermissionMessage<\n | {\n permission: BasicPermission;\n resourceRef?: undefined;\n }\n | { permission: ResourcePermission; resourceRef: string[] }\n>;\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"PermissionClient.esm.js","sources":["../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 { 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 PermissionMessageBatch,\n PermissionCriteria,\n PermissionCondition,\n PermissionEvaluator,\n QueryPermissionRequest,\n AuthorizePermissionRequest,\n AuthorizePermissionResponse,\n QueryPermissionResponse,\n IdentifiedPermissionMessage,\n} from './types/api';\nimport { DiscoveryApi } from './types/discovery';\nimport {\n AuthorizeRequestOptions,\n BasicPermission,\n ResourcePermission,\n} from './types/permission';\nimport { isResourcePermission } from './permissions';\n\nconst permissionCriteriaSchema: z.ZodSchema<\n PermissionCriteria<PermissionCondition>\n> = z.lazy(() =>\n z\n .object({\n rule: z.string(),\n resourceType: z.string(),\n params: z.record(z.any()).optional(),\n })\n .or(z.object({ anyOf: z.array(permissionCriteriaSchema).nonempty() }))\n .or(z.object({ allOf: z.array(permissionCriteriaSchema).nonempty() }))\n .or(z.object({ not: permissionCriteriaSchema })),\n);\n\nconst authorizePermissionResponseSchema: z.ZodSchema<AuthorizePermissionResponse> =\n z.object({\n result: z\n .literal(AuthorizeResult.ALLOW)\n .or(z.literal(AuthorizeResult.DENY)),\n });\n\nconst authorizePermissionResponseBatchSchema = z\n .object({\n result: z.array(\n z.union([\n z.literal(AuthorizeResult.ALLOW),\n z.literal(AuthorizeResult.DENY),\n ]),\n ),\n })\n .or(authorizePermissionResponseSchema);\n\nconst queryPermissionResponseSchema: z.ZodSchema<QueryPermissionResponse> =\n z.union([\n z.object({\n result: z\n .literal(AuthorizeResult.ALLOW)\n .or(z.literal(AuthorizeResult.DENY)),\n }),\n z.object({\n result: z.literal(AuthorizeResult.CONDITIONAL),\n pluginId: z.string(),\n resourceType: z.string(),\n conditions: permissionCriteriaSchema,\n }),\n ]);\n\nconst responseSchema = <T>(\n itemSchema: z.ZodSchema<T>,\n ids: Set<string>,\n): z.ZodSchema<PermissionMessageBatch<T>> =>\n z.object({\n items: z\n .array(\n z.intersection(\n z.object({\n id: z.string(),\n }),\n itemSchema,\n ),\n )\n .refine(\n items =>\n items.length === ids.size && items.every(({ id }) => ids.has(id)),\n {\n message: 'Items in response do not match request',\n },\n ),\n });\n\n/**\n * Options for {@link PermissionClient} requests.\n *\n * @public\n */\nexport type PermissionClientRequestOptions = {\n token?: string;\n};\n\n/**\n * An isomorphic client for requesting authorization for Backstage permissions.\n * @public\n */\nexport class PermissionClient implements PermissionEvaluator {\n private readonly enabled: boolean;\n private readonly discovery: DiscoveryApi;\n private readonly enableBatchedRequests: boolean;\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 this.enableBatchedRequests =\n options.config.getOptionalBoolean(\n 'permission.EXPERIMENTAL_enableBatchedRequests',\n ) ?? false;\n }\n\n /**\n * {@inheritdoc PermissionEvaluator.authorize}\n */\n async authorize(\n requests: AuthorizePermissionRequest[],\n options?: PermissionClientRequestOptions,\n ): Promise<AuthorizePermissionResponse[]> {\n if (!this.enabled) {\n return requests.map(_ => ({ result: AuthorizeResult.ALLOW as const }));\n }\n\n if (this.enableBatchedRequests) {\n return this.makeBatchedRequest(requests, options);\n }\n\n return this.makeRequest(\n requests,\n authorizePermissionResponseSchema,\n options,\n );\n }\n\n /**\n * {@inheritdoc PermissionEvaluator.authorizeConditional}\n */\n async authorizeConditional(\n queries: QueryPermissionRequest[],\n options?: PermissionClientRequestOptions,\n ): Promise<QueryPermissionResponse[]> {\n if (!this.enabled) {\n return queries.map(_ => ({ result: AuthorizeResult.ALLOW as const }));\n }\n\n return this.makeRequest(queries, queryPermissionResponseSchema, options);\n }\n\n private async makeRequest<TQuery, TResult>(\n queries: TQuery[],\n itemSchema: z.ZodSchema<TResult>,\n options?: AuthorizeRequestOptions,\n ) {\n const request: PermissionMessageBatch<TQuery> = {\n items: queries.map(query => ({\n id: uuid.v4(),\n ...query,\n })),\n };\n\n const parsedResponse = await this.makeRawRequest(\n request,\n itemSchema,\n options,\n );\n\n const responsesById = parsedResponse.items.reduce((acc, r) => {\n acc[r.id] = r;\n return acc;\n }, {} as Record<string, z.infer<typeof itemSchema>>);\n\n return request.items.map(query => responsesById[query.id]);\n }\n\n private async makeBatchedRequest(\n queries: AuthorizePermissionRequest[],\n options?: AuthorizeRequestOptions,\n ) {\n const request: Record<string, BatchedAuthorizePermissionRequest> = {};\n\n for (const query of queries) {\n const { permission, resourceRef } = query;\n\n if (isResourcePermission(permission)) {\n request[permission.name] ||= {\n permission,\n resourceRef: [],\n id: uuid.v4(),\n };\n\n if (resourceRef) {\n request[permission.name].resourceRef?.push(resourceRef);\n }\n } else {\n request[permission.name] ||= {\n permission,\n id: uuid.v4(),\n };\n }\n }\n\n const parsedResponse = await this.makeRawRequest(\n { items: Object.values(request) },\n authorizePermissionResponseBatchSchema,\n options,\n );\n\n const responsesById = parsedResponse.items.reduce((acc, r) => {\n acc[r.id] = r;\n return acc;\n }, {} as Record<string, (typeof parsedResponse)['items'][number]>);\n\n return queries.map(query => {\n const { id } = request[query.permission.name];\n\n const item = responsesById[id];\n\n if (Array.isArray(item.result)) {\n return {\n result: query.resourceRef ? item.result.shift()! : item.result[0],\n };\n }\n return { result: item.result };\n });\n }\n\n private async makeRawRequest<TQuery, TResult>(\n request: PermissionMessageBatch<TQuery>,\n itemSchema: z.ZodSchema<TResult>,\n options?: AuthorizeRequestOptions,\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\n return responseSchema(\n itemSchema,\n new Set(request.items.map(({ id }) => id)),\n ).parse(responseBody);\n }\n\n private getAuthorizationHeader(token?: string): Record<string, string> {\n return token ? { Authorization: `Bearer ${token}` } : {};\n }\n}\n\n/**\n * @internal\n */\nexport type BatchedAuthorizePermissionRequest = IdentifiedPermissionMessage<\n | {\n permission: BasicPermission;\n resourceRef?: undefined;\n }\n | { permission: ResourcePermission; resourceRef: string[] }\n>;\n"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@backstage/plugin-permission-common",
3
- "version": "0.9.0-next.0",
3
+ "version": "0.9.0",
4
4
  "description": "Isomorphic types and client for Backstage permissions and authorization",
5
5
  "backstage": {
6
6
  "role": "common-library",
@@ -48,16 +48,16 @@
48
48
  "test": "backstage-cli package test"
49
49
  },
50
50
  "dependencies": {
51
- "@backstage/config": "1.3.2",
52
- "@backstage/errors": "1.2.7",
53
- "@backstage/types": "1.2.1",
51
+ "@backstage/config": "^1.3.2",
52
+ "@backstage/errors": "^1.2.7",
53
+ "@backstage/types": "^1.2.1",
54
54
  "cross-fetch": "^4.0.0",
55
55
  "uuid": "^11.0.0",
56
56
  "zod": "^3.22.4",
57
57
  "zod-to-json-schema": "^3.20.4"
58
58
  },
59
59
  "devDependencies": {
60
- "@backstage/cli": "0.32.1-next.1",
60
+ "@backstage/cli": "^0.32.1",
61
61
  "msw": "^1.0.0"
62
62
  },
63
63
  "configSchema": "config.d.ts",