🐛(maildomain) fix domain access creation
During a new domain creation, a call to dimail is made to create user/allow on dimail side before owner role creation on our side. So when user/allow creation on dimain side fails, the owner role is not created on our side. Therefore the domain is created but invisible on the user interface. The user will probably try to create the same domain again and see the error message 'this domain already exists'. To avoid this we make sure to create owner role on our side despite dimail failure and set domain to failed status to retry later dimail access creation.
This commit is contained in:
@@ -8,6 +8,10 @@ and this project adheres to
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
### Fixed
|
||||
|
||||
- 🐛(backend) fix manage roles on domain admin view
|
||||
|
||||
### Added
|
||||
|
||||
- ✨(organizations) add siret to name conversion #584
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
"""Client serializers for People's mailbox manager app."""
|
||||
|
||||
import json
|
||||
from logging import getLogger
|
||||
|
||||
from requests.exceptions import HTTPError
|
||||
from rest_framework import exceptions, serializers
|
||||
|
||||
from core.api.client.serializers import UserSerializer
|
||||
@@ -10,6 +12,8 @@ from core.models import User
|
||||
from mailbox_manager import enums, models
|
||||
from mailbox_manager.utils.dimail import DimailAPIClient
|
||||
|
||||
logger = getLogger(__name__)
|
||||
|
||||
|
||||
class MailboxSerializer(serializers.ModelSerializer):
|
||||
"""Serialize mailbox."""
|
||||
@@ -190,14 +194,20 @@ class MailDomainAccessSerializer(serializers.ModelSerializer):
|
||||
"""
|
||||
dimail = DimailAPIClient()
|
||||
|
||||
user = validated_data["user"]
|
||||
domain = validated_data["domain"]
|
||||
|
||||
if validated_data["role"] in [
|
||||
enums.MailDomainRoleChoices.ADMIN,
|
||||
enums.MailDomainRoleChoices.OWNER,
|
||||
]:
|
||||
dimail.create_user(validated_data["user"].sub)
|
||||
dimail.create_allow(
|
||||
validated_data["user"].sub, validated_data["domain"].name
|
||||
)
|
||||
try:
|
||||
dimail.create_user(user.sub)
|
||||
dimail.create_allow(user.sub, domain.name)
|
||||
except HTTPError:
|
||||
logger.exception("[DIMAIL] access creation failed %s")
|
||||
domain.status = enums.MailDomainStatusChoices.FAILED
|
||||
domain.save()
|
||||
|
||||
return super().create(validated_data)
|
||||
|
||||
|
||||
@@ -122,6 +122,77 @@ def test_api_mail_domains__create_authenticated():
|
||||
assert domain.accesses.filter(role="owner", user=user).exists()
|
||||
|
||||
|
||||
def test_api_mail_domains__create_authenticated__dimail_failure():
|
||||
"""
|
||||
Despite a dimail failure for user and/or allow creation,
|
||||
an authenticated user should be able to create a mail domain
|
||||
and should automatically be added as owner of the newly created domain.
|
||||
"""
|
||||
user = core_factories.UserFactory()
|
||||
|
||||
client = APIClient()
|
||||
client.force_login(user)
|
||||
|
||||
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",
|
||||
)
|
||||
rsps.add(
|
||||
rsps.POST,
|
||||
re.compile(r".*/users/"),
|
||||
body=str(
|
||||
{
|
||||
"name": "request-user-sub",
|
||||
"is_admin": "false",
|
||||
"uuid": "user-uuid-on-dimail",
|
||||
"perms": [],
|
||||
}
|
||||
),
|
||||
status=status.HTTP_201_CREATED,
|
||||
content_type="application/json",
|
||||
)
|
||||
rsps.add(
|
||||
rsps.POST,
|
||||
re.compile(r".*/allows/"),
|
||||
body=str({"user": "request-user-sub", "domain": str(domain_name)}),
|
||||
status=status.HTTP_403_FORBIDDEN,
|
||||
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()
|
||||
|
||||
# response is as expected
|
||||
assert response.json() == {
|
||||
"id": str(domain.id),
|
||||
"name": domain.name,
|
||||
"slug": domain.slug,
|
||||
"status": enums.MailDomainStatusChoices.FAILED,
|
||||
"created_at": domain.created_at.isoformat().replace("+00:00", "Z"),
|
||||
"updated_at": domain.updated_at.isoformat().replace("+00:00", "Z"),
|
||||
"abilities": domain.get_abilities(user),
|
||||
}
|
||||
|
||||
# a new domain with status "failed" is created and authenticated user is the owner
|
||||
assert domain.status == enums.MailDomainStatusChoices.FAILED
|
||||
assert domain.name == domain_name
|
||||
assert domain.accesses.filter(role="owner", user=user).exists()
|
||||
|
||||
|
||||
## SYNC TO DIMAIL
|
||||
def test_api_mail_domains__create_dimail_domain(caplog):
|
||||
"""
|
||||
|
||||
@@ -245,7 +245,7 @@ class DimailAPIClient:
|
||||
except json.decoder.JSONDecodeError:
|
||||
error_content = response.content.decode(response.encoding)
|
||||
|
||||
logger.error(
|
||||
logger.exception(
|
||||
"[DIMAIL] unexpected error : %s %s", response.status_code, error_content
|
||||
)
|
||||
raise requests.exceptions.HTTPError(
|
||||
|
||||
Reference in New Issue
Block a user