fix:login

This commit is contained in:
muhamad fais aizat 2025-05-16 17:24:07 +07:00
parent 33ebfa8318
commit c88f5c6660
1 changed files with 45 additions and 25 deletions

View File

@ -2,13 +2,13 @@ import os
import bcrypt import bcrypt
import jwt import jwt
from datetime import datetime, timedelta from datetime import datetime, timedelta
from fastapi import APIRouter, HTTPException, Query from fastapi import APIRouter, HTTPException, Query, status
from pydantic import BaseModel from pydantic import BaseModel
from config.db import conn from config.db import conn
from models.index import users from models.index import users
from dotenv import load_dotenv from dotenv import load_dotenv
from sqlalchemy.sql import select from sqlalchemy.sql import select
from sqlalchemy.exc import SQLAlchemyError from sqlalchemy.exc import SQLAlchemyError, OperationalError
# Load environment variables # Load environment variables
load_dotenv() load_dotenv()
@ -31,34 +31,54 @@ class LoginRequest(BaseModel):
@auth_router.post("/login") @auth_router.post("/login")
async def login(data: LoginRequest): async def login(data: LoginRequest):
# Cek apakah user dengan email ini ada di database try:
user = conn.execute(users.select().where(users.c.email == data.email)).fetchone() # Eksekusi query untuk cek user
if not user: query = users.select().where(users.c.email == data.email)
raise HTTPException(status_code=400, detail="Invalid email or password") user = conn.execute(query).fetchone()
# Verifikasi password # Validasi user
if not bcrypt.checkpw(data.password.encode("utf-8"), user.password.encode("utf-8")): if not user:
raise HTTPException(status_code=400, detail="Invalid email or password") raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="Invalid email or password")
# Buat token JWT # Verifikasi password
payload = { if not bcrypt.checkpw(data.password.encode("utf-8"), user.password.encode("utf-8")):
"sub": user.email, raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="Invalid email or password")
"role": user.role,
"exp": datetime.utcnow() + timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
}
token = jwt.encode(payload, SECRET_KEY, algorithm=ALGORITHM)
# Kembalikan token beserta data user # Buat token JWT
return { payload = {
"access_token": token, "sub": user.email,
"token_type": "bearer",
"expires_in": ACCESS_TOKEN_EXPIRE_MINUTES * 60,
"user": {
"id": user.id,
"email": user.email,
"role": user.role, "role": user.role,
"exp": datetime.utcnow() + timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
} }
} token = jwt.encode(payload, SECRET_KEY, algorithm=ALGORITHM)
return {
"access_token": token,
"token_type": "bearer",
"expires_in": ACCESS_TOKEN_EXPIRE_MINUTES * 60,
"user": {
"id": user.id,
"email": user.email,
"role": user.role,
}
}
except OperationalError:
# Jika koneksi DB putus, coba reconnect
try:
conn.close() # tutup koneksi lama (jika masih terbuka)
from config.db import engine # impor ulang engine
conn.connect() # buka koneksi baru
raise HTTPException(status_code=500, detail="Koneksi database sempat terputus, silakan coba lagi.")
except Exception as reconnect_error:
raise HTTPException(status_code=500, detail=f"Gagal reconnect ke database: {str(reconnect_error)}")
except SQLAlchemyError as e:
conn.rollback() # rollback jika error transaksi
raise HTTPException(status_code=500, detail=f"Database error: {str(e)}")
except Exception as e:
raise HTTPException(status_code=500, detail=f"Unexpected error: {str(e)}")
class ForgotPasswordRequest(BaseModel): class ForgotPasswordRequest(BaseModel):
email: str email: str