fairdm.contrib.plugins.access#

One access decision, consulted by both navigation and dispatch through :func:can_open.

Module Contents#

Functions#

is_instance_of

Return a predicate that passes when the record is one of model_classes.

has_perm

Resolve permission for the request’s user, memoised for the life of the request.

holds_level

Say whether the viewer holds a level on a project, dataset, sample or measurement.

resolve_check

Read a view’s predicate as declared, without invoking the descriptor protocol.

check_is_valid

Report whether check is a bool or a callable that :func:can_open can evaluate.

can_open

Decide whether the user may open this view for this record.

menu_check

Adapt :func:can_open to the check(request, **kwargs) signature flex_menu calls.

Data#

API#

logger#

‘getLogger(…)’

is_instance_of(*model_classes: type[django.db.models.Model]) → collections.abc.Callable[..., bool][source]#

Return a predicate that passes when the record is one of model_classes.

A record of None passes, so the plugin is admitted where no record is in hand.

Args: *model_classes: The accepted model classes.

Returns: A check(request, obj) predicate.

Example: Narrow a plugin to one subtype of a polymorphic record::

    class RockAnalysis(Plugin, FairDMTemplateView):
        check = staticmethod(is_instance_of(RockSample))
has_perm(request: django.http.HttpRequest, permission: str, obj: django.db.models.Model | None = None) → bool[source]#

Resolve permission for the request’s user, memoised for the life of the request.

Args: request: The current request. permission: The permission codename, with app label. obj: The record to check against, if any.

Returns: True when the user holds the permission globally or on the record.

LEVEL_ACTIONS#

None

holds_level(request: django.http.HttpRequest, level: str, obj: django.db.models.Model | None) → bool[source]#

Say whether the viewer holds a level on a project, dataset, sample or measurement.

The level is asked as the permission the record’s own pages are opened with: view_<model>, change_<model> or delete_<model>, resolved by :func:has_perm. So a level held on a record above counts, and so does the permission held for the whole portal. A visitor holds no level, on a public record as on a private one: the question is who is on the record’s team, not who may read it.

Args: request: The current request. level: "view", "edit" or "manage". obj: The record asked about.

Returns: True when the viewer holds the level or a higher one. False when there is no record, or it is not a project, dataset, sample or measurement.

Raises: ValueError: level is not one of the three.

resolve_check(view_class: type) → collections.abc.Callable[..., bool] | bool[source]#

Read a view’s predicate as declared, without invoking the descriptor protocol.

Args: view_class: The view class.

Returns: The check attribute, or True when the view declares none.

check_is_valid(check: Any) → bool[source]#

Report whether check is a bool or a callable that :func:can_open can evaluate.

A classmethod object is neither but is truthy, so it would publish a page meant to be hidden.

Args: check: The value read from a view’s check attribute.

Returns: True when the value is a bool or callable.

can_open(view_class: type, request: django.http.HttpRequest, obj: django.db.models.Model | None = None) → bool[source]#

Decide whether the user may open this view for this record.

A view answers for itself: only its own check and permission are read. An additional view listed in a plugin’s extra_views takes nothing from that plugin, so it states its own rule or stays open while the plugin is refused.

Args: view_class: The plugin or additional view class. request: The current request. obj: The record the page belongs to, if any.

Returns: True when the predicate and every required permission pass.

menu_check(view_class: type) → collections.abc.Callable[..., bool][source]#

Adapt :func:can_open to the check(request, **kwargs) signature flex_menu calls.

Args: view_class: The plugin or additional view class.

Returns: A predicate that hides the entry when the check raises.