Files
notifications-api/tests/app/organization/test_invite_rest.py

317 lines
10 KiB
Python
Raw Normal View History

2024-03-19 13:59:55 -07:00
import os
import uuid
import pytest
from flask import current_app, json
from freezegun import freeze_time
from notifications_utils.url_safe_token import generate_token
from app.enums import InvitedUserStatus
from app.models import Notification
from tests import create_admin_authorization_header
from tests.app.db import create_invited_org_user
2023-08-29 14:54:30 -07:00
@pytest.mark.parametrize(
"platform_admin, expected_invited_by",
2024-03-04 10:23:45 -07:00
((True, "The Notify.gov team"), (False, "Test User")),
2023-08-29 14:54:30 -07:00
)
@pytest.mark.parametrize(
"extra_args, expected_start_of_invite_url",
[
({}, "http://localhost:6012/organization-invitation/"),
(
{"invite_link_host": "https://www.example.com"},
"https://www.example.com/organization-invitation/",
),
],
)
def test_create_invited_org_user(
admin_request,
2023-07-10 11:06:29 -07:00
sample_organization,
sample_user,
mocker,
org_invite_email_template,
extra_args,
expected_start_of_invite_url,
platform_admin,
expected_invited_by,
):
2024-03-19 13:59:55 -07:00
os.environ["LOGIN_DOT_GOV_REGISTRATION_URL"] = "http://foo.fake.gov"
2023-08-29 14:54:30 -07:00
mocked = mocker.patch("app.celery.provider_tasks.deliver_email.apply_async")
email_address = "invited_user@example.com"
sample_user.platform_admin = platform_admin
data = dict(
2023-07-10 11:06:29 -07:00
organization=str(sample_organization.id),
email_address=email_address,
invited_by=str(sample_user.id),
**extra_args
)
json_resp = admin_request.post(
2023-08-29 14:54:30 -07:00
"organization_invite.invite_user_to_org",
2023-07-10 11:06:29 -07:00
organization_id=sample_organization.id,
_data=data,
2023-08-29 14:54:30 -07:00
_expected_status=201,
)
2023-08-29 14:54:30 -07:00
assert json_resp["data"]["organization"] == str(sample_organization.id)
assert json_resp["data"]["email_address"] == email_address
assert json_resp["data"]["invited_by"] == str(sample_user.id)
assert json_resp["data"]["status"] == InvitedUserStatus.PENDING
2023-08-29 14:54:30 -07:00
assert json_resp["data"]["id"]
notification = Notification.query.first()
assert notification.reply_to_text == sample_user.email_address
assert len(notification.personalisation.keys()) == 3
2023-08-29 14:54:30 -07:00
assert notification.personalisation["organization_name"] == "sample organization"
assert notification.personalisation["user_name"] == expected_invited_by
2024-03-19 13:23:22 -07:00
# assert notification.personalisation["url"].startswith(expected_start_of_invite_url)
# assert len(notification.personalisation["url"]) > len(expected_start_of_invite_url)
2023-08-29 14:54:30 -07:00
mocked.assert_called_once_with(
[(str(notification.id))], queue="notify-internal-tasks"
)
2023-08-29 14:54:30 -07:00
def test_create_invited_user_invalid_email(
admin_request, sample_organization, sample_user, mocker
):
mocked = mocker.patch("app.celery.provider_tasks.deliver_email.apply_async")
email_address = "notanemail"
data = {
2023-08-29 14:54:30 -07:00
"service": str(sample_organization.id),
"email_address": email_address,
"invited_by": str(sample_user.id),
}
json_resp = admin_request.post(
2023-08-29 14:54:30 -07:00
"organization_invite.invite_user_to_org",
2023-07-10 11:06:29 -07:00
organization_id=sample_organization.id,
_data=data,
2023-08-29 14:54:30 -07:00
_expected_status=400,
)
2023-08-29 14:54:30 -07:00
assert (
json_resp["errors"][0]["message"] == "email_address Not a valid email address"
)
assert mocked.call_count == 0
2023-08-29 14:54:30 -07:00
def test_get_all_invited_users_by_service(
admin_request, sample_organization, sample_user
):
for i in range(5):
create_invited_org_user(
2023-07-10 11:06:29 -07:00
sample_organization,
sample_user,
2023-08-29 14:54:30 -07:00
email_address="invited_user_{}@service.gov.uk".format(i),
)
json_resp = admin_request.get(
2023-08-29 14:54:30 -07:00
"organization_invite.get_invited_org_users_by_organization",
organization_id=sample_organization.id,
)
2023-08-29 14:54:30 -07:00
assert len(json_resp["data"]) == 5
for invite in json_resp["data"]:
assert invite["organization"] == str(sample_organization.id)
assert invite["invited_by"] == str(sample_user.id)
assert invite["id"]
2023-08-29 14:54:30 -07:00
def test_get_invited_users_by_service_with_no_invites(
admin_request, sample_organization
):
json_resp = admin_request.get(
2023-08-29 14:54:30 -07:00
"organization_invite.get_invited_org_users_by_organization",
organization_id=sample_organization.id,
)
2023-08-29 14:54:30 -07:00
assert len(json_resp["data"]) == 0
2023-07-10 11:06:29 -07:00
def test_get_invited_user_by_organization(admin_request, sample_invited_org_user):
json_resp = admin_request.get(
2023-08-29 14:54:30 -07:00
"organization_invite.get_invited_org_user_by_organization",
2023-07-10 11:06:29 -07:00
organization_id=sample_invited_org_user.organization.id,
2023-08-29 14:54:30 -07:00
invited_org_user_id=sample_invited_org_user.id,
)
2023-08-29 14:54:30 -07:00
assert json_resp["data"]["email_address"] == sample_invited_org_user.email_address
2023-07-10 11:06:29 -07:00
def test_get_invited_user_by_organization_when_user_does_not_belong_to_the_org(
admin_request,
sample_invited_org_user,
fake_uuid,
):
json_resp = admin_request.get(
2023-08-29 14:54:30 -07:00
"organization_invite.get_invited_org_user_by_organization",
2023-07-10 11:06:29 -07:00
organization_id=fake_uuid,
invited_org_user_id=sample_invited_org_user.id,
2023-08-29 14:54:30 -07:00
_expected_status=404,
)
2023-08-29 14:54:30 -07:00
assert json_resp["result"] == "error"
2023-08-29 14:54:30 -07:00
def test_update_org_invited_user_set_status_to_cancelled(
admin_request, sample_invited_org_user
):
data = {"status": InvitedUserStatus.CANCELLED}
json_resp = admin_request.post(
2023-08-29 14:54:30 -07:00
"organization_invite.update_org_invite_status",
2023-07-10 11:06:29 -07:00
organization_id=sample_invited_org_user.organization_id,
invited_org_user_id=sample_invited_org_user.id,
2023-08-29 14:54:30 -07:00
_data=data,
)
assert json_resp["data"]["status"] == InvitedUserStatus.CANCELLED
2023-08-29 14:54:30 -07:00
def test_update_org_invited_user_for_wrong_service_returns_404(
admin_request, sample_invited_org_user, fake_uuid
):
data = {"status": InvitedUserStatus.CANCELLED}
json_resp = admin_request.post(
2023-08-29 14:54:30 -07:00
"organization_invite.update_org_invite_status",
2023-07-10 11:06:29 -07:00
organization_id=fake_uuid,
invited_org_user_id=sample_invited_org_user.id,
_data=data,
2023-08-29 14:54:30 -07:00
_expected_status=404,
)
2023-08-29 14:54:30 -07:00
assert json_resp["message"] == "No result found"
2023-08-29 14:54:30 -07:00
def test_update_org_invited_user_for_invalid_data_returns_400(
admin_request, sample_invited_org_user
):
data = {"status": "garbage"}
json_resp = admin_request.post(
2023-08-29 14:54:30 -07:00
"organization_invite.update_org_invite_status",
2023-07-10 11:06:29 -07:00
organization_id=sample_invited_org_user.organization_id,
invited_org_user_id=sample_invited_org_user.id,
_data=data,
2023-08-29 14:54:30 -07:00
_expected_status=400,
)
assert len(json_resp["errors"]) == 1
assert (
json_resp["errors"][0]["message"]
== "status garbage is not one of [pending, accepted, cancelled, expired]"
)
2023-08-29 14:54:30 -07:00
@pytest.mark.parametrize(
"endpoint_format_str",
[
"/invite/organization/{}",
"/invite/organization/check/{}",
],
)
def test_validate_invitation_token_returns_200_when_token_valid(
client, sample_invited_org_user, endpoint_format_str
):
token = generate_token(
str(sample_invited_org_user.id),
current_app.config["SECRET_KEY"],
current_app.config["DANGEROUS_SALT"],
)
url = endpoint_format_str.format(token)
auth_header = create_admin_authorization_header()
2023-08-29 14:54:30 -07:00
response = client.get(
url, headers=[("Content-Type", "application/json"), auth_header]
)
assert response.status_code == 200
json_resp = json.loads(response.get_data(as_text=True))
2023-08-29 14:54:30 -07:00
assert json_resp["data"] == sample_invited_org_user.serialize()
def test_validate_invitation_token_for_expired_token_returns_400(client):
2023-08-29 14:54:30 -07:00
with freeze_time("2016-01-01T12:00:00"):
token = generate_token(
str(uuid.uuid4()),
current_app.config["SECRET_KEY"],
current_app.config["DANGEROUS_SALT"],
)
url = "/invite/organization/{}".format(token)
auth_header = create_admin_authorization_header()
2023-08-29 14:54:30 -07:00
response = client.get(
url, headers=[("Content-Type", "application/json"), auth_header]
)
assert response.status_code == 400
json_resp = json.loads(response.get_data(as_text=True))
2023-08-29 14:54:30 -07:00
assert json_resp["result"] == "error"
assert json_resp["message"] == {
"invitation": "Your invitation to GOV.UK Notify has expired. "
"Please ask the person that invited you to send you another one"
}
def test_validate_invitation_token_returns_400_when_invited_user_does_not_exist(client):
2023-08-29 14:54:30 -07:00
token = generate_token(
str(uuid.uuid4()),
current_app.config["SECRET_KEY"],
current_app.config["DANGEROUS_SALT"],
)
url = "/invite/organization/{}".format(token)
auth_header = create_admin_authorization_header()
2023-08-29 14:54:30 -07:00
response = client.get(
url, headers=[("Content-Type", "application/json"), auth_header]
)
assert response.status_code == 404
json_resp = json.loads(response.get_data(as_text=True))
2023-08-29 14:54:30 -07:00
assert json_resp["result"] == "error"
assert json_resp["message"] == "No result found"
def test_validate_invitation_token_returns_400_when_token_is_malformed(client):
token = generate_token(
str(uuid.uuid4()),
2023-08-29 14:54:30 -07:00
current_app.config["SECRET_KEY"],
current_app.config["DANGEROUS_SALT"],
)[:-2]
2023-08-29 14:54:30 -07:00
url = "/invite/organization/{}".format(token)
auth_header = create_admin_authorization_header()
2023-08-29 14:54:30 -07:00
response = client.get(
url, headers=[("Content-Type", "application/json"), auth_header]
)
assert response.status_code == 400
json_resp = json.loads(response.get_data(as_text=True))
2023-08-29 14:54:30 -07:00
assert json_resp["result"] == "error"
assert json_resp["message"] == {
"invitation": "Somethings wrong with this link. Make sure youve copied the whole thing."
}
def test_get_invited_org_user(admin_request, sample_invited_org_user):
json_resp = admin_request.get(
2023-08-29 14:54:30 -07:00
"organization_invite.get_invited_org_user",
invited_org_user_id=sample_invited_org_user.id,
)
assert json_resp["data"]["id"] == str(sample_invited_org_user.id)
assert json_resp["data"]["email_address"] == sample_invited_org_user.email_address
assert json_resp["data"]["organization"] == str(
sample_invited_org_user.organization_id
)
2023-08-29 14:54:30 -07:00
def test_get_invited_org_user_404s_if_invite_doesnt_exist(
admin_request, sample_invited_org_user, fake_uuid
):
json_resp = admin_request.get(
2023-08-29 14:54:30 -07:00
"organization_invite.get_invited_org_user",
invited_org_user_id=fake_uuid,
2023-08-29 14:54:30 -07:00
_expected_status=404,
)
2023-08-29 14:54:30 -07:00
assert json_resp["result"] == "error"