♻️(backend) rename DomainInvitation
All models relacted to mail domain are prefixed with "MailDomain". Do the same for mail domain invitations.
This commit is contained in:
@@ -269,11 +269,11 @@ class MailDomainAccessReadOnlySerializer(MailDomainAccessSerializer):
|
||||
]
|
||||
|
||||
|
||||
class DomainInvitationSerializer(serializers.ModelSerializer):
|
||||
class MailDomainInvitationSerializer(serializers.ModelSerializer):
|
||||
"""Serialize invitations."""
|
||||
|
||||
class Meta:
|
||||
model = models.DomainInvitation
|
||||
model = models.MailDomainInvitation
|
||||
fields = ["id", "created_at", "email", "domain", "role", "issuer", "is_expired"]
|
||||
read_only_fields = ["id", "created_at", "domain", "issuer", "is_expired"]
|
||||
|
||||
|
||||
@@ -294,7 +294,7 @@ class MailBoxViewSet(
|
||||
return Response(serializers.MailboxSerializer(mailbox).data)
|
||||
|
||||
|
||||
class DomainInvitationViewset(
|
||||
class MailDomainInvitationViewset(
|
||||
mixins.CreateModelMixin,
|
||||
mixins.ListModelMixin,
|
||||
mixins.RetrieveModelMixin,
|
||||
@@ -320,11 +320,11 @@ class DomainInvitationViewset(
|
||||
lookup_field = "id"
|
||||
permission_classes = [permissions.AccessPermission]
|
||||
queryset = (
|
||||
models.DomainInvitation.objects.all()
|
||||
models.MailDomainInvitation.objects.all()
|
||||
.select_related("domain")
|
||||
.order_by("-created_at")
|
||||
)
|
||||
serializer_class = serializers.DomainInvitationSerializer
|
||||
serializer_class = serializers.MailDomainInvitationSerializer
|
||||
|
||||
def get_serializer_context(self):
|
||||
"""Extra context provided to the serializer class."""
|
||||
|
||||
@@ -86,11 +86,11 @@ class MailboxEnabledFactory(MailboxFactory):
|
||||
status = enums.MailboxStatusChoices.ENABLED
|
||||
|
||||
|
||||
class DomainInvitationFactory(factory.django.DjangoModelFactory):
|
||||
class MailDomainInvitationFactory(factory.django.DjangoModelFactory):
|
||||
"""A factory to create invitations for a user"""
|
||||
|
||||
class Meta:
|
||||
model = models.DomainInvitation
|
||||
model = models.MailDomainInvitation
|
||||
|
||||
domain = factory.SubFactory(MailDomainEnabledFactory)
|
||||
email = factory.Faker("email")
|
||||
|
||||
@@ -15,20 +15,20 @@ class Migration(migrations.Migration):
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='DomainInvitation',
|
||||
name='MailDomainInvitation',
|
||||
fields=[
|
||||
('id', models.UUIDField(default=uuid.uuid4, editable=False, help_text='primary key for the record as UUID', primary_key=True, serialize=False, verbose_name='id')),
|
||||
('created_at', models.DateTimeField(auto_now_add=True, help_text='date and time at which a record was created', verbose_name='created at')),
|
||||
('updated_at', models.DateTimeField(auto_now=True, help_text='date and time at which a record was last updated', verbose_name='updated at')),
|
||||
('email', models.EmailField(max_length=254, verbose_name='email address')),
|
||||
('role', models.CharField(choices=[('viewer', 'Viewer'), ('administrator', 'Administrator'), ('owner', 'Owner')], default='viewer', max_length=20)),
|
||||
('domain', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='domain_invitations', to='mailbox_manager.maildomain')),
|
||||
('issuer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='domain_invitations', to=settings.AUTH_USER_MODEL)),
|
||||
('domain', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='mail_domain_invitations', to='mailbox_manager.maildomain')),
|
||||
('issuer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='mail_domain_invitations', to=settings.AUTH_USER_MODEL)),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Domain invitation',
|
||||
'verbose_name_plural': 'Domain invitations',
|
||||
'db_table': 'people_domain_invitation',
|
||||
'verbose_name': 'Mail domain invitation',
|
||||
'verbose_name_plural': 'Mail domain invitations',
|
||||
'db_table': 'people_mail_domain_invitation',
|
||||
'constraints': [models.UniqueConstraint(fields=('email', 'domain'), name='email_and_domain_unique_together')],
|
||||
},
|
||||
),
|
||||
|
||||
@@ -275,18 +275,18 @@ class Mailbox(AbstractBaseUser, BaseModel):
|
||||
return f"{self.local_part}@{self.domain.name}"
|
||||
|
||||
|
||||
class DomainInvitation(BaseInvitation):
|
||||
class MailDomainInvitation(BaseInvitation):
|
||||
"""User invitation to teams."""
|
||||
|
||||
issuer = models.ForeignKey(
|
||||
User,
|
||||
on_delete=models.CASCADE,
|
||||
related_name="domain_invitations",
|
||||
related_name="mail_domain_invitations",
|
||||
)
|
||||
domain = models.ForeignKey(
|
||||
MailDomain,
|
||||
on_delete=models.CASCADE,
|
||||
related_name="domain_invitations",
|
||||
related_name="mail_domain_invitations",
|
||||
)
|
||||
role = models.CharField(
|
||||
max_length=20,
|
||||
@@ -295,9 +295,9 @@ class DomainInvitation(BaseInvitation):
|
||||
)
|
||||
|
||||
class Meta:
|
||||
db_table = "people_domain_invitation"
|
||||
verbose_name = _("Domain invitation")
|
||||
verbose_name_plural = _("Domain invitations")
|
||||
db_table = "people_mail_domain_invitation"
|
||||
verbose_name = _("Mail domain invitation")
|
||||
verbose_name_plural = _("Mail domain invitations")
|
||||
constraints = [
|
||||
models.UniqueConstraint(
|
||||
fields=["email", "domain"], name="email_and_domain_unique_together"
|
||||
|
||||
@@ -13,7 +13,7 @@ from django.utils import timezone
|
||||
from core.models import User
|
||||
|
||||
from mailbox_manager import enums
|
||||
from mailbox_manager.models import DomainInvitation, MailDomainAccess
|
||||
from mailbox_manager.models import MailDomainAccess, MailDomainInvitation
|
||||
from mailbox_manager.utils.dimail import DimailAPIClient
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -27,7 +27,7 @@ def convert_domain_invitations(sender, created, instance, **kwargs): # pylint:
|
||||
"""
|
||||
logger.info("Convert domain invitations for user %s", instance)
|
||||
if created:
|
||||
valid_domain_invitations = DomainInvitation.objects.filter(
|
||||
valid_domain_invitations = MailDomainInvitation.objects.filter(
|
||||
email=instance.email,
|
||||
created_at__gte=(
|
||||
timezone.now()
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
"""
|
||||
Tests for DomainInvitations API endpoint in People's app mailbox_manager. Focus on "create" action.
|
||||
Tests for MailDomainInvitations API endpoint in People's app mailbox_manager.
|
||||
Focus on "create" action.
|
||||
"""
|
||||
|
||||
import pytest
|
||||
@@ -17,8 +18,8 @@ pytestmark = pytest.mark.django_db
|
||||
def test_api_domain_invitations__create__anonymous():
|
||||
"""Anonymous users should not be able to create invitations."""
|
||||
domain = factories.MailDomainEnabledFactory()
|
||||
invitation_values = serializers.DomainInvitationSerializer(
|
||||
factories.DomainInvitationFactory.build()
|
||||
invitation_values = serializers.MailDomainInvitationSerializer(
|
||||
factories.MailDomainInvitationFactory.build()
|
||||
).data
|
||||
|
||||
response = APIClient().post(
|
||||
@@ -37,8 +38,8 @@ def test_api_domain_invitations__create__authenticated_outsider():
|
||||
for a domain they don't manage."""
|
||||
user = core_factories.UserFactory()
|
||||
domain = factories.MailDomainEnabledFactory()
|
||||
invitation_values = serializers.DomainInvitationSerializer(
|
||||
factories.DomainInvitationFactory.build()
|
||||
invitation_values = serializers.MailDomainInvitationSerializer(
|
||||
factories.MailDomainInvitationFactory.build()
|
||||
).data
|
||||
|
||||
client = APIClient()
|
||||
@@ -62,8 +63,8 @@ def test_api_domain_invitations__admin_should_create_invites(role):
|
||||
domain = factories.MailDomainEnabledFactory()
|
||||
factories.MailDomainAccessFactory(domain=domain, user=user, role=role)
|
||||
|
||||
invitation_values = serializers.DomainInvitationSerializer(
|
||||
factories.DomainInvitationFactory.build()
|
||||
invitation_values = serializers.MailDomainInvitationSerializer(
|
||||
factories.MailDomainInvitationFactory.build()
|
||||
).data
|
||||
|
||||
client = APIClient()
|
||||
@@ -87,8 +88,8 @@ def test_api_domain_invitations__viewers_should_not_invite_to_manage_domains():
|
||||
domain=domain, user=user, role=enums.MailDomainRoleChoices.VIEWER
|
||||
)
|
||||
|
||||
invitation_values = serializers.DomainInvitationSerializer(
|
||||
factories.DomainInvitationFactory.build()
|
||||
invitation_values = serializers.MailDomainInvitationSerializer(
|
||||
factories.MailDomainInvitationFactory.build()
|
||||
).data
|
||||
|
||||
client = APIClient()
|
||||
@@ -107,7 +108,7 @@ def test_api_domain_invitations__viewers_should_not_invite_to_manage_domains():
|
||||
|
||||
def test_api_domain_invitations__should_not_create_duplicate_invitations():
|
||||
"""An email should not be invited multiple times to the same domain."""
|
||||
existing_invitation = factories.DomainInvitationFactory()
|
||||
existing_invitation = factories.MailDomainInvitationFactory()
|
||||
domain = existing_invitation.domain
|
||||
|
||||
# Grant privileged role on the domain to the user
|
||||
@@ -117,8 +118,8 @@ def test_api_domain_invitations__should_not_create_duplicate_invitations():
|
||||
)
|
||||
|
||||
# Create a new invitation to the same domain with the exact same email address
|
||||
duplicated_invitation = serializers.DomainInvitationSerializer(
|
||||
factories.DomainInvitationFactory.build(email=existing_invitation.email)
|
||||
duplicated_invitation = serializers.MailDomainInvitationSerializer(
|
||||
factories.MailDomainInvitationFactory.build(email=existing_invitation.email)
|
||||
).data
|
||||
|
||||
client = APIClient()
|
||||
@@ -130,5 +131,5 @@ def test_api_domain_invitations__should_not_create_duplicate_invitations():
|
||||
)
|
||||
assert response.status_code == status.HTTP_400_BAD_REQUEST
|
||||
assert response.json()["__all__"] == [
|
||||
"Domain invitation with this Email address and Domain already exists."
|
||||
"Mail domain invitation with this Email address and Domain already exists."
|
||||
]
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
"""
|
||||
Tests for DomainInvitations API endpoint in People's app mailbox_manager. Focus on "list" action.
|
||||
Tests for MailDomainInvitations API endpoint in People's app mailbox_manager.
|
||||
Focus on "list" action.
|
||||
"""
|
||||
|
||||
import time
|
||||
@@ -37,24 +38,24 @@ def test_api_domain_invitations__domain_managers_should_list_invitations():
|
||||
factories.MailDomainAccessFactory(
|
||||
domain=domain, user=other_user, role=enums.MailDomainRoleChoices.OWNER
|
||||
)
|
||||
invitation = factories.DomainInvitationFactory(
|
||||
invitation = factories.MailDomainInvitationFactory(
|
||||
domain=domain, role=enums.MailDomainRoleChoices.ADMIN, issuer=auth_user
|
||||
)
|
||||
other_invitations = factories.DomainInvitationFactory.create_batch(
|
||||
other_invitations = factories.MailDomainInvitationFactory.create_batch(
|
||||
2, domain=domain, role=enums.MailDomainRoleChoices.VIEWER, issuer=other_user
|
||||
)
|
||||
|
||||
# expired invitations should be listed too
|
||||
# override settings to accelerate validation expiration
|
||||
settings.INVITATION_VALIDITY_DURATION = 1 # second
|
||||
expired_invitation = factories.DomainInvitationFactory(
|
||||
expired_invitation = factories.MailDomainInvitationFactory(
|
||||
domain=domain, role=enums.MailDomainRoleChoices.VIEWER, issuer=auth_user
|
||||
)
|
||||
time.sleep(1)
|
||||
|
||||
# invitations from other teams should not be listed
|
||||
other_domain = factories.MailDomainEnabledFactory()
|
||||
factories.DomainInvitationFactory.create_batch(
|
||||
factories.MailDomainInvitationFactory.create_batch(
|
||||
2, domain=other_domain, role=enums.MailDomainRoleChoices.OWNER
|
||||
)
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
"""
|
||||
Tests for DomainInvitations API endpoint. Focus on "retrieve" action.
|
||||
Tests for MailDomainInvitations API endpoint. Focus on "retrieve" action.
|
||||
"""
|
||||
|
||||
import pytest
|
||||
@@ -18,7 +18,7 @@ def test_api_domain_invitations__anonymous_user_should_not_retrieve_invitations(
|
||||
Anonymous user should not be able to retrieve invitations.
|
||||
"""
|
||||
|
||||
invitation = factories.DomainInvitationFactory()
|
||||
invitation = factories.MailDomainInvitationFactory()
|
||||
response = APIClient().get(
|
||||
f"/api/v1.0/mail-domains/{invitation.domain.slug}/invitations/",
|
||||
)
|
||||
@@ -31,7 +31,7 @@ def test_api_domain_invitations__unrelated_user_should_not_retrieve_invitations(
|
||||
Authenticated unrelated users should not be able to retrieve invitations.
|
||||
"""
|
||||
auth_user = core_factories.UserFactory()
|
||||
invitation = factories.DomainInvitationFactory()
|
||||
invitation = factories.MailDomainInvitationFactory()
|
||||
|
||||
client = APIClient()
|
||||
client.force_login(auth_user)
|
||||
@@ -50,7 +50,7 @@ def test_api_domain_invitations__domain_managers_should_list_invitations():
|
||||
whatever their role in the domain.
|
||||
"""
|
||||
auth_user = core_factories.UserFactory()
|
||||
invitation = factories.DomainInvitationFactory()
|
||||
invitation = factories.MailDomainInvitationFactory()
|
||||
factories.MailDomainAccessFactory(
|
||||
domain=invitation.domain, user=auth_user, role=enums.MailDomainRoleChoices.ADMIN
|
||||
)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
"""
|
||||
Unit tests for the Domain Invitation model
|
||||
Unit tests for the Mail Domain Invitation model
|
||||
"""
|
||||
|
||||
import re
|
||||
@@ -23,7 +23,7 @@ pytestmark = pytest.mark.django_db
|
||||
|
||||
def test_models_domain_invitations_readonly_after_create():
|
||||
"""Existing invitations should be readonly."""
|
||||
invitation = factories.DomainInvitationFactory()
|
||||
invitation = factories.MailDomainInvitationFactory()
|
||||
with pytest.raises(exceptions.PermissionDenied):
|
||||
invitation.save()
|
||||
|
||||
@@ -33,7 +33,7 @@ def test_models_domain_invitations__is_expired():
|
||||
The 'is_expired' property should return False until validity duration
|
||||
is exceeded and True afterwards.
|
||||
"""
|
||||
expired_invitation = factories.DomainInvitationFactory()
|
||||
expired_invitation = factories.MailDomainInvitationFactory()
|
||||
assert expired_invitation.is_expired is False
|
||||
|
||||
settings.INVITATION_VALIDITY_DURATION = 1
|
||||
@@ -49,17 +49,17 @@ def test_models_domain_invitation__should_convert_invitations_to_accesses_upon_j
|
||||
"""
|
||||
# Two invitations to the same mail but to different domains
|
||||
email = "future_admin@example.com"
|
||||
invitation_to_domain1 = factories.DomainInvitationFactory(
|
||||
invitation_to_domain1 = factories.MailDomainInvitationFactory(
|
||||
email=email, role=enums.MailDomainRoleChoices.OWNER
|
||||
)
|
||||
invitation_to_domain2 = factories.DomainInvitationFactory(email=email)
|
||||
invitation_to_domain2 = factories.MailDomainInvitationFactory(email=email)
|
||||
|
||||
# an expired invitation that should not be converted
|
||||
with freeze_time("1985-10-30"):
|
||||
expired_invitation = factories.DomainInvitationFactory(email=email)
|
||||
expired_invitation = factories.MailDomainInvitationFactory(email=email)
|
||||
|
||||
# another person invited to domain2
|
||||
other_invitation = factories.DomainInvitationFactory(
|
||||
other_invitation = factories.MailDomainInvitationFactory(
|
||||
domain=invitation_to_domain2.domain
|
||||
)
|
||||
|
||||
@@ -89,15 +89,15 @@ def test_models_domain_invitation__should_convert_invitations_to_accesses_upon_j
|
||||
assert models.MailDomainAccess.objects.filter(
|
||||
domain=invitation_to_domain2.domain, user=new_user
|
||||
).exists()
|
||||
assert not models.DomainInvitation.objects.filter(
|
||||
assert not models.MailDomainInvitation.objects.filter(
|
||||
domain=invitation_to_domain1.domain, email=email
|
||||
).exists() # invitation "consumed"
|
||||
assert not models.DomainInvitation.objects.filter(
|
||||
assert not models.MailDomainInvitation.objects.filter(
|
||||
domain=invitation_to_domain2.domain, email=email
|
||||
).exists() # invitation "consumed"
|
||||
assert models.DomainInvitation.objects.filter(
|
||||
assert models.MailDomainInvitation.objects.filter(
|
||||
domain=expired_invitation.domain, email=email
|
||||
).exists() # expired invitation remains
|
||||
assert models.DomainInvitation.objects.filter(
|
||||
assert models.MailDomainInvitation.objects.filter(
|
||||
domain=invitation_to_domain2.domain, email=other_invitation.email
|
||||
).exists() # the other invitation remains
|
||||
|
||||
@@ -26,7 +26,7 @@ maildomain_related_router.register(
|
||||
|
||||
maildomain_related_router.register(
|
||||
"invitations",
|
||||
viewsets.DomainInvitationViewset,
|
||||
viewsets.MailDomainInvitationViewset,
|
||||
basename="invitations",
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user