Files
hackathon-acapulquitos-boys…/server/app/api/routes/auth_router.py

77 lines
2.4 KiB
Python

from datetime import datetime, timedelta
from fastapi import APIRouter, HTTPException, Depends, status
from pydantic import BaseModel, EmailStr
import jwt
from passlib.context import CryptContext
from app.core.config import settings
from app.db.database import get_connection
router = APIRouter()
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
class UserRegister(BaseModel):
email: EmailStr
phone: str | None = None
password: str
class UserLogin(BaseModel):
email: EmailStr
password: str
class TokenResponse(BaseModel):
access_token: str
token_type: str = "bearer"
def hash_password(password: str) -> str:
return pwd_context.hash(password)
def verify_password(plain: str, hashed: str) -> bool:
return pwd_context.verify(plain, hashed)
def create_token(user_id: int) -> str:
expire = datetime.utcnow() + timedelta(minutes=settings.access_token_expire_minutes)
payload = {"sub": str(user_id), "exp": expire}
return jwt.encode(payload, settings.secret_key, algorithm=settings.algorithm)
@router.post("/register", response_model=TokenResponse)
async def register(user: UserRegister):
conn = get_connection()
existing = conn.execute(
"SELECT id FROM users WHERE email = ?", (user.email,)
).fetchone()
if existing:
raise HTTPException(status_code=400, detail="Email already registered")
password_hash = hash_password(user.password)
cursor = conn.execute(
"INSERT INTO users (email, phone, password_hash) VALUES (?, ?, ?) RETURNING id",
(user.email, user.phone, password_hash)
)
user_id = cursor.fetchone()[0]
# Create default preferences
conn.execute(
"INSERT INTO notification_preferences (user_id) VALUES (?)",
(user_id,)
)
conn.commit()
conn.close()
token = create_token(user_id)
return TokenResponse(access_token=token)
@router.post("/login", response_model=TokenResponse)
async def login(user: UserLogin):
conn = get_connection()
db_user = conn.execute(
"SELECT id, password_hash FROM users WHERE email = ?",
(user.email,)
).fetchone()
conn.close()
if not db_user or not verify_password(user.password, db_user[1]):
raise HTTPException(status_code=401, detail="Invalid credentials")
token = create_token(db_user[0])
return TokenResponse(access_token=token)