Skip to content

Commit

Permalink
Add protobuf validation in json
Browse files Browse the repository at this point in the history
  • Loading branch information
DaevMithran committed Oct 14, 2024
1 parent bdec2ab commit 050e920
Show file tree
Hide file tree
Showing 3 changed files with 138 additions and 20 deletions.
88 changes: 88 additions & 0 deletions x/did/types/diddoc_diddoc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -295,4 +295,92 @@ var _ = DescribeTable("DIDDoc Validation tests", func(testCase DIDDocTestCase) {
isValid: false,
errorMsg: "assertionMethod should be a valid key reference within the DID document's verification method",
}),
Entry(
"Assertion method has invalid protobuf value",
DIDDocTestCase{
didDoc: &DidDoc{
Id: ValidTestDID,
Controller: []string{ValidTestDID},
VerificationMethod: []*VerificationMethod{
{
Id: fmt.Sprintf("%s#fragment", ValidTestDID),
VerificationMethodType: "Ed25519VerificationKey2020",
Controller: ValidTestDID,
VerificationMaterial: ValidEd25519VerificationKey2020VerificationMaterial,
},
},
AssertionMethod: []string{func() string {
b, _ := json.Marshal(struct {
Id string
Type string
Controller string
InvalidField map[string]interface{}
}{
Id: fmt.Sprintf("%s#fragment", ValidTestDID),
Type: "Ed25519VerificationKey2020",
Controller: ValidTestDID,
InvalidField: map[string]interface{}{"unsupported": []int{1, 2, 3}},
})
return strconv.Quote(string(b))
}()},
},
isValid: false,
errorMsg: "field InvalidField is not protobuf-supported",
}),
Entry(
"Assertion method is missing controller value in JSON",
DIDDocTestCase{
didDoc: &DidDoc{
Id: ValidTestDID,
Controller: []string{ValidTestDID},
VerificationMethod: []*VerificationMethod{
{
Id: fmt.Sprintf("%s#fragment", ValidTestDID),
VerificationMethodType: "Ed25519VerificationKey2020",
Controller: ValidTestDID,
VerificationMaterial: ValidEd25519VerificationKey2020VerificationMaterial,
},
},
AssertionMethod: []string{func() string {
b, _ := json.Marshal(struct {
Id string
Type string
}{
Id: fmt.Sprintf("%s#fragment", ValidTestDID),
Type: "Ed25519VerificationKey2020",
})
return strconv.Quote(string(b))
}()},
},
isValid: false,
errorMsg: "assertion_method: (0: (Controller: cannot be blank.).).",
}),
Entry(
"Assertion method is contains unescaped JSON string",
DIDDocTestCase{
didDoc: &DidDoc{
Id: ValidTestDID,
Controller: []string{ValidTestDID},
VerificationMethod: []*VerificationMethod{
{
Id: fmt.Sprintf("%s#fragment", ValidTestDID),
VerificationMethodType: "Ed25519VerificationKey2020",
Controller: ValidTestDID,
VerificationMaterial: ValidEd25519VerificationKey2020VerificationMaterial,
},
},
AssertionMethod: []string{func() string {
b, _ := json.Marshal(struct {
Id string
Type string
}{
Id: fmt.Sprintf("%s#fragment", ValidTestDID),
Type: "Ed25519VerificationKey2020",
})
return string(b)
}()},
},
isValid: false,
errorMsg: "assertionMethod should be a DIDUrl or an Escaped JSON string",
}),
)
41 changes: 22 additions & 19 deletions x/did/types/validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,32 +121,35 @@ func IsAssertionMethod(allowedNamespaces []string, didDoc DidDoc) *CustomErrorRu
panic("IsAssertionMethod must be only applied on string properties")
}

if err != nil {
unescapedJSON, err := strconv.Unquote(casted)
if err != nil {
return errors.New("assertionMethod should be a DIDUrl or an Escaped JSON string")
if err == nil {
for _, v := range didDoc.VerificationMethod {
if v.Id == casted {
return nil
}
}

var result AssertionMethod
err = json.Unmarshal([]byte(unescapedJSON), &result)
if err != nil {
return errors.New("assertionMethod should be a DIDUrl or an Escaped JSON string")
}
return errors.New("assertionMethod should be a valid key reference within the DID document's verification method")
}

unescapedJSON, err := strconv.Unquote(casted)
if err != nil {
return errors.New("assertionMethod should be a DIDUrl or an Escaped JSON string")
}

return validation.ValidateStruct(&result,
validation.Field(&result.Id, validation.Required, IsAssertionMethod(allowedNamespaces, didDoc)),
validation.Field(&result.Controller, validation.Required, IsDID(allowedNamespaces)),
validation.Field(&result.Type, IsURI()),
)
if err := utils.ValidateProtobufFields(unescapedJSON); err != nil {
return err
}

for _, v := range didDoc.VerificationMethod {
if v.Id == casted {
return nil
}
var result AssertionMethod
if err = json.Unmarshal([]byte(unescapedJSON), &result); err != nil {
return errors.New("assertionMethod should be a DIDUrl or an Escaped JSON string with id, type and controller values")
}

return errors.New("assertionMethod should be a valid key reference within the DID document's verification method")
return validation.ValidateStruct(&result,
validation.Field(&result.Id, validation.Required, IsAssertionMethod(allowedNamespaces, didDoc)),
validation.Field(&result.Controller, validation.Required, IsDID(allowedNamespaces)),
validation.Field(&result.Type, IsURI()),
)
})
}

Expand Down
29 changes: 28 additions & 1 deletion x/did/utils/str.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
package utils

import "sort"
import (
"encoding/json"
"errors"
"fmt"
"sort"

"google.golang.org/protobuf/proto"
)

func IndexOf(array []string, searchElement string, fromIndex int) int {
for i, v := range array[fromIndex:] {
Expand Down Expand Up @@ -100,3 +107,23 @@ func UniqueSorted(ls []string) []string {
func StrBytes(p string) []byte {
return []byte(p)
}

// Generic function to validate protobuf-supported fields in a JSON string
func ValidateProtobufFields(jsonString string) error {
var input map[string]interface{}
if err := json.Unmarshal([]byte(jsonString), &input); err != nil {
return errors.New("input should be a valid JSON string")
}

for key, value := range input {
fmt.Println(key, value)
switch value.(type) {
case string, int, int32, int64, float32, float64, bool, proto.Message:
continue
default:
return fmt.Errorf("field %s is not protobuf-supported", key)
}
}

return nil
}

0 comments on commit 050e920

Please sign in to comment.