Loading...
Loading...
Add access control to a ZenStack V3 schema. Use when writing access policies (@@allow / @@deny), the auth() function, field-level rules, post-update rules, or setting up the policy plugin and $setAuth runtime. (For data validation — @email/@length/@@validate — see zenstack-querying.)
npx skill4agent add zenstackhq/skills zenstack-access-controlzenstack-schema-modelingzenstack-queryingzen generatezen checkplugin policy {
provider = '@zenstackhq/plugin-policy'
}npm install @zenstackhq/plugin-policyimport { ZenStackClient } from '@zenstackhq/orm';
import { PolicyPlugin } from '@zenstackhq/plugin-policy';
const db = new ZenStackClient(schema, { dialect }); // raw, unprotected
export const authDb = db.$use(new PolicyPlugin()); // access control enforcedZenStackClient$use()$setAuth()dbauth()$setAuth()auth()const userDb = authDb.$setAuth(user); // user-bound client
await userDb.post.findMany(); // policies evaluated against `user`$setAuth()auth()null$setAuth(undefined)client.$authauth()modeltype@@authUsertypetype Auth {
id Int
role String
@@auth
}@@allow@@deny@@allow(operation, condition)
@@deny(operation, condition)createreadupdatedeletepost-updateall@@deny@@allowreadupdatedeletecreatemodel User {
id Int @id @default(autoincrement())
email String @unique
posts Post[]
@@allow('create,read', true) // anyone can sign up; profiles public
@@allow('all', auth().id == id) // the user has full access to themselves
}
model Post {
id Int @id @default(autoincrement())
title String
published Boolean @default(false)
author User @relation(fields: [authorId], references: [id])
authorId Int
@@deny('all', auth() == null) // no anonymous access
@@allow('read', published) // published posts readable by anyone
@@allow('all', auth().id == authorId) // author has full access
}==!=>>=<<=&&||!auth().city == profile.address.cityrelation?[cond]relation![cond]relation^[cond]@@deny('delete', posts?[published == true]) // can't delete a user with published poststhiscomments?[author.verified && this.published]createcheck(relation [, op])@@allow('read', check(user))@@allow('update', check(user, 'update'))containsstartsWithendsWithhashasSomehasEveryisEmptycurrentModel()currentOperation()@@allow@denyreadupdatemodel User {
id Int @id
email String @allow('update', auth() == this) // only the owner can change it
name String @deny('read', auth() == null) // hidden from anonymous readers
}nullnullORMErrorREJECTED_BY_POLICYpost-updatebefore()future()model Post {
published Boolean @default(false)
authorId Int
@@deny('post-update', published == true && auth().id != authorId) // only author can publish
@@deny('post-update', before().authorId != authorId) // authorId is immutable
}post-updateupdate@@allow('post-update', ...)zenstack-queryingORMError.reasonREJECTED_BY_POLICYNOT_FOUNDREJECTED_BY_POLICYrejectedByPolicyReasonNO_ACCESSCANNOT_READ_BACKOTHER$queryRaw$executeRawnew PolicyPlugin({ dangerouslyAllowRawSql: true })references/@@allow@@denyauth()$setAuthpost-updatebefore()