feat(auth): enhance user authentication with detailed error handling
This commit is contained in:
parent
ebbbf62df5
commit
b53746dd1f
@ -191,14 +191,36 @@ async def login_for_access_token(form_data: UserLogin, db: Session = Depends(get
|
||||
Raises:
|
||||
HTTPException: If credentials are invalid
|
||||
"""
|
||||
user = authenticate_user(db, form_data.email, form_data.password)
|
||||
user, reason = authenticate_user(db, form_data.email, form_data.password)
|
||||
if not user:
|
||||
logger.warning(f"Login attempt with invalid credentials: {form_data.email}")
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_401_UNAUTHORIZED,
|
||||
detail="Invalid email or password",
|
||||
headers={"WWW-Authenticate": "Bearer"},
|
||||
)
|
||||
if reason == "user_not_found" or reason == "invalid_password":
|
||||
logger.warning(f"Login attempt with invalid credentials: {form_data.email}")
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_401_UNAUTHORIZED,
|
||||
detail="Invalid email or password",
|
||||
headers={"WWW-Authenticate": "Bearer"},
|
||||
)
|
||||
elif reason == "email_not_verified":
|
||||
logger.warning(f"Login attempt with unverified email: {form_data.email}")
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_403_FORBIDDEN,
|
||||
detail="Email not verified",
|
||||
)
|
||||
elif reason == "inactive_user":
|
||||
logger.warning(f"Login attempt with inactive user: {form_data.email}")
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_403_FORBIDDEN,
|
||||
detail="User account is inactive",
|
||||
)
|
||||
else:
|
||||
logger.warning(
|
||||
f"Login attempt failed for {form_data.email} (reason: {reason})"
|
||||
)
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_401_UNAUTHORIZED,
|
||||
detail="Invalid email or password",
|
||||
headers={"WWW-Authenticate": "Bearer"},
|
||||
)
|
||||
|
||||
access_token = create_access_token(user)
|
||||
logger.info(f"Login successful for user: {user.email}")
|
||||
|
@ -374,7 +374,9 @@ def get_user_by_email(db: Session, email: str) -> Optional[User]:
|
||||
return None
|
||||
|
||||
|
||||
def authenticate_user(db: Session, email: str, password: str) -> Optional[User]:
|
||||
def authenticate_user(
|
||||
db: Session, email: str, password: str
|
||||
) -> Tuple[Optional[User], str]:
|
||||
"""
|
||||
Authenticates a user with email and password
|
||||
|
||||
@ -384,16 +386,18 @@ def authenticate_user(db: Session, email: str, password: str) -> Optional[User]:
|
||||
password: User password
|
||||
|
||||
Returns:
|
||||
Optional[User]: Authenticated user or None
|
||||
Tuple[Optional[User], str]: Authenticated user and reason (or None and reason)
|
||||
"""
|
||||
user = get_user_by_email(db, email)
|
||||
if not user:
|
||||
return None
|
||||
return None, "user_not_found"
|
||||
if not verify_password(password, user.password_hash):
|
||||
return None
|
||||
return None, "invalid_password"
|
||||
if not user.email_verified:
|
||||
return None, "email_not_verified"
|
||||
if not user.is_active:
|
||||
return None
|
||||
return user
|
||||
return None, "inactive_user"
|
||||
return user, "success"
|
||||
|
||||
|
||||
def get_admin_users(db: Session, skip: int = 0, limit: int = 100):
|
||||
|
Loading…
Reference in New Issue
Block a user