Enforce durable enemy event validation

This commit is contained in:
2026-08-09 02:03:27 +00:00
parent b3644abc0e
commit 82ffe85f2d
12 changed files with 313 additions and 28 deletions

View File

@@ -5,11 +5,14 @@ import (
"embed"
"encoding/json"
"fmt"
"strings"
"gitea.maximumdirect.net/eric/notarius/internal/core/source"
"gitea.maximumdirect.net/eric/notarius/internal/framework/contracts"
"gitea.maximumdirect.net/eric/notarius/internal/modules/dnd"
"gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/codec/candidatejson"
"gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/codec/sourcerange"
enemyeventmodel "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/enemyevents"
)
const (
@@ -51,7 +54,7 @@ func (c *Codec) Metadata(value dnd.EnemyEventList) map[string]any {
}
func (c *Codec) Encode(value dnd.EnemyEventList) ([]byte, error) {
if err := validateRequiredValueFields(value); err != nil {
if err := validate(value); err != nil {
return nil, fmt.Errorf("encode dnd enemy event list: %w", err)
}
return c.EncodeCandidate(value)
@@ -71,6 +74,9 @@ func (c *Codec) Decode(content []byte) (dnd.EnemyEventList, error) {
if err := validateRequiredJSONFields(content); err != nil {
return dnd.EnemyEventList{}, fmt.Errorf("decode dnd enemy event list: %w", err)
}
if err := validate(value); err != nil {
return dnd.EnemyEventList{}, fmt.Errorf("decode dnd enemy event list: %w", err)
}
return value, nil
}
@@ -84,13 +90,29 @@ func (c *Codec) DecodeCandidate(content []byte) (dnd.EnemyEventList, error) {
return cloneList(value), nil
}
func validateRequiredValueFields(value dnd.EnemyEventList) error {
func validate(value dnd.EnemyEventList) error {
if value.Events == nil {
return fmt.Errorf("events must be present")
}
for index, event := range value.Events {
if event.SourceRefs == nil {
return fmt.Errorf("events[%d].source_refs must be present", index)
prefix := fmt.Sprintf("events[%d]", index)
if strings.TrimSpace(event.Name) == "" {
return fmt.Errorf("%s.name must not be empty", prefix)
}
if !enemyeventmodel.SupportedKind(event.Kind) {
return fmt.Errorf("%s.kind must be supported", prefix)
}
if len(event.SourceRefs) == 0 {
return fmt.Errorf("%s.source_refs must contain at least one reference", prefix)
}
for refIndex, ref := range event.SourceRefs {
refPrefix := fmt.Sprintf("%s.source_refs[%d]", prefix, refIndex)
if strings.TrimSpace(ref.SourceID) == "" {
return fmt.Errorf("%s.source_id must not be empty", refPrefix)
}
if err := sourcerange.Validate(ref); err != nil {
return fmt.Errorf("%s: %w", refPrefix, err)
}
}
}
return nil
@@ -176,7 +198,8 @@ func cloneList(value dnd.EnemyEventList) dnd.EnemyEventList {
for index, event := range value.Events {
cloned.Events[index] = event
if event.SourceRefs != nil {
cloned.Events[index].SourceRefs = append([]source.SourceRef(nil), event.SourceRefs...)
cloned.Events[index].SourceRefs = make([]source.SourceRef, len(event.SourceRefs))
copy(cloned.Events[index].SourceRefs, event.SourceRefs)
}
}
return cloned