fix(dcy-011/bat-022): GET /v1/admin/daemons 목록 엔드포인트 추가 — UI 계약 누락(405) 해소 (라이브 통합테스트 결함)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VHtM5Ws1HKCKQ4JGi6GRb5
This commit is contained in:
@@ -9,7 +9,13 @@ from fastapi import APIRouter, Depends, HTTPException, Response, status
|
||||
from app.core.auth import AuthContext, require_admin
|
||||
from app.core.config import Settings, get_settings
|
||||
from app.repositories.factory import get_portfolio_repository_from_settings
|
||||
from app.schemas.v1 import DaemonAdminResponse, DaemonCreateRequest, DaemonUpdateRequest
|
||||
from app.schemas.v1 import (
|
||||
DaemonAdminResponse,
|
||||
DaemonCreateRequest,
|
||||
DaemonDetail,
|
||||
DaemonDetailListResponse,
|
||||
DaemonUpdateRequest,
|
||||
)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
router = APIRouter(prefix="/v1/admin", tags=["v1-admin"])
|
||||
@@ -41,6 +47,39 @@ def _daemon_error_to_http(exc: ValueError) -> HTTPException:
|
||||
return HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=detail)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# GET /v1/admin/daemons — 전체 데몬 목록 (admin 전용)
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
@router.get("/daemons", response_model=DaemonDetailListResponse)
|
||||
def list_all_daemons(
|
||||
_auth: AuthContext = Depends(require_admin),
|
||||
settings: Settings = Depends(get_settings),
|
||||
) -> DaemonDetailListResponse:
|
||||
"""Return all daemons across all owners (admin only).
|
||||
|
||||
Matches trex-web DaemonDetailListResponse / DaemonDetail contract
|
||||
consumed by adminListDaemons() (REQ-035).
|
||||
"""
|
||||
repo = _get_repo(settings)
|
||||
try:
|
||||
daemons = repo.list_daemons_all()
|
||||
items = [
|
||||
DaemonDetail(
|
||||
id=d.id,
|
||||
daemon_slug=d.daemon_slug,
|
||||
display_name=d.display_name,
|
||||
is_active=d.is_active,
|
||||
owner_user_id=d.owner_user_id,
|
||||
)
|
||||
for d in daemons
|
||||
]
|
||||
return DaemonDetailListResponse(daemons=items, total=len(items))
|
||||
finally:
|
||||
if callable(getattr(type(repo), "close", None)):
|
||||
repo.close()
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# POST /v1/admin/daemons — 데몬 생성 (REQ-053 AC-1/2)
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
@@ -2289,6 +2289,19 @@ class PostgresPortfolioRepository:
|
||||
rows = cur.fetchall()
|
||||
return [self._row_to_daemon(row) for row in rows]
|
||||
|
||||
def list_daemons_all(self) -> list[Daemon]:
|
||||
"""Return all daemons across all owners (admin use only)."""
|
||||
self.ensure_schema()
|
||||
with self._connect().cursor() as cur:
|
||||
cur.execute(
|
||||
"""
|
||||
SELECT id, owner_user_id, daemon_slug, display_name, is_active, created_at, updated_at
|
||||
FROM daemons ORDER BY created_at ASC
|
||||
""",
|
||||
)
|
||||
rows = cur.fetchall()
|
||||
return [self._row_to_daemon(row) for row in rows]
|
||||
|
||||
def update_daemon(
|
||||
self,
|
||||
daemon_id: str,
|
||||
|
||||
@@ -375,3 +375,22 @@ class DaemonAdminResponse(BaseModel):
|
||||
display_name: str | None = None
|
||||
owner_user_id: str
|
||||
is_active: bool
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# GET /v1/admin/daemons (REQ-053 목록 조회)
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
class DaemonDetail(BaseModel):
|
||||
"""Single daemon item for admin list — matches trex-web DaemonDetail contract."""
|
||||
id: str
|
||||
daemon_slug: str
|
||||
display_name: str | None = None
|
||||
is_active: bool
|
||||
owner_user_id: str
|
||||
|
||||
|
||||
class DaemonDetailListResponse(BaseModel):
|
||||
"""Response for GET /v1/admin/daemons — matches trex-web DaemonDetailListResponse."""
|
||||
daemons: list[DaemonDetail]
|
||||
total: int
|
||||
|
||||
Reference in New Issue
Block a user