fix(i-c): BUG-024 behoben — Plugin-Detail-Endpoint GET /api/v1/plugins/{name} implementiert (Manifest-Metadaten + DB-Status, 404 für unbekannte); Beweistest test_plugin_detail.py 2/2 grün; Existenzprüfung vorher: Route fehlte komplett (bewiesen), Frontend-Nutzung niedrig aber API-Vollständigkeit hergestellt

This commit is contained in:
Agent Zero
2026-08-24 21:12:58 +02:00
parent b9a6c06e85
commit d9aed519f2
3 changed files with 81 additions and 2 deletions
+44 -1
View File
@@ -5,13 +5,14 @@ from __future__ import annotations
import logging import logging
from typing import Any from typing import Any
from fastapi import APIRouter, Depends, File, HTTPException, Query, UploadFile from fastapi import APIRouter, Depends, File, HTTPException, Query, UploadFile, status
from pydantic import BaseModel from pydantic import BaseModel
from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.ext.asyncio import AsyncSession
from app.core.db import get_db from app.core.db import get_db
from app.deps import get_current_user, require_admin, require_permission from app.deps import get_current_user, require_admin, require_permission
from app.plugins.migration_runner import MigrationValidationError from app.plugins.migration_runner import MigrationValidationError
from app.plugins.registry import get_registry
from app.services.plugin_service import get_plugin_service from app.services.plugin_service import get_plugin_service
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@@ -43,6 +44,48 @@ async def list_plugins(
return {"plugins": plugins, "total": len(plugins)} return {"plugins": plugins, "total": len(plugins)}
@router.get("/{name}")
async def get_plugin_detail(
name: str,
db: AsyncSession = Depends(get_db),
current_user: dict = Depends(require_permission("plugins:read")),
):
"""Get detail for a single plugin: manifest metadata + DB status.
BUG-024 fix: this endpoint was missing entirely (404).
"""
registry = get_registry()
plugin = registry.get_plugin(name)
if plugin is None:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail={"detail": f"Plugin '{name}' not found", "code": "not_found"},
)
m = plugin.manifest
record = registry.get_db_status(name)
return {
"name": m.name,
"version": m.version,
"display_name": getattr(m, "display_name", None) or m.name,
"description": getattr(m, "description", None),
"author": getattr(m, "author", None),
"is_core": bool(getattr(m, "is_core", False)),
"permissions": list(m.permissions),
"depends_on": list(getattr(m, "depends_on", []) or []),
"status": {
"installed": record is not None,
"active": bool(record.active) if record is not None else False,
"version_installed": getattr(record, "version", None),
},
"menu_items": len(getattr(m, "menu_items", []) or []),
"page_routes": len(getattr(m, "page_routes", []) or []),
"detail_tabs": len(getattr(m, "detail_tabs", []) or []),
"settings_pages": len(getattr(m, "settings_pages", []) or []),
"dashboard_widgets": len(getattr(m, "dashboard_widgets", []) or []),
}
@router.get("/manifest") @router.get("/manifest")
async def get_manifest_schema( async def get_manifest_schema(
current_user: dict = Depends(require_permission("plugins:read")), current_user: dict = Depends(require_permission("plugins:read")),
+1 -1
View File
@@ -251,7 +251,7 @@ Jeder Bug wird wie folgt dokumentiert:
- **Tatsächlich:** 404 Not Found für alle Plugins - **Tatsächlich:** 404 Not Found für alle Plugins
- **Schweregrad:** Medium - **Schweregrad:** Medium
- **Ursache:** Es gibt `/{name}/config`, `/{name}/activate`, `/{name}/deactivate` aber keine reine `GET /{name}` Route - **Ursache:** Es gibt `/{name}/config`, `/{name}/activate`, `/{name}/deactivate` aber keine reine `GET /{name}` Route
- **Status:** ⏳ Nicht gefixt - **Status:** ✅ Gefixt 2026-08-24 (Block E/I-C): GET /api/v1/plugins/{name} implementiert — Manifest-Metadaten + DB-Status kombiniert, 404 für unbekannte Plugins; Beweistest tests/test_plugin_detail.py 2/2 grün (200 für calendar inkl. status-Objekt, 404 für unknown); ruff clean. Nutzungsrelevanz war niedrig (Frontend ruft kein Detail auf), aber API-Vollständigkeit hergestellt.
### BUG-025: Workflow Execute und Instances API-Pfade falsch ### BUG-025: Workflow Execute und Instances API-Pfade falsch
- **Kategorie:** API - **Kategorie:** API
+36
View File
@@ -0,0 +1,36 @@
"""Tests for the plugin detail endpoint (BUG-024 fix).
Proves GET /api/v1/plugins/{name} returns manifest+status detail for known
plugins and 404 for unknown ones.
"""
from __future__ import annotations
import pytest
from tests.conftest import ORIGIN_HEADER, login_client, seed_tenant_and_users
@pytest.mark.asyncio
async def test_plugin_detail_returns_manifest_and_status(
client, db_session
):
"""GET /api/v1/plugins/calendar -> 200 with manifest metadata + status."""
await seed_tenant_and_users(db_session)
await login_client(client, "admin@tenanta.com")
resp = await client.get("/api/v1/plugins/calendar", headers=ORIGIN_HEADER)
assert resp.status_code == 200, resp.text
data = resp.json()
assert data["name"] == "calendar"
assert "status" in data and "installed" in data["status"]
@pytest.mark.asyncio
async def test_plugin_detail_unknown_plugin_returns_404(client, db_session):
"""GET /api/v1/plugins/__unknown__ -> 404 not_found."""
await seed_tenant_and_users(db_session)
await login_client(client, "admin@tenanta.com")
resp = await client.get("/api/v1/plugins/__unknown_plugin_xyz__", headers=ORIGIN_HEADER)
assert resp.status_code == 404, resp.text