@backstage/plugin-permission-backend 0.5.37 → 0.5.38
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 +6 -0
- package/alpha/package.json +1 -1
- package/dist/alpha.cjs.js +2 -2
- package/dist/cjs/{router-ced2cd8a.cjs.js → router-CjGokdX5.cjs.js} +11 -13
- package/dist/cjs/router-CjGokdX5.cjs.js.map +1 -0
- package/dist/index.cjs.js +1 -3
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/package.json +1 -1
- package/dist/cjs/router-ced2cd8a.cjs.js.map +0 -1
package/CHANGELOG.md
CHANGED
package/alpha/package.json
CHANGED
package/dist/alpha.cjs.js
CHANGED
|
@@ -5,7 +5,7 @@ Object.defineProperty(exports, '__esModule', { value: true });
|
|
|
5
5
|
var backendCommon = require('@backstage/backend-common');
|
|
6
6
|
var backendPluginApi = require('@backstage/backend-plugin-api');
|
|
7
7
|
var alpha = require('@backstage/plugin-permission-node/alpha');
|
|
8
|
-
var router = require('./cjs/router-
|
|
8
|
+
var router = require('./cjs/router-CjGokdX5.cjs.js');
|
|
9
9
|
require('zod');
|
|
10
10
|
require('express');
|
|
11
11
|
require('express-promise-router');
|
|
@@ -82,5 +82,5 @@ const permissionPlugin = backendPluginApi.createBackendPlugin({
|
|
|
82
82
|
}
|
|
83
83
|
});
|
|
84
84
|
|
|
85
|
-
exports
|
|
85
|
+
exports.default = permissionPlugin;
|
|
86
86
|
//# sourceMappingURL=alpha.cjs.js.map
|
|
@@ -10,12 +10,12 @@ var fetch = require('node-fetch');
|
|
|
10
10
|
var lodash = require('lodash');
|
|
11
11
|
var DataLoader = require('dataloader');
|
|
12
12
|
|
|
13
|
-
function
|
|
13
|
+
function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
|
|
14
14
|
|
|
15
|
-
var express__default = /*#__PURE__*/
|
|
16
|
-
var Router__default = /*#__PURE__*/
|
|
17
|
-
var fetch__default = /*#__PURE__*/
|
|
18
|
-
var DataLoader__default = /*#__PURE__*/
|
|
15
|
+
var express__default = /*#__PURE__*/_interopDefaultCompat(express);
|
|
16
|
+
var Router__default = /*#__PURE__*/_interopDefaultCompat(Router);
|
|
17
|
+
var fetch__default = /*#__PURE__*/_interopDefaultCompat(fetch);
|
|
18
|
+
var DataLoader__default = /*#__PURE__*/_interopDefaultCompat(DataLoader);
|
|
19
19
|
|
|
20
20
|
var __defProp = Object.defineProperty;
|
|
21
21
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
@@ -45,7 +45,7 @@ class PermissionIntegrationClient {
|
|
|
45
45
|
onBehalfOf: credentials,
|
|
46
46
|
targetPluginId: pluginId
|
|
47
47
|
}).then((t) => t.token);
|
|
48
|
-
const response = await fetch__default
|
|
48
|
+
const response = await fetch__default.default(endpoint, {
|
|
49
49
|
method: "POST",
|
|
50
50
|
body: JSON.stringify({
|
|
51
51
|
items: decisions.map(
|
|
@@ -63,9 +63,7 @@ class PermissionIntegrationClient {
|
|
|
63
63
|
}
|
|
64
64
|
});
|
|
65
65
|
if (!response.ok) {
|
|
66
|
-
throw
|
|
67
|
-
`Unexpected response from plugin upstream when applying conditions. Expected 200 but got ${response.status} - ${response.statusText}`
|
|
68
|
-
);
|
|
66
|
+
throw await errors.ResponseError.fromResponse(response);
|
|
69
67
|
}
|
|
70
68
|
const result = responseSchema.parse(await response.json());
|
|
71
69
|
return result.items;
|
|
@@ -103,7 +101,7 @@ const evaluatePermissionRequestBatchSchema = zod.z.object({
|
|
|
103
101
|
});
|
|
104
102
|
const handleRequest = async (requests, policy, permissionIntegrationClient, credentials, auth, userInfo) => {
|
|
105
103
|
const applyConditionsLoaderFor = lodash.memoize((pluginId) => {
|
|
106
|
-
return new DataLoader__default
|
|
104
|
+
return new DataLoader__default.default(
|
|
107
105
|
(batch) => permissionIntegrationClient.applyConditions(pluginId, credentials, batch)
|
|
108
106
|
);
|
|
109
107
|
});
|
|
@@ -170,8 +168,8 @@ async function createRouter(options) {
|
|
|
170
168
|
discovery,
|
|
171
169
|
auth
|
|
172
170
|
});
|
|
173
|
-
const router = Router__default
|
|
174
|
-
router.use(express__default
|
|
171
|
+
const router = Router__default.default();
|
|
172
|
+
router.use(express__default.default.json());
|
|
175
173
|
router.get("/health", (_, response) => {
|
|
176
174
|
response.json({ status: "ok" });
|
|
177
175
|
});
|
|
@@ -205,4 +203,4 @@ async function createRouter(options) {
|
|
|
205
203
|
}
|
|
206
204
|
|
|
207
205
|
exports.createRouter = createRouter;
|
|
208
|
-
//# sourceMappingURL=router-
|
|
206
|
+
//# sourceMappingURL=router-CjGokdX5.cjs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"router-CjGokdX5.cjs.js","sources":["../../src/service/PermissionIntegrationClient.ts","../../src/service/router.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 fetch from 'node-fetch';\nimport { z } from 'zod';\nimport {\n AuthorizeResult,\n ConditionalPolicyDecision,\n} from '@backstage/plugin-permission-common';\nimport {\n ApplyConditionsRequestEntry,\n ApplyConditionsResponseEntry,\n} from '@backstage/plugin-permission-node';\nimport {\n AuthService,\n BackstageCredentials,\n DiscoveryService,\n} from '@backstage/backend-plugin-api';\nimport { ResponseError } from '@backstage/errors';\n\nconst responseSchema = z.object({\n items: z.array(\n z.object({\n id: z.string(),\n result: z\n .literal(AuthorizeResult.ALLOW)\n .or(z.literal(AuthorizeResult.DENY)),\n }),\n ),\n});\n\nexport type ResourcePolicyDecision = ConditionalPolicyDecision & {\n resourceRef: string;\n};\n\nexport class PermissionIntegrationClient {\n private readonly discovery: DiscoveryService;\n private readonly auth: AuthService;\n\n constructor(options: { discovery: DiscoveryService; auth: AuthService }) {\n this.discovery = options.discovery;\n this.auth = options.auth;\n }\n\n async applyConditions(\n pluginId: string,\n credentials: BackstageCredentials,\n decisions: readonly ApplyConditionsRequestEntry[],\n ): Promise<ApplyConditionsResponseEntry[]> {\n const baseUrl = await this.discovery.getBaseUrl(pluginId);\n const endpoint = `${baseUrl}/.well-known/backstage/permissions/apply-conditions`;\n\n const token = this.auth.isPrincipal(credentials, 'none')\n ? undefined\n : await this.auth\n .getPluginRequestToken({\n onBehalfOf: credentials,\n targetPluginId: pluginId,\n })\n .then(t => t.token);\n\n const response = await fetch(endpoint, {\n method: 'POST',\n body: JSON.stringify({\n items: decisions.map(\n ({ id, resourceRef, resourceType, conditions }) => ({\n id,\n resourceRef,\n resourceType,\n conditions,\n }),\n ),\n }),\n headers: {\n ...(token ? { authorization: `Bearer ${token}` } : {}),\n 'content-type': 'application/json',\n },\n });\n\n if (!response.ok) {\n throw await ResponseError.fromResponse(response);\n }\n\n const result = responseSchema.parse(await response.json());\n\n return result.items;\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 { z } from 'zod';\nimport express, { Request, Response } from 'express';\nimport Router from 'express-promise-router';\nimport { Logger } from 'winston';\nimport {\n createLegacyAuthAdapters,\n errorHandler,\n} from '@backstage/backend-common';\nimport { InputError } from '@backstage/errors';\nimport {\n BackstageIdentityResponse,\n IdentityApi,\n} from '@backstage/plugin-auth-node';\nimport {\n AuthorizeResult,\n EvaluatePermissionResponse,\n EvaluatePermissionRequest,\n IdentifiedPermissionMessage,\n EvaluatePermissionRequestBatch,\n EvaluatePermissionResponseBatch,\n isResourcePermission,\n PermissionAttributes,\n} from '@backstage/plugin-permission-common';\nimport {\n ApplyConditionsRequestEntry,\n ApplyConditionsResponseEntry,\n PermissionPolicy,\n} from '@backstage/plugin-permission-node';\nimport { PermissionIntegrationClient } from './PermissionIntegrationClient';\nimport { memoize } from 'lodash';\nimport DataLoader from 'dataloader';\nimport { Config } from '@backstage/config';\nimport {\n AuthService,\n BackstageCredentials,\n BackstageNonePrincipal,\n BackstageUserPrincipal,\n DiscoveryService,\n HttpAuthService,\n UserInfoService,\n} from '@backstage/backend-plugin-api';\n\nconst attributesSchema: z.ZodSchema<PermissionAttributes> = z.object({\n action: z\n .union([\n z.literal('create'),\n z.literal('read'),\n z.literal('update'),\n z.literal('delete'),\n ])\n .optional(),\n});\n\nconst permissionSchema = z.union([\n z.object({\n type: z.literal('basic'),\n name: z.string(),\n attributes: attributesSchema,\n }),\n z.object({\n type: z.literal('resource'),\n name: z.string(),\n attributes: attributesSchema,\n resourceType: z.string(),\n }),\n]);\n\nconst evaluatePermissionRequestSchema: z.ZodSchema<\n IdentifiedPermissionMessage<EvaluatePermissionRequest>\n> = z.object({\n id: z.string(),\n resourceRef: z.string().optional(),\n permission: permissionSchema,\n});\n\nconst evaluatePermissionRequestBatchSchema: z.ZodSchema<EvaluatePermissionRequestBatch> =\n z.object({\n items: z.array(evaluatePermissionRequestSchema),\n });\n\n/**\n * Options required when constructing a new {@link express#Router} using\n * {@link createRouter}.\n *\n * @public\n */\nexport interface RouterOptions {\n logger: Logger;\n discovery: DiscoveryService;\n policy: PermissionPolicy;\n identity?: IdentityApi;\n config: Config;\n auth?: AuthService;\n httpAuth?: HttpAuthService;\n userInfo?: UserInfoService;\n}\n\nconst handleRequest = async (\n requests: IdentifiedPermissionMessage<EvaluatePermissionRequest>[],\n policy: PermissionPolicy,\n permissionIntegrationClient: PermissionIntegrationClient,\n credentials: BackstageCredentials<\n BackstageNonePrincipal | BackstageUserPrincipal\n >,\n auth: AuthService,\n userInfo: UserInfoService,\n): Promise<IdentifiedPermissionMessage<EvaluatePermissionResponse>[]> => {\n const applyConditionsLoaderFor = memoize((pluginId: string) => {\n return new DataLoader<\n ApplyConditionsRequestEntry,\n ApplyConditionsResponseEntry\n >(batch =>\n permissionIntegrationClient.applyConditions(pluginId, credentials, batch),\n );\n });\n\n let user: BackstageIdentityResponse | undefined;\n if (auth.isPrincipal(credentials, 'user')) {\n const { ownershipEntityRefs } = await userInfo.getUserInfo(credentials);\n const { token } = await auth.getPluginRequestToken({\n onBehalfOf: credentials,\n targetPluginId: 'catalog', // TODO: unknown at this point\n });\n user = {\n identity: {\n type: 'user',\n userEntityRef: credentials.principal.userEntityRef,\n ownershipEntityRefs,\n },\n token,\n };\n }\n\n return Promise.all(\n requests.map(({ id, resourceRef, ...request }) =>\n policy.handle(request, user).then(decision => {\n if (decision.result !== AuthorizeResult.CONDITIONAL) {\n return {\n id,\n ...decision,\n };\n }\n\n if (!isResourcePermission(request.permission)) {\n throw new Error(\n `Conditional decision returned from permission policy for non-resource permission ${request.permission.name}`,\n );\n }\n\n if (decision.resourceType !== request.permission.resourceType) {\n throw new Error(\n `Invalid resource conditions returned from permission policy for permission ${request.permission.name}`,\n );\n }\n\n if (!resourceRef) {\n return {\n id,\n ...decision,\n };\n }\n\n return applyConditionsLoaderFor(decision.pluginId).load({\n id,\n resourceRef,\n ...decision,\n });\n }),\n ),\n );\n};\n\n/**\n * Creates a new {@link express#Router} which provides the backend API\n * for the permission system.\n *\n * @public\n */\nexport async function createRouter(\n options: RouterOptions,\n): Promise<express.Router> {\n const { policy, discovery, config, logger } = options;\n const { auth, httpAuth, userInfo } = createLegacyAuthAdapters(options);\n\n if (!config.getOptionalBoolean('permission.enabled')) {\n logger.warn(\n 'Permission backend started with permissions disabled. Enable permissions by setting permission.enabled=true.',\n );\n }\n\n const permissionIntegrationClient = new PermissionIntegrationClient({\n discovery,\n auth,\n });\n\n const router = Router();\n router.use(express.json());\n\n router.get('/health', (_, response) => {\n response.json({ status: 'ok' });\n });\n\n router.post(\n '/authorize',\n async (\n req: Request<EvaluatePermissionRequestBatch>,\n res: Response<EvaluatePermissionResponseBatch>,\n ) => {\n const credentials = await httpAuth.credentials(req, {\n allow: ['user', 'none'],\n });\n\n const parseResult = evaluatePermissionRequestBatchSchema.safeParse(\n req.body,\n );\n\n if (!parseResult.success) {\n throw new InputError(parseResult.error.toString());\n }\n\n const body = parseResult.data;\n\n res.json({\n items: await handleRequest(\n body.items,\n policy,\n permissionIntegrationClient,\n credentials,\n auth,\n userInfo,\n ),\n });\n },\n );\n\n router.use(errorHandler());\n\n return router;\n}\n"],"names":["z","AuthorizeResult","fetch","ResponseError","memoize","DataLoader","isResourcePermission","createLegacyAuthAdapters","Router","express","InputError","errorHandler"],"mappings":"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"}
|
package/dist/index.cjs.js
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
var router = require('./cjs/router-ced2cd8a.cjs.js');
|
|
3
|
+
var router = require('./cjs/router-CjGokdX5.cjs.js');
|
|
6
4
|
require('zod');
|
|
7
5
|
require('express');
|
|
8
6
|
require('express-promise-router');
|
package/dist/index.cjs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.cjs.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;"}
|
package/dist/index.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"router-ced2cd8a.cjs.js","sources":["../../src/service/PermissionIntegrationClient.ts","../../src/service/router.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 fetch from 'node-fetch';\nimport { z } from 'zod';\nimport {\n AuthorizeResult,\n ConditionalPolicyDecision,\n} from '@backstage/plugin-permission-common';\nimport {\n ApplyConditionsRequestEntry,\n ApplyConditionsResponseEntry,\n} from '@backstage/plugin-permission-node';\nimport {\n AuthService,\n BackstageCredentials,\n DiscoveryService,\n} from '@backstage/backend-plugin-api';\n\nconst responseSchema = z.object({\n items: z.array(\n z.object({\n id: z.string(),\n result: z\n .literal(AuthorizeResult.ALLOW)\n .or(z.literal(AuthorizeResult.DENY)),\n }),\n ),\n});\n\nexport type ResourcePolicyDecision = ConditionalPolicyDecision & {\n resourceRef: string;\n};\n\nexport class PermissionIntegrationClient {\n private readonly discovery: DiscoveryService;\n private readonly auth: AuthService;\n\n constructor(options: { discovery: DiscoveryService; auth: AuthService }) {\n this.discovery = options.discovery;\n this.auth = options.auth;\n }\n\n async applyConditions(\n pluginId: string,\n credentials: BackstageCredentials,\n decisions: readonly ApplyConditionsRequestEntry[],\n ): Promise<ApplyConditionsResponseEntry[]> {\n const baseUrl = await this.discovery.getBaseUrl(pluginId);\n const endpoint = `${baseUrl}/.well-known/backstage/permissions/apply-conditions`;\n\n const token = this.auth.isPrincipal(credentials, 'none')\n ? undefined\n : await this.auth\n .getPluginRequestToken({\n onBehalfOf: credentials,\n targetPluginId: pluginId,\n })\n .then(t => t.token);\n\n const response = await fetch(endpoint, {\n method: 'POST',\n body: JSON.stringify({\n items: decisions.map(\n ({ id, resourceRef, resourceType, conditions }) => ({\n id,\n resourceRef,\n resourceType,\n conditions,\n }),\n ),\n }),\n headers: {\n ...(token ? { authorization: `Bearer ${token}` } : {}),\n 'content-type': 'application/json',\n },\n });\n\n if (!response.ok) {\n throw new Error(\n `Unexpected response from plugin upstream when applying conditions. Expected 200 but got ${response.status} - ${response.statusText}`,\n );\n }\n\n const result = responseSchema.parse(await response.json());\n\n return result.items;\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 { z } from 'zod';\nimport express, { Request, Response } from 'express';\nimport Router from 'express-promise-router';\nimport { Logger } from 'winston';\nimport {\n createLegacyAuthAdapters,\n errorHandler,\n} from '@backstage/backend-common';\nimport { InputError } from '@backstage/errors';\nimport {\n BackstageIdentityResponse,\n IdentityApi,\n} from '@backstage/plugin-auth-node';\nimport {\n AuthorizeResult,\n EvaluatePermissionResponse,\n EvaluatePermissionRequest,\n IdentifiedPermissionMessage,\n EvaluatePermissionRequestBatch,\n EvaluatePermissionResponseBatch,\n isResourcePermission,\n PermissionAttributes,\n} from '@backstage/plugin-permission-common';\nimport {\n ApplyConditionsRequestEntry,\n ApplyConditionsResponseEntry,\n PermissionPolicy,\n} from '@backstage/plugin-permission-node';\nimport { PermissionIntegrationClient } from './PermissionIntegrationClient';\nimport { memoize } from 'lodash';\nimport DataLoader from 'dataloader';\nimport { Config } from '@backstage/config';\nimport {\n AuthService,\n BackstageCredentials,\n BackstageNonePrincipal,\n BackstageUserPrincipal,\n DiscoveryService,\n HttpAuthService,\n UserInfoService,\n} from '@backstage/backend-plugin-api';\n\nconst attributesSchema: z.ZodSchema<PermissionAttributes> = z.object({\n action: z\n .union([\n z.literal('create'),\n z.literal('read'),\n z.literal('update'),\n z.literal('delete'),\n ])\n .optional(),\n});\n\nconst permissionSchema = z.union([\n z.object({\n type: z.literal('basic'),\n name: z.string(),\n attributes: attributesSchema,\n }),\n z.object({\n type: z.literal('resource'),\n name: z.string(),\n attributes: attributesSchema,\n resourceType: z.string(),\n }),\n]);\n\nconst evaluatePermissionRequestSchema: z.ZodSchema<\n IdentifiedPermissionMessage<EvaluatePermissionRequest>\n> = z.object({\n id: z.string(),\n resourceRef: z.string().optional(),\n permission: permissionSchema,\n});\n\nconst evaluatePermissionRequestBatchSchema: z.ZodSchema<EvaluatePermissionRequestBatch> =\n z.object({\n items: z.array(evaluatePermissionRequestSchema),\n });\n\n/**\n * Options required when constructing a new {@link express#Router} using\n * {@link createRouter}.\n *\n * @public\n */\nexport interface RouterOptions {\n logger: Logger;\n discovery: DiscoveryService;\n policy: PermissionPolicy;\n identity?: IdentityApi;\n config: Config;\n auth?: AuthService;\n httpAuth?: HttpAuthService;\n userInfo?: UserInfoService;\n}\n\nconst handleRequest = async (\n requests: IdentifiedPermissionMessage<EvaluatePermissionRequest>[],\n policy: PermissionPolicy,\n permissionIntegrationClient: PermissionIntegrationClient,\n credentials: BackstageCredentials<\n BackstageNonePrincipal | BackstageUserPrincipal\n >,\n auth: AuthService,\n userInfo: UserInfoService,\n): Promise<IdentifiedPermissionMessage<EvaluatePermissionResponse>[]> => {\n const applyConditionsLoaderFor = memoize((pluginId: string) => {\n return new DataLoader<\n ApplyConditionsRequestEntry,\n ApplyConditionsResponseEntry\n >(batch =>\n permissionIntegrationClient.applyConditions(pluginId, credentials, batch),\n );\n });\n\n let user: BackstageIdentityResponse | undefined;\n if (auth.isPrincipal(credentials, 'user')) {\n const { ownershipEntityRefs } = await userInfo.getUserInfo(credentials);\n const { token } = await auth.getPluginRequestToken({\n onBehalfOf: credentials,\n targetPluginId: 'catalog', // TODO: unknown at this point\n });\n user = {\n identity: {\n type: 'user',\n userEntityRef: credentials.principal.userEntityRef,\n ownershipEntityRefs,\n },\n token,\n };\n }\n\n return Promise.all(\n requests.map(({ id, resourceRef, ...request }) =>\n policy.handle(request, user).then(decision => {\n if (decision.result !== AuthorizeResult.CONDITIONAL) {\n return {\n id,\n ...decision,\n };\n }\n\n if (!isResourcePermission(request.permission)) {\n throw new Error(\n `Conditional decision returned from permission policy for non-resource permission ${request.permission.name}`,\n );\n }\n\n if (decision.resourceType !== request.permission.resourceType) {\n throw new Error(\n `Invalid resource conditions returned from permission policy for permission ${request.permission.name}`,\n );\n }\n\n if (!resourceRef) {\n return {\n id,\n ...decision,\n };\n }\n\n return applyConditionsLoaderFor(decision.pluginId).load({\n id,\n resourceRef,\n ...decision,\n });\n }),\n ),\n );\n};\n\n/**\n * Creates a new {@link express#Router} which provides the backend API\n * for the permission system.\n *\n * @public\n */\nexport async function createRouter(\n options: RouterOptions,\n): Promise<express.Router> {\n const { policy, discovery, config, logger } = options;\n const { auth, httpAuth, userInfo } = createLegacyAuthAdapters(options);\n\n if (!config.getOptionalBoolean('permission.enabled')) {\n logger.warn(\n 'Permission backend started with permissions disabled. Enable permissions by setting permission.enabled=true.',\n );\n }\n\n const permissionIntegrationClient = new PermissionIntegrationClient({\n discovery,\n auth,\n });\n\n const router = Router();\n router.use(express.json());\n\n router.get('/health', (_, response) => {\n response.json({ status: 'ok' });\n });\n\n router.post(\n '/authorize',\n async (\n req: Request<EvaluatePermissionRequestBatch>,\n res: Response<EvaluatePermissionResponseBatch>,\n ) => {\n const credentials = await httpAuth.credentials(req, {\n allow: ['user', 'none'],\n });\n\n const parseResult = evaluatePermissionRequestBatchSchema.safeParse(\n req.body,\n );\n\n if (!parseResult.success) {\n throw new InputError(parseResult.error.toString());\n }\n\n const body = parseResult.data;\n\n res.json({\n items: await handleRequest(\n body.items,\n policy,\n permissionIntegrationClient,\n credentials,\n auth,\n userInfo,\n ),\n });\n },\n );\n\n router.use(errorHandler());\n\n return router;\n}\n"],"names":["z","AuthorizeResult","fetch","memoize","DataLoader","isResourcePermission","createLegacyAuthAdapters","Router","express","InputError","errorHandler"],"mappings":"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"}
|