Files
descrybe/apps/api/internal/company/settings.go
T
greeneclipse 8580c996c3 Initial commit of Descrybe v2 without local scratch artifacts.
Drop one-shot tmp/axe scripts and agent i18n scratch so the Gitea tree is deployable.
2026-08-09 22:47:43 +02:00

58 lines
1.5 KiB
Go

package company
import (
"fmt"
"strings"
)
// Well-known tenant company_settings.settings JSON keys (migrator domain fields).
// Do not invent preference keys here — extend only when a real product key exists.
const (
SettingsKeyLanguage = "language"
SettingsKeyMergeProducts = "merge_products"
)
// AllowedSettingsKeys is the allowlist for PUT /api/company/settings mass-assignment guard.
func AllowedSettingsKeys() map[string]struct{} {
return map[string]struct{}{
SettingsKeyLanguage: {},
SettingsKeyMergeProducts: {},
}
}
func isAllowedSettingsKey(key string) bool {
_, ok := AllowedSettingsKeys()[key]
return ok
}
// ValidateSettingsMap rejects unknown keys and mistyped values for the settings bag.
// nil / empty maps are valid (clear or no-op payload).
func ValidateSettingsMap(settings map[string]any) error {
if len(settings) == 0 {
return nil
}
for k, v := range settings {
if strings.TrimSpace(k) == "" || strings.ContainsAny(k, " \t\n\r") || k != strings.TrimSpace(k) {
return fmt.Errorf("unknown settings key")
}
if !isAllowedSettingsKey(k) {
return fmt.Errorf("unknown settings key")
}
switch k {
case SettingsKeyLanguage:
raw, ok := v.(string)
if !ok {
return fmt.Errorf("invalid language")
}
if _, err := ParseLanguage(raw, false); err != nil {
return fmt.Errorf("unsupported language")
}
case SettingsKeyMergeProducts:
if _, ok := v.(bool); !ok {
return fmt.Errorf("invalid merge_products")
}
}
}
return nil
}