Open
Description
The Prisma extension library ZenStack we are building happens to share the same view with wladiston andLiam-Tait’s solution to use the schema as the single source of truth. 🤝
This is how the sample schema should be represented in ZenStack now:
enum Role {
USER
ADMIN
}
model Cart {
id String @id @default(uuid())
customer Profile @relation(fields: [customerId], references: [id])
customerId String
//Carts are only visible by owners
@@allow('read', customerId == auth().id)
//Admins can do anything with carts
@@allow('all', auth().role == 'ADMIN')
}
The only differences are:
- We use @@Allow and @@deny instead of @@security
- We don’t generate RLS for now. Instead, we add a transparent proxy on Prisma client.
For the multitenancy issues, we invited a Collection Predict Expression to express it. Here is how it looks now:
enum Role {
USER
ADMIN
}
model User {
id String @id @default(cuid())
spaces SpaceUser[]
// can be created by anyone, even not logged in
@@allow('create', true)
// can be read by users sharing any space
@@allow('read', spaces?[space.members?[user == auth()]])
// full access by oneself
@@allow('all', auth() == this)
}
model Space {
id String @id @default(uuid())
members SpaceUser[]
// require login
@@deny('all', auth() == null)
// everyone can create a space
@@allow('create', true)
// any user in the space can read the space
@@allow('read', members?[user == auth()])
// space admin can update and delete
@@allow('update,delete', members?[user == auth() && role == ADMIN])
}
/*
* Model representing membership of a user in a space
*/
model SpaceUser {
id String @id @default(uuid())
space Space @relation(fields:[spaceId], references: [id], onDelete: Cascade)
spaceId String
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
userId String
role Role
// require login
@@deny('all', auth() == null)
// space admin can create/update/delete
@@allow('create,update,delete', space.members?[user == auth() && role == ADMIN])
// user can read entries for spaces which he's a member of
@@allow('read', space.members?[user == auth()])
}
If you feel interested, there is a tutorial post I wrote about it:
How to build a collaborative SaaS product using Next.js and ZenStack's access control policy
We would really appreciate it if you could share your opinions by commenting or joining our Discord to help us make ZenStack the right thing to solve your problems.
Metadata
Metadata
Assignees
Labels
No labels