Fix bugs in API perm checking

This commit is contained in:
Griatch 2021-05-23 00:42:30 +02:00
parent 07f994ce91
commit 43d678d8ca
5 changed files with 41 additions and 8 deletions

View file

@ -167,7 +167,8 @@ def perm(accessing_obj, accessed_obj, *args, **kwargs):
try: try:
permission = args[0].lower() permission = args[0].lower()
perms_object = accessing_obj.permissions.all() perms_object = accessing_obj.permissions.all()
except (AttributeError, IndexError): except (AttributeError, IndexError) as err:
print("accessing_obj err:", err)
return False return False
gtmode = kwargs.pop("_greater_than", False) gtmode = kwargs.pop("_greater_than", False)

View file

@ -693,6 +693,29 @@ def check_lockstring(
access_type=access_type, access_type=access_type,
) )
def check_perm(
obj, permission, no_superuser_bypass=False):
"""
Shortcut for checking if an object has the given `permission`. If the
permission is in `settings.PERMISSION_HIERARCHY`, the check passes
if the object has this permission or higher.
This is equivalent to calling the perm() lockfunc, but without needing
an accessed object.
Args:
obj (Object, Account): The object to check access. If this has a linked
Account, the account is checked instead (same rules as per perm()).
permission (str): The permission string to check.
no_superuser_bypass (bool, optional): If unset, the superuser
will always pass this check.
"""
from evennia.locks.lockfuncs import perm
if not no_superuser_bypass and obj.is_superuser:
return True
return perm(obj, None, permission)
def validate_lockstring(lockstring): def validate_lockstring(lockstring):
""" """

View file

@ -1,6 +1,7 @@
# Evennia API # Evennia API
## Synopsis ## Synopsis
An API, or [Application Programming Interface][wiki-api], is a way of establishing rules An API, or [Application Programming Interface][wiki-api], is a way of establishing rules
through which external services can use your program. In web development, it's through which external services can use your program. In web development, it's
often that case that the 'frontend' of a web app is written in HTML and Javascript often that case that the 'frontend' of a web app is written in HTML and Javascript
@ -141,4 +142,4 @@ the native [Fetch][fetch].
[rest]: https://en.wikipedia.org/wiki/Representational_state_transfer [rest]: https://en.wikipedia.org/wiki/Representational_state_transfer
[requests]: https://requests.readthedocs.io/en/master/ [requests]: https://requests.readthedocs.io/en/master/
[axios]: https://github.com/axios/axios [axios]: https://github.com/axios/axios
[fetch]: https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API [fetch]: https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API

View file

@ -1,13 +1,20 @@
from rest_framework import permissions """
Sets up an api-access permission check using the in-game permission hierarchy.
"""
from rest_framework import permissions
from django.conf import settings from django.conf import settings
from evennia.locks.lockhandler import check_perm
class EvenniaPermission(permissions.BasePermission): class EvenniaPermission(permissions.BasePermission):
""" """
A Django Rest Framework permission class that allows us to use A Django Rest Framework permission class that allows us to use Evennia's
Evennia's permission structure. Based on the action in a given permission structure. Based on the action in a given view, we'll check a
view, we'll check a corresponding Evennia access/lock check. corresponding Evennia access/lock check.
""" """
# subclass this to change these permissions # subclass this to change these permissions
@ -40,9 +47,9 @@ class EvenniaPermission(permissions.BasePermission):
return True return True
# these actions don't support object-level permissions, so use the above definitions # these actions don't support object-level permissions, so use the above definitions
if view.action == "list": if view.action == "list":
return request.user.has_permistring(self.MINIMUM_LIST_PERMISSION) return check_perm(request.user, self.MINIMUM_LIST_PERMISSION)
if view.action == "create": if view.action == "create":
return request.user.has_permistring(self.MINIMUM_CREATE_PERMISSION) return check_perm(request.user, self.MINIMUM_CREATE_PERMISSION)
return True # this means we'll check object-level permissions return True # this means we'll check object-level permissions
@staticmethod @staticmethod

View file

@ -7,6 +7,7 @@ actions that it detects for a viewset. For example, below we create a DefaultRou
We then register ObjectDBViewSet, a viewset for CRUD operations for ObjectDB We then register ObjectDBViewSet, a viewset for CRUD operations for ObjectDB
instances, to the 'objects' base endpoint. That will generate a number of URLs instances, to the 'objects' base endpoint. That will generate a number of URLs
like the following: like the following:
list objects: action: GET, url: /objects/, view name: object-list list objects: action: GET, url: /objects/, view name: object-list
create object: action: POST, url: /objects/, view name: object-list create object: action: POST, url: /objects/, view name: object-list
retrieve object: action: GET, url: /objects/<:pk>, view name: object-detail retrieve object: action: GET, url: /objects/<:pk>, view name: object-detail