@cerbos/orm-prisma
Version:
Prisma adapter for Cerbos query plans
1,336 lines • 166 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const _1 = require(".");
const globals_1 = require("@jest/globals");
const client_1 = require("@prisma/client");
const grpc_1 = require("@cerbos/grpc");
const prisma = new client_1.PrismaClient();
const cerbos = new grpc_1.GRPC("127.0.0.1:3593", { tls: false });
function createConditionalPlan(condition) {
return {
kind: _1.PlanKind.CONDITIONAL,
condition,
cerbosCallId: "",
requestId: "",
validationErrors: [],
metadata: undefined,
};
}
function getExpressionOperand(expression, index) {
const operand = expression.operands[index];
if (!operand) {
throw new Error(`Missing operand at index ${index}`);
}
return operand;
}
const fixtureUsers = [
{
id: "user1",
aBool: true,
aNumber: 1,
aString: "string",
},
{
id: "user2",
aBool: true,
aNumber: 2,
aString: "string",
},
];
const fixtureNextLevelResources = [
{
id: "nextLevel1",
aBool: true,
aNumber: 1,
aString: "string",
},
{
id: "nextLevel2",
aBool: false,
aNumber: 1,
aString: "string",
},
{
id: "nextLevel3",
aBool: true,
aNumber: 1,
aString: "string",
},
];
const fixtureTags = [
{
id: "tag1",
name: "public",
},
{
id: "tag2",
name: "private",
},
{
id: "tag3",
name: "draft",
},
];
const fixtureNestedResources = [
{
id: "nested1",
aBool: true,
aNumber: 1,
aString: "string",
nextlevel: {
connect: {
id: "nextLevel1",
},
},
},
{
id: "nested2",
aBool: false,
aNumber: 1,
aString: "string",
nextlevel: {
connect: {
id: "nextLevel2",
},
},
},
{
id: "nested3",
aBool: true,
aNumber: 1,
aString: "string",
nextlevel: {
connect: {
id: "nextLevel3",
},
},
},
];
const fixtureLabels = [
{ id: "label1", name: "important" },
{ id: "label2", name: "archived" },
{ id: "label3", name: "flagged" },
];
const fixtureSubCategories = [
{
id: "sub1",
name: "finance",
labels: {
connect: [{ id: "label1" }, { id: "label2" }],
},
},
{
id: "sub2",
name: "tech",
labels: {
connect: [{ id: "label2" }, { id: "label3" }],
},
},
];
const fixtureCategories = [
{
id: "cat1",
name: "business",
subCategories: {
connect: [{ id: "sub1" }],
},
},
{
id: "cat2",
name: "development",
subCategories: {
connect: [{ id: "sub2" }],
},
},
];
const fixtureResources = [
{
id: "resource1",
aBool: true,
aNumber: 1,
aString: "string",
aOptionalString: "optionalString",
createdBy: {
connect: {
id: "user1",
},
},
ownedBy: {
connect: [
{
id: "user1",
},
],
},
nested: {
connect: {
id: "nested1",
},
},
tags: {
connect: [
{ id: "tag1" }, // public
],
},
categories: {
connect: [{ id: "cat1" }],
},
},
{
id: "resource2",
aBool: false,
aNumber: 2,
aString: "string2",
createdBy: {
connect: {
id: "user2",
},
},
ownedBy: {
connect: [
{
id: "user2",
},
],
},
nested: {
connect: {
id: "nested3",
},
},
tags: {
connect: [
{ id: "tag2" }, // private
],
},
categories: {
connect: [{ id: "cat2" }],
},
},
{
id: "resource3",
aBool: false,
aNumber: 3,
aString: "string3",
createdBy: {
connect: {
id: "user1",
},
},
ownedBy: {
connect: [
{
id: "user1",
},
{
id: "user2",
},
],
},
nested: {
connect: {
id: "nested3",
},
},
tags: {
connect: [
{ id: "tag1" }, // public
{ id: "tag3" }, // draft
],
},
categories: {
connect: [{ id: "cat1" }, { id: "cat2" }],
},
},
];
(0, globals_1.beforeAll)(async () => {
await prisma.resource.deleteMany();
await prisma.nextLevelNestedResource.deleteMany();
await prisma.nestedResource.deleteMany();
await prisma.tag.deleteMany();
await prisma.user.deleteMany();
});
(0, globals_1.beforeEach)(async () => {
for (const tag of fixtureTags) {
await prisma.tag.create({ data: tag });
}
for (const user of fixtureUsers) {
await prisma.user.create({ data: user });
}
for (const resource of fixtureNextLevelResources) {
await prisma.nextLevelNestedResource.create({ data: resource });
}
for (const resource of fixtureNestedResources) {
await prisma.nestedResource.create({ data: resource });
}
for (const label of fixtureLabels) {
await prisma.label.create({ data: label });
}
for (const subCategory of fixtureSubCategories) {
await prisma.subCategory.create({ data: subCategory });
}
for (const category of fixtureCategories) {
await prisma.category.create({ data: category });
}
for (const resource of fixtureResources) {
await prisma.resource.create({ data: resource });
}
});
(0, globals_1.afterEach)(async () => {
await prisma.resource.deleteMany();
await prisma.nestedResource.deleteMany();
await prisma.nextLevelNestedResource.deleteMany();
await prisma.tag.deleteMany();
await prisma.user.deleteMany();
await prisma.category.deleteMany();
await prisma.subCategory.deleteMany();
await prisma.label.deleteMany();
});
// Core Functionality
(0, globals_1.describe)("Basic Plan Types", () => {
(0, globals_1.test)("always allowed", async () => {
const queryPlan = await cerbos.planResources({
principal: { id: "user1", roles: ["USER"] },
resource: { kind: "resource" },
action: "always-allow",
});
(0, globals_1.expect)(queryPlan.kind).toEqual(_1.PlanKind.ALWAYS_ALLOWED);
const result = (0, _1.queryPlanToPrisma)({
queryPlan,
});
(0, globals_1.expect)(result).toStrictEqual({
kind: _1.PlanKind.ALWAYS_ALLOWED,
});
const query = await prisma.resource.findMany({});
(0, globals_1.expect)(query.length).toEqual(fixtureResources.length);
});
(0, globals_1.test)("always denied", async () => {
const queryPlan = await cerbos.planResources({
principal: { id: "user1", roles: ["USER"] },
resource: { kind: "resource" },
action: "always-deny",
});
(0, globals_1.expect)(queryPlan.kind).toEqual(_1.PlanKind.ALWAYS_DENIED);
const result = (0, _1.queryPlanToPrisma)({
queryPlan,
mapper: {},
});
(0, globals_1.expect)(result).toEqual({
kind: _1.PlanKind.ALWAYS_DENIED,
});
});
});
// Field Operations
(0, globals_1.describe)("Field Operations", () => {
(0, globals_1.describe)("Basic Field Tests", () => {
(0, globals_1.test)("conditional - eq", async () => {
const queryPlan = await cerbos.planResources({
principal: { id: "user1", roles: ["USER"] },
resource: { kind: "resource" },
action: "equal",
});
(0, globals_1.expect)(queryPlan.kind).toEqual(_1.PlanKind.CONDITIONAL);
(0, globals_1.expect)(queryPlan.condition).toEqual({
operator: "eq",
operands: [{ name: "request.resource.attr.aBool" }, { value: true }],
});
const result = (0, _1.queryPlanToPrisma)({
queryPlan,
mapper: {
"request.resource.attr.aBool": { field: "aBool" },
},
});
(0, globals_1.expect)(result).toStrictEqual({
kind: _1.PlanKind.CONDITIONAL,
filters: { aBool: { equals: true } },
});
const query = await prisma.resource.findMany({
where: result.kind === _1.PlanKind.CONDITIONAL ? { ...result.filters } : {},
});
(0, globals_1.expect)(query.map((r) => r.id)).toEqual(fixtureResources.filter((a) => a.aBool).map((r) => r.id));
});
(0, globals_1.test)("conditional - eq - inverted order", async () => {
const queryPlan = await cerbos.planResources({
principal: { id: "user1", roles: ["USER"] },
resource: { kind: "resource" },
action: "equal",
});
(0, globals_1.expect)(queryPlan.kind).toEqual(_1.PlanKind.CONDITIONAL);
(0, globals_1.expect)(queryPlan.condition).toEqual({
operator: "eq",
operands: [{ name: "request.resource.attr.aBool" }, { value: true }],
});
const typeQp = queryPlan;
const invertedQueryPlan = {
...typeQp,
condition: {
...typeQp.condition,
operands: [
getExpressionOperand(typeQp.condition, 1),
getExpressionOperand(typeQp.condition, 0),
],
},
};
const result = (0, _1.queryPlanToPrisma)({
queryPlan: invertedQueryPlan,
mapper: {
"request.resource.attr.aBool": { field: "aBool" },
},
});
(0, globals_1.expect)(result).toStrictEqual({
kind: _1.PlanKind.CONDITIONAL,
filters: { aBool: { equals: true } },
});
if (result.kind !== _1.PlanKind.CONDITIONAL) {
throw new Error("Expected CONDITIONAL result");
}
const query = await prisma.resource.findMany({
where: { ...result.filters },
});
(0, globals_1.expect)(query.map((r) => r.id)).toEqual(fixtureResources.filter((a) => a.aBool).map((r) => r.id));
});
(0, globals_1.test)("conditional - ne", async () => {
const queryPlan = await cerbos.planResources({
principal: { id: "user1", roles: ["USER"] },
resource: { kind: "resource" },
action: "ne",
});
(0, globals_1.expect)(queryPlan.kind).toEqual(_1.PlanKind.CONDITIONAL);
(0, globals_1.expect)(queryPlan.condition).toEqual({
operator: "ne",
operands: [
{ name: "request.resource.attr.aString" },
{ value: "string" },
],
});
const result = (0, _1.queryPlanToPrisma)({
queryPlan,
mapper: {
"request.resource.attr.aString": { field: "aString" },
},
});
(0, globals_1.expect)(result).toStrictEqual({
kind: _1.PlanKind.CONDITIONAL,
filters: { aString: { not: "string" } },
});
if (result.kind !== _1.PlanKind.CONDITIONAL) {
throw new Error("Expected CONDITIONAL result");
}
const query = await prisma.resource.findMany({
where: { ...result.filters },
});
(0, globals_1.expect)(query.map((r) => r.id)).toEqual(fixtureResources.filter((a) => a.aString != "string").map((r) => r.id));
});
(0, globals_1.test)("conditional - explicit-deny", async () => {
const queryPlan = await cerbos.planResources({
principal: { id: "user1", roles: ["USER"] },
resource: { kind: "resource" },
action: "explicit-deny",
});
(0, globals_1.expect)(queryPlan.kind).toEqual(_1.PlanKind.CONDITIONAL);
(0, globals_1.expect)(queryPlan.condition).toEqual({
operator: "not",
operands: [
{
operator: "eq",
operands: [
{ name: "request.resource.attr.aBool" },
{ value: true },
],
},
],
});
const result = (0, _1.queryPlanToPrisma)({
queryPlan,
mapper: {
"request.resource.attr.aBool": { field: "aBool" },
},
});
(0, globals_1.expect)(result).toStrictEqual({
kind: _1.PlanKind.CONDITIONAL,
filters: { NOT: { aBool: { equals: true } } },
});
if (result.kind !== _1.PlanKind.CONDITIONAL) {
throw new Error("Expected CONDITIONAL result");
}
const query = await prisma.resource.findMany({
where: { ...result.filters },
});
(0, globals_1.expect)(query.map((r) => r.id)).toEqual(fixtureResources.filter((a) => !a.aBool).map((r) => r.id));
});
});
(0, globals_1.describe)("Comparison Tests", () => {
(0, globals_1.test)("conditional - gt", async () => {
const queryPlan = await cerbos.planResources({
principal: { id: "user1", roles: ["USER"] },
resource: { kind: "resource" },
action: "gt",
});
(0, globals_1.expect)(queryPlan.kind).toEqual(_1.PlanKind.CONDITIONAL);
(0, globals_1.expect)(queryPlan.condition).toEqual({
operator: "gt",
operands: [{ name: "request.resource.attr.aNumber" }, { value: 1 }],
});
const result = (0, _1.queryPlanToPrisma)({
queryPlan,
mapper: {
"request.resource.attr.aNumber": { field: "aNumber" },
},
});
(0, globals_1.expect)(result).toStrictEqual({
kind: _1.PlanKind.CONDITIONAL,
filters: {
aNumber: { gt: 1 },
},
});
if (result.kind !== _1.PlanKind.CONDITIONAL) {
throw new Error("Expected CONDITIONAL result");
}
const query = await prisma.resource.findMany({
where: { ...result.filters },
});
(0, globals_1.expect)(query.map((r) => r.id)).toEqual(fixtureResources
.filter((r) => {
return r.aNumber > 1;
})
.map((r) => r.id));
});
(0, globals_1.test)("conditional - lt", async () => {
const queryPlan = await cerbos.planResources({
principal: { id: "user1", roles: ["USER"] },
resource: { kind: "resource" },
action: "lt",
});
(0, globals_1.expect)(queryPlan.kind).toEqual(_1.PlanKind.CONDITIONAL);
(0, globals_1.expect)(queryPlan.condition).toEqual({
operator: "lt",
operands: [{ name: "request.resource.attr.aNumber" }, { value: 2 }],
});
const result = (0, _1.queryPlanToPrisma)({
queryPlan,
mapper: {
"request.resource.attr.aNumber": { field: "aNumber" },
},
});
(0, globals_1.expect)(result).toStrictEqual({
kind: _1.PlanKind.CONDITIONAL,
filters: {
aNumber: { lt: 2 },
},
});
if (result.kind !== _1.PlanKind.CONDITIONAL) {
throw new Error("Expected CONDITIONAL result");
}
const query = await prisma.resource.findMany({
where: { ...result.filters },
});
(0, globals_1.expect)(query.map((r) => r.id)).toEqual(fixtureResources
.filter((r) => {
return r.aNumber < 2;
})
.map((r) => r.id));
});
(0, globals_1.test)("conditional - gte", async () => {
const queryPlan = await cerbos.planResources({
principal: { id: "user1", roles: ["USER"] },
resource: { kind: "resource" },
action: "gte",
});
(0, globals_1.expect)(queryPlan.kind).toEqual(_1.PlanKind.CONDITIONAL);
(0, globals_1.expect)(queryPlan.condition).toEqual({
operator: "ge",
operands: [{ name: "request.resource.attr.aNumber" }, { value: 1 }],
});
const result = (0, _1.queryPlanToPrisma)({
queryPlan,
mapper: {
"request.resource.attr.aNumber": { field: "aNumber" },
},
});
(0, globals_1.expect)(result).toStrictEqual({
kind: _1.PlanKind.CONDITIONAL,
filters: {
aNumber: { gte: 1 },
},
});
if (result.kind !== _1.PlanKind.CONDITIONAL) {
throw new Error("Expected CONDITIONAL result");
}
const query = await prisma.resource.findMany({
where: { ...result.filters },
});
(0, globals_1.expect)(query.map((r) => r.id)).toEqual(fixtureResources
.filter((r) => {
return r.aNumber >= 1;
})
.map((r) => r.id));
});
(0, globals_1.test)("conditional - lte", async () => {
const queryPlan = await cerbos.planResources({
principal: { id: "user1", roles: ["USER"] },
resource: { kind: "resource" },
action: "lte",
});
(0, globals_1.expect)(queryPlan.kind).toEqual(_1.PlanKind.CONDITIONAL);
(0, globals_1.expect)(queryPlan.condition).toEqual({
operator: "le",
operands: [{ name: "request.resource.attr.aNumber" }, { value: 2 }],
});
const result = (0, _1.queryPlanToPrisma)({
queryPlan,
mapper: {
"request.resource.attr.aNumber": { field: "aNumber" },
},
});
(0, globals_1.expect)(result).toStrictEqual({
kind: _1.PlanKind.CONDITIONAL,
filters: {
aNumber: { lte: 2 },
},
});
if (result.kind !== _1.PlanKind.CONDITIONAL) {
throw new Error("Expected CONDITIONAL result");
}
const query = await prisma.resource.findMany({
where: { ...result.filters },
});
(0, globals_1.expect)(query.map((r) => r.id)).toEqual(fixtureResources
.filter((r) => {
return r.aNumber <= 2;
})
.map((r) => r.id));
});
});
(0, globals_1.describe)("String Tests", () => {
(0, globals_1.test)("conditional - contains", async () => {
const queryPlan = await cerbos.planResources({
principal: { id: "user1", roles: ["USER"] },
resource: { kind: "resource" },
action: "contains",
});
(0, globals_1.expect)(queryPlan.kind).toEqual(_1.PlanKind.CONDITIONAL);
(0, globals_1.expect)(queryPlan.condition).toEqual({
operands: [
{
name: "request.resource.attr.aString",
},
{
value: "str",
},
],
operator: "contains",
});
const result = (0, _1.queryPlanToPrisma)({
queryPlan,
mapper: {
"request.resource.attr.aString": { field: "aString" },
},
});
(0, globals_1.expect)(result).toStrictEqual({
kind: _1.PlanKind.CONDITIONAL,
filters: { aString: { contains: "str" } },
});
if (result.kind !== _1.PlanKind.CONDITIONAL) {
throw new Error("Expected CONDITIONAL result");
}
const query = await prisma.resource.findMany({
where: { ...result.filters },
});
(0, globals_1.expect)(query.map((r) => r.id)).toEqual(fixtureResources
.filter((a) => a.aString.includes("str"))
.map((r) => r.id));
});
(0, globals_1.test)("conditional - startsWith", async () => {
const queryPlan = await cerbos.planResources({
principal: { id: "user1", roles: ["USER"] },
resource: { kind: "resource" },
action: "starts-with",
});
(0, globals_1.expect)(queryPlan.kind).toEqual(_1.PlanKind.CONDITIONAL);
(0, globals_1.expect)(queryPlan.condition).toEqual({
operands: [
{
name: "request.resource.attr.aString",
},
{
value: "str",
},
],
operator: "startsWith",
});
const result = (0, _1.queryPlanToPrisma)({
queryPlan,
mapper: {
"request.resource.attr.aString": { field: "aString" },
},
});
(0, globals_1.expect)(result).toStrictEqual({
kind: _1.PlanKind.CONDITIONAL,
filters: { aString: { startsWith: "str" } },
});
if (result.kind !== _1.PlanKind.CONDITIONAL) {
throw new Error("Expected CONDITIONAL result");
}
const query = await prisma.resource.findMany({
where: { ...result.filters },
});
(0, globals_1.expect)(query.map((r) => r.id)).toEqual(fixtureResources
.filter((a) => a.aString.startsWith("str"))
.map((r) => r.id));
});
(0, globals_1.test)("conditional - endsWith", async () => {
const queryPlan = await cerbos.planResources({
principal: { id: "user1", roles: ["USER"] },
resource: { kind: "resource" },
action: "ends-with",
});
(0, globals_1.expect)(queryPlan.kind).toEqual(_1.PlanKind.CONDITIONAL);
(0, globals_1.expect)(queryPlan.condition).toEqual({
operands: [
{
name: "request.resource.attr.aString",
},
{
value: "ing",
},
],
operator: "endsWith",
});
const result = (0, _1.queryPlanToPrisma)({
queryPlan,
mapper: {
"request.resource.attr.aString": { field: "aString" },
},
});
(0, globals_1.expect)(result).toStrictEqual({
kind: _1.PlanKind.CONDITIONAL,
filters: { aString: { endsWith: "ing" } },
});
if (result.kind !== _1.PlanKind.CONDITIONAL) {
throw new Error("Expected CONDITIONAL result");
}
const query = await prisma.resource.findMany({
where: { ...result.filters },
});
(0, globals_1.expect)(query.map((r) => r.id)).toEqual(fixtureResources
.filter((a) => a.aString.endsWith("ing"))
.map((r) => r.id));
});
(0, globals_1.test)("conditional - isSet", async () => {
const queryPlan = await cerbos.planResources({
principal: { id: "user1", roles: ["USER"] },
resource: { kind: "resource" },
action: "is-set",
});
(0, globals_1.expect)(queryPlan.kind).toEqual(_1.PlanKind.CONDITIONAL);
(0, globals_1.expect)(queryPlan.condition).toEqual({
operands: [
{
name: "request.resource.attr.aOptionalString",
},
{
value: null,
},
],
operator: "ne",
});
const result = (0, _1.queryPlanToPrisma)({
queryPlan,
mapper: {
"request.resource.attr.aOptionalString": { field: "aOptionalString" },
},
});
(0, globals_1.expect)(result).toStrictEqual({
kind: _1.PlanKind.CONDITIONAL,
filters: { aOptionalString: { not: null } },
});
if (result.kind !== _1.PlanKind.CONDITIONAL) {
throw new Error("Expected CONDITIONAL result");
}
const query = await prisma.resource.findMany({
where: { ...result.filters },
});
(0, globals_1.expect)(query.map((r) => r.id)).toEqual(fixtureResources.filter((a) => a.aOptionalString).map((r) => r.id));
});
});
});
// Collection Operations
(0, globals_1.describe)("Collection Operations", () => {
(0, globals_1.describe)("Basic Collections", () => {
(0, globals_1.test)("conditional - in", async () => {
const queryPlan = await cerbos.planResources({
principal: { id: "user1", roles: ["USER"] },
resource: { kind: "resource" },
action: "in",
});
(0, globals_1.expect)(queryPlan.kind).toEqual(_1.PlanKind.CONDITIONAL);
(0, globals_1.expect)(queryPlan.condition).toEqual({
operator: "in",
operands: [
{ name: "request.resource.attr.aString" },
{ value: ["string", "anotherString"] },
],
});
const result = (0, _1.queryPlanToPrisma)({
queryPlan,
mapper: {
"request.resource.attr.aString": { field: "aString" },
},
});
(0, globals_1.expect)(result).toStrictEqual({
kind: _1.PlanKind.CONDITIONAL,
filters: {
aString: { in: ["string", "anotherString"] },
},
});
if (result.kind !== _1.PlanKind.CONDITIONAL) {
throw new Error("Expected CONDITIONAL result");
}
const query = await prisma.resource.findMany({
where: { ...result.filters },
});
(0, globals_1.expect)(query.map((r) => r.id)).toEqual(fixtureResources
.filter((r) => {
return ["string", "anotherString"].includes(r.aString);
})
.map((r) => r.id));
});
(0, globals_1.test)("conditional - in - scalar value", async () => {
const queryPlan = createConditionalPlan({
operator: "in",
operands: [
{ name: "request.resource.attr.aString" },
{ value: "string" },
],
});
const result = (0, _1.queryPlanToPrisma)({
queryPlan,
mapper: {
"request.resource.attr.aString": { field: "aString" },
},
});
(0, globals_1.expect)(result).toStrictEqual({
kind: _1.PlanKind.CONDITIONAL,
filters: { aString: "string" },
});
if (result.kind !== _1.PlanKind.CONDITIONAL) {
throw new Error("Expected CONDITIONAL result");
}
const query = await prisma.resource.findMany({
where: { ...result.filters },
});
(0, globals_1.expect)(query.map((r) => r.id).sort()).toEqual(fixtureResources
.filter((r) => r.aString === "string")
.map((r) => r.id)
.sort());
});
(0, globals_1.test)("conditional - relation in", async () => {
const queryPlan = createConditionalPlan({
operator: "in",
operands: [
{ name: "request.resource.attr.categories.name" },
{ value: ["business"] },
],
});
const result = (0, _1.queryPlanToPrisma)({
queryPlan,
mapper: {
"request.resource.attr.categories": {
relation: {
name: "categories",
type: "many",
fields: {
name: { field: "name" },
},
},
},
},
});
(0, globals_1.expect)(result).toStrictEqual({
kind: _1.PlanKind.CONDITIONAL,
filters: {
categories: {
some: {
name: "business",
},
},
},
});
if (result.kind !== _1.PlanKind.CONDITIONAL) {
throw new Error("Expected CONDITIONAL result");
}
const query = await prisma.resource.findMany({
where: { ...result.filters },
});
(0, globals_1.expect)(query.map((r) => r.id).sort()).toEqual(fixtureResources
.filter((resource) => {
const categoryRefs = resource.categories?.connect ??
[];
return categoryRefs.some((categoryRef) => {
const category = fixtureCategories.find((fc) => fc.id === categoryRef.id);
return category?.name === "business";
});
})
.map((r) => r.id)
.sort());
});
(0, globals_1.test)("conditional - relation in multiple values", async () => {
const queryPlan = createConditionalPlan({
operator: "in",
operands: [
{ name: "request.resource.attr.categories.name" },
{ value: ["business", "development"] },
],
});
const result = (0, _1.queryPlanToPrisma)({
queryPlan,
mapper: {
"request.resource.attr.categories": {
relation: {
name: "categories",
type: "many",
fields: {
name: { field: "name" },
},
},
},
},
});
(0, globals_1.expect)(result).toStrictEqual({
kind: _1.PlanKind.CONDITIONAL,
filters: {
categories: {
some: {
name: { in: ["business", "development"] },
},
},
},
});
if (result.kind !== _1.PlanKind.CONDITIONAL) {
throw new Error("Expected CONDITIONAL result");
}
const query = await prisma.resource.findMany({
where: { ...result.filters },
});
(0, globals_1.expect)(query.map((r) => r.id).sort()).toEqual(fixtureResources
.filter((resource) => {
const categoryRefs = resource.categories?.connect ??
[];
return categoryRefs.some((categoryRef) => {
const category = fixtureCategories.find((fc) => fc.id === categoryRef.id);
return ["business", "development"].includes(category?.name ?? "");
});
})
.map((r) => r.id)
.sort());
});
(0, globals_1.test)("conditional - except relation subset", async () => {
const queryPlan = createConditionalPlan({
operator: "except",
operands: [
{ name: "request.resource.attr.categories" },
{
operator: "lambda",
operands: [
{
operator: "eq",
operands: [
{ name: "cat.name" },
{ value: "business" },
],
},
{ name: "cat" },
],
},
],
});
const result = (0, _1.queryPlanToPrisma)({
queryPlan,
mapper: {
"request.resource.attr.categories": {
relation: {
name: "categories",
type: "many",
fields: {
name: { field: "name" },
},
},
},
},
});
(0, globals_1.expect)(result).toStrictEqual({
kind: _1.PlanKind.CONDITIONAL,
filters: {
categories: {
some: {
NOT: {
name: { equals: "business" },
},
},
},
},
});
if (result.kind !== _1.PlanKind.CONDITIONAL) {
throw new Error("Expected CONDITIONAL result");
}
const query = await prisma.resource.findMany({
where: { ...result.filters },
});
(0, globals_1.expect)(query.map((r) => r.id).sort()).toEqual(fixtureResources
.filter((resource) => {
const categoryRefs = resource.categories?.connect ??
[];
return categoryRefs.some((categoryRef) => {
const category = fixtureCategories.find((fc) => fc.id === categoryRef.id);
return category?.name !== "business";
});
})
.map((r) => r.id)
.sort());
});
(0, globals_1.test)("conditional - except nested relation subset", async () => {
const queryPlan = createConditionalPlan({
operator: "except",
operands: [
{ name: "request.resource.attr.categories" },
{
operator: "lambda",
operands: [
{
operator: "exists",
operands: [
{ name: "cat.subCategories" },
{
operator: "lambda",
operands: [
{
operator: "eq",
operands: [
{ name: "sub.name" },
{ value: "finance" },
],
},
{ name: "sub" },
],
},
],
},
{ name: "cat" },
],
},
],
});
const result = (0, _1.queryPlanToPrisma)({
queryPlan,
mapper: {
"request.resource.attr.categories": {
relation: {
name: "categories",
type: "many",
fields: {
subCategories: {
relation: {
name: "subCategories",
type: "many",
fields: {
name: { field: "name" },
},
},
},
},
},
},
},
});
(0, globals_1.expect)(result).toStrictEqual({
kind: _1.PlanKind.CONDITIONAL,
filters: {
categories: {
some: {
NOT: {
subCategories: {
some: {
name: { equals: "finance" },
},
},
},
},
},
},
});
if (result.kind !== _1.PlanKind.CONDITIONAL) {
throw new Error("Expected CONDITIONAL result");
}
const query = await prisma.resource.findMany({
where: { ...result.filters },
});
(0, globals_1.expect)(query.map((r) => r.id).sort()).toEqual(fixtureResources
.filter((resource) => {
const categoryRefs = resource.categories?.connect ??
[];
return categoryRefs.some((categoryRef) => {
const category = fixtureCategories.find((fc) => fc.id === categoryRef.id);
if (!category) {
return false;
}
const subCategoryRefs = category.subCategories?.connect ??
[];
return !subCategoryRefs.some((subCategoryRef) => {
const subCategory = fixtureSubCategories.find((fsc) => fsc.id === subCategoryRef.id);
return subCategory?.name === "finance";
});
});
})
.map((r) => r.id)
.sort());
});
(0, globals_1.test)("conditional - exists single", async () => {
const queryPlan = await cerbos.planResources({
principal: { id: "user1", roles: ["USER"] },
resource: { kind: "resource" },
action: "exists-single",
});
(0, globals_1.expect)(queryPlan.kind).toEqual(_1.PlanKind.CONDITIONAL);
(0, globals_1.expect)(queryPlan.condition).toEqual({
operator: "exists",
operands: [
{
name: "request.resource.attr.tags",
},
{
operator: "lambda",
operands: [
{
operator: "eq",
operands: [
{
name: "tag.id",
},
{
value: "tag1",
},
],
},
{
name: "tag",
},
],
},
],
});
const result = (0, _1.queryPlanToPrisma)({
queryPlan,
mapper: {
"request.resource.attr.tags": {
relation: {
name: "tags",
type: "many",
},
},
},
});
(0, globals_1.expect)(result).toStrictEqual({
kind: _1.PlanKind.CONDITIONAL,
filters: {
tags: {
some: {
id: {
equals: "tag1",
},
},
},
},
});
if (result.kind !== _1.PlanKind.CONDITIONAL) {
throw new Error("Expected CONDITIONAL result");
}
const query = await prisma.resource.findMany({
where: { ...result.filters },
});
(0, globals_1.expect)(query.map((r) => r.id)).toEqual(fixtureResources
.filter((a) => Array.isArray(a.tags?.connect) &&
a.tags?.connect
.map((t) => {
return fixtureTags.find((f) => f.id === t.id);
})
.filter((t) => t?.id == "tag1").length > 0)
.map((r) => r.id));
});
(0, globals_1.test)("conditional - exists multiple", async () => {
const queryPlan = await cerbos.planResources({
principal: { id: "user1", roles: ["USER"] },
resource: { kind: "resource" },
action: "exists-multiple",
});
(0, globals_1.expect)(queryPlan.kind).toEqual(_1.PlanKind.CONDITIONAL);
(0, globals_1.expect)(queryPlan.condition).toEqual({
operator: "exists",
operands: [
{
name: "request.resource.attr.tags",
},
{
operator: "lambda",
operands: [
{
operator: "and",
operands: [
{
operator: "eq",
operands: [
{
name: "tag.id",
},
{
value: "tag1",
},
],
},
{
operator: "eq",
operands: [
{
name: "tag.name",
},
{
value: "public",
},
],
},
],
},
{
name: "tag",
},
],
},
],
});
const result = (0, _1.queryPlanToPrisma)({
queryPlan,
mapper: {
"request.resource.attr.tags": {
relation: {
name: "tags",
type: "many",
},
},
},
});
(0, globals_1.expect)(result).toStrictEqual({
kind: _1.PlanKind.CONDITIONAL,
filters: {
tags: {
some: {
AND: [
{
id: {
equals: "tag1",
},
},
{
name: {
equals: "public",
},
},
],
},
},
},
});
if (result.kind !== _1.PlanKind.CONDITIONAL) {
throw new Error("Expected CONDITIONAL result");
}
const query = await prisma.resource.findMany({
where: { ...result.filters },
});
(0, globals_1.expect)(query.map((r) => r.id)).toEqual(fixtureResources
.filter((a) => Array.isArray(a.tags?.connect) &&
a.tags?.connect
.map((t) => {
return fixtureTags.find((f) => f.id === t.id);
})
.filter((t) => t?.id === "tag1" && t?.name === "public")
.length > 0)
.map((r) => r.id));
});
(0, globals_1.test)("conditional - exists_one", async () => {
const queryPlan = await cerbos.planResources({
principal: { id: "user1", roles: ["USER"] },
resource: { kind: "resource" },
action: "exists-one",
});
(0, globals_1.expect)(queryPlan.kind).toEqual(_1.PlanKind.CONDITIONAL);
(0, globals_1.expect)(queryPlan.condition).toEqual({
operator: "exists_one",
operands: [
{
name: "request.resource.attr.tags",
},
{
operator: "lambda",
operands: [
{
operator: "eq",
operands: [
{
name: "tag.name",
},
{
value: "public",
},
],
},
{
name: "tag",
},
],
},
],
});
const result = (0, _1.queryPlanToPrisma)({
queryPlan,
mapper: {
"request.resource.attr.tags": {
relation: {
name: "tags",
type: "many",
},
},
},
});
(0, globals_1.expect)(result).toStrictEqual({
kind: _1.PlanKind.CONDITIONAL,
filters: {
tags: {
some: {
name: { equals: "public" },
},
},
AND: [
{
tags: {
every: {
OR: [
{ name: { equals: "public" } },
{ NOT: { name: { equals: "public" } } },
],
},
},
},
],
},
});
if (result.kind !== _1.PlanKind.CONDITIONAL) {
throw new Error("Expected CONDITIONAL result");
}
const query = await prisma.resource.findMany({
where: { ...result.filters },
});
(0, globals_1.expect)(query.map((r) => r.id)).toEqual(fixtureResources
.filter((a) => Array.isArray(a.tags?.connect) &&
a.tags?.connect
.map((t) => {
return fixtureTags.find((f) => f.id === t.id);
})
.filter((t) =>