You're Invited:Meet the Socket Team at RSAC and BSidesSF 2026, March 23–26.RSVP
Socket
Book a DemoSign in
Socket

github.com/gradientzero/comby-store-postgres

Package Overview
Dependencies
Versions
10
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

github.com/gradientzero/comby-store-postgres - go Package Compare versions

Comparing version
v1.0.2
to
v1.0.3
+121
-1
command.store.postgres_test.go

@@ -7,3 +7,3 @@ package store_test

"github.com/gradientzero/comby-store-postgres"
store "github.com/gradientzero/comby-store-postgres"
"github.com/gradientzero/comby/v2"

@@ -116,1 +116,121 @@ )

}
func TestCommandStoreEncrypted(t *testing.T) {
var err error
ctx := context.Background()
// create crypto service
key := []byte("12345678901234567890123456789012")
cryptoService, _ := comby.NewCryptoService(key)
// setup and init store
commandStore := store.NewCommandStorePostgres("localhost", 5432, "postgres", "mysecretpassword", "postgres")
if err = commandStore.Init(ctx,
comby.CommandStoreOptionWithCryptoService(cryptoService),
); err != nil {
t.Fatal(err)
}
// create domain data to encrypt/decrypt
type MyDomainCommand struct {
String string
Int int64
Boolean bool
}
domainData := &MyDomainCommand{
String: "string",
Int: 123,
Boolean: true,
}
// Create values
cmd1 := &comby.BaseCommand{
CommandUuid: comby.NewUuid(),
TenantUuid: "TenantUuid_1",
Domain: "Domain_1",
CreatedAt: 1000,
DomainCmd: domainData,
}
if err := commandStore.Create(ctx,
comby.CommandStoreCreateOptionWithCommand(cmd1),
); err != nil {
t.Fatal(err)
}
// Get a value
if _cmd1, err := commandStore.Get(ctx,
comby.CommandStoreGetOptionWithCommandUuid(cmd1.CommandUuid),
); err != nil {
t.Fatal(err)
} else {
_domainData := &MyDomainCommand{}
_domainData, _ = comby.Deserialize(_cmd1.GetDomainCmdBytes(), _domainData)
if _domainData.String != "string" {
t.Fatalf("wrong value: %q", _domainData.String)
}
if _domainData.Int != 123 {
t.Fatalf("wrong value: %q", _domainData.Int)
}
if _domainData.Boolean != true {
t.Fatalf("wrong value")
}
}
// List all commands
if cmds, _, err := commandStore.List(ctx); err == nil {
_cmd1 := cmds[0]
_domainData := &MyDomainCommand{}
_domainData, _ = comby.Deserialize(_cmd1.GetDomainCmdBytes(), _domainData)
if _domainData.String != "string" {
t.Fatalf("wrong value: %q", _domainData.String)
}
if _domainData.Int != 123 {
t.Fatalf("wrong value: %q", _domainData.Int)
}
if _domainData.Boolean != true {
t.Fatalf("wrong value")
}
}
// Update event
domainData.String = "string2"
domainData.Int = 456
domainData.Boolean = false
cmd1.DomainCmd = domainData
// Delete an event
if err := commandStore.Update(ctx,
comby.CommandStoreUpdateOptionWithCommand(cmd1),
); err != nil {
t.Fatal(err)
}
// Get a value
if _cmd1, err := commandStore.Get(ctx,
comby.CommandStoreGetOptionWithCommandUuid(cmd1.CommandUuid),
); err != nil {
t.Fatal(err)
} else {
_domainData := &MyDomainCommand{}
_domainData, _ = comby.Deserialize(_cmd1.GetDomainCmdBytes(), _domainData)
if _domainData.String != "string2" {
t.Fatalf("wrong value: %q", _domainData.String)
}
if _domainData.Int != 456 {
t.Fatalf("wrong value: %q", _domainData.Int)
}
if _domainData.Boolean != false {
t.Fatalf("wrong value")
}
}
// reset database
if err := commandStore.Reset(ctx); err != nil {
t.Fatal(err)
}
// close connection
if err := commandStore.Close(ctx); err != nil {
t.Fatalf("failed to close connection: %v", err)
}
}

