92 lines
3.4 KiB
Python
92 lines
3.4 KiB
Python
import os
|
|
import httpx
|
|
from fastapi import APIRouter, Depends, HTTPException, status
|
|
# Import the new dependency
|
|
from fastapi.security import OAuth2PasswordRequestForm
|
|
from firebase_admin import auth
|
|
from ..firebase_config import get_db
|
|
# The LoginPasswordRequest model is no longer needed for this endpoint
|
|
from ..models import UserCreate, UserRecord, LoginResponse
|
|
|
|
router = APIRouter()
|
|
FIREBASE_WEB_API_KEY = os.environ.get("FIREBASE_WEB_API_KEY")
|
|
FIREBASE_SIGN_IN_URL = f"https://identitytoolkit.googleapis.com/v1/accounts:signInWithPassword?key={FIREBASE_WEB_API_KEY}"
|
|
|
|
|
|
@router.post("/register", response_model=UserRecord, status_code=status.HTTP_201_CREATED)
|
|
async def register_user(user: UserCreate):
|
|
"""
|
|
Registers a user in Firebase Auth and creates a corresponding user document in Firestore.
|
|
"""
|
|
# ... (this function remains the same)
|
|
try:
|
|
user_record = auth.create_user(
|
|
email=user.email,
|
|
password=user.password,
|
|
display_name=user.full_name
|
|
)
|
|
|
|
db = get_db()
|
|
user_data = {
|
|
"uid": user_record.uid,
|
|
"email": user.email,
|
|
"full_name": user.full_name,
|
|
"role": "member"
|
|
}
|
|
db.collection('users').document(user_record.uid).set(user_data)
|
|
|
|
return user_data
|
|
|
|
except auth.EmailAlreadyExistsError:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_400_BAD_REQUEST,
|
|
detail="Email already registered",
|
|
)
|
|
|
|
# The signature of this function is updated
|
|
@router.post("/login", response_model=LoginResponse)
|
|
async def login_with_password(form_data: OAuth2PasswordRequestForm = Depends()):
|
|
"""
|
|
Authenticates a user with email/password via Firebase REST API,
|
|
checks their role in Firestore, and returns their UID and ID token.
|
|
"""
|
|
payload = {
|
|
# Use form_data.username as the email
|
|
"email": form_data.username,
|
|
"password": form_data.password,
|
|
"returnSecureToken": True
|
|
}
|
|
|
|
async with httpx.AsyncClient() as client:
|
|
try:
|
|
response = await client.post(FIREBASE_SIGN_IN_URL, json=payload)
|
|
response.raise_for_status()
|
|
|
|
auth_data = response.json()
|
|
uid = auth_data['localId']
|
|
|
|
# Check user role in Firestore to ensure account is active
|
|
db = get_db()
|
|
user_doc = db.collection('users').document(uid).get()
|
|
|
|
if not user_doc.exists:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_403_FORBIDDEN,
|
|
detail="User authenticated but not found in database.",
|
|
)
|
|
|
|
user = user_doc.to_dict()
|
|
if user.get("role") == "member":
|
|
raise HTTPException(
|
|
status_code=status.HTTP_403_FORBIDDEN,
|
|
detail="Account is not activated. Please contact an administrator."
|
|
)
|
|
|
|
return LoginResponse(uid=uid, id_token=auth_data['idToken'])
|
|
|
|
except httpx.HTTPStatusError as e:
|
|
error_detail = e.response.json().get("error", {}).get("message", "Authentication failed.")
|
|
raise HTTPException(
|
|
status_code=status.HTTP_401_UNAUTHORIZED,
|
|
detail=error_detail
|
|
) |