🐛(mailbox) fix case-sensitive duplicate display names
uniqueness on first name + last name was case-sensitive, which allowed duplicates
This commit is contained in:
committed by
Marie
parent
302671bc69
commit
71a7bf688f
@@ -8,6 +8,7 @@ and this project adheres to
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
- 🐛(mailbox) fix case-sensitive duplicates on display names
|
||||
- ✨(mailbox) synchronize password of newly created mailbox with Dimail's
|
||||
|
||||
## [1.19.1] - 2025-09-19
|
||||
|
||||
@@ -206,7 +206,7 @@ class MailboxAdmin(UserAdmin):
|
||||
|
||||
list_display = ("__str__", "domain", "status", "updated_at")
|
||||
list_filter = ("status",)
|
||||
search_fields = ("local_part", "domain__name")
|
||||
search_fields = ("local_part", "domain__name", "first_name", "last_name")
|
||||
readonly_fields = ["updated_at"]
|
||||
|
||||
fieldsets = None
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
# Generated by Django 5.2.7 on 2025-10-21 15:49
|
||||
|
||||
import django.db.models.functions.text
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('mailbox_manager', '0026_alter_mailbox_unique_together_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveConstraint(
|
||||
model_name='mailbox',
|
||||
name='unique_ox_display_name',
|
||||
),
|
||||
migrations.AddConstraint(
|
||||
model_name='mailbox',
|
||||
constraint=models.UniqueConstraint(django.db.models.functions.text.Lower('first_name'), django.db.models.functions.text.Lower('last_name'), models.F('domain'), name='unique_ox_display_name', violation_error_message='Mailbox with this First name, Last name and Domain already exists.'),
|
||||
),
|
||||
]
|
||||
@@ -10,6 +10,7 @@ from django.contrib.auth.base_user import AbstractBaseUser
|
||||
from django.contrib.sites.models import Site
|
||||
from django.core import exceptions, mail, validators
|
||||
from django.db import models
|
||||
from django.db.models.functions import Lower
|
||||
from django.template.loader import render_to_string
|
||||
from django.utils.text import slugify
|
||||
from django.utils.translation import get_language, gettext, override
|
||||
@@ -308,12 +309,17 @@ class Mailbox(AbstractBaseUser, BaseModel):
|
||||
fields=["local_part", "domain"], name="unique_username"
|
||||
),
|
||||
models.UniqueConstraint(
|
||||
fields=["first_name", "last_name", "domain"],
|
||||
Lower("first_name"),
|
||||
Lower("last_name"),
|
||||
"domain",
|
||||
name="unique_ox_display_name",
|
||||
violation_error_message="Mailbox with this First name, \
|
||||
Last name and Domain already exists.",
|
||||
),
|
||||
# Display name in OpenXChange must be unique
|
||||
# To avoid sending failing requests to dimail,
|
||||
# we impose uniqueness here too
|
||||
# And compare to lowercase to enforce case-insensitive uniqueness
|
||||
]
|
||||
ordering = ["-created_at"]
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@ def test_api_mailboxes__create_viewer_failure(mailbox_data):
|
||||
def test_api_mailboxes__create_display_name_must_be_unique():
|
||||
"""Primary id on OpenXchange is display name (first_name + last_name).
|
||||
It needs to be unique on each context. We don't track context info for now
|
||||
but can impose uniqueness by domain."""
|
||||
but can impose case-insensitive uniqueness by domain."""
|
||||
access = factories.MailDomainAccessFactory(role=enums.MailDomainRoleChoices.OWNER)
|
||||
existing_mailbox = factories.MailboxFactory(domain=access.domain)
|
||||
|
||||
@@ -86,8 +86,8 @@ def test_api_mailboxes__create_display_name_must_be_unique():
|
||||
|
||||
new_mailbox_data = {
|
||||
"local_part": "something_else",
|
||||
"first_name": existing_mailbox.first_name,
|
||||
"last_name": existing_mailbox.last_name,
|
||||
"first_name": existing_mailbox.first_name.upper(), # ensure case-insensitivity
|
||||
"last_name": existing_mailbox.last_name.lower(),
|
||||
}
|
||||
response = client.post(
|
||||
f"/api/v1.0/mail-domains/{access.domain.slug}/mailboxes/",
|
||||
|
||||
Reference in New Issue
Block a user