Introduce PermissionMessageBatch utility type. Rename Identified type to IdentifiedPermissionMessage.

Co-authored-by: Mike Lewis <mtlewis@users.noreply.github.com>
Signed-off-by: Joe Porpeglia <josephp@spotify.com>
This commit is contained in:
Joe Porpeglia
2022-03-21 21:19:45 -04:00
committed by Joe Porpeglia
parent fa013a336b
commit ac0a6cb827
7 changed files with 59 additions and 40 deletions
@@ -32,7 +32,7 @@ import {
AuthorizeResult,
AuthorizeDecision,
AuthorizeQuery,
Identified,
IdentifiedPermissionMessage,
AuthorizeRequest,
AuthorizeResponse,
isResourcePermission,
@@ -73,11 +73,12 @@ const permissionSchema = z.union([
}),
]);
const querySchema: z.ZodSchema<Identified<AuthorizeQuery>> = z.object({
id: z.string(),
resourceRef: z.string().optional(),
permission: permissionSchema,
});
const querySchema: z.ZodSchema<IdentifiedPermissionMessage<AuthorizeQuery>> =
z.object({
id: z.string(),
resourceRef: z.string().optional(),
permission: permissionSchema,
});
const requestSchema: z.ZodSchema<AuthorizeRequest> = z.object({
items: z.array(querySchema),
@@ -98,12 +99,12 @@ export interface RouterOptions {
}
const handleRequest = async (
requests: Identified<AuthorizeQuery>[],
requests: IdentifiedPermissionMessage<AuthorizeQuery>[],
user: BackstageIdentityResponse | undefined,
policy: PermissionPolicy,
permissionIntegrationClient: PermissionIntegrationClient,
authHeader?: string,
): Promise<Identified<AuthorizeDecision>[]> => {
): Promise<IdentifiedPermissionMessage<AuthorizeDecision>[]> => {
const applyConditionsLoaderFor = memoize((pluginId: string) => {
return new DataLoader<
ApplyConditionsRequestEntry,
@@ -18,7 +18,11 @@ import { RestContext, rest } from 'msw';
import { setupServer } from 'msw/node';
import { ConfigReader } from '@backstage/config';
import { PermissionClient } from './PermissionClient';
import { AuthorizeQuery, AuthorizeResult, Identified } from './types/api';
import {
AuthorizeQuery,
AuthorizeResult,
IdentifiedPermissionMessage,
} from './types/api';
import { DiscoveryApi } from './types/discovery';
import { createPermission } from './permissions';
@@ -54,10 +58,12 @@ describe('PermissionClient', () => {
};
const mockAuthorizeHandler = jest.fn((req, res, { json }: RestContext) => {
const responses = req.body.items.map((a: Identified<AuthorizeQuery>) => ({
id: a.id,
result: AuthorizeResult.ALLOW,
}));
const responses = req.body.items.map(
(a: IdentifiedPermissionMessage<AuthorizeQuery>) => ({
id: a.id,
result: AuthorizeResult.ALLOW,
}),
);
return res(json({ items: responses }));
});
@@ -141,7 +147,7 @@ describe('PermissionClient', () => {
mockAuthorizeHandler.mockImplementationOnce(
(req, res, { json }: RestContext) => {
const responses = req.body.items.map(
(a: Identified<AuthorizeQuery>) => ({
(a: IdentifiedPermissionMessage<AuthorizeQuery>) => ({
id: a.id,
outcome: AuthorizeResult.ALLOW,
}),
@@ -158,10 +164,12 @@ describe('PermissionClient', () => {
it('should allow all when permission.enabled is false', async () => {
mockAuthorizeHandler.mockImplementationOnce(
(req, res, { json }: RestContext) => {
const responses = req.body.map((a: Identified<AuthorizeQuery>) => ({
id: a.id,
result: AuthorizeResult.DENY,
}));
const responses = req.body.map(
(a: IdentifiedPermissionMessage<AuthorizeQuery>) => ({
id: a.id,
result: AuthorizeResult.DENY,
}),
);
return res(json({ items: responses }));
},
@@ -180,10 +188,12 @@ describe('PermissionClient', () => {
it('should allow all when permission.enabled is not configured', async () => {
mockAuthorizeHandler.mockImplementationOnce(
(req, res, { json }: RestContext) => {
const responses = req.body.map((a: Identified<AuthorizeQuery>) => ({
id: a.id,
outcome: AuthorizeResult.DENY,
}));
const responses = req.body.map(
(a: IdentifiedPermissionMessage<AuthorizeQuery>) => ({
id: a.id,
outcome: AuthorizeResult.DENY,
}),
);
return res(json(responses));
},
@@ -23,7 +23,7 @@ import {
AuthorizeResult,
AuthorizeQuery,
AuthorizeDecision,
Identified,
IdentifiedPermissionMessage,
PermissionCriteria,
PermissionCondition,
AuthorizeResponse,
@@ -145,7 +145,7 @@ export class PermissionClient implements PermissionAuthorizer {
const responsesById = responseBody.items.reduce((acc, r) => {
acc[r.id] = r;
return acc;
}, {} as Record<string, Identified<AuthorizeDecision>>);
}, {} as Record<string, IdentifiedPermissionMessage<AuthorizeDecision>>);
return request.items.map(query => responsesById[query.id]);
}
+11 -7
View File
@@ -21,7 +21,15 @@ import { Permission } from './permission';
* requests.
* @public
*/
export type Identified<T> = T & { id: string };
export type IdentifiedPermissionMessage<T> = T & { id: string };
/**
* A batch of request or response items.
* @public
*/
export type PermissionMessageBatch<T> = {
items: IdentifiedPermissionMessage<T>[];
};
/**
* The result of an authorization request.
@@ -55,9 +63,7 @@ export type AuthorizeQuery = {
* A batch of authorization requests from {@link PermissionClient#authorize}.
* @public
*/
export type AuthorizeRequest = {
items: Identified<AuthorizeQuery>[];
};
export type AuthorizeRequest = PermissionMessageBatch<AuthorizeQuery>;
/**
* A condition returned with a CONDITIONAL authorization response.
@@ -127,6 +133,4 @@ export type AuthorizeDecision =
* A batch of authorization responses from {@link PermissionClient#authorize}.
* @public
*/
export type AuthorizeResponse = {
items: Identified<AuthorizeDecision>[];
};
export type AuthorizeResponse = PermissionMessageBatch<AuthorizeDecision>;
+2 -1
View File
@@ -20,7 +20,8 @@ export type {
AuthorizeRequest,
AuthorizeDecision,
AuthorizeResponse,
Identified,
IdentifiedPermissionMessage,
PermissionMessageBatch,
PermissionCondition,
PermissionCriteria,
AllOfCriteria,
@@ -16,7 +16,7 @@
import { ServerPermissionClient } from './ServerPermissionClient';
import {
Identified,
IdentifiedPermissionMessage,
AuthorizeQuery,
AuthorizeResult,
createPermission,
@@ -32,10 +32,12 @@ import { RestContext, rest } from 'msw';
const server = setupServer();
const mockAuthorizeHandler = jest.fn((req, res, { json }: RestContext) => {
const responses = req.body.items.map((r: Identified<AuthorizeQuery>) => ({
id: r.id,
result: AuthorizeResult.ALLOW,
}));
const responses = req.body.items.map(
(r: IdentifiedPermissionMessage<AuthorizeQuery>) => ({
id: r.id,
result: AuthorizeResult.ALLOW,
}),
);
return res(json({ items: responses }));
});
@@ -21,7 +21,7 @@ import { InputError } from '@backstage/errors';
import { errorHandler } from '@backstage/backend-common';
import {
AuthorizeResult,
Identified,
IdentifiedPermissionMessage,
PermissionCondition,
PermissionCriteria,
} from '@backstage/plugin-permission-common';
@@ -67,7 +67,7 @@ const applyConditionsRequestSchema = z.object({
*
* @public
*/
export type ApplyConditionsRequestEntry = Identified<{
export type ApplyConditionsRequestEntry = IdentifiedPermissionMessage<{
resourceRef: string;
resourceType: string;
conditions: PermissionCriteria<PermissionCondition>;
@@ -88,7 +88,8 @@ export type ApplyConditionsRequest = {
*
* @public
*/
export type ApplyConditionsResponseEntry = Identified<DefinitivePolicyDecision>;
export type ApplyConditionsResponseEntry =
IdentifiedPermissionMessage<DefinitivePolicyDecision>;
/**
* A batch of {@link ApplyConditionsResponseEntry} objects.