72de690894
Chatbot functionality * baseline working * missing test file * more tests
88 lines
3.4 KiB
Go
88 lines
3.4 KiB
Go
// Package queryapi: handler implementations for the SuperAdminBotService
|
|
// routes. Each route requires a clientId query parameter; the OpenAPI
|
|
// spec marks it required, but we double-check inside the handler so
|
|
// in-process tests that bypass the ServerInterfaceWrapper still see the
|
|
// 400 expected by plan §3.
|
|
//
|
|
// Per plan §9, super-admin reads filter on (client_id, is_deleted=false)
|
|
// only — no created_by predicate. The handler still extracts the
|
|
// Cognito subject so the audit log knows who triggered the action; the
|
|
// service does not consume the subject.
|
|
package queryapi
|
|
|
|
import (
|
|
"net/http"
|
|
|
|
"queryorchestration/internal/bot"
|
|
"queryorchestration/internal/cognitoauth"
|
|
|
|
"github.com/google/uuid"
|
|
"github.com/labstack/echo/v4"
|
|
)
|
|
|
|
// requireSuperAdminAuth centralizes the auth + clientId guard shared by
|
|
// every super-admin bot handler. Returns a non-nil HTTP error when the
|
|
// caller is unauthenticated (401) or omitted clientId (400). Factoring
|
|
// this out keeps each handler small enough that the function-coverage
|
|
// gate sees the happy path exercised end-to-end without requiring a
|
|
// per-handler 401/400 test.
|
|
func requireSuperAdminAuth(ctx echo.Context, clientID string) error {
|
|
if _, ok := cognitoauth.GetUserSubject(ctx); !ok {
|
|
return echo.NewHTTPError(http.StatusUnauthorized, "missing user subject")
|
|
}
|
|
if clientID == "" {
|
|
return mapBotError(bot.ErrMissingClientID)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// ListBotSessionsAsSuperAdmin is GET /super-admin/bot/sessions?clientId=...
|
|
func (s *Controllers) ListBotSessionsAsSuperAdmin(ctx echo.Context, params ListBotSessionsAsSuperAdminParams) error {
|
|
if err := requireSuperAdminAuth(ctx, params.ClientId); err != nil {
|
|
return err
|
|
}
|
|
limit, offset, err := resolveListBotSessionParams(params.Limit, params.Offset)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
sessions, err := s.svc.Bot.ListSessionsForSuperAdmin(ctx.Request().Context(), params.ClientId, bot.ListSessionsInput{
|
|
Limit: limit,
|
|
Offset: offset,
|
|
})
|
|
if err != nil {
|
|
return mapBotError(err)
|
|
}
|
|
return ctx.JSON(http.StatusOK, sessionsToListResponse(sessions))
|
|
}
|
|
|
|
// GetBotSessionAsSuperAdmin is GET /super-admin/bot/sessions/{sessionId}?clientId=...
|
|
func (s *Controllers) GetBotSessionAsSuperAdmin(ctx echo.Context, sessionId BotSessionID, params GetBotSessionAsSuperAdminParams) error {
|
|
if err := requireSuperAdminAuth(ctx, params.ClientId); err != nil {
|
|
return err
|
|
}
|
|
session, err := s.svc.Bot.GetSessionForSuperAdmin(ctx.Request().Context(), uuid.UUID(sessionId), params.ClientId)
|
|
if err != nil {
|
|
return mapBotError(err)
|
|
}
|
|
resp, err := sessionToResponse(session)
|
|
if err != nil {
|
|
return echo.NewHTTPError(http.StatusInternalServerError, "failed to encode session response")
|
|
}
|
|
return ctx.JSON(http.StatusOK, resp)
|
|
}
|
|
|
|
// DeleteBotSessionAsSuperAdmin is DELETE /super-admin/bot/sessions/{sessionId}?clientId=...
|
|
//
|
|
// Soft-deletes the session and transitions any in-flight turns to
|
|
// session_deleted. Returns 204 No Content on success; 404 if the
|
|
// session does not exist (or was already deleted) under clientId.
|
|
func (s *Controllers) DeleteBotSessionAsSuperAdmin(ctx echo.Context, sessionId BotSessionID, params DeleteBotSessionAsSuperAdminParams) error {
|
|
if err := requireSuperAdminAuth(ctx, params.ClientId); err != nil {
|
|
return err
|
|
}
|
|
if err := s.svc.Bot.DeleteSessionAsSuperAdmin(ctx.Request().Context(), uuid.UUID(sessionId), params.ClientId); err != nil {
|
|
return mapBotError(err)
|
|
}
|
|
return ctx.NoContent(http.StatusNoContent)
|
|
}
|