diff --git a/cri_api/serializers/__init__.py b/cri_api/serializers/__init__.py index 95a169b067ab1d110902b315c382a3c771a3be63..8bac94c2ddaccecf138eca7c0066eddc93c63ee9 100644 --- a/cri_api/serializers/__init__.py +++ b/cri_api/serializers/__init__.py @@ -1,281 +1,31 @@ -from django.db import transaction - -from rest_framework import serializers -from rest_framework_serializer_field_permissions.serializers import ( - FieldPermissionSerializerMixin, +from .cards import CardGenerationSerializer +from .models import ( + CRIComputedMembershipSerializer, + CRIGroupSerializer, + CRIUserSearchSerializer, + CRIUserSerializer, + CampusSerializer, + ProfileSerializer, + SimpleCRIGroupSerializer, + SimpleCRIUserSerializer, +) +from .criusercreationrequest import ( + CRIUserCreateSerializer, + NestedCRIMembershipCreateSerializer, + NestedKerberosPrincipalSerializer, ) -from rest_framework_serializer_field_permissions import fields - -from cri_models import models -from .. import permissions - - -class SimpleCRIUserSerializer( - FieldPermissionSerializerMixin, serializers.HyperlinkedModelSerializer -): - login = serializers.CharField(read_only=True, source="username") - - old_accounts = fields.ListField( - read_only=True, - source="get_old_accounts", - child=fields.CharField(), - permission_classes=(permissions.CanViewRelatedAccounts(),), - ) - - new_account = fields.CharField( - read_only=True, - allow_null=True, - source="get_new_account", - permission_classes=(permissions.CanViewRelatedAccounts(),), - ) - - class Meta: - model = models.CRIUser - fields = ("url", "login", "old_accounts", "new_account") - extra_kwargs = { - "url": {"lookup_field": "username", "lookup_url_kwarg": "login"} - } - - -class SimpleCRIGroupSerializer(serializers.HyperlinkedModelSerializer): - class Meta: - model = models.CRIGroup - fields = ("url", "slug") - extra_kwargs = {"url": {"lookup_field": "slug"}} - - -class CampusSerializer(serializers.HyperlinkedModelSerializer): - name = serializers.CharField(source="group.name", read_only=True) - - group = SimpleCRIGroupSerializer(read_only=True) - - class Meta: - model = models.Campus - fields = ("url", "slug", "group", "name") - extra_kwargs = {"url": {"lookup_field": "slug"}} - - -class CRIGroupSerializer(serializers.HyperlinkedModelSerializer): - members_url = serializers.HyperlinkedIdentityField( - read_only=True, view_name="crigroup-members", lookup_field="slug" - ) - - history_url = serializers.HyperlinkedIdentityField( - read_only=True, view_name="crigroup-history", lookup_field="slug" - ) - - managers = SimpleCRIUserSerializer(read_only=True, many=True, source="get_managers") - - class Meta: - model = models.CRIGroup - fields = ( - "url", - "slug", - "gid", - "name", - "kind", - "members_url", - "history_url", - "managers", - "private", - ) - extra_kwargs = {"url": {"lookup_field": "slug"}} - - -class CRIComputedMembershipSerializer(serializers.ModelSerializer): - user = SimpleCRIUserSerializer(read_only=True) - - group = SimpleCRIGroupSerializer(read_only=True) - - is_current = fields.BooleanField(read_only=True) - - class Meta: - model = models.CRIComputedMembership - fields = ( - "group", - "user", - "begin_at", - "end_at", - "graduation_year", - "is_current", - ) - - def __init__(self, *args, excluded_fields=None, **kwargs): - super().__init__(*args, **kwargs) - self.excluded_fields = excluded_fields or [] - - def to_representation(self, instance): - r = super().to_representation(instance) - return {k: v for k, v in r.items() if k not in self.excluded_fields} - - -class ProfileSerializer(serializers.HyperlinkedModelSerializer): - login = serializers.CharField(read_only=True, source="username") - - primary_group = SimpleCRIGroupSerializer(read_only=True) - - groups_history = CRIComputedMembershipSerializer( - many=True, - read_only=True, - source="crimembership_set", - excluded_fields=["user"], - ) - - current_groups = SimpleCRIGroupSerializer( - many=True, read_only=True, source="get_groups" - ) - - old_accounts = fields.ListField( - read_only=True, child=fields.CharField(), source="get_old_accounts" - ) - - new_account = serializers.CharField( - required=False, - read_only=True, - allow_null=True, - source="get_new_account", - ) - - class Meta: - model = models.CRIUser - fields = ( - "url", - "login", - "uid", - "primary_group", - "first_name", - "last_name", - "legal_first_name", - "legal_last_name", - "email", - "phone", - "birthdate", - "groups_history", - "current_groups", - "old_accounts", - "new_account", - ) - extra_kwargs = { - "url": {"lookup_field": "username", "lookup_url_kwarg": "login"} - } - - -class CRIUserSerializer(FieldPermissionSerializerMixin, ProfileSerializer): - old_accounts = fields.ListField( - read_only=True, - child=fields.CharField(), - source="get_old_accounts", - permission_classes=(permissions.CanViewRelatedAccounts(),), - ) - - new_account = fields.CharField( - required=False, - read_only=True, - allow_null=True, - source="get_new_account", - permission_classes=(permissions.CanViewRelatedAccounts(),), - ) - - legal_first_name = fields.CharField( - required=False, - permission_classes=(permissions.CanViewLegalIdentity(),), - ) - - legal_last_name = fields.CharField( - required=False, - permission_classes=(permissions.CanViewLegalIdentity(),), - ) - - phone = fields.CharField( - required=False, permission_classes=(permissions.CanViewPhone(),) - ) - - birthdate = fields.CharField( - required=False, permission_classes=(permissions.CanViewBirthdate(),) - ) - - -class NestedCRIMembershipCreateSerializer(serializers.ModelSerializer): - group = serializers.SlugRelatedField( - slug_field="slug", queryset=models.CRIGroup.objects.all() - ) - - class Meta: - model = models.CRIMembership - fields = ("group", "begin_at", "end_at", "graduation_year") - - -class NestedKerberosPrincipalSerializer(serializers.ModelSerializer): - is_primary = fields.BooleanField(write_only=True, default=False) - - class Meta: - model = models.KerberosPrincipal - fields = ("principal", "is_primary", "out_of_date") - - -class CRIUserCreateSerializer(serializers.ModelSerializer): - primary_group = serializers.CharField() - - login = serializers.CharField(source="username") - - memberships = NestedCRIMembershipCreateSerializer(many=True) - - kerberos_principals = NestedKerberosPrincipalSerializer( - many=True, source="kerberosprincipal_set" - ) - - class Meta: - model = models.CRIUser - fields = ( - "login", - "uid", - "primary_group", - "first_name", - "last_name", - "legal_first_name", - "legal_last_name", - "email", - "phone", - "birthdate", - "memberships", - "kerberos_principals", - ) - - def validate(self, attrs): - principals = attrs.get("kerberosprincipal_set", []) - if len([p for p in principals if p.get("is_primary", False)]) > 1: - raise serializers.ValidationError( - "Only one Kerberos principal can be set as primary principal" - ) - - return super().validate(attrs) - - @transaction.atomic() - def create(self, validated_data): - primary_group = models.CRIGroup.objects.get( - slug=validated_data.pop("primary_group") - ) - validated_data["primary_group"] = primary_group - memberships = validated_data.pop("memberships", []) - kerberos_principals = validated_data.pop("kerberosprincipal_set", []) - instance = super().create(validated_data) - for membership in memberships: - membership["user"] = instance - NestedCRIMembershipCreateSerializer(membership).create(membership) - for principal in kerberos_principals: - principal["user"] = instance - is_primary = principal.pop("is_primary", False) - principal_instance = NestedKerberosPrincipalSerializer(principal).create( - principal - ) - if is_primary: - instance.primary_principal = principal_instance - instance.save() - instance.sync() - return instance - - -class CRIUserSearchSerializer(serializers.Serializer): - logins = fields.ListField(write_only=True, child=fields.CharField()) - uids = fields.ListField(write_only=True, child=fields.IntegerField()) +__all__ = ( + "CRIComputedMembershipSerializer", + "CRIGroupSerializer", + "CRIUserCreateSerializer", + "CRIUserSearchSerializer", + "CRIUserSerializer", + "CampusSerializer", + "CardGenerationSerializer", + "NestedCRIMembershipCreateSerializer", + "NestedKerberosPrincipalSerializer", + "ProfileSerializer", + "SimpleCRIGroupSerializer", + "SimpleCRIUserSerializer", +) diff --git a/cri_api/serializers/criusercreation.py b/cri_api/serializers/criusercreation.py new file mode 100644 index 0000000000000000000000000000000000000000..c78bedf9c23e014f7831c194cc95502fad5551de --- /dev/null +++ b/cri_api/serializers/criusercreation.py @@ -0,0 +1,82 @@ +from rest_framework import serializers +from cri_models import models + + +class NestedCRIMembershipCreateSerializer(serializers.ModelSerializer): + group = serializers.SlugRelatedField( + slug_field="slug", queryset=models.CRIGroup.objects.all() + ) + + class Meta: + model = models.CRIMembership + fields = ("group", "begin_at", "end_at", "graduation_year") + + +class NestedKerberosPrincipalSerializer(serializers.ModelSerializer): + is_primary = fields.BooleanField(write_only=True, default=False) + + class Meta: + model = models.KerberosPrincipal + fields = ("principal", "is_primary", "out_of_date") + + +class CRIUserCreateSerializer(serializers.ModelSerializer): + primary_group = serializers.CharField() + + login = serializers.CharField(source="username") + + memberships = NestedCRIMembershipCreateSerializer(many=True) + + kerberos_principals = NestedKerberosPrincipalSerializer( + many=True, source="kerberosprincipal_set" + ) + + class Meta: + model = models.CRIUser + fields = ( + "login", + "uid", + "primary_group", + "first_name", + "last_name", + "legal_first_name", + "legal_last_name", + "email", + "phone", + "birthdate", + "memberships", + "kerberos_principals", + ) + + def validate(self, attrs): + principals = attrs.get("kerberosprincipal_set", []) + if len([p for p in principals if p.get("is_primary", False)]) > 1: + raise serializers.ValidationError( + "Only one Kerberos principal can be set as primary principal" + ) + + return super().validate(attrs) + + @transaction.atomic() + def create(self, validated_data): + primary_group = models.CRIGroup.objects.get( + slug=validated_data.pop("primary_group") + ) + validated_data["primary_group"] = primary_group + memberships = validated_data.pop("memberships", []) + kerberos_principals = validated_data.pop("kerberosprincipal_set", []) + instance = super().create(validated_data) + for membership in memberships: + membership["user"] = instance + NestedCRIMembershipCreateSerializer(membership).create(membership) + for principal in kerberos_principals: + principal["user"] = instance + is_primary = principal.pop("is_primary", False) + principal_instance = NestedKerberosPrincipalSerializer(principal).create( + principal + ) + if is_primary: + instance.primary_principal = principal_instance + instance.save() + instance.sync() + return instance diff --git a/cri_api/serializers/models.py b/cri_api/serializers/models.py new file mode 100644 index 0000000000000000000000000000000000000000..d88e7add18f6a2f6d215c759b98d4421c323576e --- /dev/null +++ b/cri_api/serializers/models.py @@ -0,0 +1,201 @@ +from django.db import transaction + +from rest_framework import serializers +from rest_framework_serializer_field_permissions.serializers import ( + FieldPermissionSerializerMixin, +) +from rest_framework_serializer_field_permissions import fields + +from cri_models import models +from .. import permissions + + +class SimpleCRIUserSerializer( + FieldPermissionSerializerMixin, serializers.HyperlinkedModelSerializer +): + login = serializers.CharField(read_only=True, source="username") + + old_accounts = fields.ListField( + read_only=True, + source="get_old_accounts", + child=fields.CharField(), + permission_classes=(permissions.CanViewRelatedAccounts(),), + ) + + new_account = fields.CharField( + read_only=True, + allow_null=True, + source="get_new_account", + permission_classes=(permissions.CanViewRelatedAccounts(),), + ) + + class Meta: + model = models.CRIUser + fields = ("url", "login", "old_accounts", "new_account") + extra_kwargs = { + "url": {"lookup_field": "username", "lookup_url_kwarg": "login"} + } + + +class SimpleCRIGroupSerializer(serializers.HyperlinkedModelSerializer): + class Meta: + model = models.CRIGroup + fields = ("url", "slug") + extra_kwargs = {"url": {"lookup_field": "slug"}} + + +class CampusSerializer(serializers.HyperlinkedModelSerializer): + name = serializers.CharField(source="group.name", read_only=True) + + group = SimpleCRIGroupSerializer(read_only=True) + + class Meta: + model = models.Campus + fields = ("url", "slug", "group", "name") + extra_kwargs = {"url": {"lookup_field": "slug"}} + + +class CRIGroupSerializer(serializers.HyperlinkedModelSerializer): + members_url = serializers.HyperlinkedIdentityField( + read_only=True, view_name="crigroup-members", lookup_field="slug" + ) + + history_url = serializers.HyperlinkedIdentityField( + read_only=True, view_name="crigroup-history", lookup_field="slug" + ) + + managers = SimpleCRIUserSerializer(read_only=True, many=True, source="get_managers") + + class Meta: + model = models.CRIGroup + fields = ( + "url", + "slug", + "gid", + "name", + "kind", + "members_url", + "history_url", + "managers", + "private", + ) + extra_kwargs = {"url": {"lookup_field": "slug"}} + + +class CRIComputedMembershipSerializer(serializers.ModelSerializer): + user = SimpleCRIUserSerializer(read_only=True) + + group = SimpleCRIGroupSerializer(read_only=True) + + is_current = fields.BooleanField(read_only=True) + + class Meta: + model = models.CRIComputedMembership + fields = ( + "group", + "user", + "begin_at", + "end_at", + "graduation_year", + "is_current", + ) + + def __init__(self, *args, excluded_fields=None, **kwargs): + super().__init__(*args, **kwargs) + self.excluded_fields = excluded_fields or [] + + def to_representation(self, instance): + r = super().to_representation(instance) + return {k: v for k, v in r.items() if k not in self.excluded_fields} + + +class ProfileSerializer(serializers.HyperlinkedModelSerializer): + login = serializers.CharField(read_only=True, source="username") + + primary_group = SimpleCRIGroupSerializer(read_only=True) + + groups_history = CRIComputedMembershipSerializer( + many=True, + read_only=True, + source="crimembership_set", + excluded_fields=["user"], + ) + + current_groups = SimpleCRIGroupSerializer( + many=True, read_only=True, source="get_groups" + ) + + old_accounts = fields.ListField( + read_only=True, child=fields.CharField(), source="get_old_accounts" + ) + + new_account = serializers.CharField( + required=False, + read_only=True, + allow_null=True, + source="get_new_account", + ) + + class Meta: + model = models.CRIUser + fields = ( + "url", + "login", + "uid", + "primary_group", + "first_name", + "last_name", + "legal_first_name", + "legal_last_name", + "email", + "phone", + "birthdate", + "groups_history", + "current_groups", + "old_accounts", + "new_account", + ) + extra_kwargs = { + "url": {"lookup_field": "username", "lookup_url_kwarg": "login"} + } + + +class CRIUserSerializer(FieldPermissionSerializerMixin, ProfileSerializer): + old_accounts = fields.ListField( + read_only=True, + child=fields.CharField(), + source="get_old_accounts", + permission_classes=(permissions.CanViewRelatedAccounts(),), + ) + + new_account = fields.CharField( + required=False, + read_only=True, + allow_null=True, + source="get_new_account", + permission_classes=(permissions.CanViewRelatedAccounts(),), + ) + + legal_first_name = fields.CharField( + required=False, + permission_classes=(permissions.CanViewLegalIdentity(),), + ) + + legal_last_name = fields.CharField( + required=False, + permission_classes=(permissions.CanViewLegalIdentity(),), + ) + + phone = fields.CharField( + required=False, permission_classes=(permissions.CanViewPhone(),) + ) + + birthdate = fields.CharField( + required=False, permission_classes=(permissions.CanViewBirthdate(),) + ) + + +class CRIUserSearchSerializer(serializers.Serializer): + logins = fields.ListField(write_only=True, child=fields.CharField()) + + uids = fields.ListField(write_only=True, child=fields.IntegerField())