views.py 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. from django.core.exceptions import ObjectDoesNotExist
  2. from django.shortcuts import get_object_or_404
  3. from django.http import Http404
  4. from rest_framework import status, viewsets, mixins
  5. from rest_framework.decorators import action
  6. from rest_framework.response import Response
  7. from rest_framework.exceptions import ValidationError
  8. from drf_yasg.utils import swagger_auto_schema
  9. from allauth.account.models import EmailAddress
  10. from organizations_ext.models import Organization
  11. from .models import User, UserProjectAlert
  12. from .serializers import (
  13. UserSerializer,
  14. UserNotificationsSerializer,
  15. EmailAddressSerializer,
  16. ConfirmEmailAddressSerializer,
  17. )
  18. class UserViewSet(viewsets.ModelViewSet):
  19. queryset = User.objects.all()
  20. serializer_class = UserSerializer
  21. def get_queryset(self):
  22. queryset = super().get_queryset()
  23. organization_slug = self.kwargs.get("organization_slug")
  24. if organization_slug:
  25. queryset = queryset.filter(
  26. organizations_ext_organization__slug=organization_slug,
  27. organizations_ext_organization__users=self.request.user,
  28. )
  29. else:
  30. queryset = queryset.filter(id=self.request.user.id)
  31. return queryset
  32. def get_object(self):
  33. pk = self.kwargs.get("pk")
  34. if pk == "me":
  35. return self.request.user
  36. return super().get_object()
  37. def perform_create(self, serializer):
  38. organization_slug = self.kwargs.get("organization_slug")
  39. try:
  40. organization = Organization.objects.get(slug=organization_slug)
  41. except Organization.DoesNotExist:
  42. raise ValidationError("Organization does not exist")
  43. # TODO deal with organization and users who aren't set up yet
  44. user = serializer.save()
  45. return user
  46. @action(detail=True, methods=["get", "post", "put"])
  47. def notifications(self, request, pk=None):
  48. user = self.get_object()
  49. if request.method == "GET":
  50. serializer = UserNotificationsSerializer(user)
  51. return Response(serializer.data)
  52. serializer = UserNotificationsSerializer(user, data=request.data)
  53. if serializer.is_valid():
  54. serializer.save()
  55. return Response(serializer.data)
  56. else:
  57. return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
  58. @action(
  59. detail=True, methods=["get", "post", "put"], url_path="notifications/alerts"
  60. )
  61. def alerts(self, request, pk=None):
  62. """
  63. Returns dictionary of project_id: status. Now project_id status means it's "default"
  64. To update, submit `{project_id: status}` where status is -1 (default), 0, or 1
  65. """
  66. user = self.get_object()
  67. alerts = user.userprojectalert_set.all()
  68. if request.method == "GET":
  69. data = {}
  70. for alert in alerts:
  71. data[alert.project_id] = alert.status
  72. return Response(data)
  73. data = request.data
  74. try:
  75. items = [x for x in data.items()]
  76. except AttributeError:
  77. raise ValidationError("Invalid alert format, expected dictionary")
  78. if len(data) != 1:
  79. raise ValidationError("Invalid alert format, expected one value")
  80. project_id, alert_status = items[0]
  81. if alert_status not in [1, 0, -1]:
  82. raise ValidationError("Invalid status, must be -1, 0, or 1")
  83. alert = alerts.filter(project_id=project_id).first()
  84. if alert and alert_status == -1:
  85. alert.delete()
  86. else:
  87. UserProjectAlert.objects.update_or_create(
  88. user=user, project_id=project_id, defaults={"status": alert_status}
  89. )
  90. return Response(status=204)
  91. class EmailAddressViewSet(
  92. mixins.CreateModelMixin, mixins.ListModelMixin, viewsets.GenericViewSet,
  93. ):
  94. queryset = EmailAddress.objects.all()
  95. serializer_class = EmailAddressSerializer
  96. pagination_class = None
  97. def get_user(self, user_pk):
  98. if user_pk == "me":
  99. return self.request.user
  100. raise ValidationError("Can only change primary email address on own account")
  101. def get_queryset(self):
  102. user = self.get_user(self.kwargs.get("user_pk"))
  103. queryset = super().get_queryset().filter(user=user)
  104. return queryset
  105. def put(self, request, user_pk, format=None):
  106. """
  107. Set a new primary email (must be verified) this will also set the email used when a user logs in.
  108. """
  109. user = self.get_user(user_pk)
  110. try:
  111. email_address = user.emailaddress_set.get(
  112. email=request.data.get("email"), verified=True
  113. )
  114. email_address.set_as_primary()
  115. except ObjectDoesNotExist:
  116. raise Http404
  117. serializer = self.serializer_class(
  118. instance=email_address, data=request.data, context={"request": request}
  119. )
  120. if serializer.is_valid():
  121. serializer.save()
  122. return Response(serializer.data)
  123. return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
  124. def delete(self, request, user_pk, format=None):
  125. user = self.get_user(user_pk)
  126. try:
  127. email_address = user.emailaddress_set.get(
  128. email=request.data.get("email"), primary=False
  129. )
  130. except ObjectDoesNotExist:
  131. raise Http404
  132. email_address.delete()
  133. return Response(status=status.HTTP_204_NO_CONTENT)
  134. @swagger_auto_schema(responses={204: "No Content"})
  135. @action(detail=False, methods=["post"])
  136. def confirm(self, request, user_pk):
  137. serializer = ConfirmEmailAddressSerializer(data=request.data)
  138. serializer.is_valid(raise_exception=True)
  139. email_address = get_object_or_404(
  140. self.get_queryset(), email=serializer.validated_data.get("email")
  141. )
  142. email_address.send_confirmation(request)
  143. return Response(status=204)