2024-10-24 10:44:38 -04:00
|
|
|
package invocation
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"time"
|
|
|
|
|
|
|
|
|
|
"github.com/ipfs/go-cid"
|
2024-11-05 17:39:39 +01:00
|
|
|
|
2024-10-24 10:44:38 -04:00
|
|
|
"github.com/ucan-wg/go-ucan/did"
|
2024-11-26 14:39:10 -05:00
|
|
|
"github.com/ucan-wg/go-ucan/pkg/args"
|
2024-10-24 10:44:38 -04:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// Option is a type that allows optional fields to be set during the
|
2024-11-05 17:39:39 +01:00
|
|
|
// creation of an invocation Token.
|
2024-10-24 10:44:38 -04:00
|
|
|
type Option func(*Token) error
|
|
|
|
|
|
|
|
|
|
// WithArgument adds a key/value pair to the Token's Arguments field.
|
2024-11-07 13:50:20 -05:00
|
|
|
func WithArgument(key string, val any) Option {
|
2024-10-24 10:44:38 -04:00
|
|
|
return func(t *Token) error {
|
2024-11-07 13:50:20 -05:00
|
|
|
return t.arguments.Add(key, val)
|
2024-10-24 10:44:38 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-11-26 14:39:10 -05:00
|
|
|
// WithArguments merges the provided arguments into the Token's existing
|
|
|
|
|
// arguments.
|
|
|
|
|
//
|
|
|
|
|
// If duplicate keys are encountered, the new value is silently dropped
|
|
|
|
|
// without causing an error. Since duplicate keys can only be encountered
|
|
|
|
|
// due to previous calls to WithArgument or WithArguments, calling only
|
|
|
|
|
// this function to set the Token's arguments is equivalent to assigning
|
|
|
|
|
// the arguments to the Token.
|
|
|
|
|
func WithArguments(args *args.Args) Option {
|
|
|
|
|
return func(t *Token) error {
|
|
|
|
|
t.arguments.Include(args)
|
|
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-10-24 10:44:38 -04:00
|
|
|
// WithAudience sets the Token's audience to the provided did.DID.
|
|
|
|
|
//
|
2024-12-09 20:39:47 +01:00
|
|
|
// This can be used if the resource on which the token operates on is different
|
|
|
|
|
// from the subject. In that situation, the subject is akin to the "service" and
|
|
|
|
|
// the audience is akin to the resource.
|
|
|
|
|
//
|
2024-10-24 10:44:38 -04:00
|
|
|
// If the provided did.DID is the same as the Token's subject, the
|
|
|
|
|
// audience is not set.
|
|
|
|
|
func WithAudience(aud did.DID) Option {
|
|
|
|
|
return func(t *Token) error {
|
2024-12-09 20:39:47 +01:00
|
|
|
if t.subject != aud {
|
2024-10-24 10:44:38 -04:00
|
|
|
t.audience = aud
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// WithMeta adds a key/value pair in the "meta" field.
|
|
|
|
|
//
|
|
|
|
|
// WithMeta can be used multiple times in the same call.
|
|
|
|
|
// Accepted types for the value are: bool, string, int, int32, int64, []byte,
|
|
|
|
|
// and ipld.Node.
|
|
|
|
|
func WithMeta(key string, val any) Option {
|
|
|
|
|
return func(t *Token) error {
|
|
|
|
|
return t.meta.Add(key, val)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-11-12 16:07:39 +01:00
|
|
|
// WithEncryptedMetaString adds a key/value pair in the "meta" field.
|
|
|
|
|
// The string value is encrypted with the given aesKey.
|
|
|
|
|
func WithEncryptedMetaString(key, val string, encryptionKey []byte) Option {
|
|
|
|
|
return func(t *Token) error {
|
|
|
|
|
return t.meta.AddEncrypted(key, val, encryptionKey)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// WithEncryptedMetaBytes adds a key/value pair in the "meta" field.
|
|
|
|
|
// The []byte value is encrypted with the given aesKey.
|
|
|
|
|
func WithEncryptedMetaBytes(key string, val, encryptionKey []byte) Option {
|
2024-11-12 15:29:48 +01:00
|
|
|
return func(t *Token) error {
|
|
|
|
|
return t.meta.AddEncrypted(key, val, encryptionKey)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-10-24 10:44:38 -04:00
|
|
|
// WithNonce sets the Token's nonce with the given value.
|
|
|
|
|
//
|
|
|
|
|
// If this option is not used, a random 12-byte nonce is generated for
|
2024-11-05 09:35:55 -05:00
|
|
|
// this required field. If you truly want to create an invocation Token
|
|
|
|
|
// without a nonce, use the WithEmptyNonce Option which will set the
|
|
|
|
|
// nonce to an empty byte array.
|
2024-10-24 10:44:38 -04:00
|
|
|
func WithNonce(nonce []byte) Option {
|
|
|
|
|
return func(t *Token) error {
|
|
|
|
|
t.nonce = nonce
|
|
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// WithEmptyNonce sets the Token's nonce to an empty byte slice as
|
|
|
|
|
// suggested by the UCAN spec for invocation tokens that represent
|
2024-11-05 07:39:51 -05:00
|
|
|
// idempotent operations.
|
2024-10-24 10:44:38 -04:00
|
|
|
func WithEmptyNonce() Option {
|
|
|
|
|
return func(t *Token) error {
|
|
|
|
|
t.nonce = []byte{}
|
|
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// WithExpiration set's the Token's optional "expiration" field to the
|
|
|
|
|
// value of the provided time.Time.
|
|
|
|
|
func WithExpiration(exp time.Time) Option {
|
|
|
|
|
return func(t *Token) error {
|
2024-11-04 16:07:11 -05:00
|
|
|
exp = exp.Round(time.Second)
|
2024-10-24 10:44:38 -04:00
|
|
|
t.expiration = &exp
|
|
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// WithExpirationIn set's the Token's optional "expiration" field to
|
|
|
|
|
// Now() plus the given duration.
|
2024-11-05 09:35:55 -05:00
|
|
|
func WithExpirationIn(after time.Duration) Option {
|
|
|
|
|
return WithExpiration(time.Now().Add(after))
|
2024-10-24 10:44:38 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// WithInvokedAt sets the Token's invokedAt field to the provided
|
|
|
|
|
// time.Time.
|
2024-11-05 09:35:55 -05:00
|
|
|
//
|
|
|
|
|
// If this Option is not provided, the invocation Token's iat field will
|
|
|
|
|
// be set to the value of time.Now(). If you want to create an invocation
|
|
|
|
|
// Token without this field being set, use the WithoutInvokedAt Option.
|
2024-10-24 10:44:38 -04:00
|
|
|
func WithInvokedAt(iat time.Time) Option {
|
|
|
|
|
return func(t *Token) error {
|
2025-03-11 12:41:24 -04:00
|
|
|
t.issuedAt = &iat
|
2024-10-24 10:44:38 -04:00
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// WithInvokedAtIn sets the Token's invokedAt field to Now() plus the
|
|
|
|
|
// given duration.
|
|
|
|
|
func WithInvokedAtIn(after time.Duration) Option {
|
2024-11-05 07:39:51 -05:00
|
|
|
return WithInvokedAt(time.Now().Add(after))
|
2024-10-24 10:44:38 -04:00
|
|
|
}
|
|
|
|
|
|
2024-10-24 12:59:38 -04:00
|
|
|
// WithoutInvokedAt clears the Token's invokedAt field.
|
|
|
|
|
func WithoutInvokedAt() Option {
|
|
|
|
|
return func(t *Token) error {
|
2025-03-11 12:41:24 -04:00
|
|
|
t.issuedAt = nil
|
2024-10-24 12:59:38 -04:00
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-10-24 10:44:38 -04:00
|
|
|
// WithCause sets the Token's cause field to the provided cid.Cid.
|
|
|
|
|
func WithCause(cause *cid.Cid) Option {
|
|
|
|
|
return func(t *Token) error {
|
|
|
|
|
t.cause = cause
|
|
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
}
|