53 lines
1.9 KiB
Python
53 lines
1.9 KiB
Python
from fastapi import APIRouter, HTTPException, Request
|
|
|
|
from lib.db import get_connection
|
|
from models.user import User, UserLogin
|
|
from lib.helpers import verify_password
|
|
from lib.logger import logger
|
|
|
|
router = APIRouter(prefix="/auth", tags=["auth"])
|
|
|
|
|
|
@router.post("/token", response_model=User)
|
|
async def login(user_login: UserLogin, request: Request):
|
|
logger.debug(
|
|
f"Login attempt for user: {user_login.username} from IP: {request.client.host}"
|
|
)
|
|
with get_connection() as conn:
|
|
user_df = conn.execute(
|
|
'SELECT * FROM "User" WHERE username = ?', (user_login.username,)
|
|
).fetchdf()
|
|
|
|
if user_df.empty:
|
|
logger.warning(
|
|
f"Failed login: Username {user_login.username} not found - IP: {request.client.host}"
|
|
)
|
|
raise HTTPException(status_code=401, detail="Invalid username or password")
|
|
|
|
user_data = user_df.to_dict(orient="records")[0]
|
|
if not verify_password(user_login.password, user_data["hashed_password"]):
|
|
logger.warning(
|
|
f"Failed login: Incorrect password for user {user_login.username} - IP: {request.client.host}"
|
|
)
|
|
raise HTTPException(status_code=401, detail="Invalid username or password")
|
|
|
|
# Update the login timestamp in the database
|
|
with get_connection() as conn:
|
|
conn.execute(
|
|
'UPDATE "User" SET last_login = CURRENT_TIMESTAMP WHERE id = ?',
|
|
(user_data["id"],),
|
|
)
|
|
|
|
# Fetch the updated user data with the new last_login timestamp
|
|
updated_user = (
|
|
conn.execute('SELECT * FROM "User" WHERE id = ?', (user_data["id"],))
|
|
.fetchdf()
|
|
.to_dict(orient="records")[0]
|
|
)
|
|
|
|
logger.info(
|
|
f"Successful login: User {user_login.username} (ID: {user_data['id']}) logged in from {request.client.host}"
|
|
)
|
|
|
|
return User(**updated_user)
|