Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,16 @@ mock/mock_jetstream.go:

mockgen: mock/mock_jetstream.go

test:
test: lint test-only

test-only:
go test ./ -v --cover -timeout 60s

.PHONY: test
lint: check-cognitive-complexity
golangci-lint run --print-issued-lines=false --exclude-use-default=false --enable=revive --enable=goimports --enable=unconvert --fix --enable=gosec --timeout=10m

check-cognitive-complexity:
find . -type f -name '*.go' -not -name "*.pb.go" -not -name "mock*.go" -not -name "*_test.go" \
-exec gocognit -over 15 {} +

.PHONY: test test-only lint check-cognitive-complexity mockgen
82 changes: 79 additions & 3 deletions event_message.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package ferstream

import (
"time"

"github.com/kumparan/go-utils"
"google.golang.org/protobuf/proto"

Expand All @@ -27,6 +29,22 @@ type (
Error error `json:"error"`
}

// NatsEventAuditLogMessage :nodoc:
NatsEventAuditLogMessage struct {
Subject string `json:"subject"` // empty on publish
ServiceName string `json:"service_name"`
UserID int64 `json:"user_id"`
AuditableType string `json:"auditable_type"`
AuditableID string `json:"auditable_id"`
Action string `json:"action"`
AuditedChanges string `json:"audited_changes"`
OldData string `json:"old_data,omitempty"`
NewData string `json:"new_data,omitempty"`
CreatedAt time.Time `json:"created_at"`
Error error `json:"error"`
}

// MessageParser :nodoc:
MessageParser interface {
ParseFromBytes(data []byte) error
AddSubject(subj string)
Expand Down Expand Up @@ -91,7 +109,7 @@ func (n *NatsEventMessage) Build() (data []byte, err error) {
return nil, n.Error
}

message, err := tapao.Marshal(n)
message, err := tapao.Marshal(n, tapao.With(tapao.JSON))
if err != nil {
n.wrapError(err)
return nil, n.Error
Expand Down Expand Up @@ -148,15 +166,17 @@ func (n *NatsEventMessage) wrapError(err error) {
n.Error = err
}

// ParseFromBytes :nodoc:
func (n *NatsEventMessage) ParseFromBytes(data []byte) (err error) {
err = tapao.Unmarshal(data, &n, tapao.FallbackWith(tapao.JSON))
err = tapao.Unmarshal(data, &n, tapao.With(tapao.JSON))
if err != nil {
n.Error = errors.Wrap(n.Error, err.Error())
return err
}
return
}

// AddSubject :nodoc:
func (n *NatsEventMessage) AddSubject(subj string) {
n.NatsEvent.Subject = subj
}
Expand All @@ -172,9 +192,65 @@ func (n *NatsEventMessage) ToJSONByte() ([]byte, error) {
return tapao.Marshal(n, tapao.With(tapao.JSON))
}

// ParseJSON parse JSON into message
// Build :nodoc:
func (n *NatsEventAuditLogMessage) Build() (data []byte, err error) {
if n.Error != nil {
return nil, n.Error
}

message, err := tapao.Marshal(n, tapao.With(tapao.JSON))
if err != nil {
n.wrapError(err)
return nil, n.Error
}

return message, nil
}

// ParseFromBytes :nodoc:
func (n *NatsEventAuditLogMessage) ParseFromBytes(data []byte) (err error) {
err = tapao.Unmarshal(data, &n, tapao.With(tapao.JSON))
if err != nil {
n.Error = errors.Wrap(n.Error, err.Error())
return err
}
return
}

// AddSubject :nodoc:
func (n *NatsEventAuditLogMessage) AddSubject(subj string) {
n.Subject = subj
}

// ToJSONString marshal message to JSON string
func (n *NatsEventAuditLogMessage) ToJSONString() (string, error) {
bt, err := tapao.Marshal(n, tapao.With(tapao.JSON))
return string(bt), err
}

// ToJSONByte marshal message to JSON byte
func (n *NatsEventAuditLogMessage) ToJSONByte() ([]byte, error) {
return tapao.Marshal(n, tapao.With(tapao.JSON))
}

func (n *NatsEventAuditLogMessage) wrapError(err error) {
if n.Error != nil {
n.Error = errors.Wrap(n.Error, err.Error())
return
}
n.Error = err
}

// ParseJSON parse JSON into Nats event message
func ParseJSON(in string) (*NatsEventMessage, error) {
msg := &NatsEventMessage{}
err := tapao.Unmarshal([]byte(in), msg, tapao.With(tapao.JSON))
return msg, err
}

// ParseNatsEventAuditLogMessageFromBytes :nodoc:
func ParseNatsEventAuditLogMessageFromBytes(in []byte) (*NatsEventAuditLogMessage, error) {
msg := &NatsEventAuditLogMessage{}
err := tapao.Unmarshal(in, msg, tapao.With(tapao.JSON))
return msg, err
}
196 changes: 191 additions & 5 deletions event_message_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package ferstream

import (
"encoding/json"
"testing"
"time"

Expand Down Expand Up @@ -83,7 +84,7 @@ func TestNatsEventMessage_WithRequest(t *testing.T) {
assert.NoError(t, result.Error)

var requestResult pb.FindByIDRequest
err := tapao.Unmarshal(result.Request, &requestResult, tapao.FallbackWith(tapao.Protobuf))
err := tapao.Unmarshal(result.Request, &requestResult, tapao.With(tapao.Protobuf))
assert.NoError(t, err)
assert.Equal(t, body.Id, requestResult.GetId())
}
Expand Down Expand Up @@ -113,14 +114,14 @@ func TestNatsEventMessage_Build(t *testing.T) {
assert.NotNil(t, message)

var result NatsEventMessage
err = tapao.Unmarshal(message, &result, tapao.FallbackWith(tapao.JSON))
err = tapao.Unmarshal(message, &result, tapao.With(tapao.JSON))
assert.NoError(t, err)
assert.Equal(t, event.ID, result.NatsEvent.ID)
assert.Equal(t, event.UserID, result.NatsEvent.UserID)
assert.Equal(t, utils.Dump(body), result.Body)

var requestResult pb.Greeting
err = tapao.Unmarshal(result.Request, &requestResult, tapao.FallbackWith(tapao.Protobuf))
err = tapao.Unmarshal(result.Request, &requestResult, tapao.With(tapao.Protobuf))
assert.NoError(t, err)
assert.Equal(t, req.Id, requestResult.Id)
assert.Equal(t, req.Name, requestResult.Name)
Expand All @@ -139,15 +140,15 @@ func TestNatsEventMessage_Build(t *testing.T) {
assert.NotNil(t, message)

var result NatsEventMessage
err = tapao.Unmarshal(message, &result, tapao.FallbackWith(tapao.JSON))
err = tapao.Unmarshal(message, &result, tapao.With(tapao.JSON))
assert.NoError(t, err)
assert.Equal(t, event.ID, result.NatsEvent.ID)
assert.Equal(t, event.UserID, result.NatsEvent.UserID)
assert.Equal(t, utils.Dump(body), result.Body)
assert.Equal(t, utils.Dump(oldBody), result.OldBody)

var requestResult pb.Greeting
err = tapao.Unmarshal(result.Request, &requestResult, tapao.FallbackWith(tapao.Protobuf))
err = tapao.Unmarshal(result.Request, &requestResult, tapao.With(tapao.Protobuf))
assert.NoError(t, err)
assert.Equal(t, req.Id, requestResult.Id)
assert.Equal(t, req.Name, requestResult.Name)
Expand Down Expand Up @@ -249,3 +250,188 @@ func TestNatsEventMessage_ParseJSON(t *testing.T) {

assert.Equal(t, msg, parsed)
}

func TestNatsEventAuditLogMessage_Build(t *testing.T) {
type User struct {
ID int64 `json:"id"`
Name string `json:"name"`
}

oldData := User{
ID: int64(123),
Name: "test name",
}

newData := User{
ID: int64(123),
Name: "new test name",
}

byteOldData, err := json.Marshal(oldData)
require.NoError(t, err)
byteNewData, err := json.Marshal(newData)
require.NoError(t, err)

createdAt, err := time.Parse("2006-01-02", "2020-01-29")
require.NoError(t, err)

t.Run("success", func(t *testing.T) {
msg := &NatsEventAuditLogMessage{
ServiceName: "test-audit",
UserID: 123,
AuditableType: "user",
AuditableID: "123",
Action: "update",
AuditedChanges: string(byteNewData),
OldData: string(byteOldData),
NewData: string(byteNewData),
CreatedAt: createdAt,
Error: nil,
}

msgByte, err := msg.Build()
require.NoError(t, err)
assert.NotNil(t, msgByte)

var result NatsEventAuditLogMessage
err = tapao.Unmarshal(msgByte, &result, tapao.With(tapao.JSON))
assert.NoError(t, err)
assert.Equal(t, msg.ServiceName, result.ServiceName)
assert.Equal(t, msg.OldData, result.OldData)
assert.Equal(t, msg.NewData, result.NewData)
})
}

func TestNatsEventAuditLogMessage_ToJSONString(t *testing.T) {
type User struct {
ID int64 `json:"id"`
Name string `json:"name"`
}

oldData := User{
ID: int64(123),
Name: "test name",
}

newData := User{
ID: int64(123),
Name: "new test name",
}

byteOldData, err := json.Marshal(oldData)
require.NoError(t, err)
byteNewData, err := json.Marshal(newData)
require.NoError(t, err)

createdAt, err := time.Parse("2006-01-02", "2020-01-29")
require.NoError(t, err)

msg := &NatsEventAuditLogMessage{
ServiceName: "test-audit",
UserID: 123,
AuditableType: "user",
AuditableID: "123",
Action: "update",
AuditedChanges: string(byteNewData),
OldData: string(byteOldData),
NewData: string(byteNewData),
CreatedAt: createdAt,
Error: nil,
}

parsed, err := msg.ToJSONString()
require.NoError(t, err)
expectedRes := "{\"subject\":\"\",\"service_name\":\"test-audit\",\"user_id\":123,\"auditable_type\":\"user\",\"auditable_id\":\"123\",\"action\":\"update\",\"audited_changes\":\"{\\\"id\\\":123,\\\"name\\\":\\\"new test name\\\"}\",\"old_data\":\"{\\\"id\\\":123,\\\"name\\\":\\\"test name\\\"}\",\"new_data\":\"{\\\"id\\\":123,\\\"name\\\":\\\"new test name\\\"}\",\"created_at\":\"2020-01-29T00:00:00Z\",\"error\":null}"
assert.Equal(t, expectedRes, parsed)
}

func TestNatsEventAuditLogMessage_ToJSONByte(t *testing.T) {
type User struct {
ID int64 `json:"id"`
Name string `json:"name"`
}

oldData := User{
ID: int64(123),
Name: "test name",
}

newData := User{
ID: int64(123),
Name: "new test name",
}

byteOldData, err := json.Marshal(oldData)
require.NoError(t, err)
byteNewData, err := json.Marshal(newData)
require.NoError(t, err)

createdAt, err := time.Parse("2006-01-02", "2020-01-29")
require.NoError(t, err)

msg := &NatsEventAuditLogMessage{
ServiceName: "test-audit",
UserID: 123,
AuditableType: "user",
AuditableID: "123",
Action: "update",
AuditedChanges: string(byteNewData),
OldData: string(byteOldData),
NewData: string(byteNewData),
CreatedAt: createdAt,
Error: nil,
}

jsonByte, err := msg.ToJSONByte()
require.NoError(t, err)

parsed, err := ParseNatsEventAuditLogMessageFromBytes(jsonByte)
require.NoError(t, err)

assert.Equal(t, parsed, msg)
}

func TestNatsEventAuditLogMessage_ParseNatsEventAuditLogMessageFromBytes(t *testing.T) {
payload := "{\"subject\":\"\",\"service_name\":\"test-audit\",\"user_id\":123,\"auditable_type\":\"user\",\"auditable_id\":\"123\",\"action\":\"update\",\"audited_changes\":\"{\\\"id\\\":123,\\\"name\\\":\\\"new test name\\\"}\",\"old_data\":\"{\\\"id\\\":123,\\\"name\\\":\\\"test name\\\"}\",\"new_data\":\"{\\\"id\\\":123,\\\"name\\\":\\\"new test name\\\"}\",\"created_at\":\"2020-01-29T00:00:00Z\",\"error\":null}"

type User struct {
ID int64 `json:"id"`
Name string `json:"name"`
}

oldData := User{
ID: int64(123),
Name: "test name",
}

newData := User{
ID: int64(123),
Name: "new test name",
}

byteOldData, err := json.Marshal(oldData)
require.NoError(t, err)
byteNewData, err := json.Marshal(newData)
require.NoError(t, err)

createdAt, err := time.Parse("2006-01-02", "2020-01-29")
require.NoError(t, err)

msg := &NatsEventAuditLogMessage{
ServiceName: "test-audit",
UserID: 123,
AuditableType: "user",
AuditableID: "123",
Action: "update",
AuditedChanges: string(byteNewData),
OldData: string(byteOldData),
NewData: string(byteNewData),
CreatedAt: createdAt,
Error: nil,
}

parsed, err := ParseNatsEventAuditLogMessageFromBytes([]byte(payload))
require.NoError(t, err)

assert.Equal(t, msg, parsed)
}
Loading