From 264be98736ac3d32ae265616f29839f752c93535 Mon Sep 17 00:00:00 2001 From: Tore Brede <Tore.Brede@uib.no> Date: Mon, 1 Nov 2021 15:23:36 +0100 Subject: [PATCH] GREG-94: Work on resending invitation --- frontend/public/locales/en/common.json | 3 +- frontend/public/locales/nb/common.json | 1 + frontend/public/locales/nn/common.json | 1 + gregui/api/urls.py | 3 ++ gregui/api/views/invitation.py | 43 ++++++++++++++++++++++++-- gregui/api/views/person.py | 5 ++- 6 files changed, 52 insertions(+), 4 deletions(-) diff --git a/frontend/public/locales/en/common.json b/frontend/public/locales/en/common.json index 795e3894..ef14baaa 100644 --- a/frontend/public/locales/en/common.json +++ b/frontend/public/locales/en/common.json @@ -94,7 +94,8 @@ "save": "Save", "cancel": "Cancel", "backToFrontPage": "Go to front page", - "cancelInvitation": "Cancel" + "cancelInvitation": "Cancel", + "resendInvitation": "Send" }, "registerWizardText": { "registerPage": "Enter the contact information for the guest below. All fields are mandatory.", diff --git a/frontend/public/locales/nb/common.json b/frontend/public/locales/nb/common.json index 2a1a32b4..6efe20b7 100644 --- a/frontend/public/locales/nb/common.json +++ b/frontend/public/locales/nb/common.json @@ -94,6 +94,7 @@ "save": "Lagre", "cancel": "Avbryt", "backToFrontPage": "Tilbake til forsiden", + "resendInvitation": "Send", "cancelInvitation": "Kanseller" }, "registerWizardText": { diff --git a/frontend/public/locales/nn/common.json b/frontend/public/locales/nn/common.json index 30dde00a..f7bd06aa 100644 --- a/frontend/public/locales/nn/common.json +++ b/frontend/public/locales/nn/common.json @@ -95,6 +95,7 @@ "save": "Lagre", "cancel": "Avbryt", "backToFrontPage": "Tilbake til forsida", + "resendInvitation": "Send", "cancelInvitation": "Kanseller" }, "registerWizardText": { diff --git a/gregui/api/urls.py b/gregui/api/urls.py index 49a4902f..a3c5e452 100644 --- a/gregui/api/urls.py +++ b/gregui/api/urls.py @@ -4,6 +4,8 @@ from rest_framework.routers import DefaultRouter from gregui.api.views.invitation import ( CheckInvitationView, + InvitedGuestView, + ResendInvitationView, InvitationView, InvitedGuestView, ) @@ -22,6 +24,7 @@ urlpatterns += [ path("invited/", InvitedGuestView.as_view(), name="invited-info"), path("invitecheck/", CheckInvitationView.as_view(), name="invite-verify"), path("invite/", InvitationView.as_view(), name="invitation"), + path("resend/<int:person_id>", ResendInvitationView.as_view(), name="invite-resend"), path("person/<int:id>", PersonView.as_view(), name="person-get"), path( "person/search/<searchstring>", PersonSearchView.as_view(), name="person-search" diff --git a/gregui/api/views/invitation.py b/gregui/api/views/invitation.py index 5a293b3f..1c6876d5 100644 --- a/gregui/api/views/invitation.py +++ b/gregui/api/views/invitation.py @@ -1,3 +1,5 @@ +import datetime +import logging from enum import Enum from typing import Optional @@ -5,20 +7,25 @@ from django.core import exceptions from django.db import transaction from django.http.response import JsonResponse from django.utils import timezone +from django.utils.timezone import now from rest_framework import status from rest_framework.authentication import SessionAuthentication, BasicAuthentication +from rest_framework.generics import CreateAPIView, GenericAPIView +from rest_framework.mixins import UpdateModelMixin from rest_framework.generics import CreateAPIView, GenericAPIView, DestroyAPIView from rest_framework.parsers import JSONParser from rest_framework.permissions import AllowAny from rest_framework.response import Response from rest_framework.views import APIView -from greg.models import Identity, InvitationLink, Person +from greg.models import Identity, InvitationLink, Person, Invitation from greg.permissions import IsSponsor from gregui.api.serializers.guest import GuestRegisterSerializer from gregui.api.serializers.invitation import InviteGuestSerializer from gregui.models import GregUserProfile +logger = logging.getLogger(__name__) + class InvitationView(CreateAPIView, DestroyAPIView): """ @@ -269,9 +276,41 @@ class InvitedGuestView(GenericAPIView): @staticmethod def _get_identity_or_none( - person: Person, identity_type: Identity.IdentityType + person: Person, identity_type: Identity.IdentityType ) -> Optional[str]: try: return person.identities.get(type=identity_type).value except Identity.DoesNotExist: return None + + +class ResendInvitationView(UpdateModelMixin, APIView): + authentication_classes = [BasicAuthentication, SessionAuthentication] + permission_classes = [IsSponsor] + + def patch(self, request, *args, **kwargs) -> Response: + person_id = kwargs["person_id"] + + active_invitation_links = InvitationLink.objects.filter(invitation__role__person__id=person_id, + expire__gte=now()) + + if active_invitation_links.count() == 0: + # No active invitations, it is not expected that this endpoint is called if that is the case + return Response(status=status.HTTP_400_BAD_REQUEST) + + if active_invitation_links.count() > 1: + logger.warning(f"Person with ID {person_id} has multiple active invitation links") + + for link in active_invitation_links: + # TODO Could also update the UUID of the existing invitation link and send it again. Not sure what is best, reusing the existing link-entry in the database or creating a new one as done here + link.expire = now() + link.save() + invitationlink = InvitationLink.objects.create( + invitation=link.invitation, + expire=timezone.now() + datetime.timedelta(days=30), + ) + + # TODO: send email to invited guest + print(invitationlink) + + return Response(status=status.HTTP_200_OK) diff --git a/gregui/api/views/person.py b/gregui/api/views/person.py index e5953a28..40761b9c 100644 --- a/gregui/api/views/person.py +++ b/gregui/api/views/person.py @@ -1,9 +1,10 @@ from django.http.response import JsonResponse +from django.utils.timezone import now from rest_framework.authentication import SessionAuthentication, BasicAuthentication from rest_framework.permissions import IsAuthenticated from rest_framework.views import APIView -from greg.models import Identity, Person +from greg.models import Identity, Person, InvitationLink from greg.permissions import IsSponsor @@ -45,6 +46,8 @@ class PersonView(APIView): } for role in person.roles.all() ], + "has_active_invitations": InvitationLink.objects.filter(invitation__role__person__id=person.id, + expire__gte=now()).count() > 0 } return JsonResponse(response) -- GitLab