Aller au contenu

Perms

Permission classes to be used within ninja-extra controllers.

Some permissions are global (like IsInGroup or IsRoot), and some others are per-object (like CanView or CanEdit).

Example
# restrict all the routes of this controller
# to subscribed users
@api_controller("/foo", permissions=[IsSubscriber])
class FooController(ControllerBase):
    @route.get("/bar")
    def bar_get(self):
        # This route inherits the permissions of the controller
        # ...

    @route.bar("/bar/{bar_id}", permissions=[CanView])
    def bar_get_one(self, bar_id: int):
        # per-object permission resolution happens
        # when calling either the `get_object_or_exception`
        # or `get_object_or_none` method.
        bar = self.get_object_or_exception(Counter, pk=bar_id)

        # you can also call the `check_object_permission` manually
        other_bar = Counter.objects.first()
        self.check_object_permissions(other_bar)

        # ...

    # This route is restricted to counter admins and root users
    @route.delete(
        "/bar/{bar_id}",
        permissions=[IsRoot | IsInGroup(settings.SITH_GROUP_COUNTER_ADMIN_ID)
    ]
    def bar_delete(self, bar_id: int):
        # ...

CanAccessLookup = IsLoggedInCounter | HasPerm('core.access_lookup') module-attribute

IsInGroup(group_pk)

Bases: BasePermission

Check that the user is in the group whose primary key is given.

Source code in api/permissions.py
def __init__(self, group_pk: int):
    self._group_pk = group_pk

HasPerm(perms, op=operator.and_)

Bases: BasePermission

Check that the user has the required perm.

If multiple perms are given, a comparer function can also be passed, in order to change the way perms are checked.

Example
@api_controller("/foo")
class FooController(ControllerBase):
    # this route will require both permissions
    @route.put("/foo", permissions=[HasPerm(["foo.change_foo", "foo.add_foo"])]
    def foo(self): ...

    # This route will require at least one of the perm,
    # but it's not mandatory to have all of them
    @route.put(
        "/bar",
        permissions=[HasPerm(["foo.change_bar", "foo.add_bar"], op=operator.or_)],
    )
    def bar(self): ...

Parameters:

Name Type Description Default
perms str | Permission | list[str | Permission]

a permission or a list of permissions the user must have

required
op Callable[[bool, bool], bool]

An operator to combine multiple permissions (in most cases, it will be either operator.and_ or operator.or_)

and_
Source code in api/permissions.py
def __init__(
    self,
    perms: str | Permission | list[str | Permission],
    op: Callable[[bool, bool], bool] = operator.and_,
):
    """
    Args:
        perms: a permission or a list of permissions the user must have
        op: An operator to combine multiple permissions (in most cases,
            it will be either `operator.and_` or `operator.or_`)
    """
    super().__init__()
    if not isinstance(perms, (list, tuple, set)):
        perms = [perms]
    self._operator = op
    self._perms = perms

IsRoot

Bases: BasePermission

Check that the user is root.

IsSubscriber

Bases: BasePermission

Check that the user is currently subscribed.

IsOldSubscriber

Bases: BasePermission

Check that the user has at least one subscription in its history.

CanView

Bases: BasePermission

Check that this user has the permission to view the object of this route.

Wrap the user.can_view(obj) method. To see an example, look at the example in the module docstring.

CanEdit

Bases: BasePermission

Check that this user has the permission to edit the object of this route.

Wrap the user.can_edit(obj) method. To see an example, look at the example in the module docstring.

IsOwner

Bases: BasePermission

Check that this user owns the object of this route.

Wrap the user.is_owner(obj) method. To see an example, look at the example in the module docstring.

IsLoggedInCounter

Bases: BasePermission

Check that a user is logged in a counter.