Skip to content

Commit 84219cc

Browse files
committed
Use detailed fastapi.status.HTTP_xxx instead of just numbers
1 parent 80ee1b9 commit 84219cc

9 files changed

Lines changed: 118 additions & 75 deletions

File tree

backend/app/auth/dependencies.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,13 @@ def get_current_user(session: SessionDep, token: TokenDep) -> User:
3939
)
4040
user = session.get(User, token_data.sub)
4141
if not user:
42-
raise HTTPException(status_code=404, detail="User not found")
42+
raise HTTPException(
43+
status_code=status.HTTP_404_NOT_FOUND, detail="User not found"
44+
)
4345
if not user.is_active:
44-
raise HTTPException(status_code=400, detail="Inactive user")
46+
raise HTTPException(
47+
status_code=status.HTTP_400_BAD_REQUEST, detail="Inactive user"
48+
)
4549
return user
4650

4751

@@ -51,6 +55,7 @@ def get_current_user(session: SessionDep, token: TokenDep) -> User:
5155
def get_current_active_superuser(current_user: CurrentUser) -> User:
5256
if not current_user.is_superuser:
5357
raise HTTPException(
54-
status_code=403, detail="The user doesn't have enough privileges"
58+
status_code=status.HTTP_403_FORBIDDEN,
59+
detail="The user doesn't have enough privileges",
5560
)
5661
return current_user

backend/app/auth/router.py

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from datetime import timedelta
22
from typing import Annotated, Any
33

4-
from fastapi import APIRouter, Depends, HTTPException
4+
from fastapi import APIRouter, Depends, HTTPException, status
55
from fastapi.responses import HTMLResponse
66
from fastapi.security import OAuth2PasswordRequestForm
77

