diff --git a/netbox/users/forms/model_forms.py b/netbox/users/forms/model_forms.py index 1cc94b94417..74a44051ffa 100644 --- a/netbox/users/forms/model_forms.py +++ b/netbox/users/forms/model_forms.py @@ -229,25 +229,6 @@ def clean(self): if self.cleaned_data['password'] and self.cleaned_data['password'] != self.cleaned_data['confirm_password']: raise forms.ValidationError(_("Passwords do not match! Please check your input and try again.")) - # TODO: Move this logic to the NetBoxUser class - def clean_username(self): - """Reject usernames that differ only in case.""" - instance = getattr(self, 'instance', None) - if instance: - qs = self._meta.model.objects.exclude(pk=instance.pk) - else: - qs = self._meta.model.objects.all() - - username = self.cleaned_data.get("username") - if ( - username and qs.filter(username__iexact=username).exists() - ): - raise forms.ValidationError( - _("user with this username already exists") - ) - - return username - class GroupForm(BootstrapMixin, forms.ModelForm): users = DynamicModelMultipleChoiceField( diff --git a/netbox/users/models.py b/netbox/users/models.py index 2b408a8af72..9c4024f1cbc 100644 --- a/netbox/users/models.py +++ b/netbox/users/models.py @@ -5,6 +5,7 @@ from django.contrib.auth.models import Group, GroupManager, User, UserManager from django.contrib.contenttypes.models import ContentType from django.contrib.postgres.fields import ArrayField +from django.core.exceptions import ValidationError from django.core.validators import MinLengthValidator from django.db import models from django.db.models.signals import post_save @@ -55,6 +56,14 @@ class Meta: def get_absolute_url(self): return reverse('users:netboxuser', args=[self.pk]) + def clean(self): + super().clean() + + # Check for any existing Users with names that differ only in case + model = self._meta.model + if model.objects.exclude(pk=self.pk).filter(username__iexact=self.username).exists(): + raise ValidationError(_("A user with this username already exists.")) + class NetBoxGroup(Group): """