Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

G2P-418 and G2P-432 #98

Open
wants to merge 14 commits into
base: main
Choose a base branch
from
2 changes: 1 addition & 1 deletion gene2phenotype_project/gene2phenotype_app/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -574,7 +574,7 @@ class Meta:
class Panel(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=100, unique=True, null=False)
description = models.CharField(max_length=255, null=True)
description = models.CharField(max_length=255, null=False, default="before_G2P_2025")
is_visible = models.SmallIntegerField(null=False)

def __str__(self):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from .user import UserSerializer, LoginSerializer, CreateUserSerializer, AddUserToPanelSerializer, LogoutSerializer, ChangePasswordSerializer, VerifyEmailSerializer, PasswordResetSerializer

from .panel import PanelDetailSerializer, LGDPanelSerializer
from .panel import PanelCreateSerializer, PanelDetailSerializer, LGDPanelSerializer

from .publication import PublicationSerializer, LGDPublicationSerializer, LGDPublicationListSerializer

Expand Down
90 changes: 90 additions & 0 deletions gene2phenotype_project/gene2phenotype_app/serializers/panel.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,100 @@
from rest_framework import serializers
from django.db.models import Q
from django.core.exceptions import ObjectDoesNotExist

from ..models import Panel, User, UserPanel, LGDPanel, Attrib

from ..utils import get_date_now


class PanelCreateSerializer(serializers.ModelSerializer):
"""
Panel Creation Serializer

Args:
name: short name of the panel (mandatory)
description: complete name of the panel (mandatory)
is_visible: panel visible to authenticated or non authenticated users


Raises:
serializers.ValidationError: Raises a validation error when the panel exists

Returns:
_type_: A created panel
"""
name = serializers.CharField(required=True)
description = serializers.CharField(required=True)
is_visible = serializers.BooleanField(required=True)

def validate(self, attrs):
"""
Validate the request data

Args:
attrs (_type_): A dictionary like object containing the request data

Raises:
serializers.ValidationError: Raises a validation error when the panel exists

Returns:
_type_: A validated request object
"""
name = attrs.get('name')
if Panel.objects.filter(name=name, is_visible=1).exists():
raise serializers.ValidationError({'message': 'Can not create an existing panel'})

return attrs

def create(self, validated_data):
"""
Creation of the panel if panel does not exist
Updating the panel if is_visible = 0

Args:
validated_data (_type_): validated request object

Returns:
_type_: Created panel
"""
name = validated_data.get('name')
description = validated_data.get('description')
is_visible = validated_data.get('is_visible')

if Panel.objects.filter(name=name, is_visible=0).exists() and is_visible is True:
self.update(name, is_visible, description)

if Panel.objects.filter(name=name, is_visible=0).exists() and is_visible is False:
raise serializers.ValidationError({"message" : f"{name} exist. It is only visible to authenticated users"})

panel = Panel.objects.create(name=name, description=description, is_visible=is_visible)

return panel

def update(self, name, is_visible, description):
"""
Updating the panel if the panel is_visible = 0

Args:
name (_type_): name of the panel

Returns:
_type_: Updated panel
"""
try:
panel = Panel.objects.get(name=name, is_visible=0)
panel.is_visible = is_visible
panel.description = description
panel.save()
except ObjectDoesNotExist:
raise serializers.ValidationError({"message": f"{panel} does not exist"})

return panel

class Meta:
model = Panel
fields = ['name', 'description', 'is_visible']

class PanelDetailSerializer(serializers.ModelSerializer):
"""
Serializer for the Panel model.
Expand Down
80 changes: 76 additions & 4 deletions gene2phenotype_project/gene2phenotype_app/serializers/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
from rest_framework_simplejwt.tokens import RefreshToken, TokenError
from rest_framework.validators import UniqueValidator
from django.contrib.auth.models import update_last_login
from django.core.exceptions import ObjectDoesNotExist


from ..utils import CustomMail
from ..models import User, UserPanel, Panel
Expand Down Expand Up @@ -230,10 +232,40 @@ class Meta:
}

class AddUserToPanelSerializer(serializers.ModelSerializer):
"""
Adds User to a Panel serializer
Args:
serializers (_type_):
user : Serializers CharField
panel : Serializers ListField that only accepts CharField and can not be empty

Raises:
serializers.ValidationError: If UserEmail is not sent in the request
serializers.ValidationError: If User does not exists
serializers.ValidationError: If Panel does not exists
serializers.ValidationError: If UserPanel already exists

Returns:
_type_: Created UserPanel or Updated UserPanel
"""
user = serializers.CharField(write_only=True)
panel = serializers.ListField(child=serializers.CharField(), allow_empty=False, write_only=True)

def validate(self, attrs):
"""
Validation step for the AddUserPanelSerializer

Args:
attrs (_type_): The request data that will be validated

Raises:
serializers.ValidationError: If UserEmail is not sent in the request
serializers.ValidationError: If User does not exists
serializers.ValidationError: If Panel does not exists

