From c4889a2cb83449d5ec5322f5e267306783381554 Mon Sep 17 00:00:00 2001 From: Sandra Vrtikapa Date: Thu, 3 Nov 2022 19:19:20 -0400 Subject: [PATCH] chore: Service priority should be an interface Service.Priority should be an interface so it can be omitted if not set. Closes #3426 Signed-off-by: Sandra Vrtikapa --- .../protocol/outofband/service_test.go | 2 +- pkg/doc/did/doc.go | 17 ++----- pkg/doc/did/doc_test.go | 6 +-- pkg/doc/did/helpers.go | 18 ++++++- pkg/doc/did/helpers_test.go | 50 ++++++++++++++++++- pkg/doc/did/legacy.go | 5 +- pkg/doc/did/serialize_interop.go | 13 +++-- pkg/mock/diddoc/mock_diddoc.go | 8 +++ 8 files changed, 97 insertions(+), 22 deletions(-) diff --git a/pkg/didcomm/protocol/outofband/service_test.go b/pkg/didcomm/protocol/outofband/service_test.go index 87b09590a..cb9d825d1 100644 --- a/pkg/didcomm/protocol/outofband/service_test.go +++ b/pkg/didcomm/protocol/outofband/service_test.go @@ -1027,7 +1027,7 @@ func TestChooseTarget(t *testing.T) { expected := map[string]interface{}{ "id": uuid.New().String(), "type": "did-communication", - "priority": uint(0), + "priority": 0, "recipientKeys": []string{"my ver key"}, "serviceEndpoint": commonmodel.NewDIDCommV1Endpoint("my service endpoint"), "RoutingKeys": []string{"my routing key"}, diff --git a/pkg/doc/did/doc.go b/pkg/doc/did/doc.go index 4630c3c99..9e30c0133 100644 --- a/pkg/doc/did/doc.go +++ b/pkg/doc/did/doc.go @@ -374,7 +374,7 @@ func (pk *VerificationMethod) JSONWebKey() *jwk.JWK { type Service struct { ID string `json:"id"` Type interface{} `json:"type"` - Priority uint `json:"priority,omitempty"` + Priority interface{} `json:"priority,omitempty"` RecipientKeys []string `json:"recipientKeys,omitempty"` RoutingKeys []string `json:"routingKeys,omitempty"` ServiceEndpoint model.Endpoint `json:"serviceEndpoint"` @@ -705,7 +705,7 @@ func populateServices(didID, baseURI string, rawServices []map[string]interface{ relativeURL: isRelative, ServiceEndpoint: sp, RecipientKeys: recipientKeys, - Priority: uintEntry(rawService[jsonldPriority]), + Priority: rawService[jsonldPriority], RoutingKeys: routingKeys, recipientKeysRelativeURL: recipientKeysRelativeURL, routingKeysRelativeURL: routingKeysRelativeURL, @@ -1051,15 +1051,6 @@ func stringEntry(entry interface{}) string { return "" } -// uintEntry. -func uintEntry(entry interface{}) uint { - if entry == nil { - return 0 - } - - return uint(entry.(float64)) -} - // stringArray. func stringArray(entry interface{}) []string { if entry == nil { @@ -1411,7 +1402,9 @@ func populateRawServices(services []Service, didID, baseURI string) []map[string rawService[jsonldServicePoint] = json.RawMessage(bytes) } - rawService[jsonldPriority] = services[i].Priority + if services[i].Priority != nil { + rawService[jsonldPriority] = services[i].Priority + } if len(recipientKeys) > 0 { rawService[jsonldRecipientKeys] = recipientKeys diff --git a/pkg/doc/did/doc_test.go b/pkg/doc/did/doc_test.go index 5b5431246..c4f7b345f 100644 --- a/pkg/doc/did/doc_test.go +++ b/pkg/doc/did/doc_test.go @@ -157,7 +157,7 @@ func TestValidWithDocBase(t *testing.T) { { ID: "did:example:123456789abcdefghi#did-communication", Type: "did-communication", - Priority: 0, + Priority: float64(0), relativeURL: true, RecipientKeys: []string{"did:example:123456789abcdefghi#key2"}, RoutingKeys: []string{"did:example:123456789abcdefghi#key2"}, @@ -413,7 +413,7 @@ func TestValid(t *testing.T) { { ID: "did:example:123456789abcdefghi#did-communication", Type: "did-communication", - Priority: 0, + Priority: float64(0), RecipientKeys: []string{"did:example:123456789abcdefghi#key2"}, RoutingKeys: []string{"did:example:123456789abcdefghi#key2"}, ServiceEndpoint: model.NewDIDCommV1Endpoint("https://agent.example.com/"), @@ -424,7 +424,7 @@ func TestValid(t *testing.T) { { ID: "did:example:123456789abcdefghi#DIDCommMessaging", Type: "DIDCommMessaging", - Priority: 0, + Priority: float64(0), RecipientKeys: []string{"did:example:123456789abcdefghi#key2"}, ServiceEndpoint: model.NewDIDCommV2Endpoint([]model.DIDCommV2Endpoint{{ URI: "https://agent.example.com/", diff --git a/pkg/doc/did/helpers.go b/pkg/doc/did/helpers.go index 66ad6adfa..1dddd596f 100644 --- a/pkg/doc/did/helpers.go +++ b/pkg/doc/did/helpers.go @@ -138,7 +138,7 @@ func LookupService(didDoc *Doc, serviceType string) (*Service, bool) { for i := range didDoc.Service { if didDoc.Service[i].Type == serviceType { - if index == notFound || didDoc.Service[index].Priority > didDoc.Service[i].Priority { + if index == notFound || comparePriority(didDoc.Service[index].Priority, didDoc.Service[i].Priority) { index = i } } @@ -151,6 +151,22 @@ func LookupService(didDoc *Doc, serviceType string) (*Service, bool) { return &didDoc.Service[index], true } +func comparePriority(v1, v2 interface{}) bool { + // expecting positive integers plus zero; otherwise cannot compare priority + intV1, okV1 := v1.(int) + intV2, okV2 := v2.(int) + + if okV1 && okV2 { + return intV1 > intV2 + } + + if !okV1 && !okV2 { + return false + } + + return !okV1 +} + // LookupDIDCommRecipientKeys gets the DIDComm recipient keys from the did doc which match the given parameters. // DIDComm recipient keys are encoded as did:key identifiers. // See: diff --git a/pkg/doc/did/helpers_test.go b/pkg/doc/did/helpers_test.go index 3c4307ac5..d791695d4 100644 --- a/pkg/doc/did/helpers_test.go +++ b/pkg/doc/did/helpers_test.go @@ -194,7 +194,54 @@ func TestGetDidCommService(t *testing.T) { s, ok := LookupService(didDoc, didCommServiceType) require.True(t, ok) require.Equal(t, "did-communication", s.Type) - require.Equal(t, uint(0), s.Priority) + require.Equal(t, 0, s.Priority) + }) + + t.Run("successfully getting did-communication service - switch order", func(t *testing.T) { + didDoc := mockdiddoc.GetMockDIDDoc(t, false) + service := didDoc.Service[0] + didDoc.Service[0] = didDoc.Service[1] + didDoc.Service[1] = service + + s, ok := LookupService(didDoc, didCommServiceType) + require.True(t, ok) + require.Equal(t, "did-communication", s.Type) + require.Equal(t, 0, s.Priority) + }) + + t.Run("successfully getting did-communication service - first priority nil", func(t *testing.T) { + didDoc := mockdiddoc.GetMockDIDDoc(t, false) + didDoc.Service[0].Priority = nil + + s, ok := LookupService(didDoc, didCommServiceType) + require.True(t, ok) + require.Equal(t, "did-communication", s.Type) + require.Equal(t, 1, s.Priority) + }) + + t.Run("successfully getting did-communication service - second priority nil", func(t *testing.T) { + didDoc := mockdiddoc.GetMockDIDDoc(t, false) + didDoc.Service[1].Priority = nil + + s, ok := LookupService(didDoc, didCommServiceType) + require.True(t, ok) + require.Equal(t, "did-communication", s.Type) + require.Equal(t, 0, s.Priority) + }) + + t.Run("successfully getting did-communication service - both nil", func(t *testing.T) { + didDoc := mockdiddoc.GetMockDIDDoc(t, false) + didDoc.Service[0].Priority = nil + didDoc.Service[1].Priority = nil + + s, ok := LookupService(didDoc, didCommServiceType) + require.True(t, ok) + require.Equal(t, "did-communication", s.Type) + require.Equal(t, nil, s.Priority) + + uri, err := s.ServiceEndpoint.URI() + require.NoError(t, err) + require.Equal(t, "https://localhost:8090", uri) }) t.Run("error due to missing service", func(t *testing.T) { @@ -209,6 +256,7 @@ func TestGetDidCommService(t *testing.T) { t.Run("error due to missing did-communication service", func(t *testing.T) { didDoc := mockdiddoc.GetMockDIDDoc(t, false) didDoc.Service[0].Type = "some-type" + didDoc.Service[1].Type = "other-type" s, ok := LookupService(didDoc, didCommServiceType) require.False(t, ok) diff --git a/pkg/doc/did/legacy.go b/pkg/doc/did/legacy.go index ec85c3eb2..14cef3316 100644 --- a/pkg/doc/did/legacy.go +++ b/pkg/doc/did/legacy.go @@ -107,7 +107,10 @@ func populateRawServicesLegacy(services []Service, didID, baseURI string) []map[ rawService[jsonldServicePoint] = uri rawService[jsonldRecipientKeys] = recipientKeys rawService[jsonldRoutingKeys] = routingKeys - rawService[jsonldPriority] = services[i].Priority + + if services[i].Priority != nil { + rawService[jsonldPriority] = services[i].Priority + } rawServices = append(rawServices, rawService) } diff --git a/pkg/doc/did/serialize_interop.go b/pkg/doc/did/serialize_interop.go index 33f7f0a3b..7e941980c 100644 --- a/pkg/doc/did/serialize_interop.go +++ b/pkg/doc/did/serialize_interop.go @@ -1,3 +1,4 @@ +//go:build ACAPyInterop // +build ACAPyInterop /* @@ -119,7 +120,10 @@ func populateRawServicesInterop(services []Service, didID, baseURI string) []map rawService[jsonldServicePoint] = uri rawService[jsonldRecipientKeys] = recipientKeys rawService[jsonldRoutingKeys] = routingKeys - rawService[jsonldPriority] = services[i].Priority + + if services[i].Priority != nil { + rawService[jsonldPriority] = services[i].Priority + } rawServices = append(rawServices, rawService) } @@ -159,9 +163,12 @@ func pubKeyFromDIDKey(didKey string) ([]byte, error) { // SerializeInterop serializes the DID doc, using normal serialization unless the `interop` build flag is set. // Verifications are serialized to accommodate aca-py issue #1104: -// https://github.com/hyperledger/aries-cloudagent-python/issues/1104 +// +// https://github.com/hyperledger/aries-cloudagent-python/issues/1104 +// // Services are serialized to accommodate aca-py issue #1106: -// https://github.com/hyperledger/aries-cloudagent-python/issues/1106 +// +// https://github.com/hyperledger/aries-cloudagent-python/issues/1106 func (doc *Doc) SerializeInterop() ([]byte, error) { context := ContextV1Old diff --git a/pkg/mock/diddoc/mock_diddoc.go b/pkg/mock/diddoc/mock_diddoc.go index d05f5d809..bbce5cd25 100644 --- a/pkg/mock/diddoc/mock_diddoc.go +++ b/pkg/mock/diddoc/mock_diddoc.go @@ -20,6 +20,7 @@ import ( ) // GetMockDIDDoc creates a mock DID Doc for testing. +// //nolint:funlen func GetMockDIDDoc(t *testing.T, isDIDCommV2 bool) *did.Doc { t.Helper() @@ -34,6 +35,13 @@ func GetMockDIDDoc(t *testing.T, isDIDCommV2 bool) *did.Doc { Priority: 0, RecipientKeys: []string{MockDIDKey(t)}, }, + { + ServiceEndpoint: model.NewDIDCommV1Endpoint("https://localhost:9090"), + RoutingKeys: []string{MockDIDKey(t)}, + Type: "did-communication", + Priority: 1, + RecipientKeys: []string{MockDIDKey(t)}, + }, } if isDIDCommV2 {