Commit f1579684 authored by Calum Mackervoy's avatar Calum Mackervoy

Merge branch 'fix-permissions' into 'master'

fix: permissions for project

See merge request !30
parents 6c3a41cc 945f9364
Pipeline #7031 passed with stage
in 27 seconds
......@@ -55,7 +55,6 @@ class Project(Model):
class Meta:
nested_fields = ['team', 'customer', 'members']
authenticated_perms = ['view', 'add', 'change', 'delete']
permission_classes = [ProjectPermissions]
rdf_type = 'hd:project'
......@@ -75,7 +74,6 @@ class Member(Model):
class Meta:
container_path = "project-members/"
permission_classes = [ProjectMemberPermissions]
authenticated_perms = ["view"]
unique_together = ['user', 'project']
def __str__(self):
......
from djangoldp.permissions import LDPPermissions
from rest_framework.exceptions import PermissionDenied
from django.db.models.base import ModelBase
# auxiliary function tests user is an admin for specified project
def is_user_admin_of_project(user, project):
from .models import Member
try:
project_member = Member.objects.get(user=user, project=project)
return project_member.is_admin
except:
return False
def get_client_ip(request):
x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
if x_forwarded_for:
ip = x_forwarded_for.split(',')[0]
else:
ip = request.META.get('REMOTE_ADDR')
return ip
class ProjectPermissions(LDPPermissions):
def has_permission(self, request, view):
# anonymous users have no rights
if request.user.is_anonymous and not request.method == 'OPTIONS':
return False
def user_permissions(self, user, obj_or_model, obj=None):
if not user.is_anonymous:
if not isinstance(obj_or_model, ModelBase):
obj = obj_or_model
if obj:
if obj.members.filter(user=user).exists():
if obj.members.filter(user=user).get().is_admin:
return ['view', 'add', 'change', 'delete']
else:
return ['view']
else:
return ['view', 'add']
# request on an existing resource - this will be reviewed by has_object_permission
if request.method == 'PATCH' or request.method == 'DELETE' or request.method == 'PUT':
return []
def has_permission(self, request, view):
if(get_client_ip(request) == '51.15.243.248'):
return True
return super().has_permission(request, view)
def has_object_permission(self, request, view, obj):
from .models import Member
# anonymous users have no rights
if request.user.is_anonymous and not request.method == 'OPTIONS':
return False
# admins have full permissions
if is_user_admin_of_project(request.user, obj):
if(get_client_ip(request) == '51.15.243.248'):
return True
# other members can perform GET only
if request.method != 'GET':
raise PermissionDenied(detail='You must be an admin to perform this action')
if not Member.objects.filter(user=request.user, project=obj).exists():
raise PermissionDenied(detail='You must be a member of this project to perform this action')
return super().has_object_permission(request, view, obj)
class ProjectMemberPermissions(LDPPermissions):
def has_permission(self, request, view):
from djangoldp.models import Model
# anonymous users have no rights
if request.user.is_anonymous and not request.method == 'OPTIONS':
return False
def user_permissions(self, user, obj_or_model, obj=None):
if not user.is_anonymous:
if not isinstance(obj_or_model, ModelBase):
obj = obj_or_model
if obj:
if not hasattr(obj, 'user'):
return ['view', 'add']
elif obj.user == user:
if obj.is_admin and obj.project.members.filter(is_admin=True).count() == 1:
return ['view']
else:
return ['view', 'delete']
else:
if obj.project.members.filter(user=user).exists():
if obj.project.members.filter(user=user).get().is_admin:
if obj.is_admin:
return ['view', 'add']
else:
return ['view', 'add', 'delete']
else:
return ['view']
else:
return ['view', 'add']
# request on an existing resource - this will be reviewed by has_object_permission
if request.method == 'PATCH' or request.method == 'DELETE' or request.method == 'PUT':
return []
def has_permission(self, request, view):
if(get_client_ip(request) == '51.15.243.248'):
return True
# only admins can add new members to a project
if request.method == 'POST':
obj = Model.resolve_id(request._request.path)
if is_user_admin_of_project(request.user, obj.project):
return True
else:
raise PermissionDenied(detail='You must be an admin to perform this action')
return super().has_permission(request, view)
def has_object_permission(self, request, view, obj):
# anonymous users have no rights
if request.user.is_anonymous and not request.method == 'OPTIONS':
return False
# I can remove myself
if obj.user.pk == request.user.pk:
return True
# admins have full permissions
if is_user_admin_of_project(request.user, obj.project):
if request.method == 'DELETE':
# I cannot remove myself if I am the last admin
if obj.pk == request.user.pk:
if obj.project.get_admins().count() == 1:
raise PermissionDenied(detail='To leave this project, you must first set up a new administrator'
' through the project panel')
# I cannot remove another admin
elif obj.is_admin:
raise PermissionDenied(detail='You cannot remove another admin')
if(get_client_ip(request) == '51.15.243.248'):
return True
return super().has_object_permission(request, view, obj)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment