What are Permission Types in Frappe v15?
Answer: A permission type is a named flag used in the permissions table of a DocType that enables granting roles access to custom actions (beyond standard operations) in Frappe Framework v15.
Key details
- The standard built-in permission types include: read, write, create, delete, submit. Frappe Docs+1
- Custom permission types allow you to define additional permission flags (for example: approve, download_file, impersonate_user) which behave like the built-in ones. Frappe Docs
- They are still fairly new/experimental in Frappe. The documentation notes that “this feature is experimental and available on develop/nightly builds”. Frappe Docs
- Using custom permission types, you maintain the same role-permission mechanism (via the Role Permission Manager) but extend granularity to cover bespoke business actions.
Why Use Custom Permission Types?
Custom permission types are useful when you have business-process requirements that go beyond the typical CRUD lifecycle. Example use-cases:
- A manufacturing ERP workflow where only users with approve_batch permission may stamp a batch as “released”.
- A document management app where only users with download_attached_file can export certain files.
- A service-desk application where only users with escalate_ticket permission can escalate to a higher level.
By using custom permission types you:
- Maintain role-based assignment via the same role permissions interface.
- Keep separation of duties supervision (important for compliance, especially in India).
- Improve clarity and maintainability of permissions: each actionable permission is explicit.
- Avoid entangling custom checks with business logic—permission becomes declarative.
How to Configure Custom Permission Types in Frappe v15
Step-by-Step
- Enable Developer Mode on your site.
- Log in as the Administrator user.
- Go to Desk → Permission Type (you may need to search it if not visible).
- Create a new Permission Type record:
- Name: e.g., approve
- DocTypes: Select one or more DocTypes to which this permission type will apply.
- Module: Choose the module (used for export/import fixtures) under which this record will belong. Frappe Docs
- Save the record. If you are exporting fixtures, this JSON will be exported under your_app/your_module/permission_type/<name>.json.
- Use the Role Permission Manager to assign the newly created permission type to roles for the given DocType(s). Think of it exactly like assigning read/write permissions but with your custom flag
Code usage – Checking permissions
Once configured, you can check permissions in your backend logic like this:
import frappe
doc = frappe.get_doc("MyDocType", "MYDOC0001")
if frappe.has_permission(doc, "approve"):
# user has the custom permission
doc.run_approval_logic()
else:
frappe.throw(_("Not permitted"), frappe.PermissionError)
This mirrors the docs’ example.
You may also use client-script guards, e.g., disable buttons via frm.has_perm(“approve”).
Technical Considerations & Implementation Details
Storage & Metadata
- The Permission Type is stored in a DocType named Permission Type.
- When exported as fixture, it resides under: your_app/your_module/permission_type/<name>.json
- The Role permission table for DocTypes is extended so that besides built-in flags (read, write, etc.), the custom permission flag appears once defined.
Internals & Version 15 relevance
- In version 15 of Frappe, there was a fix to “Check permission_type in get_permitted_fieldnames”. GitHub
- This indicates that the permission_type field is recognized within the permission engine in v15.
- That said: the documentation states the feature is still experimental. So caution is advised when using in a mission-critical production environment.
Hook and override mechanisms
You can override has_permission hook for a DocType in hooks.py:
has_permission = {
"MyDocType": "myapp.permissions.mydoctype_has_permission"
}
- Then in mydoctype_has_permission(doc, user, permission_type) you can implement logic based on permission_type.
- Important note: In some forum posts users found that permission_type was always None when using the hook (especially in earlier versions). Frappe Forum
- For v15 custom permission types you must ensure your version supports passing the permission_type to the hook.
- Fallback: you may need to inspect frappe.permissions.get_doc_permissions() or debug the permission engine.
Interaction with standard permissions
- Custom permission types are additive to standard permissions. That means roles must already have the standard access (say read) for a DocType, then you may further gate actions via the custom permission.
- Be mindful: if a role lacks read but has approve, the user may not be able to open the doc to approve. So you still need typical permissions.
Best Practices & Tips
- Plan your permission model early — especially for ERP/ERPNext projects (e.g., Ahmedabad manufacturing or services). List out business actions which map to permissions (approve, escalate, archive, export) and map them to permission types.
- Keep naming consistent and meaningful — e.g., approve, export_csv, escalate, download_attachment.
- Grant minimal necessary roles — use the “least privilege” approach: roles only get exactly what they need.
- Document your custom permission types in your app README or implementation guide for future maintainers.
- Test permission boundaries — create test users for each role and verify they cannot bypass permissions. Remember the forum warning that some user permission edges are tricky. Frappe Forum
- Export fixtures for permission types and roles so they are reproducible across sites and versions (e.g., for your India-based rollout).
- Monitor changes across upgrades — because custom permissions are labeled experimental, when you upgrade from v15 to v16 (or patch versions) check for any permission engine changes.
- Audit frequently — especially for modules with financial or manufacturing data, an audit trail of permissions changes is recommended.
Real-World Example: Manufacturing ERP Scenario
Imagine you are deploying a manufacturing ERP in Ahmedabad using ERPNext built on Frappe v15. You want a role “Quality Inspector” who can view production batches and approve them for shipping, but cannot cancel them or amend them. Here’s how you’d implement:
- Create a custom permission type: name = approve_batch, DocType = Production Batch, Module = Manufacturing.
- In Role Permission Manager for Production Batch: grant read and approve_batch to the role “Quality Inspector”. Do not grant cancel or amend.
In the server script or DocType event code:
def on_submit(self):
if frappe.session.user_role == "Quality Inspector":
if not frappe.has_permission(self, "approve_batch"):
frappe.throw(_("You do not have permission to approve this batch"), frappe.PermissionError)
# otherwise proceed with approval logic
3. Test: Log in as a user with role “Quality Inspector”. They can open the batch, can click “Approve” button (enabled only if they have the custom permission), but cannot cancel or amend it.
This allows fine-grain process control fitting manufacturing compliance needs (e.g., traceability, QC sign-off) in a modular fashion.
Summary
Custom permission types in Frappe Framework v15 offer a powerful way to extend role-based access control beyond CRUD operations. By declaring permissions like approve, download, escalate and mapping them via the Role Permission Manager, developers and implementers can align the permission model closely to business workflows. For ERPNext and Frappe deployments in India (for example Ahmedabad manufacturing companies), this capability helps enforce regulatory compliance and process discipline. While the feature is marked experimental, when used with care and documented well, it significantly enhances the flexibility of your access-control architecture.
Related Topics & Cross-References
- Role Permission Manager (standard Frappe functionality)
- User Permissions (filtering by specific field values) – see docs for “Users and Permissions” Frappe Docs
- DocType Permissions and Permission Levels (how fields are grouped by level)
- Hooks: has_permission — how custom logic interacts with permission engine
- Upgrading to v15 and implications for custom permission code — migration guide for v15. GitHub