Made changs to allow params and schemas to be defaulted and required only when there is params defined.
Co-authored-by: Vincenzo Scamporlino <vincenzos@spotify.com> Co-authored-by: Mike Lewis <mlewis@spotify.com> Signed-off-by: Harry Hogg <hhogg@spotify.com>
This commit is contained in:
@@ -55,7 +55,9 @@ export type Condition<TRule> = TRule extends PermissionRule<
|
||||
infer TResourceType,
|
||||
infer TParams
|
||||
>
|
||||
? (params: TParams) => PermissionCondition<TResourceType, TParams>
|
||||
? undefined extends TParams
|
||||
? () => PermissionCondition<TResourceType, TParams>
|
||||
: (params: TParams) => PermissionCondition<TResourceType, TParams>
|
||||
: never;
|
||||
|
||||
// @public
|
||||
@@ -98,7 +100,7 @@ export const createConditionFactory: <
|
||||
TParams extends PermissionRuleParams = PermissionRuleParams,
|
||||
>(
|
||||
rule: PermissionRule<unknown, unknown, TResourceType, TParams>,
|
||||
) => (params: TParams) => PermissionCondition<TResourceType, TParams>;
|
||||
) => (args_0: TParams) => PermissionCondition<TResourceType, TParams>;
|
||||
|
||||
// @public
|
||||
export const createConditionTransformer: <
|
||||
@@ -129,7 +131,7 @@ export const createPermissionRule: <
|
||||
TResource,
|
||||
TQuery,
|
||||
TResourceType extends string,
|
||||
TParams extends PermissionRuleParams = PermissionRuleParams,
|
||||
TParams extends PermissionRuleParams = undefined,
|
||||
>(
|
||||
rule: PermissionRule<TResource, TQuery, TResourceType, TParams>,
|
||||
) => PermissionRule<TResource, TQuery, TResourceType, TParams>;
|
||||
@@ -154,7 +156,7 @@ export const makeCreatePermissionRule: <
|
||||
TResource,
|
||||
TQuery,
|
||||
TResourceType extends string,
|
||||
>() => <TParams extends PermissionRuleParams = PermissionRuleParams>(
|
||||
>() => <TParams extends PermissionRuleParams = undefined>(
|
||||
rule: PermissionRule<TResource, TQuery, TResourceType, TParams>,
|
||||
) => PermissionRule<TResource, TQuery, TResourceType, TParams>;
|
||||
|
||||
@@ -177,7 +179,7 @@ export type PermissionRule<
|
||||
name: string;
|
||||
description: string;
|
||||
resourceType: TResourceType;
|
||||
paramsSchema: PermissionRuleSchema<TParams>;
|
||||
paramsSchema?: PermissionRuleSchema<TParams>;
|
||||
apply(
|
||||
resource: TResource,
|
||||
params: NoInfer<z.input<PermissionRuleSchema<TParams>>>,
|
||||
|
||||
@@ -36,7 +36,9 @@ export type Condition<TRule> = TRule extends PermissionRule<
|
||||
infer TResourceType,
|
||||
infer TParams
|
||||
>
|
||||
? (params: TParams) => PermissionCondition<TResourceType, TParams>
|
||||
? undefined extends TParams
|
||||
? () => PermissionCondition<TResourceType, TParams>
|
||||
: (params: TParams) => PermissionCondition<TResourceType, TParams>
|
||||
: never;
|
||||
|
||||
/**
|
||||
|
||||
@@ -37,6 +37,7 @@ describe('createConditionFactory', () => {
|
||||
describe('return value', () => {
|
||||
it('constructs a condition with the rule name and supplied params', () => {
|
||||
const conditionFactory = createConditionFactory(testRule);
|
||||
|
||||
expect(
|
||||
conditionFactory({
|
||||
foo: 'bar',
|
||||
|
||||
@@ -36,15 +36,17 @@ import { PermissionRule } from '../types';
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const createConditionFactory =
|
||||
<
|
||||
TResourceType extends string,
|
||||
TParams extends PermissionRuleParams = PermissionRuleParams,
|
||||
>(
|
||||
rule: PermissionRule<unknown, unknown, TResourceType, TParams>,
|
||||
) =>
|
||||
(params: TParams): PermissionCondition<TResourceType, TParams> => ({
|
||||
rule: rule.name,
|
||||
resourceType: rule.resourceType,
|
||||
params,
|
||||
});
|
||||
export const createConditionFactory = <
|
||||
TResourceType extends string,
|
||||
TParams extends PermissionRuleParams = PermissionRuleParams,
|
||||
>(
|
||||
rule: PermissionRule<unknown, unknown, TResourceType, TParams>,
|
||||
) => {
|
||||
return (...args: [TParams]): PermissionCondition<TResourceType, TParams> => {
|
||||
return {
|
||||
rule: rule.name,
|
||||
resourceType: rule.resourceType,
|
||||
params: args[0],
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -47,13 +47,13 @@ const mapConditions = <TQuery>(
|
||||
}
|
||||
|
||||
const rule = getRule(criteria.rule);
|
||||
const result = rule.paramsSchema.safeParse(criteria.params);
|
||||
const result = rule.paramsSchema?.safeParse(criteria.params);
|
||||
|
||||
if (rule.paramsSchema && !result.success) {
|
||||
if (result && !result.success) {
|
||||
throw new InputError(`Parameters to rule are invalid`, result.error);
|
||||
}
|
||||
|
||||
return rule.toQuery(criteria.params);
|
||||
return rule.toQuery(criteria.params ?? {});
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -52,11 +52,8 @@ const testRule2 = createPermissionRule({
|
||||
name: 'test-rule-2',
|
||||
description: 'Test rule 2',
|
||||
resourceType: 'test-resource',
|
||||
paramsSchema: z.object({
|
||||
foo: z.string().describe('foo'),
|
||||
}),
|
||||
apply: (_resource: any, _foo) => false,
|
||||
toQuery: _foo => ({}),
|
||||
apply: (_resource: any) => false,
|
||||
toQuery: () => ({}),
|
||||
});
|
||||
|
||||
describe('createPermissionIntegrationRouter', () => {
|
||||
@@ -105,7 +102,6 @@ describe('createPermissionIntegrationRouter', () => {
|
||||
{
|
||||
rule: 'test-rule-2',
|
||||
resourceType: 'test-resource',
|
||||
params: { foo: 'b' },
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -113,9 +109,6 @@ describe('createPermissionIntegrationRouter', () => {
|
||||
not: {
|
||||
rule: 'test-rule-2',
|
||||
resourceType: 'test-resource',
|
||||
params: {
|
||||
foo: 'c',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -133,9 +126,6 @@ describe('createPermissionIntegrationRouter', () => {
|
||||
{
|
||||
rule: 'test-rule-2',
|
||||
resourceType: 'test-resource',
|
||||
params: {
|
||||
foo: 'b',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -153,9 +143,6 @@ describe('createPermissionIntegrationRouter', () => {
|
||||
{
|
||||
rule: 'test-rule-2',
|
||||
resourceType: 'test-resource',
|
||||
params: {
|
||||
foo: 'c',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -191,9 +178,6 @@ describe('createPermissionIntegrationRouter', () => {
|
||||
{
|
||||
rule: 'test-rule-2',
|
||||
resourceType: 'test-resource',
|
||||
params: {
|
||||
foo: 'a',
|
||||
},
|
||||
},
|
||||
{
|
||||
allOf: [
|
||||
@@ -208,7 +192,6 @@ describe('createPermissionIntegrationRouter', () => {
|
||||
{
|
||||
rule: 'test-rule-2',
|
||||
resourceType: 'test-resource',
|
||||
params: { foo: 'b' },
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -227,9 +210,6 @@ describe('createPermissionIntegrationRouter', () => {
|
||||
{
|
||||
rule: 'test-rule-2',
|
||||
resourceType: 'test-resource',
|
||||
params: {
|
||||
foo: 'b',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -248,9 +228,6 @@ describe('createPermissionIntegrationRouter', () => {
|
||||
not: {
|
||||
rule: 'test-rule-2',
|
||||
resourceType: 'test-resource',
|
||||
params: {
|
||||
foo: 'd',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
@@ -309,9 +286,6 @@ describe('createPermissionIntegrationRouter', () => {
|
||||
conditions: {
|
||||
rule: 'test-rule-2',
|
||||
resourceType: 'test-resource',
|
||||
params: {
|
||||
foo: 'b',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -337,9 +311,6 @@ describe('createPermissionIntegrationRouter', () => {
|
||||
not: {
|
||||
rule: 'test-rule-2',
|
||||
resourceType: 'test-resource',
|
||||
params: {
|
||||
foo: 'c',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -360,9 +331,6 @@ describe('createPermissionIntegrationRouter', () => {
|
||||
{
|
||||
rule: 'test-rule-2',
|
||||
resourceType: 'test-resource',
|
||||
params: {
|
||||
foo: 'd',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -626,13 +594,7 @@ describe('createPermissionIntegrationRouter', () => {
|
||||
paramsSchema: {
|
||||
$schema: 'http://json-schema.org/draft-07/schema#',
|
||||
additionalProperties: false,
|
||||
properties: {
|
||||
foo: {
|
||||
description: 'foo',
|
||||
type: 'string',
|
||||
},
|
||||
},
|
||||
required: ['foo'],
|
||||
properties: {},
|
||||
type: 'object',
|
||||
},
|
||||
},
|
||||
|
||||
@@ -47,7 +47,7 @@ const permissionCriteriaSchema: z.ZodSchema<
|
||||
z.object({
|
||||
rule: z.string(),
|
||||
resourceType: z.string(),
|
||||
params: z.record(z.any()),
|
||||
params: z.record(z.any()).optional(),
|
||||
}),
|
||||
]),
|
||||
);
|
||||
@@ -127,13 +127,13 @@ const applyConditions = <TResourceType extends string, TResource>(
|
||||
}
|
||||
|
||||
const rule = getRule(criteria.rule);
|
||||
const result = rule.paramsSchema.safeParse(criteria.params);
|
||||
const result = rule.paramsSchema?.safeParse(criteria.params);
|
||||
|
||||
if (rule.paramsSchema && !result.success) {
|
||||
if (result && !result.success) {
|
||||
throw new InputError(`Parameters to rule are invalid`, result.error);
|
||||
}
|
||||
|
||||
return rule.apply(resource, criteria.params);
|
||||
return rule.apply(resource, criteria.params ?? {});
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -195,7 +195,7 @@ export const createPermissionIntegrationRouter = <
|
||||
name: rule.name,
|
||||
description: rule.description,
|
||||
resourceType: rule.resourceType,
|
||||
paramsSchema: zodToJsonSchema(rule.paramsSchema),
|
||||
paramsSchema: zodToJsonSchema(rule.paramsSchema ?? z.object({})),
|
||||
}));
|
||||
|
||||
return res.json({ permissions, rules: serializableRules });
|
||||
|
||||
@@ -26,7 +26,7 @@ export const createPermissionRule = <
|
||||
TResource,
|
||||
TQuery,
|
||||
TResourceType extends string,
|
||||
TParams extends PermissionRuleParams = PermissionRuleParams,
|
||||
TParams extends PermissionRuleParams = undefined,
|
||||
>(
|
||||
rule: PermissionRule<TResource, TQuery, TResourceType, TParams>,
|
||||
) => rule;
|
||||
@@ -41,7 +41,7 @@ export const createPermissionRule = <
|
||||
*/
|
||||
export const makeCreatePermissionRule =
|
||||
<TResource, TQuery, TResourceType extends string>() =>
|
||||
<TParams extends PermissionRuleParams = PermissionRuleParams>(
|
||||
<TParams extends PermissionRuleParams = undefined>(
|
||||
rule: PermissionRule<TResource, TQuery, TResourceType, TParams>,
|
||||
) =>
|
||||
createPermissionRule(rule);
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { z } from 'zod';
|
||||
import { createPermissionRule } from './createPermissionRule';
|
||||
import {
|
||||
createGetRule,
|
||||
@@ -31,7 +30,6 @@ describe('permission integration utils', () => {
|
||||
name: 'test-rule-1',
|
||||
description: 'Test rule 1',
|
||||
resourceType: 'test-resource',
|
||||
paramsSchema: z.object({}),
|
||||
apply: jest.fn(),
|
||||
toQuery: jest.fn(),
|
||||
});
|
||||
@@ -40,7 +38,6 @@ describe('permission integration utils', () => {
|
||||
name: 'test-rule-2',
|
||||
description: 'Test rule 2',
|
||||
resourceType: 'test-resource',
|
||||
paramsSchema: z.object({}),
|
||||
apply: jest.fn(),
|
||||
toQuery: jest.fn(),
|
||||
});
|
||||
|
||||
@@ -64,9 +64,9 @@ export type PermissionRule<
|
||||
resourceType: TResourceType;
|
||||
|
||||
/**
|
||||
* A ZodSchema that documents the parameters that this rule accepts.
|
||||
* A ZodSchema that reflects the structure of the parameters that are passed to
|
||||
*/
|
||||
paramsSchema: PermissionRuleSchema<TParams>;
|
||||
paramsSchema?: PermissionRuleSchema<TParams>;
|
||||
|
||||
/**
|
||||
* Apply this rule to a resource already loaded from a backing data source. The params are
|
||||
|
||||
Reference in New Issue
Block a user