From 4201ab2dca07899d08c934479068f9b4b6732e5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20Mur=C3=A9?= Date: Tue, 1 Oct 2024 14:25:07 +0200 Subject: [PATCH] tokens: expose Inspect and FindTag --- tokens/inspect.go | 105 +++++--------------------- tokens/inspect_test.go | 24 ------ tokens/internal/envelope/ipld.go | 32 ++++---- tokens/internal/envelope/ipld_test.go | 23 +++++- 4 files changed, 58 insertions(+), 126 deletions(-) delete mode 100644 tokens/inspect_test.go diff --git a/tokens/inspect.go b/tokens/inspect.go index c4bf134..cfb8a24 100644 --- a/tokens/inspect.go +++ b/tokens/inspect.go @@ -1,90 +1,19 @@ package tokens -// -// // EnvelopeInfo describes the fields of an Envelope enclosing a UCAN token. -// type EnvelopeInfo struct { -// Signature []byte -// Tag string -// VarsigHeader []byte -// } -// -// // InspectEnvelope accepts arbitrary data and attempts to decode it as a -// // UCAN token's Envelope. -// func Inspect(data []byte) (EnvelopeInfo, error) { -// undef := EnvelopeInfo{} -// -// node, err := decodeAny(data) -// if err != nil { -// return undef, err -// } -// -// info, err := envelope.inspect(node) -// if err != nil { -// return undef, err -// } -// -// iterator := info.SigPayloadNode.MapIterator() -// foundVarsigHeader := false -// foundTokenPayload := false -// tag := "" -// i := 0 -// -// for !iterator.Done() { -// k, _, err := iterator.Next() -// if err != nil { -// return undef, err -// } -// -// key, err := k.AsString() -// if err != nil { -// return undef, err -// } -// -// if key == envelope.VarsigHeaderKey { -// foundVarsigHeader = true -// i++ -// -// continue -// } -// -// if strings.HasPrefix(key, envelope.UCANTagPrefix) { -// tag = key -// foundTokenPayload = true -// i++ -// } -// } -// -// if i != 2 { -// return undef, fmt.Errorf("expected two and only two fields in SigPayload: %d", i) -// } -// -// if !foundVarsigHeader { -// return undef, errors.New("failed to find VarsigHeader field") -// } -// -// if !foundTokenPayload { -// return undef, errors.New("failed to find TokenPayload field") -// } -// -// return EnvelopeInfo{ -// Signature: info.Signature, -// Tag: tag, -// VarsigHeader: info.VarsigHeader, -// }, nil -// } -// -// func decodeAny(data []byte) (datamodel.Node, error) { -// for _, decoder := range []codec.Decoder{ -// dagcbor.Decode, -// dagjson.Decode, -// cbor.Decode, -// json.Decode, -// raw.Decode, -// } { -// if node, err := ipld.Decode(data, decoder); err == nil { -// return node, nil -// } -// } -// -// return nil, errors.New("failed to decode (any) the provided data") -// } +import ( + "github.com/ipld/go-ipld-prime/datamodel" + + "github.com/ucan-wg/go-ucan/tokens/internal/envelope" +) + +type Info = envelope.Info + +// Inspect inspects the given token IPLD representation and extract some envelope facts. +func Inspect(node datamodel.Node) (Info, error) { + return envelope.Inspect(node) +} + +// FindTag inspect the given token IPLD representation and extract the token tag. +func FindTag(node datamodel.Node) (string, error) { + return envelope.FindTag(node) +} diff --git a/tokens/inspect_test.go b/tokens/inspect_test.go deleted file mode 100644 index cbaf3b6..0000000 --- a/tokens/inspect_test.go +++ /dev/null @@ -1,24 +0,0 @@ -package tokens_test - -// func TestInspect(t *testing.T) { -// t.Parallel() -// -// for _, filename := range []string{ -// "example.dagcbor", -// "example.dagjson", -// } { -// t.Run(filename, func(t *testing.T) { -// t.Parallel() -// -// data := golden.Get(t, filename) -// expSig, err := base64.RawStdEncoding.DecodeString("fPqfwL3iFpbw9SvBiq0DIbUurv9o6c36R08tC/yslGrJcwV51ghzWahxdetpEf6T5LCszXX9I/K8khvnmAxjAg") -// require.NoError(t, err) -// -// info, err := tokens.Inspect(data) -// require.NoError(t, err) -// assert.Equal(t, expSig, info.Signature) -// assert.Equal(t, "ucan/example@v1.0.0-rc.1", info.Tag) -// assert.Equal(t, []byte{0x34, 0xed, 0x1, 0x71}, info.VarsigHeader) -// }) -// } -// } diff --git a/tokens/internal/envelope/ipld.go b/tokens/internal/envelope/ipld.go index 6803692..3ba3c63 100644 --- a/tokens/internal/envelope/ipld.go +++ b/tokens/internal/envelope/ipld.go @@ -131,15 +131,10 @@ func FromIPLD[T Tokener](node datamodel.Node) (T, error) { return zero, errors.New("data doesn't match the expected type") } - tokenPayloadNode, err := info.sigPayloadNode.LookupByString(info.Tag) - if err != nil { - return zero, err - } - // This needs to be done before converting this node to its schema // representation (afterwards, the field might be renamed os it's safer // to use the wire name). - issuerNode, err := tokenPayloadNode.LookupByString("iss") + issuerNode, err := info.tokenPayloadNode.LookupByString("iss") if err != nil { return zero, err } @@ -149,12 +144,12 @@ func FromIPLD[T Tokener](node datamodel.Node) (T, error) { // unwrapping it. nb := zero.Prototype().Representation().NewBuilder() - err = nb.AssignNode(tokenPayloadNode) + err = nb.AssignNode(info.tokenPayloadNode) if err != nil { return zero, err } - tokenPayloadNode = nb.Build() + tokenPayloadNode := nb.Build() tokenPayload := bindnode.Unwrap(tokenPayloadNode) if tokenPayload == nil { @@ -279,13 +274,17 @@ func ToIPLD(privKey crypto.PrivKey, token Tokener) (datamodel.Node, error) { }) } -// FindTag inspect the given token IPLD representation and extract the token tag. +// FindTag inspects the given token IPLD representation and extract the token tag. func FindTag(node datamodel.Node) (string, error) { sigPayloadNode, err := node.LookupByIndex(1) if err != nil { return "", err } + if sigPayloadNode.Kind() != datamodel.Kind_Map { + return "", fmt.Errorf("unexpected type instead of map") + } + it := sigPayloadNode.MapIterator() i := 0 @@ -313,12 +312,14 @@ func FindTag(node datamodel.Node) (string, error) { } type Info struct { - Tag string - Signature []byte - sigPayloadNode datamodel.Node // private, we don't want to expose that - VarsigHeader []byte + Tag string + Signature []byte + VarsigHeader []byte + sigPayloadNode datamodel.Node // private, we don't want to expose that + tokenPayloadNode datamodel.Node // private, we don't want to expose that } +// Inspect inspects the given token IPLD representation and extract some envelope facts. func Inspect(node datamodel.Node) (Info, error) { var res Info @@ -337,6 +338,10 @@ func Inspect(node datamodel.Node) (Info, error) { return Info{}, err } + if res.sigPayloadNode.Kind() != datamodel.Kind_Map { + return Info{}, fmt.Errorf("unexpected type instead of map") + } + it := res.sigPayloadNode.MapIterator() foundVarsigHeader := false foundTokenPayload := false @@ -368,6 +373,7 @@ func Inspect(node datamodel.Node) (Info, error) { case strings.HasPrefix(key, UCANTagPrefix): foundTokenPayload = true res.Tag = key + res.tokenPayloadNode = v default: return Info{}, fmt.Errorf("unexpected key type %q", key) } diff --git a/tokens/internal/envelope/ipld_test.go b/tokens/internal/envelope/ipld_test.go index 7c8dcc2..76da597 100644 --- a/tokens/internal/envelope/ipld_test.go +++ b/tokens/internal/envelope/ipld_test.go @@ -3,12 +3,16 @@ package envelope_test import ( "bytes" "crypto/sha256" + "encoding/base64" "testing" + "github.com/ipld/go-ipld-prime" + "github.com/ipld/go-ipld-prime/codec/dagcbor" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/ucan-wg/go-ucan/tokens/internal/envelope" "gotest.tools/v3/golden" + + "github.com/ucan-wg/go-ucan/tokens/internal/envelope" ) func TestDecode(t *testing.T) { @@ -149,3 +153,20 @@ func TestHash(t *testing.T) { require.Equal(t, hash1[:], hash2) require.Equal(t, hash1[:], hash3) } + +func TestInspect(t *testing.T) { + t.Parallel() + + data := golden.Get(t, "example.dagcbor") + node, err := ipld.Decode(data, dagcbor.Decode) + require.NoError(t, err) + + expSig, err := base64.RawStdEncoding.DecodeString("fPqfwL3iFpbw9SvBiq0DIbUurv9o6c36R08tC/yslGrJcwV51ghzWahxdetpEf6T5LCszXX9I/K8khvnmAxjAg") + require.NoError(t, err) + + info, err := envelope.Inspect(node) + require.NoError(t, err) + assert.Equal(t, expSig, info.Signature) + assert.Equal(t, "ucan/example@v1.0.0-rc.1", info.Tag) + assert.Equal(t, []byte{0x34, 0xed, 0x1, 0x71}, info.VarsigHeader) +}