diff --git a/plugins/permission-node/api-report.md b/plugins/permission-node/api-report.md index 407ea3dc84..fe26dc2a1a 100644 --- a/plugins/permission-node/api-report.md +++ b/plugins/permission-node/api-report.md @@ -111,6 +111,6 @@ export type PolicyResult = // Warnings were encountered during analysis: // -// src/integration/createPermissionIntegration.d.ts:38:5 - (ae-forgotten-export) The symbol "QueryType" needs to be exported by the entry point index.d.ts -// src/integration/createPermissionIntegration.d.ts:39:5 - (ae-forgotten-export) The symbol "Conditions" needs to be exported by the entry point index.d.ts +// src/integration/createPermissionIntegration.d.ts:28:5 - (ae-forgotten-export) The symbol "QueryType" needs to be exported by the entry point index.d.ts +// src/integration/createPermissionIntegration.d.ts:29:5 - (ae-forgotten-export) The symbol "Conditions" needs to be exported by the entry point index.d.ts ``` diff --git a/plugins/permission-node/src/integration/createPermissionIntegration.ts b/plugins/permission-node/src/integration/createPermissionIntegration.ts index 35d6f0da54..cbdcb72041 100644 --- a/plugins/permission-node/src/integration/createPermissionIntegration.ts +++ b/plugins/permission-node/src/integration/createPermissionIntegration.ts @@ -15,6 +15,7 @@ */ import express, { Response, Router } from 'express'; +import { z } from 'zod'; import { AuthorizeResult, PermissionCondition, @@ -24,6 +25,26 @@ import { PermissionRule } from '../types'; import { conditionFor } from './conditionFor'; import { applyConditions, mapConditions } from './util'; +const permissionCriteriaSchema: z.ZodSchema< + PermissionCriteria +> = z.lazy(() => + z.union([ + z.object({ anyOf: z.array(permissionCriteriaSchema) }), + z.object({ allOf: z.array(permissionCriteriaSchema) }), + z.object({ not: permissionCriteriaSchema }), + z.object({ + rule: z.string(), + params: z.array(z.unknown()), + }), + ]), +); + +const applyConditionsRequestSchema = z.object({ + resourceRef: z.string(), + resourceType: z.string(), + conditions: permissionCriteriaSchema, +}); + /** * A request to load the referenced resource and apply conditions, to finalize a conditional * authorization response. @@ -105,15 +126,25 @@ export const createPermissionIntegration = < express.json(), async ( req, - res: Response<{ - result: Omit; - }>, + res: Response< + | { + result: Omit; + } + | string + >, ) => { - // TODO(authorization-framework): validate input - const body = req.body as ApplyConditionsRequest; + const parseResult = applyConditionsRequestSchema.safeParse(req.body); + + if (!parseResult.success) { + return res.status(400).send(`Invalid request body.`); + } + + const { data: body } = parseResult; if (body.resourceType !== resourceType) { - throw new Error(`Unexpected resource type: ${body.resourceType}`); + return res + .status(400) + .send(`Unexpected resource type: ${body.resourceType}.`); } const resource = await getResource( @@ -122,7 +153,9 @@ export const createPermissionIntegration = < ); if (!resource) { - return res.status(400).end(); + return res + .status(400) + .send(`Resource for ref ${body.resourceRef} not found.`); } return res.status(200).json({