Skip to content

Commit

Permalink
fix: 🐛 consider nested or and and conditions in rule relations
Browse files Browse the repository at this point in the history
  • Loading branch information
dennemark committed Aug 8, 2024
1 parent e795fbe commit 7f5187f
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 20 deletions.
35 changes: 15 additions & 20 deletions src/applyRuleRelationsQuery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,35 +4,30 @@ import { createPrismaAbility, PrismaQuery } from '@casl/prisma';
import { Prisma } from '@prisma/client';
import { relationFieldsByModel } from './helpers';

function flattenAst(ast: any) {
if (['and', 'or'].includes(ast.operator.toLowerCase())) {
return ast.value.flatMap((childAst: any) => flattenAst(childAst))
} else {
return [ast]
}
}

function getRuleRelationsQuery(model: string, ast: any) {
const obj: Record<string, any> = {}
if (ast) {
if (typeof ast.value === 'object') {
if (Array.isArray(ast.value)) {
ast.value.map((childAst: any) => {
const relation = relationFieldsByModel[model]
if (childAst.field) {
if (childAst.field in relation) {
obj[childAst.field] = {
select: getRuleRelationsQuery(relation[childAst.field].type, childAst.value)
}
} else {
obj[childAst.field] = true
}
}
})
} else {
flattenAst(ast).map((childAst: any) => {
const relation = relationFieldsByModel[model]
if (ast.field) {
if (ast.field in relation) {
obj[ast.field] = {
select: getRuleRelationsQuery(relation[ast.field].type, ast.value)
if (childAst.field) {
if (childAst.field in relation) {
obj[childAst.field] = {
select: getRuleRelationsQuery(relation[childAst.field].type, childAst.value)
}
} else {
obj[ast.field] = true
obj[childAst.field] = true
}
}
}
})
} else {
obj[ast.field] = true
}
Expand Down
39 changes: 39 additions & 0 deletions test/applyRuleRelationsQuery.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -201,4 +201,43 @@ describe('apply rule relations query', () => {
expect(mask).toEqual({ threads: true })
})

it('adds missing select queries also for conditions with nested OR / AND condition', () => {
const { can, build } = abilityBuilder()
//@ts-ignore
can('read', 'Thread', {
posts: {
some: {
OR: [{
threadId: null,
AND: [
{
text: {
contains: '-'
},
OR: [{
text: '-'
}]
}
]
},
{
threadId: null,
}]
}
}
})
const { args, mask } = applyRuleRelationsQuery({}, build(), 'read', 'Thread')
expect(args).toEqual({
include: {
posts: {
select: {
text: true,
threadId: true
}
}
}
})
expect(mask).toEqual({ posts: true })
})

})

0 comments on commit 7f5187f

Please sign in to comment.