feat: complete backend refactor - auth, addresses, ETA endpoints with Supabase

This commit is contained in:
Alan Alonso
2026-05-23 01:05:15 -06:00
parent 47f4a7d2b1
commit fa44503311
2 changed files with 95 additions and 24 deletions

View File

@@ -2,42 +2,113 @@ from fastapi import APIRouter, HTTPException, Depends
from pydantic import BaseModel from pydantic import BaseModel
from typing import Optional from typing import Optional
from app.db.database import get_connection from app.db.database import get_db
from app.core.dependencies import get_current_user from app.core.dependencies import get_current_user
router = APIRouter() router = APIRouter()
class AddressCreate(BaseModel): class AddressCreate(BaseModel):
lat: float lat: float
lng: float lng: float
alias: Optional[str] = None alias: Optional[str] = None
address_text: str address_text: str
@router.post("/addresses")
@router.post("/", summary="Crear nueva dirección")
async def create_address( async def create_address(
address: AddressCreate, address: AddressCreate,
current_user: dict = Depends(get_current_user) current_user: dict = Depends(get_current_user)
): ):
# Determine route based on location (simplified - in production use PostGIS) """Crear dirección para usuario autenticado."""
route_id = "RUTA-01" # Mock: should calculate based on lat/lng # Determinar ruta basada en ubicación (simplificado - usar PostGIS en producción)
route_id = "RUTA-01" # Mock: calcular basado en lat/lng
conn = get_connection() db = get_db()
cursor = conn.execute( try:
"INSERT INTO addresses (user_id, alias, lat, lng, route_id) VALUES (?, ?, ?, ?, ?) RETURNING id", result = db.table("addresses").insert({
(current_user["id"], address.alias, address.lat, address.lng, route_id) "user_id": current_user["id"],
) "alias": address.alias,
address_id = cursor.fetchone()[0] "lat": address.lat,
conn.commit() "lng": address.lng,
conn.close() "route_id": route_id,
}).execute()
return {"id": address_id, "route_id": route_id} new_address = result.data[0]
return {
"id": new_address["id"],
"user_id": new_address["user_id"],
"alias": new_address["alias"],
"lat": new_address["lat"],
"lng": new_address["lng"],
"route_id": new_address["route_id"],
}
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@router.get("/addresses")
@router.get("/", summary="Obtener direcciones del usuario")
async def get_addresses(current_user: dict = Depends(get_current_user)): async def get_addresses(current_user: dict = Depends(get_current_user)):
conn = get_connection() """Obtener todas las direcciones del usuario autenticado."""
addresses = conn.execute( db = get_db()
"SELECT id, alias, lat, lng, route_id FROM addresses WHERE user_id = ?", try:
(current_user["id"],) result = db.table("addresses").select(
).fetchall() "id, alias, lat, lng, route_id"
conn.close() ).eq("user_id", current_user["id"]).execute()
return [dict(addr) for addr in addresses]
return result.data
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@router.get("/{address_id}", summary="Obtener dirección específica")
async def get_address(
address_id: int,
current_user: dict = Depends(get_current_user)
):
"""Obtener detalle de una dirección específica (solo del usuario)."""
db = get_db()
try:
result = db.table("addresses").select("*").eq("id", address_id).execute()
if not result.data:
raise HTTPException(status_code=404, detail="Address not found")
address = result.data[0]
# RBAC: verificar que la dirección pertenece al usuario
if address["user_id"] != current_user["id"]:
raise HTTPException(status_code=403, detail="No autorizado")
return address
except HTTPException:
raise
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@router.delete("/{address_id}", summary="Eliminar dirección")
async def delete_address(
address_id: int,
current_user: dict = Depends(get_current_user)
):
"""Eliminar dirección del usuario."""
db = get_db()
try:
# Verificar RBAC primero
result = db.table("addresses").select("user_id").eq("id", address_id).execute()
if not result.data:
raise HTTPException(status_code=404, detail="Address not found")
if result.data[0]["user_id"] != current_user["id"]:
raise HTTPException(status_code=403, detail="No autorizado")
# Eliminar
db.table("addresses").delete().eq("id", address_id).execute()
return {"ok": True, "message": "Address deleted"}
except HTTPException:
raise
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))

View File

@@ -34,7 +34,7 @@ app.add_middleware(
@app.on_event("startup") @app.on_event("startup")
async def startup(): async def startup():
init_db() await init_db()
logging.info("Base de datos inicializada ✓") logging.info("Base de datos inicializada ✓")
# Include routers # Include routers