fix(delegation): simplify package API and restore convenient encoding
This commit is contained in:
@@ -1,19 +1,14 @@
|
||||
package delegation
|
||||
|
||||
// Code generated by github.com/launchdarkly/go-options. DO NOT EDIT.
|
||||
|
||||
import "fmt"
|
||||
// Code generated by github.com/selesy/go-options. DO NOT EDIT.
|
||||
|
||||
import (
|
||||
"github.com/ipld/go-ipld-prime/datamodel"
|
||||
"github.com/ucan-wg/go-ucan/did"
|
||||
"time"
|
||||
)
|
||||
|
||||
type ApplyOptionFunc func(c *config) error
|
||||
|
||||
func (f ApplyOptionFunc) apply(c *config) error {
|
||||
return f(c)
|
||||
}
|
||||
type Option func(c *config) error
|
||||
|
||||
func newConfig(options ...Option) (config, error) {
|
||||
var c config
|
||||
@@ -23,152 +18,52 @@ func newConfig(options ...Option) (config, error) {
|
||||
|
||||
func applyConfigOptions(c *config, options ...Option) error {
|
||||
for _, o := range options {
|
||||
if err := o.apply(c); err != nil {
|
||||
if err := o(c); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type Option interface {
|
||||
apply(*config) error
|
||||
}
|
||||
|
||||
type withExpirationImpl struct {
|
||||
o *time.Time
|
||||
}
|
||||
|
||||
func (o withExpirationImpl) apply(c *config) error {
|
||||
c.Expiration = o.o
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o withExpirationImpl) String() string {
|
||||
name := "WithExpiration"
|
||||
|
||||
// hack to avoid go vet error about passing a function to Sprintf
|
||||
var value interface{} = o.o
|
||||
return fmt.Sprintf("%s: %+v", name, value)
|
||||
}
|
||||
|
||||
func WithExpiration(o *time.Time) Option {
|
||||
return withExpirationImpl{
|
||||
o: o,
|
||||
return func(c *config) error {
|
||||
c.Expiration = o
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
type withMetaImpl struct {
|
||||
o map[string]any
|
||||
}
|
||||
|
||||
func (o withMetaImpl) apply(c *config) error {
|
||||
c.Meta = o.o
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o withMetaImpl) String() string {
|
||||
name := "WithMeta"
|
||||
|
||||
// hack to avoid go vet error about passing a function to Sprintf
|
||||
var value interface{} = o.o
|
||||
return fmt.Sprintf("%s: %+v", name, value)
|
||||
}
|
||||
|
||||
func WithMeta(o map[string]any) Option {
|
||||
return withMetaImpl{
|
||||
o: o,
|
||||
func WithMeta(o map[string]datamodel.Node) Option {
|
||||
return func(c *config) error {
|
||||
c.Meta = o
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
type withNoExpirationImpl struct {
|
||||
o bool
|
||||
}
|
||||
|
||||
func (o withNoExpirationImpl) apply(c *config) error {
|
||||
c.NoExpiration = o.o
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o withNoExpirationImpl) String() string {
|
||||
name := "WithNoExpiration"
|
||||
|
||||
// hack to avoid go vet error about passing a function to Sprintf
|
||||
var value interface{} = o.o
|
||||
return fmt.Sprintf("%s: %+v", name, value)
|
||||
}
|
||||
|
||||
func WithNoExpiration(o bool) Option {
|
||||
return withNoExpirationImpl{
|
||||
o: o,
|
||||
return func(c *config) error {
|
||||
c.NoExpiration = o
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
type withNotBeforeImpl struct {
|
||||
o *time.Time
|
||||
}
|
||||
|
||||
func (o withNotBeforeImpl) apply(c *config) error {
|
||||
c.NotBefore = o.o
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o withNotBeforeImpl) String() string {
|
||||
name := "WithNotBefore"
|
||||
|
||||
// hack to avoid go vet error about passing a function to Sprintf
|
||||
var value interface{} = o.o
|
||||
return fmt.Sprintf("%s: %+v", name, value)
|
||||
}
|
||||
|
||||
func WithNotBefore(o *time.Time) Option {
|
||||
return withNotBeforeImpl{
|
||||
o: o,
|
||||
return func(c *config) error {
|
||||
c.NotBefore = o
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
type withSubjectImpl struct {
|
||||
o *did.DID
|
||||
}
|
||||
|
||||
func (o withSubjectImpl) apply(c *config) error {
|
||||
c.Subject = o.o
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o withSubjectImpl) String() string {
|
||||
name := "WithSubject"
|
||||
|
||||
// hack to avoid go vet error about passing a function to Sprintf
|
||||
var value interface{} = o.o
|
||||
return fmt.Sprintf("%s: %+v", name, value)
|
||||
}
|
||||
|
||||
// WithSubject is a did.DID representing the Subject.
|
||||
func WithSubject(o *did.DID) Option {
|
||||
return withSubjectImpl{
|
||||
o: o,
|
||||
return func(c *config) error {
|
||||
c.Subject = o
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
type withPowerlineImpl struct {
|
||||
o bool
|
||||
}
|
||||
|
||||
func (o withPowerlineImpl) apply(c *config) error {
|
||||
c.Powerline = o.o
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o withPowerlineImpl) String() string {
|
||||
name := "WithPowerline"
|
||||
|
||||
// hack to avoid go vet error about passing a function to Sprintf
|
||||
var value interface{} = o.o
|
||||
return fmt.Sprintf("%s: %+v", name, value)
|
||||
}
|
||||
|
||||
func WithPowerline(o bool) Option {
|
||||
return withPowerlineImpl{
|
||||
o: o,
|
||||
return func(c *config) error {
|
||||
c.Powerline = o
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
package delegation
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/ipld/go-ipld-prime/datamodel"
|
||||
"github.com/ipld/go-ipld-prime/node/bindnode"
|
||||
"github.com/ipld/go-ipld-prime/schema"
|
||||
"github.com/libp2p/go-libp2p/core/crypto"
|
||||
"github.com/ucan-wg/go-ucan/capability/command"
|
||||
"github.com/ucan-wg/go-ucan/capability/policy"
|
||||
"github.com/ucan-wg/go-ucan/did"
|
||||
@@ -14,15 +15,19 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
Tag = "ucan/dlg@"
|
||||
Tag = "ucan/dlg@1.0.0-rc.1"
|
||||
)
|
||||
|
||||
//go:generate -command options go run github.com/launchdarkly/go-options
|
||||
//go:generate options -type=config -prefix=With -output=delegatiom_options.go -cmp=false -imports=time,github.com/ucan-wg/go-ucan/did
|
||||
type Delegation struct {
|
||||
envel *envelope.Envelope
|
||||
}
|
||||
|
||||
//go:generate -command options go run github.com/selesy/go-options
|
||||
//go:generate options -type=config -prefix=With -output=delegatiom_options.go -cmp=false -stringer=false -imports=time,github.com/ucan-wg/go-ucan/did,github.com/ipld/go-ipld-prime/datamodel
|
||||
|
||||
type config struct {
|
||||
Expiration *time.Time
|
||||
Meta map[string]any
|
||||
Meta map[string]datamodel.Node
|
||||
NoExpiration bool
|
||||
NotBefore *time.Time
|
||||
// is a did.DID representing the Subject.
|
||||
@@ -30,81 +35,105 @@ type config struct {
|
||||
Powerline bool
|
||||
}
|
||||
|
||||
type Meta struct {
|
||||
Keys []string
|
||||
Values map[string]datamodel.Node
|
||||
}
|
||||
// Required fields for delegation
|
||||
|
||||
func NewMeta(meta map[string]any) Meta {
|
||||
keys := make([]string, len(meta))
|
||||
values := make(map[string]datamodel.Node, len(meta))
|
||||
i := 0
|
||||
// Requirements for root
|
||||
|
||||
for k, v := range meta {
|
||||
keys[i] = k
|
||||
values[k] = bindnode.Wrap(&v, nil)
|
||||
}
|
||||
|
||||
return Meta{
|
||||
Keys: keys,
|
||||
Values: values,
|
||||
}
|
||||
}
|
||||
|
||||
var _ envelope.Tokener = (*Token)(nil)
|
||||
|
||||
type Token struct {
|
||||
// Issuer DID (sender)
|
||||
Issuer did.DID
|
||||
// Audience DID (receiver)
|
||||
Audience did.DID
|
||||
// Principal that the chain is about (the Subject)
|
||||
Subject *did.DID
|
||||
// The Command to eventually invoke
|
||||
Command *command.Command
|
||||
// The delegation policy
|
||||
Policy *policy.Policy
|
||||
// A unique, random nonce
|
||||
Nonce []byte
|
||||
// Arbitrary Metadata
|
||||
Meta Meta
|
||||
// "Not before" UTC Unix Timestamp in seconds (valid from), 53-bits integer
|
||||
NotBefore *time.Time
|
||||
// The timestamp at which the Invocation becomes invalid
|
||||
Expiration *time.Time
|
||||
}
|
||||
|
||||
func New(iss did.DID, aud did.DID, prf []Token, cmd *command.Command, pol *policy.Policy, exp *time.Time, nonce []byte, opts ...Option) (*Token, error) {
|
||||
func New(privKey crypto.PrivKey, iss did.DID, aud did.DID, cmd *command.Command, pol *policy.Policy, exp *time.Time, nonce []byte, opts ...Option) (*Delegation, error) {
|
||||
cfg, err := newConfig(opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tkn := &Token{
|
||||
Issuer: iss,
|
||||
Audience: aud,
|
||||
Subject: cfg.Subject,
|
||||
Command: cmd,
|
||||
Policy: pol,
|
||||
Nonce: nonce,
|
||||
NotBefore: cfg.NotBefore,
|
||||
if !iss.Defined() {
|
||||
return nil, fmt.Errorf("%w: %s", token.ErrMissingRequiredDID, "iss")
|
||||
}
|
||||
|
||||
if !aud.Defined() {
|
||||
return nil, fmt.Errorf("%w: %s", token.ErrMissingRequiredDID, "aud")
|
||||
}
|
||||
audience := aud.String()
|
||||
|
||||
var subject *string
|
||||
if cfg.Subject != nil && cfg.Subject.Defined() {
|
||||
s := cfg.Subject.String()
|
||||
subject = &s
|
||||
}
|
||||
|
||||
policy, err := pol.ToIPLD()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
nonce = []uint8(nonce)
|
||||
|
||||
var notBefore *int
|
||||
if cfg.NotBefore != nil {
|
||||
n := int(cfg.NotBefore.Unix())
|
||||
notBefore = &n
|
||||
}
|
||||
|
||||
var meta *token.Map__String__Any
|
||||
if len(cfg.Meta) > 0 {
|
||||
tkn.Meta = NewMeta(cfg.Meta)
|
||||
m := token.ToIPLDMapStringAny(cfg.Meta)
|
||||
meta = &m
|
||||
}
|
||||
|
||||
var expiration *int
|
||||
if exp != nil && !cfg.NoExpiration {
|
||||
tkn.Expiration = exp
|
||||
e := int(cfg.NotBefore.Unix())
|
||||
expiration = &e
|
||||
}
|
||||
|
||||
return tkn, nil
|
||||
tkn := &token.Token{
|
||||
Issuer: iss.String(),
|
||||
Audience: &audience,
|
||||
Subject: subject,
|
||||
Command: cmd.String(),
|
||||
Policy: &policy,
|
||||
Nonce: &nonce,
|
||||
Meta: meta,
|
||||
NotBefore: notBefore,
|
||||
Expiration: expiration,
|
||||
}
|
||||
|
||||
envel, err := envelope.New(privKey, tkn, Tag)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
dlg := &Delegation{envel: envel}
|
||||
|
||||
if err := dlg.Validate(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return dlg, nil
|
||||
}
|
||||
|
||||
func (d *Token) Tag() string {
|
||||
return Tag
|
||||
type validateFunc func() error
|
||||
|
||||
func (d *Delegation) Validate() error {
|
||||
return errors.Join(
|
||||
d.validateDID("iss", &d.envel.TokenPayload().Issuer, false),
|
||||
d.validateDID("aud", d.envel.TokenPayload().Audience, false),
|
||||
d.validateDID("sub", d.envel.TokenPayload().Subject, true),
|
||||
)
|
||||
}
|
||||
|
||||
func (d *Token) Prototype() schema.TypedPrototype {
|
||||
return bindnode.Prototype((*Token)(nil), mustLoadSchema().TypeByName("Delegation"), token.BindnodeOptions()...)
|
||||
func (d *Delegation) validateDID(fieldName string, identity *string, nullableOrOptional bool) error {
|
||||
if identity == nil && !nullableOrOptional {
|
||||
return fmt.Errorf("a required DID is missing: %s", fieldName)
|
||||
}
|
||||
|
||||
id, err := did.Parse(*identity)
|
||||
if err != nil {
|
||||
|
||||
}
|
||||
|
||||
if !id.Defined() && !id.Key() {
|
||||
return fmt.Errorf("a required DID is missing: %s", fieldName)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
type DID string
|
||||
|
||||
# The Delegation payload MUST describe the authorization claims, who is involved, and its validity period.
|
||||
type Payload struct {
|
||||
# Issuer DID (sender)
|
||||
iss DID
|
||||
# Audience DID (receiver)
|
||||
aud DID
|
||||
# Principal that the chain is about (the Subject)
|
||||
sub optional DID
|
||||
|
||||
# The Command to eventually invoke
|
||||
cmd String
|
||||
|
||||
# The delegation policy
|
||||
# It doesn't seem possible to represent it with a schema.
|
||||
pol Any
|
||||
|
||||
# A unique, random nonce
|
||||
nonce Bytes
|
||||
|
||||
# Arbitrary Metadata
|
||||
meta {String : Any}
|
||||
|
||||
# "Not before" UTC Unix Timestamp in seconds (valid from), 53-bits integer
|
||||
nbf optional Int
|
||||
# The timestamp at which the Invocation becomes invalid
|
||||
exp nullable Int
|
||||
}
|
||||
|
||||
type Delegation struct {
|
||||
# Issuer DID (sender)
|
||||
issuer DID (rename "iss")
|
||||
# Audience DID (receiver)
|
||||
audience DID (rename "aud")
|
||||
# Principal that the chain is about (the Subject)
|
||||
subject optional DID (rename "sub")
|
||||
|
||||
# The Command to eventually invoke
|
||||
command String (rename "cmd")
|
||||
|
||||
# The delegation policy
|
||||
# It doesn't seem possible to represent it with a schema.
|
||||
policy Any (rename "pol")
|
||||
|
||||
# A unique, random nonce
|
||||
nonce Bytes
|
||||
|
||||
# Arbitrary Metadata
|
||||
meta {String : Any}
|
||||
|
||||
# "Not before" UTC Unix Timestamp in seconds (valid from), 53-bits integer
|
||||
notBefore optional Int (rename "nbf")
|
||||
# The timestamp at which the Invocation becomes invalid
|
||||
expiration nullable Int (rename "exp")
|
||||
}
|
||||
|
||||
type Save struct {
|
||||
|
||||
}
|
||||
@@ -1,87 +0,0 @@
|
||||
package delegation_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/ipld/go-ipld-prime"
|
||||
"github.com/ipld/go-ipld-prime/codec/dagjson"
|
||||
"github.com/ipld/go-ipld-prime/node/bindnode"
|
||||
"github.com/ipld/go-ipld-prime/schema"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/ucan-wg/go-ucan/delegation"
|
||||
"github.com/ucan-wg/go-ucan/internal/token"
|
||||
)
|
||||
|
||||
func TestToken_Proto(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
const delegationJson = `
|
||||
{
|
||||
"aud":"did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK",
|
||||
"cmd":"/foo/bar",
|
||||
"exp":123456,
|
||||
"iss":"did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK",
|
||||
"meta":{
|
||||
"bar":"baaar",
|
||||
"foo":"fooo"
|
||||
},
|
||||
"nbf":123456,
|
||||
"nonce":{
|
||||
"/":{
|
||||
"bytes":"c3VwZXItcmFuZG9t"
|
||||
}
|
||||
},
|
||||
"pol":[
|
||||
["==", ".status", "draft"],
|
||||
["all", ".reviewer", [
|
||||
["like", ".email", "*@example.com"]]
|
||||
],
|
||||
["any", ".tags", [
|
||||
["or", [
|
||||
["==", ".", "news"],
|
||||
["==", ".", "press"]]
|
||||
]]
|
||||
]
|
||||
],
|
||||
"sub":"did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK"
|
||||
}
|
||||
`
|
||||
|
||||
proto := (*delegation.Token)(nil).Prototype()
|
||||
|
||||
node, err := ipld.DecodeUsingPrototype([]byte(delegationJson), dagjson.Decode, proto)
|
||||
require.NoError(t, err)
|
||||
|
||||
tkn, ok := bindnode.Unwrap(node).(*delegation.Token)
|
||||
require.True(t, ok)
|
||||
|
||||
t.Log("Token:")
|
||||
t.Log(" Audience:", tkn.Audience)
|
||||
t.Log(" Command: ", tkn.Command)
|
||||
// t.Log(" Expiration: ", token.Expiration)
|
||||
t.Log(" Issuer:", tkn.Issuer)
|
||||
// t.Log(" Meta:", token.Meta)
|
||||
// t.Log(" NotBefore", token.NotBefore)
|
||||
// t.Log(" Nonce:", token.Nonce)
|
||||
// t.Log(" Policy:", token.Policy)
|
||||
t.Log(" Subject:", tkn.Subject)
|
||||
|
||||
// token.Command = nil
|
||||
// token.Meta = nil
|
||||
// token.Policy = nil
|
||||
// token.Expiration = nil
|
||||
// token.NotBefore = nil
|
||||
|
||||
_ = bindnode.Wrap(tkn, proto.Type(), token.BindnodeOptions()...)
|
||||
|
||||
typed, ok := node.(schema.TypedNode)
|
||||
require.True(t, ok)
|
||||
|
||||
json, err := ipld.Encode(typed.Representation(), dagjson.Encode)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.JSONEq(t, delegationJson, string(json))
|
||||
|
||||
t.Log(string(json))
|
||||
t.Fail()
|
||||
}
|
||||
93
delegation/encoding.go
Normal file
93
delegation/encoding.go
Normal file
@@ -0,0 +1,93 @@
|
||||
package delegation
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/ipld/go-ipld-prime"
|
||||
"github.com/ipld/go-ipld-prime/codec"
|
||||
"github.com/ipld/go-ipld-prime/codec/dagcbor"
|
||||
"github.com/ipld/go-ipld-prime/codec/dagjson"
|
||||
"github.com/ipld/go-ipld-prime/datamodel"
|
||||
"github.com/ucan-wg/go-ucan/internal/envelope"
|
||||
)
|
||||
|
||||
// Encode marshals a Delegation to the the format specified by the provided
|
||||
// codec.Encoder.
|
||||
func (d *Delegation) Encode(encFn codec.Encoder) ([]byte, error) {
|
||||
node, err := d.ToIPLD()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return ipld.Encode(node, encFn)
|
||||
}
|
||||
|
||||
// ToDagCbor marshals the Delegation to the DAG-CBOR format.
|
||||
func (d *Delegation) ToDagCbor() ([]byte, error) {
|
||||
return d.Encode(dagcbor.Encode)
|
||||
}
|
||||
|
||||
// ToDagJson marshals the Delegation to the DAG-JSON format.
|
||||
func (d *Delegation) ToDagJson() ([]byte, error) {
|
||||
return d.Encode(dagjson.Encode)
|
||||
}
|
||||
|
||||
// ToIPLD wraps the Delegation in an IPLD datamodel.Node.
|
||||
func (d *Delegation) ToIPLD() (datamodel.Node, error) {
|
||||
return d.envel.Wrap()
|
||||
}
|
||||
|
||||
// Decode unmarshals the input data using the format specified by the
|
||||
// provided codec.Decoder into a Delegation.
|
||||
//
|
||||
// An error is returned if the conversion fails, or if the resulting
|
||||
// Delegation is invalid.
|
||||
func Decode(b []byte, decFn codec.Decoder) (*Delegation, error) {
|
||||
node, err := ipld.Decode(b, decFn)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return FromIPLD(node)
|
||||
}
|
||||
|
||||
// FromDagCbor unmarshals the input data into a Delegation.
|
||||
//
|
||||
// An error is returned if the conversion fails, or if the resulting
|
||||
// Delegation is invalid.
|
||||
func FromDagCbor(data []byte) (*Delegation, error) {
|
||||
return Decode(data, dagcbor.Decode)
|
||||
}
|
||||
|
||||
// FromDagsjon unmarshals the input data into a Delegation.
|
||||
//
|
||||
// An error is returned if the conversion fails, or if the resulting
|
||||
// Delegation is invalid.
|
||||
func FromDagJson(data []byte) (*Delegation, error) {
|
||||
return Decode(data, dagjson.Decode)
|
||||
}
|
||||
|
||||
// FromIPLD unwraps a Delegation from the provided IPLD datamodel.Node
|
||||
//
|
||||
// An error is returned if the conversion fails, or if the resulting
|
||||
// Delegation is invalid.
|
||||
func FromIPLD(node datamodel.Node) (*Delegation, error) {
|
||||
envel, err := envelope.Unwrap(node)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if envel.Tag() != Tag {
|
||||
return nil, fmt.Errorf("wrong tag for TokenPayload: received %s but expected %s", envel.Tag(), Tag)
|
||||
}
|
||||
|
||||
dlg := &Delegation{
|
||||
envel: envel,
|
||||
}
|
||||
|
||||
if err := dlg.Validate(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return dlg, nil
|
||||
}
|
||||
101
delegation/encoding_test.go
Normal file
101
delegation/encoding_test.go
Normal file
@@ -0,0 +1,101 @@
|
||||
package delegation_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/ucan-wg/go-ucan/delegation"
|
||||
)
|
||||
|
||||
func TestEncodingRoundTrip(t *testing.T) {
|
||||
const delegationJson = `
|
||||
[
|
||||
{
|
||||
"/": {
|
||||
"bytes": "QWr0Pk+sSWE1nszuBMQzggbHX4ofJb8QRdwrLJK/AGCx2p4s/xaCRieomfstDjsV4ezBzX1HARvcoNgdwDQ8Aw"
|
||||
}
|
||||
},
|
||||
{
|
||||
"h": {
|
||||
"/": {
|
||||
"bytes": "NO0BcQ"
|
||||
}
|
||||
},
|
||||
"ucan/dlg@1.0.0-rc.1": {
|
||||
"aud": "did:key:z6Mkpzn2n3ZGT2VaqMGSQC3tzmzV4TS9S71iFsDXE1WnoNH2",
|
||||
"cmd": "/foo/bar",
|
||||
"exp": -62135596800,
|
||||
"iss": "did:key:z6Mkpzn2n3ZGT2VaqMGSQC3tzmzV4TS9S71iFsDXE1WnoNH2",
|
||||
"meta": {
|
||||
"bar": "barr",
|
||||
"foo": "fooo"
|
||||
},
|
||||
"nbf": -62135596800,
|
||||
"nonce": {
|
||||
"/": {
|
||||
"bytes": "X93ORvN1QIXrKPyEP5m5XoVK9VLX9nX8VV/+HlWrp9c"
|
||||
}
|
||||
},
|
||||
"pol": [
|
||||
[
|
||||
"==",
|
||||
".status",
|
||||
"draft"
|
||||
],
|
||||
[
|
||||
"all",
|
||||
".reviewer",
|
||||
[
|
||||
"like",
|
||||
".email",
|
||||
"*@example.com"
|
||||
]
|
||||
],
|
||||
[
|
||||
"any",
|
||||
".tags",
|
||||
[
|
||||
"or",
|
||||
[
|
||||
[
|
||||
"==",
|
||||
".",
|
||||
"news"
|
||||
],
|
||||
[
|
||||
"==",
|
||||
".",
|
||||
"press"
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
],
|
||||
"sub": "did:key:z6MktA1uBdCpq4uJBqE9jjMiLyxZBg9a6xgPPKJjMqss6Zc2"
|
||||
}
|
||||
}
|
||||
]
|
||||
`
|
||||
// format: dagJson --> Delegation --> dagCbor --> Delegation --> dagJson
|
||||
// function: FromDagJson() ToDagCbor() FromDagCbor() ToDagJson()
|
||||
|
||||
p1, err := delegation.FromDagJson([]byte(delegationJson))
|
||||
require.NoError(t, err)
|
||||
|
||||
cborBytes, err := p1.ToDagCbor()
|
||||
require.NoError(t, err)
|
||||
fmt.Println("cborBytes length", len(cborBytes))
|
||||
fmt.Println("cbor", string(cborBytes))
|
||||
|
||||
p2, err := delegation.FromDagCbor(cborBytes)
|
||||
require.NoError(t, err)
|
||||
fmt.Println("read Cbor", p2)
|
||||
|
||||
readJson, err := p2.ToDagJson()
|
||||
require.NoError(t, err)
|
||||
fmt.Println("readJson length", len(readJson))
|
||||
fmt.Println("json: ", string(readJson))
|
||||
|
||||
require.JSONEq(t, delegationJson, string(readJson))
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
package delegation
|
||||
|
||||
import (
|
||||
_ "embed"
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"github.com/ipld/go-ipld-prime"
|
||||
"github.com/ipld/go-ipld-prime/schema"
|
||||
)
|
||||
|
||||
//go:embed delegation.ipldsch
|
||||
var schemaBytes []byte
|
||||
|
||||
var (
|
||||
once sync.Once
|
||||
ts *schema.TypeSystem
|
||||
err error
|
||||
)
|
||||
|
||||
func mustLoadSchema() *schema.TypeSystem {
|
||||
once.Do(func() {
|
||||
ts, err = ipld.LoadSchemaBytes(schemaBytes)
|
||||
})
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("failed to load IPLD schema: %s", err))
|
||||
}
|
||||
return ts
|
||||
}
|
||||
|
||||
func PayloadType() schema.Type {
|
||||
return mustLoadSchema().TypeByName("Payload")
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
package delegation
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/ipld/go-ipld-prime"
|
||||
)
|
||||
|
||||
func BenchmarkSchemaLoad(b *testing.B) {
|
||||
b.ReportAllocs()
|
||||
for i := 0; i < b.N; i++ {
|
||||
_, _ = ipld.LoadSchemaBytes(schemaBytes)
|
||||
}
|
||||
}
|
||||
@@ -98,10 +98,16 @@ func Unwrap(node datamodel.Node) (*Envelope, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &Envelope{
|
||||
envel := &Envelope{
|
||||
signature: signature,
|
||||
sigPayload: sigPayload,
|
||||
}, nil
|
||||
}
|
||||
|
||||
if ok, err := envel.Verify(); !ok || err != nil {
|
||||
return nil, fmt.Errorf("envelope was not signed by issuer")
|
||||
}
|
||||
|
||||
return envel, nil
|
||||
}
|
||||
|
||||
// Signature returns the cryptographic signature of the Envelope's
|
||||
|
||||
21
internal/envelope/testdata/example.dagjson
vendored
21
internal/envelope/testdata/example.dagjson
vendored
@@ -1 +1,20 @@
|
||||
[{"/":{"bytes":"PZV6A2aI7n+MlyADqcqmWhkuyNrgUCDz+qSLSnI9bpasOwOhKUTx95m5Nu5CO/INa1LqzHGioD9+PVf6qdtTBg"}},{"h":{"/":{"bytes":"NO0BcQ"}},"ucan/example@v1.0.0-rc.1":{"cmd":"","exp":null,"iss":"did:key:z6MkpuK2Amsu1RqcLGgmHHQHhvmeXCCBVsM4XFSg2cCyg4Nh","sub":null}}]
|
||||
[
|
||||
{
|
||||
"/": {
|
||||
"bytes": "PZV6A2aI7n+MlyADqcqmWhkuyNrgUCDz+qSLSnI9bpasOwOhKUTx95m5Nu5CO/INa1LqzHGioD9+PVf6qdtTBg"
|
||||
}
|
||||
},
|
||||
{
|
||||
"h": {
|
||||
"/": {
|
||||
"bytes": "NO0BcQ"
|
||||
}
|
||||
},
|
||||
"ucan/example@v1.0.0-rc.1": {
|
||||
"cmd": "",
|
||||
"exp": null,
|
||||
"iss": "did:key:z6MkpuK2Amsu1RqcLGgmHHQHhvmeXCCBVsM4XFSg2cCyg4Nh",
|
||||
"sub": null
|
||||
}
|
||||
}
|
||||
]
|
||||
Reference in New Issue
Block a user