78 lines
2.2 KiB
Go
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)
|
|
}
|