Skip to content
Snippets Groups Projects
Commit aa855416 authored by Matthias Weinreuter's avatar Matthias Weinreuter
Browse files

Issues #5, #7: Backend fixes

parent 1f4827ac
No related branches found
No related tags found
No related merge requests found
Pipeline #391068 failed
......@@ -4,6 +4,32 @@ from projects.models import Project
from django.contrib.auth.models import User
def get_pk_int_from_context(request):
pk = request.parser_context["kwargs"].get("pk")
return None if pk is None else int(pk)
def is_any_member_from_data(request):
project_id = request.data.get("project")
if project_id is None:
return False
return check_if_in_project(project_id, request.user)
def is_any_member_from_context(request):
project_id = get_pk_int_from_context(request)
if project_id is None:
return False
return check_if_project_member(project_id, request.user)
def check_if_in_project(project_id: int, user: User):
return (
check_if_project_member(project_id, user)
or
check_if_project_manager(project_id, user)
)
def check_if_project_manager(project_id: int, user: User):
"""Check if provided user is manager of the provided project.
......@@ -32,6 +58,7 @@ def check_if_project_member(project_id: int, user: User):
Returns: True if user is member else False
"""
pass
if (
Project.objects.get(id=project_id)
.members.filter(username=user.username)
......
"""Contains permission classes."""
from rest_framework import permissions
from projects.models import Project
from mqtt.models import Role, Permission
from mqtt.permission_helpers import check_if_project_manager, check_if_project_member
from mqtt.models import Role, Permission, Device
from mqtt.permission_helpers import is_any_member_from_data, \
is_any_member_from_context, get_pk_int_from_context, check_if_in_project
class AllowProjectMembers(permissions.DjangoObjectPermissions):
"""Permissions class for the django rest framework.
* Superusers can do everything
* Every Authenticated user is allowed to create an object
* only project members or manages are allowed to change
"""
def has_permission(self, request, view):
"""Check if the User has the permission for a non object related method.
Args:
request (object): rest framework request
view (object): The view from which the filter is called
Returns:
True if user is authenticated
"""
if request.user.is_superuser:
return True
if request.user.is_authenticated and request.method in permissions.SAFE_METHODS:
if not request.user.is_authenticated:
return False
if request.method in permissions.SAFE_METHODS:
return True
if request.data.get("project"):
if check_if_project_member(
request.data.get("project"), request.user
) or check_if_project_manager(request.data.get("project"), request.user):
return True
if request.method == "PATCH" and request.parser_context["kwargs"].get("pk"):
project_id = request.parser_context["kwargs"].get("pk")
if check_if_project_member(
project_id, request.user
) or check_if_project_manager(project_id, request.user):
return True
if (
request.method == "DELETE"
): # Bypass object related methods because these will be checked later
if is_any_member_from_data(request):
return True
if request.method == "PATCH" and is_any_member_from_context(request):
return True
if request.method == "DELETE": # Bypass object related methods because these will be checked later
return True
return False
def has_object_permission(self, request, view, request_object):
"""Check if the User has the permission for an object related method.
Args:
request (object): rest framework request
view (object): The view from which the filter is called
request_object (object): The object that should be accessed
Returns:
True if user is a superuser, project member or manager
"""
if request.user.is_superuser:
return True
if request.user in request_object.project.managers.all():
......@@ -62,57 +32,27 @@ class AllowProjectMembers(permissions.DjangoObjectPermissions):
class AllowRoleProjectMembers(permissions.DjangoObjectPermissions):
"""Permissions class for the django rest framework.
* Superusers can do everything
* Every Authenticated user is allowed to create an object
* only role->project members or manages are allowed to change
"""
def has_permission(self, request, view):
"""Check if the User has the permission for a non object related method.
Args:
request (object): rest framework request
view (object): The view from which the filter is called
Returns:
True if user is authenticated
"""
if request.user.is_superuser:
return True
if request.user.is_authenticated and request.method in permissions.SAFE_METHODS:
if not request.user.is_authenticated:
return False
if request.method in permissions.SAFE_METHODS:
return True
if request.data.get("role"):
project_id = Role.objects.get(id=request.data.get("role")).project_id
if check_if_project_member(
project_id, request.user
) or check_if_project_manager(project_id, request.user):
if check_if_in_project(project_id, request.user):
return True
if request.method == "PATCH" and request.parser_context["kwargs"].get("pk"):
project_id = Permission.objects.get(
id=request.parser_context["kwargs"].get("pk")
).role.project_id
if check_if_project_member(
project_id, request.user
) or check_if_project_manager(project_id, request.user):
permission_id = get_pk_int_from_context(request)
if request.method == "PATCH" and permission_id is not None:
project_id = Permission.objects.get(id=permission_id).role.project_id
if check_if_in_project(project_id, request.user):
return True
if (
request.method == "DELETE"
): # Bypass object related methods because these will be checked later
if request.method == "DELETE": # Bypass object related methods because these will be checked later
return True
def has_object_permission(self, request, view, request_object):
"""Check if the User has the permission for an object related method.
Args:
request (object): rest framework request
view (object): The view from which the filter is called
request_object (object): The object that should be accessed
Returns:
True if user is a superuser, project member or manager
"""
if request.user.is_superuser:
return True
if request.user in request_object.role.project.managers.all():
......@@ -121,27 +61,13 @@ class AllowRoleProjectMembers(permissions.DjangoObjectPermissions):
class RootTopicPermissions(permissions.DjangoObjectPermissions):
"""Permissions class for the Root Topic Views.
* Superusers can do everything
* Project managers are allowed to create and delete an object
"""
def has_permission(self, request, view):
"""Check if the User has the permission for a non object related method.
Args:
request (object): rest framework request
view (object): The view from which the filter is called
Returns:
True if user is authenticated
"""
if request.user.is_superuser:
return True
if (
request.method in permissions.SAFE_METHODS
and request.user.is_authenticated()
and request.user.is_authenticated
):
return True
if (
......@@ -161,7 +87,41 @@ class RootTopicPermissions(permissions.DjangoObjectPermissions):
return True
def has_object_permission(self, request, view, request_object):
"""Check if the User has the permission for an object related method. Blocks all changes to the object except delete.
if request.user.is_superuser:
return True
if request.method in permissions.SAFE_METHODS:
return True
if request.method == "DELETE":
if request_object.project.managers.filter(
username=request.user.username
).exists():
return True
class AllowDeviceProjectMembers(permissions.DjangoObjectPermissions):
def has_permission(self, request, view):
"""
Check if the User has the permission for a non object related method.
"""
if request.user.is_superuser:
return True
if not request.user.is_authenticated:
return False
if request.method in permissions.SAFE_METHODS:
return True
if is_any_member_from_data(request):
return True
device_id = get_pk_int_from_context(request)
if request.method == "PATCH" and device_id is not None:
project_id = Device.objects.get(id=device_id).project_id
return check_if_in_project(project_id, request.user)
if request.method == "DELETE": # Bypass object related methods because these will be checked later
return True
return False
def has_object_permission(self, request, view, request_object):
"""Check if the User has the permission for an object related method.
Args:
request (object): rest framework request
......@@ -169,14 +129,10 @@ class RootTopicPermissions(permissions.DjangoObjectPermissions):
request_object (object): The object that should be accessed
Returns:
True if user is a superuser or request method is safe or delete
True if user is a superuser, project member or manager
"""
if request.user.is_superuser:
return True
if request.method in permissions.SAFE_METHODS:
if request.user in request_object.project.managers.all():
return True
if request.method == "DELETE":
if request_object.project.managers.filter(
username=request.user.username
).exists():
return True
return request.user in request_object.project.members.all()
......@@ -7,7 +7,7 @@ from fluffy.utils import get_message_from_validation_error
from mqtt.models import Device
from mqtt.serializers import DeviceSerializer
from mqtt.filters import ProjectUserFilter
from mqtt.permissions import AllowProjectMembers
from mqtt.permissions import AllowDeviceProjectMembers
from uuid import uuid4
import logging
......@@ -20,7 +20,7 @@ class DeviceViewSet(viewsets.ModelViewSet):
queryset = Device.objects.all()
serializer_class = DeviceSerializer
filter_backends = [ProjectUserFilter]
permission_classes = [AllowProjectMembers]
permission_classes = [AllowDeviceProjectMembers]
def create(self, request, *args, **kwargs):
if request.data.get('password') is None:
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment