16914: "Get current user" is forwarded to LoginCluster
authorPeter Amstutz <peter.amstutz@curii.com>
Mon, 28 Sep 2020 21:00:33 +0000 (17:00 -0400)
committerPeter Amstutz <peter.amstutz@curii.com>
Mon, 28 Sep 2020 21:29:43 +0000 (17:29 -0400)
Results from "get user" and "current user" are now cached, same as
"user list".

Arvados-DCO-1.1-Signed-off-by: Peter Amstutz <peter.amstutz@curii.com>

lib/controller/federation/conn.go

index 61cac9bbabcd1d5128417fe0ab91041981afd207..60cdfbfd42360bc8f92ac291b6bc554d4765047e 100644 (file)
@@ -500,11 +500,49 @@ func (conn *Conn) UserUnsetup(ctx context.Context, options arvados.GetOptions) (
 }
 
 func (conn *Conn) UserGet(ctx context.Context, options arvados.GetOptions) (arvados.User, error) {
-       return conn.chooseBackend(options.UUID).UserGet(ctx, options)
+       resp, err := conn.chooseBackend(options.UUID).UserGet(ctx, options)
+       if err != nil {
+               return resp, err
+       }
+       if options.UUID != resp.UUID {
+               return arvados.User{}, httpErrorf(http.StatusBadGateway, "Had requested %v but response was for %v", options.UUID, resp.UUID)
+       }
+       if options.UUID[:5] != conn.cluster.ClusterID {
+               err = conn.batchUpdateUsers(ctx, arvados.ListOptions{}, []arvados.User{resp})
+               if err != nil {
+                       return arvados.User{}, err
+               }
+       }
+       return resp, nil
 }
 
 func (conn *Conn) UserGetCurrent(ctx context.Context, options arvados.GetOptions) (arvados.User, error) {
-       return conn.chooseBackend(options.UUID).UserGetCurrent(ctx, options)
+       c, ok := auth.FromContext(ctx)
+       if !ok || len(c.Tokens) == 0 {
+               return arvados.User{}, httpErrorf(http.StatusUnauthorized, "Must supply a token")
+       }
+
+       tok := c.Tokens[0]
+       if !strings.HasPrefix(tok, "v2/") || len(tok) < 30 {
+               return conn.localOrLoginCluster().UserGetCurrent(ctx, options)
+       }
+
+       // Contact the cluster that issued the token to find out what
+       // user it belongs to.
+       remote := tok[3:8]
+       resp, err := conn.chooseBackend(remote).UserGetCurrent(ctx, options)
+       if err != nil {
+               return resp, err
+       }
+
+       // If it is a remote cluster that owns the user, update the local user record.
+       if remote != conn.cluster.ClusterID && remote == resp.UUID[:5] {
+               err = conn.batchUpdateUsers(ctx, arvados.ListOptions{}, []arvados.User{resp})
+               if err != nil {
+                       return arvados.User{}, err
+               }
+       }
+       return resp, nil
 }
 
 func (conn *Conn) UserGetSystem(ctx context.Context, options arvados.GetOptions) (arvados.User, error) {