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 name to check permission for
Permission type: “read”, “write”, “create”, “submit”, “cancel”, “delete”, “amend”
Document object or name to check user permissions for
User to check permission for. Default: current user
Raise PermissionError if not permitted
Required when checking permission for child DocType
Print detailed permission check logs
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 to get roles for. Default: current user
# 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.
Document name user has access to
User to apply permission to
DocType this permission applies to
Set as default value in forms
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.
frappe.permissions.remove_user_permission(
"Territory",
"India",
"user@example.com"
)
clear_user_permissions_for_doctype
Clear all user permissions for a doctype.
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.
Raise PermissionError if not allowed
if frappe.permissions.can_import("Customer"):
# Process import
pass
can_export
Check if user can export data for a doctype.
Raise PermissionError if not allowed
Check if user is owner of records
if frappe.permissions.can_export("Customer"):
# Export data
pass
get_user_permissions
Get all user permissions for a user.
User to get permissions for. Default: current user
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.
Document or document name
User to check. Default: current user
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.
User to check. Default: current user
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
)