permission-node: allow batch retrieval of resources in /apply-conditions
Signed-off-by: MT Lewis <mtlewis@users.noreply.github.com>
This commit is contained in:
@@ -275,7 +275,11 @@ describe('PermissionIntegrationClient', () => {
|
||||
router.use(
|
||||
createPermissionIntegrationRouter({
|
||||
resourceType: 'test-resource',
|
||||
getResource: async resourceRef => ({ id: resourceRef }),
|
||||
getResources: async resourceRefs =>
|
||||
resourceRefs.reduce((acc, ref) => {
|
||||
acc[ref] = { id: ref };
|
||||
return acc;
|
||||
}, {} as Record<string, { id: string }>),
|
||||
rules: [
|
||||
{
|
||||
name: 'RULE_1',
|
||||
|
||||
@@ -97,7 +97,7 @@ export const createConditionTransformer: <
|
||||
export const createPermissionIntegrationRouter: <TResource>(options: {
|
||||
resourceType: string;
|
||||
rules: PermissionRule<TResource, any, unknown[]>[];
|
||||
getResource: (resourceRef: string) => Promise<TResource | undefined>;
|
||||
getResources: (resourceRefs: string[]) => Promise<Record<string, TResource>>;
|
||||
}) => express.Router;
|
||||
|
||||
// @public
|
||||
|
||||
@@ -19,9 +19,14 @@ import express, { Express, Router } from 'express';
|
||||
import request, { Response } from 'supertest';
|
||||
import { createPermissionIntegrationRouter } from './createPermissionIntegrationRouter';
|
||||
|
||||
const mockGetResource: jest.MockedFunction<
|
||||
Parameters<typeof createPermissionIntegrationRouter>[0]['getResource']
|
||||
> = jest.fn(async resourceRef => ({ id: resourceRef }));
|
||||
const mockGetResources: jest.MockedFunction<
|
||||
Parameters<typeof createPermissionIntegrationRouter>[0]['getResources']
|
||||
> = jest.fn(async resourceRefs =>
|
||||
resourceRefs.reduce(
|
||||
(acc, resourceRef) => ({ ...acc, [resourceRef]: { id: resourceRef } }),
|
||||
{},
|
||||
),
|
||||
);
|
||||
|
||||
const testRule1 = {
|
||||
name: 'test-rule-1',
|
||||
@@ -46,7 +51,7 @@ describe('createPermissionIntegrationRouter', () => {
|
||||
beforeAll(() => {
|
||||
router = createPermissionIntegrationRouter({
|
||||
resourceType: 'test-resource',
|
||||
getResource: mockGetResource,
|
||||
getResources: mockGetResources,
|
||||
rules: [testRule1, testRule2],
|
||||
});
|
||||
|
||||
@@ -214,6 +219,15 @@ describe('createPermissionIntegrationRouter', () => {
|
||||
{ id: '567', result: AuthorizeResult.ALLOW },
|
||||
]);
|
||||
});
|
||||
|
||||
it('calls getResources for all required resources at once', () => {
|
||||
expect(mockGetResources).toHaveBeenCalledWith([
|
||||
'default:test/resource-1',
|
||||
'default:test/resource-2',
|
||||
'default:test/resource-3',
|
||||
'default:test/resource-4',
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
it('returns 400 when called with incorrect resource type', async () => {
|
||||
@@ -237,7 +251,7 @@ describe('createPermissionIntegrationRouter', () => {
|
||||
});
|
||||
|
||||
it('returns 200/DENY when resource is not found', async () => {
|
||||
mockGetResource.mockReturnValueOnce(Promise.resolve(undefined));
|
||||
mockGetResources.mockReturnValueOnce(Promise.resolve({}));
|
||||
|
||||
const response = await request(app)
|
||||
.post('/.well-known/backstage/permissions/apply-conditions')
|
||||
|
||||
@@ -156,9 +156,9 @@ const applyConditions = <TResource>(
|
||||
export const createPermissionIntegrationRouter = <TResource>(options: {
|
||||
resourceType: string;
|
||||
rules: PermissionRule<TResource, any>[];
|
||||
getResource: (resourceRef: string) => Promise<TResource | undefined>;
|
||||
getResources: (resourceRefs: string[]) => Promise<Record<string, TResource>>;
|
||||
}): express.Router => {
|
||||
const { resourceType, rules, getResource } = options;
|
||||
const { resourceType, rules, getResources } = options;
|
||||
const router = Router();
|
||||
|
||||
const getRule = createGetRule(rules);
|
||||
@@ -188,12 +188,9 @@ export const createPermissionIntegrationRouter = <TResource>(options: {
|
||||
|
||||
assertValidResourceTypes(body);
|
||||
|
||||
const resources = {} as Record<string, TResource | undefined>;
|
||||
for (const { resourceRef } of body) {
|
||||
if (!resources[resourceRef]) {
|
||||
resources[resourceRef] = await getResource(resourceRef);
|
||||
}
|
||||
}
|
||||
const resources = await getResources(
|
||||
Array.from(new Set(body.map(({ resourceRef }) => resourceRef))),
|
||||
);
|
||||
|
||||
return res.status(200).json(
|
||||
body.map(request => ({
|
||||
|
||||
Reference in New Issue
Block a user