🐛(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]
|
## [Unreleased]
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- 🐛(backend) fix manage roles on domain admin view
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- ✨(organizations) add siret to name conversion #584
|
- ✨(organizations) add siret to name conversion #584
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
"""Client serializers for People's mailbox manager app."""
|
"""Client serializers for People's mailbox manager app."""
|
||||||
|
|
||||||
import json
|
import json
|
||||||
|
from logging import getLogger
|
||||||
|
|
||||||
|
from requests.exceptions import HTTPError
|
||||||
from rest_framework import exceptions, serializers
|
from rest_framework import exceptions, serializers
|
||||||
|
|
||||||
from core.api.client.serializers import UserSerializer
|
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 import enums, models
|
||||||
from mailbox_manager.utils.dimail import DimailAPIClient
|
from mailbox_manager.utils.dimail import DimailAPIClient
|
||||||
|
|
||||||
|
logger = getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class MailboxSerializer(serializers.ModelSerializer):
|
class MailboxSerializer(serializers.ModelSerializer):
|
||||||
"""Serialize mailbox."""
|
"""Serialize mailbox."""
|
||||||
@@ -190,14 +194,20 @@ class MailDomainAccessSerializer(serializers.ModelSerializer):
|
|||||||
"""
|
"""
|
||||||
dimail = DimailAPIClient()
|
dimail = DimailAPIClient()
|
||||||
|
|
||||||
|
user = validated_data["user"]
|
||||||
|
domain = validated_data["domain"]
|
||||||
|
|
||||||
if validated_data["role"] in [
|
if validated_data["role"] in [
|
||||||
enums.MailDomainRoleChoices.ADMIN,
|
enums.MailDomainRoleChoices.ADMIN,
|
||||||
enums.MailDomainRoleChoices.OWNER,
|
enums.MailDomainRoleChoices.OWNER,
|
||||||
]:
|
]:
|
||||||
dimail.create_user(validated_data["user"].sub)
|
try:
|
||||||
dimail.create_allow(
|
dimail.create_user(user.sub)
|
||||||
validated_data["user"].sub, validated_data["domain"].name
|
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)
|
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()
|
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
|
## SYNC TO DIMAIL
|
||||||
def test_api_mail_domains__create_dimail_domain(caplog):
|
def test_api_mail_domains__create_dimail_domain(caplog):
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -245,7 +245,7 @@ class DimailAPIClient:
|
|||||||
except json.decoder.JSONDecodeError:
|
except json.decoder.JSONDecodeError:
|
||||||
error_content = response.content.decode(response.encoding)
|
error_content = response.content.decode(response.encoding)
|
||||||
|
|
||||||
logger.error(
|
logger.exception(
|
||||||
"[DIMAIL] unexpected error : %s %s", response.status_code, error_content
|
"[DIMAIL] unexpected error : %s %s", response.status_code, error_content
|
||||||
)
|
)
|
||||||
raise requests.exceptions.HTTPError(
|
raise requests.exceptions.HTTPError(
|
||||||
|
|||||||
Reference in New Issue
Block a user