Skip to content

Commit

Permalink
Merge pull request #781 from bstasyszyn/766
Browse files Browse the repository at this point in the history
feat: Return alternate links in WebFinger for DID and CAS
  • Loading branch information
bstasyszyn committed Sep 17, 2021
2 parents 107e3f4 + 7b6c41e commit 8820a16
Show file tree
Hide file tree
Showing 21 changed files with 1,303 additions and 193 deletions.
45 changes: 30 additions & 15 deletions cmd/orb-server/startcmd/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,10 @@ import (
"github.com/trustbloc/orb/pkg/activitypub/vocab"
"github.com/trustbloc/orb/pkg/anchor/builder"
"github.com/trustbloc/orb/pkg/anchor/graph"
"github.com/trustbloc/orb/pkg/anchor/handler/acknowlegement"
"github.com/trustbloc/orb/pkg/anchor/handler/credential"
"github.com/trustbloc/orb/pkg/anchor/handler/proof"
"github.com/trustbloc/orb/pkg/anchor/linkstore"
"github.com/trustbloc/orb/pkg/anchor/policy"
policyhandler "github.com/trustbloc/orb/pkg/anchor/policy/resthandler"
"github.com/trustbloc/orb/pkg/anchor/writer"
Expand Down Expand Up @@ -607,6 +609,11 @@ func startOrbServices(parameters *orbParameters) error {

resourceResolver := resource.New(httpClient, ipfsReader)

anchorLinkStore, err := linkstore.New(storeProviders.provider)
if err != nil {
return fmt.Errorf("open store: %w", err)
}

// create new observer and start it
providers := &observer.Providers{
ProtocolClientProvider: pcp,
Expand All @@ -618,13 +625,16 @@ func startOrbServices(parameters *orbParameters) error {
WebFingerResolver: resourceResolver,
CASResolver: casResolver,
DocLoader: orbDocumentLoader,
AnchorLinkStore: anchorLinkStore,
}

o, err := observer.New(providers, observer.WithDiscoveryDomain(parameters.discoveryDomain))
if err != nil {
return fmt.Errorf("failed to create observer: %s", err.Error())
}

anchorEventHandler := acknowlegement.New(anchorLinkStore)

activityPubService, err = apservice.New(apConfig,
apStore, t, apSigVerifier, pubSub, apClient, resourceResolver, metrics.Get(),
apspi.WithProofHandler(proofHandler),
Expand All @@ -636,7 +646,7 @@ func startOrbServices(parameters *orbParameters) error {
// apspi.WithWitnessInvitationAuth(inviteWitnessAuth),
// apspi.WithFollowerAuth(followerAuth),
// apspi.WithUndeliverableHandler(undeliverableHandler),
// apspi.WithAnchorEventAcknowledgementHandler(anchorEventHandler),
apspi.WithAnchorEventAcknowledgementHandler(anchorEventHandler),
)
if err != nil {
return fmt.Errorf("failed to create ActivityPub service: %s", err.Error())
Expand Down Expand Up @@ -755,20 +765,25 @@ func startOrbServices(parameters *orbParameters) error {
orbDocUpdateHandler := updatehandler.New(didDocHandler, metrics.Get(), updateHandlerOpts...)

// create discovery rest api
endpointDiscoveryOp, err := discoveryrest.New(&discoveryrest.Config{
PubKey: pubKey,
VerificationMethodType: verificationMethodType,
KID: parameters.keyID,
ResolutionPath: baseResolvePath,
OperationPath: baseUpdatePath,
WebCASPath: casPath,
BaseURL: parameters.externalEndpoint,
DiscoveryDomains: parameters.discoveryDomains,
DiscoveryMinimumResolvers: parameters.discoveryMinimumResolvers,
VctURL: parameters.vctURL,
DiscoveryVctDomains: parameters.discoveryVctDomains,
ResourceRegistry: resourceRegistry,
})
endpointDiscoveryOp, err := discoveryrest.New(
&discoveryrest.Config{
PubKey: pubKey,
VerificationMethodType: verificationMethodType,
KID: parameters.keyID,
ResolutionPath: baseResolvePath,
OperationPath: baseUpdatePath,
WebCASPath: casPath,
BaseURL: parameters.externalEndpoint,
DiscoveryDomains: parameters.discoveryDomains,
DiscoveryMinimumResolvers: parameters.discoveryMinimumResolvers,
VctURL: parameters.vctURL,
DiscoveryVctDomains: parameters.discoveryVctDomains,
},
&discoveryrest.Providers{
ResourceRegistry: resourceRegistry,
CAS: coreCASClient,
AnchorLinkStore: anchorLinkStore,
})
if err != nil {
return fmt.Errorf("discovery rest: %w", err)
}
Expand Down
31 changes: 1 addition & 30 deletions pkg/activitypub/service/activityhandler/inboxhandler.go
Original file line number Diff line number Diff line change
Expand Up @@ -969,36 +969,7 @@ type noOpAnchorEventAcknowledgementHandler struct{}
func (p *noOpAnchorEventAcknowledgementHandler) AnchorEventAcknowledged(actor, anchorRef *url.URL,
additionalAnchorRefs []*url.URL) error {
logger.Infof("Anchor event was acknowledged by [%s] for anchor %s. Additional anchors: %s",
actor, newHashLinkInfo(anchorRef), newHashLinkInfo(additionalAnchorRefs...))
actor, hashlink.ToString(anchorRef), hashlink.ToString(additionalAnchorRefs...))

return nil
}

type hashLinkInfo struct {
hl []*url.URL
}

func newHashLinkInfo(hl ...*url.URL) *hashLinkInfo {
return &hashLinkInfo{hl: hl}
}

func (hlInfo *hashLinkInfo) String() string {
str := ""

parser := hashlink.New()

for i, hl := range hlInfo.hl {
if i > 0 {
str += ", "
}

info, err := parser.ParseHashLink(hl.String())
if err != nil {
str += fmt.Sprintf("{INVALID HASHLINK [%s]}", hl)
} else {
str += fmt.Sprintf("{Hash [%s], Links %s}", info.ResourceHash, info.Links)
}
}

return str
}
73 changes: 73 additions & 0 deletions pkg/anchor/handler/acknowlegement/acknowledgement.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/*
Copyright SecureKey Technologies Inc. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/

package acknowlegement

import (
"fmt"
"net/url"

"github.com/trustbloc/edge-core/pkg/log"

"github.com/trustbloc/orb/pkg/hashlink"
)

var logger = log.New("anchor-acknowledgement-handler")

type anchorLinkStore interface {
PutLinks(links []*url.URL) error
}

// Handler handles notifications of successful anchor events processed from an Orb server.
type Handler struct {
anchorLinkStore anchorLinkStore
}

// New returns a new handler.
func New(store anchorLinkStore) *Handler {
return &Handler{anchorLinkStore: store}
}

// AnchorEventAcknowledged handles a notification of a successful anchor event processed from an Orb server.
// The given additional references are added to the anchor link store so that they are available for
// WebFinger requests.
func (p *Handler) AnchorEventAcknowledged(actor, anchorRef *url.URL, additionalAnchorRefs []*url.URL) error {
logger.Infof("Anchor event was acknowledged by [%s] for anchor %s. Additional anchors: %s",
actor, hashlink.ToString(anchorRef), hashlink.ToString(additionalAnchorRefs...))

parser := hashlink.New()

info, err := parser.ParseHashLink(anchorRef.String())
if err != nil {
return fmt.Errorf("parse hashlink [%s]: %w", anchorRef, err)
}

var links []*url.URL

for _, hl := range additionalAnchorRefs {
hlInfo, err := parser.ParseHashLink(hl.String())
if err != nil {
logger.Warnf("Error parsing hashlink [%s]: %s", anchorRef, err)

continue
}

if hlInfo.ResourceHash != info.ResourceHash {
logger.Warnf("Hash in additional anchor ref [%s] does not match the hash of the acknowledged anchor event [%s]",
hlInfo.ResourceHash, info.ResourceHash)

continue
}

links = append(links, hl)
}

if err := p.anchorLinkStore.PutLinks(links); err != nil {
return fmt.Errorf("put links [%s]: %w", info.ResourceHash, err)
}

return nil
}
57 changes: 57 additions & 0 deletions pkg/anchor/handler/acknowlegement/acknowledgement_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
Copyright SecureKey Technologies Inc. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/

package acknowlegement

import (
"errors"
"net/url"
"testing"

"github.com/stretchr/testify/require"

"github.com/trustbloc/orb/pkg/internal/testutil"
"github.com/trustbloc/orb/pkg/mocks"
)

func TestHandler(t *testing.T) {
actor := testutil.MustParseURL("https://domain1.com")
anchorRef := testutil.MustParseURL("hl:uEiALYp_C4wk2WegpfnCSoSTBdKZ1MVdDadn4rdmZl5GKzQ:uoQ-BeDVpcGZzOi8vUW1jcTZKV0RVa3l4ZWhxN1JWWmtQM052aUU0SHFSdW5SalgzOXZ1THZFSGFRTg") //nolint:lll

additionalRefs := []*url.URL{
// Valid hashlink.
testutil.MustParseURL("hl:uEiALYp_C4wk2WegpfnCSoSTBdKZ1MVdDadn4rdmZl5GKzQ:uoQ-BeEtodHRwczovL29yYi5kb21haW4yLmNvbS9jYXMvdUVpQlVRRFJJNXR0SXpYYmUxTFpLVWFaV2I2eUZzbk1ucmdEa3NBdFEtd0NhS3c"), //nolint:lll
// Hash in hashlink doesn't match anchor hash.
testutil.MustParseURL("hl:uEiBUQDRI5ttIzXbe1LZKUaZWb6yFsnMnrgDksAtQ-wCaKw:uoQ-BeEtodHRwczovL29yYi5kb21haW4yLmNvbS9jYXMvdUVpQlVRRFJJNXR0SXpYYmUxTFpLVWFaV2I2eUZzbk1ucmdEa3NBdFEtd0NhS3c"), //nolint:lll
// Invalid hashlink.
testutil.MustParseURL("xx:invalid"),
}

linkStore := &mocks.AnchorLinkStore{}

h := New(linkStore)

t.Run("Success", func(t *testing.T) {
linkStore.PutLinksReturns(nil)

require.NoError(t, h.AnchorEventAcknowledged(actor, anchorRef, additionalRefs))
})

t.Run("Anchor link storage error", func(t *testing.T) {
errExpected := errors.New("injected storage error")

linkStore.PutLinksReturns(errExpected)

err := h.AnchorEventAcknowledged(actor, anchorRef, additionalRefs)

require.Error(t, err)
require.Contains(t, err.Error(), errExpected.Error())
})

t.Run("Invalid anchor link", func(t *testing.T) {
require.Error(t, h.AnchorEventAcknowledged(actor, testutil.MustParseURL("xx:invalid"), additionalRefs))
})
}
Loading

0 comments on commit 8820a16

Please sign in to comment.