Merge pull request #40 from ucan-wg/dlg-example
delegation: make the examples more examply, less testy
This commit is contained in:
@@ -4,10 +4,12 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/ipld/go-ipld-prime"
|
"github.com/ipld/go-ipld-prime"
|
||||||
"github.com/ipld/go-ipld-prime/datamodel"
|
"github.com/ipld/go-ipld-prime/datamodel"
|
||||||
"github.com/ipld/go-ipld-prime/node/basicnode"
|
"github.com/ipld/go-ipld-prime/node/basicnode"
|
||||||
|
"github.com/ipld/go-ipld-prime/printer"
|
||||||
)
|
)
|
||||||
|
|
||||||
var ErrUnsupported = errors.New("failure adding unsupported type to meta")
|
var ErrUnsupported = errors.New("failure adding unsupported type to meta")
|
||||||
@@ -139,6 +141,25 @@ func (m *Meta) Equals(other *Meta) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *Meta) String() string {
|
||||||
|
buf := strings.Builder{}
|
||||||
|
buf.WriteString("{")
|
||||||
|
|
||||||
|
var i int
|
||||||
|
for key, node := range m.Values {
|
||||||
|
if i > 0 {
|
||||||
|
buf.WriteString(", ")
|
||||||
|
}
|
||||||
|
i++
|
||||||
|
buf.WriteString(key)
|
||||||
|
buf.WriteString(":")
|
||||||
|
buf.WriteString(printer.Sprint(node))
|
||||||
|
}
|
||||||
|
|
||||||
|
buf.WriteString("}")
|
||||||
|
return buf.String()
|
||||||
|
}
|
||||||
|
|
||||||
func fqtn(val any) string {
|
func fqtn(val any) string {
|
||||||
var name string
|
var name string
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,11 @@ package policy
|
|||||||
// https://github.com/ucan-wg/delegation/blob/4094d5878b58f5d35055a3b93fccda0b8329ebae/README.md#policy
|
// https://github.com/ucan-wg/delegation/blob/4094d5878b58f5d35055a3b93fccda0b8329ebae/README.md#policy
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/ipld/go-ipld-prime"
|
"github.com/ipld/go-ipld-prime"
|
||||||
|
"github.com/ipld/go-ipld-prime/codec/dagjson"
|
||||||
|
|
||||||
"github.com/ucan-wg/go-ucan/pkg/policy/selector"
|
"github.com/ucan-wg/go-ucan/pkg/policy/selector"
|
||||||
)
|
)
|
||||||
@@ -24,8 +28,20 @@ const (
|
|||||||
|
|
||||||
type Policy []Statement
|
type Policy []Statement
|
||||||
|
|
||||||
|
func (p Policy) String() string {
|
||||||
|
if len(p) == 0 {
|
||||||
|
return "[]"
|
||||||
|
}
|
||||||
|
childs := make([]string, len(p))
|
||||||
|
for i, statement := range p {
|
||||||
|
childs[i] = strings.ReplaceAll(statement.String(), "\n", "\n ")
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("[\n %s\n]", strings.Join(childs, ",\n "))
|
||||||
|
}
|
||||||
|
|
||||||
type Statement interface {
|
type Statement interface {
|
||||||
Kind() string
|
Kind() string
|
||||||
|
String() string
|
||||||
}
|
}
|
||||||
|
|
||||||
type equality struct {
|
type equality struct {
|
||||||
@@ -38,6 +54,14 @@ func (e equality) Kind() string {
|
|||||||
return e.kind
|
return e.kind
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (e equality) String() string {
|
||||||
|
child, err := ipld.Encode(e.value, dagjson.Encode)
|
||||||
|
if err != nil {
|
||||||
|
return "ERROR: INVALID VALUE"
|
||||||
|
}
|
||||||
|
return fmt.Sprintf(`["%s", "%s", %s]`, e.kind, e.selector, strings.ReplaceAll(string(child), "\n", "\n "))
|
||||||
|
}
|
||||||
|
|
||||||
func Equal(selector selector.Selector, value ipld.Node) Statement {
|
func Equal(selector selector.Selector, value ipld.Node) Statement {
|
||||||
return equality{kind: KindEqual, selector: selector, value: value}
|
return equality{kind: KindEqual, selector: selector, value: value}
|
||||||
}
|
}
|
||||||
@@ -66,6 +90,11 @@ func (n negation) Kind() string {
|
|||||||
return KindNot
|
return KindNot
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (n negation) String() string {
|
||||||
|
child := n.statement.String()
|
||||||
|
return fmt.Sprintf(`["%s", "%s"]`, n.Kind(), strings.ReplaceAll(child, "\n", "\n "))
|
||||||
|
}
|
||||||
|
|
||||||
func Not(stmt Statement) Statement {
|
func Not(stmt Statement) Statement {
|
||||||
return negation{statement: stmt}
|
return negation{statement: stmt}
|
||||||
}
|
}
|
||||||
@@ -79,6 +108,14 @@ func (c connective) Kind() string {
|
|||||||
return c.kind
|
return c.kind
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c connective) String() string {
|
||||||
|
childs := make([]string, len(c.statements))
|
||||||
|
for i, statement := range c.statements {
|
||||||
|
childs[i] = strings.ReplaceAll(statement.String(), "\n", "\n ")
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("[\"%s\", [\n %s]]\n", c.kind, strings.Join(childs, ",\n "))
|
||||||
|
}
|
||||||
|
|
||||||
func And(stmts ...Statement) Statement {
|
func And(stmts ...Statement) Statement {
|
||||||
return connective{kind: KindAnd, statements: stmts}
|
return connective{kind: KindAnd, statements: stmts}
|
||||||
}
|
}
|
||||||
@@ -96,6 +133,10 @@ func (n wildcard) Kind() string {
|
|||||||
return KindLike
|
return KindLike
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (n wildcard) String() string {
|
||||||
|
return fmt.Sprintf(`["%s", "%s", "%s"]`, n.Kind(), n.selector, n.pattern)
|
||||||
|
}
|
||||||
|
|
||||||
func Like(selector selector.Selector, pattern string) (Statement, error) {
|
func Like(selector selector.Selector, pattern string) (Statement, error) {
|
||||||
g, err := parseGlob(pattern)
|
g, err := parseGlob(pattern)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -105,6 +146,14 @@ func Like(selector selector.Selector, pattern string) (Statement, error) {
|
|||||||
return wildcard{selector: selector, pattern: g}, nil
|
return wildcard{selector: selector, pattern: g}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func MustLike(selector selector.Selector, pattern string) Statement {
|
||||||
|
g, err := Like(selector, pattern)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return g
|
||||||
|
}
|
||||||
|
|
||||||
type quantifier struct {
|
type quantifier struct {
|
||||||
kind string
|
kind string
|
||||||
selector selector.Selector
|
selector selector.Selector
|
||||||
@@ -115,6 +164,11 @@ func (n quantifier) Kind() string {
|
|||||||
return n.kind
|
return n.kind
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (n quantifier) String() string {
|
||||||
|
child := n.statement.String()
|
||||||
|
return fmt.Sprintf("[\"%s\", \"%s\",\n %s]", n.Kind(), n.selector, strings.ReplaceAll(child, "\n", "\n "))
|
||||||
|
}
|
||||||
|
|
||||||
func All(selector selector.Selector, statement Statement) Statement {
|
func All(selector selector.Selector, statement Statement) Statement {
|
||||||
return quantifier{kind: KindAll, selector: selector, statement: statement}
|
return quantifier{kind: KindAll, selector: selector, statement: statement}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ func Parse(str string) (Selector, error) {
|
|||||||
if len(sel) > 0 && sel[len(sel)-1].Identity() {
|
if len(sel) > 0 && sel[len(sel)-1].Identity() {
|
||||||
return nil, newParseError("selector contains unsupported recursive descent segment: '..'", str, col, tok)
|
return nil, newParseError("selector contains unsupported recursive descent segment: '..'", str, col, tok)
|
||||||
}
|
}
|
||||||
sel = append(sel, Identity)
|
sel = append(sel, segment{".", true, false, false, nil, "", 0})
|
||||||
case "[]":
|
case "[]":
|
||||||
sel = append(sel, segment{tok, false, opt, true, nil, "", 0})
|
sel = append(sel, segment{tok, false, opt, true, nil, "", 0})
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ func (s Selector) String() string {
|
|||||||
return res.String()
|
return res.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
var Identity = segment{".", true, false, false, nil, "", 0}
|
var Identity = MustParse(".")
|
||||||
|
|
||||||
var (
|
var (
|
||||||
indexRegex = regexp.MustCompile(`^-?\d+$`)
|
indexRegex = regexp.MustCompile(`^-?\d+$`)
|
||||||
|
|||||||
@@ -2,10 +2,12 @@ package delegation_test
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"crypto/rand"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/ipfs/go-cid"
|
"github.com/ipfs/go-cid"
|
||||||
"github.com/ipld/go-ipld-prime"
|
"github.com/ipld/go-ipld-prime"
|
||||||
@@ -16,6 +18,8 @@ import (
|
|||||||
"github.com/ucan-wg/go-ucan/did"
|
"github.com/ucan-wg/go-ucan/did"
|
||||||
"github.com/ucan-wg/go-ucan/pkg/command"
|
"github.com/ucan-wg/go-ucan/pkg/command"
|
||||||
"github.com/ucan-wg/go-ucan/pkg/policy"
|
"github.com/ucan-wg/go-ucan/pkg/policy"
|
||||||
|
"github.com/ucan-wg/go-ucan/pkg/policy/literal"
|
||||||
|
"github.com/ucan-wg/go-ucan/pkg/policy/selector"
|
||||||
"github.com/ucan-wg/go-ucan/token/delegation"
|
"github.com/ucan-wg/go-ucan/token/delegation"
|
||||||
"github.com/ucan-wg/go-ucan/token/internal/envelope"
|
"github.com/ucan-wg/go-ucan/token/internal/envelope"
|
||||||
)
|
)
|
||||||
@@ -23,42 +27,58 @@ import (
|
|||||||
// The following example shows how to create a delegation.Token with
|
// The following example shows how to create a delegation.Token with
|
||||||
// distinct DIDs for issuer (iss), audience (aud) and subject (sub).
|
// distinct DIDs for issuer (iss), audience (aud) and subject (sub).
|
||||||
func ExampleNew() {
|
func ExampleNew() {
|
||||||
issuerPrivKey := examplePrivKey(issuerPrivKeyCfg)
|
issPriv, issPub, err := crypto.GenerateEd25519Key(rand.Reader)
|
||||||
audienceDID := exampleDID(AudienceDID)
|
printThenPanicOnErr(err)
|
||||||
command := exampleCommand(subJectCmd)
|
|
||||||
policy := examplePolicy(subjectPol)
|
|
||||||
subjectDID := exampleDID(subjectDID)
|
|
||||||
|
|
||||||
// Don't do this in your code - a nonce should be a cryptographically
|
issDid, err := did.FromPubKey(issPub)
|
||||||
// strong random slice of bytes to ensure the integrity of your private
|
printThenPanicOnErr(err)
|
||||||
// key. For this example, a fixed nonce is required to obtain the fixed
|
fmt.Println("issDid:", issDid)
|
||||||
// printed output (below). If unsure of what value to supply for the
|
|
||||||
// nonce, don't pass the WithNonce option and one will be generated
|
|
||||||
// when the token is created.
|
|
||||||
nonce := []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b}
|
|
||||||
|
|
||||||
tkn, err := delegation.New(
|
audDid := did.MustParse(AudienceDID)
|
||||||
issuerPrivKey,
|
subDid := did.MustParse(subjectDID)
|
||||||
audienceDID,
|
|
||||||
command,
|
// The command defines the shape of the arguments that will be evaluated against the policy
|
||||||
policy,
|
cmd := command.MustParse("/foo/bar")
|
||||||
delegation.WithSubject(subjectDID),
|
|
||||||
delegation.WithNonce(nonce),
|
// The policy defines what is allowed to do.
|
||||||
|
pol := policy.Policy{
|
||||||
|
policy.Equal(selector.MustParse(".status"), literal.String("draft")),
|
||||||
|
policy.All(selector.MustParse(".reviewer"),
|
||||||
|
policy.MustLike(selector.MustParse(".email"), "*@example.com"),
|
||||||
|
),
|
||||||
|
policy.Any(selector.MustParse(".tags"), policy.Or(
|
||||||
|
policy.Equal(selector.Identity, literal.String("news")),
|
||||||
|
policy.Equal(selector.Identity, literal.String("press")),
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
|
||||||
|
tkn, err := delegation.New(issPriv, audDid, cmd, pol,
|
||||||
|
delegation.WithSubject(subDid),
|
||||||
|
delegation.WithExpirationAfter(time.Hour),
|
||||||
|
delegation.WithMeta("foo", "bar"),
|
||||||
|
delegation.WithMeta("baz", 123),
|
||||||
)
|
)
|
||||||
printThenPanicOnErr(err)
|
printThenPanicOnErr(err)
|
||||||
data, id, err := tkn.ToSealed(issuerPrivKey)
|
|
||||||
|
// "Seal", meaning encode and wrap into a signed envelope.
|
||||||
|
data, id, err := tkn.ToSealed(issPriv)
|
||||||
printThenPanicOnErr(err)
|
printThenPanicOnErr(err)
|
||||||
|
|
||||||
printCIDAndSealed(id, data)
|
printCIDAndSealed(id, data)
|
||||||
|
|
||||||
// Output:
|
// Example output:
|
||||||
// CID (base58BTC): zdpuAw26pFuvZa2Z9YAtpZZnWN6VmnRFr7Z8LVY5c7RVWoxGY
|
//
|
||||||
// DAG-CBOR (base64) out: glhAmnAkgfjAx4SA5pzJmtaHRJtTGNpF1y6oqb4yhGoM2H2EUGbBYT4rVDjMKBgCjhdGHjipm00L8iR5SsQh3sIEBaJhaEQ07QFxc3VjYW4vZGxnQDEuMC4wLXJjLjGoY2F1ZHg4ZGlkOmtleTp6Nk1rcTVZbWJKY1RyUEV4TkRpMjZpbXJUQ3BLaGVwakJGQlNIcXJCRE4yQXJQa3ZjY21kaC9mb28vYmFyY2V4cPZjaXNzeDhkaWQ6a2V5Ono2TWtwem4ybjNaR1QyVmFxTUdTUUMzdHptelY0VFM5UzcxaUZzRFhFMVdub05IMmNwb2yDg2I9PWcuc3RhdHVzZWRyYWZ0g2NhbGxpLnJldmlld2Vyg2RsaWtlZi5lbWFpbG0qQGV4YW1wbGUuY29tg2NhbnllLnRhZ3OCYm9ygoNiPT1hLmRuZXdzg2I9PWEuZXByZXNzY3N1Yng4ZGlkOmtleTp6Nk1rdEExdUJkQ3BxNHVKQnFFOWpqTWlMeXhaQmc5YTZ4Z1BQS0pqTXFzczZaYzJkbWV0YaBlbm9uY2VMAAECAwQFBgcICQoL
|
// issDid: did:key:z6MksKbqUiXRKVDHQJ2yezG83M6d68AQbz9rtajULF575X3s
|
||||||
|
//
|
||||||
|
// CID (base58BTC): zdpuAtXJQXZt123WNczSueoBrVcyKoJ2LH1aTmf41dZrisJJA
|
||||||
|
//
|
||||||
|
// DAG-CBOR (base64) out: glhAGCWszoibTPgkBSe5pk03wsB2orGzRKFvxLeqoDTNixxzXTDGKTj4ZfZrGOyCxf6rNW5zP8x2esFKV/akgy/nAaJhaEQ07QFxc3VjYW4vZGxnQDEuMC4wLXJjLjGoY2F1ZHg4ZGlkOmtleTp6Nk1rcTVZbWJKY1RyUEV4TkRpMjZpbXJUQ3BLaGVwakJGQlNIcXJCRE4yQXJQa3ZjY21kaC9mb28vYmFyY2V4cBpnDPLWY2lzc3g4ZGlkOmtleTp6Nk1rc0ticVVpWFJLVkRIUUoyeWV6RzgzTTZkNjhBUWJ6OXJ0YWpVTEY1NzVYM3NjcG9sg4NiPT1nLnN0YXR1c2VkcmFmdINjYWxsaS5yZXZpZXdlcoNkbGlrZWYuZW1haWxtKkBleGFtcGxlLmNvbYNjYW55ZS50YWdzgmJvcoKDYj09YS5kbmV3c4NiPT1hLmVwcmVzc2NzdWJ4OGRpZDprZXk6ejZNa3RBMXVCZENwcTR1SkJxRTlqak1pTHl4WkJnOWE2eGdQUEtKak1xc3M2WmMyZG1ldGGiY2Jhehh7Y2Zvb2NiYXJlbm9uY2VMgb9wlP/cdMKutRg+
|
||||||
|
//
|
||||||
// Converted to DAG-JSON out:
|
// Converted to DAG-JSON out:
|
||||||
// [
|
// [
|
||||||
// {
|
// {
|
||||||
// "/": {
|
// "/": {
|
||||||
// "bytes": "mnAkgfjAx4SA5pzJmtaHRJtTGNpF1y6oqb4yhGoM2H2EUGbBYT4rVDjMKBgCjhdGHjipm00L8iR5SsQh3sIEBQ"
|
// "bytes": "GCWszoibTPgkBSe5pk03wsB2orGzRKFvxLeqoDTNixxzXTDGKTj4ZfZrGOyCxf6rNW5zP8x2esFKV/akgy/nAQ"
|
||||||
// }
|
// }
|
||||||
// },
|
// },
|
||||||
// {
|
// {
|
||||||
@@ -70,12 +90,15 @@ func ExampleNew() {
|
|||||||
// "ucan/dlg@1.0.0-rc.1": {
|
// "ucan/dlg@1.0.0-rc.1": {
|
||||||
// "aud": "did:key:z6Mkq5YmbJcTrPExNDi26imrTCpKhepjBFBSHqrBDN2ArPkv",
|
// "aud": "did:key:z6Mkq5YmbJcTrPExNDi26imrTCpKhepjBFBSHqrBDN2ArPkv",
|
||||||
// "cmd": "/foo/bar",
|
// "cmd": "/foo/bar",
|
||||||
// "exp": null,
|
// "exp": 1728901846,
|
||||||
// "iss": "did:key:z6Mkpzn2n3ZGT2VaqMGSQC3tzmzV4TS9S71iFsDXE1WnoNH2",
|
// "iss": "did:key:z6MksKbqUiXRKVDHQJ2yezG83M6d68AQbz9rtajULF575X3s",
|
||||||
// "meta": {},
|
// "meta": {
|
||||||
|
// "baz": 123,
|
||||||
|
// "foo": "bar"
|
||||||
|
// },
|
||||||
// "nonce": {
|
// "nonce": {
|
||||||
// "/": {
|
// "/": {
|
||||||
// "bytes": "AAECAwQFBgcICQoL"
|
// "bytes": "gb9wlP/cdMKutRg+"
|
||||||
// }
|
// }
|
||||||
// },
|
// },
|
||||||
// "pol": [
|
// "pol": [
|
||||||
@@ -123,40 +146,56 @@ func ExampleNew() {
|
|||||||
// - a delegation.Token with the subject (sub) set to the value of issuer
|
// - a delegation.Token with the subject (sub) set to the value of issuer
|
||||||
// (iss).
|
// (iss).
|
||||||
func ExampleRoot() {
|
func ExampleRoot() {
|
||||||
issuerPrivKey := examplePrivKey(issuerPrivKeyCfg)
|
issPriv, issPub, err := crypto.GenerateEd25519Key(rand.Reader)
|
||||||
audienceDID := exampleDID(AudienceDID)
|
printThenPanicOnErr(err)
|
||||||
command := exampleCommand(subJectCmd)
|
|
||||||
policy := examplePolicy(subjectPol)
|
|
||||||
|
|
||||||
// Don't do this in your code - a nonce should be a cryptographically
|
issDid, err := did.FromPubKey(issPub)
|
||||||
// strong random slice of bytes to ensure the integrity of your private
|
printThenPanicOnErr(err)
|
||||||
// key. For this example, a fixed nonce is required to obtain the fixed
|
fmt.Println("issDid:", issDid)
|
||||||
// printed output (below). If unsure of what value to supply for the
|
|
||||||
// nonce, don't pass the WithNonce option and one will be generated
|
|
||||||
// when the token is created.
|
|
||||||
nonce := []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b}
|
|
||||||
|
|
||||||
tkn, err := delegation.Root(
|
audDid := did.MustParse(AudienceDID)
|
||||||
issuerPrivKey,
|
|
||||||
audienceDID,
|
// The command defines the shape of the arguments that will be evaluated against the policy
|
||||||
command,
|
cmd := command.MustParse("/foo/bar")
|
||||||
policy,
|
|
||||||
delegation.WithNonce(nonce),
|
// The policy defines what is allowed to do.
|
||||||
|
pol := policy.Policy{
|
||||||
|
policy.Equal(selector.MustParse(".status"), literal.String("draft")),
|
||||||
|
policy.All(selector.MustParse(".reviewer"),
|
||||||
|
policy.MustLike(selector.MustParse(".email"), "*@example.com"),
|
||||||
|
),
|
||||||
|
policy.Any(selector.MustParse(".tags"), policy.Or(
|
||||||
|
policy.Equal(selector.Identity, literal.String("news")),
|
||||||
|
policy.Equal(selector.Identity, literal.String("press")),
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
|
||||||
|
tkn, err := delegation.Root(issPriv, audDid, cmd, pol,
|
||||||
|
delegation.WithExpirationAfter(time.Hour),
|
||||||
|
delegation.WithMeta("foo", "bar"),
|
||||||
|
delegation.WithMeta("baz", 123),
|
||||||
)
|
)
|
||||||
printThenPanicOnErr(err)
|
printThenPanicOnErr(err)
|
||||||
data, id, err := tkn.ToSealed(issuerPrivKey)
|
|
||||||
|
// "Seal", meaning encode and wrap into a signed envelope.
|
||||||
|
data, id, err := tkn.ToSealed(issPriv)
|
||||||
printThenPanicOnErr(err)
|
printThenPanicOnErr(err)
|
||||||
|
|
||||||
printCIDAndSealed(id, data)
|
printCIDAndSealed(id, data)
|
||||||
|
|
||||||
// Output:
|
// Example output:
|
||||||
// CID (base58BTC): zdpuAnbsR3e6DK8hBk5WA7KwbHYN6CKY4a3Bv1GNehvFYShQ8
|
//
|
||||||
// DAG-CBOR (base64) out: glhA67ASBczF/wlIP0ESENn+4ZNQKukjcTNz+fo7K2tYa6OUm0rWICDJJkDWm7lJeQt+KvSA+Y4ctHTQbAr3Lr7mDqJhaEQ07QFxc3VjYW4vZGxnQDEuMC4wLXJjLjGoY2F1ZHg4ZGlkOmtleTp6Nk1rcTVZbWJKY1RyUEV4TkRpMjZpbXJUQ3BLaGVwakJGQlNIcXJCRE4yQXJQa3ZjY21kaC9mb28vYmFyY2V4cPZjaXNzeDhkaWQ6a2V5Ono2TWtwem4ybjNaR1QyVmFxTUdTUUMzdHptelY0VFM5UzcxaUZzRFhFMVdub05IMmNwb2yDg2I9PWcuc3RhdHVzZWRyYWZ0g2NhbGxpLnJldmlld2Vyg2RsaWtlZi5lbWFpbG0qQGV4YW1wbGUuY29tg2NhbnllLnRhZ3OCYm9ygoNiPT1hLmRuZXdzg2I9PWEuZXByZXNzY3N1Yng4ZGlkOmtleTp6Nk1rcHpuMm4zWkdUMlZhcU1HU1FDM3R6bXpWNFRTOVM3MWlGc0RYRTFXbm9OSDJkbWV0YaBlbm9uY2VMAAECAwQFBgcICQoL
|
// issDid: did:key:z6MkshW2ADRrmfBuuBpKJiyNd7acLK1yjnxFJuBimwjQ4Bo5
|
||||||
|
//
|
||||||
|
// CID (base58BTC): zdpuAoBzE3kJK1qZC9EXH7h6iCwym1TqfxT9XzUfFNfcjcAKh
|
||||||
|
//
|
||||||
|
// DAG-CBOR (base64) out: glhADpyBSrTdRn2oZdJU26CjgFbaH7LbTDWyyAdgIwAW0p151XSdJwoBS2vTCp0+7sEkf4X2wl6N5IhxiKyQ8OkbCaJhaEQ07QFxc3VjYW4vZGxnQDEuMC4wLXJjLjGoY2F1ZHg4ZGlkOmtleTp6Nk1rcTVZbWJKY1RyUEV4TkRpMjZpbXJUQ3BLaGVwakJGQlNIcXJCRE4yQXJQa3ZjY21kaC9mb28vYmFyY2V4cBpnDPPCY2lzc3g4ZGlkOmtleTp6Nk1rc2hXMkFEUnJtZkJ1dUJwS0ppeU5kN2FjTEsxeWpueEZKdUJpbXdqUTRCbzVjcG9sg4NiPT1nLnN0YXR1c2VkcmFmdINjYWxsaS5yZXZpZXdlcoNkbGlrZWYuZW1haWxtKkBleGFtcGxlLmNvbYNjYW55ZS50YWdzgmJvcoKDYj09YS5kbmV3c4NiPT1hLmVwcmVzc2NzdWJ4OGRpZDprZXk6ejZNa3NoVzJBRFJybWZCdXVCcEtKaXlOZDdhY0xLMXlqbnhGSnVCaW13alE0Qm81ZG1ldGGiY2Jhehh7Y2Zvb2NiYXJlbm9uY2VMDmBGXMa/TCvhLHqu
|
||||||
|
//
|
||||||
// Converted to DAG-JSON out:
|
// Converted to DAG-JSON out:
|
||||||
// [
|
// [
|
||||||
// {
|
// {
|
||||||
// "/": {
|
// "/": {
|
||||||
// "bytes": "67ASBczF/wlIP0ESENn+4ZNQKukjcTNz+fo7K2tYa6OUm0rWICDJJkDWm7lJeQt+KvSA+Y4ctHTQbAr3Lr7mDg"
|
// "bytes": "DpyBSrTdRn2oZdJU26CjgFbaH7LbTDWyyAdgIwAW0p151XSdJwoBS2vTCp0+7sEkf4X2wl6N5IhxiKyQ8OkbCQ"
|
||||||
// }
|
// }
|
||||||
// },
|
// },
|
||||||
// {
|
// {
|
||||||
@@ -168,12 +207,15 @@ func ExampleRoot() {
|
|||||||
// "ucan/dlg@1.0.0-rc.1": {
|
// "ucan/dlg@1.0.0-rc.1": {
|
||||||
// "aud": "did:key:z6Mkq5YmbJcTrPExNDi26imrTCpKhepjBFBSHqrBDN2ArPkv",
|
// "aud": "did:key:z6Mkq5YmbJcTrPExNDi26imrTCpKhepjBFBSHqrBDN2ArPkv",
|
||||||
// "cmd": "/foo/bar",
|
// "cmd": "/foo/bar",
|
||||||
// "exp": null,
|
// "exp": 1728902082,
|
||||||
// "iss": "did:key:z6Mkpzn2n3ZGT2VaqMGSQC3tzmzV4TS9S71iFsDXE1WnoNH2",
|
// "iss": "did:key:z6MkshW2ADRrmfBuuBpKJiyNd7acLK1yjnxFJuBimwjQ4Bo5",
|
||||||
// "meta": {},
|
// "meta": {
|
||||||
|
// "baz": 123,
|
||||||
|
// "foo": "bar"
|
||||||
|
// },
|
||||||
// "nonce": {
|
// "nonce": {
|
||||||
// "/": {
|
// "/": {
|
||||||
// "bytes": "AAECAwQFBgcICQoL"
|
// "bytes": "DmBGXMa/TCvhLHqu"
|
||||||
// }
|
// }
|
||||||
// },
|
// },
|
||||||
// "pol": [
|
// "pol": [
|
||||||
@@ -211,7 +253,7 @@ func ExampleRoot() {
|
|||||||
// ]
|
// ]
|
||||||
// ]
|
// ]
|
||||||
// ],
|
// ],
|
||||||
// "sub": "did:key:z6Mkpzn2n3ZGT2VaqMGSQC3tzmzV4TS9S71iFsDXE1WnoNH2"
|
// "sub": "did:key:z6MkshW2ADRrmfBuuBpKJiyNd7acLK1yjnxFJuBimwjQ4Bo5"
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
// ]
|
// ]
|
||||||
@@ -220,8 +262,10 @@ func ExampleRoot() {
|
|||||||
// The following example demonstrates how to get a delegation.Token from
|
// The following example demonstrates how to get a delegation.Token from
|
||||||
// a DAG-CBOR []byte.
|
// a DAG-CBOR []byte.
|
||||||
func ExampleToken_FromSealed() {
|
func ExampleToken_FromSealed() {
|
||||||
cborBytes := exampleCBORData()
|
const cborBase64 = "glhAmnAkgfjAx4SA5pzJmtaHRJtTGNpF1y6oqb4yhGoM2H2EUGbBYT4rVDjMKBgCjhdGHjipm00L8iR5SsQh3sIEBaJhaEQ07QFxc3VjYW4vZGxnQDEuMC4wLXJjLjGoY2F1ZHg4ZGlkOmtleTp6Nk1rcTVZbWJKY1RyUEV4TkRpMjZpbXJUQ3BLaGVwakJGQlNIcXJCRE4yQXJQa3ZjY21kaC9mb28vYmFyY2V4cPZjaXNzeDhkaWQ6a2V5Ono2TWtwem4ybjNaR1QyVmFxTUdTUUMzdHptelY0VFM5UzcxaUZzRFhFMVdub05IMmNwb2yDg2I9PWcuc3RhdHVzZWRyYWZ0g2NhbGxpLnJldmlld2Vyg2RsaWtlZi5lbWFpbG0qQGV4YW1wbGUuY29tg2NhbnllLnRhZ3OCYm9ygoNiPT1hLmRuZXdzg2I9PWEuZXByZXNzY3N1Yng4ZGlkOmtleTp6Nk1rdEExdUJkQ3BxNHVKQnFFOWpqTWlMeXhaQmc5YTZ4Z1BQS0pqTXFzczZaYzJkbWV0YaBlbm9uY2VMAAECAwQFBgcICQoL"
|
||||||
fmt.Println("DAG-CBOR (base64) in:", base64.StdEncoding.EncodeToString(cborBytes))
|
|
||||||
|
cborBytes, err := base64.StdEncoding.DecodeString(cborBase64)
|
||||||
|
printThenPanicOnErr(err)
|
||||||
|
|
||||||
tkn, c, err := delegation.FromSealed(cborBytes)
|
tkn, c, err := delegation.FromSealed(cborBytes)
|
||||||
printThenPanicOnErr(err)
|
printThenPanicOnErr(err)
|
||||||
@@ -231,64 +275,34 @@ func ExampleToken_FromSealed() {
|
|||||||
fmt.Println("Audience (aud):", tkn.Audience().String())
|
fmt.Println("Audience (aud):", tkn.Audience().String())
|
||||||
fmt.Println("Subject (sub):", tkn.Subject().String())
|
fmt.Println("Subject (sub):", tkn.Subject().String())
|
||||||
fmt.Println("Command (cmd):", tkn.Command().String())
|
fmt.Println("Command (cmd):", tkn.Command().String())
|
||||||
fmt.Println("Policy (pol): TODO")
|
fmt.Println("Policy (pol):", tkn.Policy().String())
|
||||||
fmt.Println("Nonce (nonce):", hex.EncodeToString(tkn.Nonce()))
|
fmt.Println("Nonce (nonce):", hex.EncodeToString(tkn.Nonce()))
|
||||||
fmt.Println("Meta (meta): TODO")
|
fmt.Println("Meta (meta):", tkn.Meta().String())
|
||||||
fmt.Println("NotBefore (nbf):", tkn.NotBefore())
|
fmt.Println("NotBefore (nbf):", tkn.NotBefore())
|
||||||
fmt.Println("Expiration (exp):", tkn.Expiration())
|
fmt.Println("Expiration (exp):", tkn.Expiration())
|
||||||
|
|
||||||
// Output:
|
// Output:
|
||||||
// DAG-CBOR (base64) in: glhAmnAkgfjAx4SA5pzJmtaHRJtTGNpF1y6oqb4yhGoM2H2EUGbBYT4rVDjMKBgCjhdGHjipm00L8iR5SsQh3sIEBaJhaEQ07QFxc3VjYW4vZGxnQDEuMC4wLXJjLjGoY2F1ZHg4ZGlkOmtleTp6Nk1rcTVZbWJKY1RyUEV4TkRpMjZpbXJUQ3BLaGVwakJGQlNIcXJCRE4yQXJQa3ZjY21kaC9mb28vYmFyY2V4cPZjaXNzeDhkaWQ6a2V5Ono2TWtwem4ybjNaR1QyVmFxTUdTUUMzdHptelY0VFM5UzcxaUZzRFhFMVdub05IMmNwb2yDg2I9PWcuc3RhdHVzZWRyYWZ0g2NhbGxpLnJldmlld2Vyg2RsaWtlZi5lbWFpbG0qQGV4YW1wbGUuY29tg2NhbnllLnRhZ3OCYm9ygoNiPT1hLmRuZXdzg2I9PWEuZXByZXNzY3N1Yng4ZGlkOmtleTp6Nk1rdEExdUJkQ3BxNHVKQnFFOWpqTWlMeXhaQmc5YTZ4Z1BQS0pqTXFzczZaYzJkbWV0YaBlbm9uY2VMAAECAwQFBgcICQoL
|
|
||||||
// CID (base58BTC): zdpuAw26pFuvZa2Z9YAtpZZnWN6VmnRFr7Z8LVY5c7RVWoxGY
|
// CID (base58BTC): zdpuAw26pFuvZa2Z9YAtpZZnWN6VmnRFr7Z8LVY5c7RVWoxGY
|
||||||
// Issuer (iss): did:key:z6Mkpzn2n3ZGT2VaqMGSQC3tzmzV4TS9S71iFsDXE1WnoNH2
|
// Issuer (iss): did:key:z6Mkpzn2n3ZGT2VaqMGSQC3tzmzV4TS9S71iFsDXE1WnoNH2
|
||||||
// Audience (aud): did:key:z6Mkq5YmbJcTrPExNDi26imrTCpKhepjBFBSHqrBDN2ArPkv
|
// Audience (aud): did:key:z6Mkq5YmbJcTrPExNDi26imrTCpKhepjBFBSHqrBDN2ArPkv
|
||||||
// Subject (sub): did:key:z6MktA1uBdCpq4uJBqE9jjMiLyxZBg9a6xgPPKJjMqss6Zc2
|
// Subject (sub): did:key:z6MktA1uBdCpq4uJBqE9jjMiLyxZBg9a6xgPPKJjMqss6Zc2
|
||||||
// Command (cmd): /foo/bar
|
// Command (cmd): /foo/bar
|
||||||
// Policy (pol): TODO
|
// Policy (pol): [
|
||||||
|
// ["==", ".status", "draft"],
|
||||||
|
// ["all", ".reviewer",
|
||||||
|
// ["like", ".email", "*@example.com"]],
|
||||||
|
// ["any", ".tags",
|
||||||
|
// ["or", [
|
||||||
|
// ["==", ".", "news"],
|
||||||
|
// ["==", ".", "press"]]]
|
||||||
|
// ]
|
||||||
|
// ]
|
||||||
// Nonce (nonce): 000102030405060708090a0b
|
// Nonce (nonce): 000102030405060708090a0b
|
||||||
// Meta (meta): TODO
|
// Meta (meta): {}
|
||||||
// NotBefore (nbf): <nil>
|
// NotBefore (nbf): <nil>
|
||||||
// Expiration (exp): <nil>
|
// Expiration (exp): <nil>
|
||||||
}
|
}
|
||||||
|
|
||||||
func exampleCBORData() []byte {
|
|
||||||
data, err := base64.StdEncoding.DecodeString("glhAmnAkgfjAx4SA5pzJmtaHRJtTGNpF1y6oqb4yhGoM2H2EUGbBYT4rVDjMKBgCjhdGHjipm00L8iR5SsQh3sIEBaJhaEQ07QFxc3VjYW4vZGxnQDEuMC4wLXJjLjGoY2F1ZHg4ZGlkOmtleTp6Nk1rcTVZbWJKY1RyUEV4TkRpMjZpbXJUQ3BLaGVwakJGQlNIcXJCRE4yQXJQa3ZjY21kaC9mb28vYmFyY2V4cPZjaXNzeDhkaWQ6a2V5Ono2TWtwem4ybjNaR1QyVmFxTUdTUUMzdHptelY0VFM5UzcxaUZzRFhFMVdub05IMmNwb2yDg2I9PWcuc3RhdHVzZWRyYWZ0g2NhbGxpLnJldmlld2Vyg2RsaWtlZi5lbWFpbG0qQGV4YW1wbGUuY29tg2NhbnllLnRhZ3OCYm9ygoNiPT1hLmRuZXdzg2I9PWEuZXByZXNzY3N1Yng4ZGlkOmtleTp6Nk1rdEExdUJkQ3BxNHVKQnFFOWpqTWlMeXhaQmc5YTZ4Z1BQS0pqTXFzczZaYzJkbWV0YaBlbm9uY2VMAAECAwQFBgcICQoL")
|
|
||||||
printThenPanicOnErr(err)
|
|
||||||
|
|
||||||
return data
|
|
||||||
}
|
|
||||||
|
|
||||||
func exampleDID(didStr string) did.DID {
|
|
||||||
id, err := did.Parse(didStr)
|
|
||||||
printThenPanicOnErr(err)
|
|
||||||
|
|
||||||
return id
|
|
||||||
}
|
|
||||||
|
|
||||||
func exampleCommand(cmdStr string) command.Command {
|
|
||||||
cmd, err := command.Parse(cmdStr)
|
|
||||||
printThenPanicOnErr(err)
|
|
||||||
|
|
||||||
return cmd
|
|
||||||
}
|
|
||||||
|
|
||||||
func examplePolicy(policyJSON string) policy.Policy {
|
|
||||||
pol, err := policy.FromDagJson(policyJSON)
|
|
||||||
printThenPanicOnErr(err)
|
|
||||||
|
|
||||||
return pol
|
|
||||||
}
|
|
||||||
|
|
||||||
func examplePrivKey(privKeyCfg string) crypto.PrivKey {
|
|
||||||
privKeyMar, err := crypto.ConfigDecodeKey(privKeyCfg)
|
|
||||||
printThenPanicOnErr(err)
|
|
||||||
|
|
||||||
privKey, err := crypto.UnmarshalPrivateKey(privKeyMar)
|
|
||||||
printThenPanicOnErr(err)
|
|
||||||
|
|
||||||
return privKey
|
|
||||||
}
|
|
||||||
|
|
||||||
func printCIDAndSealed(id cid.Cid, data []byte) {
|
func printCIDAndSealed(id cid.Cid, data []byte) {
|
||||||
fmt.Println("CID (base58BTC):", envelope.CIDToBase58BTC(id))
|
fmt.Println("CID (base58BTC):", envelope.CIDToBase58BTC(id))
|
||||||
fmt.Println("DAG-CBOR (base64) out:", base64.StdEncoding.EncodeToString(data))
|
fmt.Println("DAG-CBOR (base64) out:", base64.StdEncoding.EncodeToString(data))
|
||||||
|
|||||||
@@ -24,6 +24,15 @@ func WithExpiration(exp time.Time) Option {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WithExpirationAfter set's the Token's optional "expiration" field to Now() plus the given duration.
|
||||||
|
func WithExpirationAfter(exp time.Duration) Option {
|
||||||
|
return func(t *Token) error {
|
||||||
|
expTime := time.Now().Add(exp)
|
||||||
|
t.expiration = &expTime
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// WithMeta adds a key/value pair in the "meta" field.
|
// WithMeta adds a key/value pair in the "meta" field.
|
||||||
//
|
//
|
||||||
// WithMeta can be used multiple times in the same call.
|
// WithMeta can be used multiple times in the same call.
|
||||||
@@ -52,7 +61,7 @@ func WithNotBefore(nbf time.Time) Option {
|
|||||||
// provided did.DID.
|
// provided did.DID.
|
||||||
//
|
//
|
||||||
// This Option should only be used with the New constructor - since
|
// This Option should only be used with the New constructor - since
|
||||||
// Subject is a required parameter when creating a Token via the Root
|
// Subject is a required parameter when creating a Token via the Root
|
||||||
// constructor, any value provided via this Option will be silently
|
// constructor, any value provided via this Option will be silently
|
||||||
// overwritten.
|
// overwritten.
|
||||||
func WithSubject(sub did.DID) Option {
|
func WithSubject(sub did.DID) Option {
|
||||||
|
|||||||
Reference in New Issue
Block a user