🐛(admin) fix organization validators

When updating an Organization in the Django admin, the validator
falsly raises a "duplicated" error because it does not exclude the
current object from the database lookup.
This commit is contained in:
Quentin BEY
2024-11-15 14:02:33 +01:00
committed by BEY Quentin
parent a991737a59
commit b524369add
2 changed files with 39 additions and 24 deletions

View File

@@ -22,8 +22,8 @@ class Migration(migrations.Migration):
('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')),
('name', models.CharField(max_length=100, verbose_name='name')),
('registration_id_list', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=128), blank=True, default=list, size=None, validators=[core.models.validate_unique_registration_id], verbose_name='registration ID list')),
('domain_list', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=256), blank=True, default=list, size=None, validators=[core.models.validate_unique_domain], verbose_name='domain list')),
('registration_id_list', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=128), blank=True, default=list, size=None, verbose_name='registration ID list')),
('domain_list', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=256), blank=True, default=list, size=None, verbose_name='domain list')),
],
options={
'verbose_name': 'organization',

View File

@@ -251,24 +251,6 @@ class OrganizationManager(models.Manager):
raise ValueError("Should never reach this point.")
def validate_unique_registration_id(value):
"""
Validate that the registration ID values in an array field are unique across all instances.
"""
if Organization.objects.filter(registration_id_list__overlap=value).exists():
raise ValidationError(
"registration_id_list value must be unique across all instances."
)
def validate_unique_domain(value):
"""
Validate that the domain values in an array field are unique across all instances.
"""
if Organization.objects.filter(domain_list__overlap=value).exists():
raise ValidationError("domain_list value must be unique across all instances.")
class Organization(BaseModel):
"""
Organization model used to regroup Teams.
@@ -298,16 +280,14 @@ class Organization(BaseModel):
verbose_name=_("registration ID list"),
default=list,
blank=True,
validators=[
validate_unique_registration_id,
],
# list overlap validation is done in the validate_unique method
)
domain_list = ArrayField(
models.CharField(max_length=256),
verbose_name=_("domain list"),
default=list,
blank=True,
validators=[validate_unique_domain],
# list overlap validation is done in the validate_unique method
)
service_providers = models.ManyToManyField(
@@ -340,6 +320,41 @@ class Organization(BaseModel):
def __str__(self):
return f"{self.name} (# {self.pk})"
def validate_unique(self, exclude=None):
"""
Validate Registration/Domain values in an array field are unique
across all instances.
This can't be done in the field validator because we need to
exclude the current object if already in database.
"""
super().validate_unique(exclude=exclude)
if self.pk:
organization_qs = Organization.objects.exclude(pk=self.pk)
else:
organization_qs = Organization.objects.all()
# Check a registration ID can only be present in one organization
if (
self.registration_id_list
and organization_qs.filter(
registration_id_list__overlap=self.registration_id_list
).exists()
):
raise ValidationError(
"registration_id_list value must be unique across all instances."
)
# Check a domain can only be present in one organization
if (
self.domain_list
and organization_qs.filter(domain_list__overlap=self.domain_list).exists()
):
raise ValidationError(
"domain_list value must be unique across all instances."
)
class User(AbstractBaseUser, BaseModel, auth_models.PermissionsMixin):
"""User model to work with OIDC only authentication."""