Skip to content

Commit

Permalink
implement validators for key data types
Browse files Browse the repository at this point in the history
re AB#9604
  • Loading branch information
Henry Jewell committed Jul 10, 2024
1 parent e154c9d commit d0013cc
Show file tree
Hide file tree
Showing 2 changed files with 312 additions and 0 deletions.
62 changes: 62 additions & 0 deletions logverification/validation.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package logverification

import "errors"

// Note: We need this logic to detect incomplete JSON unmarshalled into these types. This should
// eventually be replaced by JSON Schema validation. We believe its a problem to solve for the
// entire go codebase through generation. We already describe the structs with json annotations and
// typing information. We don't want to half-cook that solution, as JSON type bugs have bitten us
// before.

var (
ErrNonEmptyEventIDRequired = errors.New("event identity field is required and must be non-empty")
ErrNonEmptyTenantIDRequired = errors.New("tenant identity field is required and must be non-empty")
ErrCommitEntryRequired = errors.New("merkle log commit field is required")
ErrIdTimestampRequired = errors.New("idtimestamp field is required and must be non-empty")
)

// Validate performs basic validation on the VerifiableEvent, ensuring that critical fields
// are present.
func (e *VerifiableEvent) Validate() error {
if e.EventID == "" {
return ErrNonEmptyEventIDRequired
}

if e.TenantID == "" {
return ErrNonEmptyTenantIDRequired
}

if e.MerkleLog == nil || e.MerkleLog.Commit == nil {
return ErrCommitEntryRequired
}

if e.MerkleLog.Commit.Idtimestamp == "" {
return ErrIdTimestampRequired
}

return nil
}

// Validate performs basic validation on the DecodedEvent, ensuring that critical fields
// are present for verification purposes.
func (e *DecodedEvent) Validate() error {
if e.V3Event.Identity == "" {
return ErrNonEmptyEventIDRequired
}

if e.V3Event.TenantIdentity == "" {
return ErrNonEmptyTenantIDRequired
}

if e.MerkleLog == nil || e.MerkleLog.Commit == nil {
return ErrCommitEntryRequired
}

if e.MerkleLog.Commit.Idtimestamp == "" {
return ErrIdTimestampRequired
}

// TODO: Validate other necessary V3 fields.

return nil
}
250 changes: 250 additions & 0 deletions logverification/validation_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,250 @@
package logverification

import (
"testing"

"github.com/datatrails/go-datatrails-common-api-gen/assets/v2/assets"
"github.com/datatrails/go-datatrails-simplehash/simplehash"
"github.com/stretchr/testify/assert"
)

func TestVerifiableEvent_Validate(t *testing.T) {
type fields struct {
EventID string
TenantID string
LeafHash []byte
MerkleLog *assets.MerkleLogEntry
}

tests := []struct {
name string
fields fields
expectedErr error
}{
{
name: "valid input returns no error",
fields: fields{
EventID: "event/7189fa3d-9af1-40b1-975c-70f792142a82",
TenantID: "tenant/7189fa3d-9af1-40b1-975c-70f792142a82",
LeafHash: []byte("2091f2349925f93546c54d4140cdca5ab59213ef82daf665d81637260d022069"),
MerkleLog: &assets.MerkleLogEntry{
Commit: &assets.MerkleLogCommit{
Index: uint64(0),
Idtimestamp: "018fa97ef269039b00",
},
},
},
expectedErr: nil,
},
{
name: "missing event identity returns specific error",
fields: fields{
EventID: "",
TenantID: "tenant/7189fa3d-9af1-40b1-975c-70f792142a82",
LeafHash: []byte("2091f2349925f93546c54d4140cdca5ab59213ef82daf665d81637260d022069"),
MerkleLog: &assets.MerkleLogEntry{
Commit: &assets.MerkleLogCommit{
Index: uint64(0),
Idtimestamp: "018fa97ef269039b00",
},
},
},
expectedErr: ErrNonEmptyEventIDRequired,
},
{
name: "missing tenant identity returns specific error",
fields: fields{
EventID: "event/7189fa3d-9af1-40b1-975c-70f792142a82",
TenantID: "",
LeafHash: []byte("2091f2349925f93546c54d4140cdca5ab59213ef82daf665d81637260d022069"),
MerkleLog: &assets.MerkleLogEntry{
Commit: &assets.MerkleLogCommit{
Index: uint64(0),
Idtimestamp: "018fa97ef269039b00",
},
},
},
expectedErr: ErrNonEmptyTenantIDRequired,
},
{
name: "missing commit entry returns specific error",
fields: fields{
EventID: "event/7189fa3d-9af1-40b1-975c-70f792142a82",
TenantID: "tenant/7189fa3d-9af1-40b1-975c-70f792142a82",
LeafHash: []byte("2091f2349925f93546c54d4140cdca5ab59213ef82daf665d81637260d022069"),
MerkleLog: &assets.MerkleLogEntry{},
},
expectedErr: ErrCommitEntryRequired,
},
{
name: "missing idtimestamp returns specific error",
fields: fields{
EventID: "event/7189fa3d-9af1-40b1-975c-70f792142a82",
TenantID: "tenant/7189fa3d-9af1-40b1-975c-70f792142a82",
LeafHash: []byte("2091f2349925f93546c54d4140cdca5ab59213ef82daf665d81637260d022069"),
MerkleLog: &assets.MerkleLogEntry{
Commit: &assets.MerkleLogCommit{
Index: uint64(0),
Idtimestamp: "",
},
},
},
expectedErr: ErrIdTimestampRequired,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
e := &VerifiableEvent{
EventID: tt.fields.EventID,
TenantID: tt.fields.TenantID,
LeafHash: tt.fields.LeafHash,
MerkleLog: tt.fields.MerkleLog,
}

err := e.Validate()
assert.ErrorIs(t, err, tt.expectedErr)
})
}
}

