(models) add MailDomain status

Add some status to allow to create mailboxes only for an active domain
This commit is contained in:
Sabrina Demagny
2024-07-07 01:16:33 +02:00
parent d69861c148
commit 955a3dd226
8 changed files with 102 additions and 9 deletions

View File

@@ -15,6 +15,7 @@ class MailDomainAdmin(admin.ModelAdmin):
"created_at",
"updated_at",
"slug",
"status",
)
search_fields = ("name",)
readonly_fields = ["created_at", "slug"]

View File

@@ -0,0 +1,15 @@
"""
Application enums declaration
"""
from django.db import models
from django.utils.translation import gettext_lazy as _
class MailDomainStatusChoices(models.TextChoices):
"""Defines the possible statuses in which a mail domain can be."""
PENDING = "pending", _("Pending")
ENABLED = "enabled", _("Enabled")
FAILED = "failed", _("Failed")
DISABLED = "disabled", _("Disabled")

View File

@@ -10,13 +10,15 @@ from faker import Faker
from core import factories as core_factories
from core import models as core_models
from mailbox_manager import models
from mailbox_manager import enums, models
fake = Faker()
class MailDomainFactory(factory.django.DjangoModelFactory):
"""A factory to create mail domain."""
"""A factory to create mail domain. Please not this is a factory to create mail domain with
default values. So the status is pending and no mailbox can be created from it,
until the mail domain is enabled."""
class Meta:
model = models.MailDomain
@@ -40,6 +42,12 @@ class MailDomainFactory(factory.django.DjangoModelFactory):
)
class MailDomainEnabledFactory(MailDomainFactory):
"""A factory to create mail domain enabled."""
status = enums.MailDomainStatusChoices.ENABLED
class MailDomainAccessFactory(factory.django.DjangoModelFactory):
"""A factory to create mail domain accesses."""
@@ -63,5 +71,5 @@ class MailboxFactory(factory.django.DjangoModelFactory):
full_name = factory.Faker("name")
local_part = factory.LazyAttribute(lambda a: a.full_name.lower().replace(" ", "."))
domain = factory.SubFactory(MailDomainFactory)
domain = factory.SubFactory(MailDomainEnabledFactory)
secondary_email = factory.Faker("email")

View File

@@ -0,0 +1,18 @@
# Generated by Django 5.0.6 on 2024-07-06 23:14
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('mailbox_manager', '0005_alter_maildomain_slug'),
]
operations = [
migrations.AddField(
model_name='maildomain',
name='status',
field=models.CharField(choices=[('pending', 'Pending'), ('enabled', 'Enabled'), ('failed', 'Failed'), ('disabled', 'Disabled')], default='pending', max_length=10),
),
]

View File

@@ -4,12 +4,15 @@ Declare and configure the models for the People additional application : mailbox
from django.conf import settings
from django.core import validators
from django.core.exceptions import ValidationError
from django.db import models
from django.utils.text import slugify
from django.utils.translation import gettext_lazy as _
from core.models import BaseModel, RoleChoices
from mailbox_manager.enums import MailDomainStatusChoices
class MailDomain(BaseModel):
"""Domain names from which we will create email addresses (mailboxes)."""
@@ -18,6 +21,11 @@ class MailDomain(BaseModel):
_("name"), max_length=150, null=False, blank=False, unique=True
)
slug = models.SlugField(null=False, blank=False, unique=True, max_length=80)
status = models.CharField(
max_length=10,
default=MailDomainStatusChoices.PENDING,
choices=MailDomainStatusChoices.choices,
)
class Meta:
db_table = "people_mail_domain"
@@ -120,3 +128,9 @@ class Mailbox(BaseModel):
def __str__(self):
return f"{self.local_part!s}@{self.domain.name:s}"
def save(self, *args, **kwargs):
self.full_clean()
if self.domain.status != MailDomainStatusChoices.ENABLED:
raise ValidationError("You can create mailbox only for a domain enabled")
super().save(*args, **kwargs)

