- go.mod module name
- All 714 import references across 289 Go files
- VERSION: 0.1.0
- CI DB names: switchboard_core_{ci,dev,test}
- Docker image: gobha/switchboard-core
- Test fixtures: JWT issuer, repo names
- .env.example, docker-compose container name
- Compiles clean (go build exit 0)
158 lines
4.5 KiB
Go
158 lines
4.5 KiB
Go
package handlers
|
|
|
|
import (
|
|
"database/sql"
|
|
"net/http"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
|
|
"switchboard-core/models"
|
|
)
|
|
|
|
// ── Team-Scoped Workflow Wrappers (v0.31.2) ────────────────
|
|
//
|
|
// Thin wrappers that enforce team ownership before delegating
|
|
// to the existing WorkflowHandler methods. Follows the same
|
|
// pattern as CreateTeamTask / ListTeamTasks.
|
|
|
|
// requireTeamWorkflow loads the workflow by :id and verifies
|
|
// its team_id matches :teamId. Returns false (and writes an
|
|
// HTTP error) if the check fails; true if the caller may proceed.
|
|
func (h *WorkflowHandler) requireTeamWorkflow(c *gin.Context) bool {
|
|
teamID := c.Param("teamId")
|
|
wfID := c.Param("id")
|
|
w, err := h.stores.Workflows.GetByID(c.Request.Context(), wfID)
|
|
if err != nil {
|
|
if err == sql.ErrNoRows {
|
|
c.JSON(http.StatusNotFound, gin.H{"error": "workflow not found"})
|
|
} else {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to load workflow"})
|
|
}
|
|
return false
|
|
}
|
|
if w.TeamID == nil || *w.TeamID != teamID {
|
|
c.JSON(http.StatusForbidden, gin.H{"error": "workflow does not belong to this team"})
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
// ── Workflow CRUD ───────────────────────────
|
|
|
|
// ListTeamWorkflows returns workflows owned by the team.
|
|
// GET /api/v1/teams/:teamId/workflows
|
|
func (h *WorkflowHandler) ListTeamWorkflows(c *gin.Context) {
|
|
teamID := c.Param("teamId")
|
|
result, err := h.stores.Workflows.ListForTeam(c.Request.Context(), teamID)
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to list workflows"})
|
|
return
|
|
}
|
|
if result == nil {
|
|
result = []models.Workflow{}
|
|
}
|
|
c.JSON(http.StatusOK, gin.H{"data": result})
|
|
}
|
|
|
|
// CreateTeamWorkflow creates a workflow scoped to the team.
|
|
// POST /api/v1/teams/:teamId/workflows
|
|
func (h *WorkflowHandler) CreateTeamWorkflow(c *gin.Context) {
|
|
teamID := c.Param("teamId")
|
|
c.Set("force_team_id", teamID)
|
|
h.Create(c)
|
|
}
|
|
|
|
// GetTeamWorkflow returns a team workflow with stages.
|
|
// GET /api/v1/teams/:teamId/workflows/:id
|
|
func (h *WorkflowHandler) GetTeamWorkflow(c *gin.Context) {
|
|
if !h.requireTeamWorkflow(c) {
|
|
return
|
|
}
|
|
h.Get(c)
|
|
}
|
|
|
|
// UpdateTeamWorkflow patches a team workflow.
|
|
// PATCH /api/v1/teams/:teamId/workflows/:id
|
|
func (h *WorkflowHandler) UpdateTeamWorkflow(c *gin.Context) {
|
|
if !h.requireTeamWorkflow(c) {
|
|
return
|
|
}
|
|
h.Update(c)
|
|
}
|
|
|
|
// DeleteTeamWorkflow deletes a team workflow.
|
|
// DELETE /api/v1/teams/:teamId/workflows/:id
|
|
func (h *WorkflowHandler) DeleteTeamWorkflow(c *gin.Context) {
|
|
if !h.requireTeamWorkflow(c) {
|
|
return
|
|
}
|
|
h.Delete(c)
|
|
}
|
|
|
|
// ── Stage CRUD ──────────────────────────────
|
|
|
|
// ListTeamWorkflowStages returns stages for a team workflow.
|
|
// GET /api/v1/teams/:teamId/workflows/:id/stages
|
|
func (h *WorkflowHandler) ListTeamWorkflowStages(c *gin.Context) {
|
|
if !h.requireTeamWorkflow(c) {
|
|
return
|
|
}
|
|
h.ListStages(c)
|
|
}
|
|
|
|
// CreateTeamWorkflowStage adds a stage to a team workflow.
|
|
// POST /api/v1/teams/:teamId/workflows/:id/stages
|
|
func (h *WorkflowHandler) CreateTeamWorkflowStage(c *gin.Context) {
|
|
if !h.requireTeamWorkflow(c) {
|
|
return
|
|
}
|
|
h.CreateStage(c)
|
|
}
|
|
|
|
// UpdateTeamWorkflowStage updates a stage on a team workflow.
|
|
// PUT /api/v1/teams/:teamId/workflows/:id/stages/:sid
|
|
func (h *WorkflowHandler) UpdateTeamWorkflowStage(c *gin.Context) {
|
|
if !h.requireTeamWorkflow(c) {
|
|
return
|
|
}
|
|
h.UpdateStage(c)
|
|
}
|
|
|
|
// DeleteTeamWorkflowStage removes a stage from a team workflow.
|
|
// DELETE /api/v1/teams/:teamId/workflows/:id/stages/:sid
|
|
func (h *WorkflowHandler) DeleteTeamWorkflowStage(c *gin.Context) {
|
|
if !h.requireTeamWorkflow(c) {
|
|
return
|
|
}
|
|
h.DeleteStage(c)
|
|
}
|
|
|
|
// ReorderTeamWorkflowStages reorders stages on a team workflow.
|
|
// PATCH /api/v1/teams/:teamId/workflows/:id/stages/reorder
|
|
func (h *WorkflowHandler) ReorderTeamWorkflowStages(c *gin.Context) {
|
|
if !h.requireTeamWorkflow(c) {
|
|
return
|
|
}
|
|
h.ReorderStages(c)
|
|
}
|
|
|
|
// ── Publish / Version ───────────────────────
|
|
|
|
// PublishTeamWorkflow publishes a team workflow version.
|
|
// POST /api/v1/teams/:teamId/workflows/:id/publish
|
|
func (h *WorkflowHandler) PublishTeamWorkflow(c *gin.Context) {
|
|
if !h.requireTeamWorkflow(c) {
|
|
return
|
|
}
|
|
h.Publish(c)
|
|
}
|
|
|
|
// GetTeamWorkflowVersion returns a version snapshot for a team workflow.
|
|
// GET /api/v1/teams/:teamId/workflows/:id/versions/:version
|
|
func (h *WorkflowHandler) GetTeamWorkflowVersion(c *gin.Context) {
|
|
if !h.requireTeamWorkflow(c) {
|
|
return
|
|
}
|
|
h.GetVersion(c)
|
|
}
|