CustomPermission
Database-stored permission override.
Allows admins to override code-first permissions with database rules.
Evaluated in the RbacPermissionAdapter alongside Meta.permissions.
Evaluation Priority:
1. Explicit DENY rules are checked first (deny wins)
2. If no deny, explicit ALLOW rules are checked
3. If no explicit rule, fall back to code-first Meta.permissions
Attributes:
for_user: Optional user ID this rule applies to
for_role: Optional role name this rule applies to
doctype_name: The DocType this permission applies to ("*" for all)
action: The action (read, write, create, delete, submit, etc.)
effect: Whether to ALLOW or DENY the permission
enabled: Whether this rule is active
priority: Rule priority (higher = evaluated first)
description: Human-readable description of why this rule exists
Source: custom_permission.py
Fields
| Field | Type | Required | Description | Validators |
|---|---|---|---|---|
| for_user | str | None | User ID this rule applies to (None = all users) | |
| for_role | str | None | Role name this rule applies to (None = all roles) | |
| doctype_name | str | DocType name or '*' for all DocTypes | - | |
| action | str | Action: read, write, create, delete, submit, cancel, amend | - | |
| effect | PermissionEffect | Whether to allow or deny this permission | - | |
| enabled | bool | Whether this rule is active | - | |
| priority | int | Rule priority (higher = evaluated first) | - | |
| description | str | None | Why this rule exists (for audit) |
Permissions
| Role | Create | Delete | Read | Write |
|---|---|---|---|---|
| Admin | ✓ | ✓ | ✓ | ✓ |
| System | ✓ |
Configuration
| Setting | Value |
|---|---|
| Submittable | False |
| Track Changes | True |
Controller
Controller hooks are implemented in *_controller.py files.
Available lifecycle hooks:
validate()- Called before save, raise exceptions for validation errorsbefore_insert()- Called before inserting a new documentafter_insert()- Called after successfully insertingbefore_save()- Called before saving (insert or update)after_save()- Called after savingbefore_delete()- Called before deletingafter_delete()- Called after deleting