release: bump version to 0.59.0
This commit is contained in:
118
backend/app/api/v1/earth.py
Normal file
118
backend/app/api/v1/earth.py
Normal file
@@ -0,0 +1,118 @@
|
||||
"""Earth asset management APIs."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException, Request, status
|
||||
from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer
|
||||
from pydantic import BaseModel, Field
|
||||
from sqlalchemy import text
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from app.core.security import decode_token, get_current_user, redis_client
|
||||
from app.db.session import get_db
|
||||
from app.models.user import User
|
||||
from app.services.earth_boundaries import (
|
||||
EarthBoundaryBuildError,
|
||||
get_boundary_build_status,
|
||||
get_boundary_status,
|
||||
save_boundary_config,
|
||||
start_boundary_build_job,
|
||||
)
|
||||
|
||||
|
||||
router = APIRouter()
|
||||
optional_bearer = HTTPBearer(auto_error=False)
|
||||
|
||||
|
||||
class EarthBoundaryConfigPayload(BaseModel):
|
||||
config: dict[str, Any] = Field(default_factory=dict)
|
||||
|
||||
|
||||
@router.get("/boundaries/status")
|
||||
async def get_earth_boundary_status():
|
||||
return get_boundary_status()
|
||||
|
||||
|
||||
async def _get_optional_current_user(
|
||||
credentials: HTTPAuthorizationCredentials | None = Depends(optional_bearer),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
) -> User | None:
|
||||
if credentials is None:
|
||||
return None
|
||||
token = credentials.credentials
|
||||
if redis_client.sismember("blacklisted_tokens", token):
|
||||
return None
|
||||
payload = decode_token(token)
|
||||
if payload is None or payload.get("type") != "access":
|
||||
return None
|
||||
user_id = payload.get("sub")
|
||||
if user_id is None:
|
||||
return None
|
||||
result = await db.execute(
|
||||
text(
|
||||
"SELECT id, username, email, password_hash, role, is_active, gatekeeper_groups FROM users WHERE id = :id"
|
||||
),
|
||||
{"id": int(user_id)},
|
||||
)
|
||||
row = result.fetchone()
|
||||
if row is None or not row[5]:
|
||||
return None
|
||||
user = User()
|
||||
user.id = row[0]
|
||||
user.username = row[1]
|
||||
user.email = row[2]
|
||||
user.password_hash = row[3]
|
||||
user.role = row[4]
|
||||
user.is_active = row[5]
|
||||
user.gatekeeper_groups = row[6] or []
|
||||
return user
|
||||
|
||||
|
||||
def _is_loopback_request(request: Request) -> bool:
|
||||
host = request.client.host if request.client else ""
|
||||
return host in {"127.0.0.1", "::1", "localhost"} or host.startswith("127.")
|
||||
|
||||
|
||||
def _require_local_or_user(request: Request, user: User | None) -> None:
|
||||
if user is not None or _is_loopback_request(request):
|
||||
return
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_401_UNAUTHORIZED,
|
||||
detail="Authentication required outside localhost",
|
||||
)
|
||||
|
||||
|
||||
@router.put("/boundaries/config")
|
||||
async def update_earth_boundary_config(
|
||||
payload: EarthBoundaryConfigPayload,
|
||||
_current_user: User = Depends(get_current_user),
|
||||
):
|
||||
try:
|
||||
return save_boundary_config(payload.config)
|
||||
except EarthBoundaryBuildError as exc:
|
||||
raise HTTPException(
|
||||
status_code=400,
|
||||
detail={"code": exc.code, "message": str(exc), "details": exc.details},
|
||||
) from exc
|
||||
|
||||
|
||||
@router.post("/boundaries/build")
|
||||
async def build_earth_boundary_assets(
|
||||
request: Request,
|
||||
current_user: User | None = Depends(_get_optional_current_user),
|
||||
):
|
||||
_require_local_or_user(request, current_user)
|
||||
try:
|
||||
return await start_boundary_build_job()
|
||||
except EarthBoundaryBuildError as exc:
|
||||
raise HTTPException(
|
||||
status_code=400,
|
||||
detail={"code": exc.code, "message": str(exc), "details": exc.details},
|
||||
) from exc
|
||||
|
||||
|
||||
@router.get("/boundaries/build/status")
|
||||
async def get_earth_boundary_build_status():
|
||||
return get_boundary_build_status()
|
||||
Reference in New Issue
Block a user