8000 feat: Inject http error detail into user authentication dependency in… · fastapi-users/fastapi-users@0021b23 · GitHub
[go: up one dir, main page]

Skip to content

Commit 0021b23

Browse files
committed
feat: Inject http error detail into user authentication dependency injector for every case
1 parent 6ac64ad commit 0021b23

File tree

3 files changed

+46
-10
lines changed

3 files changed

+46
-10
lines changed

fastapi_users/authentication/authenticator.py

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import re
22
from inspect import Parameter, Signature
3-
from typing import Callable, List, Optional, Sequence, Tuple, cast
3+
from typing import Callable, List, Optional, Sequence, Tuple, cast, ClassVar
44

55
from fastapi import Depends, HTTPException, status
66
from makefun import with_signature
@@ -48,14 +48,29 @@ class Authenticator:
4848

4949
backends: Sequence[AuthenticationBackend]
5050

51+
default_no_user: ClassVar[str] = "Unauthorized: No authenticated user"
52+
default_detail_inactive_user: ClassVar[str] = "Unauthorized: User is inactive"
53+
default_detail_unverified_user: ClassVar[str] = "Forbidden: User is unverified"
54+
5155
def __init__(
5256
self,
5357
backends: Sequence[AuthenticationBackend],
5458
get_user_manager: UserManagerDependency[models.UP, models.ID],
59+
http_error_no_user: Optional[str] = None,
60+
http_error_detail_inactive_user: Optional[str] = None,
61+
http_error_detail_unverified_user: Optional[str] = None,
5562
):
5663
self.backends = backends
5764
self.get_user_manager = get_user_manager
5865

66+
self.http_error_no_user = http_error_no_user or self.default_no_user
67+
self.http_error_detail_inactive_user = (
68+
http_error_detail_inactive_user or self.default_detail_inactive_user
69+
)
70+
self.http_error_detail_unverified_user = (
71+
http_error_detail_unverified_user or self.default_detail_unverified_user
72+
)
73+
5974
def current_user_token(
6075
self,
6176
optional: bool = False,
@@ -171,18 +186,30 @@ async def _authenticate(
171186
if user:
172187
break
173188

174-
status_code = status.HTTP_401_UNAUTHORIZED
175189
if user:
176-
status_code = status.HTTP_403_FORBIDDEN
177190
if active and not user.is_active:
178-
status_code = status.HTTP_401_UNAUTHORIZED
191+
if not optional:
192+
raise HTTPException(
193+
status_code=status.HTTP_401_UNAUTHORIZED,
194+
detail=self.http_error_detail_inactive_user,
195+
)
179196
user = None
197+
180198
elif (
181199
verified and not user.is_verified or superuser and not user.is_superuser
182200
):
201+
if not optional:
202+
raise HTTPException(
203+
status_code=status.HTTP_403_FORBIDDEN,
204+
detail=self.http_error_detail_unverified_user,
205+
)
183206
user = None
184-
if not user and not optional:
185-
raise HTTPException(status_code=status_code)
207+
208+
elif not optional:
209+
raise HTTPException(
210+
status_code=status.HTTP_401_UNAUTHORIZED, detail=self.http_error_no_user
211+
)
212+
186213
return user, token
187214

188215
def _get_dependency_signature(

fastapi_users/fastapi_users.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,17 @@ def __init__(
4141
self,
4242
get_user_manager: UserManagerDependency[models.UP, models.ID],
4343
auth_backends: Sequence[AuthenticationBackend],
44+
http_error_no_user: Optional[str] = None,
45+
http_error_detail_inactive_user: Optional[str] = None,
46+
http_error_detail_unverified_user: Optional[str] = None,
4447
):
45-
self.authenticator = Authenticator(auth_backends, get_user_manager)
48+
self.authenticator = Authenticator(
49+
auth_backends,
50+
get_user_manager,
51+
http_error_no_user,
52+
http_error_detail_inactive_user,
53+
http_error_detail_unverified_user,
54+
)
4655
self.get_user_manager = get_user_manager
4756
self.current_user = self.authenticator.current_user
4857

tests/test_router_oauth.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -173,9 +173,9 @@ async def test_already_exists_error(
173173
async_method_mocker(
174174
oauth_client, "get_id_email", return_value=("user_oauth1", user_oauth.email)
175175
)
176-
async_method_mocker(
177-
user_manager_oauth, "oauth_callback"
178-
).side_effect = exceptions.UserAlreadyExists
176+
async_method_mocker(user_manager_oauth, "oauth_callback").side_effect = (
177+
exceptions.UserAlreadyExists
178+
)
179179

180180
response = await test_app_client.get(
181181
"/oauth/callback",

0 commit comments

Comments
 (0)
0