@@ -29,9 +29,14 @@ def login_access_token(
2929
session=session, email=form_data.username, password=form_data.password
3030
)
3131
if not user:
32-
raise HTTPException(status_code=400, detail="Incorrect email or password")
32+
raise HTTPException(
33+
status_code=status.HTTP_400_BAD_REQUEST,
34+
detail="Incorrect email or password",
35+
)
3336
elif not user.is_active:
34-
raise HTTPException(status_code=400, detail="Inactive user")
37+
raise HTTPException(
38+
status_code=status.HTTP_400_BAD_REQUEST, detail="Inactive user"
39+
)
3540
access_token_expires = timedelta(minutes=settings.ACCESS_TOKEN_EXPIRE_MINUTES)
3641
return Token(
3742
access_token=create_access_token(user.id, expires_delta=access_token_expires)
@@ -77,13 +82,19 @@ def reset_password(session: SessionDep, body: NewPassword) -> Message:
7782
"""
7883
email = auth_service.verify_password_reset_token(token=body.token)
7984
if not email:
80-
raise HTTPException(status_code=400, detail="Invalid token")
85+
raise HTTPException(
86+
status_code=status.HTTP_400_BAD_REQUEST, detail="Invalid token"
87+
)
8188
user = user_service.get_user_by_email(session=session, email=email)
8289
if not user:
8390
# Don't reveal that the user doesn't exist - use same error as invalid token
84-
raise HTTPException(status_code=400, detail="Invalid token")
91+
raise HTTPException(
92+
status_code=status.HTTP_400_BAD_REQUEST, detail="Invalid token"
93+
)
8594
elif not user.is_active:
86-
raise HTTPException(status_code=400, detail="Inactive user")
95+
raise HTTPException(
96+
status_code=status.HTTP_400_BAD_REQUEST, detail="Inactive user"
97+
)
8798
user_in_update = UserUpdate(password=body.new_password)
8899
user_service.update_user(
89100
session=session,
@@ -106,7 +117,7 @@ def recover_password_html_content(email: str, session: SessionDep) -> Any:
106117

107118
if not user:
108119
raise HTTPException(
109-
status_code=404,
120+
status_code=status.HTTP_404_NOT_FOUND,
110121
detail="The user with this username does not exist in the system.",
111122
)
112123
password_reset_token = auth_service.generate_password_reset_token(email=email)

backend/app/items/router.py

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import uuid
22
from typing import Any
33

4-
from fastapi import APIRouter, HTTPException
4+
from fastapi import APIRouter, HTTPException, status
55
from sqlmodel import col, func, select
66

77
from app.auth.dependencies import CurrentUser, SessionDep
@@ -53,9 +53,13 @@ def read_item(session: SessionDep, current_user: CurrentUser, id: uuid.UUID) ->
5353
"""
5454
item = session.get(Item, id)
5555
if not item:
56-
raise HTTPException(status_code=404, detail="Item not found")
56+
raise HTTPException(
57+
status_code=status.HTTP_404_NOT_FOUND, detail="Item not found"
58+
)
5759
if not current_user.is_superuser and (item.owner_id != current_user.id):
58-
raise HTTPException(status_code=403, detail="Not enough permissions")
60+
raise HTTPException(
61+
status_code=status.HTTP_403_FORBIDDEN, detail="Not enough permissions"
62+
)
5963
return item
6064

6165

@@ -86,9 +90,13 @@ def update_item(
8690
"""
8791
item = session.get(Item, id)
8892
if not item:
89-
raise HTTPException(status_code=404, detail="Item not found")
93+
raise HTTPException(
94+
status_code=status.HTTP_404_NOT_FOUND, detail="Item not found"
95+
)
9096
if not current_user.is_superuser and (item.owner_id != current_user.id):
91-
raise HTTPException(status_code=403, detail="Not enough permissions")
97+
raise HTTPException(
98+
status_code=status.HTTP_403_FORBIDDEN, detail="Not enough permissions"
99+
)
92100
update_dict = item_in.model_dump(exclude_unset=True)
93101
item.sqlmodel_update(update_dict)
94102
session.add(item)
@@ -106,9 +114,13 @@ def delete_item(
106114
"""
107115
item = session.get(Item, id)
108116
if not item:
109-
raise HTTPException(status_code=404, detail="Item not found")
117+
raise HTTPException(
118+
status_code=status.HTTP_404_NOT_FOUND, detail="Item not found"
119+
)
110120
if not current_user.is_superuser and (item.owner_id != current_user.id):
111-
raise HTTPException(status_code=403, detail="Not enough permissions")
121+
raise HTTPException(
122+
status_code=status.HTTP_403_FORBIDDEN, detail="Not enough permissions"
123+
)
112124
session.delete(item)
113125
session.commit()
114126
return Message(message="Item deleted successfully")

backend/app/users/router.py

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import uuid
22
from typing import Any
33

4-
from fastapi import APIRouter, Depends, HTTPException
4+
from fastapi import APIRouter, Depends, HTTPException, status
55
from sqlmodel import col, delete, func, select
66

77
from app.auth.dependencies import (
@@ -60,7 +60,7 @@ def create_user(*, session: SessionDep, user_in: UserCreate) -> Any:
6060
user = user_service.get_user_by_email(session=session, email=user_in.email)
6161
if user:
6262
raise HTTPException(
63-
status_code=400,
63+
status_code=status.HTTP_400_BAD_REQUEST,
6464
detail="The user with this email already exists in the system.",
6565
)
6666

@@ -91,7 +91,8 @@ def update_user_me(
9191
)
9292
if existing_user and existing_user.id != current_user.id:
9393
raise HTTPException(
94-
status_code=409, detail="User with this email already exists"
94+
status_code=status.HTTP_409_CONFLICT,
95+
detail="User with this email already exists",
9596
)
9697
user_data = user_in.model_dump(exclude_unset=True)
9798
current_user.sqlmodel_update(user_data)
@@ -110,10 +111,13 @@ def update_password_me(
110111
"""
111112
verified, _ = verify_password(body.current_password, current_user.hashed_password)
112113
if not verified:
113-
raise HTTPException(status_code=400, detail="Incorrect password")
114+
raise HTTPException(
115+
status_code=status.HTTP_400_BAD_REQUEST, detail="Incorrect password"
116+
)
114117
if body.current_password == body.new_password:
115118
raise HTTPException(
116-
status_code=400, detail="New password cannot be the same as the current one"
119+
status_code=status.HTTP_400_BAD_REQUEST,
120+
detail="New password cannot be the same as the current one",
117121
)
118122
hashed_password = get_password_hash(body.new_password)
119123
current_user.hashed_password = hashed_password
@@ -137,7 +141,8 @@ def delete_user_me(session: SessionDep, current_user: CurrentUser) -> Any:
137141
"""
138142
if current_user.is_superuser:
139143
raise HTTPException(
140-
status_code=403, detail="Super users are not allowed to delete themselves"
144+
status_code=status.HTTP_403_FORBIDDEN,
145+
detail="Super users are not allowed to delete themselves",
141146
)
142147
session.delete(current_user)
143148
session.commit()
@@ -152,7 +157,7 @@ def register_user(session: SessionDep, user_in: UserRegister) -> Any:
152157
user = user_service.get_user_by_email(session=session, email=user_in.email)
153158
if user:
154159
raise HTTPException(
155-
status_code=400,
160+
status_code=status.HTTP_400_BAD_REQUEST,
156161
detail="The user with this email already exists in the system",
157162
)
158163
user_create = UserCreate.model_validate(user_in)
@@ -172,11 +177,13 @@ def read_user_by_id(
172177
return user
173178
if not current_user.is_superuser:
174179
raise HTTPException(
175-
status_code=403,
180+
status_code=status.HTTP_403_FORBIDDEN,
176181
detail="The user doesn't have enough privileges",
177182
)
178183
if user is None:
179-
raise HTTPException(status_code=404, detail="User not found")
184+
raise HTTPException(
185+
status_code=status.HTTP_404_NOT_FOUND, detail="User not found"
186+
)
180187
return user
181188

182189

@@ -198,7 +205,7 @@ def update_user(
198205
db_user = session.get(User, user_id)
199206
if not db_user:
200207
raise HTTPException(
201-
status_code=404,
208+
status_code=status.HTTP_404_NOT_FOUND,
202209
detail="The user with this id does not exist in the system",
203210
)
204211
if user_in.email:
@@ -207,7 +214,8 @@ def update_user(
207214
)
208215
if existing_user and existing_user.id != user_id:
209216
raise HTTPException(
210-
status_code=409, detail="User with this email already exists"
217+
status_code=status.HTTP_409_CONFLICT,
218+
detail="User with this email already exists",
211219
)
212220

213221
db_user = user_service.update_user(
@@ -225,10 +233,13 @@ def delete_user(
225233
"""
226234
user = session.get(User, user_id)
227235
if not user:
228-
raise HTTPException(status_code=404, detail="User not found")
236+
raise HTTPException(
237+
status_code=status.HTTP_404_NOT_FOUND, detail="User not found"
238+
)
229239
if user == current_user:
230240
raise HTTPException(
231-
status_code=403, detail="Super users are not allowed to delete themselves"
241+
status_code=status.HTTP_403_FORBIDDEN,
242+
detail="Super users are not allowed to delete themselves",
232243
)
233244
statement = delete(Item).where(col(Item.owner_id) == user_id)
234245
session.exec(statement)

backend/app/utils/router.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from fastapi import APIRouter, Depends
1+
from fastapi import APIRouter, Depends, status
22
from pydantic.networks import EmailStr
33

44
from app.auth.dependencies import get_current_active_superuser
@@ -11,7 +11,7 @@
1111
@router.post(
1212
"/test-email/",
1313
dependencies=[Depends(get_current_active_superuser)],
14-
status_code=201,
14+
status_code=status.HTTP_201_CREATED,
1515
)
1616
def test_email(email_to: EmailStr) -> Message:
1717
"""

backend/tests/auth/test_router.py

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from unittest.mock import patch
22

3+
from fastapi import status
34
from fastapi.testclient import TestClient
45
from pwdlib.hashers.bcrypt import BcryptHasher
56
from sqlmodel import Session
@@ -21,7 +22,7 @@ def test_get_access_token(client: TestClient) -> None:
2122
}
2223
r = client.post(f"{settings.API_V1_STR}/login/access-token", data=login_data)
2324
tokens = r.json()
24-
assert r.status_code == 200
25+
assert r.status_code == status.HTTP_200_OK
2526
assert "access_token" in tokens
2627
assert tokens["access_token"]
2728

@@ -32,7 +33,7 @@ def test_get_access_token_incorrect_password(client: TestClient) -> None:
3233
"password": "incorrect",
3334
}
3435
r = client.post(f"{settings.API_V1_STR}/login/access-token", data=login_data)
35-
assert r.status_code == 400
36+
assert r.status_code == status.HTTP_400_BAD_REQUEST
3637

3738

3839
def test_use_access_token(
@@ -43,7 +44,7 @@ def test_use_access_token(
4344
headers=superuser_token_headers,
4445
)
4546
result = r.json()
46-
assert r.status_code == 200
47+
assert r.status_code == status.HTTP_200_OK
4748
assert "email" in result
4849

4950

@@ -59,7 +60,7 @@ def test_recovery_password(
5960
f"{settings.API_V1_STR}/password-recovery/{email}",
6061
headers=normal_user_token_headers,
6162
)
62-
assert r.status_code == 200
63+
assert r.status_code == status.HTTP_200_OK
6364
assert r.json() == {
6465
"message": "If that email is registered, we sent a password recovery link"
6566
}
@@ -74,7 +75,7 @@ def test_recovery_password_user_not_exits(
7475
headers=normal_user_token_headers,
7576
)
7677
# Should return 200 with generic message to prevent email enumeration attacks
77-
assert r.status_code == 200
78+
assert r.status_code == status.HTTP_200_OK
7879
assert r.json() == {
7980
"message": "If that email is registered, we sent a password recovery link"
8081
}
@@ -103,7 +104,7 @@ def test_reset_password(client: TestClient, db: Session) -> None:
103104
json=data,
104105
)
105106

106-
assert r.status_code == 200
107+
assert r.status_code == status.HTTP_200_OK
107108
assert r.json() == {"message": "Password updated successfully"}
108109

109110
db.refresh(user)
@@ -123,7 +124,7 @@ def test_reset_password_invalid_token(
123124
response = r.json()
124125

125126
assert "detail" in response
126-
assert r.status_code == 400
127+
assert r.status_code == status.HTTP_400_BAD_REQUEST
127128
assert response["detail"] == "Invalid token"
128129

129130

@@ -148,7 +149,7 @@ def test_login_with_bcrypt_password_upgrades_to_argon2(
148149

149150
login_data = {"username": email, "password": password}
150151
r = client.post(f"{settings.API_V1_STR}/login/access-token", data=login_data)
151-
assert r.status_code == 200
152+
assert r.status_code == status.HTTP_200_OK
152153
tokens = r.json()
153154
assert "access_token" in tokens
154155

@@ -182,7 +183,7 @@ def test_login_with_argon2_password_keeps_hash(client: TestClient, db: Session)
182183

183184
login_data = {"username": email, "password": password}
184185
r = client.post(f"{settings.API_V1_STR}/login/access-token", data=login_data)
185-
assert r.status_code == 200
186+
assert r.status_code == status.HTTP_200_OK
186187
tokens = r.json()
187188
assert "access_token" in tokens
188189

0 commit comments

Comments
 (0)