@@ -6,2 +6,3 @@ package store

"database/sql"
"encoding/hex"
"fmt"

@@ -29,4 +30,4 @@

func NewCommandStorePostgres(host string, port int, user, password, dbName string) comby.CommandStore {
return &commandStorePostgres{
func NewCommandStorePostgres(host string, port int, user, password, dbName string, opts ...comby.CommandStoreOption) comby.CommandStore {
cs := &commandStorePostgres{
host: host,

@@ -38,2 +39,8 @@ port: port,

}
for _, opt := range opts {
if _, err := opt(&cs.options); err != nil {
return nil
}
}
return cs
}

@@ -143,2 +150,9 @@

// encrypt domain data if crypto service is provided
if cs.options.CryptoService != nil {
if err := cs.encryptDomainData(dbRecord); err != nil {
return err
}
}
// sql begin transaction

@@ -234,2 +248,9 @@ tx, err := cs.db.Begin()

// decrypt domain data if crypto service is provided
if cs.options.CryptoService != nil {
if err := cs.decryptDomainData(&dbRecord); err != nil {
return nil, err
}
}
// db record to command

@@ -362,2 +383,11 @@ cmd, err := internal.DbCommandToBaseCommand(&dbRecord)

// decrypt domain data if crypto service is provided
if cs.options.CryptoService != nil {
for _, dbRecord := range dbRecords {
if err := cs.decryptDomainData(dbRecord); err != nil {
return nil, 0, err
}
}
}
// convert

@@ -397,2 +427,9 @@ cmds, err := internal.DbCommandsToBaseCommands(dbRecords)

// encrypt domain data if crypto service is provided
if cs.options.CryptoService != nil {
if err := cs.encryptDomainData(dbRecord); err != nil {
return err
}
}
// sql begin transaction

@@ -413,3 +450,3 @@ tx, err := cs.db.Begin()

req_ctx=$7
) WHERE uuid=$8 LIMIT 1;`
WHERE uuid=$8;`
stmt, err := tx.Prepare(query)

@@ -534,1 +571,36 @@ if err != nil {

}
func (cs *commandStorePostgres) encryptDomainData(dbRecord *internal.Command) error {
if cs.options.CryptoService == nil {
return fmt.Errorf("'%s' failed - crypto service is nil", cs.String())
}
domainData := []byte(dbRecord.DataBytes)
if len(domainData) < 1 {
return fmt.Errorf("'%s' failed - domain data is empty", cs.String())
}
if encryptedData, err := cs.options.CryptoService.Encrypt(domainData); err != nil {
return fmt.Errorf("'%s' failed - failed to encrypt domain data: %w", cs.String(), err)
} else {
dbRecord.DataBytes = hex.EncodeToString(encryptedData)
}
return nil
}
func (cs *commandStorePostgres) decryptDomainData(dbRecord *internal.Command) error {
if cs.options.CryptoService == nil {
return fmt.Errorf("'%s' failed - crypto service is nil", cs.String())
}
encryptedData, err := hex.DecodeString(dbRecord.DataBytes)
if err != nil {
return fmt.Errorf("'%s' failed - failed to decode hex domain data: %w", cs.String(), err)
}
if len(encryptedData) < 1 {
return fmt.Errorf("'%s' failed - encrypted domain data is empty", cs.String())
}
if decryptedData, err := cs.options.CryptoService.Decrypt(encryptedData); err != nil {
return fmt.Errorf("'%s' failed - failed to decrypt domain data: %w", cs.String(), err)
} else {
dbRecord.DataBytes = string(decryptedData)
}
return nil
}

@@ -117,1 +117,121 @@ package store_test

}
func TestEventStoreWithEncrypted(t *testing.T) {
var err error
ctx := context.Background()
// create crypto service
key := []byte("12345678901234567890123456789012")
cryptoService, _ := comby.NewCryptoService(key)
// setup and init store
eventStore := store.NewEventStorePostgres("localhost", 5432, "postgres", "mysecretpassword", "postgres")
if err = eventStore.Init(ctx,
comby.EventStoreOptionWithCryptoService(cryptoService),
); err != nil {
t.Fatal(err)
}
// create domain data to encrypt/decrypt
type MyDomainEvent struct {
String string
Int int64
Boolean bool
}
domainData := &MyDomainEvent{
String: "string",
Int: 123,
Boolean: true,
}
// Create values
evt1 := &comby.BaseEvent{
EventUuid: comby.NewUuid(),
AggregateUuid: "AggregateUuid_1",
Domain: "Domain_1",
CreatedAt: 1000,
Version: 1,
DomainEvt: domainData,
}
if err := eventStore.Create(ctx,
comby.EventStoreCreateOptionWithEvent(evt1),
); err != nil {
t.Fatal(err)
}
// Get a value
if _evt1, err := eventStore.Get(ctx,
comby.EventStoreGetOptionWithEventUuid(evt1.EventUuid),
); err != nil {
t.Fatal(err)
} else {
_domainData := &MyDomainEvent{}
_domainData, _ = comby.Deserialize(_evt1.GetDomainEvtBytes(), _domainData)
if _domainData.String != "string" {
t.Fatalf("wrong value: %q", _domainData.String)
}
if _domainData.Int != 123 {
t.Fatalf("wrong value: %q", _domainData.Int)
}
if _domainData.Boolean != true {
t.Fatalf("wrong value")
}
}
// List all events
if evts, _, err := eventStore.List(ctx); err == nil {
_evt1 := evts[0]
_domainData := &MyDomainEvent{}
_domainData, _ = comby.Deserialize(_evt1.GetDomainEvtBytes(), _domainData)
if _domainData.String != "string" {
t.Fatalf("wrong value: %q", _domainData.String)
}
if _domainData.Int != 123 {
t.Fatalf("wrong value: %q", _domainData.Int)
}
if _domainData.Boolean != true {
t.Fatalf("wrong value")
}
}
// Update event
domainData.String = "string2"
domainData.Int = 456
domainData.Boolean = false
evt1.DomainEvt = domainData
if err := eventStore.Update(ctx,
comby.EventStoreUpdateOptionWithEvent(evt1),
); err != nil {
t.Fatal(err)
}
// Get a value
if _evt1, err := eventStore.Get(ctx,
comby.EventStoreGetOptionWithEventUuid(evt1.EventUuid),
); err != nil {
t.Fatal(err)
} else {
_domainData := &MyDomainEvent{}
_domainData, _ = comby.Deserialize(_evt1.GetDomainEvtBytes(), _domainData)
if _domainData.String != "string2" {
t.Fatalf("wrong value: %q", _domainData.String)
}
if _domainData.Int != 456 {
t.Fatalf("wrong value: %q", _domainData.Int)
}
if _domainData.Boolean != false {
t.Fatalf("wrong value")
}
}
// reset database
if err := eventStore.Reset(ctx); err != nil {
t.Fatal(err)
}
// close connection
if err := eventStore.Close(ctx); err != nil {
t.Fatalf("failed to close connection: %v", err)
}
}

