feat: complete backend refactor - auth, addresses, ETA endpoints with Supabase
This commit is contained in:
@@ -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))
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user