Permissions¶
Note
This document covers the internals of Wagtail’s permissions system. You should read about how Wagtail makes use of Django’s permissions system first.
Please note that aside from the register_permission_policy() function, the APIs described in this document are considered internal and thus are not subject to our Deprecation policy.
At the basic level, Wagtail’s permission system is implemented using a set of classes called “permission policies” that define the permission rules for a given Django model. Whenever a permission test is performed, a global registry is consulted to determine the permission policy instance to use for a given Django model. As such, any model managed within Wagtail should register a corresponding permission policy instance to the global registry.
Other supporting code (not documented here) is used by pages and snippets to cater for more specific permission checks needed by features such as publishing, locking, and workflows. As a result, the following should not be considered a comprehensive documentation of how Wagtail does permission checks.
Permission policies¶
- class wagtail.permission_policies.BasePermissionPolicy(model)¶
A ‘permission policy’ is an object that handles all decisions about the actions users are allowed to perform on a given model. The mechanism by which it does this is arbitrary, and may or may not involve the
django.contrib.authPermissionmodel; it could be as simple as “allow all users to do everything”.In this way, admin apps can change their permission-handling logic just by swapping to a different policy object, rather than having that logic spread across numerous view functions.
BasePermissionPolicyis an abstract class that all permission policies inherit from. The only method that subclasses need to implement isusers_with_any_permission(); all other methods can be derived from that (but in practice, subclasses will probably want to override additional methods, either for efficiency or to implement more fine-grained permission logic).- Parameters:
model – The model class that this permission policy applies to. This may be a model class or a string in the form of
app_label.model_name.
- get_all_permissions_for_user(user)¶
Return a set of all permissions that the given user has on this model.
They may be instances of
Permission, or custom permission objects defined by the policy, which are not necessarily model instances.
- get_cached_permissions_for_user(user)¶
Return a list of all permissions that the given user has on this model, using the cache if available and populating the cache if not.
This can be useful for the other methods to perform efficient queries against the set of permissions that the user has.
- user_has_permission(user, action)¶
Return whether the given user has permission to perform the given action on some or all instances of this model.
- user_has_any_permission(user, actions)¶
Return whether the given user has permission to perform any of the given actions on some or all instances of this model.
- users_with_any_permission(actions)¶
Return a queryset of users who have permission to perform any of the given actions on some or all instances of this model.
- users_with_permission(action)¶
Return a queryset of users who have permission to perform the given action on some or all instances of this model.
- user_has_permission_for_instance(user, action, instance)¶
Return whether the given user has permission to perform the given action on the given model instance.
- user_has_any_permission_for_instance(user, actions, instance)¶
Return whether the given user has permission to perform any of the given actions on the given model instance.
- instances_user_has_any_permission_for(user, actions)¶
Return a queryset of all instances of this model for which the given user has permission to perform any of the given actions.
- instances_user_has_permission_for(user, action)¶
Return a queryset of all instances of this model for which the given user has permission to perform the given action.
- users_with_any_permission_for_instance(actions, instance)¶
Return a queryset of all users who have permission to perform any of the given actions on the given model instance.
- users_with_permission_for_instance(action, instance)¶
Return a queryset of all users who have permission to perform the given action on the given model instance.
- class wagtail.permission_policies.BaseDjangoAuthPermissionPolicy(model, auth_model=None)¶
Extends
BasePermissionPolicywith helper methods useful for policies that need to perform lookups against thePermissionmodel.- Parameters:
model – The model class that this permission policy applies to. This may be a model class or a string in the form of
app_label.model_name.auth_model – The model class (or a string in the form of
app_label.model_name) to use for permission record lookups. Usually this will matchmodel(which specifies the type of instances thatinstances_user_has_permission_for()will return), but this may differ when swappable models are in use - for example, an interface for editing user records might use a customUsermodel but will typically still refer to the permission records forauth.User.
- class wagtail.permission_policies.ModelPermissionPolicy(model, auth_model=None)¶
A permission policy that enforces permissions at the model level, by consulting the standard
Permissionmodel directly.
- class wagtail.permission_policies.OwnershipPermissionPolicy(model, auth_model=None, owner_field_name='owner')¶
A permission policy for objects that support a concept of ‘ownership’, where the owner is typically the user who created the object.
This policy piggybacks off
addandchangepermissions defined through thePermissionmodel, as follows:any user with
addpermission can create instances, and ALSO edit instances that they ownany user with
changepermission can edit instances regardless of ownershipability to edit also implies ability to delete
Besides
add,changeanddelete, no other actions are recognised or permitted (unless the user is an active superuser, in which case they can do everything).
- class wagtail.permission_policies.collections.CollectionPermissionPolicy(model, auth_model=None)¶
A permission policy for objects that are assigned locations in the
Collectiontree. Permissions may be defined at any node of the hierarchy, through theGroupCollectionPermissionmodel, and propagate downwards. These permissions are applied to objects according to the standardPermissionmodel.
- class wagtail.permission_policies.collections.CollectionOwnershipPermissionPolicy(model, auth_model=None, owner_field_name='owner')¶
A permission policy for objects that are assigned locations in the Collection tree. Permissions may be defined at any node of the hierarchy, through the
GroupCollectionPermissionmodel, and propagate downwards. These permissions are applied to objects according to the ‘ownership’ permission model (seeOwnershipPermissionPolicy).
- class wagtail.permission_policies.collections.CollectionManagementPermissionPolicy(model, auth_model=None)¶
A permission policy for managing collections themselves, rather than objects assigned to collections.
- class wagtail.permission_policies.pages.PagePermissionPolicy(model=None)¶
A permission policy for page objects, which are arranged in a tree structure. Permissions may be defined at any node of the tree, through the
GroupPagePermissionmodel, and propagate downwards. These permissions are applied to objects according to the ‘ownership’ permission model (seeOwnershipPermissionPolicy).
- class wagtail.permission_policies.sites.SitePermissionPolicy(model, auth_model=None, site_field_name='site')¶
A permission policy for objects that are associated with site records, such as
wagtail.contrib.settings.models.BaseSiteSettingsubclasses (see Settings models). Permissions may be assigned globally through standardPermissionobjects, or for individual sites throughwagtail.models.GroupSitePermissionrecords.
Permission policy registry¶
- class wagtail.permissions.PolicyRegistry¶
A registry that maps model classes to their permission policy instances. This is used by Wagtail to determine which permission policy to use for a given model class.
Instead of using this class directly, use the global
policy_registryinstance and theregister_permission_policy()function instead.- get_by_type(cls: type[Model], fallback=True) BasePermissionPolicy¶
Get the permission policy for a given model class. If a matching policy was registered with
exact_class=True, it will be returned. Otherwise, the policy registered withexact_class=Falsefor the given class or its nearest ancestor class will be returned. If no policy can be found andfallbackis True, a default fallbackModelPermissionPolicywill be used. Otherwise, returnNone.
- get(obj: Model) BasePermissionPolicy¶
Get the permission policy for a given model instance based on its class.
- wagtail.permissions.policy_registry = <wagtail.permissions.PolicyRegistry object>¶
A global instance of
PolicyRegistryused to register and look up permission policies for models managed by Wagtail.
Retrieving a permission policy for a given Django model class or instance can be done as below.
from wagtail.permissions import policy_registry
from .models import MyModel
# With the model class
policy_registry.get_by_type(MyModel)
# With a model instance
policy_registry.get(MyModel.objects.first())
- wagtail.permissions.register_permission_policy(model: type[Model], policy: BasePermissionPolicy = None, exact_class=False)¶
Register a permission policy for a given model class.
If no policy is provided, a default
ModelPermissionPolicywill be created. Ifexact_classis set to True, the policy will only be used for the exact model class, otherwise it will also be used for subclasses of the model class.
To register a permission policy for a model, call this function at the top of
the model app’s wagtail_hooks.py.
# wagtail_hooks.py
from wagtail.permissions import register_permission_policy
from .models import MyModel
register_permission_policy(MyModel)
... # More customizations
Alternatively, you can also call the function from the
AppConfig.ready() method.
# apps.py
class MyAppConfig(AppConfig):
...
def ready(self):
from wagtail.permissions import register_permission_policy
from .models import MyModel
register_permission_policy(MyModel)
Note
Currently, register_permission_policy(MyModel) is the only officially supported use case of this function.
While it is possible to register a custom permission policy instance for any model (including Wagtail’s built-in models), we cannot guarantee that a custom permissions implementation would always be respected by Wagtail. We intend to support this in the future. Refer to our issue tracker for supporting custom permission behavior for more details.