When using zenstack permissions it is not using overridden query args for checking
Description and expected behavior
Actually its the same context as here (https://github.com/zenstackhq/zenstack/issues/1173) but a different issue. We have the following zmodel and want to check if we created something in the same currency the user currently has:
test.zmodel
import "../../../prisma/zmodel/auth/user.zmodel"
model Test {
id String @id @default(dbgenerated("uuid_generate_v4()")) @db.Uuid
currency String
@@schema("public")
@@map("test")
@@allow("create",
auth().settlement_currency == currency
)
@@allow("read", true)
}
We have the same pre- and postTransformers as mentioned in the other issue. So we basically do preTransformations to 5 char currencies (filling with Z) and when reading we remove these Z again as its just some internally saved currency stuff.
For completion here is the code:
currency-extension.ts
import { Prisma } from '@prisma/client';
import {
postTransformations,
preTransformations,
} from '@vdrip-database/database.util-test';
export const CurrencyTransformationExtensionTest = Prisma.defineExtension({
name: 'Currency Transformation',
model: {
$allModels: {
async createWithCurrency<Model, Args extends object>(
this: Model,
args: Prisma.Exact<Args, Prisma.Args<Model, 'create'>>
): Promise<Prisma.Result<Model, Args, 'create'>> {
// @ts-expect-error
args.data = preTransformations.args.currencyTransform(
// @ts-expect-error
args.data
);
// @ts-expect-error: Requires more types from Prisma
return this.create({
...args,
});
},
},
},
query: {
$allModels: {
async $allOperations({ operation, args, query }) {
const valueFields = ['data', 'create', 'update', 'where'];
switch (operation) {
// For all select operations
case 'aggregate':
case 'count':
case 'findFirst':
case 'findFirstOrThrow':
case 'findMany':
case 'findUnique':
case 'groupBy':
case 'upsert':
case 'update':
case 'updateMany':
case 'findUniqueOrThrow':
// For all mutation operations
case 'create':
case 'createMany':
case 'update':
case 'updateMany':
case 'upsert': {
valueFields.forEach((field) => {
// @ts-expect-error
if (args[field]) {
// @ts-expect-error
args[field] = preTransformations.args.currencyTransform(
// @ts-expect-error
args[field]
);
}
});
}
}
return postTransformations.result.currencyTransform(await query(args));
},
},
},
});
But when executing this following test, we get an error during creation:
test.spec.ts
it('should transform currencies automatically, but save them differently', async () => {
// setup
const extendedAndEnhancedPrisma = enhance(testContext.prismaClient);
const testEntity = await extendedAndEnhancedPrisma.test.create({
data: {
currency: 'USD',
},
});
testEntity;
});
Error:
Error calling enhanced Prisma method `create`: denied by policy: test entities failed 'create' check
So it seems like it is not checking the right values. During further investigation I was seeing that my debugger never got called inside the overridden query call, so it looks like the validation is being done before we execute the Prisma.Extension. I actually don't know if this is a bug or the desired behavior, but I was thinking that the validation of the permissions would be done either right before the query or right after it. At least I would think that my extensions would be applied, before doing the permissions checks.
Environment:
ZenStack version: 1.11.1 Prisma version: 5.9.1 Database type: Postgresql
Additional context This time it is also failing when using custom model function, unlike in the other issue.