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

     1  package server
     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/transaction"
    12  	"github.com/storacha/go-ucanto/transport"
    13  	"github.com/storacha/go-ucanto/ucan"
    14  	"github.com/storacha/go-ucanto/validator"
    15  )
    16  
    17  // Option is an option configuring a ucanto server.
    18  type Option func(cfg *srvConfig) error
    19  
    20  type srvConfig struct {
    21  	codec                 transport.InboundCodec
    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  	validateTimeBounds    validator.TimeBoundsValidatorFunc
    29  	authorityProofs       []delegation.Delegation
    30  	altAudiences          []ucan.Principal
    31  	catch                 ErrorHandlerFunc
    32  	logReceipt            ReceiptLoggerFunc
    33  }
    34  
    35  func WithServiceMethod[O ipld.Builder, X failure.IPLDBuilderFailure](can string, handleFunc ServiceMethod[O, X]) Option {
    36  	return func(cfg *srvConfig) error {
    37  		cfg.service[can] = func(ctx context.Context, input invocation.Invocation, invCtx InvocationContext) (transaction.Transaction[ipld.Builder, failure.IPLDBuilderFailure], error) {
    38  			tx, err := handleFunc(ctx, input, invCtx)
    39  			if err != nil {
    40  				return nil, 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())), nil
    48  		}
    49  		return nil
    50  	}
    51  }
    52  
    53  // WithInboundCodec configures the codec used to decode requests and encode
    54  // responses.
    55  func WithInboundCodec(codec transport.InboundCodec) Option {
    56  	return func(cfg *srvConfig) error {
    57  		cfg.codec = codec
    58  		return nil
    59  	}
    60  }
    61  
    62  // WithRevocationChecker configures the function used to check UCANs for
    63  // revocation.
    64  func WithRevocationChecker(fn validator.RevocationCheckerFunc[any]) Option {
    65  	return func(cfg *srvConfig) error {
    66  		cfg.validateAuthorization = fn
    67  		return nil
    68  	}
    69  }
    70  
    71  // WithErrorHandler configures a function to be called when errors occur during
    72  // execution of a handler.
    73  func WithErrorHandler(fn ErrorHandlerFunc) Option {
    74  	return func(cfg *srvConfig) error {
    75  		cfg.catch = fn
    76  		return nil
    77  	}
    78  }
    79  
    80  // WithReceiptLogger configures a function to be called when a receipt is
    81  // issued.
    82  func WithReceiptLogger(fn ReceiptLoggerFunc) Option {
    83  	return func(cfg *srvConfig) error {
    84  		cfg.logReceipt = fn
    85  		return nil
    86  	}
    87  }
    88  
    89  // WithCanIssue configures a function that determines whether a given capability
    90  // can be issued by a given DID or whether it needs to be delegated to the
    91  // issuer.
    92  func WithCanIssue(fn validator.CanIssueFunc[any]) Option {
    93  	return func(cfg *srvConfig) error {
    94  		cfg.canIssue = fn
    95  		return nil
    96  	}
    97  }
    98  
    99  // WithProofResolver configures a function that finds delegations corresponding
   100  // to a given link. If a resolver is not provided the validator may not be able
   101  // to explore corresponding path within a proof chain.
   102  func WithProofResolver(fn validator.ProofResolverFunc) Option {
   103  	return func(cfg *srvConfig) error {
   104  		cfg.resolveProof = fn
   105  		return nil
   106  	}
   107  }
   108  
   109  // WithPrincipalParser configures a function that provides verifier instances
   110  // that can validate UCANs issued by a given principal.
   111  func WithPrincipalParser(fn validator.PrincipalParserFunc) Option {
   112  	return func(cfg *srvConfig) error {
   113  		cfg.parsePrincipal = fn
   114  		return nil
   115  	}
   116  }
   117  
   118  // WithPrincipalResolver configures a function that resolves the key of a
   119  // principal that is identified by DID different from did:key method.
   120  func WithPrincipalResolver(fn validator.PrincipalResolverFunc) Option {
   121  	return func(cfg *srvConfig) error {
   122  		cfg.resolveDIDKey = fn
   123  		return nil
   124  	}
   125  }
   126  
   127  // WithTimeBoundsValidator configures a function that validates the time bounds of a delegation.
   128  func WithTimeBoundsValidator(fn validator.TimeBoundsValidatorFunc) Option {
   129  	return func(cfg *srvConfig) error {
   130  		cfg.validateTimeBounds = fn
   131  		return nil
   132  	}
   133  }
   134  
   135  // WithAuthorityProofs allows to provide a list of proofs that designate other
   136  // principals (beyond the service authority) whose attestations will be recognized as valid.
   137  func WithAuthorityProofs(proofs ...delegation.Delegation) Option {
   138  	return func(cfg *srvConfig) error {
   139  		cfg.authorityProofs = proofs
   140  		return nil
   141  	}
   142  }
   143  
   144  // WithAlternativeAudiences configures a set of alternative audiences that will be assumed by the service.
   145  // Invocations targeted to the service itself or any of the alternative audiences will be accepted.
   146  func WithAlternativeAudiences(audiences ...ucan.Principal) Option {
   147  	return func(cfg *srvConfig) error {
   148  		cfg.altAudiences = audiences
   149  		return nil
   150  	}
   151  }