Skip to content

Commit

Permalink
cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
pcrespov committed Dec 5, 2024
1 parent 7f78097 commit 9ce3607
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 39 deletions.
21 changes: 8 additions & 13 deletions services/web/server/src/simcore_service_webserver/users/schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,20 +119,20 @@ class ProfileUpdate(BaseModel):

@field_validator("user_name")
@classmethod
def _validate_user_name(cls, value):
def _validate_user_name(cls, value: str):
# Ensure valid characters (alphanumeric + . _ -)
if not re.match(r"^[a-zA-Z][a-zA-Z0-9_]*$", value):
msg = "Username must start with a letter and can only contain letters, numbers and '_'."
msg = f"Username '{value}' must start with a letter and can only contain letters, numbers and '_'."
raise ValueError(msg)

# Ensure no consecutive special characters
if re.search(r"[_]{2,}", value):
msg = "Username cannot contain consecutive special characters like '__'."
msg = f"Username '{value}' cannot contain consecutive special characters like '__'."
raise ValueError(msg)

# Ensure it doesn't end with a special character
if value[-1] in {".", "_", "-"}:
msg = "Username cannot end with a special character."
if {value[0], value[-1]}.intersection({"_"}):
msg = f"Username '{value}' cannot end or start with a special character."
raise ValueError(msg)

# Check reserved words (example list; extend as needed)
Expand All @@ -144,15 +144,10 @@ def _validate_user_name(cls, value):
"undefined",
"support",
"moderator",
# NOTE: add here extra via env vars
}
if value.lower() in reserved_words:
msg = f"Username '{value}' is reserved and cannot be used."
raise ValueError(msg)

# Ensure no offensive content
offensive_terms = {"badword1", "badword2"}
if any(term in value.lower() for term in offensive_terms):
msg = "Username contains prohibited or offensive content"
if any(w in value.lower() for w in reserved_words):
msg = f"Username '{value}' cannot be used."
raise ValueError(msg)

return value
Expand Down
50 changes: 24 additions & 26 deletions services/web/server/tests/unit/with_dbs/03/test_users.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,10 +100,7 @@ async def test_access_update_profile(
await assert_status(resp, expected)


@pytest.mark.parametrize(
"user_role",
[UserRole.USER],
)
@pytest.mark.parametrize("user_role", [UserRole.USER])
async def test_get_profile(
logged_user: UserInfoDict,
client: TestClient,
Expand Down Expand Up @@ -156,10 +153,7 @@ async def test_get_profile(
)


@pytest.mark.parametrize(
"user_role",
[UserRole.USER],
)
@pytest.mark.parametrize("user_role", [UserRole.USER])
async def test_update_profile(
logged_user: UserInfoDict,
client: TestClient,
Expand Down Expand Up @@ -197,10 +191,7 @@ def _copy(data: dict, exclude: set) -> dict:
assert _copy(data, exclude) == _copy(before, exclude)


@pytest.mark.parametrize(
"user_role",
[UserRole.USER],
)
@pytest.mark.parametrize("user_role", [UserRole.USER])
async def test_profile_workflow(
logged_user: UserInfoDict,
client: TestClient,
Expand All @@ -217,7 +208,7 @@ async def test_profile_workflow(
resp = await client.patch(
f"{url}",
json={
"firstName": "Odei",
"first_name": "Odei", # NOTE: still not camecase!
"userName": "odei123",
"privacy": {"hide_fullname": False},
},
Expand All @@ -241,34 +232,41 @@ async def test_profile_workflow(
assert updated_profile.privacy.hide_fullname != my_profile.privacy.hide_fullname


@pytest.mark.parametrize(
"user_role",
[UserRole.USER],
)
@pytest.mark.parametrize("user_role", [UserRole.USER])
@pytest.mark.parametrize("invalid_username", ["", "_foo", "superadmin", "foo..-123"])
async def test_update_wrong_user_name(
logged_user: UserInfoDict,
client: TestClient,
user_role: UserRole,
invalid_username: str,
):
assert client.app

# update with INVALID username
url = client.app.router["update_my_profile"].url_for()
resp = await client.patch(
f"{url}",
json={
"userName": invalid_username,
},
)
await assert_status(resp, status.HTTP_422_UNPROCESSABLE_ENTITY)

for invalid_username in ("_foo", "superadmin", "foo..-123"):
resp = await client.patch(
f"{url}",
json={
"userName": invalid_username,
},
)
await assert_status(resp, status.HTTP_422_UNPROCESSABLE_ENTITY)

@pytest.mark.parametrize("user_role", [UserRole.USER])
async def test_update_existing_user_name(
logged_user: UserInfoDict,
client: TestClient,
user_role: UserRole,
):
assert client.app

# update with SAME username (i.e. existing)
url = client.app.router["get_my_profile"].url_for()
resp = await client.get(f"{url}")
data, _ = await assert_status(resp, status.HTTP_200_OK)

assert data["userName"] == logged_user["name"]

url = client.app.router["update_my_profile"].url_for()
resp = await client.patch(
f"{url}",
Expand Down

0 comments on commit 9ce3607

Please sign in to comment.