update db str

This commit is contained in:
2026-03-05 12:43:44 +05:30
parent eabf295f2e
commit 6e184dc590
27 changed files with 2780 additions and 146 deletions

View File

@@ -1,10 +1,11 @@
"""User management routes"""
from fastapi import APIRouter, HTTPException, Header
from pymongo.errors import DuplicateKeyError
from fastapi import APIRouter, HTTPException
from pymongo.errors import DuplicateKeyError, WriteError
from db import get_database
from models import UserCreate, UserUpdate, User
from datetime import datetime
from typing import Optional, List
from typing import Optional
from bson import ObjectId
router = APIRouter()
@@ -12,56 +13,107 @@ router = APIRouter()
@router.post("/register", response_model=dict)
async def register_user(user_data: UserCreate):
"""
Register a new user (called after Firebase Google Auth)
Stores user profile in MongoDB
Register or get user (idempotent).
Uses upsert pattern to ensure one user per email.
If user already exists, returns existing user.
Called after Firebase Google Auth on frontend.
"""
db = get_database()
try:
user_doc = {
"email": user_data.email,
"displayName": user_data.displayName or user_data.email.split("@")[0],
"photoURL": user_data.photoURL,
"createdAt": datetime.utcnow(),
"updatedAt": datetime.utcnow(),
"theme": "light"
}
# Upsert: Update if exists, insert if not
result = db.users.update_one(
{"email": user_data.email},
{
"$setOnInsert": {
"email": user_data.email,
"displayName": user_data.displayName or user_data.email.split("@")[0],
"photoURL": user_data.photoURL,
"theme": "light",
"createdAt": datetime.utcnow()
},
"$set": {
"updatedAt": datetime.utcnow()
}
},
upsert=True
)
result = db.users.insert_one(user_doc)
user_doc["id"] = str(result.inserted_id)
# Fetch the user (either newly created or existing)
user = db.users.find_one({"email": user_data.email})
if not user:
raise HTTPException(status_code=500, detail="Failed to retrieve user after upsert")
return {
"id": user_doc["id"],
"email": user_doc["email"],
"displayName": user_doc["displayName"],
"message": "User registered successfully"
"id": str(user["_id"]),
"email": user["email"],
"displayName": user["displayName"],
"photoURL": user.get("photoURL"),
"theme": user.get("theme", "light"),
"createdAt": user["createdAt"].isoformat(),
"updatedAt": user["updatedAt"].isoformat(),
"message": "User registered successfully" if result.upserted_id else "User already exists"
}
except DuplicateKeyError:
raise HTTPException(status_code=400, detail="User already exists")
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
raise HTTPException(status_code=500, detail=f"Registration failed: {str(e)}")
@router.get("/by-email/{email}", response_model=dict)
async def get_user_by_email(email: str):
"""Get user profile by email (called after Firebase Auth)"""
"""Get user profile by email (called after Firebase Auth)."""
db = get_database()
user = db.users.find_one({"email": email})
if not user:
raise HTTPException(status_code=404, detail="User not found")
user["id"] = str(user["_id"])
return user
@router.put("/update/{user_id}", response_model=dict)
async def update_user(user_id: str, user_data: UserUpdate):
"""Update user profile"""
db = get_database()
from bson import ObjectId
try:
user = db.users.find_one({"email": email})
if not user:
raise HTTPException(status_code=404, detail="User not found")
return {
"id": str(user["_id"]),
"email": user["email"],
"displayName": user.get("displayName"),
"photoURL": user.get("photoURL"),
"theme": user.get("theme", "light"),
"createdAt": user["createdAt"].isoformat(),
"updatedAt": user["updatedAt"].isoformat()
}
except Exception as e:
raise HTTPException(status_code=500, detail=f"Failed to fetch user: {str(e)}")
@router.get("/{user_id}", response_model=dict)
async def get_user_by_id(user_id: str):
"""Get user profile by ID."""
db = get_database()
try:
user = db.users.find_one({"_id": ObjectId(user_id)})
if not user:
raise HTTPException(status_code=404, detail="User not found")
return {
"id": str(user["_id"]),
"email": user["email"],
"displayName": user.get("displayName"),
"photoURL": user.get("photoURL"),
"theme": user.get("theme", "light"),
"createdAt": user["createdAt"].isoformat(),
"updatedAt": user["updatedAt"].isoformat()
}
except Exception as e:
if "invalid ObjectId" in str(e).lower():
raise HTTPException(status_code=400, detail="Invalid user ID format")
raise HTTPException(status_code=500, detail=f"Failed to fetch user: {str(e)}")
@router.put("/{user_id}", response_model=dict)
async def update_user(user_id: str, user_data: UserUpdate):
"""Update user profile."""
db = get_database()
try:
# Prepare update data (exclude None values)
update_data = user_data.model_dump(exclude_unset=True)
update_data["updatedAt"] = datetime.utcnow()
@@ -73,20 +125,47 @@ async def update_user(user_id: str, user_data: UserUpdate):
if result.matched_count == 0:
raise HTTPException(status_code=404, detail="User not found")
return {"message": "User updated successfully"}
# Fetch and return updated user
user = db.users.find_one({"_id": ObjectId(user_id)})
return {
"id": str(user["_id"]),
"email": user["email"],
"displayName": user.get("displayName"),
"photoURL": user.get("photoURL"),
"theme": user.get("theme", "light"),
"createdAt": user["createdAt"].isoformat(),
"updatedAt": user["updatedAt"].isoformat(),
"message": "User updated successfully"
}
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
if "invalid ObjectId" in str(e).lower():
raise HTTPException(status_code=400, detail="Invalid user ID format")
raise HTTPException(status_code=500, detail=f"Update failed: {str(e)}")
@router.delete("/{user_id}")
async def delete_user(user_id: str):
"""Delete user account and all associated data"""
"""Delete user account and all associated data."""
db = get_database()
from bson import ObjectId
try:
# Delete user
db.users.delete_one({"_id": ObjectId(user_id)})
user_result = db.users.delete_one({"_id": ObjectId(user_id)})
if user_result.deleted_count == 0:
raise HTTPException(status_code=404, detail="User not found")
# Delete all user's entries
entry_result = db.entries.delete_many({"userId": ObjectId(user_id)})
return {
"message": "User deleted successfully",
"user_deleted": user_result.deleted_count,
"entries_deleted": entry_result.deleted_count
}
except Exception as e:
if "invalid ObjectId" in str(e).lower():
raise HTTPException(status_code=400, detail="Invalid user ID format")
raise HTTPException(status_code=500, detail=f"Deletion failed: {str(e)}")
# Delete all entries by user
db.entries.delete_many({"userId": user_id})