Skip to content

Commit

Permalink
Merge branch 'fix-branch' of https://github.com/dennemark/prisma-exte…
Browse files Browse the repository at this point in the history
  • Loading branch information
dennemark committed Nov 29, 2024
2 parents a7267df + 2effde5 commit 3fdf5f6
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 11 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@
### Features

* :sparkles: add before and afterQuery functions ([7433bee](https://github.com/dennemark/prisma-extension-casl/commit/7433bee16b76eb6c8c506c48ed2792d03e2ddc64))
## [1.0.2](https://github.com/dennemark/prisma-extension-casl/compare/1.0.1...1.0.2) (2024-11-28)

### Bug Fixes

* :bug: deep merge nested rule relations ([ecd8741](https://github.com/dennemark/prisma-extension-casl/commit/ecd87416b69ed3c477629bbaf891e182070283f5))

## [1.0.1](https://github.com/dennemark/prisma-extension-casl/compare/1.0.0...1.0.1) (2024-10-29)

Expand Down
12 changes: 7 additions & 5 deletions src/filterQueryResults.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export function filterQueryResults(result: any, mask: any, creationTree: Creatio
if (!prismaModel) {
throw new Error(`Model ${model} does not exist on Prisma Client`)
}
const operationFields = caslOperationDict[operation].operationFields
const operationFields = ["_min", "_max", "_avg", "_count", "_sum"]

const filterPermittedFields = (entry: any) => {
if (!entry) { return null }
Expand Down Expand Up @@ -75,15 +75,17 @@ export function filterQueryResults(result: any, mask: any, creationTree: Creatio
if (relationField) {
const nestedCreationTree = creationTree && field in creationTree.children ? creationTree.children[field] : undefined
const res = filterQueryResults(entry[field], mask?.[field], nestedCreationTree, abilities, relationField.type, operation)
entry[field] = Array.isArray(res) ? res.length > 0 ? res : null : res
// do not distinguish array to get empty array for prisma
entry[field] = res // Array.isArray(res) ? res.length > 0 ? res : null : res
}
if ((!permittedFields.includes(field) && !relationField) || mask?.[field] === true) {
delete entry[field]
} else if (relationField) {
hasKeys = true
if (entry[field] === null) {
delete entry[field]
}
// do not delete to get null values when returning for prisma
// if (entry[field] === null) {
// delete entry[field]
// }
} else {
hasKeys = true
}
Expand Down
6 changes: 2 additions & 4 deletions src/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,6 @@ export const caslOperationDict: Record<
dataQuery: boolean
whereQuery: boolean
includeSelectQuery: boolean
// optional fields for certain actions that should be allowed to access
operationFields?: string[]
}
> = {
create: { action: 'create', dataQuery: true, whereQuery: false, includeSelectQuery: true },
Expand All @@ -63,9 +61,9 @@ export const caslOperationDict: Record<
findMany: { action: 'read', dataQuery: false, whereQuery: true, includeSelectQuery: true },
findUnique: { action: 'read', dataQuery: false, whereQuery: true, includeSelectQuery: true },
findUniqueOrThrow: { action: 'read', dataQuery: false, whereQuery: true, includeSelectQuery: true },
aggregate: { action: 'read', dataQuery: false, whereQuery: true, includeSelectQuery: false, operationFields: ['_min', '_max', '_avg', '_count', '_sum'] },
aggregate: { action: 'read', dataQuery: false, whereQuery: true, includeSelectQuery: false },
count: { action: 'read', dataQuery: false, whereQuery: true, includeSelectQuery: false },
groupBy: { action: 'read', dataQuery: false, whereQuery: true, includeSelectQuery: false, operationFields: ['_min', '_max', '_avg', '_count', '_sum'] },
groupBy: { action: 'read', dataQuery: false, whereQuery: true, includeSelectQuery: false },
update: { action: 'update', dataQuery: true, whereQuery: true, includeSelectQuery: true },
updateMany: { action: 'update', dataQuery: true, whereQuery: true, includeSelectQuery: false },
delete: { action: 'delete', dataQuery: false, whereQuery: true, includeSelectQuery: true },
Expand Down
3 changes: 2 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ export function useCaslAbilities(
const [fluentRelationModel, fluentRelationField] = (fluentModel !== model ? Object.entries(relationFieldsByModel[model]).find(([k, v]) => v.type === fluentModel) : undefined) ?? [undefined, undefined]
const transaction = (rest as any).__internalParams.transaction
const debug = (process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'test') && args.debugCasl
const debugAllErrors = args.debugCasl
delete args.debugCasl
const perf = debug ? performance : undefined
const logger = debug ? console : undefined
Expand Down Expand Up @@ -85,7 +86,7 @@ export function useCaslAbilities(
return applyCaslToQuery(operation, args, abilities, model, opts?.permissionField ? true : false)
}
catch (e) {
if (args.debugCasl || caslOperationDict[operation as PrismaCaslOperation].action !== 'read') {
if (debugAllErrors || caslOperationDict[operation as PrismaCaslOperation].action !== 'read') {
throw e
}

Expand Down
31 changes: 30 additions & 1 deletion test/extension.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -578,7 +578,7 @@ describe('prisma extension casl', () => {
}
},
})
expect(result).toEqual({ author: { email: '1', posts: [{ id: 1 }] } })
expect(result).toEqual({ author: { email: '1', posts: [{ id: 1, thread: null }] } })
})

it('includes nested fields if query does not include properties to check for rules', async () => {
Expand Down Expand Up @@ -1897,6 +1897,35 @@ describe('prisma extension casl', () => {
_sum: { id: 1 },
})
})
it('can aggregate data', async () => {
function builderFactory() {
const builder = abilityBuilder()
const { can, cannot } = builder

can('read', 'Thread')
can('read', 'Post')

return builder
}
const client = seedClient.$extends(
useCaslAbilities(builderFactory)
)
await seedClient.post.updateMany({ data: { threadId: null } })
const result = await client.thread.findUnique({
where: {
id: 0
},
include: {
_count: { select: { posts: true } },
}
})
expect(result).toEqual({
_count: { posts: 0 },
creatorId: 0,
id: 0,
topicId: 0
})
})
})
describe('count', () => {
it('can count data', async () => {
Expand Down

0 comments on commit 3fdf5f6

Please sign in to comment.