Skip to content

Commit

Permalink
feat: initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
gromdimon committed Aug 10, 2023
1 parent 19ce749 commit 0e293f1
Show file tree
Hide file tree
Showing 7 changed files with 1,508 additions and 43 deletions.
10 changes: 10 additions & 0 deletions docs_manual/source/api_samplesheets.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,16 @@ API Views

.. autoclass:: IrodsCollsCreateAPIView

.. autoclass:: IrodsAccessTicketListAPIView

.. autoclass:: IrodsAccessTicketRetrieveAPIView

.. autoclass:: IrodsAccessTicketCreateAPIView

.. autoclass:: IrodsAccessTicketUpdateAPIView

.. autoclass:: IrodsAccessTicketDeleteAPIView

.. autoclass:: IrodsDataRequestRetrieveAPIView

.. autoclass:: IrodsDataRequestListAPIView
Expand Down
136 changes: 135 additions & 1 deletion samplesheets/serializers.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
"""API view model serializers for the samplesheets app"""

import re

from django.core.exceptions import ObjectDoesNotExist
from django.utils import timezone
from rest_framework import serializers

# Projectroles dependency
Expand All @@ -11,7 +15,13 @@
)

from samplesheets.forms import IrodsDataRequestValidateMixin
from samplesheets.models import Investigation, Study, Assay, IrodsDataRequest
from samplesheets.models import (
Investigation,
Study,
Assay,
IrodsDataRequest,
IrodsAccessTicket,
)


class AssaySerializer(SODARNestedListSerializer):
Expand Down Expand Up @@ -130,3 +140,127 @@ def create(self, validated_data):
validated_data['project'] = self.context['project']
validated_data['user'] = self.context['request'].user
return super().create(validated_data)


class IrodsAccessTicketSerializer(serializers.ModelSerializer):
"""Serializer for the IrodsAccessTicket model"""

is_active = serializers.SerializerMethodField()

class Meta:
model = IrodsAccessTicket
fields = [
'study',
'assay',
'ticket',
'path',
'user',
'date_created',
'date_expires',
'label',
'sodar_uuid',
'is_active',
]

def get_is_active(self, obj):
if not obj.date_expires:
return True
return obj.date_expires > timezone.now()

def get_read_only_fields(self):
return [
'study',
'assay',
'ticket',
'path',
'user',
'date_created',
'is_active',
'sodar_uuid',
]

def validate(self, attrs):
irods_backend = get_backend_api('omics_irods')
# Validate path (only if creating)
if not self.instance:
project = self.context['project']
try:
attrs['path'] = irods_backend.sanitize_path(attrs['path'])
except Exception as ex:
raise serializers.ValidationError(
{'path': 'Invalid iRODS path: {}'.format(ex)}
)
# Ensure path is within project
if not attrs['path'].startswith(irods_backend.get_path(project)):
raise serializers.ValidationError(
{'path': 'Path is not within the project'}
)
# Ensure path is a collection
with irods_backend.get_session() as irods:
if not irods.collections.exists(attrs['path']):
raise serializers.ValidationError(
{
'path': 'Path does not point to a collection or the'
' collection doesn\'t exist'
}
)
# Ensure path is within a project assay
match = re.search(
r'/assay_([0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12})',
attrs['path'],
)
if not match:
raise serializers.ValidationError(
{'path': 'Not a valid assay path'}
)
else:
try:
# Set assay if successful
attrs['assay'] = Assay.objects.get(
study__investigation__project=project,
sodar_uuid=match.group(1),
)
except ObjectDoesNotExist:
raise serializers.ValidationError(
{'path': 'Assay not found in project'}
)
# Ensure path is not assay root
if attrs['path'] == irods_backend.get_path(attrs['assay']):
raise serializers.ValidationError(
{
'path': 'Ticket creation for assay root path is not allowed'
}
)

# Add study from assay
attrs['study'] = attrs['assay'].study
# Add empty ticket
attrs['ticket'] = ''
# Add user from context
attrs['user'] = self.context['user']
else: # Update
attrs['path'] = self.instance.path
attrs['assay'] = self.instance.assay
attrs['study'] = self.instance.study
attrs['ticket'] = self.instance.ticket
attrs['user'] = self.instance.user

# Check if expiry date is in the past
if (
attrs.get('date_expires')
and attrs.get('date_expires') <= timezone.now()
):
raise serializers.ValidationError(
{'date_expires': 'Expiry date in the past not allowed'}
)

# Check if unexpired ticket already exists for path
if (
not self.instance
and IrodsAccessTicket.objects.filter(path=attrs['path']).first()
):
raise serializers.ValidationError(
{'path': 'Ticket for path already exists'}
)

return attrs
Loading

0 comments on commit 0e293f1

Please sign in to comment.