Skip to content

Commit

Permalink
feat(remote): remote client signs HTTP feed and preview requests
Browse files Browse the repository at this point in the history
  • Loading branch information
b5 committed Feb 11, 2020
1 parent e1a203d commit a742faa
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 0 deletions.
32 changes: 32 additions & 0 deletions remote/peer_sync_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"net/http"
"net/url"
"strings"
"time"

coreiface "github.com/ipfs/interface-go-ipfs-core"
crypto "github.com/libp2p/go-libp2p-core/crypto"
Expand All @@ -24,6 +25,7 @@ import (
"github.com/qri-io/qri/repo"
"github.com/qri-io/qri/repo/profile"
reporef "github.com/qri-io/qri/repo/ref"
"github.com/qri-io/qri/version"
)

var (
Expand Down Expand Up @@ -500,6 +502,28 @@ func (c *PeerSyncClient) AddDataset(ctx context.Context, ref *reporef.DatasetRef
return base.ReplaceRefIfMoreRecent(node.Repo, &prevRef, ref)
}

func (c *PeerSyncClient) signHTTPRequest(req *http.Request) error {
pk := c.node.Repo.PrivateKey()
now := fmt.Sprintf("%d", nowFunc().In(time.UTC).Unix())

// TODO (b5) - we shouldn't be calculating profile IDs here
peerID, err := calcProfileID(pk)
if err != nil {
return err
}

b64Sig, err := signString(pk, requestSigningString(now, peerID, req.URL.Path))
if err != nil {
return err
}

req.Header.Add("timestamp", now)
req.Header.Add("pid", peerID)
req.Header.Add("signature", b64Sig)
req.Header.Add("qri-version", version.String)
return nil
}

// Feeds fetches the first page of featured & recent feeds in one call
func (c *PeerSyncClient) Feeds(ctx context.Context, remoteAddr string) (map[string][]dsref.VersionInfo, error) {
if at := addressType(remoteAddr); at != "http" {
Expand All @@ -512,6 +536,10 @@ func (c *PeerSyncClient) Feeds(ctx context.Context, remoteAddr string) (map[stri
return nil, err
}

if err := c.signHTTPRequest(req); err != nil {
return nil, err
}

res, err := http.DefaultClient.Do(req)
if err != nil {
if strings.Contains(err.Error(), "no such host") {
Expand Down Expand Up @@ -551,6 +579,10 @@ func (c *PeerSyncClient) Preview(ctx context.Context, ref dsref.Ref, remoteAddr
return nil, err
}

if err := c.signHTTPRequest(req); err != nil {
return nil, err
}

res, err := http.DefaultClient.Do(req)
if err != nil {
if strings.Contains(err.Error(), "no such host") {
Expand Down
40 changes: 40 additions & 0 deletions remote/peer_sync_client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"testing"

"github.com/google/go-cmp/cmp"
"github.com/qri-io/dataset"
"github.com/qri-io/qfs"
"github.com/qri-io/qfs/cafs"
"github.com/qri-io/qri/config"
Expand Down Expand Up @@ -83,6 +84,45 @@ func TestClientFeedsAndPreviews(t *testing.T) {
if diff := cmp.Diff(expect, feeds); diff != "" {
t.Errorf("feeds result mismatch (-want +got): \n%s", diff)
}

ds, err := cli.Preview(tr.Ctx, reporef.ConvertToDsref(worldBankRef), server.URL)
if err != nil {
t.Error(err)
}

expectDs := &dataset.Dataset{
Body: []interface{}{float64(100)},
BodyPath: "/ipfs/QmWVxUKnBmbiXai1Wgu6SuMzyZwYRqjt5TXL8xxghN5hWL",
Commit: &dataset.Commit{
Message: "created dataset",
Path: "/ipfs/QmW27MUFMSvPiE3FpmHhSeBZQEuYAppofudDCLvPXVfSLR",
Qri: "cm:0",
Signature: "XLjvPUsiTxtnhkFajlPosxBl+id/tZJB1RWe9BwPpyqg3toIx6qOkhZtXefDh58rX1L0Id1HU0RkVP8sEl0L54d9C4xv25Uzyv3mAvT9VNN5pzblni5TPvU0mHIbawN57hSiywUP3HQLk8VbjRPo6qjpL5DngwvWXe8mAxTPKWwbV9Zx47tJJWImxJC5vLFRUD1KrRarnhYnGRyGaUiOxssaOnzERw49pA/1dDuFCEWghMpARVgWheZCyHN7rVTs+xH8XOTi8/Zz05bKTlpstm57BcCUENKqJgIt7bjsSIh/gHEc+et1A/kO/DBi3vcoKsA1vZI6lFoJzOwlKRKahg==",
Title: "initial commit",
},
Meta: &dataset.Meta{Qri: "md:0", Title: "World Bank Population"},
Name: "world_bank_population",
Path: "/ipfs/QmVeWbw4DJQqWjKXohgTu5JdhVniLPiyb6z6m1duwvXdQe",
Peername: "A",
Qri: "ds:0",
Structure: &dataset.Structure{
Checksum: "QmShoKqAQ98zKKgLrSDGKDCkmAf6Ts1pgk5qPCXkaeshej",
Depth: 1,
Entries: 1,
Format: "json",
Length: 5,
Qri: "st:0",
Schema: map[string]interface{}{"type": string("array")},
},
}

// calling meta has the side-effect of allocating dataset.Meta.meta
// TODO (b5) - this is bad. we need a meta constructor
expectDs.Meta.Meta()

if diff := cmp.Diff(expectDs, ds, cmp.AllowUnexported(dataset.Dataset{}, dataset.Meta{})); diff != "" {
t.Errorf("preview result mismatch (-want +got): \n%s", diff)
}
}

func newMemRepoTestNode(t *testing.T) *p2p.QriNode {
Expand Down

0 comments on commit a742faa

Please sign in to comment.