func TestDecodedEvent_Validate(t *testing.T) {
testPrincipal := map[string]any{
"issuer": "https://.soak.stage.datatrails.ai/appidpv1",
"subject": "e96dfa33-b645-4b83-a041-e87ac426c089",
"display_name": "test",
"email": "[email protected]",
}

type fields struct {
V3Event simplehash.V3Event
MerkleLog *assets.MerkleLogEntry
}

tests := []struct {
name string
fields fields
expectedErr error
}{
{
name: "valid input returns no error",
fields: fields{
V3Event: simplehash.V3Event{
Identity: "event/7189fa3d-9af1-40b1-975c-70f792142a82",
TenantIdentity: "tenant/7189fa3d-9af1-40b1-975c-70f792142a82",
Operation: "NewAsset",
Behaviour: "AssetCreator",
TimestampDeclared: "2024-03-14T23:24:50Z",
TimestampAccepted: "2024-03-14T23:24:50Z",
TimestampCommitted: "2024-03-22T11:13:55.557Z",
PrincipalDeclared: testPrincipal,
PrincipalAccepted: testPrincipal,
},
MerkleLog: &assets.MerkleLogEntry{
Commit: &assets.MerkleLogCommit{
Index: uint64(0),
Idtimestamp: "018fa97ef269039b00",
},
},
},
expectedErr: nil,
},
{
name: "missing event identity returns specific error",
fields: fields{
V3Event: simplehash.V3Event{
Identity: "",
TenantIdentity: "tenant/7189fa3d-9af1-40b1-975c-70f792142a82",
Operation: "NewAsset",
Behaviour: "AssetCreator",
TimestampDeclared: "2024-03-14T23:24:50Z",
TimestampAccepted: "2024-03-14T23:24:50Z",
TimestampCommitted: "2024-03-22T11:13:55.557Z",
PrincipalDeclared: testPrincipal,
PrincipalAccepted: testPrincipal,
},
MerkleLog: &assets.MerkleLogEntry{
Commit: &assets.MerkleLogCommit{
Index: uint64(0),
Idtimestamp: "018fa97ef269039b00",
},
},
},
expectedErr: ErrNonEmptyEventIDRequired,
},
{
name: "missing tenant identity returns specific error",
fields: fields{
V3Event: simplehash.V3Event{
Identity: "event/7189fa3d-9af1-40b1-975c-70f792142a82",
TenantIdentity: "",
Operation: "NewAsset",
Behaviour: "AssetCreator",
TimestampDeclared: "2024-03-14T23:24:50Z",
TimestampAccepted: "2024-03-14T23:24:50Z",
TimestampCommitted: "2024-03-22T11:13:55.557Z",
PrincipalDeclared: testPrincipal,
PrincipalAccepted: testPrincipal,
},
MerkleLog: &assets.MerkleLogEntry{
Commit: &assets.MerkleLogCommit{
Index: uint64(0),
Idtimestamp: "018fa97ef269039b00",
},
},
},
expectedErr: ErrNonEmptyTenantIDRequired,
},
{
name: "missing commit entry returns specific error",
fields: fields{
V3Event: simplehash.V3Event{
Identity: "event/7189fa3d-9af1-40b1-975c-70f792142a82",
TenantIdentity: "tenant/7189fa3d-9af1-40b1-975c-70f792142a82",
Operation: "NewAsset",
Behaviour: "AssetCreator",
TimestampDeclared: "2024-03-14T23:24:50Z",
TimestampAccepted: "2024-03-14T23:24:50Z",
TimestampCommitted: "2024-03-22T11:13:55.557Z",
PrincipalDeclared: testPrincipal,
PrincipalAccepted: testPrincipal,
},
MerkleLog: &assets.MerkleLogEntry{},
},
expectedErr: ErrCommitEntryRequired,
},
{
name: "missing idtimestamp returns specific error",
fields: fields{
V3Event: simplehash.V3Event{
Identity: "event/7189fa3d-9af1-40b1-975c-70f792142a82",
TenantIdentity: "tenant/7189fa3d-9af1-40b1-975c-70f792142a82",
Operation: "NewAsset",
Behaviour: "AssetCreator",
TimestampDeclared: "2024-03-14T23:24:50Z",
TimestampAccepted: "2024-03-14T23:24:50Z",
TimestampCommitted: "2024-03-22T11:13:55.557Z",
PrincipalDeclared: testPrincipal,
PrincipalAccepted: testPrincipal,
},
MerkleLog: &assets.MerkleLogEntry{
Commit: &assets.MerkleLogCommit{
Index: uint64(0),
Idtimestamp: "",
},
},
},
expectedErr: ErrIdTimestampRequired,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
e := &DecodedEvent{
V3Event: tt.fields.V3Event,
MerkleLog: tt.fields.MerkleLog,
}

err := e.Validate()
assert.ErrorIs(t, err, tt.expectedErr)
})
}
}

0 comments on commit d0013cc

Please sign in to comment.