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

سرویس‌ها

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

AccessService

AccessService(actor: User | None)

Makes, changes and gives out access, for one actor - None for the system.

create_bundle

create_bundle(name: str, grants: Grants) -> Group

A new bundle, holding grants.

change_bundle

change_bundle(bundle: Group, *, name: str | None = None, grants: Grants | None = None) -> Group

Rename bundle, or replace what it holds - for everybody holding it.

Renaming changes nobody's access, so even somebody holding the bundle may do it; changing what it holds is refused to them.

delete_bundle

delete_bundle(bundle: Group) -> None

Delete bundle. Whoever held it stops holding what it gave.

give_bundle

give_bundle(person: UserModel, bundle: Group) -> None

Give person bundle. Refused for one's own account, and for a bundle holding what the actor does not hold; giving it twice is no change.

take_bundle

take_bundle(person: UserModel, bundle: Group) -> None

Take bundle back from person - one given to them, not one they start with by their role. Refused for one's own account, and when it would leave nobody but the superuser able to manage access.

bundle_grants

bundle_grants(bundle: Group) -> dict[str, Scope]

What bundle holds: {permission: scope}.

grant

grant(person: UserModel, permission: str, scope: Scope = None) -> None

Give person permission directly, in scope. Granting one that was taken away from them gives it back; granting one they hold with another scope changes the scope.

revoke

revoke(person: UserModel, permission: str, *, reason: str = '') -> None

Take permission from person, whatever gives it: a direct grant is removed, and what their bundles give is subtracted for them alone.

restore

restore(person: UserModel, permission: str) -> None

Undo a revocation: person's bundles give permission again. That is giving it, so the actor must hold it, with every scope they give it in.

create_scope_rule

create_scope_rule(model: type[Model], code: str, name: str, conditions: list[dict[str, Any]], *, match: str = 'all') -> ScopeRule

A new rule scope for model, every condition checked. Nobody holds it yet, so making one changes nobody's access.

change_scope_rule

change_scope_rule(rule: ScopeRule, *, name: str | None = None, conditions: list[dict[str, Any]] | None = None, match: str | None = None) -> ScopeRule

Rename rule, or change the rows it reaches - for everybody holding a grant in it. Changing the rows is refused to whoever holds one: it would change their own access. And it is giving every permission granted in it with other rows, so the actor must hold each of them on every row: otherwise somebody holding nothing about a model could widen "the north" to every row for a colleague.

delete_scope_rule

delete_scope_rule(rule: ScopeRule) -> None

Delete rule - refused while any grant is in it, which would then reach nothing.

protect_field

protect_field(model: type[Model], field: str) -> ProtectedField

Protect model.field, making its view and edit permissions.

Nobody holds either yet, so from now on the field is left out for everybody but the superuser until a bundle holding them is given out. A field a scope rule reads is refused: the rule would tell whoever it reaches what the field holds.

unprotect_field

unprotect_field(model: type[Model], field: str) -> None

Stop protecting model.field: everybody who reads the row reads it again. Its two permissions go, and every grant of them with them.

Only somebody holding both may do it - otherwise it would give them a field they were never given - and a field protected in code is unprotected in code.

create_status_action

create_status_action(model: type[Model], code: str, name: str, field: str, to: list[Any], start: list[Any] | None = None) -> StatusAction

A new status action: from now on only whoever is allowed code writes the values in to - from the values in start, or from any.

Its permission is made with it and held by nobody, so the values are written by nobody but the superuser until it is given out.

change_status_action

change_status_action(action: StatusAction, *, name: str | None = None, to: list[Any] | None = None, start: list[Any] | None = None) -> StatusAction

Rename action, or change the values it claims and where from.

A value no longer claimed is written by whoever may write the row, so only somebody allowed the action on every row may release one. A from that lets it write from more values gives whoever holds it more: it is refused to them, whose own access it would change, and to whoever does not hold it, who has nothing to give - so it is the superuser's, and the ACCESS file's.

delete_status_action

delete_status_action(action: StatusAction) -> None

Delete action and its permission: its values are then written by whoever may write the row - so only somebody allowed it on every row may delete it.

check_grants

check_grants(grants: Grants) -> None

A ValidationError naming each permission or scope in grants that is not there.

AccessRefused

AccessRefused(rule: str, message: object)

Bases: PermissionDenied

A change to access the safety rules refuse, saying which rule - rule, for code - and why, in the language of whoever is refused.

outranks

outranks(person: object, actor: object) -> bool

Whether person's account holds anything actor does not: the superuser's flag, or a permission - or a wider scope of one.

Changing an account is holding it: whoever sets its password signs in with it. So an account is changed or deleted only by somebody holding at least what it holds - never one that would hand them more. A scope held by both counts only when it reaches the same rows for anybody: holding "their branch" is not holding somebody else's. A switched-off account counts by what switching it on would give back. Nobody outranks themselves, and nobody outranks the superuser.