mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-07-24 21:11:53 +00:00
feat(User): PRWLR-4988 Make users' email case insensitive (#56)
* feat(User): PRWLR-4988 make User.email case insensitive * test(User): PRWLR-4988 update unit tests * feat(User): PRWLR-4988 include email validation in serializer
This commit is contained in:
committed by
GitHub
parent
6d69a192f3
commit
a8825c385b
@@ -58,6 +58,9 @@ class CustomUserManager(BaseUserManager):
|
||||
user.save(using=self._db)
|
||||
return user
|
||||
|
||||
def get_by_natural_key(self, email):
|
||||
return self.get(email__iexact=email)
|
||||
|
||||
|
||||
def enum_to_choices(enum_class):
|
||||
"""
|
||||
|
||||
@@ -156,7 +156,12 @@ class Migration(migrations.Migration):
|
||||
blank=True, null=True, verbose_name="last login"
|
||||
),
|
||||
),
|
||||
("email", models.EmailField(max_length=254, unique=True)),
|
||||
(
|
||||
"email",
|
||||
models.EmailField(
|
||||
max_length=254, unique=True, help_text="Case insensitive"
|
||||
),
|
||||
),
|
||||
("company_name", models.CharField(max_length=150, blank=True)),
|
||||
("is_active", models.BooleanField(default=True)),
|
||||
("date_joined", models.DateTimeField(auto_now_add=True)),
|
||||
|
||||
@@ -69,7 +69,7 @@ class StateChoices(models.TextChoices):
|
||||
class User(AbstractBaseUser):
|
||||
id = models.UUIDField(primary_key=True, default=uuid4, editable=False)
|
||||
name = models.CharField(max_length=150, validators=[MinLengthValidator(3)])
|
||||
email = models.EmailField(max_length=254, unique=True)
|
||||
email = models.EmailField(max_length=254, unique=True, help_text="Case insensitive")
|
||||
company_name = models.CharField(max_length=150, blank=True)
|
||||
is_active = models.BooleanField(default=True)
|
||||
date_joined = models.DateTimeField(auto_now_add=True, editable=False)
|
||||
@@ -82,6 +82,11 @@ class User(AbstractBaseUser):
|
||||
def is_member_of_tenant(self, tenant_id):
|
||||
return self.memberships.filter(tenant_id=tenant_id).exists()
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
if self.email:
|
||||
self.email = self.email.strip().lower()
|
||||
super().save(*args, **kwargs)
|
||||
|
||||
class Meta:
|
||||
db_table = "users"
|
||||
|
||||
|
||||
@@ -38,32 +38,27 @@ class TestUserViewSet:
|
||||
valid_user_payload = {
|
||||
"name": "test",
|
||||
"password": "newpassword123",
|
||||
"email": "newuser@example.com",
|
||||
"email": "NeWuSeR@example.com",
|
||||
}
|
||||
response = client.post(
|
||||
reverse("user-list"), data=valid_user_payload, format="json"
|
||||
)
|
||||
assert response.status_code == status.HTTP_201_CREATED
|
||||
assert User.objects.filter(email=valid_user_payload["email"]).exists()
|
||||
assert User.objects.filter(email__iexact=valid_user_payload["email"]).exists()
|
||||
assert (
|
||||
response.json()["data"]["attributes"]["email"]
|
||||
== valid_user_payload["email"]
|
||||
== valid_user_payload["email"].lower()
|
||||
)
|
||||
|
||||
def test_users_invalid_create(self, client):
|
||||
invalid_user_payload = {
|
||||
"name": "test",
|
||||
"password": "thepasswordisfine123",
|
||||
"email": "invalidemail",
|
||||
}
|
||||
response = client.post(
|
||||
reverse("user-list"), data=invalid_user_payload, format="json"
|
||||
)
|
||||
assert response.status_code == status.HTTP_400_BAD_REQUEST
|
||||
assert (
|
||||
response.json()["errors"][0]["source"]["pointer"]
|
||||
== "/data/attributes/email"
|
||||
)
|
||||
def test_users_create_duplicated_email(self, client):
|
||||
# Create a user
|
||||
self.test_users_create(client)
|
||||
|
||||
# Try to create it again and expect a 400
|
||||
with pytest.raises(AssertionError) as assertion_error:
|
||||
self.test_users_create(client)
|
||||
|
||||
assert "Response status_code=400" in str(assertion_error)
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"password",
|
||||
|
||||
@@ -177,6 +177,12 @@ class UserCreateSerializer(BaseWriteSerializer):
|
||||
validate_password(value, user=user)
|
||||
return value
|
||||
|
||||
def validate_email(self, value):
|
||||
normalized_email = value.strip().lower()
|
||||
if User.objects.filter(email__iexact=normalized_email).exists():
|
||||
raise ValidationError("User with this email already exists.")
|
||||
return value
|
||||
|
||||
def create(self, validated_data):
|
||||
password = validated_data.pop("password")
|
||||
user = User(**validated_data)
|
||||
|
||||
Reference in New Issue
Block a user