-
-
Notifications
You must be signed in to change notification settings - Fork 134
Description
Description and expected behavior
When a parent model and a related child model both have @deny access control rules on the same field name, updating the parent model generates invalid SQL with a missing FROM-clause entry.
Expected behavior: Access control rules should work correctly when the same field is protected in related models, or the PolicyPlugin should generate a clear error message explaining the limitation.
Steps to reproduce:
- Create two related models where both have @deny rules on a field with the same name:
model Thread {
id Int @id @default(autoincrement())
api_key_id Int @deny('all', auth().role != 'ADMIN')
question_answers Question[]
}
model Question {
id Int @id @default(autoincrement())
api_key_id Int @deny('all', auth().role != 'ADMIN') // Same field name
thread_id Int
thread Thread @relation(fields: [thread_id], references: [id])
}
- Update the parent model (Thread) via REST API or ORM query
Actual error: [DB ERROR]: error: missing FROM-clause entry for table "ParentModelName$relationName$sub"
Workaround:
Remove the @deny rule from either the parent or child model (not both). The access control on one side of the relation is sufficient. You do not need to protect the same field on both models:
Option A: Keep @deny on parent only
model Thread {
api_key_id Int @deny('all', auth().role != 'ADMIN')
}
model Question {
api_key_id Int // Remove @deny from here
}
Option B: Keep @deny on child only
model Thread {
api_key_id Int // Remove @deny from here
}
model Question {
api_key_id Int @deny('all', auth().role != 'ADMIN')
}
** Environment:**
- ZenStack version: v3.3.3
- Database type: PostgreSQL
- Node.js version: v23.10.0
- Package manager: npm
Additional context
- The issue is triggered by field name overlap: when the parent and child both protect a field with the same name
- The PolicyPlugin fails to generate valid SQL when constructing subqueries for access control verification across relations with overlapping protected field names
- The error references a generated table alias ($sub) that doesn't exist in the FROM clause, indicating a bug in how the PolicyPlugin builds the query
- This is a limitation/bug of the current PolicyPlugin implementation when handling shared field names across related models