engine
engine copied to clipboard
RFC: entity access only through relations
Introduction
This RFC proposes enhancements to the Access Control List (ACL) system in Contember. The focus is on introducing a more nuanced control mechanism for non-root entities, like Image
, allowing them to be accessible only through relations, and not by direct querying. This document outlines the proposed syntax and the logic for evaluating these rules.
Proposed Syntax
1. Explicit through
Relation
Entities can have ACL rules that specify explicit relations through which they can be accessed:
@c.allow(publicRole, {
read: ['url'],
when: { deletedAt: { isNull: true } },
through: ['articleCoverImage', 'userAvatar']
})
export class Image {
// ...
url = c.stringColumn().notNull()
articleCoverImage = c.oneHasOneInverse(Article, 'coverImage')
userAvatar = c.oneHasOneInverse(User, 'avatar')
}
-
through
: Specifies an array of relation names through which the entity can be accessed. These relation names are defined on the side of the entity being accessed, usually on the inverse side of the relationship. This means that the specified relations in through should correspond to relation properties within the entity class.
2. Wildcard through
Relation
A wildcard (*
) can be used to denote that the entity is accessible through any relation, but not directly:
@c.allow(publicRole, {
read: ['url'],
when: { deletedAt: { isNull: true } },
through: '*'
})
export class Image {
// ...
}
-
through: '*'
: Indicates that access is allowed through any relation. In the context of this wildcard rule, it is not necessary for the inverse side of the relation to be explicitly present on the accessed entity. This provides flexibility in scenarios where the exact relations may not be directly defined or are numerous, making explicit enumeration impractical.
3. General allow
Rules without through
For direct access without relation-based restrictions:
@c.allow(publicRole, {
read: ['url'],
when: {deletedAt: {isNull: true}},
})
export class Image {
// ...
}
- This is the standard rule for direct access. Also, it is the default rule if no other rules are defined.
Rule Evaluation Logic
Priority Order
-
First Priority: Rules with explicit, named
through
relations. -
Second Priority: Rules with a wildcard
through
(*
). -
Third Priority: General
allow
rules withoutthrough
.
Rule Merging
- Within each priority level, if multiple rules are defined, they are merged using an "OR" logic. Access is granted if any one of the rules within the same priority level is satisfied.
Perhaps we could use the same API for through
as we do for CRUD, replacing the wildcard *
with true
.
2. Wildcard through Relation
@c.allow(publicRole, {
read: ['url'],
when: { deletedAt: { isNull: true } },
through: true
})
export class Image {
// ...
}
I don't like the word through
. I think it makes sense only when you understand deeply what it does. Don't have a better alternative handy though.