Skip to content

Permissions not treated as units #5

@xlotlu

Description

@xlotlu

Because C.has_permission and C.has_object_permission both run self.evaluate_permissions() in a disconnected manner, this leads to the following logical error when OR-ing permissions:

Given

    A = hpA & hopA, and
    B = hpB & hopB,

A || B should really get evaluated unitarily, as

    (hpA & hopA) || (hpB & hopB),

but instead gets evaluated as

    (hpA || hpB) & (hopA || hopB)

which is incorrect, and leads to the following problem:

Consider

class A(BasePermission):
    def has_permission(self, request, view):
        return True

    def has_object_permission(self, request, view, obj):
        return False

class B(BasePermission):
    def has_permission(self, request, view):
        return False

    def has_object_permission(self, request, view, obj):
        return True

C(A) | C(B) should always return false for object-level access, but it returns true.

I saw that in #1 you dismissed maintaining state during the initial has_permission run as something downstream developers should implement, but it really needs to be done in rest_condition for logical correctness. If maintaining state, in the case above "the whole of B" would get marked as False during the initial phase, and B.has_object_permission would never get to run.

On an unrelated note, this would also be the stepping stone for dealing sensibly with mixing permissions with different combinations of has_permissions / has_object_permissions (both #1 and #2). When the method is missing (presuming one didn't inherit from BasePermission), it should be a no-op -- basically behaving like it returned True when AND-ed, and False when OR-ed.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions