zenstack icon indicating copy to clipboard operation
zenstack copied to clipboard

When using zenstack permissions it is not using overridden query args for checking

Open CollinKempkes opened this issue 1 year ago • 0 comments

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.

CollinKempkes avatar Mar 25 '24 09:03 CollinKempkes