Skip to content

Commit

Permalink
feat: verify objects permission on external endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
helllllllder committed Jul 17, 2023
1 parent 837fee9 commit 9590306
Show file tree
Hide file tree
Showing 7 changed files with 111 additions and 6 deletions.
81 changes: 75 additions & 6 deletions chats/apps/api/v1/external/permissions.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,84 @@
from django.core.exceptions import ObjectDoesNotExist
from rest_framework import permissions

from chats.apps.projects.models import ProjectPermission


class IsAdminPermission(permissions.BasePermission):
def has_permission(self, request, view): # pragma: no cover
def get_auth_permission(self, request):
auth_header = request.META.get("HTTP_AUTHORIZATION")
auth_token = auth_header.split()[1]
permission = ProjectPermission.objects.get(pk=auth_token, role=1)
return permission

def has_permission(self, request, view): # pragma: no cover
if view.action in ["list", "create"]:
try:
permission = self.get_auth_permission(request)
project = permission.project

validation = ValidatePermissionRequest(
request_data=request.data or request.query_params, project=project
)

return validation.is_valid
except (AttributeError, IndexError, ProjectPermission.DoesNotExist):
return False

return super().has_permission(request, view)

def has_object_permission(self, request, view, obj):
"""
Return `True` if permission is granted, `False` otherwise.
"""
try:
permission = self.get_auth_permission(request)
project = obj.project
except ProjectPermission.DoesNotExist:
return False
return permission.project == project


LEVEL_NAME_MAPPING = {
"project_uuid": "project",
"project": "project",
"sector_uuid": "pk",
"sector": "pk",
"queue_uuid": "queues",
"queue": "queues",
}


class ValidatePermissionRequest:
def __init__(self, request_data, project) -> None:
self.project = project
self.data = request_data
self.queryset = {}

# Get the instance type and pk
for key in [
"project",
"sector",
"queue",
"project_uuid",
"sector_uuid",
"queue_uuid",
]:
self.level_name = LEVEL_NAME_MAPPING[key]
self.level_id = self.data.get(key, None)
if self.level_name != "project" and self.level_id is not None:
self.queryset = {self.level_name: self.level_id}
break
elif self.level_name == "project" and self.level_id is not None:
break

@property
def is_valid(self):
try:
auth_token = auth_header.split()[1]
return (
True if ProjectPermission.objects.get(pk=auth_token, role=1) else False
)
except (AttributeError, IndexError, ProjectPermission.DoesNotExist):
if self.level_name == "project":
return str(self.project.pk) == self.level_id
if self.queryset != {}:
return self.project.sectors.filter(**self.queryset).exists()
except ObjectDoesNotExist:
return False
return False
4 changes: 4 additions & 0 deletions chats/apps/dashboard/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,7 @@ class Meta:

def __str__(self):
return self.room.queue.name

@property
def project(self):
return self.room.project
8 changes: 8 additions & 0 deletions chats/apps/msgs/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,10 @@ def notify_room(self, action: str, callback: bool = False):
headers={"content-type": "application/json"},
)

@property
def project(self):
return self.room.project


class MessageMedia(BaseModel):
message = models.ForeignKey(
Expand Down Expand Up @@ -146,3 +150,7 @@ def callback(self):
def notify_room(self, *args, **kwargs):
""" """
self.message.notify_room(*args, **kwargs)

@property
def project(self):
return self.message.project
4 changes: 4 additions & 0 deletions chats/apps/projects/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -351,3 +351,7 @@ class Meta:

def __str__(self):
return self.receiver_type + ": " + self.external_id

@property
def project(self):
return self.flow_start.project
8 changes: 8 additions & 0 deletions chats/apps/queues/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,10 @@ def set_queue_authorization(self, user, role: int):
)
return sector_auth

@property
def project(self):
return self.sector.project


class QueueAuthorization(BaseModel):
ROLE_NOT_SETTED = 0
Expand Down Expand Up @@ -132,6 +136,10 @@ def get_permission(self, user):
def sector(self):
return self.queue.sector

@property
def project(self):
return self.queue.project

@property
def is_agent(self):
return self.role == self.ROLE_AGENT
Expand Down
4 changes: 4 additions & 0 deletions chats/apps/rooms/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,10 @@ def get_is_waiting(self):
check_flowstarts = self.flowstarts.filter(is_deleted=False).exists()
return check_messages or check_flowstarts

@property
def project(self):
return self.queue.project

@property
def last_contact_message(self):
return (
Expand Down
8 changes: 8 additions & 0 deletions chats/apps/sectors/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,10 @@ def notify_user(self, action):
action=f"sector_authorization.{action}",
)

@property
def project(self):
return self.sector.project


class SectorTag(BaseModel):
name = models.CharField(_("Name"), max_length=120)
Expand All @@ -251,3 +255,7 @@ class Meta:

def __str__(self):
return self.name

@property
def project(self):
return self.sector.project

0 comments on commit 9590306

Please sign in to comment.