View File

@@ -15,7 +15,7 @@ pytestmark = pytest.mark.django_db
def test_api_mailboxes__create_anonymous_forbidden():
"""Anonymous users should not be able to create a new mailbox via the API."""
mail_domain = factories.MailDomainFactory()
mail_domain = factories.MailDomainEnabledFactory()
response = APIClient().post(
f"/api/v1.0/mail-domains/{mail_domain.slug}/mailboxes/",
@@ -41,7 +41,7 @@ def test_api_mailboxes__create_authenticated_missing_fields():
client = APIClient()
client.force_login(user)
mail_domain = factories.MailDomainFactory()
mail_domain = factories.MailDomainEnabledFactory()
response = client.post(
f"/api/v1.0/mail-domains/{mail_domain.slug}/mailboxes/",
{
@@ -78,7 +78,7 @@ def test_api_mailboxes__create_authenticated_successful():
client = APIClient()
client.force_login(user)
mail_domain = factories.MailDomainFactory(name="saint-jean.collectivite.fr")
mail_domain = factories.MailDomainEnabledFactory(name="saint-jean.collectivite.fr")
response = client.post(
f"/api/v1.0/mail-domains/{mail_domain.slug}/mailboxes/",
{

View File

@@ -15,7 +15,7 @@ pytestmark = pytest.mark.django_db
def test_api_mailboxes__list_anonymous():
"""Anonymous users should not be allowed to list mailboxes."""
mail_domain = factories.MailDomainFactory()
mail_domain = factories.MailDomainEnabledFactory()
factories.MailboxFactory.create_batch(2, domain=mail_domain)
response = APIClient().get(f"/api/v1.0/mail-domains/{mail_domain.slug}/mailboxes/")
@@ -32,7 +32,7 @@ def test_api_mailboxes__list_authenticated_no_query():
client = APIClient()
client.force_login(user)
mail_domain = factories.MailDomainFactory()
mail_domain = factories.MailDomainEnabledFactory()
mailbox1 = factories.MailboxFactory(domain=mail_domain)
mailbox2 = factories.MailboxFactory(domain=mail_domain)

View File

@@ -6,7 +6,7 @@ from django.core.exceptions import ValidationError
import pytest
from mailbox_manager import factories
from mailbox_manager import enums, factories
pytestmark = pytest.mark.django_db
@@ -89,3 +89,40 @@ def test_models_mailboxes__secondary_email_cannot_be_null():
"""The "secondary_email" field should not be null."""
with pytest.raises(ValidationError, match="This field cannot be null"):
factories.MailboxFactory(secondary_email=None)
def test_models_mailboxes__cannot_be_created_for_disabled_maildomain():
"""Mailbox creation is allowed only for a domain enabled.
A disabled status for the mail domain raises an error."""
with pytest.raises(
ValidationError, match="You can create mailbox only for a domain enabled"
):
factories.MailboxFactory(
domain=factories.MailDomainFactory(
status=enums.MailDomainStatusChoices.DISABLED
)
)
def test_models_mailboxes__cannot_be_created_for_failed_maildomain():
"""Mailbox creation is allowed only for a domain enabled.
A failed status for the mail domain raises an error."""
with pytest.raises(
ValidationError, match="You can create mailbox only for a domain enabled"
):
factories.MailboxFactory(
domain=factories.MailDomainFactory(
status=enums.MailDomainStatusChoices.FAILED
)
)
def test_models_mailboxes__cannot_be_created_for_pending_maildomain():
"""Mailbox creation is allowed only for a domain enabled.
A pending status for the mail domain raises an error."""
with pytest.raises(
ValidationError, match="You can create mailbox only for a domain enabled"
):
# MailDomainFactory initializes a mail domain with default values,
# so mail domain status is pending!
factories.MailboxFactory(domain=factories.MailDomainFactory())