github.com/storacha/go-ucanto@v0.7.2/server/retrieval/options.go (about)

     1  package retrieval
     2  
     3  import (
     4  	"context"
     5  
     6  	"github.com/storacha/go-ucanto/core/delegation"
     7  	"github.com/storacha/go-ucanto/core/invocation"
     8  	"github.com/storacha/go-ucanto/core/ipld"
     9  	"github.com/storacha/go-ucanto/core/result"
    10  	"github.com/storacha/go-ucanto/core/result/failure"
    11  	"github.com/storacha/go-ucanto/server"
    12  	"github.com/storacha/go-ucanto/server/transaction"
    13  	"github.com/storacha/go-ucanto/ucan"
    14  	"github.com/storacha/go-ucanto/validator"
    15  )
    16  
    17  // Option is an option configuring a ucanto retrieval server. It does not
    18  // include a transport codec option as it must be [headercar].
    19  type Option func(cfg *srvConfig) error
    20  
    21  type srvConfig struct {
    22  	service               Service
    23  	validateAuthorization validator.RevocationCheckerFunc[any]
    24  	canIssue              validator.CanIssueFunc[any]
    25  	resolveProof          validator.ProofResolverFunc
    26  	parsePrincipal        validator.PrincipalParserFunc
    27  	resolveDIDKey         validator.PrincipalResolverFunc
    28  	authorityProofs       []delegation.Delegation
    29  	altAudiences          []ucan.Principal
    30  	catch                 server.ErrorHandlerFunc
    31  	logReceipt            server.ReceiptLoggerFunc
    32  	delegationCache       delegation.Store
    33  }
    34  
    35  func WithServiceMethod[O ipld.Builder, X failure.IPLDBuilderFailure](can string, handler ServiceMethod[O, X]) Option {
    36  	return func(cfg *srvConfig) error {
    37  		cfg.service[can] = func(ctx context.Context, input invocation.Invocation, invCtx server.InvocationContext, req Request) (transaction.Transaction[ipld.Builder, failure.IPLDBuilderFailure], Response, error) {
    38  			tx, resp, err := handler(ctx, input, invCtx, req)
    39  			if err != nil {
    40  				return nil, resp, err
    41  			}
    42  			out := result.MapResultR0(
    43  				tx.Out(),
    44  				func(o O) ipld.Builder { return o },
    45  				func(x X) failure.IPLDBuilderFailure { return x },
    46  			)
    47  			return transaction.NewTransaction(out, transaction.WithEffects(tx.Fx())), resp, nil
    48  		}
    49  		return nil
    50  	}
    51  }
    52  
    53  // WithRevocationChecker configures the function used to check UCANs for
    54  // revocation.
    55  func WithRevocationChecker(fn validator.RevocationCheckerFunc[any]) Option {
    56  	return func(cfg *srvConfig) error {
    57  		cfg.validateAuthorization = fn
    58  		return nil
    59  	}
    60  }
    61  
    62  // WithErrorHandler configures a function to be called when errors occur during
    63  // execution of a handler.
    64  func WithErrorHandler(fn server.ErrorHandlerFunc) Option {
    65  	return func(cfg *srvConfig) error {
    66  		cfg.catch = fn
    67  		return nil
    68  	}
    69  }
    70  
    71  // WithReceiptLogger configures a function to be called when a receipt is generated,
    72  // allowing access to the receipts produced by the server.
    73  func WithReceiptLogger(fn server.ReceiptLoggerFunc) Option {
    74  	return func(cfg *srvConfig) error {
    75  		cfg.logReceipt = fn
    76  		return nil
    77  	}
    78  }
    79  
    80  // WithCanIssue configures a function that determines whether a given capability
    81  // can be issued by a given DID or whether it needs to be delegated to the
    82  // issuer.
    83  func WithCanIssue(fn validator.CanIssueFunc[any]) Option {
    84  	return func(cfg *srvConfig) error {
    85  		cfg.canIssue = fn
    86  		return nil
    87  	}
    88  }
    89  
    90  // WithProofResolver configures a function that finds delegations corresponding
    91  // to a given link. If a resolver is not provided the validator may not be able
    92  // to explore corresponding path within a proof chain.
    93  func WithProofResolver(fn validator.ProofResolverFunc) Option {
    94  	return func(cfg *srvConfig) error {
    95  		cfg.resolveProof = fn
    96  		return nil
    97  	}
    98  }
    99  
   100  // WithPrincipalParser configures a function that provides verifier instances
   101  // that can validate UCANs issued by a given principal.
   102  func WithPrincipalParser(fn validator.PrincipalParserFunc) Option {
   103  	return func(cfg *srvConfig) error {
   104  		cfg.parsePrincipal = fn
   105  		return nil
   106  	}
   107  }
   108  
   109  // WithPrincipalResolver configures a function that resolves the key of a
   110  // principal that is identified by DID different from did:key method.
   111  func WithPrincipalResolver(fn validator.PrincipalResolverFunc) Option {
   112  	return func(cfg *srvConfig) error {
   113  		cfg.resolveDIDKey = fn
   114  		return nil
   115  	}
   116  }
   117  
   118  // WithAuthorityProofs allows to provide a list of proofs that designate other
   119  // principals (beyond the service authority) whose attestations will be recognized as valid.
   120  func WithAuthorityProofs(proofs ...delegation.Delegation) Option {
   121  	return func(cfg *srvConfig) error {
   122  		cfg.authorityProofs = proofs
   123  		return nil
   124  	}
   125  }
   126  
   127  // WithAlternativeAudiences configures a set of alternative audiences that will be assumed by the service.
   128  // Invocations targeted to the service itself or any of the alternative audiences will be accepted.
   129  func WithAlternativeAudiences(audiences ...ucan.Principal) Option {
   130  	return func(cfg *srvConfig) error {
   131  		cfg.altAudiences = audiences
   132  		return nil
   133  	}
   134  }
   135  
   136  // WithDelegationCache configures a delegation cache for the server - if not
   137  // configured an in-memory cache is used.
   138  func WithDelegationCache(cache delegation.Store) Option {
   139  	return func(cfg *srvConfig) error {
   140  		cfg.delegationCache = cache
   141  		return nil
   142  	}
   143  }