Browse Source

Update API response for study

master
Joshua Rubingh 8 months ago
parent
commit
e12683c35f
  1. 5
      VRE/apps/researcher/serializers.py
  2. 39
      VRE/apps/study/serializers.py
  3. 4
      VRE/apps/study/signals.py
  4. 56
      VRE/apps/study/views.py
  5. 4
      VRE/apps/vrw/models.py

5
VRE/apps/researcher/serializers.py

@ -1,13 +1,14 @@ @@ -1,13 +1,14 @@
from rest_framework import serializers
from .models import Researcher
from django.contrib.auth.models import User
from apps.university.serializers import UniversitySerializer, FacultySerializer
class ResearcherSerializer(serializers.ModelSerializer):
#'Proxy' some data from the user model to our Researcher model.
first_name = serializers.CharField(source='user.first_name', read_only=True)
last_name = serializers.CharField(source='user.last_name', read_only=True)
email_address = serializers.CharField(source='user.email', read_only=True)
university = UniversitySerializer(source='faculty.university', read_only=True)
faculty = FacultySerializer(read_only=True)
class Meta:
model = Researcher

39
VRE/apps/study/serializers.py

@ -5,18 +5,21 @@ from apps.researcher.serializers import ResearcherSerializer @@ -5,18 +5,21 @@ from apps.researcher.serializers import ResearcherSerializer
from apps.study.models import Study, StudyRole
from apps.researcher.models import Researcher
from apps.university.serializers import StudyFieldSerializer
class ContributorSerializer(serializers.ModelSerializer):
researcher = ResearcherSerializer(read_only=True)
researcher_id = serializers.PrimaryKeyRelatedField(
researcher = ResearcherSerializer(read_only=True)
researcher_id = serializers.PrimaryKeyRelatedField(
write_only=True, source='researcher', queryset=Researcher.objects.all())
class Meta:
model = StudyRole
fields = ('researcher', 'researcher_id', 'role','active')
fields = ('researcher', 'researcher_id', 'role', 'active')
class ContributorUpdateSerializer(serializers.ModelSerializer):
researcher_id = serializers.PrimaryKeyRelatedField(
researcher_id = serializers.PrimaryKeyRelatedField(
write_only=False, source='researcher', queryset=Researcher.objects.all())
class Meta:
@ -33,13 +36,14 @@ class ContributorUpdateSerializer(serializers.ModelSerializer): @@ -33,13 +36,14 @@ class ContributorUpdateSerializer(serializers.ModelSerializer):
return obj
class StudySerializer(serializers.ModelSerializer):
contributors = serializers.SerializerMethodField()
# owner = ResearcherSerializer(required=False, read_only=True)
#owner = ResearcherSerializer(required=False, read_only=True)
class Meta:
model = Study
exclude = ['upload_code','upload_uuid']
exclude = ['upload_code', 'upload_uuid']
read_only_fields = ['owner']
extra_kwargs = {'owner': {'required': False}}
@ -66,4 +70,25 @@ class StudySerializer(serializers.ModelSerializer): @@ -66,4 +70,25 @@ class StudySerializer(serializers.ModelSerializer):
@swagger_serializer_method(serializer_or_field=ContributorSerializer(many=True))
def get_contributors(self, study_instance):
data = StudyRole.objects.filter(study=study_instance)
return [ContributorSerializer(study_role).data for study_role in data]
return [ContributorSerializer(study_role).data for study_role in data]
class StudySerializerDetail(serializers.ModelSerializer):
contributors = serializers.SerializerMethodField()
owner = ResearcherSerializer(required=False, read_only=True)
field = serializers.SerializerMethodField()
class Meta:
model = Study
exclude = ['upload_code', 'upload_uuid']
read_only_fields = ['owner']
extra_kwargs = {'owner': {'required': False}}
@swagger_serializer_method(serializer_or_field=ContributorSerializer(many=True))
def get_contributors(self, study_instance):
data = StudyRole.objects.filter(study=study_instance)
return [ContributorSerializer(study_role).data for study_role in data]
@swagger_serializer_method(serializer_or_field=StudyFieldSerializer(many=False))
def get_field(self, study_instance):
return StudyFieldSerializer(study_instance.field).data

4
VRE/apps/study/signals.py

@ -18,7 +18,7 @@ def create_virtual_machine(sender, instance, created, **kwargs): @@ -18,7 +18,7 @@ def create_virtual_machine(sender, instance, created, **kwargs):
created (bool): Is it a create or update action
"""
# check if the current researcher does have enough rights and does not have already a virtual machine
if created and instance.active and instance.role in [StudyRoleNames.OWNER, StudyRoleNames.ADMIN, StudyRoleNames.RESEARCHER] and VirtualMachine.objects.filter(researcher=instance.researcher, study=instance.study).count() == 0:
if created and instance.active and instance.role in [StudyRoleNames.ADMIN, StudyRoleNames.RESEARCHER] and VirtualMachine.objects.filter(researcher=instance.researcher, study=instance.study).count() == 0:
# Create a new virtual machine on premium profile
profile = VirtualMachineProfile.objects.get(pk=settings.DEFAULT_VM_PROFILE)
os = VirtualMachineOperatingSystem.objects.get(pk=settings.DEFAULT_VM_OS)
@ -43,4 +43,4 @@ def create_virtual_machine(sender, instance, created, **kwargs): @@ -43,4 +43,4 @@ def create_virtual_machine(sender, instance, created, **kwargs):
# Save VM to DB
vm.save()
# Add networks to the new VM
vm.networks.set(profile.networks.all())
vm.networks.set(profile.networks.all())

56
VRE/apps/study/views.py

@ -4,13 +4,16 @@ from rest_framework.response import Response @@ -4,13 +4,16 @@ from rest_framework.response import Response
from rest_framework.exceptions import ValidationError
from drf_yasg.utils import swagger_auto_schema
from rest_framework.generics import ListAPIView, RetrieveAPIView, DestroyAPIView
from apps.researcher.models import Researcher
from apps.university.models import Faculty, StudyField
from .models import Study, StudyRole, StudyRoleNames
from .serializers import StudySerializer, ContributorSerializer, ContributorUpdateSerializer
from .serializers import StudySerializer, ContributorSerializer, ContributorUpdateSerializer, StudySerializerDetail
from .permissions import IsStudyContributor
class Studies(viewsets.ModelViewSet):
"""
API endpoint for creating/reading/updating/deleting studies.
@ -18,39 +21,48 @@ class Studies(viewsets.ModelViewSet): @@ -18,39 +21,48 @@ class Studies(viewsets.ModelViewSet):
queryset = Study.objects.all().order_by('name')
serializer_class = StudySerializer
http_method_names = [ 'head','get','post','put','delete']
http_method_names = ['get', 'post', 'put', 'delete']
# Doet niets?????
#permission_classes = [IsStudyContributor]
serializer_class_by_action = {
'retrieve': StudySerializerDetail,
'list': StudySerializerDetail,
}
def get_serializer_class(self):
if hasattr(self, 'serializer_class_by_action'):
return self.serializer_class_by_action.get(self.action, self.serializer_class)
return super().get_serializer_class()
def _valid_study_field_check(self, serializer):
# Check if the study field is correct based on the researcher that is creating this study
if serializer.validated_data.get('field').faculty != self.request.user.researcher.faculty:
raise ValidationError(f'Study field {serializer.validated_data.get("field")} is not valid for faculty {self.request.user.researcher.faculty}')
def _valid_contributors_check(self, serializer):
contributors = serializer.validated_data.get('contributors', [])
if len(contributors) == 0:
# There are zero contributors, so add the current loggedin user as the first one with admin rights
contributors.append({'researcher' : self.request.user.researcher, 'role' : StudyRoleNames.ADMIN, 'active' : True})
contributors.append({'researcher': self.request.user.researcher, 'role': StudyRoleNames.ADMIN, 'active': True})
else:
# Check if the current loggedin user is already part of this study
creator_in_contributors = any([contributor['researcher'] == self.request.user.researcher for contributor in contributors])
if not creator_in_contributors:
# Add the current loggedin user as an admin to the study
contributors.append({'researcher' : self.request.user.researcher, 'role' : StudyRoleNames.ADMIN, 'active' : True})
contributors.append({'researcher': self.request.user.researcher, 'role': StudyRoleNames.ADMIN, 'active': True})
# Get a list of the researchers working on the same faculty
valid_researchers = list(Researcher.objects.filter(faculty=self.request.user.researcher.faculty).values_list('pk',flat=True))
valid_researchers = list(Researcher.objects.filter(faculty=self.request.user.researcher.faculty).values_list('pk', flat=True))
# Filter the list based on the logged in researcher his faculty
contributors = [contributor for contributor in contributors if contributor['researcher'].id in valid_researchers]
return contributors
def get_queryset(self):
if getattr(self, 'swagger_fake_view', False):
@ -77,10 +89,26 @@ class Studies(viewsets.ModelViewSet): @@ -77,10 +89,26 @@ class Studies(viewsets.ModelViewSet):
serializer.save()
@swagger_auto_schema(responses={200: StudySerializerDetail(many=False)})
def retrieve(self, request, *args, **kwargs):
return super().retrieve(request, *args, **kwargs)
@swagger_auto_schema(responses={200: StudySerializerDetail(many=True)})
def list(self, request, *args, **kwargs):
return super().list(request, *args, **kwargs)
@swagger_auto_schema(request_body=StudySerializer(many=False), responses={200: StudySerializerDetail(many=False)})
def create(self, request, *args, **kwargs):
study = super().create(request, *args, **kwargs)
# Get the created study and reload it for different serializer
study = get_object_or_404(Study, pk=study.data['id'], contributors__in=[self.request.user.researcher])
return Response(StudySerializerDetail(study).data, status=status.HTTP_200_OK)
class Contributors(GenericAPIView):
# TODO: Add check of the logged in researcher is allowed to change the contributors....
http_method_names = ['head','get','post']
http_method_names = ['head', 'get', 'post']
queryset = StudyRole.objects.all()
serializer_class = ContributorUpdateSerializer
@ -90,9 +118,9 @@ class Contributors(GenericAPIView): @@ -90,9 +118,9 @@ class Contributors(GenericAPIView):
Get all the contributors that are assigned to a study
"""
study = get_object_or_404(Study,pk=kwargs['pk'],contributors__in=[self.request.user.researcher])
study = get_object_or_404(Study, pk=kwargs['pk'], contributors__in=[self.request.user.researcher])
contributors = StudyRole.objects.filter(study=study)
return Response([ContributorSerializer(contributor).data for contributor in contributors],status=status.HTTP_200_OK)
return Response([ContributorSerializer(contributor).data for contributor in contributors], status=status.HTTP_200_OK)
@swagger_auto_schema(request_body=ContributorUpdateSerializer(many=True), responses={200: ContributorSerializer(many=True)})
def post(self, request, *args, **kwargs):
@ -102,12 +130,12 @@ class Contributors(GenericAPIView): @@ -102,12 +130,12 @@ class Contributors(GenericAPIView):
So when you remove a contributor from this list, it will be deleted from the study.
"""
study = get_object_or_404(Study,pk=kwargs['pk'],contributors__in=[self.request.user.researcher])
study = get_object_or_404(Study, pk=kwargs['pk'], contributors__in=[self.request.user.researcher])
# Get the existing list of contributors excluding the admin user. An admin user cannot be deleted
# This list is later on used for deleting the left over of this list as those contributors are not a member anymore.
deleted_contributors = list(StudyRole.objects.filter(study=study).exclude(role=StudyRoleNames.ADMIN).values_list('pk',flat=True))
deleted_contributors = list(StudyRole.objects.filter(study=study).exclude(role=StudyRoleNames.ADMIN).values_list('pk', flat=True))
# Get a list of the researchers working on the same faculty
valid_researchers = list(Researcher.objects.filter(faculty=study.field.faculty).values_list('pk',flat=True))
valid_researchers = list(Researcher.objects.filter(faculty=study.field.faculty).values_list('pk', flat=True))
for contributor in request.data:
serializer = self.get_serializer(data=contributor)

4
VRE/apps/vrw/models.py

@ -128,7 +128,9 @@ class Workspace(MetaDataModel, CloudBasicDataModel): @@ -128,7 +128,9 @@ class Workspace(MetaDataModel, CloudBasicDataModel):
# TODO: We need to speed up this query... And we do not want the 'owner' role here...
@property
def role(self):
return self.virtual_machine.study.studyrole_set.filter(researcher=self.virtual_machine.researcher).exclude(role=StudyRoleNames.OWNER).first().role
study_role = self.virtual_machine.study.studyrole_set.filter(researcher=self.virtual_machine.researcher).first()
if study_role:
return study_role.role
class WorkspaceQueue(MetaDataModel):

Loading…
Cancel
Save