Initial import — snapshot from admin host /srv/gosec/gsc-ops-api
This repo had no version control prior to this commit. The import is a
straight snapshot of the working tree at 2026-05-03; the deployed
binary on fihelvop01 was being rebuilt from this source via `make
build` + scp into place, with no upstream review path.
The snapshot already includes one in-flight fix made on 2026-05-03 to
internal/service/persona.go:GetSelfModel — the handler queried
`source` and `strength` columns plus an `is_active = true` filter on
persona.persona_commitments, none of which exist on that table (its
shape is session-bound commitments with `status`, `commitment_meta`,
etc.). The query returned a 500 every time SynapseHub bootstrapped a
persona's self-model, dropping the IdentityConstraints / Commitments /
ConscienceStandards layer from the assembled prompt. The patched
query reads existing columns only (commitment_text, commitment_type),
filters on `status='active'`, and synthesises Source="learned" /
Strength=1.0 to keep the SelfModel response shape stable for callers.
Verified live: `GET /api/v1/personas/70f7cfd9-.../self-model` now
returns 200 with `{identityConstraints:[],commitments:[],
conscienceStandards:[]}` instead of 500.
Future changes go through PRs against this repo — no more bin-only
deploys.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
603
internal/handler/pbx.go
Normal file
603
internal/handler/pbx.go
Normal file
@@ -0,0 +1,603 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/google/uuid"
|
||||
|
||||
"github.com/gosec/gsc-ops-api/internal/middleware"
|
||||
"github.com/gosec/gsc-ops-api/internal/service"
|
||||
"github.com/gosec/gsc-ops-api/pkg/types"
|
||||
)
|
||||
|
||||
// PBXHandler handles PBX management endpoints
|
||||
type PBXHandler struct {
|
||||
svc *service.PBXService
|
||||
}
|
||||
|
||||
// NewPBXHandler creates a new PBX handler
|
||||
func NewPBXHandler(svc *service.PBXService) *PBXHandler {
|
||||
return &PBXHandler{svc: svc}
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Trunks
|
||||
// ============================================================================
|
||||
|
||||
// ListTrunks handles GET /api/v1/pbx/trunks
|
||||
func (h *PBXHandler) ListTrunks(c *fiber.Ctx) error {
|
||||
reqID := middleware.GetRequestID(c)
|
||||
|
||||
params := types.ListParams{
|
||||
Limit: c.QueryInt("limit", 50),
|
||||
Offset: c.QueryInt("offset", 0),
|
||||
Search: c.Query("search"),
|
||||
Status: c.Query("status"),
|
||||
}
|
||||
|
||||
trunks, total, err := h.svc.ListTrunks(c.Context(), params)
|
||||
if err != nil {
|
||||
apiErr := types.NewInternal(err.Error())
|
||||
return c.Status(apiErr.Status).JSON(types.NewErrorResponse(apiErr, reqID))
|
||||
}
|
||||
|
||||
return c.JSON(types.NewPagedResponse(trunks, total, params.Limit, params.Offset, reqID))
|
||||
}
|
||||
|
||||
// GetTrunk handles GET /api/v1/pbx/trunks/:id
|
||||
func (h *PBXHandler) GetTrunk(c *fiber.Ctx) error {
|
||||
reqID := middleware.GetRequestID(c)
|
||||
|
||||
id, err := uuid.Parse(c.Params("id"))
|
||||
if err != nil {
|
||||
apiErr := types.NewBadRequest("Invalid trunk ID")
|
||||
return c.Status(apiErr.Status).JSON(types.NewErrorResponse(apiErr, reqID))
|
||||
}
|
||||
|
||||
trunk, err := h.svc.GetTrunk(c.Context(), id)
|
||||
if err != nil {
|
||||
apiErr := types.NewNotFound("Trunk not found")
|
||||
return c.Status(apiErr.Status).JSON(types.NewErrorResponse(apiErr, reqID))
|
||||
}
|
||||
|
||||
return c.JSON(types.NewDataResponse(trunk, reqID))
|
||||
}
|
||||
|
||||
// CreateTrunk handles POST /api/v1/pbx/trunks
|
||||
func (h *PBXHandler) CreateTrunk(c *fiber.Ctx) error {
|
||||
reqID := middleware.GetRequestID(c)
|
||||
|
||||
var req types.PBXTrunkCreate
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
apiErr := types.NewBadRequest("Invalid request body: " + err.Error())
|
||||
return c.Status(apiErr.Status).JSON(types.NewErrorResponse(apiErr, reqID))
|
||||
}
|
||||
|
||||
if req.Name == "" || req.Host == "" || req.TenantID == uuid.Nil {
|
||||
apiErr := types.NewValidation("tenantId, name, and host are required")
|
||||
return c.Status(apiErr.Status).JSON(types.NewErrorResponse(apiErr, reqID))
|
||||
}
|
||||
|
||||
trunk, err := h.svc.CreateTrunk(c.Context(), &req)
|
||||
if err != nil {
|
||||
apiErr := types.NewInternal(err.Error())
|
||||
return c.Status(apiErr.Status).JSON(types.NewErrorResponse(apiErr, reqID))
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusCreated).JSON(types.NewDataResponse(trunk, reqID))
|
||||
}
|
||||
|
||||
// UpdateTrunk handles PUT /api/v1/pbx/trunks/:id
|
||||
func (h *PBXHandler) UpdateTrunk(c *fiber.Ctx) error {
|
||||
reqID := middleware.GetRequestID(c)
|
||||
|
||||
id, err := uuid.Parse(c.Params("id"))
|
||||
if err != nil {
|
||||
apiErr := types.NewBadRequest("Invalid trunk ID")
|
||||
return c.Status(apiErr.Status).JSON(types.NewErrorResponse(apiErr, reqID))
|
||||
}
|
||||
|
||||
var req types.PBXTrunkUpdate
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
apiErr := types.NewBadRequest("Invalid request body: " + err.Error())
|
||||
return c.Status(apiErr.Status).JSON(types.NewErrorResponse(apiErr, reqID))
|
||||
}
|
||||
|
||||
trunk, err := h.svc.UpdateTrunk(c.Context(), id, &req)
|
||||
if err != nil {
|
||||
apiErr := types.NewInternal(err.Error())
|
||||
return c.Status(apiErr.Status).JSON(types.NewErrorResponse(apiErr, reqID))
|
||||
}
|
||||
|
||||
return c.JSON(types.NewDataResponse(trunk, reqID))
|
||||
}
|
||||
|
||||
// DeleteTrunk handles DELETE /api/v1/pbx/trunks/:id
|
||||
func (h *PBXHandler) DeleteTrunk(c *fiber.Ctx) error {
|
||||
reqID := middleware.GetRequestID(c)
|
||||
|
||||
id, err := uuid.Parse(c.Params("id"))
|
||||
if err != nil {
|
||||
apiErr := types.NewBadRequest("Invalid trunk ID")
|
||||
return c.Status(apiErr.Status).JSON(types.NewErrorResponse(apiErr, reqID))
|
||||
}
|
||||
|
||||
if err := h.svc.DeleteTrunk(c.Context(), id); err != nil {
|
||||
apiErr := types.NewInternal(err.Error())
|
||||
return c.Status(apiErr.Status).JSON(types.NewErrorResponse(apiErr, reqID))
|
||||
}
|
||||
|
||||
return c.JSON(types.NewDataResponse(fiber.Map{"id": id, "deleted": true}, reqID))
|
||||
}
|
||||
|
||||
// ActivateTrunk handles POST /api/v1/pbx/trunks/:id/activate
|
||||
func (h *PBXHandler) ActivateTrunk(c *fiber.Ctx) error {
|
||||
reqID := middleware.GetRequestID(c)
|
||||
|
||||
id, err := uuid.Parse(c.Params("id"))
|
||||
if err != nil {
|
||||
apiErr := types.NewBadRequest("Invalid trunk ID")
|
||||
return c.Status(apiErr.Status).JSON(types.NewErrorResponse(apiErr, reqID))
|
||||
}
|
||||
|
||||
trunk, err := h.svc.ActivateTrunk(c.Context(), id)
|
||||
if err != nil {
|
||||
apiErr := types.NewInternal(err.Error())
|
||||
return c.Status(apiErr.Status).JSON(types.NewErrorResponse(apiErr, reqID))
|
||||
}
|
||||
|
||||
return c.JSON(types.NewDataResponse(trunk, reqID))
|
||||
}
|
||||
|
||||
// DeactivateTrunk handles POST /api/v1/pbx/trunks/:id/deactivate
|
||||
func (h *PBXHandler) DeactivateTrunk(c *fiber.Ctx) error {
|
||||
reqID := middleware.GetRequestID(c)
|
||||
|
||||
id, err := uuid.Parse(c.Params("id"))
|
||||
if err != nil {
|
||||
apiErr := types.NewBadRequest("Invalid trunk ID")
|
||||
return c.Status(apiErr.Status).JSON(types.NewErrorResponse(apiErr, reqID))
|
||||
}
|
||||
|
||||
trunk, err := h.svc.DeactivateTrunk(c.Context(), id)
|
||||
if err != nil {
|
||||
apiErr := types.NewInternal(err.Error())
|
||||
return c.Status(apiErr.Status).JSON(types.NewErrorResponse(apiErr, reqID))
|
||||
}
|
||||
|
||||
return c.JSON(types.NewDataResponse(trunk, reqID))
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Trunk DIDs
|
||||
// ============================================================================
|
||||
|
||||
// ListTrunkDIDs handles GET /api/v1/pbx/trunks/:id/dids
|
||||
func (h *PBXHandler) ListTrunkDIDs(c *fiber.Ctx) error {
|
||||
reqID := middleware.GetRequestID(c)
|
||||
|
||||
trunkID, err := uuid.Parse(c.Params("id"))
|
||||
if err != nil {
|
||||
apiErr := types.NewBadRequest("Invalid trunk ID")
|
||||
return c.Status(apiErr.Status).JSON(types.NewErrorResponse(apiErr, reqID))
|
||||
}
|
||||
|
||||
dids, err := h.svc.ListTrunkDIDs(c.Context(), trunkID)
|
||||
if err != nil {
|
||||
apiErr := types.NewInternal(err.Error())
|
||||
return c.Status(apiErr.Status).JSON(types.NewErrorResponse(apiErr, reqID))
|
||||
}
|
||||
|
||||
return c.JSON(types.NewDataResponse(dids, reqID))
|
||||
}
|
||||
|
||||
// CreateTrunkDID handles POST /api/v1/pbx/trunks/:id/dids
|
||||
func (h *PBXHandler) CreateTrunkDID(c *fiber.Ctx) error {
|
||||
reqID := middleware.GetRequestID(c)
|
||||
|
||||
trunkID, err := uuid.Parse(c.Params("id"))
|
||||
if err != nil {
|
||||
apiErr := types.NewBadRequest("Invalid trunk ID")
|
||||
return c.Status(apiErr.Status).JSON(types.NewErrorResponse(apiErr, reqID))
|
||||
}
|
||||
|
||||
var req types.PBXTrunkDIDCreate
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
apiErr := types.NewBadRequest("Invalid request body: " + err.Error())
|
||||
return c.Status(apiErr.Status).JSON(types.NewErrorResponse(apiErr, reqID))
|
||||
}
|
||||
|
||||
if req.DIDNumber == "" || req.TenantID == uuid.Nil {
|
||||
apiErr := types.NewValidation("tenantId and didNumber are required")
|
||||
return c.Status(apiErr.Status).JSON(types.NewErrorResponse(apiErr, reqID))
|
||||
}
|
||||
|
||||
did, err := h.svc.CreateTrunkDID(c.Context(), trunkID, &req)
|
||||
if err != nil {
|
||||
apiErr := types.NewInternal(err.Error())
|
||||
return c.Status(apiErr.Status).JSON(types.NewErrorResponse(apiErr, reqID))
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusCreated).JSON(types.NewDataResponse(did, reqID))
|
||||
}
|
||||
|
||||
// DeleteTrunkDID handles DELETE /api/v1/pbx/trunks/:id/dids/:didId
|
||||
func (h *PBXHandler) DeleteTrunkDID(c *fiber.Ctx) error {
|
||||
reqID := middleware.GetRequestID(c)
|
||||
|
||||
trunkID, err := uuid.Parse(c.Params("id"))
|
||||
if err != nil {
|
||||
apiErr := types.NewBadRequest("Invalid trunk ID")
|
||||
return c.Status(apiErr.Status).JSON(types.NewErrorResponse(apiErr, reqID))
|
||||
}
|
||||
|
||||
didID, err := uuid.Parse(c.Params("didId"))
|
||||
if err != nil {
|
||||
apiErr := types.NewBadRequest("Invalid DID ID")
|
||||
return c.Status(apiErr.Status).JSON(types.NewErrorResponse(apiErr, reqID))
|
||||
}
|
||||
|
||||
if err := h.svc.DeleteTrunkDID(c.Context(), trunkID, didID); err != nil {
|
||||
apiErr := types.NewInternal(err.Error())
|
||||
return c.Status(apiErr.Status).JSON(types.NewErrorResponse(apiErr, reqID))
|
||||
}
|
||||
|
||||
return c.JSON(types.NewDataResponse(fiber.Map{"id": didID, "deleted": true}, reqID))
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Extensions
|
||||
// ============================================================================
|
||||
|
||||
// ListExtensions handles GET /api/v1/pbx/extensions
|
||||
func (h *PBXHandler) ListExtensions(c *fiber.Ctx) error {
|
||||
reqID := middleware.GetRequestID(c)
|
||||
|
||||
params := types.ListParams{
|
||||
Limit: c.QueryInt("limit", 50),
|
||||
Offset: c.QueryInt("offset", 0),
|
||||
Search: c.Query("search"),
|
||||
Status: c.Query("status"),
|
||||
}
|
||||
|
||||
exts, total, err := h.svc.ListExtensions(c.Context(), params)
|
||||
if err != nil {
|
||||
apiErr := types.NewInternal(err.Error())
|
||||
return c.Status(apiErr.Status).JSON(types.NewErrorResponse(apiErr, reqID))
|
||||
}
|
||||
|
||||
return c.JSON(types.NewPagedResponse(exts, total, params.Limit, params.Offset, reqID))
|
||||
}
|
||||
|
||||
// GetExtension handles GET /api/v1/pbx/extensions/:id
|
||||
func (h *PBXHandler) GetExtension(c *fiber.Ctx) error {
|
||||
reqID := middleware.GetRequestID(c)
|
||||
|
||||
id, err := uuid.Parse(c.Params("id"))
|
||||
if err != nil {
|
||||
apiErr := types.NewBadRequest("Invalid extension ID")
|
||||
return c.Status(apiErr.Status).JSON(types.NewErrorResponse(apiErr, reqID))
|
||||
}
|
||||
|
||||
ext, err := h.svc.GetExtension(c.Context(), id)
|
||||
if err != nil {
|
||||
apiErr := types.NewNotFound("Extension not found")
|
||||
return c.Status(apiErr.Status).JSON(types.NewErrorResponse(apiErr, reqID))
|
||||
}
|
||||
|
||||
return c.JSON(types.NewDataResponse(ext, reqID))
|
||||
}
|
||||
|
||||
// CreateExtension handles POST /api/v1/pbx/extensions
|
||||
func (h *PBXHandler) CreateExtension(c *fiber.Ctx) error {
|
||||
reqID := middleware.GetRequestID(c)
|
||||
|
||||
var req types.PBXExtensionCreate
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
apiErr := types.NewBadRequest("Invalid request body: " + err.Error())
|
||||
return c.Status(apiErr.Status).JSON(types.NewErrorResponse(apiErr, reqID))
|
||||
}
|
||||
|
||||
if req.Extension == "" || req.Name == "" || req.TenantID == uuid.Nil {
|
||||
apiErr := types.NewValidation("tenantId, extension, and name are required")
|
||||
return c.Status(apiErr.Status).JSON(types.NewErrorResponse(apiErr, reqID))
|
||||
}
|
||||
|
||||
ext, err := h.svc.CreateExtension(c.Context(), &req)
|
||||
if err != nil {
|
||||
apiErr := types.NewInternal(err.Error())
|
||||
return c.Status(apiErr.Status).JSON(types.NewErrorResponse(apiErr, reqID))
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusCreated).JSON(types.NewDataResponse(ext, reqID))
|
||||
}
|
||||
|
||||
// UpdateExtension handles PUT /api/v1/pbx/extensions/:id
|
||||
func (h *PBXHandler) UpdateExtension(c *fiber.Ctx) error {
|
||||
reqID := middleware.GetRequestID(c)
|
||||
|
||||
id, err := uuid.Parse(c.Params("id"))
|
||||
if err != nil {
|
||||
apiErr := types.NewBadRequest("Invalid extension ID")
|
||||
return c.Status(apiErr.Status).JSON(types.NewErrorResponse(apiErr, reqID))
|
||||
}
|
||||
|
||||
var req types.PBXExtensionUpdate
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
apiErr := types.NewBadRequest("Invalid request body: " + err.Error())
|
||||
return c.Status(apiErr.Status).JSON(types.NewErrorResponse(apiErr, reqID))
|
||||
}
|
||||
|
||||
ext, err := h.svc.UpdateExtension(c.Context(), id, &req)
|
||||
if err != nil {
|
||||
apiErr := types.NewInternal(err.Error())
|
||||
return c.Status(apiErr.Status).JSON(types.NewErrorResponse(apiErr, reqID))
|
||||
}
|
||||
|
||||
return c.JSON(types.NewDataResponse(ext, reqID))
|
||||
}
|
||||
|
||||
// DeleteExtension handles DELETE /api/v1/pbx/extensions/:id
|
||||
func (h *PBXHandler) DeleteExtension(c *fiber.Ctx) error {
|
||||
reqID := middleware.GetRequestID(c)
|
||||
|
||||
id, err := uuid.Parse(c.Params("id"))
|
||||
if err != nil {
|
||||
apiErr := types.NewBadRequest("Invalid extension ID")
|
||||
return c.Status(apiErr.Status).JSON(types.NewErrorResponse(apiErr, reqID))
|
||||
}
|
||||
|
||||
if err := h.svc.DeleteExtension(c.Context(), id); err != nil {
|
||||
apiErr := types.NewInternal(err.Error())
|
||||
return c.Status(apiErr.Status).JSON(types.NewErrorResponse(apiErr, reqID))
|
||||
}
|
||||
|
||||
return c.JSON(types.NewDataResponse(fiber.Map{"id": id, "deleted": true}, reqID))
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Inbound Routes
|
||||
// ============================================================================
|
||||
|
||||
// ListInboundRoutes handles GET /api/v1/pbx/inbound-routes
|
||||
func (h *PBXHandler) ListInboundRoutes(c *fiber.Ctx) error {
|
||||
reqID := middleware.GetRequestID(c)
|
||||
|
||||
params := types.ListParams{
|
||||
Limit: c.QueryInt("limit", 50),
|
||||
Offset: c.QueryInt("offset", 0),
|
||||
Search: c.Query("search"),
|
||||
}
|
||||
|
||||
routes, total, err := h.svc.ListInboundRoutes(c.Context(), params)
|
||||
if err != nil {
|
||||
apiErr := types.NewInternal(err.Error())
|
||||
return c.Status(apiErr.Status).JSON(types.NewErrorResponse(apiErr, reqID))
|
||||
}
|
||||
|
||||
return c.JSON(types.NewPagedResponse(routes, total, params.Limit, params.Offset, reqID))
|
||||
}
|
||||
|
||||
// GetInboundRoute handles GET /api/v1/pbx/inbound-routes/:id
|
||||
func (h *PBXHandler) GetInboundRoute(c *fiber.Ctx) error {
|
||||
reqID := middleware.GetRequestID(c)
|
||||
|
||||
id, err := uuid.Parse(c.Params("id"))
|
||||
if err != nil {
|
||||
apiErr := types.NewBadRequest("Invalid route ID")
|
||||
return c.Status(apiErr.Status).JSON(types.NewErrorResponse(apiErr, reqID))
|
||||
}
|
||||
|
||||
route, err := h.svc.GetInboundRoute(c.Context(), id)
|
||||
if err != nil {
|
||||
apiErr := types.NewNotFound("Inbound route not found")
|
||||
return c.Status(apiErr.Status).JSON(types.NewErrorResponse(apiErr, reqID))
|
||||
}
|
||||
|
||||
return c.JSON(types.NewDataResponse(route, reqID))
|
||||
}
|
||||
|
||||
// CreateInboundRoute handles POST /api/v1/pbx/inbound-routes
|
||||
func (h *PBXHandler) CreateInboundRoute(c *fiber.Ctx) error {
|
||||
reqID := middleware.GetRequestID(c)
|
||||
|
||||
var req types.PBXInboundRouteCreate
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
apiErr := types.NewBadRequest("Invalid request body: " + err.Error())
|
||||
return c.Status(apiErr.Status).JSON(types.NewErrorResponse(apiErr, reqID))
|
||||
}
|
||||
|
||||
if req.Name == "" || req.DestinationType == "" || req.TenantID == uuid.Nil {
|
||||
apiErr := types.NewValidation("tenantId, name, and destinationType are required")
|
||||
return c.Status(apiErr.Status).JSON(types.NewErrorResponse(apiErr, reqID))
|
||||
}
|
||||
|
||||
route, err := h.svc.CreateInboundRoute(c.Context(), &req)
|
||||
if err != nil {
|
||||
apiErr := types.NewInternal(err.Error())
|
||||
return c.Status(apiErr.Status).JSON(types.NewErrorResponse(apiErr, reqID))
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusCreated).JSON(types.NewDataResponse(route, reqID))
|
||||
}
|
||||
|
||||
// UpdateInboundRoute handles PUT /api/v1/pbx/inbound-routes/:id
|
||||
func (h *PBXHandler) UpdateInboundRoute(c *fiber.Ctx) error {
|
||||
reqID := middleware.GetRequestID(c)
|
||||
|
||||
id, err := uuid.Parse(c.Params("id"))
|
||||
if err != nil {
|
||||
apiErr := types.NewBadRequest("Invalid route ID")
|
||||
return c.Status(apiErr.Status).JSON(types.NewErrorResponse(apiErr, reqID))
|
||||
}
|
||||
|
||||
var req types.PBXInboundRouteUpdate
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
apiErr := types.NewBadRequest("Invalid request body: " + err.Error())
|
||||
return c.Status(apiErr.Status).JSON(types.NewErrorResponse(apiErr, reqID))
|
||||
}
|
||||
|
||||
route, err := h.svc.UpdateInboundRoute(c.Context(), id, &req)
|
||||
if err != nil {
|
||||
apiErr := types.NewInternal(err.Error())
|
||||
return c.Status(apiErr.Status).JSON(types.NewErrorResponse(apiErr, reqID))
|
||||
}
|
||||
|
||||
return c.JSON(types.NewDataResponse(route, reqID))
|
||||
}
|
||||
|
||||
// DeleteInboundRoute handles DELETE /api/v1/pbx/inbound-routes/:id
|
||||
func (h *PBXHandler) DeleteInboundRoute(c *fiber.Ctx) error {
|
||||
reqID := middleware.GetRequestID(c)
|
||||
|
||||
id, err := uuid.Parse(c.Params("id"))
|
||||
if err != nil {
|
||||
apiErr := types.NewBadRequest("Invalid route ID")
|
||||
return c.Status(apiErr.Status).JSON(types.NewErrorResponse(apiErr, reqID))
|
||||
}
|
||||
|
||||
if err := h.svc.DeleteInboundRoute(c.Context(), id); err != nil {
|
||||
apiErr := types.NewInternal(err.Error())
|
||||
return c.Status(apiErr.Status).JSON(types.NewErrorResponse(apiErr, reqID))
|
||||
}
|
||||
|
||||
return c.JSON(types.NewDataResponse(fiber.Map{"id": id, "deleted": true}, reqID))
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Outbound Routes
|
||||
// ============================================================================
|
||||
|
||||
// ListOutboundRoutes handles GET /api/v1/pbx/outbound-routes
|
||||
func (h *PBXHandler) ListOutboundRoutes(c *fiber.Ctx) error {
|
||||
reqID := middleware.GetRequestID(c)
|
||||
|
||||
params := types.ListParams{
|
||||
Limit: c.QueryInt("limit", 50),
|
||||
Offset: c.QueryInt("offset", 0),
|
||||
Search: c.Query("search"),
|
||||
}
|
||||
|
||||
routes, total, err := h.svc.ListOutboundRoutes(c.Context(), params)
|
||||
if err != nil {
|
||||
apiErr := types.NewInternal(err.Error())
|
||||
return c.Status(apiErr.Status).JSON(types.NewErrorResponse(apiErr, reqID))
|
||||
}
|
||||
|
||||
return c.JSON(types.NewPagedResponse(routes, total, params.Limit, params.Offset, reqID))
|
||||
}
|
||||
|
||||
// GetOutboundRoute handles GET /api/v1/pbx/outbound-routes/:id
|
||||
func (h *PBXHandler) GetOutboundRoute(c *fiber.Ctx) error {
|
||||
reqID := middleware.GetRequestID(c)
|
||||
|
||||
id, err := uuid.Parse(c.Params("id"))
|
||||
if err != nil {
|
||||
apiErr := types.NewBadRequest("Invalid route ID")
|
||||
return c.Status(apiErr.Status).JSON(types.NewErrorResponse(apiErr, reqID))
|
||||
}
|
||||
|
||||
route, err := h.svc.GetOutboundRoute(c.Context(), id)
|
||||
if err != nil {
|
||||
apiErr := types.NewNotFound("Outbound route not found")
|
||||
return c.Status(apiErr.Status).JSON(types.NewErrorResponse(apiErr, reqID))
|
||||
}
|
||||
|
||||
return c.JSON(types.NewDataResponse(route, reqID))
|
||||
}
|
||||
|
||||
// CreateOutboundRoute handles POST /api/v1/pbx/outbound-routes
|
||||
func (h *PBXHandler) CreateOutboundRoute(c *fiber.Ctx) error {
|
||||
reqID := middleware.GetRequestID(c)
|
||||
|
||||
var req types.PBXOutboundRouteCreate
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
apiErr := types.NewBadRequest("Invalid request body: " + err.Error())
|
||||
return c.Status(apiErr.Status).JSON(types.NewErrorResponse(apiErr, reqID))
|
||||
}
|
||||
|
||||
if req.Name == "" || len(req.DialPatterns) == 0 || req.TenantID == uuid.Nil {
|
||||
apiErr := types.NewValidation("tenantId, name, and dialPatterns are required")
|
||||
return c.Status(apiErr.Status).JSON(types.NewErrorResponse(apiErr, reqID))
|
||||
}
|
||||
|
||||
route, err := h.svc.CreateOutboundRoute(c.Context(), &req)
|
||||
if err != nil {
|
||||
apiErr := types.NewInternal(err.Error())
|
||||
return c.Status(apiErr.Status).JSON(types.NewErrorResponse(apiErr, reqID))
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusCreated).JSON(types.NewDataResponse(route, reqID))
|
||||
}
|
||||
|
||||
// UpdateOutboundRoute handles PUT /api/v1/pbx/outbound-routes/:id
|
||||
func (h *PBXHandler) UpdateOutboundRoute(c *fiber.Ctx) error {
|
||||
reqID := middleware.GetRequestID(c)
|
||||
|
||||
id, err := uuid.Parse(c.Params("id"))
|
||||
if err != nil {
|
||||
apiErr := types.NewBadRequest("Invalid route ID")
|
||||
return c.Status(apiErr.Status).JSON(types.NewErrorResponse(apiErr, reqID))
|
||||
}
|
||||
|
||||
var req types.PBXOutboundRouteUpdate
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
apiErr := types.NewBadRequest("Invalid request body: " + err.Error())
|
||||
return c.Status(apiErr.Status).JSON(types.NewErrorResponse(apiErr, reqID))
|
||||
}
|
||||
|
||||
route, err := h.svc.UpdateOutboundRoute(c.Context(), id, &req)
|
||||
if err != nil {
|
||||
apiErr := types.NewInternal(err.Error())
|
||||
return c.Status(apiErr.Status).JSON(types.NewErrorResponse(apiErr, reqID))
|
||||
}
|
||||
|
||||
return c.JSON(types.NewDataResponse(route, reqID))
|
||||
}
|
||||
|
||||
// DeleteOutboundRoute handles DELETE /api/v1/pbx/outbound-routes/:id
|
||||
func (h *PBXHandler) DeleteOutboundRoute(c *fiber.Ctx) error {
|
||||
reqID := middleware.GetRequestID(c)
|
||||
|
||||
id, err := uuid.Parse(c.Params("id"))
|
||||
if err != nil {
|
||||
apiErr := types.NewBadRequest("Invalid route ID")
|
||||
return c.Status(apiErr.Status).JSON(types.NewErrorResponse(apiErr, reqID))
|
||||
}
|
||||
|
||||
if err := h.svc.DeleteOutboundRoute(c.Context(), id); err != nil {
|
||||
apiErr := types.NewInternal(err.Error())
|
||||
return c.Status(apiErr.Status).JSON(types.NewErrorResponse(apiErr, reqID))
|
||||
}
|
||||
|
||||
return c.JSON(types.NewDataResponse(fiber.Map{"id": id, "deleted": true}, reqID))
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// System Operations
|
||||
// ============================================================================
|
||||
|
||||
// Status handles GET /api/v1/pbx/status
|
||||
func (h *PBXHandler) Status(c *fiber.Ctx) error {
|
||||
reqID := middleware.GetRequestID(c)
|
||||
|
||||
status, err := h.svc.GetStatus(c.Context())
|
||||
if err != nil {
|
||||
apiErr := types.NewInternal(err.Error())
|
||||
return c.Status(apiErr.Status).JSON(types.NewErrorResponse(apiErr, reqID))
|
||||
}
|
||||
|
||||
return c.JSON(types.NewDataResponse(status, reqID))
|
||||
}
|
||||
|
||||
// Reload handles POST /api/v1/pbx/reload
|
||||
func (h *PBXHandler) Reload(c *fiber.Ctx) error {
|
||||
reqID := middleware.GetRequestID(c)
|
||||
|
||||
result, err := h.svc.Reload(c.Context())
|
||||
if err != nil {
|
||||
apiErr := types.NewInternal(err.Error())
|
||||
return c.Status(apiErr.Status).JSON(types.NewErrorResponse(apiErr, reqID))
|
||||
}
|
||||
|
||||
return c.JSON(types.NewDataResponse(result, reqID))
|
||||
}
|
||||
Reference in New Issue
Block a user