(mailboxes) add mail provisioning api integration

We want people to create new mailboxes in La Régie.
This commit adds integration with intermediary dimail-api,
which will in turn send our email creation request to Open-Xchange.
This commit is contained in:
Marie PUPO JEAMMET
2024-08-05 12:20:44 +02:00
committed by Marie
parent 2c82f38c59
commit f55cb3a813
12 changed files with 432 additions and 13 deletions

View File

@@ -2,7 +2,11 @@
Unit tests for the mailbox API
"""
import json
import re
import pytest
import responses
from rest_framework import status
from rest_framework.test import APIClient
@@ -130,12 +134,12 @@ def test_api_mailboxes__create_with_accent_success(role):
mailbox_values = serializers.MailboxSerializer(
factories.MailboxFactory.build(first_name="Aimé")
).data
response = client.post(
f"/api/v1.0/mail-domains/{mail_domain.slug}/mailboxes/",
mailbox_values,
format="json",
)
assert response.status_code == status.HTTP_201_CREATED
mailbox = models.Mailbox.objects.get()
@@ -187,3 +191,135 @@ def test_api_mailboxes__create_administrator_missing_fields():
assert response.status_code == status.HTTP_400_BAD_REQUEST
assert not models.Mailbox.objects.exists()
assert response.json() == {"secondary_email": ["This field is required."]}
### SYNC TO PROVISIONING API
def test_api_mailboxes__unrelated_user_provisioning_api_not_called():
"""
Provisioning API should not be called if an user tries
to create a mailbox on a domain they have no access to.
"""
domain = factories.MailDomainEnabledFactory()
client = APIClient()
client.force_login(core_factories.UserFactory()) # user with no access
body_values = serializers.MailboxSerializer(
factories.MailboxFactory.build(domain=domain)
).data
with responses.RequestsMock():
# We add no simulated response in RequestsMock
# because we expected no "outside" calls to be made
response = client.post(
f"/api/v1.0/mail-domains/{domain.slug}/mailboxes/",
body_values,
format="json",
)
# No exception raised by RequestsMock means no call was sent
# our API blocked the request before sending it
assert response.status_code == status.HTTP_403_FORBIDDEN
def test_api_mailboxes__domain_viewer_provisioning_api_not_called():
"""
Provisioning API should not be called if a domain viewer tries
to create a mailbox on a domain they are not owner/admin of.
"""
access = factories.MailDomainAccessFactory(
domain=factories.MailDomainEnabledFactory(),
user=core_factories.UserFactory(),
role=enums.MailDomainRoleChoices.VIEWER,
)
client = APIClient()
client.force_login(access.user)
body_values = serializers.MailboxSerializer(factories.MailboxFactory.build()).data
with responses.RequestsMock():
# We add no simulated response in RequestsMock
# because we expected no "outside" calls to be made
response = client.post(
f"/api/v1.0/mail-domains/{access.domain.slug}/mailboxes/",
body_values,
format="json",
)
# No exception raised by RequestsMock means no call was sent
# our API blocked the request before sending it
assert response.status_code == status.HTTP_403_FORBIDDEN
@pytest.mark.parametrize(
"role",
[enums.MailDomainRoleChoices.ADMIN, enums.MailDomainRoleChoices.OWNER],
)
def test_api_mailboxes__domain_owner_or_admin_successful_creation_and_provisioning(
role,
):
"""
Domain owner/admin should be able to create mailboxes.
Provisioning API should be called when owner/admin makes a call.
Expected response contains new email and password.
"""
# creating all needed objects
access = factories.MailDomainAccessFactory(role=role)
client = APIClient()
client.force_login(access.user)
mailbox_data = serializers.MailboxSerializer(
factories.MailboxFactory.build(domain=access.domain)
).data
with responses.RequestsMock() as rsps:
# Ensure successful response using "responses":
rsps.add(
rsps.GET,
re.compile(r".*/token/"),
body='{"access_token": "domain_owner_token"}',
status=status.HTTP_200_OK,
content_type="application/json",
)
rsp = rsps.add(
rsps.POST,
re.compile(rf".*/domains/{access.domain.name}/mailboxes/"),
body=str(
{
"email": f"{mailbox_data['local_part']}@{access.domain.name}",
"password": "newpass",
"uuid": "uuid",
}
),
status=status.HTTP_201_CREATED,
content_type="application/json",
)
response = client.post(
f"/api/v1.0/mail-domains/{access.domain.slug}/mailboxes/",
mailbox_data,
format="json",
)
# Checks payload sent to email-provisioning API
payload = json.loads(rsps.calls[1].request.body)
assert payload == {
"displayName": f"{mailbox_data['first_name']} {mailbox_data['last_name']}",
"email": f"{mailbox_data['local_part']}@{access.domain.name}",
"givenName": mailbox_data["first_name"],
"surName": mailbox_data["last_name"],
}
# Checks response
assert response.status_code == status.HTTP_201_CREATED
assert rsp.call_count == 1
mailbox = models.Mailbox.objects.get()
assert response.json() == {
"id": str(mailbox.id),
"first_name": str(mailbox_data["first_name"]),
"last_name": str(mailbox_data["last_name"]),
"local_part": str(mailbox_data["local_part"]),
"secondary_email": str(mailbox_data["secondary_email"]),
}
assert mailbox.first_name == mailbox_data["first_name"]
assert mailbox.last_name == mailbox_data["last_name"]
assert mailbox.local_part == mailbox_data["local_part"]
assert mailbox.secondary_email == mailbox_data["secondary_email"]