Skip to content

Object-Level Delegation

Complex domains often need permissions that depend on related objects. Both AdditiveManagerPermission and OverrideManagerPermission support this through the __based_on__ attribute, which delegates evaluation to the permission class of another manager.

class ProjectMember(GeneralManager):
    project: Project
    user: User

    class Permission(AdditiveManagerPermission):
        __based_on__ = "project"
        __create__ = ["isProjectManager"]
        __update__ = ["isProjectManager"]
        __delete__ = ["isProjectManager"]

When the permission class encounters __based_on__, it loads the referenced manager (either an attribute or a nested manager type) and invokes its permission checks. If the delegation returns False, the original action is denied before local additive or override rules are considered.

Permission data manager

Behind the scenes, PermissionDataManager builds a comparison context containing the payload, the current manager state, and the requesting user. It exposes helper methods for change tracking (for example, for_update) so that permission expressions can compare old and new values.

Filters and delegation

get_permission_filter() merges filters returned by the delegated permission. This ensures bucket queries respect constraints from both the primary manager and the related manager. When the delegated attribute is None, implicit CRUD rules fall back to GENERAL_MANAGER["DEFAULT_PERMISSIONS"]; if that setting is not configured, the fallback is ["public"] for reads and ["isAuthenticated"] for create, update, and delete.

Tips

  • Validate that the delegated attribute resolves to a manager instance; otherwise permission evaluation raises TypeError.
  • Use attribute-level overrides (field = {"update": ["isOwner"]}) alongside __based_on__ to fine-tune write access on sensitive fields.
  • In GraphQL mutations, always run permission checks before performing side effects to avoid inconsistent state when a delegated permission rejects the action.
  • Superusers bypass all permission checks and filters, so delegation should focus on regular users while admin tooling continues to function.