From ad7c869c75a5541d08d75e956fd5514d5efc956a Mon Sep 17 00:00:00 2001
From: Andreas Ellewsen <ae@uio.no>
Date: Tue, 12 Oct 2021 12:51:50 +0200
Subject: [PATCH] Add test of views using invitations

---
 gregui/api/urls.py                  |   4 +-
 gregui/api/views/invitation.py      |   2 +-
 gregui/tests/api/test_invitation.py | 135 ++++++++++++++++++++++++++++
 gregui/tests/conftest.py            |  46 +++++++++-
 4 files changed, 183 insertions(+), 4 deletions(-)
 create mode 100644 gregui/tests/api/test_invitation.py

diff --git a/gregui/api/urls.py b/gregui/api/urls.py
index 64977e22..e5b04c50 100644
--- a/gregui/api/urls.py
+++ b/gregui/api/urls.py
@@ -16,7 +16,7 @@ urlpatterns = router.urls
 urlpatterns += [
     re_path(r"roletypes/$", RoleTypeViewSet.as_view(), name="role-types"),
     re_path(r"units/$", UnitsViewSet.as_view(), name="units"),
-    path("invited/", InvitedGuestView.as_view(), name="invite"),
-    path("invited/<uuid>", CheckInvitationView.as_view()),
+    path("invited/", InvitedGuestView.as_view(), name="invited-info"),
+    path("invited/<uuid>", CheckInvitationView.as_view(), name="invite-verify"),
     path("invite/", CreateInvitationView.as_view(), name="invite-create"),
 ]
