Public source validation / validate (push) Failing after 3m8s
87 lines
2.3 KiB
Go
87 lines
2.3 KiB
Go
package dashboard
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"regexp"
|
|
)
|
|
|
|
const CurrentSchemaVersion = 2
|
|
|
|
var slugPattern = regexp.MustCompile("^[a-z0-9]+(?:-[a-z0-9]+)*$")
|
|
|
|
type Document map[string]any
|
|
|
|
func Validate(document Document) error {
|
|
if document == nil {
|
|
return errors.New("dashboard document is required")
|
|
}
|
|
if version, ok := number(document["schemaVersion"]); !ok || version < 1 || version > CurrentSchemaVersion {
|
|
return errors.New("unsupported dashboard schema version")
|
|
}
|
|
for _, field := range []string{"id", "slug", "name", "scope", "variables", "widgets", "settings"} {
|
|
if _, ok := document[field]; !ok {
|
|
return fmt.Errorf("dashboard field %q is required", field)
|
|
}
|
|
}
|
|
slug, ok := document["slug"].(string)
|
|
if !ok || !slugPattern.MatchString(slug) || len(slug) > 80 {
|
|
return errors.New("invalid dashboard slug")
|
|
}
|
|
name, ok := document["name"].(string)
|
|
if !ok || name == "" || len(name) > 120 {
|
|
return errors.New("invalid dashboard name")
|
|
}
|
|
scope, ok := document["scope"].(string)
|
|
if !ok || scope != "personal" && scope != "shared" && scope != "system" {
|
|
return errors.New("invalid dashboard scope")
|
|
}
|
|
if _, ok := document["widgets"].([]any); !ok {
|
|
return errors.New("dashboard widgets must be an array")
|
|
}
|
|
if _, ok := document["variables"].([]any); !ok {
|
|
return errors.New("dashboard variables must be an array")
|
|
}
|
|
if _, ok := document["settings"].(map[string]any); !ok {
|
|
return errors.New("dashboard settings must be an object")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func Migrate(document Document) (Document, error) {
|
|
if err := Validate(document); err != nil {
|
|
return nil, err
|
|
}
|
|
version, _ := number(document["schemaVersion"])
|
|
if version == CurrentSchemaVersion {
|
|
return clone(document), nil
|
|
}
|
|
migrated := clone(document)
|
|
migrated["schemaVersion"] = CurrentSchemaVersion
|
|
settings := migrated["settings"].(map[string]any)
|
|
if _, ok := settings["live"]; !ok {
|
|
settings["live"] = false
|
|
}
|
|
if _, ok := settings["refreshSeconds"]; !ok {
|
|
settings["refreshSeconds"] = 30
|
|
}
|
|
return migrated, nil
|
|
}
|
|
func clone(document Document) Document {
|
|
encoded, _ := json.Marshal(document)
|
|
var result Document
|
|
_ = json.Unmarshal(encoded, &result)
|
|
return result
|
|
}
|
|
func number(value any) (int, bool) {
|
|
switch v := value.(type) {
|
|
case int:
|
|
return v, true
|
|
case float64:
|
|
return int(v), v == float64(int(v))
|
|
default:
|
|
return 0, false
|
|
}
|
|
}
|