From 4aedc4de39cd74ad09b16071453131d648c67ba3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20Mur=C3=A9?= Date: Tue, 18 Mar 2025 18:03:00 +0100 Subject: [PATCH] client: add a convenient PrepareDelegation function --- toolkit/client/client.go | 78 ++++++++++++++++++++++++++++++---------- 1 file changed, 59 insertions(+), 19 deletions(-) diff --git a/toolkit/client/client.go b/toolkit/client/client.go index f9cca09..346c9fe 100644 --- a/toolkit/client/client.go +++ b/toolkit/client/client.go @@ -9,6 +9,8 @@ import ( "github.com/ucan-wg/go-ucan/did" "github.com/ucan-wg/go-ucan/pkg/command" "github.com/ucan-wg/go-ucan/pkg/container" + "github.com/ucan-wg/go-ucan/pkg/policy" + "github.com/ucan-wg/go-ucan/token/delegation" "github.com/ucan-wg/go-ucan/token/invocation" ) @@ -33,26 +35,11 @@ func NewClient(privKey crypto.PrivKey, requester DelegationRequester) (*Client, }, nil } -// PrepareInvoke returns an invocation and the proof delegation, bundled in a container.Writer. +// PrepareInvoke returns an invocation, bundled in a container.Writer with the necessary proofs. func (c *Client) PrepareInvoke(ctx context.Context, cmd command.Command, subject did.DID, opts ...invocation.Option) (container.Writer, error) { - var proof []cid.Cid - - // do we already have a valid proof? - if proof = c.pool.FindProof(c.did, cmd, subject); len(proof) == 0 { - // we need to request a new proof - proofBundles, err := c.requester.RequestDelegation(ctx, c.did, cmd, subject) - if err != nil { - return nil, fmt.Errorf("requesting delegation: %w", err) - } - - // cache the new proofs - for bundle, err := range proofBundles { - if err != nil { - return nil, err - } - proof = append(proof, bundle.Cid) - c.pool.AddBundle(bundle) - } + proof, err := c.findProof(ctx, cmd, subject) + if err != nil { + return nil, err } inv, err := invocation.New(c.did, cmd, subject, proof, opts...) @@ -76,3 +63,56 @@ func (c *Client) PrepareInvoke(ctx context.Context, cmd command.Command, subject return cont, nil } + +// PrepareDelegation returns a new delegation for a third party DID, bundled in a container.Writer with the necessary proofs. +func (c *Client) PrepareDelegation(ctx context.Context, aud did.DID, cmd command.Command, subject did.DID, policies policy.Policy, opts ...delegation.Option) (container.Writer, error) { + proof, err := c.findProof(ctx, cmd, subject) + if err != nil { + return nil, err + } + + dlg, err := delegation.New(c.did, aud, cmd, policies, subject, opts...) + if err != nil { + return nil, err + } + + dlgSealed, _, err := dlg.ToSealed(c.privKey) + if err != nil { + return nil, err + } + + cont := container.NewWriter() + cont.AddSealed(dlgSealed) + for bundle, err := range c.pool.GetBundles(proof) { + if err != nil { + return nil, err + } + cont.AddSealed(bundle.Sealed) + } + + return cont, nil +} + +func (c *Client) findProof(ctx context.Context, cmd command.Command, subject did.DID) ([]cid.Cid, error) { + var proof []cid.Cid + + // do we already have a valid proof? + if proof = c.pool.FindProof(c.did, cmd, subject); len(proof) == 0 { + // we need to request a new proof + proofBundles, err := c.requester.RequestDelegation(ctx, c.did, cmd, subject) + if err != nil { + return nil, fmt.Errorf("requesting delegation: %w", err) + } + + // cache the new proofs + for bundle, err := range proofBundles { + if err != nil { + return nil, err + } + proof = append(proof, bundle.Cid) + c.pool.AddBundle(bundle) + } + } + + return proof, nil +}