Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions changelog/7953-username-validation.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
type: Fixed
description: Added character and length validation to usernames on user creation
pr: 7953
labels: []
11 changes: 8 additions & 3 deletions src/fides/api/schemas/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
from fides.api.models.fides_user import FidesUser
from fides.api.models.fides_user_invite import FidesUserInvite

USERNAME_PATTERN = r"[a-zA-Z0-9._-]{1,100}"
Comment thread
erosselli marked this conversation as resolved.


class PrivacyRequestUser(FidesSchema):
"""Data we can expose via PrivacyRequest user relations (reviewer, submitter, etc.)"""
Expand All @@ -38,9 +40,12 @@ class UserCreate(FidesSchema):
@field_validator("username")
@classmethod
def validate_username(cls, username: str) -> str:
"""Ensure username does not have spaces."""
if " " in username:
raise ValueError("Usernames cannot have spaces.")
"""Ensure username contains only valid characters and is within length limits."""
if not re.fullmatch(USERNAME_PATTERN, username):
Comment thread
erosselli marked this conversation as resolved.
raise ValueError(
"Usernames must be 1-100 characters and may only contain "
"letters, numbers, periods, underscores, and hyphens."
)
return username

@field_validator("password")
Expand Down
41 changes: 38 additions & 3 deletions tests/lib/test_oauth_schemas_user.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,17 +30,52 @@ def test_bad_password(password, message):
assert message in str(excinfo.value)


def test_user_create_user_name_with_spaces():
with pytest.raises(ValueError):
@pytest.mark.parametrize(
"username",
[
"some user",
"user&name",
"user=name",
"user<name",
"user@name",
"",
"a" * 101,
],
)
def test_user_create_invalid_username(username):
with pytest.raises(ValueError, match="Usernames must be"):
UserCreate(
username="some user",
username=username,
password=str_to_b64_str("Testtest1!"),
email_address="test.user@ethyca.com",
first_name="test",
last_name="test",
)


@pytest.mark.parametrize(
"username",
[
"testuser",
"test-user",
"test_user",
"Test_User-123",
"john.doe",
"a",
"a" * 100,
],
)
def test_user_create_valid_username(username):
user = UserCreate(
username=username,
password=str_to_b64_str("Testtest1!"),
email_address="test.user@ethyca.com",
first_name="test",
last_name="test",
)
assert user.username == username


def test_user_create_invalid_email():
with pytest.raises(ValidationError):
UserCreate(
Expand Down
Loading