serializers.py 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. from rest_framework import serializers, status
  2. from rest_framework.exceptions import APIException, PermissionDenied
  3. from projects.serializers.base_serializers import ProjectReferenceWithMemberSerializer
  4. from users.serializers import UserSerializer
  5. from teams.serializers import TeamSerializer
  6. from teams.models import Team
  7. from users.models import User
  8. from users.utils import is_user_registration_open
  9. from .base_serializers import OrganizationReferenceSerializer
  10. from ..models import OrganizationUser, OrganizationUserRole, ROLES
  11. class OrganizationSerializer(OrganizationReferenceSerializer):
  12. pass
  13. class OrganizationDetailSerializer(OrganizationSerializer):
  14. projects = ProjectReferenceWithMemberSerializer(many=True)
  15. teams = TeamSerializer(many=True)
  16. openMembership = serializers.BooleanField(source="open_membership")
  17. scrubIPAddresses = serializers.BooleanField(source="scrub_ip_addresses")
  18. class Meta(OrganizationSerializer.Meta):
  19. fields = OrganizationSerializer.Meta.fields + (
  20. "projects",
  21. "openMembership",
  22. "scrubIPAddresses",
  23. "teams",
  24. )
  25. class HTTP409APIException(APIException):
  26. status_code = status.HTTP_409_CONFLICT
  27. class OrganizationUserSerializer(serializers.ModelSerializer):
  28. user = UserSerializer(required=False, read_only=True)
  29. role = serializers.CharField(source="get_role")
  30. roleName = serializers.CharField(source="get_role_display", read_only=True)
  31. dateCreated = serializers.DateTimeField(source="created", read_only=True)
  32. teams = serializers.SlugRelatedField(
  33. many=True, write_only=True, slug_field="slug", queryset=Team.objects.none()
  34. )
  35. class Meta:
  36. model = OrganizationUser
  37. fields = (
  38. "role",
  39. "id",
  40. "user",
  41. "roleName",
  42. "dateCreated",
  43. "email",
  44. "teams",
  45. "pending",
  46. )
  47. def __init__(self, *args, request_user=None, **kwargs):
  48. super().__init__(*args, **kwargs)
  49. if "request" in self.context:
  50. organization_slug = self.context["view"].kwargs.get("organization_slug")
  51. self.fields["teams"].child_relation.queryset = Team.objects.filter(
  52. organization__slug=organization_slug
  53. )
  54. def get_extra_kwargs(self):
  55. """email should be read only when updating"""
  56. extra_kwargs = super().get_extra_kwargs()
  57. if self.instance is not None:
  58. extra_kwargs["email"] = {"read_only": True}
  59. extra_kwargs["user"] = {"read_only": True}
  60. return extra_kwargs
  61. def create(self, validated_data):
  62. role = OrganizationUserRole.from_string(validated_data.get("get_role"))
  63. email = validated_data.get("email")
  64. organization = validated_data.get("organization")
  65. teams = validated_data.get("teams")
  66. if (
  67. not is_user_registration_open()
  68. and not User.objects.filter(email=email).exists()
  69. ):
  70. raise PermissionDenied("Only existing users may be invited")
  71. if organization.organization_users.filter(email=email).exists():
  72. raise HTTP409APIException(f"The user {email} is already invited", "email")
  73. if organization.organization_users.filter(user__email=email).exists():
  74. raise HTTP409APIException(f"The user {email} is already a member", "email")
  75. org_user = super().create(
  76. {"role": role, "email": email, "organization": organization}
  77. )
  78. org_user.team_set.add(*teams)
  79. return org_user
  80. def update(self, instance, validated_data):
  81. get_role = validated_data.pop("get_role", None)
  82. if get_role:
  83. role = OrganizationUserRole.from_string(get_role)
  84. validated_data["role"] = role
  85. return super().update(instance, validated_data)
  86. def to_representation(self, obj):
  87. """Override email for representation to potientially show user's email"""
  88. self.fields["email"] = serializers.SerializerMethodField()
  89. return super().to_representation(obj)
  90. def get_email(self, obj):
  91. """Prefer user primary email over org user email (which is only for invites)"""
  92. if obj.user:
  93. return obj.user.email
  94. return obj.email
  95. class OrganizationUserDetailSerializer(OrganizationUserSerializer):
  96. teams = serializers.SlugRelatedField(
  97. source="team_set", slug_field="slug", read_only=True, many=True
  98. )
  99. roles = serializers.SerializerMethodField()
  100. class Meta(OrganizationUserSerializer.Meta):
  101. fields = OrganizationUserSerializer.Meta.fields + ("roles",)
  102. def get_roles(self, obj):
  103. return ROLES
  104. class OrganizationUserProjectsSerializer(OrganizationUserSerializer):
  105. projects = serializers.SerializerMethodField()
  106. class Meta(OrganizationUserSerializer.Meta):
  107. fields = OrganizationUserSerializer.Meta.fields + ("projects",)
  108. def get_projects(self, obj):
  109. return obj.organization.projects.filter(team__members=obj).values_list(
  110. "slug", flat=True
  111. )
  112. class ReinviteSerializer(serializers.Serializer):
  113. reinvite = serializers.IntegerField()
  114. def update(self, instance, validated_data):
  115. if validated_data.get("reinvite"):
  116. pass
  117. # Send email
  118. return instance
  119. class OrganizationUserOrganizationSerializer(OrganizationUserSerializer):
  120. """Organization User Serializer with Organization info"""
  121. organization = OrganizationSerializer()
  122. class Meta(OrganizationUserSerializer.Meta):
  123. fields = OrganizationUserSerializer.Meta.fields + ("organization",)
  124. class AcceptInviteSerializer(serializers.Serializer):
  125. accept_invite = serializers.BooleanField()
  126. org_user = OrganizationUserOrganizationSerializer(read_only=True)