(dimail) send domain creation request to dimail

Send domain creation request to dimail when someone creates a domain in people.
This commit is contained in:
Marie PUPO JEAMMET
2024-10-23 18:44:14 +02:00
committed by Marie
parent 8f30264445
commit 21bf431940
5 changed files with 166 additions and 8 deletions

View File

@@ -77,6 +77,19 @@ class MailDomainSerializer(serializers.ModelSerializer):
return domain.get_abilities(request.user)
return {}
def create(self, validated_data):
"""
Override create function to fire a request to dimail upon domain creation.
"""
# send new domain request to dimail
client = DimailAPIClient()
client.send_domain_creation_request(
validated_data["name"], self.context["request"].user.sub
)
# no exception raised ? Then actually save domain on our database
return models.MailDomain.objects.create(**validated_data)
class MailDomainAccessSerializer(serializers.ModelSerializer):
"""Serialize mail domain access."""

View File

@@ -2,7 +2,13 @@
Tests for MailDomains API endpoint in People's app mailbox_manager. Focus on "create" action.
"""
import re
from logging import Logger
from unittest import mock
import pytest
import responses
from requests.exceptions import HTTPError
from rest_framework import status
from rest_framework.test import APIClient
@@ -56,13 +62,26 @@ def test_api_mail_domains__create_authenticated():
client = APIClient()
client.force_login(user)
response = client.post(
"/api/v1.0/mail-domains/",
{
"name": "mydomain.com",
},
format="json",
)
domain_name = "test.domain.fr"
with responses.RequestsMock() as rsps:
rsps.add(
rsps.POST,
re.compile(r".*/domains/"),
body=str(
{
"name": domain_name,
}
),
status=status.HTTP_201_CREATED,
content_type="application/json",
)
response = client.post(
"/api/v1.0/mail-domains/",
{"name": domain_name, "context": "null", "features": ["webmail"]},
format="json",
)
assert response.status_code == status.HTTP_201_CREATED
domain = models.MailDomain.objects.get()
@@ -79,5 +98,94 @@ def test_api_mail_domains__create_authenticated():
# a new domain with status "pending" is created and authenticated user is the owner
assert domain.status == enums.MailDomainStatusChoices.PENDING
assert domain.name == "mydomain.com"
assert domain.name == domain_name
assert domain.accesses.filter(role="owner", user=user).exists()
## SYNC TO DIMAIL
@mock.patch.object(Logger, "info")
def test_api_mail_domains__create_dimail_domain(mock_info):
"""
Creating a domain should trigger a call to create a domain on dimail too.
"""
user = core_factories.UserFactory()
client = APIClient()
client.force_login(user)
domain_name = "test.fr"
with responses.RequestsMock() as rsps:
rsp = rsps.add(
rsps.POST,
re.compile(r".*/domains/"),
body=str(
{
"name": domain_name,
}
),
status=status.HTTP_201_CREATED,
content_type="application/json",
)
response = client.post(
"/api/v1.0/mail-domains/",
{
"name": domain_name,
},
format="json",
)
assert response.status_code == status.HTTP_201_CREATED
assert rsp.call_count == 1 # endpoint was called
# Logger
assert (
mock_info.call_count == 2
) # should be 1. A new empty info has been added. To be investigated
assert mock_info.call_args_list[0][0] == (
"Domain %s successfully created on dimail by user %s",
domain_name,
user.sub,
)
def test_api_mail_domains__no_creation_when_dimail_duplicate(caplog):
"""No domain should be created when dimail returns a 409 conflict."""
user = core_factories.UserFactory()
client = APIClient()
client.force_login(user)
domain_name = "test.fr"
dimail_error = {
"status_code": status.HTTP_409_CONFLICT,
"detail": "Domain already exists",
}
with responses.RequestsMock() as rsps:
rsp = rsps.add(
rsps.POST,
re.compile(r".*/domains/"),
body=str({"detail": dimail_error["detail"]}),
status=dimail_error["status_code"],
content_type="application/json",
)
with pytest.raises(HTTPError):
response = client.post(
"/api/v1.0/mail-domains/",
{
"name": domain_name,
},
format="json",
)
assert rsp.call_count == 1 # endpoint was called
assert response.status_code == dimail_error["status_code"]
assert response.json() == {"detail": dimail_error["detail"]}
# check logs
assert len(caplog.records) == 2 # 1 + new empty info. To be investigated
record = caplog.records[0]
assert record.levelname == "ERROR"
assert (
record.message
== f"[DIMAIL] {dimail_error['status_code']}: {dimail_error['detail']}"
)

View File

@@ -76,6 +76,40 @@ class DimailAPIClient:
return self.pass_dimail_unexpected_response(response)
def send_domain_creation_request(self, domain_name, request_user):
"""Send a domain creation request to dimail API."""
payload = {
"domain": domain_name,
"context": domain_name, # for now, we put each domain on its own context
"features": ["webmail", "mailboxes"],
}
try:
response = session.post(
f"{self.API_URL}/domains/",
json=payload,
headers={"Authorization": f"Basic {self.API_CREDENTIALS}"},
verify=True,
timeout=10,
)
except requests.exceptions.ConnectionError as error:
logger.error(
"Connection error while trying to reach %s.",
self.API_URL,
exc_info=error,
)
raise error
if response.status_code == status.HTTP_201_CREATED:
logger.info(
"Domain %s successfully created on dimail by user %s",
domain_name,
request_user,
)
return response
return self.pass_dimail_unexpected_response(response)
def send_mailbox_request(self, mailbox, user_sub=None):
"""Send a CREATE mailbox request to mail provisioning API."""