-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
implement validators for key data types
re AB#9604
- Loading branch information
Henry Jewell
committed
Jul 10, 2024
1 parent
e154c9d
commit d0013cc
Showing
2 changed files
with
312 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | ||
}) | ||
} | ||
} |