zenstackhq / zenstack

Fullstack TypeScript toolkit that enhances Prisma ORM with flexible Authorization layer for RBAC/ABAC/PBAC/ReBAC, offering auto-generated type-safe APIs and frontend hooks.
https://zenstack.dev
MIT License
2.07k stars 89 forks source link

Allow accessing all fields through auth() when @@auth is applied on model with @@delegate #1267

Open bogsen opened 5 months ago

bogsen commented 5 months ago

Description and expected behavior Example schema:

model User {
    id Int @id @default(autoincrement())
    type String

    @@auth
    @@delegate(type)
}

model HappyUser extends User {
    veryHappy Boolean
}

model SadUser extends User {
    verySad Boolean
}

model Fridge {
    id Int @id @default(autoincrement())
    content String

    @@allow('all', auth().verySad)
}

Currently, this doesn't compile, because verySad isn't recognized as a field of auth(). I think it would make sense for auth() to consider extended model fields valid as well (and optional), since that's what you would get from a prisma.user.find() call.

Screenshots If applicable, add screenshots to help explain your problem.

Environment (please complete the following information):

Additional context Add any other context about the problem here.

ymc9 commented 5 months ago

Hi @bogsen , I think from an OO perspective, fields from sub-types shouldn't be directly visible from base type. I'm interested in knowing your real use case here. I haven't thought about having a polymorphic User model 😄.

bogsen commented 5 months ago

Maybe not directly visible from the base type, but right now as far as I can see they aren't accessible at all, which is strange - if I implemented the same polymorphism on the schema without using @@delegate, I would at least be able to use the relations within @@allow to access the fields I need. Also, on the TypeScript side I can directly do prisma.user.find().verySad since the User is a discriminated union.

The use case I have in mind is that I want to have 2 kinds of User - a HumanUser and a MachineUser, where policies on the HumanUser are broader and MachineUser permissions are more granular (thus needing more fields that are specific to them).

The same effect can be obtained without polymorphism (for example, by adding an extra layer of indirection between policy rules and Users), but this seemed like the more obvious solution for me.

ymc9 commented 5 months ago

Thanks for the clarification. I understand it's useful to have access to fields of concrete types. I'm thinking if it's only for 'auth' or should generally work for all contexts where base type is accessed. If we have it probably it's good to make it more generalized.

Is it blocking you in a real project now?