Skip to content

Commit d49a741

Browse files
committed
fix update_user route
1 parent 0866c1c commit d49a741

File tree

2 files changed

+61
-5
lines changed

2 files changed

+61
-5
lines changed

backend/app/routers/users.py

+9-4
Original file line numberDiff line numberDiff line change
@@ -118,13 +118,18 @@ async def update_user(
118118
user = await models.User.find_one({"uuid": userid})
119119
if user is None:
120120
raise HTTPException(status_code=404, detail="User not found")
121-
if update.password is not None:
122-
update.password = get_hashed_password(update.password)
123-
updated_user = user.model_copy(update=update.model_dump(exclude_unset=True))
121+
update_data = update.model_dump(exclude_unset=True)
122+
try:
123+
if update_data["password"]:
124+
update_data["hashed_password"] = get_hashed_password(update_data["password"])
125+
del update_data["password"]
126+
except KeyError:
127+
pass
128+
updated_user = user.model_copy(update=update_data)
124129
try:
125130
await updated_user.save()
126131
return updated_user
127-
except errors.DuplicateKeyError:
132+
except (errors.DuplicateKeyError, RevisionIdWasChanged):
128133
raise HTTPException(
129134
status_code=400, detail="User with that email already exists."
130135
)

backend/tests/routers/test_users.py

+52-1
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ async def test_create_user_existing_username(client: AsyncClient) -> None:
6767

6868
@pytest.mark.anyio
6969
async def test_get_existing_user(
70-
client: AsyncClient, superuser_token_headers: dict
70+
client: AsyncClient, superuser_token_headers: dict[str, str]
7171
) -> None:
7272
user = await create_test_user()
7373
r = await client.get(
@@ -83,6 +83,7 @@ async def test_get_existing_user(
8383
async def test_update_profile(client: AsyncClient) -> None:
8484
# create user
8585
user = await create_test_user()
86+
user_hashed_password = user.hashed_password
8687
token_headers = await generate_user_auth_headers(client, user)
8788

8889
# update user email and pw
@@ -95,6 +96,7 @@ async def test_update_profile(client: AsyncClient) -> None:
9596
updated_user = await User.get(user.id)
9697
assert updated_user is not None
9798
assert updated_user.email == data["email"]
99+
assert updated_user.hashed_password != user_hashed_password
98100

99101

100102
@pytest.mark.anyio
@@ -130,3 +132,52 @@ async def test_update_profile_cannot_set_superuser(client: AsyncClient) -> None:
130132
assert updated_user is not None
131133
assert updated_user.is_superuser is False
132134
assert updated_user.is_active is True
135+
136+
137+
@pytest.mark.anyio
138+
async def test_update_user(
139+
client: AsyncClient, superuser_token_headers: dict[str, str]
140+
) -> None:
141+
# create user
142+
user = await create_test_user()
143+
user_hashed_password = user.hashed_password
144+
145+
# update user email and pw
146+
data = {
147+
"email": random_email(),
148+
"password": random_lower_string(),
149+
"is_superuser": True,
150+
"is_active": False,
151+
}
152+
r = await client.patch(
153+
f"{settings.API_V1_STR}/users/{user.uuid}",
154+
json=data,
155+
headers=superuser_token_headers,
156+
)
157+
assert r.status_code == 200
158+
159+
updated_user = await User.get(user.id)
160+
assert updated_user is not None
161+
assert updated_user.email == data["email"]
162+
assert updated_user.hashed_password != user_hashed_password
163+
assert updated_user.is_superuser is True
164+
assert updated_user.is_active is False
165+
166+
167+
@pytest.mark.anyio
168+
async def test_update_user_existing_email(
169+
client: AsyncClient, superuser_token_headers: dict[str, str]
170+
) -> None:
171+
# create user
172+
user = await create_test_user()
173+
174+
# update user email to already existing email
175+
data = {"email": settings.FIRST_SUPERUSER}
176+
r = await client.patch(
177+
f"{settings.API_V1_STR}/users/{user.uuid}",
178+
json=data,
179+
headers=superuser_token_headers,
180+
)
181+
response = r.json()
182+
assert r.status_code == 400
183+
assert response["detail"] == "User with that email already exists."

0 commit comments

Comments
 (0)