diff --git a/header.go b/header.go index d32ea2c..468f30f 100644 --- a/header.go +++ b/header.go @@ -23,7 +23,7 @@ import ( const ( // Version is semantic version. - Version = "0.2.18" + Version = "0.3.0" // TokenTypeJwt is the JWT token type supported JWT tokens // encoded and decoded by this library diff --git a/imports.go b/imports.go index b41f700..8a0f0c9 100644 --- a/imports.go +++ b/imports.go @@ -120,7 +120,14 @@ type Imports []*Import // Validate checks if an import is valid for the wrapping account func (i *Imports) Validate(acctPubKey string, vr *ValidationResults) { + toSet := make(map[Subject]bool, len(*i)) for _, v := range *i { + if v.Type == Service { + if _, ok := toSet[v.To]; ok { + vr.AddError("Duplicate To subjects for %q", v.To) + } + toSet[v.To] = true + } v.Validate(acctPubKey, vr) } } diff --git a/imports_test.go b/imports_test.go index 8a9bd3a..a08bcb0 100644 --- a/imports_test.go +++ b/imports_test.go @@ -348,3 +348,32 @@ func TestImportSubjectValidation(t *testing.T) { t.Errorf("imports with valid contains subject should be valid") } } + +func TestImportServiceDoubleToSubjectsValidation(t *testing.T) { + akp := createAccountNKey(t) + akp2 := createAccountNKey(t) + apk := publicKey(akp, t) + apk2 := publicKey(akp2, t) + + account := NewAccountClaims(apk) + + i := &Import{Subject: "one.two", Account: apk2, To: "foo.bar", Type: Service} + account.Imports.Add(i) + + vr := CreateValidationResults() + account.Validate(vr) + + if vr.IsBlocking(true) { + t.Fatalf("Expected no blocking validation errors") + } + + i2 := &Import{Subject: "two.three", Account: apk2, To: "foo.bar", Type: Service} + account.Imports.Add(i2) + + vr = CreateValidationResults() + account.Validate(vr) + + if !vr.IsBlocking(true) { + t.Fatalf("Expected multiple import 'to' subjects to produce an error") + } +}