diff --git a/gregui/api/views/invitation.py b/gregui/api/views/invitation.py
index 82ac8bbc..18ac8723 100644
--- a/gregui/api/views/invitation.py
+++ b/gregui/api/views/invitation.py
@@ -169,7 +169,7 @@ class InvitedGuestView(APIView):
         clicked by the user. The next part of the flow is for the sponsor to confirm
         the guest.
         """
-        invite_id = kwargs["uuid"]
+        invite_id = request.session.get("invite_id")
         data = request.data
 
         with transaction.atomic():
diff --git a/gregui/tests/api/test_invitation.py b/gregui/tests/api/test_invitation.py
new file mode 100644
index 00000000..d2aa578d
--- /dev/null
+++ b/gregui/tests/api/test_invitation.py
@@ -0,0 +1,135 @@
+import pytest
+
+from rest_framework import status
+from rest_framework.reverse import reverse
+from rest_framework.test import APIClient
+
+from greg.models import InvitationLink, Person
+
+
+@pytest.mark.django_db
+def test_get_invite(client):
+    """Forbid access with bad invitation link uuid"""
+    response = client.get(
+        reverse("gregui-v1:invite-verify", kwargs={"uuid": "baduuid"})
+    )
+    assert response.status_code == status.HTTP_403_FORBIDDEN
+
+
+@pytest.mark.django_db
+def test_get_invite_ok(client, invitation_link):
+    """Access okay with valid invitation link"""
+    response = client.get(
+        reverse("gregui-v1:invite-verify", kwargs={"uuid": invitation_link.uuid})
+    )
+    assert response.status_code == status.HTTP_200_OK
+
+
+@pytest.mark.django_db
+def test_get_invite_expired(client, invitation_link_expired):
+    """Forbid access with expired invite link"""
+    response = client.get(
+        reverse(
+            "gregui-v1:invite-verify", kwargs={"uuid": invitation_link_expired.uuid}
+        )
+    )
+    assert response.status_code == status.HTTP_403_FORBIDDEN
+
+
+@pytest.mark.django_db
+def test_get_invited_info_no_session(client, invitation_link):
+    response = client.get(reverse("gregui-v1:invited-info"))
+    assert response.status_code == status.HTTP_403_FORBIDDEN
+
+
+@pytest.mark.django_db
+def test_get_invited_info_session_okay(client, invitation_link):
+    # get a session
+    client.get(
+        reverse("gregui-v1:invite-verify", kwargs={"uuid": invitation_link.uuid})
+    )
+    # Get info
+    response = client.get(reverse("gregui-v1:invited-info"))
+    assert response.status_code == status.HTTP_200_OK
+    data = response.json()
+    assert data.get("person")
+    assert data.get("sponsor")
+    assert data.get("role")
+
+
+@pytest.mark.django_db
+def test_get_invited_info_expired_link(client, invitation_link):
+    # Get a session while link is valid
+    client.get(
+        reverse("gregui-v1:invite-verify", kwargs={"uuid": invitation_link.uuid})
+    )
+    # Set expire link to expire long ago
+    invlink = InvitationLink.objects.get(uuid=invitation_link.uuid)
+    invlink.expire = "1970-01-01"
+    invlink.save()
+    # Make a get request that should fail because invite expired after login, but
+    # before get to userinfo
+    response = client.get(reverse("gregui-v1:invited-info"))
+    assert response.status_code == status.HTTP_403_FORBIDDEN
+
+
+@pytest.mark.django_db
+def test_post_invited_info_ok_mobile_update(client: APIClient, invitation_link):
+    # get a session
+    client.get(
+        reverse("gregui-v1:invite-verify", kwargs={"uuid": invitation_link.uuid})
+    )
+    # post updated info to confirm from guest
+    new_phone = "12345678"
+    post_data = {"mobile_phone": new_phone}
+    response = client.post(
+        reverse("gregui-v1:invited-info"),
+        post_data,
+        format="json",
+    )
+    assert response.status_code == status.HTTP_201_CREATED
+    # Check that the object was updated in the database
+    person = Person.objects.get(id=invitation_link.invitation.role.person.id)
+    assert person.mobile_phone == new_phone
+
+
+@pytest.mark.django_db
+def test_post_invited_info_ok(client, invitation_link):
+    # get a session
+    client.get(
+        reverse("gregui-v1:invite-verify", kwargs={"uuid": invitation_link.uuid})
+    )
+    # post updated info to confirm from guest
+    response = client.post(reverse("gregui-v1:invited-info"))
+    assert response.status_code == status.HTTP_201_CREATED
+
+
+@pytest.mark.django_db
+def test_post_invited_info_expired_session(client, invitation_link):
+    # get a session
+    client.get(
+        reverse("gregui-v1:invite-verify", kwargs={"uuid": invitation_link.uuid})
+    )
+    # Set expire link to expire long ago
+    invlink = InvitationLink.objects.get(uuid=invitation_link.uuid)
+    invlink.expire = "1970-01-01"
+    invlink.save()
+    # post updated info to confirm from guest, should fail because of expired
+    # invitation link
+    response = client.post(reverse("gregui-v1:invited-info"))
+    assert response.status_code == status.HTTP_403_FORBIDDEN
+
+
+@pytest.mark.django_db
+def test_post_invited_info_deleted_inv_link(client, invitation_link):
+    # get a session
+    client.get(
+        reverse("gregui-v1:invite-verify", kwargs={"uuid": invitation_link.uuid})
+    )
+    # Delete link
+    invlink = InvitationLink.objects.get(uuid=invitation_link.uuid)
+    invlink.delete()
+    # post updated info to confirm from guest, should fail because of removed
+    # invitation link
+    response = client.post(reverse("gregui-v1:invited-info"))
+    assert response.status_code == status.HTTP_403_FORBIDDEN
diff --git a/gregui/tests/conftest.py b/gregui/tests/conftest.py
index b71080b0..40d3fab6 100644
--- a/gregui/tests/conftest.py
+++ b/gregui/tests/conftest.py
@@ -6,7 +6,15 @@ from rest_framework.test import APIClient
 
 import pytest
 
-from greg.models import Sponsor, OrganizationalUnit, RoleType
+from greg.models import (
+    Invitation,
+    InvitationLink,
+    OrganizationalUnit,
+    Person,
+    Role,
+    RoleType,
+    Sponsor,
+)
 from gregui.models import GregUserProfile
 
 # faker spams the logs with localisation warnings
@@ -56,3 +64,39 @@ def user_sponsor(sponsor_guy: Sponsor) -> User:
 
     # This user is a sponsor for unit_foo
     return user
+
+
+@pytest.fixture
+def person() -> Person:
+    pe = Person.objects.create()
+    return Person.objects.get(id=pe.id)
+
+
+@pytest.fixture
+def role(person, sponsor_guy, unit_foo, role_type_foo) -> Role:
+    role = Role.objects.create(
+        person=person,
+        sponsor_id=sponsor_guy,
+        orgunit_id=unit_foo,
+        end_date="2050-10-15",
+        type_id=role_type_foo.id,
+    )
+    return Role.objects.get(id=role.id)
+
+
+@pytest.fixture
+def invitation(role) -> Invitation:
+    inv = Invitation.objects.create(role=role)
+    return Invitation.objects.get(id=inv.id)
+
+
+@pytest.fixture
+def invitation_link(invitation) -> InvitationLink:
+    il = InvitationLink.objects.create(invitation=invitation, expire="2060-10-15")
+    return InvitationLink.objects.get(id=il.id)
+
+
+@pytest.fixture
+def invitation_link_expired(invitation) -> InvitationLink:
+    il = InvitationLink.objects.create(invitation=invitation, expire="1970-01-01")
+    return InvitationLink.objects.get(id=il.id)
-- 
GitLab