Skip to content

Commit

Permalink
Merge pull request #1446 from sandrask/issue-1441
Browse files Browse the repository at this point in the history
feat: Add equivalent ID to also known as for did:web
  • Loading branch information
fqutishat authored Aug 24, 2022
2 parents 670839f + 7c4c596 commit 2af19b7
Show file tree
Hide file tree
Showing 2 changed files with 128 additions and 6 deletions.
46 changes: 44 additions & 2 deletions pkg/document/webresolver/resolvehandler.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,13 @@ func (r *ResolveHandler) ResolveDocument(id string) (*document.ResolutionResult,

orbDID := getOrbDID(localResponse)

equivalentID, err := getEquivalentID(localResponse)
if err != nil {
return nil, err
}

// replace did:web ID with did:orb ID in also known as; if did:web ID is not found then add did:orb ID anyway
didWebDoc, err = updateAlsoKnownAs(didWebDoc, webDID, orbDID)
didWebDoc, err = updateAlsoKnownAs(didWebDoc, webDID, orbDID, equivalentID)
if err != nil {
return nil, err
}
Expand All @@ -101,7 +106,7 @@ func (r *ResolveHandler) ResolveDocument(id string) (*document.ResolutionResult,
return &document.ResolutionResult{Document: didWebDoc, Context: localResponse.Context}, nil
}

func updateAlsoKnownAs(didWebDoc document.Document, webDID, orbDID string) (document.Document, error) {
func updateAlsoKnownAs(didWebDoc document.Document, webDID, orbDID string, equivalentID []string) (document.Document, error) { //nolint:lll
alsoKnownAs, err := getAlsoKnownAs(didWebDoc)
if err != nil {
return nil, err
Expand All @@ -114,6 +119,16 @@ func updateAlsoKnownAs(didWebDoc document.Document, webDID, orbDID string) (docu
updatedAlsoKnownAs = append(updatedAlsoKnownAs, orbDID)
}

// unpublished doc has 1 equivalent ID, and published has 2+ (first one is canonical)
const maxEquivalentIDLength = 2
count := minimum(maxEquivalentIDLength, len(equivalentID))

for i := 0; i < count; i++ {
if !contains(updatedAlsoKnownAs, equivalentID[i]) {
updatedAlsoKnownAs = append(updatedAlsoKnownAs, equivalentID[i])
}
}

didWebDoc[document.AlsoKnownAs] = updatedAlsoKnownAs

return didWebDoc, nil
Expand Down Expand Up @@ -180,6 +195,25 @@ func getAlsoKnownAs(doc document.Document) ([]string, error) {
return nil, fmt.Errorf("unexpected interface '%T' for also known as", alsoKnownAsObj)
}

func getEquivalentID(result *document.ResolutionResult) ([]string, error) {
equivalentIDObj, ok := result.DocumentMetadata[document.EquivalentIDProperty]
if !ok {
return nil, nil
}

equivalentIDArr, ok := equivalentIDObj.([]interface{})
if ok {
return document.StringArray(equivalentIDArr), nil
}

equivalentIDStrArr, ok := equivalentIDObj.([]string)
if ok {
return equivalentIDStrArr, nil
}

return nil, fmt.Errorf("unexpected interface '%T' for equivalentId", equivalentIDObj)
}

func getDeactivatedFlag(result *document.ResolutionResult) bool {
deactivatedObj, ok := result.DocumentMetadata[document.DeactivatedProperty]
if ok {
Expand All @@ -201,3 +235,11 @@ func contains(values []string, value string) bool {

return false
}

func minimum(a, b int) int {
if a < b {
return a
}

return b
}
88 changes: 84 additions & 4 deletions pkg/document/webresolver/resolvehandler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,11 @@ func TestResolveHandler_Resolve(t *testing.T) {
require.NotNil(t, response)

require.Equal(t, "did:web:orb.domain1.com:scid:"+testSuffix, response.Document.ID())
require.True(t, contains(response.Document[document.AlsoKnownAs].([]string),
"did:orb:uEiAZPHwtTJ7-rG0nBeD6nqyL3Xsg1IA2BX1n9iGlv5yBJQ:EiBmPHOGe4f8L4_ZVgBg5V343_nDSSX3l6X-9VKRhE57Tw"))
require.Equal(t, response.Document[document.AlsoKnownAs].([]string)[0], "https://myblog.example/")
require.Equal(t, response.Document[document.AlsoKnownAs].([]string)[1],
"did:orb:uEiAZPHwtTJ7-rG0nBeD6nqyL3Xsg1IA2BX1n9iGlv5yBJQ:EiBmPHOGe4f8L4_ZVgBg5V343_nDSSX3l6X-9VKRhE57Tw")
require.Equal(t, response.Document[document.AlsoKnownAs].([]string)[2],
"did:orb:hl:uEiAZPHwtTJ7-rG0nBeD6nqyL3Xsg1IA2BX1n9iGlv5yBJQ:uoQ-CeEtodHRwczovL29yYi5kb21haW4xLmNvbS9jYXMvdUVpQVpQSHd0VEo3LXJHMG5CZUQ2bnF5TDNYc2cxSUEyQlgxbjlpR2x2NXlCSlF4QmlwZnM6Ly9iYWZrcmVpYXpocjZjMnRlNjcyd2cyanlmNGQ1ajVsZWwzdjVzYnZlYWd5Y3gyejd3ZWdzMzdoZWJldQ:EiBmPHOGe4f8L4_ZVgBg5V343_nDSSX3l6X-9VKRhE57Tw") //nolint:lll

responseBytes, err := json.Marshal(response)
require.NoError(t, err)
Expand All @@ -76,8 +79,17 @@ func TestResolveHandler_Resolve(t *testing.T) {
require.NotNil(t, response)

require.Equal(t, "did:web:orb.domain1.com:scid:"+testUnpublishedSuffix, response.Document.ID())
require.True(t, contains(response.Document[document.AlsoKnownAs].([]string),
"did:orb:uAAA:EiBmPHOGe4f8L4_ZVgBg5V343_nDSSX3l6X-9VKRhE57Tw"))
require.Equal(t, 3, len(response.Document[document.AlsoKnownAs].([]string)))
require.Equal(t, response.Document[document.AlsoKnownAs].([]string)[0], "https://myblog.example/")
require.Equal(t, response.Document[document.AlsoKnownAs].([]string)[1],
"did:orb:uAAA:EiBmPHOGe4f8L4_ZVgBg5V343_nDSSX3l6X-9VKRhE57Tw")
require.Equal(t, response.Document[document.AlsoKnownAs].([]string)[2],
"did:orb:https:orb.domain1.com:uAAA:EiBmPHOGe4f8L4_ZVgBg5V343_nDSSX3l6X-9VKRhE57Tw")

responseBytes, err := json.Marshal(response)
require.NoError(t, err)

fmt.Println(string(responseBytes))
})

t.Run("success - published did but domain not in alsoKnownAs (orb canonical ID added to also known as)", func(t *testing.T) { //nolint:lll
Expand Down Expand Up @@ -124,6 +136,55 @@ func TestResolveHandler_Resolve(t *testing.T) {
"did:orb:uEiAZPHwtTJ7-rG0nBeD6nqyL3Xsg1IA2BX1n9iGlv5yBJQ:EiBmPHOGe4f8L4_ZVgBg5V343_nDSSX3l6X-9VKRhE57Tw"))
})

t.Run("success - equivalent ID does not exist in the document", func(t *testing.T) {
rr, err := getTestResolutionResult()
require.NoError(t, err)

delete(rr.DocumentMetadata, document.EquivalentIDProperty)

orbResolver := &mocks.OrbResolver{}
orbResolver.ResolveDocumentReturns(rr, nil)

handler := NewResolveHandler(testDomainURL,
orbPrefix, orbUnpublishedLabel, orbResolver,
&orbmocks.MetricsProvider{})

response, err := handler.ResolveDocument(testSuffix)
require.NoError(t, err)
require.NotNil(t, response)

require.Equal(t, "did:web:orb.domain1.com:scid:"+testSuffix, response.Document.ID())
require.Equal(t, 2, len(response.Document[document.AlsoKnownAs].([]string)))
require.Equal(t, response.Document[document.AlsoKnownAs].([]string)[0], "https://myblog.example/")
require.Equal(t, response.Document[document.AlsoKnownAs].([]string)[1],
"did:orb:uEiAZPHwtTJ7-rG0nBeD6nqyL3Xsg1IA2BX1n9iGlv5yBJQ:EiBmPHOGe4f8L4_ZVgBg5V343_nDSSX3l6X-9VKRhE57Tw")
})

t.Run("success - equivalent ID is string array", func(t *testing.T) {
rr, err := getTestResolutionResult()
require.NoError(t, err)

rr.DocumentMetadata[document.EquivalentIDProperty] = []string{"https://test.com"}

orbResolver := &mocks.OrbResolver{}
orbResolver.ResolveDocumentReturns(rr, nil)

handler := NewResolveHandler(testDomainURL,
orbPrefix, orbUnpublishedLabel, orbResolver,
&orbmocks.MetricsProvider{})

response, err := handler.ResolveDocument(testSuffix)
require.NoError(t, err)
require.NotNil(t, response)

require.Equal(t, "did:web:orb.domain1.com:scid:"+testSuffix, response.Document.ID())
require.Equal(t, 3, len(response.Document[document.AlsoKnownAs].([]string)))
require.Equal(t, response.Document[document.AlsoKnownAs].([]string)[0], "https://myblog.example/")
require.Equal(t, response.Document[document.AlsoKnownAs].([]string)[1],
"did:orb:uEiAZPHwtTJ7-rG0nBeD6nqyL3Xsg1IA2BX1n9iGlv5yBJQ:EiBmPHOGe4f8L4_ZVgBg5V343_nDSSX3l6X-9VKRhE57Tw")
require.Equal(t, response.Document[document.AlsoKnownAs].([]string)[2], "https://test.com")
})

t.Run("success - current domain not listed in also known as(string array version)", func(t *testing.T) {
rr, err := getTestResolutionResult()
require.NoError(t, err)
Expand Down Expand Up @@ -182,6 +243,25 @@ func TestResolveHandler_Resolve(t *testing.T) {
require.Contains(t, err.Error(), "unexpected interface 'float64' for also known as")
})

t.Run("error - equivalent ID is an unexpected interface", func(t *testing.T) {
rr, err := getTestResolutionResult()
require.NoError(t, err)

rr.DocumentMetadata[document.EquivalentIDProperty] = 123

orbResolver := &mocks.OrbResolver{}
orbResolver.ResolveDocumentReturns(rr, nil)

handler := NewResolveHandler(testDomainURL,
orbPrefix, orbUnpublishedLabel, orbResolver,
&orbmocks.MetricsProvider{})

response, err := handler.ResolveDocument(testSuffix)
require.Error(t, err)
require.Nil(t, response)
require.Contains(t, err.Error(), "unexpected interface 'int' for equivalentId")
})

t.Run("error - orb resolver error", func(t *testing.T) {
orbResolver := &mocks.OrbResolver{}
orbResolver.ResolveDocumentReturns(nil, fmt.Errorf("orb resolver error"))
Expand Down

0 comments on commit 2af19b7

Please sign in to comment.