mirror of
https://github.com/Dvorinka/MyClubServer.git
synced 2026-06-03 18:22:57 +00:00
125 lines
3.5 KiB
Go
125 lines
3.5 KiB
Go
package controllers
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
)
|
|
|
|
// StyleValidator validates and normalizes style objects before saving
|
|
type StyleValidator struct{}
|
|
|
|
// ValidateAndNormalizeStyles ensures style data is properly structured
|
|
func (sv *StyleValidator) ValidateAndNormalizeStyles(settings map[string]interface{}) error {
|
|
if settings == nil {
|
|
return nil
|
|
}
|
|
|
|
// If styles exist as a top-level key, ensure it's a valid object
|
|
if stylesRaw, exists := settings["styles"]; exists {
|
|
switch styles := stylesRaw.(type) {
|
|
case map[string]interface{}:
|
|
// Valid object - ensure all values are valid CSS values
|
|
for key, val := range styles {
|
|
if !sv.isValidCSSValue(val) {
|
|
return fmt.Errorf("invalid CSS value for property '%s': %v", key, val)
|
|
}
|
|
}
|
|
case string:
|
|
// Try to parse as JSON
|
|
var styleMap map[string]interface{}
|
|
if err := json.Unmarshal([]byte(styles), &styleMap); err != nil {
|
|
return fmt.Errorf("styles must be a valid JSON object or map")
|
|
}
|
|
// Replace with parsed object
|
|
settings["styles"] = styleMap
|
|
default:
|
|
return fmt.Errorf("styles must be an object, got %T", styles)
|
|
}
|
|
}
|
|
|
|
// Validate customCSS if present
|
|
if customCSS, exists := settings["customCSS"]; exists {
|
|
if _, ok := customCSS.(string); !ok {
|
|
return fmt.Errorf("customCSS must be a string, got %T", customCSS)
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// isValidCSSValue checks if a value is a valid CSS value type
|
|
func (sv *StyleValidator) isValidCSSValue(val interface{}) bool {
|
|
switch val.(type) {
|
|
case string, int, int64, float64, bool:
|
|
return true
|
|
default:
|
|
return false
|
|
}
|
|
}
|
|
|
|
// MergeStyles merges new styles into existing settings preserving other fields
|
|
func (sv *StyleValidator) MergeStyles(existingSettings map[string]interface{}, newStyles map[string]interface{}) map[string]interface{} {
|
|
if existingSettings == nil {
|
|
existingSettings = make(map[string]interface{})
|
|
}
|
|
|
|
// If newStyles contains a "styles" key, merge it
|
|
if newStylesMap, exists := newStyles["styles"]; exists {
|
|
if existingStylesRaw, exists := existingSettings["styles"]; exists {
|
|
// Merge with existing styles
|
|
if existingStyles, ok := existingStylesRaw.(map[string]interface{}); ok {
|
|
if newStylesObj, ok := newStylesMap.(map[string]interface{}); ok {
|
|
// Merge newStylesObj into existingStyles
|
|
for k, v := range newStylesObj {
|
|
existingStyles[k] = v
|
|
}
|
|
existingSettings["styles"] = existingStyles
|
|
} else {
|
|
// Replace entirely if type mismatch
|
|
existingSettings["styles"] = newStylesMap
|
|
}
|
|
} else {
|
|
// Replace if existing was not a map
|
|
existingSettings["styles"] = newStylesMap
|
|
}
|
|
} else {
|
|
// No existing styles - set directly
|
|
existingSettings["styles"] = newStyles["styles"]
|
|
}
|
|
}
|
|
|
|
// Merge other top-level keys
|
|
for k, v := range newStyles {
|
|
if k != "styles" {
|
|
existingSettings[k] = v
|
|
}
|
|
}
|
|
|
|
return existingSettings
|
|
}
|
|
|
|
// ExtractStylesForSave prepares settings object for database save
|
|
// Ensures styles are properly nested under settings.styles
|
|
func (sv *StyleValidator) ExtractStylesForSave(input map[string]interface{}) map[string]interface{} {
|
|
settings := make(map[string]interface{})
|
|
|
|
// Copy all non-style fields
|
|
for k, v := range input {
|
|
if k != "styles" && k != "customCSS" {
|
|
settings[k] = v
|
|
}
|
|
}
|
|
|
|
// Nest styles under styles key
|
|
if stylesRaw, exists := input["styles"]; exists {
|
|
settings["styles"] = stylesRaw
|
|
}
|
|
|
|
// Also nest customCSS if present
|
|
if customCSS, exists := input["customCSS"]; exists {
|
|
settings["customCSS"] = customCSS
|
|
}
|
|
|
|
return settings
|
|
}
|