Skip to content

Commit

Permalink
Add check for spaces in collection names
Browse files Browse the repository at this point in the history
  • Loading branch information
totemcaf committed Jun 7, 2023
1 parent c1df202 commit 337e2a3
Show file tree
Hide file tree
Showing 6 changed files with 122 additions and 12 deletions.
15 changes: 8 additions & 7 deletions eventstore/mongodb_v2/eventstore.go
Expand Up @@ -24,6 +24,7 @@ import (
"io"
"time"

"github.com/looplab/eventhorizon/mongoutils"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
Expand Down Expand Up @@ -192,14 +193,14 @@ func WithEventHandlerInTX(h eh.EventHandler) Option {
// Will return an error if provided parameters are equal.
func WithCollectionNames(eventsColl, streamsColl string) Option {
return func(s *EventStore) error {
if eventsColl == streamsColl {
if err := mongoutils.CheckCollectionName(eventsColl); err != nil {
return fmt.Errorf("events collection: %w", err)
} else if err := mongoutils.CheckCollectionName(streamsColl); err != nil {
return fmt.Errorf("streams collection: %w", err)
} else if eventsColl == streamsColl {
return fmt.Errorf("custom collection names are equal")
}

if eventsColl == "" || streamsColl == "" {
return fmt.Errorf("missing collection name")
}

db := s.events.Database()
s.events = db.Collection(eventsColl)
s.streams = db.Collection(streamsColl)
Expand All @@ -211,8 +212,8 @@ func WithCollectionNames(eventsColl, streamsColl string) Option {
// WithSnapshotCollectionName uses different collections from the default "snapshots" collections.
func WithSnapshotCollectionName(snapshotColl string) Option {
return func(s *EventStore) error {
if snapshotColl == "" {
return fmt.Errorf("missing collection name")
if err := mongoutils.CheckCollectionName(snapshotColl); err != nil {
return fmt.Errorf("snapshot collection: %w", err)
}

db := s.events.Database()
Expand Down
28 changes: 25 additions & 3 deletions eventstore/mongodb_v2/eventstore_test.go
Expand Up @@ -112,15 +112,29 @@ func TestWithCollectionNamesIntegration(t *testing.T) {
_, err = NewEventStore(url, db,
WithCollectionNames("", "my-collection"),
)
if err == nil || err.Error() != "error while applying option: missing collection name" {
if err == nil || err.Error() != "error while applying option: events collection: missing collection name" {
t.Fatal("there should be an error")
}

// providing empty collection names should result in an error
_, err = NewEventStore(url, db,
WithCollectionNames("my-collection", ""),
)
if err == nil || err.Error() != "error while applying option: missing collection name" {
if err == nil || err.Error() != "error while applying option: streams collection: missing collection name" {
t.Fatal("there should be an error")
}
// providing invalid streams collection names should result in an error
_, err = NewEventStore(url, db,
WithCollectionNames("my-collection", "name with spaces"),
)
if err == nil || err.Error() != "error while applying option: streams collection: invalid char in collection name (space)" {
t.Fatal("there should be an error")
}
// providing invalid events collection names should result in an error
_, err = NewEventStore(url, db,
WithCollectionNames("my collection", "a-good-name"),
)
if err == nil || err.Error() != "error while applying option: events collection: invalid char in collection name (space)" {
t.Fatal("there should be an error")
}
}
Expand Down Expand Up @@ -155,7 +169,15 @@ func TestWithSnapshotCollectionNamesIntegration(t *testing.T) {
_, err = NewEventStore(url, db,
WithSnapshotCollectionName(""),
)
if err == nil || err.Error() != "error while applying option: missing collection name" {
if err == nil || err.Error() != "error while applying option: snapshot collection: missing collection name" {
t.Fatal("there should be an error")
}

// providing invalid snapshot collection names should result in an error
_, err = NewEventStore(url, db,
WithSnapshotCollectionName("no space-allowed"),
)
if err == nil || err.Error() != "error while applying option: snapshot collection: invalid char in collection name (space)" {
t.Fatal("there should be an error")
}
}
Expand Down
22 changes: 22 additions & 0 deletions mongoutils/checks.go
@@ -0,0 +1,22 @@
package mongoutils

import (
"errors"
"strings"
)

var (
ErrMissingCollectionName = errors.New("missing collection name")
ErrInvalidCharInCollectionName = errors.New("invalid char in collection name (space)")
)

// CheckCollectionName checks if a collection name is valid for mongodb.
// We only check on spaces because they are hard to see by humans.
func CheckCollectionName(name string) error {
if name == "" {
return ErrMissingCollectionName
} else if strings.ContainsAny(name, " ") {
return ErrInvalidCharInCollectionName
}
return nil
}
45 changes: 45 additions & 0 deletions mongoutils/checks_test.go
@@ -0,0 +1,45 @@
package mongoutils

import (
"testing"
)

func TestCheckValidCollectionName(t *testing.T) {
type args struct {
name string
}
tests := []struct {
name string
args args
wantErr bool
}{
{
"empty name",
args{
name: "",
},
true,
},
{
"valid name",
args{
name: "valid",
},
false,
},
{
"with spaces",
args{
name: "invalid name",
},
true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if err := CheckCollectionName(tt.args.name); (err != nil) != tt.wantErr {
t.Errorf("CheckCollectionName() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}
5 changes: 3 additions & 2 deletions outbox/mongodb/outbox.go
Expand Up @@ -9,6 +9,7 @@ import (
"time"

bsonCodec "github.com/looplab/eventhorizon/codec/bson"
"github.com/looplab/eventhorizon/mongoutils"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/mongo"
Expand Down Expand Up @@ -130,8 +131,8 @@ func WithWatchToken(token string) Option {
// WithCollectionName uses different collections from the default "outbox" collection.
func WithCollectionName(outboxColl string) Option {
return func(s *Outbox) error {
if outboxColl == "" {
return fmt.Errorf("missing collection name")
if err := mongoutils.CheckCollectionName(outboxColl); err != nil {
return fmt.Errorf("outbox collection: %w", err)
}

s.outbox = s.outbox.Database().Collection(outboxColl)
Expand Down
19 changes: 19 additions & 0 deletions outbox/mongodb/outbox_test.go
Expand Up @@ -78,6 +78,25 @@ func TestWithCollectionNameIntegration(t *testing.T) {
}
}

func TestWithCollectionNameInvalidNames(t *testing.T) {
if testing.Short() {
t.Skip("skipping integration test")
}

url, db := makeDB(t)

nameWithSpaces := "foo outbox"
_, err := NewOutbox(url, db, WithCollectionName(nameWithSpaces))
if err == nil || err.Error() != "error while applying option: outbox collection: invalid char in collection name (space)" {
t.Fatal("there should be an error")
}

_, err = NewOutbox(url, db, WithCollectionName(""))
if err == nil || err.Error() != "error while applying option: outbox collection: missing collection name" {
t.Fatal("there should be an error")
}
}

func makeDB(t *testing.T) (string, string) {
// Use MongoDB in Docker with fallback to localhost.
url := os.Getenv("MONGODB_ADDR")
Expand Down

0 comments on commit 337e2a3

Please sign in to comment.