Source code for evennia.web.api.permissions
"""
Sets up an api-access permission check using the in-game permission hierarchy.
"""
from django.conf import settings
from rest_framework import permissions
from evennia.locks.lockhandler import check_perm
[docs]class EvenniaPermission(permissions.BasePermission):
"""
A Django Rest Framework permission class that allows us to use Evennia's
permission structure. Based on the action in a given view, we'll check a
corresponding Evennia access/lock check.
"""
# subclass this to change these permissions
MINIMUM_LIST_PERMISSION = settings.REST_FRAMEWORK.get("DEFAULT_LIST_PERMISSION", "builder")
MINIMUM_CREATE_PERMISSION = settings.REST_FRAMEWORK.get("DEFAULT_CREATE_PERMISSION", "builder")
view_locks = settings.REST_FRAMEWORK.get("DEFAULT_VIEW_LOCKS", ["examine"])
destroy_locks = settings.REST_FRAMEWORK.get("DEFAULT_DESTROY_LOCKS", ["delete"])
update_locks = settings.REST_FRAMEWORK.get("DEFAULT_UPDATE_LOCKS", ["control", "edit"])
[docs] def has_permission(self, request, view):
"""Checks for permissions
Args:
request (Request): The incoming request object.
view (View): The django view we are checking permission for.
Returns:
bool: If permission is granted or not. If we return False here, a PermissionDenied
error will be raised from the view.
Notes:
This method is a check that always happens first. If there's an object involved,
such as with retrieve, update, or delete, then the has_object_permission method
is called after this, assuming this returns `True`.
"""
# Only allow authenticated users to call the API
if not request.user.is_authenticated:
return False
if request.user.is_superuser:
return True
# these actions don't support object-level permissions, so use the above definitions
if view.action == "list":
return check_perm(request.user, self.MINIMUM_LIST_PERMISSION)
if view.action == "create":
return check_perm(request.user, self.MINIMUM_CREATE_PERMISSION)
return True # this means we'll check object-level permissions
[docs] @staticmethod
def check_locks(obj, user, locks):
"""Checks access for user for object with given locks
Args:
obj: Object instance we're checking
user (Account): User who we're checking permissions
locks (list): list of lockstrings
Returns:
bool: True if they have access, False if they don't
"""
return any([obj.access(user, lock) for lock in locks])
[docs] def has_object_permission(self, request, view, obj):
"""Checks object-level permissions after has_permission
Args:
request (Request): The incoming request object.
view (View): The django view we are checking permission for.
obj: Object we're checking object-level permissions for
Returns:
bool: If permission is granted or not. If we return False here, a PermissionDenied
error will be raised from the view.
Notes:
This method assumes that has_permission has already returned True. We check
equivalent Evennia permissions in the request.user to determine if they can
complete the action.
"""
if view.action in ("list", "retrieve"):
# access_type is based on the examine command
return self.check_locks(obj, request.user, self.view_locks)
if view.action == "destroy":
# access type based on the destroy command
return self.check_locks(obj, request.user, self.destroy_locks)
if view.action in ("update", "partial_update", "set_attribute"):
# access type based on set command
return self.check_locks(obj, request.user, self.update_locks)