Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/frappe/frappe/llms.txt

Use this file to discover all available pages before exploring further.

The Permission API provides functions to check user permissions, manage roles, and control access to documents.

Checking permissions

has_permission

Return True if user has permission for given doctype or document.
doctype
str
required
DocType name to check permission for
ptype
str
default:"read"
Permission type: “read”, “write”, “create”, “submit”, “cancel”, “delete”, “amend”
doc
Document | str
Document object or name to check user permissions for
user
str
User to check permission for. Default: current user
throw
bool
default:"False"
Raise PermissionError if not permitted
parent_doctype
str
Required when checking permission for child DocType
debug
bool
default:"False"
Print detailed permission check logs
return
bool
True if user has permission
# Check if user can read Customer doctype
if frappe.has_permission("Customer"):
    customers = frappe.get_all("Customer")

# Check write permission
if frappe.has_permission("Customer", "write"):
    print("User can modify customers")

# Check permission for specific document
if frappe.has_permission("Customer", "write", "CUST-001"):
    doc = frappe.get_doc("Customer", "CUST-001")
    doc.territory = "India"
    doc.save()

# Raise exception if no permission
frappe.has_permission("Customer", "delete", throw=True)

# Check for another user
if frappe.has_permission("Customer", "read", user="user@example.com"):
    print("User has read access")

# Check child table permission
frappe.has_permission(
    "Sales Order Item",
    "write",
    parent_doctype="Sales Order"
)

only_for

Raises PermissionError if the user does not have any of the permitted roles.
roles
str | list | tuple
required
Role or list of roles
message
bool | str
default:"False"
Custom error message or True for default message
# Restrict to single role
frappe.only_for("System Manager")

# Allow multiple roles
frappe.only_for(["System Manager", "Accounts Manager"])

# With custom message
frappe.only_for(
    "System Manager",
    message="Only System Managers can perform this action"
)
Administrator user always passes this check regardless of roles.

Role management

get_roles

Return roles of current or specified user.
user
str
User to get roles for. Default: current user
return
list
List of role names
# Get current user's roles
roles = frappe.get_roles()
if "System Manager" in roles:
    print("User is a System Manager")

# Get roles for specific user
user_roles = frappe.get_roles("user@example.com")

add_user_permission

Add a user permission rule.
doctype
str
required
DocType to restrict
name
str
required
Document name user has access to
user
str
required
User to apply permission to
applicable_for
str
DocType this permission applies to
is_default
bool
default:"False"
Set as default value in forms
hide_descendants
bool
default:"False"
Hide nested records (for tree doctypes)
# Allow user to access only one territory
frappe.permissions.add_user_permission(
    "Territory",
    "India",
    "user@example.com"
)

# With applicable_for - restrict when creating Sales Orders
frappe.permissions.add_user_permission(
    "Customer",
    "CUST-001",
    "user@example.com",
    applicable_for="Sales Order"
)

# Set as default
frappe.permissions.add_user_permission(
    "Warehouse",
    "Mumbai",
    "user@example.com",
    is_default=True
)

remove_user_permission

Remove a user permission.
doctype
str
required
DocType
name
str
required
Document name
user
str
required
User
frappe.permissions.remove_user_permission(
    "Territory",
    "India",
    "user@example.com"
)

clear_user_permissions_for_doctype

Clear all user permissions for a doctype.
doctype
str
required
DocType
user
str
User to clear permissions for. If not specified, clears for all users
# Clear for specific user
frappe.permissions.clear_user_permissions_for_doctype(
    "Territory",
    "user@example.com"
)

# Clear for all users
frappe.permissions.clear_user_permissions_for_doctype("Territory")

Permission utilities

can_import

Check if user can import data for a doctype.
doctype
str
required
DocType name
raise_exception
bool
default:"False"
Raise PermissionError if not allowed
return
bool
True if user can import
if frappe.permissions.can_import("Customer"):
    # Process import
    pass

can_export

Check if user can export data for a doctype.
doctype
str
required
DocType name
raise_exception
bool
default:"False"
Raise PermissionError if not allowed
is_owner
bool
default:"False"
Check if user is owner of records
return
bool
True if user can export
if frappe.permissions.can_export("Customer"):
    # Export data
    pass

get_user_permissions

Get all user permissions for a user.
user
str
User to get permissions for. Default: current user
return
dict
Dictionary of user permissions organized by doctype
user_perms = frappe.permissions.get_user_permissions("user@example.com")
print(user_perms)
# {
#     "Territory": [
#         {"doc": "India", "applicable_for": None},
#         {"doc": "Mumbai", "applicable_for": "Warehouse"}
#     ],
#     "Customer": [
#         {"doc": "CUST-001", "applicable_for": "Sales Order"}
#     ]
# }

Advanced permission checks

has_website_permission

Check if user has website permission for a document.
doc
Document | str
required
Document or document name
ptype
str
default:"read"
Permission type
user
str
User to check. Default: current user
doctype
str
DocType name (required if doc is string)
# Check website permission
if frappe.has_website_permission("Blog Post", "read", "BP-001"):
    post = frappe.get_doc("Blog Post", "BP-001")

get_role_permissions

Get permission settings for a doctype based on user’s roles.
doctype
str
required
DocType name
user
str
User to check. Default: current user
return
dict
Dictionary of permission flags
perms = frappe.permissions.get_role_permissions("Customer")
print(perms)
# {
#     "read": 1,
#     "write": 1,
#     "create": 1,
#     "delete": 0,
#     "submit": 0,
#     ...
# }

Permission constants

# Available permission types
frappe.permissions.std_rights
# ('select', 'read', 'write', 'create', 'delete',
#  'submit', 'cancel', 'amend', 'print', 'email',
#  'report', 'import', 'export', 'share')

# Standard roles
frappe.permissions.GUEST_ROLE  # "Guest"
frappe.permissions.ALL_USER_ROLE  # "All"
frappe.permissions.SYSTEM_USER_ROLE  # "Desk User"
frappe.permissions.ADMIN_ROLE  # "Administrator"

Best practices

# Always check permissions before operations
def update_customer_territory(customer, territory):
    # Check permission first
    if not frappe.has_permission("Customer", "write", customer):
        frappe.throw("Not allowed to update this customer")
    
    doc = frappe.get_doc("Customer", customer)
    doc.territory = territory
    doc.save()

# Use only_for for role-based access
@frappe.whitelist()
def sensitive_operation():
    frappe.only_for(["System Manager", "Administrator"])
    # Perform operation
    pass

# Check permissions with debug for troubleshooting
frappe.has_permission(
    "Customer",
    "write",
    "CUST-001",
    debug=True  # Shows why permission was granted/denied
)