Files
aura-crm/production/backend/internal/featuremodules/handler.go
T

78 lines
2.2 KiB
Go

package featuremodules
import (
"context"
"log"
"production/internal/auth"
"github.com/gofiber/fiber/v2"
"github.com/jackc/pgx/v5/pgxpool"
)
type Handler struct {
db *pgxpool.Pool
}
func NewHandler(db *pgxpool.Pool) *Handler {
return &Handler{db: db}
}
type moduleRow struct {
Key string `json:"key"`
Enabled bool `json:"enabled"`
}
// List is reachable by any authenticated staff (nav-building needs it on
// every login), unlike Set which is gated to the "settings" permission at
// the route level in main.go.
func (h *Handler) List(c *fiber.Ctx) error {
rows, err := h.db.Query(context.Background(), `SELECT key, enabled FROM feature_modules ORDER BY key`)
if err != nil {
log.Printf("featuremodules: list failed: %v", err)
return c.Status(500).JSON(fiber.Map{"error": "internal error"})
}
defer rows.Close()
modules := []moduleRow{}
for rows.Next() {
var m moduleRow
if err := rows.Scan(&m.Key, &m.Enabled); err != nil {
log.Printf("featuremodules: scan failed: %v", err)
return c.Status(500).JSON(fiber.Map{"error": "internal error"})
}
modules = append(modules, m)
}
return c.JSON(modules)
}
// Set toggles one module. Unknown keys 400 rather than silently no-op-ing
// (INSERT ... ON CONFLICT would let a typo'd key from a stale frontend
// build create a phantom row nothing ever reads) — see isValidKey's
// Go-side allowlist.
func (h *Handler) Set(c *fiber.Ctx) error {
key := c.Params("key")
if !isValidKey(key) {
return c.Status(400).JSON(fiber.Map{"error": "unknown module key"})
}
var body struct {
Enabled *bool `json:"enabled"`
}
if err := c.BodyParser(&body); err != nil || body.Enabled == nil {
return c.Status(400).JSON(fiber.Map{"error": "enabled is required"})
}
tag, err := h.db.Exec(context.Background(),
`UPDATE feature_modules SET enabled = $1, updated_at = NOW(), updated_by_staff_name = $2 WHERE key = $3`,
*body.Enabled, auth.StaffName(c), key)
if err != nil {
log.Printf("featuremodules: set failed: %v", err)
return c.Status(500).JSON(fiber.Map{"error": "internal error"})
}
if tag.RowsAffected() == 0 {
return c.Status(404).JSON(fiber.Map{"error": "module not found"})
}
return h.List(c)
}