Returns:
_type_: Validated data
"""
user = attrs.get('user', '')
if user is None:
raise serializers.ValidationError({'message': 'user email is required to add user to panel'})
Expand All @@ -251,24 +283,64 @@ def validate(self, attrs):


def create(self, validated_data):
"""
Creates the User panel, taking the User and a list of panels from validated data
Also calls the update function if UserPanel already exists

Args:
validated_data (_type_): A dictionary object containing a list of panels and user_email

Raises:
serializers.ValidationError: If UserPanel already exists and it is not deleted

Returns:
_type_: Created UserPanel
"""
user_email = validated_data.get('user')
panels = validated_data.get('panel')

user_obj = User.objects.get(email=user_email)
for panel in panels:
panel_obj = Panel.objects.get(name=panel)

if UserPanel.objects.filter(user=user_obj, panel=panel_obj, is_deleted=1).exists():
raise serializers.ValidationError({'message': f"User {user_email} used to exists in this {panel}, Update instead"})

self.update(user_obj, panel_obj)
continue

if not UserPanel.objects.filter(user=user_obj, panel=panel_obj, is_deleted=0).exists():
user_panel = UserPanel.objects.create(user=user_obj, panel=panel_obj, is_deleted=0)
else:
raise serializers.ValidationError({'message': f"User {user_email} already exists in this {panel}"})

return user_panel

def update(self, user, panel):
"""
Updates the UserPanel, if UserPanel exists
Changes from is_deleted = 1 to is_deleted = 0

Args:
user (_type_): user object
panel (_type_): Panel object

Returns:
_type_: The updated user panel
"""
try:
user_panel = UserPanel.objects.get(user=user, panel=panel, is_deleted=1)
user_panel.is_deleted = 0
user_panel.save()


user_info = {
"message" : f"{user} has been updated in this {panel}"
}

except ObjectDoesNotExist:
return {
"message": f"{user} does not exist in this panel "
}

return user_info
class Meta:
model = UserPanel
fields = ['user', 'panel']
Expand Down
7 changes: 5 additions & 2 deletions gene2phenotype_project/gene2phenotype_app/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,8 @@ def perform_create(self, serializer):
path('curation/publish/<str:stable_id>/', views.PublishRecord.as_view(), name="publish_record"),

#user management
path("create/user/", views.CreateUserView.as_view(), name="create"),
path('add_user/panel/', views.AddUserToPanelView.as_view(), name="add_user"),
path("create/user/", views.CreateUserView.as_view(), name="create_user"),
path('add_user/panel/', views.AddUserToPanelView.as_view(), name="add_user_panel"),
path('profile/', views.ManageUserView.as_view(), name='profile'),
path('change_password/', views.ChangePasswordView.as_view(), name='change_password'),
path('reset_password/<uid>/<token>/', views.ResetPasswordView.as_view(), name='reset_password'),
Expand All @@ -81,5 +81,8 @@ def perform_create(self, serializer):
path('logout/', views.LogOutView.as_view(), name='logout'),
path('token/refresh/', views.CustomTokenRefreshView.as_view(), name='token_refresh'),

#panels management
path("create/panel/", views.PanelCreateView.as_view(), name="panel_create")

]
urlpatterns = format_suffix_patterns(urlpatterns)
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from .base import BaseView, BaseAdd, BaseUpdate, ListEndpoints

from .panel import (PanelList, PanelDetail, PanelRecordsSummary,
from .panel import (PanelCreateView, PanelList, PanelDetail, PanelRecordsSummary,
PanelDownload, LGDEditPanel)

from .locus import LocusGene, LocusGeneSummary, GeneFunction
Expand Down
10 changes: 8 additions & 2 deletions gene2phenotype_project/gene2phenotype_app/views/panel.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,16 @@
LGDPublication, LGDCrossCuttingModifier,
LGDPanel, LGDComment)

from gene2phenotype_app.serializers import PanelDetailSerializer, LGDPanelSerializer, UserSerializer
from gene2phenotype_app.serializers import PanelCreateSerializer, PanelDetailSerializer, LGDPanelSerializer, UserSerializer

from .base import BaseView, IsSuperUser, CustomPermissionAPIView

class PanelCreateView(generics.CreateAPIView):
"""
Panel Creation View
"""
serializer_class = PanelCreateSerializer
permission_classes = [permissions.IsAdminUser]

class PanelList(generics.ListAPIView):
"""
Expand Down Expand Up @@ -143,7 +149,7 @@ class LGDEditPanel(CustomPermissionAPIView):
# Define specific permissions
method_permissions = {
"post": [permissions.IsAuthenticated],
"update": [permissions.IsAuthenticated, IsSuperUser],
"update": [IsSuperUser],
}

@transaction.atomic
Expand Down
6 changes: 6 additions & 0 deletions gene2phenotype_project/gene2phenotype_app/views/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,12 @@ class CreateUserView(generics.CreateAPIView):
permission_classes = [permissions.IsAdminUser]

class AddUserToPanelView(generics.CreateAPIView):
"""
Add User to Panel view

Args:
generics (_type_): Adds User to panel, permissions is AdminUser, so views only available to AdminUser
"""
serializer_class = AddUserToPanelSerializer
permission_classes = [permissions.IsAdminUser]

Expand Down