Commit 5b1dd5fb authored by Calum Mackervoy's avatar Calum Mackervoy

project admins and permissions

parent eab671ad
Pipeline #6598 passed with stage
in 27 seconds
# -*- coding: utf-8 -*-
# Generated by Django 1.11 on 2019-11-28 16:15
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('djangoldp_project', '0001_initial'),
]
operations = [
migrations.AddField(
model_name='member',
name='is_admin',
field=models.BooleanField(default=False),
),
]
from django.conf import settings
from django.db import models
from django.dispatch import receiver
from django.db.models.signals import post_save
from djangoldp.models import Model
from .permissions import ProjectPermissions, ProjectMemberPermissions
class Customer(Model):
......@@ -51,19 +54,42 @@ class Project(Model):
class Meta:
nested_fields = ['team', 'customer', 'members']
authenticated_perms = ['view', 'add', 'change', 'delete']
permission_classes = [ProjectPermissions]
rdf_type = 'hd:project'
def __str__(self):
return self.name
def get_admins(self):
return self.members.filter(is_admin=True)
class Member(Model):
project = models.ForeignKey(Project, on_delete=models.CASCADE, related_name='members')
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
name = models.CharField(max_length=255, blank=True)
is_admin = models.BooleanField(default=False)
class Meta:
container_path = "project-members/"
permission_classes = [ProjectMemberPermissions]
authenticated_perms = ["view"]
unique_together = ['user', 'project']
def __str__(self):
return self.name
def save(self, *args, **kwargs):
# cannot be duplicated Members
if not self.pk and Member.objects.filter(project=self.project, user=self.user).exists():
return
super(Member, self).save(*args, **kwargs)
Member._meta.container_path = "project-members/"
@receiver(post_save, sender=Project)
def set_captain_as_member(instance, created, **kwargs):
# add captain as an admin member, if they've not already been added
if created and instance.captain is not None and\
not instance.members.filter(user=instance.captain).exists():
Member.objects.create(user=instance.captain, project=instance, is_admin=True)
from djangoldp.permissions import LDPPermissions
# 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
class ProjectPermissions(LDPPermissions):
def has_permission(self, request, view):
# 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
# 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':
return False
if not Member.objects.filter(user=request.user, project=obj).exists():
return False
return super().has_object_permission(request, view, obj)
class ProjectMemberPermissions(LDPPermissions):
def has_permission(self, request, view):
from djangoldp.models import Model
# 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)
return is_user_admin_of_project(request.user, obj.project)
return super().has_permission(request, view)
def has_object_permission(self, request, view, obj):
# 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:
return False
# I cannot remove another admin
elif obj.is_admin:
return False
return True
# I can remove myself
if obj.user.pk == request.user.pk:
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