Skip to content

Commit

Permalink
fix: 🐛 fluent list relation mask
Browse files Browse the repository at this point in the history
  • Loading branch information
dennemark committed Dec 6, 2024
1 parent 64077dc commit 5afde2e
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 33 deletions.
51 changes: 27 additions & 24 deletions src/applyRuleRelationsQuery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,11 +77,10 @@ function mergeArgsAndRelationQuery(args: any, relationQuery: any) {
...(args.include ?? {}),
[k]: v
}
mask[k] = removeNestedIncludeSelect(v.select)
mask[k] = args.where ? true : removeNestedIncludeSelect(v.select)
}
})
}

return {
args,
mask
Expand Down Expand Up @@ -165,31 +164,35 @@ function getNestedQueryRelations(args: any, abilities: PureAbility<AbilityTuple,
inverted: false
}
}))
const ast = rulesToAST(ability, action, model)

const queryRelations = getRuleRelationsQuery(model, ast, creationSelectQuery === true ? {} : creationSelectQuery)
;['include', 'select'].map((method) => {
if (args && args[method]) {
for (const relation in args[method]) {
if (model in relationFieldsByModel && relation in relationFieldsByModel[model]) {
const relationField = relationFieldsByModel[model][relation]

if (relationField) {
const nestedQueryRelations = deepMerge(
getNestedQueryRelations(args[method][relation], abilities, action === 'all' ? 'all' : 'read', relationField.type as Prisma.ModelName),
(typeof queryRelations[relation]?.select === 'object' ? queryRelations[relation]?.select : {})
)
if (nestedQueryRelations && Object.keys(nestedQueryRelations).length > 0) {
queryRelations[relation] = {
...(queryRelations[relation] ?? {}),
select: nestedQueryRelations
try {
const ast = rulesToAST(ability, action, model)

const queryRelations = getRuleRelationsQuery(model, ast, creationSelectQuery === true ? {} : creationSelectQuery)
;['include', 'select'].map((method) => {
if (args && args[method]) {
for (const relation in args[method]) {
if (model in relationFieldsByModel && relation in relationFieldsByModel[model]) {
const relationField = relationFieldsByModel[model][relation]

if (relationField) {
const nestedQueryRelations = deepMerge(
getNestedQueryRelations(args[method][relation], abilities, action === 'all' ? 'all' : 'read', relationField.type as Prisma.ModelName),
(typeof queryRelations[relation]?.select === 'object' ? queryRelations[relation]?.select : {})
)
if (nestedQueryRelations && Object.keys(nestedQueryRelations).length > 0) {
queryRelations[relation] = {
...(queryRelations[relation] ?? {}),
select: nestedQueryRelations
}
}
}
}
}
}
}
})

return queryRelations
})
return queryRelations
} catch (e) {
console.error(`Your ability relation probably is missing an 'is': [relation]: { is: { id: 0 } }`)
throw e
}
}
4 changes: 1 addition & 3 deletions test/applyCaslToQuery.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,9 +108,7 @@ describe('apply casl to query', () => {
author: {
id: true,
posts: {
thread: {
creatorId: true
}
thread: true
}
},
thread: true
Expand Down
6 changes: 1 addition & 5 deletions test/applyRuleRelationsQuery.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -258,11 +258,7 @@ describe('apply rule relations query', () => {
const { args, mask } = applyRuleRelationsQuery(includeArgs, build(), 'read', 'User')
expect(mask).toEqual({
posts: {
author: {
threads: {
id: true
}
}
author: true
}
})
expect(args?.include).toEqual({
Expand Down
35 changes: 34 additions & 1 deletion test/extension.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -581,7 +581,7 @@ describe('prisma extension casl', () => {
}
},
})
expect(result).toEqual({ author: { email: '1', posts: [{ id: 1, thread: null }] } })
expect(result).toEqual({ author: { email: '1', posts: [{ id: 1 }] } })
})

it('includes nested fields if query does not include properties to check for rules', async () => {
Expand Down Expand Up @@ -2090,6 +2090,39 @@ describe('prisma extension casl', () => {
expect(result).toEqual({ email: '0', id: 0, casl: ['create', 'read', 'update', 'delete'] })
})
})
describe('filter query', () => {
it('removes query mask', async () => {
function builderFactory() {
const builder = abilityBuilder()
const { can, cannot } = builder

can('read', 'Thread')
can('read', 'Post', {
threadId: 0,
author: {
is: {
threads: {
some: {
id: 0
}
}
}
}
})
can('read', 'User')

return builder
}
const client = seedClient.$extends(
useCaslAbilities(builderFactory, { permissionField: 'casl' })
)
const result = await client.user.findUnique({ where: { id: 0 } }).posts()
expect(result).toEqual([
{ authorId: 0, text: "", threadId: 0, id: 0, casl: ['read'] }
])

})
})
})
afterAll(async () => {
await seedClient.$disconnect()
Expand Down

0 comments on commit 5afde2e

Please sign in to comment.