Compost / backend /routers /auth.py
abc1181's picture
fix: use backend. prefix for all internal imports
e8c0a73
Raw
History Blame Contribute Delete
3.25 kB
from datetime import timedelta
from fastapi import APIRouter, Depends, HTTPException, status
from fastapi.security import OAuth2PasswordRequestForm
from sqlalchemy.orm import Session
from pydantic import BaseModel, EmailStr
from backend.database import get_db, User
from backend.auth import (
verify_password, get_password_hash, create_access_token,
create_refresh_token, decode_token, get_current_user
)
router = APIRouter()
class RegisterRequest(BaseModel):
email: EmailStr
password: str
class LoginResponse(BaseModel):
access_token: str
refresh_token: str
token_type: str = "bearer"
user: dict
class TokenRefreshRequest(BaseModel):
refresh_token: str
class UserResponse(BaseModel):
id: str
email: str
is_active: bool
created_at: str
@router.post("/register", response_model=UserResponse)
async def register(request: RegisterRequest, db: Session = Depends(get_db)):
existing = db.query(User).filter(User.email == request.email).first()
if existing:
raise HTTPException(status_code=400, detail="Email already registered")
user = User(
email=request.email,
hashed_password=get_password_hash(request.password),
is_active=True
)
db.add(user)
db.commit()
db.refresh(user)
return UserResponse(
id=user.id,
email=user.email,
is_active=user.is_active,
created_at=user.created_at.isoformat()
)
@router.post("/login", response_model=LoginResponse)
async def login(form_data: OAuth2PasswordRequestForm = Depends(), db: Session = Depends(get_db)):
user = db.query(User).filter(User.email == form_data.username).first()
if not user or not verify_password(form_data.password, user.hashed_password):
raise HTTPException(status_code=401, detail="Invalid credentials")
if not user.is_active:
raise HTTPException(status_code=403, detail="User account is disabled")
access_token = create_access_token({"sub": user.id})
refresh_token = create_refresh_token({"sub": user.id})
return LoginResponse(
access_token=access_token,
refresh_token=refresh_token,
user={"id": user.id, "email": user.email}
)
@router.post("/refresh")
async def refresh_token(request: TokenRefreshRequest, db: Session = Depends(get_db)):
payload = decode_token(request.refresh_token)
if payload.get("type") != "refresh":
raise HTTPException(status_code=401, detail="Invalid token type")
user_id = payload.get("sub")
user = db.query(User).filter(User.id == user_id).first()
if not user or not user.is_active:
raise HTTPException(status_code=401, detail="User not found")
access_token = create_access_token({"sub": user.id})
return {"access_token": access_token, "token_type": "bearer"}
@router.get("/me", response_model=UserResponse)
async def get_me(current_user: User = Depends(get_current_user)):
return UserResponse(
id=current_user.id,
email=current_user.email,
is_active=current_user.is_active,
created_at=current_user.created_at.isoformat()
)
@router.post("/logout")
async def logout():
return {"message": "Successfully logged out"}