mirror of
https://github.com/eitchtee/WYGIWYH.git
synced 2026-09-10 11:51:54 +02:00
Add apps.common.functions.get_owned_object_or_403, an ownership-enforcing variant of get_object_or_404, and apply it across every rules handler that resolved a TransactionRule / (UpdateOrCreate)TransactionRuleAction from a URL id without an owner check. Mirrors the check in transaction_rule_edit (obj.owner and obj.owner != request.user); objects with no owner remain accessible, preserving existing behaviour. Nested ownership (actions owned via their parent rule) is handled with owner_path='rule.owner'.
37 lines
1.4 KiB
Python
37 lines
1.4 KiB
Python
from django.core.exceptions import PermissionDenied
|
|
from django.shortcuts import get_object_or_404
|
|
|
|
|
|
def get_owned_object_or_403(klass, request, *args, owner_path="owner", **kwargs):
|
|
"""Fetch an object like ``get_object_or_404`` while enforcing ownership.
|
|
|
|
Returns the object when it has no owner, or when it is owned by
|
|
``request.user``; otherwise raises :class:`~django.core.exceptions.PermissionDenied`
|
|
(HTTP 403). This mirrors the owner check used by ``transaction_rule_edit``
|
|
(``if obj.owner and obj.owner != request.user``) so authorization is applied
|
|
uniformly across handlers that resolve an object from a URL id.
|
|
|
|
An object with no owner stays accessible to everyone, preserving the
|
|
existing behaviour for legacy/unowned objects.
|
|
|
|
``owner_path`` is a dotted attribute path to the owning user, so nested
|
|
ownership is supported for objects owned through a relation, e.g. a rule
|
|
action owned via its parent rule::
|
|
|
|
get_owned_object_or_403(
|
|
TransactionRuleAction, request, id=pk, owner_path="rule.owner"
|
|
)
|
|
"""
|
|
obj = get_object_or_404(klass, *args, **kwargs)
|
|
|
|
owner = obj
|
|
for attr in owner_path.split("."):
|
|
owner = getattr(owner, attr, None)
|
|
if owner is None:
|
|
break
|
|
|
|
if owner is not None and owner != request.user:
|
|
raise PermissionDenied
|
|
|
|
return obj
|