پرش به محتویات

Policyها

چیزی که درباره‌ی یک اکشن تصمیم می‌گیرد - مجوزی در دامنه‌اش، و قانونی که هیچ مجوزی نمی‌تواند بگوید - و جایی که policy یک مدل پیدا می‌شود. توضیح‌های زیر از خود کد خوانده می‌شوند، و مثل کد به انگلیسی‌اند.

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

check_declaration() -> None

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

allows(user: User, action: str, obj: object | None = None) -> bool

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

authorize(user: User, action: str, obj: object | None = None) -> None

Raise Django's PermissionDenied unless user may do action.

hook

hook(action: str) -> 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

hook_name(action: str) -> str

The name of the method that would decide action, whether or not it exists.

decides_itself

decides_itself(action: str) -> bool

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

permission_for(action: str) -> str

The permission action requires: shop.change_order, loans.loan_approve.

has

has(user: User, action: str) -> bool

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

within_scope(user: User, action: str, obj: object | None) -> bool

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

has_within_scope(user: User, action: str, obj: object | None) -> bool

The permission for action, and obj within its scope: every standard hook.

can_list

can_list(user: User, obj: object | None = None) -> bool

Whether user may see a list at all - the rows are the queryset's to narrow.

can_view

can_view(user: User, obj: object | None = None) -> bool

Whether user may read obj: the view permission, within its scope.

can_create

can_create(user: User, obj: object | None = None) -> bool

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

can_edit(user: User, obj: object | None = None) -> bool

Whether user may change obj: the edit permission, within its scope.

can_delete

can_delete(user: User, obj: object | None = None) -> bool

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

PermissionRegistry()

Holds one policy instance per resource.

register

register(policy_class: type[PolicyT]) -> ResourcePermission[PolicyT]

Register a policy and return it, bound.

Raises ImproperlyConfigured when the policy is not well formed, or when another policy already holds its resource.

policy_for

policy_for(model: type[Model]) -> BasePolicy

The policy registered for model, or the model's own ModelPolicy.

ResourcePermission

ResourcePermission(policy: PolicyT)

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.

key property

key: str

loans.loan - the resource, as the registry knows it.

registry module-attribute

registry = PermissionRegistry()