permission-node: switch to array for getResources return value

Signed-off-by: MT Lewis <mtlewis@users.noreply.github.com>
This commit is contained in:
MT Lewis
2021-12-20 17:17:20 +00:00
parent 419ca637c0
commit 8e72b573aa
5 changed files with 20 additions and 14 deletions
+1 -1
View File
@@ -8,4 +8,4 @@ Optimizations to the integration between the permission backend and plugin-backe
- The permission backend already supported batched requests to authorize, but would make calls to plugin backend to apply conditions serially. Now, after applying the policy for each authorization request, the permission backend makes a single batched /apply-conditions request to each plugin backend referenced in policy decisions.
- The `getResource` method accepted by `createPermissionIntegrationRouter` has been replaced with `getResources`, to allow consumers to make batch requests to upstream data stores. When /apply-conditions is called with a batch of requests, all required resources are requested in a single invocation of `getResources`.
Plugin owners consuming `createPermissionIntegrationRouter` should replace the `getResource` method in the options with a `getResources` method, accepting an array of resourceRefs, and returning a record object mapping those resourceRefs to resources (if present).
Plugin owners consuming `createPermissionIntegrationRouter` should replace the `getResource` method in the options with a `getResources` method, accepting an array of resourceRefs, and returning an array of the corresponding resources.
@@ -276,10 +276,9 @@ describe('PermissionIntegrationClient', () => {
createPermissionIntegrationRouter({
resourceType: 'test-resource',
getResources: async resourceRefs =>
resourceRefs.reduce((acc, ref) => {
acc[ref] = { id: ref };
return acc;
}, {} as Record<string, { id: string }>),
resourceRefs.map(resourceRef => ({
id: resourceRef,
})),
rules: [
{
name: 'RULE_1',
+1 -1
View File
@@ -97,7 +97,7 @@ export const createConditionTransformer: <
export const createPermissionIntegrationRouter: <TResource>(options: {
resourceType: string;
rules: PermissionRule<TResource, any, unknown[]>[];
getResources: (resourceRefs: string[]) => Promise<Record<string, TResource>>;
getResources: (resourceRefs: string[]) => Promise<(TResource | undefined)[]>;
}) => express.Router;
// @public
@@ -22,10 +22,7 @@ import { createPermissionIntegrationRouter } from './createPermissionIntegration
const mockGetResources: jest.MockedFunction<
Parameters<typeof createPermissionIntegrationRouter>[0]['getResources']
> = jest.fn(async resourceRefs =>
resourceRefs.reduce(
(acc, resourceRef) => ({ ...acc, [resourceRef]: { id: resourceRef } }),
{},
),
resourceRefs.map(resourceRef => ({ id: resourceRef })),
);
const testRule1 = {
@@ -251,7 +248,9 @@ describe('createPermissionIntegrationRouter', () => {
});
it('returns 200/DENY when resource is not found', async () => {
mockGetResources.mockReturnValueOnce(Promise.resolve({}));
mockGetResources.mockImplementationOnce(async resourceRefs =>
resourceRefs.map(() => undefined),
);
const response = await request(app)
.post('/.well-known/backstage/permissions/apply-conditions')
@@ -156,7 +156,9 @@ const applyConditions = <TResource>(
export const createPermissionIntegrationRouter = <TResource>(options: {
resourceType: string;
rules: PermissionRule<TResource, any>[];
getResources: (resourceRefs: string[]) => Promise<Record<string, TResource>>;
getResources: (
resourceRefs: string[],
) => Promise<Array<TResource | undefined>>;
}): express.Router => {
const { resourceType, rules, getResources } = options;
const router = Router();
@@ -188,9 +190,15 @@ export const createPermissionIntegrationRouter = <TResource>(options: {
assertValidResourceTypes(body);
const resources = await getResources(
Array.from(new Set(body.map(({ resourceRef }) => resourceRef))),
const resourceRefs = Array.from(
new Set(body.map(({ resourceRef }) => resourceRef)),
);
const resourceArray = await getResources(resourceRefs);
const resources = resourceRefs.reduce((acc, resourceRef, index) => {
acc[resourceRef] = resourceArray[index];
return acc;
}, {} as Record<string, TResource | undefined>);
return res.status(200).json(
body.map(request => ({