github.com/storacha/go-ucanto@v0.7.2/ucan/view.go (about) 1 package ucan 2 3 import ( 4 "fmt" 5 6 "github.com/storacha/go-ucanto/did" 7 "github.com/storacha/go-ucanto/ucan/crypto/signature" 8 udm "github.com/storacha/go-ucanto/ucan/datamodel/ucan" 9 ) 10 11 type UCAN interface { 12 // Issuer is the signer of the UCAN. 13 Issuer() Principal 14 // Audience is the principal delegated to. 15 Audience() Principal 16 // Version is the spec version the UCAN conforms to. 17 Version() Version 18 // Capabilities are claimed abilities that can be performed on a resource. 19 Capabilities() []Capability[any] 20 // Expiration is the time in seconds since the Unix epoch that the UCAN 21 // becomes invalid. 22 Expiration() *UTCUnixTimestamp 23 // NotBefore is the time in seconds since the Unix epoch that the UCAN 24 // becomes valid. 25 NotBefore() UTCUnixTimestamp 26 // Nonce is a randomly generated string to provide a unique 27 Nonce() Nonce 28 // Facts are arbitrary facts and proofs of knowledge. 29 Facts() []Fact 30 // Proofs of delegation. 31 Proofs() []Link 32 // Signature of the UCAN issuer. 33 Signature() signature.SignatureView 34 } 35 36 // View represents a decoded "view" of a UCAN that can be used in your 37 // domain logic, etc. 38 type View interface { 39 UCAN 40 // Model references the underlying IPLD datamodel instance. 41 Model() *udm.UCANModel 42 } 43 44 type ucanView struct { 45 model *udm.UCANModel 46 } 47 48 var _ View = (*ucanView)(nil) 49 50 func (v *ucanView) Audience() Principal { 51 did, err := did.Decode(v.model.Aud) 52 if err != nil { 53 fmt.Printf("Error: decoding audience DID: %s\n", err) 54 } 55 return did 56 } 57 58 func (v *ucanView) Capabilities() []Capability[any] { 59 caps := []Capability[any]{} 60 for _, c := range v.model.Att { 61 caps = append(caps, NewCapability[any](c.Can, c.With, c.Nb)) 62 } 63 return caps 64 } 65 66 func (v *ucanView) Expiration() *UTCUnixTimestamp { 67 return v.model.Exp 68 } 69 70 func (v *ucanView) Facts() []map[string]any { 71 facts := []map[string]any{} 72 for _, f := range v.model.Fct { 73 fact := map[string]any{} 74 for k, v := range f.Values { 75 fact[k] = v 76 } 77 facts = append(facts, fact) 78 } 79 return facts 80 } 81 82 func (v *ucanView) Issuer() Principal { 83 did, err := did.Decode(v.model.Iss) 84 if err != nil { 85 fmt.Printf("decoding issuer DID: %s\n", err) 86 } 87 return did 88 } 89 90 func (v *ucanView) Model() *udm.UCANModel { 91 return v.model 92 } 93 94 func (v *ucanView) Nonce() string { 95 if v.model.Nnc == nil { 96 return "" 97 } 98 return *v.model.Nnc 99 } 100 101 func (v *ucanView) NotBefore() int { 102 if v.model.Nbf == nil { 103 return 0 104 } 105 return *v.model.Nbf 106 } 107 108 func (v *ucanView) Proofs() []Link { 109 return v.model.Prf 110 } 111 112 func (v *ucanView) Signature() signature.SignatureView { 113 s := signature.Decode(v.model.S) 114 return signature.NewSignatureView(s) 115 } 116 117 func (v *ucanView) Version() string { 118 return v.model.V 119 } 120 121 // NewUCAN creates a UCAN view from the underlying data model. Please note 122 // that this function does no verification of the model and it is callers 123 // responsibility to ensure that: 124 // 125 // 1. Data model is correct contains all the field etc. 126 // 2. Payload of the signature will match paylodad when model is serialized 127 // with DAG-JSON. 128 // 129 // In other words you should never use this function unless you've parsed or 130 // decoded a valid UCAN and want to wrap it into a view. 131 func NewUCAN(model *udm.UCANModel) (View, error) { 132 return &ucanView{model}, nil 133 }