permissions-expert

Frappe Permissions Expert

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "permissions-expert" with this command: npx skills add kehwar/frappe_tweaks/kehwar-frappe-tweaks-permissions-expert

Frappe Permissions Expert

This skill provides comprehensive guidance for understanding and extending Frappe's permission system.

Overview

Frappe's permission system is multi-layered and evaluates permissions in a specific order:

  • Administrator Check: Administrator user bypasses all permission checks

  • Role-Based Permissions: DocType permissions configured through Permission Manager

  • Controller Permissions: Custom has_permission hooks in doctypes

  • User Permissions: Document-level restrictions based on user-specific rules

  • Permission Query Conditions: SQL-based filters for list views and reports

  • Share Permissions: Explicit document sharing between users

Permission Types

Frappe supports the following permission types (ptypes):

rights = ( "select", # View in list (limited fields) "read", # Full read access "write", # Edit existing documents "create", # Create new documents "delete", # Delete documents "submit", # Submit submittable documents "cancel", # Cancel submitted documents "amend", # Amend cancelled documents "print", # Print documents "email", # Email documents "report", # Access reports "import", # Import documents "export", # Export documents "share", # Share documents with others )

Quick Reference

Main Permission Check Function

frappe.has_permission( doctype="DocType Name", ptype="read", # Permission type to check doc=None, # Optional: specific document instance user=None, # Optional: defaults to current user raise_exception=True, # Display error message if False parent_doctype=None, # Required for child doctypes debug=False, # Enable debug logging ignore_share_permissions=False )

Key Concepts

  • Child Tables: Don't have their own permissions; permissions are checked on the parent document

  • Virtual DocTypes: Permission query conditions don't apply; only has_permission hook and role permissions apply

  • Permission Levels: Provide field-level access control within a document (permlevel 0, 1, 2, etc.)

Extension Hooks

Frappe provides seven main hooks for extending permission logic:

  1. has_permission
  • Controller Permission Check

Purpose: Implement custom document-level permission logic

Location: In your doctype's .py file or registered in hooks.py

Signature:

def has_permission(doc, ptype=None, user=None, debug=False): """ Returns: bool or None: - True: Explicitly grant permission - False: Explicitly deny permission - None: No opinion, continue with other checks """

Important Notes:

  • Return None to defer to other permission checks (recommended default)

  • Return False to explicitly deny permission (overrides role permissions)

  • Return True to explicitly grant permission (use with caution)

When to read: See references/has-permission-hook.md when implementing document-level permission logic with 7 detailed examples covering owner access, team hierarchies, status restrictions, and more.

  1. permission_query_conditions
  • List View Filtering and Document Access

Purpose: Return SQL WHERE conditions to filter documents in list views and validate individual document access

Location: In your doctype's .py file or registered in hooks.py

Signature:

def get_permission_query_conditions(user=None, doctype=None): """ Returns: str: SQL WHERE clause without the "WHERE" keyword Returns empty string "" to allow all documents """

Security: Always escape dynamic values with frappe.db.escape()

Important: These conditions are checked both in list views AND when accessing individual documents via has_permission() for read/select operations.

When to read: See references/permission-query-conditions-hook.md when implementing list filtering or document access validation with 7 examples including company filtering, role-based regions, time-based access, and multi-tenant patterns.

  1. write_permission_query_conditions
  • Post-Write Validation

Purpose: Validate that saved/updated documents satisfy custom conditions before committing to database

Location: In your doctype's .py file or registered in hooks.py

Signature:

def get_write_permission_query_conditions(user=None, doctype=None, ptype="write"): """ Return SQL WHERE conditions to validate written documents.

This is automatically called during has_permission() checks
for write/create/submit/cancel/delete operations.

Checked AFTER database write but BEFORE commit.
If validation fails, transaction is rolled back.
"""

When to read: See references/write-permission-query-conditions-hook.md when validating writes before commit with examples for regional restrictions, document age limits, and status-based validation.

  1. Server Scripts - Permission Query

Purpose: Define permission query conditions using Server Scripts (Python code in the UI)

Location: Created through Frappe UI at /app/server-script

Script Type: "Permission Query"

When to read: See references/server-scripts.md when prototyping permission logic via UI before moving to code, with examples for department filtering and role-based access.

  1. has_website_permission
  • Website/Portal Access

Purpose: Control access to documents on the website/portal (not desk)

Location: In your doctype's .py file or registered in hooks.py

When to read: See references/has-website-permission-hook.md when implementing portal/website access control with examples for customer orders, published content, and contact relationships.

Workflow Permission Hooks

Frappe provides two additional hooks specifically for workflow-based permissions:

  1. filter_workflow_transitions
  • Custom Transition Filtering

Purpose: Filter and customize the list of available workflow transitions based on custom logic

Location: Registered in hooks.py

Use Cases:

  • Hide specific transitions based on document field values

  • Apply time-based or date-based restrictions

  • Implement dynamic transition visibility

  1. has_workflow_action_permission
  • Action-Level Permission

Purpose: Control which users should receive workflow action notifications and have permission to execute specific actions

Location: Registered in hooks.py

Use Cases:

  • Implement approval hierarchies

  • Department or region-based approval routing

  • Amount-based approval limits

When to read: See references/workflow-permission-hooks.md when implementing workflow transition filtering or approval routing with 10+ examples covering hierarchical approvals, time restrictions, and regional routing.

User Permissions

User Permissions restrict access to specific document values for link fields.

Creating User Permissions:

from frappe.permissions import add_user_permission

add_user_permission( doctype="Company", name="Company A", user="user@example.com", applicable_for="Sales Order", # Optional is_default=1, # Optional ignore_permissions=True # Optional )

Use Cases:

  • Restrict sales users to their own territory

  • Limit employees to their branch/department

  • Multi-company access control

When to read: See references/user-permissions.md when implementing document-level restrictions using User Permissions with comprehensive examples for multi-company, territory, and department-based access.

Share Permissions

Documents can be explicitly shared with specific users:

frappe.share.add( doctype="Sales Order", name="SO-0001", user="user@example.com", read=1, write=1, share=0, submit=0, notify=1 )

When to read: See references/share-permissions.md when implementing explicit document sharing between users with examples for collaboration, temporary access, and cross-department workflows.

Permission Levels

Permission levels provide field-level access control:

  • Each field can have a permlevel (0, 1, 2, etc.)

  • Users must have role permission with that permlevel to see/edit the field

  • Permlevel 0 is default and always checked

When to read: See references/permission-levels.md when implementing field-level access control with examples for hiding pricing, cost fields, and internal notes from specific roles.

Best Practices

Security

  • Always Escape User Input: Use frappe.db.escape() when building SQL conditions

  • Fail Secure: Default to denying access when in doubt

  • Validate Hook Returns: Ensure hooks return expected types

  • Test Permission Boundaries: Test with users having minimal permissions

  • Avoid Side Effects: Permission checks should be read-only

Performance

  • Optimize SQL Conditions: Use indexed columns in WHERE clauses

  • Cache User Data: Cache frequently accessed user properties

  • Minimize Hook Complexity: Keep permission logic simple and fast

  • Use Appropriate Hooks:

  • Use permission_query_conditions for list filtering

  • Use has_permission for complex document-specific logic

Maintainability

  • Document Permission Logic: Add docstrings explaining the rules

  • Separate Concerns: Keep permission logic separate from business logic

  • Use Constants: Define permission-related constants

  • Consistent Return Values: Be explicit about what you're returning

When to read: See references/best-practices.md when writing production-ready permission code with comprehensive guidelines for security, performance, and maintainability.

Debugging Permissions

Enable Debug Mode

In Python

result = frappe.has_permission("DocType", "read", doc, debug=True)

Logs will show the permission evaluation flow

Or enable globally

frappe.conf.developer_mode = 1

Check Permission Debug Logs

After permission check with debug=True

logs = frappe.local.permission_debug_log for log in logs: print(log)

When to read: See references/debugging.md when troubleshooting permission issues with comprehensive debugging workflows, common scenarios, and logging techniques.

Common Issues and Solutions

When to read: See references/common-issues.md when facing permission problems with detailed troubleshooting for:

  • User Can't See Documents in List View

  • Can See Document in List but Can't Open

  • Permission Query Hook Not Working

  • Write Operations Fail Silently

  • Virtual DocType Permission Issues

  • Share Permissions Not Working

  • Administrator Not Seeing All Documents

Common Patterns

When to read: See references/common-patterns.md for 15 ready-to-use permission patterns including:

  • Owner-Only Access

  • Role-Based Region Filtering

  • Hierarchical Access (Team/Department)

  • Status-Based Restrictions

  • Time-Based Access

  • Multi-Tenant Access

  • Permission Level Filtering

  • Child Table Permissions

  • Conditional Field Visibility

  • Combined Role and Territory Access

Testing Permission Hooks

When to read: See references/testing.md when writing unit and integration tests for permission logic with comprehensive examples and patterns.

Migration Guide

When to read: See references/migration-guide.md for a step-by-step guide when adding custom permissions to existing DocTypes.

Core Implementation Files

Key files in Frappe codebase:

  • /frappe/permissions.py

  • Main permission system

  • /frappe/model/db_query.py

  • Permission query integration

  • /frappe/model/document.py

  • Document lifecycle and permission checks

  • /frappe/core/doctype/user_permission/

  • User permission management

Usage

When working with permissions:

  • Identify the requirement: What access control is needed?

  • Choose appropriate hook: Select based on use case

  • Reference appropriate guide: Use reference files for detailed patterns

  • Follow best practices: Security, performance, maintainability

  • Test thoroughly: With different roles and edge cases

  • Debug when needed: Use debug mode and logging

Important Notes

  • Administrator always bypasses all permission checks

  • Permission query conditions are applied to both list views AND individual document access

  • Virtual doctypes don't support permission query conditions

  • Child tables inherit parent document permissions

  • Always escape user input in SQL conditions to prevent SQL injection

  • Permission checks should be read-only operations

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

open-observe-api-expert

No summary provided by upstream source.

Repository SourceNeeds Review
General

skill-importer

No summary provided by upstream source.

Repository SourceNeeds Review
General

report-expert

No summary provided by upstream source.

Repository SourceNeeds Review
General

frappe-ci-expert

No summary provided by upstream source.

Repository SourceNeeds Review