fairdm.core.utils#
Helpers for core records: polymorphic-aware permissions and fieldsets.
Module Contents#
Functions#
Return an object re-fetched through its polymorphic base’s non-polymorphic manager. |
|
Return the object a permission check or grant should actually target. |
|
Assign a permission, normalising a polymorphic instance first. |
|
Remove a permission, with the same normalisation as :func: |
|
List every permission a user or group holds on an object. |
|
List the objects a user holds a permission for, allowing for polymorphic subclasses. |
|
Group a sample model’s own fields into fieldsets, one per class in its inheritance chain. |
Data#
A regex the matches the uuid of a core data object (project, sample, measurement, etc.) and captures it in a named group ‘uuid’. |
|
API#
- UUID_RE_PATTERN#
‘^(?P
[pdsmea-zA-Z0-9_-]{22})/$’ A regex the matches the uuid of a core data object (project, sample, measurement, etc.) and captures it in a named group ‘uuid’.
- CORE_PERMISSIONS#
[(‘add_contributor’, ‘Can add contributors’), (‘modify_contributor’, ‘Can modify contributors’), (‘m…
- get_non_polymorphic_instance(obj)[source]#
Return an object re-fetched through its polymorphic base’s non-polymorphic manager.
Gated on
type_ofdirectly, not onpolymorphic_model_marker: every polymorphic model carries the marker, but onlySample,MeasurementandContributordeclaretype_of. A portal-defined polymorphic model that is none of those would otherwise raiseAttributeErrorhere rather than being left alone.Args: obj: The record to re-fetch.
Returns: The non-polymorphic instance, or
objitself when it declares notype_of.
- get_permission_target(obj, perm)[source]#
Return the object a permission check or grant should actually target.
A polymorphic subclass instance (e.g.
RockSample) carries its own app label and content type, so guardian either raisesWrongAppErroror silently misses a stored row when the permission is declared on the polymorphic base instead. Normalising to the base fixes that, but only when the base is the one that actually owns the permission being checked. Doing it unconditionally would retarget every polymorphic record’s content type, including one whose own subclass owns the permission: anOrganizationnormalised toContributorwould orphan every permission ever assigned to it.Gated on the object, not on the permission string: guardian only compares app labels when the permission carries one (
"." in perm), so a gate keyed on that would never fire for an unqualified permission and the failure would become a silent denial instead of an error.Gated on
type_ofdirectly, not onpolymorphic_model_marker: a portal-defined polymorphic model that declares notype_ofwould otherwise raiseAttributeErrorinside an authentication backend rather than being left alone.Args: obj: The record the permission is checked or granted on, or
None. perm: The permission codename, with or without an app label.Returns: The object to pass to guardian:
objitself or its non-polymorphic base instance.
- assign_perm(perm, user_or_group, obj)[source]#
Assign a permission, normalising a polymorphic instance first.
A backend takes no part in granting a right.
guardian.shortcuts.assign_permresolves the object’s own content type directly, so a permission declared on a polymorphic base (e.g.change_sample) could not be stored against a subclass instance. Uses the same gate as the check side, so the two never disagree about which records they cover.Args: perm: The permission to assign. user_or_group: The user or group receiving the permission. obj: The record the permission applies to.
Returns: Whatever
guardian.shortcuts.assign_permreturns.
- remove_perm(perm, user_or_group, obj)[source]#
Remove a permission, with the same normalisation as :func:
assign_perm.Args: perm: The permission to remove. user_or_group: The user or group losing the permission. obj: The record the permission applies to.
Returns: Whatever
guardian.shortcuts.remove_permreturns.
- get_perms(user_or_group, obj)[source]#
List every permission a user or group holds on an object.
Merges rows stored against the object’s own content type with rows stored against its polymorphic base, because :func:
assign_permmay have written to either depending on which one owns the permission, and there is no single permission here to gate the choice on.Args: user_or_group: The user or group to look up. obj: The record to look up permissions on.
Returns: The sorted permission codenames.
- get_objects_for_user(user, perm, klass, **kwargs)[source]#
List the objects a user holds a permission for, allowing for polymorphic subclasses.
guardian.shortcuts.get_objects_for_userderives its content-type filter from the permission’s own app label and model name, so a permission built from a subclass (e.g."demo.view_rocksample") finds nothing when the grant is filed under the polymorphic base’s content type (sample.view_sample). Handing it the base-model permission alongside a subclass queryset raisesMixedContentTypeError. This recomputes the permission against the base model, resolves matching primary keys there, and narrows the caller’s own queryset by them. That is safe because a polymorphic subclass shares its primary key with its base.Args: user: The user to look up. perm: The permission, in
app_label.codenameform. klass: The model or queryset to filter. **kwargs: Keyword arguments passed toguardian.shortcuts.get_objects_for_user.Returns: The queryset of objects the user holds the permission for.
- model_class_inheritance_to_fieldsets(obj_or_class)[source]#
Group a sample model’s own fields into fieldsets, one per class in its inheritance chain.
Each field appears once, under the first class in the chain that declares it, and the bookkeeping fields every sample carries (
id,local_id,imageand the like) are left out. The most derived class’s fields are then folded into the first group, and that last group is dropped.Args: obj_or_class: A sample instance or sample model class.
Returns: A list of
(name, {"fields": [...]})pairs.nameis the class’s verbose name, orNoneforSampleitself.