- Rename Go module switchboard-core → armature (155+ files) - Rename Docker image → gobha/armature - Rename K8s resources, secrets, deployments - Rename Prometheus metrics switchboard_* → armature_* - Rename env vars SWITCHBOARD_ADMIN_* → ARMATURE_ADMIN_* - Rename DB names switchboard_core* → armature* - Update all frontend branding, notification templates, docs - Update CI scripts, e2e tests, Keycloak realm, nginx conf - Rename scripts/switchboard-ca.sh → scripts/armature-ca.sh - Rename k8s/switchboard.yaml → k8s/armature.yaml - Rename chart alerting/dashboard files - Fix: DockerHub push uses env: binding for secret injection - Helm chart updated (name, labels, template functions, dashboard, alerting) - Replace favicon/icon assets with Armature brand No functional changes. Pure mechanical rename + CI fix. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
123 lines
3.6 KiB
Go
123 lines
3.6 KiB
Go
package handlers
|
|
|
|
// team_package_settings.go
|
|
//
|
|
// Team-admin endpoints for managing team-scoped package settings.
|
|
// These sit in the settings cascade between global (admin) and user.
|
|
// Only overridable keys (user_overridable != false) can be set at team scope.
|
|
|
|
import (
|
|
"encoding/json"
|
|
"strings"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
|
|
"armature/store"
|
|
)
|
|
|
|
// TeamPackageSettingsHandler serves team-scoped package settings endpoints.
|
|
type TeamPackageSettingsHandler struct {
|
|
stores store.Stores
|
|
}
|
|
|
|
func NewTeamPackageSettingsHandler(s store.Stores) *TeamPackageSettingsHandler {
|
|
return &TeamPackageSettingsHandler{stores: s}
|
|
}
|
|
|
|
// GetTeamPackageSettings returns the team-scoped settings for a package,
|
|
// along with the overridable schema keys for the UI.
|
|
// GET /api/v1/teams/:teamId/packages/:id/settings
|
|
func (h *TeamPackageSettingsHandler) GetTeamPackageSettings(c *gin.Context) {
|
|
teamID := c.Param("teamId")
|
|
pkgID := c.Param("id")
|
|
|
|
pkg, err := h.stores.Packages.Get(c.Request.Context(), pkgID)
|
|
if err != nil || pkg == nil {
|
|
c.JSON(404, gin.H{"error": "package not found"})
|
|
return
|
|
}
|
|
|
|
// Parse schema and filter to overridable keys only
|
|
schema := store.ParseSettingsSchema(pkg.Manifest)
|
|
var overridableSchema []store.SettingSchema
|
|
for _, s := range schema {
|
|
if s.IsUserOverridable() {
|
|
overridableSchema = append(overridableSchema, s)
|
|
}
|
|
}
|
|
|
|
// Load current team values
|
|
settings, err := h.stores.Packages.GetTeamSettings(c.Request.Context(), pkgID, teamID)
|
|
if err != nil {
|
|
settings = json.RawMessage("{}")
|
|
}
|
|
|
|
c.JSON(200, gin.H{
|
|
"schema": overridableSchema,
|
|
"values": json.RawMessage(settings),
|
|
})
|
|
}
|
|
|
|
// UpdateTeamPackageSettings saves team-scoped overrides for a package.
|
|
// Non-overridable keys are stripped before saving.
|
|
// PUT /api/v1/teams/:teamId/packages/:id/settings
|
|
func (h *TeamPackageSettingsHandler) UpdateTeamPackageSettings(c *gin.Context) {
|
|
teamID := c.Param("teamId")
|
|
pkgID := c.Param("id")
|
|
|
|
pkg, err := h.stores.Packages.Get(c.Request.Context(), pkgID)
|
|
if err != nil || pkg == nil {
|
|
c.JSON(404, gin.H{"error": "package not found"})
|
|
return
|
|
}
|
|
|
|
var body struct {
|
|
Settings json.RawMessage `json:"settings" binding:"required"`
|
|
}
|
|
if err := c.ShouldBindJSON(&body); err != nil {
|
|
c.JSON(400, gin.H{"error": "invalid request body"})
|
|
return
|
|
}
|
|
|
|
// Parse and enforce user_overridable
|
|
schema := store.ParseSettingsSchema(pkg.Manifest)
|
|
var incoming map[string]any
|
|
if err := json.Unmarshal(body.Settings, &incoming); err != nil {
|
|
c.JSON(400, gin.H{"error": "settings must be a JSON object"})
|
|
return
|
|
}
|
|
|
|
filtered, rejected := store.FilterOverridableKeys(incoming, schema)
|
|
if len(filtered) == 0 && len(rejected) > 0 {
|
|
c.JSON(400, gin.H{"error": "these settings cannot be overridden: " + strings.Join(rejected, ", ")})
|
|
return
|
|
}
|
|
|
|
settingsJSON, err := json.Marshal(filtered)
|
|
if err != nil {
|
|
c.JSON(500, gin.H{"error": "failed to marshal settings"})
|
|
return
|
|
}
|
|
|
|
if err := h.stores.Packages.SetTeamSettings(c.Request.Context(), pkgID, teamID, json.RawMessage(settingsJSON)); err != nil {
|
|
c.JSON(500, gin.H{"error": "failed to save team settings"})
|
|
return
|
|
}
|
|
|
|
c.JSON(200, gin.H{"ok": true, "rejected_keys": rejected})
|
|
}
|
|
|
|
// DeleteTeamPackageSettings removes team-scoped overrides for a package.
|
|
// DELETE /api/v1/teams/:teamId/packages/:id/settings
|
|
func (h *TeamPackageSettingsHandler) DeleteTeamPackageSettings(c *gin.Context) {
|
|
teamID := c.Param("teamId")
|
|
pkgID := c.Param("id")
|
|
|
|
if err := h.stores.Packages.DeleteTeamSettings(c.Request.Context(), pkgID, teamID); err != nil {
|
|
c.JSON(500, gin.H{"error": "failed to delete team settings"})
|
|
return
|
|
}
|
|
|
|
c.JSON(200, gin.H{"ok": true})
|
|
}
|