diff --git a/greg/api/serializers/invitation.py b/greg/api/serializers/invitation.py index 820e51979548a180c02fe80630ada93aaf7f8c5b..c169fea1c89d862606a250b2dde6f8bfdd11febb 100644 --- a/greg/api/serializers/invitation.py +++ b/greg/api/serializers/invitation.py @@ -1,13 +1,8 @@ -from datetime import timedelta - from rest_framework import serializers -from django.conf import settings -from django.db import transaction -from django.utils import timezone from greg.api.serializers.role import RoleInvitationSerializer -from greg.models import Identity, Invitation, InvitationLink, Person, Role, Sponsor -from greg.utils import is_identity_duplicate +from greg.models import Identity, Person, Sponsor +from greg.utils import create_objects_for_invitation, is_identity_duplicate from gregui.api.serializers.identity import IdentityDuplicateError @@ -21,29 +16,19 @@ class InvitationSerializer(serializers.ModelSerializer): role_data = validated_data.pop("role") sponsor = validated_data.pop("sponsor") - with transaction.atomic(): - # Find sponsor based on feide_id - # If not found create sponsor with feide_id instead - try: - sponsor = Sponsor.objects.get(feide_id=sponsor) - except Sponsor.DoesNotExist: - sponsor = Sponsor.objects.create(feide_id=sponsor) - - person = Person.objects.create(**validated_data) - Identity.objects.create( - person=person, - type=Identity.IdentityType.PRIVATE_EMAIL, - value=email, - source=settings.DEFAULT_IDENTITY_SOURCE, - ) - role_data["person"] = person - role_data["sponsor"] = sponsor - role = Role.objects.create(**role_data) - invitation = Invitation.objects.create(role=role) - InvitationLink.objects.create( - invitation=invitation, - expire=timezone.now() + timedelta(days=30), - ) + # Find sponsor based on feide_id + # If not found it will be created + try: + sponsor = Sponsor.objects.get(feide_id=sponsor) + except Sponsor.DoesNotExist: + pass + + person = create_objects_for_invitation( + person_data=validated_data, + person_email=email, + role_data=role_data, + sponsor=sponsor, + ) return person diff --git a/greg/api/views/invitation.py b/greg/api/views/invitation.py index 5924832087f99d47a15a26a1496b03328472ac1e..ced0f05ece6512d8d0a87319180bf8c48c8b914d 100644 --- a/greg/api/views/invitation.py +++ b/greg/api/views/invitation.py @@ -2,8 +2,8 @@ from rest_framework import permissions, status, viewsets from rest_framework.response import Response from greg.api.serializers.invitation import InvitationSerializer -from greg.models import InvitationLink, Sponsor -from gregui.mailutils.invite_guest import InviteGuest +from greg.models import Sponsor +from greg.utils import queue_mail_to_invitee class InvitationViewSet(viewsets.ModelViewSet): @@ -21,12 +21,7 @@ class InvitationViewSet(viewsets.ModelViewSet): sponsor_feide_id = serializer.validated_data["sponsor"] sponsor = Sponsor.objects.get(feide_id=sponsor_feide_id) - for invitationlink in InvitationLink.objects.filter( - invitation__role__person_id=person.id, - invitation__role__sponsor_id=sponsor.id, - ): - invitemailer = InviteGuest() - invitemailer.queue_mail(invitationlink) + queue_mail_to_invitee(person, sponsor) headers = self.get_success_headers(serializer.validated_data) return Response(status=status.HTTP_201_CREATED, headers=headers) diff --git a/greg/utils.py b/greg/utils.py index 1afb6f20868692dc182eafb561eb94b0df43dbae..c051a7f6b299657b1e5351f579d4e0521f475c3e 100644 --- a/greg/utils.py +++ b/greg/utils.py @@ -1,10 +1,19 @@ import re import typing from datetime import date, datetime, timedelta +from django.db import transaction from django.conf import settings from django.utils import timezone -from greg.models import Identity +from greg.models import ( + Identity, + Invitation, + InvitationLink, + Person, + Role, + Sponsor, +) +from gregui.mailutils.invite_guest import InviteGuest def camel_to_snake(s: str) -> str: @@ -120,3 +129,44 @@ def get_default_invitation_expire_date_from_now(): def is_identity_duplicate(identity_type: Identity.IdentityType, value: str) -> bool: return Identity.objects.filter(type=identity_type).filter(value=value).exists() + + +def create_objects_for_invitation( + person_data: dict, + person_email: str, + role_data: dict, + sponsor: typing.Union[Sponsor, str], +) -> Person: + + with transaction.atomic(): + + # If only sponsor's feide_id is provided create the sponsor + if isinstance(sponsor, str): + sponsor = Sponsor.objects.create(feide_id=sponsor) + + person = Person.objects.create(**person_data) + Identity.objects.create( + person=person, + type=Identity.IdentityType.PRIVATE_EMAIL, + value=person_email, + source=settings.DEFAULT_IDENTITY_SOURCE, + ) + role_data["person"] = person + role_data["sponsor"] = sponsor + role = Role.objects.create(**role_data) + invitation = Invitation.objects.create(role=role) + InvitationLink.objects.create( + invitation=invitation, + expire=timezone.now() + timedelta(days=30), + ) + + return person + + +def queue_mail_to_invitee(person: Person, sponsor: Sponsor): + for invitationlink in InvitationLink.objects.filter( + invitation__role__person_id=person.id, + invitation__role__sponsor_id=sponsor.id, + ): + invitemailer = InviteGuest() + invitemailer.queue_mail(invitationlink) diff --git a/gregui/api/serializers/invitation.py b/gregui/api/serializers/invitation.py index 1673de9b812946258b517459da4689ae7c9344ac..add333aa7655ec35efd159134c7f9e32ab466584 100644 --- a/gregui/api/serializers/invitation.py +++ b/gregui/api/serializers/invitation.py @@ -1,12 +1,7 @@ -import datetime - -from django.conf import settings -from django.db import transaction -from django.utils import timezone from rest_framework import serializers -from greg.models import Invitation, InvitationLink, Person, Role, Identity -from greg.utils import is_identity_duplicate +from greg.models import Person, Identity +from greg.utils import create_objects_for_invitation, is_identity_duplicate from gregui.api.serializers.identity import IdentityDuplicateError from gregui.api.serializers.role import InviteRoleSerializerUi from gregui.models import GregUserProfile @@ -21,25 +16,17 @@ class InviteGuestSerializer(serializers.ModelSerializer): email = validated_data.pop("email") role_data = validated_data.pop("role") - user = GregUserProfile.objects.get(user=self.context["request"].user) + user_str = self.context["request"].user + user = GregUserProfile.objects.get(user=user_str) + sponsor = user.sponsor + + person = create_objects_for_invitation( + person_data=validated_data, + person_email=email, + role_data=role_data, + sponsor=sponsor, + ) - # Create objects - with transaction.atomic(): - person = Person.objects.create(**validated_data) - Identity.objects.create( - person=person, - type=Identity.IdentityType.PRIVATE_EMAIL, - value=email, - source=settings.DEFAULT_IDENTITY_SOURCE, - ) - role_data["person"] = person - role_data["sponsor"] = user.sponsor - role = Role.objects.create(**role_data) - invitation = Invitation.objects.create(role=role) - InvitationLink.objects.create( - invitation=invitation, - expire=timezone.now() + datetime.timedelta(days=30), - ) return person def validate_email(self, email): diff --git a/gregui/api/views/invitation.py b/gregui/api/views/invitation.py index cadd633dc128f23b2cd937345b326ddf41d61f39..5832a675cce2f3bce679bdda0787f2ffb8c54e68 100644 --- a/gregui/api/views/invitation.py +++ b/gregui/api/views/invitation.py @@ -20,7 +20,10 @@ from rest_framework.views import APIView from greg.models import Identity, InvitationLink, Person from greg.permissions import IsSponsor -from greg.utils import get_default_invitation_expire_date_from_now +from greg.utils import ( + get_default_invitation_expire_date_from_now, + queue_mail_to_invitee, +) from gregui.api.serializers.guest import GuestRegisterSerializer from gregui.api.serializers.invitation import InviteGuestSerializer from gregui.mailutils.confirm_guest import ConfirmGuest @@ -67,19 +70,17 @@ class InvitationView(CreateAPIView, DestroyAPIView): information, and confirm it. """ sponsor_user = GregUserProfile.objects.get(user=request.user) + sponsor = sponsor_user.sponsor + serializer = self.serializer_class( data=request.data, - context={"request": request, "sponsor": sponsor_user.sponsor}, + context={"request": request, "sponsor": sponsor}, ) serializer.is_valid(raise_exception=True) person = serializer.save() - for invitationlink in InvitationLink.objects.filter( - invitation__role__person_id=person.id, - invitation__role__sponsor_id=sponsor_user.sponsor_id, - ): - invitemailer = InviteGuest() - invitemailer.queue_mail(invitationlink) + queue_mail_to_invitee(person, sponsor) + # Empty json-body to avoid client complaining about non-json data in response return Response(status=status.HTTP_201_CREATED, data={})