Commit 8471e811 authored by Jean-Baptiste Pasquier's avatar Jean-Baptiste Pasquier

fix: permissions for project

parent 6c3a41cc
Pipeline #7013 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
# 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
from django.db.models.base import ModelBase
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
# 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 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):
return True
# other members can perform GET only
if request.method != 'GET':
raise PermissionDenied(detail='You must be an admin to perform this action')
def user_permissions(self, user, obj_or_model, obj=None):
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')
if isinstance(obj_or_model, ModelBase):
return ['view', 'add']
else:
obj = obj_or_model
if obj.members.filter(user=user).exists():
if obj.members.filter(user=user).get().is_admin:
return ['view', 'add', 'change', 'delete']
else:
return ['view']
return super().has_object_permission(request, view, obj)
return []
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
# 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 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
def user_permissions(self, user, obj_or_model, obj=None):
if isinstance(obj_or_model, ModelBase):
return ['view', 'add']
else:
obj = obj_or_model
if obj.user == user:
if obj.is_admin and obj.project.members.filter(is_admin=True).count() == 1:
return ['view']
else:
return ['view', 'delete']
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')
return True
if obj.project.members.filter(user=user).exists():
if obj.project.members.filter(user=user).get().is_admin:
return ['view', 'add', 'delete']
else:
return ['view']
return super().has_object_permission(request, view, obj)
return []
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