from fastapi import APIRouter, HTTPException, Depends from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.future import select from passlib.context import CryptContext from jose import jwt from pydantic.v1 import BaseModel, EmailStr from app.database import get_db # Updated: use the correct async session dependency from app.models import User import os import logging from dotenv import load_dotenv router = APIRouter() logger = logging.getLogger(__name__) load_dotenv() # Load secret key and JWT algorithm SECRET_KEY = os.getenv("SECRET_KEY", "secret") ALGORITHM = "HS256" # Password hashing config pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") # Request Schemas class SignUp(BaseModel): email: EmailStr password: str class Login(BaseModel): email: EmailStr password: str @router.post("/auth/signup") async def signup(data: SignUp, db: AsyncSession = Depends(get_db)): # Check if user already exists result = await db.execute(select(User).where(User.email == data.email)) existing_user = result.scalar_one_or_none() if existing_user: raise HTTPException(status_code=400, detail="Email already exists") hashed_password = pwd_context.hash(data.password) new_user = User(email=data.email, hashed_password=hashed_password) try: db.add(new_user) await db.commit() await db.refresh(new_user) return {"message": "User created", "user_id": new_user.id} except Exception as e: await db.rollback() logger.error(f"Signup error: {e}") raise HTTPException(status_code=500, detail="Internal Server Error") @router.post("/auth/login") async def login(data: Login, db: AsyncSession = Depends(get_db)): result = await db.execute(select(User).where(User.email == data.email)) user = result.scalar_one_or_none() if not user or not pwd_context.verify(data.password, user.hashed_password): raise HTTPException(status_code=401, detail="Invalid credentials") token = jwt.encode({"user_id": user.id}, SECRET_KEY, algorithm=ALGORITHM) return { "access_token": token, "token_type": "bearer", "user": {"id": user.id, "email": user.email}, }