Policies¶
What decides an action - a permission within its scope, and a rule no permission can say - and where a model's policy is found.
BasePolicy
¶
Maps an action to a decision.
A subclass names its model, or declares app_label and codename
for a resource that is not one model. Each hook then asks for the
permission permissions.permission_for names - in Django's style or the
library's, whichever the model keeps. custom_actions maps a view's
action to the hook that decides it, when the two are named differently -
{'approve_all': 'can_approve'}.
check_declaration
classmethod
¶
Raise ImproperlyConfigured if this policy cannot work.
Run when the policy is registered, at import time, so a policy that names no codename, or maps an action to a hook it does not have, fails the moment the project starts rather than the first time it is asked.
allows
¶
Whether user may do action, to obj when there is one.
Whatever the hook says, an account is changed or deleted only by
somebody holding at least what it holds (safety.outranks): setting
its password is signing in as it. Reading and creating are the hook's.
authorize
¶
Raise Django's PermissionDenied unless user may do action.
hook
¶
The hook that decides action: the one custom_actions maps it
to, can_approve for approve when the policy has one, and
otherwise the action's permission within its scope.
hook_name
¶
The name of the method that would decide action, whether or not it exists.
decides_itself
¶
Whether a hook of the policy's own decides action - so a row within
the action's scope may still be refused, and only asking it can tell.
BasePolicy's hooks ask the scope and nothing more: they are not one.
permission_for
¶
The permission action requires: shop.change_order, loans.loan_approve.
has
¶
Whether user holds the permission for action.
The building block every hook starts from, so it refuses anybody not
signed in and any account switched off, itself. Django's own backend
refuses an inactive account too, but has_perm asks every backend
and grants when any one does - and a project's own backend need not
look at is_active. A switched-off account must hold nothing,
whatever is installed.
Asked without the object, because Django's own backend answers "no" to any permission asked about an object - object rules are the hooks' to add.
within_scope
¶
Whether obj is among the rows user reaches for action.
True when there is no object, or the person reaches every row of its
model. Otherwise one exists(): the same question visible answers
for a list, asked about one row.
has_within_scope
¶
The permission for action, and obj within its scope: every standard hook.
can_list
¶
Whether user may see a list at all - the rows are the queryset's to narrow.
can_view
¶
Whether user may read obj: the view permission, within its scope.
can_create
¶
Whether user may create rows. Whether the row made is within the
scope create was given in is asked once it is saved.
can_edit
¶
Whether user may change obj: the edit permission, within its scope.
can_delete
¶
Whether user may delete obj: the delete permission, within its scope.
ModelPolicy
¶
Bases: BasePolicy
The policy of a model nobody wrote one for: its permissions and its scopes.
Made by the registry, one per model, on first use - so every model is asked the same way whether or not its project wrote a policy for it.
SignedInReadPolicy
¶
Bases: BasePolicy
Readable by anybody signed in; writable by permission.
For reference data - the list of branches, the kinds of loan - that describes how a platform works rather than anything about a person. Gating its reads adds friction and protects nothing.
PermissionRegistry
¶
ResourcePermission
¶
Bases: Generic[PolicyT]
A registered policy, and what is built from it.
The bridges from a view to a policy hang off this: the DRF permission class, for one, is generated from the policy rather than written by hand.