@@ -6,2 +6,3 @@ package store

"database/sql"
"encoding/hex"
"fmt"

@@ -29,4 +30,4 @@

func NewEventStorePostgres(host string, port int, user, password, dbName string) comby.EventStore {
return &eventStorePostgres{
func NewEventStorePostgres(host string, port int, user, password, dbName string, opts ...comby.EventStoreOption) comby.EventStore {
es := &eventStorePostgres{
host: host,

@@ -38,2 +39,8 @@ port: port,

}
for _, opt := range opts {
if _, err := opt(&es.options); err != nil {
return nil
}
}
return es
}

@@ -151,2 +158,9 @@

// encrypt domain data if crypto service is provided
if es.options.CryptoService != nil {
if err := es.encryptDomainData(dbRecord); err != nil {
return err
}
}
// sql begin transaction

@@ -248,2 +262,9 @@ tx, err := es.db.Begin()

// decrypt domain data if crypto service is provided
if es.options.CryptoService != nil {
if err := es.decryptDomainData(&dbRecord); err != nil {
return nil, err
}
}
// db record to event

@@ -386,2 +407,11 @@ evt, err := internal.DbEventToBaseEvent(&dbRecord)

// decrypt domain data if crypto service is provided
if es.options.CryptoService != nil {
for _, dbRecord := range dbRecords {
if err := es.decryptDomainData(dbRecord); err != nil {
return nil, 0, err
}
}
}
// convert

@@ -422,2 +452,9 @@ evts, err := internal.DbEventsToBaseEvents(dbRecords)

// encrypt domain data if crypto service is provided
if es.options.CryptoService != nil {
if err := es.encryptDomainData(dbRecord); err != nil {
return err
}
}
// sql begin transaction

@@ -660,1 +697,36 @@ tx, err := es.db.Begin()

}
func (es *eventStorePostgres) encryptDomainData(dbRecord *internal.Event) error {
if es.options.CryptoService == nil {
return fmt.Errorf("'%s' failed - crypto service is nil", es.String())
}
domainData := []byte(dbRecord.DataBytes)
if len(domainData) < 1 {
return fmt.Errorf("'%s' failed - domain data is empty", es.String())
}
if encryptedData, err := es.options.CryptoService.Encrypt(domainData); err != nil {
return fmt.Errorf("'%s' failed - failed to encrypt domain data: %w", es.String(), err)
} else {
dbRecord.DataBytes = hex.EncodeToString(encryptedData)
}
return nil
}
func (es *eventStorePostgres) decryptDomainData(dbRecord *internal.Event) error {
if es.options.CryptoService == nil {
return fmt.Errorf("'%s' failed - crypto service is nil", es.String())
}
encryptedData, err := hex.DecodeString(dbRecord.DataBytes)
if err != nil {
return fmt.Errorf("'%s' failed - failed to decode hex domain data: %w", es.String(), err)
}
if len(encryptedData) < 1 {
return fmt.Errorf("'%s' failed - encrypted domain data is empty", es.String())
}
if decryptedData, err := es.options.CryptoService.Decrypt(encryptedData); err != nil {
return fmt.Errorf("'%s' failed - failed to decrypt domain data: %w", es.String(), err)
} else {
dbRecord.DataBytes = string(decryptedData)
}
return nil
}
+21
-1

@@ -12,2 +12,22 @@ module github.com/gradientzero/comby-store-postgres

require github.com/huandu/go-clone v1.7.2 // indirect
require (
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/huandu/go-clone v1.7.2 // indirect
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
golang.org/x/mod v0.14.0 // indirect
golang.org/x/sys v0.18.0 // indirect
golang.org/x/tools v0.17.0 // indirect
lukechampine.com/uint128 v1.2.0 // indirect
modernc.org/cc/v3 v3.40.0 // indirect
modernc.org/ccgo/v3 v3.16.13 // indirect
modernc.org/libc v1.29.0 // indirect
modernc.org/mathutil v1.6.0 // indirect
modernc.org/memory v1.7.2 // indirect
modernc.org/opt v0.1.3 // indirect
modernc.org/sqlite v1.28.0 // indirect
modernc.org/strutil v1.1.3 // indirect
modernc.org/token v1.0.1 // indirect
)