schema: hardcode handle "d" tag automatically.

This commit is contained in:
fiatjaf
2025-11-23 13:41:16 -03:00
parent e4babdd2bf
commit 18887727d1

View File

@@ -73,7 +73,7 @@ type Validator struct {
Schema Schema Schema Schema
FailOnUnknownKind bool FailOnUnknownKind bool
FailOnUnknownType bool FailOnUnknownType bool
TypeValidators map[string]func(string, *nextSpec) error TypeValidators map[string]func(value string, spec *nextSpec) error
UnknownTypes []string UnknownTypes []string
} }
@@ -92,7 +92,7 @@ func NewValidatorFromBytes(schemaData []byte) (Validator, error) {
func NewValidatorFromSchema(sch Schema) Validator { func NewValidatorFromSchema(sch Schema) Validator {
validator := Validator{ validator := Validator{
Schema: sch, Schema: sch,
TypeValidators: map[string]func(string, *nextSpec) error{ TypeValidators: map[string]func(value string, spec *nextSpec) error{
"id": func(value string, spec *nextSpec) error { "id": func(value string, spec *nextSpec) error {
if len(value) != 64 { if len(value) != 64 {
return fmt.Errorf("needed 64 hex chars") return fmt.Errorf("needed 64 hex chars")
@@ -159,6 +159,12 @@ func NewValidatorFromSchema(sch Schema) Validator {
} }
return fmt.Errorf("not a space-separated keyval") return fmt.Errorf("not a space-separated keyval")
}, },
"empty": func(value string, spec *nextSpec) error {
if len(value) > 0 {
return fmt.Errorf("not empty")
}
return nil
},
"free": func(value string, spec *nextSpec) error { "free": func(value string, spec *nextSpec) error {
return nil // accepts anything return nil // accepts anything
}, },
@@ -187,13 +193,14 @@ func NewValidatorFromURL(schemaURL string) (Validator, error) {
} }
var ( var (
ErrUnknownContent = fmt.Errorf("unknown content") ErrUnknownContent = fmt.Errorf("unknown content")
ErrUnknownKind = fmt.Errorf("unknown kind") ErrUnknownKind = fmt.Errorf("unknown kind")
ErrInvalidJson = fmt.Errorf("invalid json") ErrInvalidJson = fmt.Errorf("invalid json")
ErrEmptyValue = fmt.Errorf("can't be empty") ErrEmptyValue = fmt.Errorf("can't be empty")
ErrEmptyTag = fmt.Errorf("empty tag") ErrEmptyTag = fmt.Errorf("empty tag")
ErrUnknownTagType = fmt.Errorf("unknown tag type") ErrDTagInNonAddressable = fmt.Errorf("non-addressable event can't have a 'd' tag")
ErrDanglingSpace = fmt.Errorf("value has dangling space") ErrUnknownTagType = fmt.Errorf("unknown tag type")
ErrDanglingSpace = fmt.Errorf("value has dangling space")
) )
type UnknownTypes struct { type UnknownTypes struct {
@@ -251,12 +258,23 @@ func (v *Validator) ValidateEvent(evt nostr.Event) error {
requiredTags = append(requiredTags, sch.Required...) requiredTags = append(requiredTags, sch.Required...)
} }
needsD := evt.Kind.IsAddressable()
tags: tags:
for ti, tag := range evt.Tags { for ti, tag := range evt.Tags {
if len(tag) == 0 { if len(tag) == 0 {
return ErrEmptyTag return ErrEmptyTag
} }
// if this is a "d" tag in an addressable event, just handle it here
if tag[0] == "d" {
if evt.Kind.IsAddressable() {
needsD = false
} else {
return ErrDTagInNonAddressable
}
}
if requiredTags != nil { if requiredTags != nil {
// swap-delete this from the list of requirements // swap-delete this from the list of requirements
if idx := slices.Index(requiredTags, tag[0]); idx != -1 { if idx := slices.Index(requiredTags, tag[0]); idx != -1 {
@@ -302,6 +320,10 @@ func (v *Validator) ValidateEvent(evt nostr.Event) error {
if len(requiredTags) > 0 { if len(requiredTags) > 0 {
return RequiredTagError{requiredTags} return RequiredTagError{requiredTags}
} }
if needsD {
return RequiredTagError{Missing: []string{"d"}}
}
} }
if v.FailOnUnknownKind { if v.FailOnUnknownKind {