package handler import ( "net/http" "github.com/gin-gonic/gin" "flowstack/internal/database" "flowstack/internal/model" ) // availablePlugins 可安装插件市场(演示数据) var availablePlugins = []gin.H{ {"pluginId": "gitops-sync", "name": "GitOps Sync", "description": "Argo CD integration", "version": "1.3.0", "author": "OpsX Team", "category": "部署", "installs": 3420}, {"pluginId": "tekton-tasks", "name": "Tekton Tasks", "description": "Cloud-native CI tasks", "version": "2.1.0", "author": "CloudNative", "category": "构建", "installs": 5180}, {"pluginId": "dark-theme", "name": "Dark Theme", "description": "Dark UI theme", "version": "1.1.0", "author": "DesignLab", "category": "主题", "installs": 8920}, {"pluginId": "sonarqube", "name": "SonarQube Scanner", "description": "Code quality scan", "version": "3.2.0", "author": "CodeQuality", "category": "扫描", "installs": 2150}, {"pluginId": "vault-secrets", "name": "Vault Secrets", "description": "HashiCorp Vault integration", "version": "1.6.0", "author": "SecurityTeam", "category": "安全", "installs": 980}, {"pluginId": "matrix-build", "name": "Matrix Build", "description": "Multi-dimension parallel build", "version": "2.0.0", "author": "BuildMaster", "category": "构建", "installs": 1670}, {"pluginId": "slack-notify", "name": "Slack Notify", "description": "Slack notifications", "version": "1.3.0", "author": "NotifyHub", "category": "通知", "installs": 2890}, } // ListPlugins GET /api/plugins func ListPlugins(c *gin.Context) { var list []model.Plugin database.DB.Order("created_at DESC").Find(&list) c.JSON(http.StatusOK, list) } // AvailablePlugins GET /api/plugins/available func AvailablePlugins(c *gin.Context) { c.JSON(http.StatusOK, availablePlugins) } // InstallPlugin POST /api/plugins/install func InstallPlugin(c *gin.Context) { var body struct { PluginID string `json:"pluginId" binding:"required"` Name string `json:"name" binding:"required"` Description string `json:"description"` Version string `json:"version" binding:"required"` Author string `json:"author"` Category string `json:"category"` EntryPath string `json:"entryPath"` } if err := c.ShouldBindJSON(&body); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } if body.Category == "" { body.Category = "general" } p := model.Plugin{ PluginID: body.PluginID, Name: body.Name, Description: body.Description, Version: body.Version, Author: body.Author, Category: body.Category, EntryPath: body.EntryPath, Installed: true, Enabled: true, Config: map[string]any{}, } if err := database.DB.Create(&p).Error; err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, p) } // TogglePlugin POST /api/plugins/:id/toggle {enabled} func TogglePlugin(c *gin.Context) { var p model.Plugin if err := database.DB.First(&p, c.Param("id")).Error; err != nil { c.JSON(http.StatusNotFound, gin.H{"error": "plugin not found"}) return } var body struct { Enabled bool `json:"enabled"` } if err := c.ShouldBindJSON(&body); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } database.DB.Model(&p).Update("enabled", body.Enabled) c.JSON(http.StatusOK, gin.H{"success": true, "enabled": body.Enabled}) } // UninstallPlugin DELETE /api/plugins/:id func UninstallPlugin(c *gin.Context) { database.DB.Delete(&model.Plugin{}, c.Param("id")) c.JSON(http.StatusOK, gin.H{"success": true}) }