wspr: UnionOfBlessings() in js

MultiPart: 2/2

Change-Id: I743c1f6118d293424f3a4d6eb65bf25ab4f51647
diff --git a/services/wspr/internal/app/app.go b/services/wspr/internal/app/app.go
index 05da65a..2f592c9 100644
--- a/services/wspr/internal/app/app.go
+++ b/services/wspr/internal/app/app.go
@@ -824,6 +824,26 @@
 	return jsBlessing, nil
 }
 
+// UnionOfBlessings returns a Blessings object that carries the union of the provided blessings.
+func (c *Controller) UnionOfBlessings(_ *context.T, _ rpc.ServerCall, handles []principal.BlessingsHandle) (*principal.JsBlessings, error) {
+	inputBlessings := make([]security.Blessings, len(handles))
+	for i, handle := range handles {
+		bless := c.GetBlessings(handle)
+		if bless.IsZero() {
+			return nil, verror.New(invalidBlessingsHandle, nil, handle)
+		}
+		inputBlessings[i] = bless
+	}
+
+	outBlessings, err := security.UnionOfBlessings(inputBlessings...)
+	if err != nil {
+		return nil, err
+	}
+
+	jsBlessings := principal.ConvertBlessingsToHandle(outBlessings, c.blessingsCache.GetOrAddHandle(outBlessings))
+	return jsBlessings, nil
+}
+
 // HandleGranterResponse handles the result of a Granter request.
 func (c *Controller) HandleGranterResponse(id int32, data string) {
 	c.Lock()
diff --git a/services/wspr/internal/app/controller.vdl b/services/wspr/internal/app/controller.vdl
index 95daf5b..3f77742 100644
--- a/services/wspr/internal/app/controller.vdl
+++ b/services/wspr/internal/app/controller.vdl
@@ -44,4 +44,6 @@
 
 	// GetDefaultBlessings fetches the default blessings for the principal of the controller.
 	GetDefaultBlessings() (?principal.JsBlessings | error)
+	// UnionOfBlessings returns a Blessings object that carries the union of the provided blessings.
+	UnionOfBlessings(toJoin []principal.BlessingsHandle) (?principal.JsBlessings | error)
 }
diff --git a/services/wspr/internal/app/controller.vdl.go b/services/wspr/internal/app/controller.vdl.go
index 4ffd6c6..115596f 100644
--- a/services/wspr/internal/app/controller.vdl.go
+++ b/services/wspr/internal/app/controller.vdl.go
@@ -51,6 +51,8 @@
 	Signature(ctx *context.T, name string, opts ...rpc.CallOpt) ([]signature.Interface, error)
 	// GetDefaultBlessings fetches the default blessings for the principal of the controller.
 	GetDefaultBlessings(*context.T, ...rpc.CallOpt) (*principal.JsBlessings, error)
+	// UnionOfBlessings returns a Blessings object that carries the union of the provided blessings.
+	UnionOfBlessings(ctx *context.T, toJoin []principal.BlessingsHandle, opts ...rpc.CallOpt) (*principal.JsBlessings, error)
 }
 
 // ControllerClientStub adds universal methods to ControllerClientMethods.
@@ -133,6 +135,11 @@
 	return
 }
 
+func (c implControllerClientStub) UnionOfBlessings(ctx *context.T, i0 []principal.BlessingsHandle, opts ...rpc.CallOpt) (o0 *principal.JsBlessings, err error) {
+	err = v23.GetClient(ctx).Call(ctx, c.name, "UnionOfBlessings", []interface{}{i0}, []interface{}{&o0}, opts...)
+	return
+}
+
 // ControllerServerMethods is the interface a server writer
 // implements for Controller.
 type ControllerServerMethods interface {
@@ -165,6 +172,8 @@
 	Signature(ctx *context.T, call rpc.ServerCall, name string) ([]signature.Interface, error)
 	// GetDefaultBlessings fetches the default blessings for the principal of the controller.
 	GetDefaultBlessings(*context.T, rpc.ServerCall) (*principal.JsBlessings, error)
+	// UnionOfBlessings returns a Blessings object that carries the union of the provided blessings.
+	UnionOfBlessings(ctx *context.T, call rpc.ServerCall, toJoin []principal.BlessingsHandle) (*principal.JsBlessings, error)
 }
 
 // ControllerServerStubMethods is the server interface containing
@@ -254,6 +263,10 @@
 	return s.impl.GetDefaultBlessings(ctx, call)
 }
 
+func (s implControllerServerStub) UnionOfBlessings(ctx *context.T, call rpc.ServerCall, i0 []principal.BlessingsHandle) (*principal.JsBlessings, error) {
+	return s.impl.UnionOfBlessings(ctx, call, i0)
+}
+
 func (s implControllerServerStub) Globber() *rpc.GlobState {
 	return s.gs
 }
@@ -391,5 +404,15 @@
 				{"", ``}, // *principal.JsBlessings
 			},
 		},
+		{
+			Name: "UnionOfBlessings",
+			Doc:  "// UnionOfBlessings returns a Blessings object that carries the union of the provided blessings.",
+			InArgs: []rpc.ArgDesc{
+				{"toJoin", ``}, // []principal.BlessingsHandle
+			},
+			OutArgs: []rpc.ArgDesc{
+				{"", ``}, // *principal.JsBlessings
+			},
+		},
 	},
 }