X-Git-Url: https://git.arvados.org/arvados.git/blobdiff_plain/6004ef0180d72531d187d6c9df412f22bc8b3cf4..2ba6cc7a5e4bfd05cd51e8ab22be2a99a883349d:/lib/controller/federation/conn.go diff --git a/lib/controller/federation/conn.go b/lib/controller/federation/conn.go index c6f6b2c97a..418b6811be 100644 --- a/lib/controller/federation/conn.go +++ b/lib/controller/federation/conn.go @@ -365,64 +365,76 @@ var userAttrsCachedFromLoginCluster = map[string]bool{ "writable_by": false, } -func (conn *Conn) UserList(ctx context.Context, options arvados.ListOptions) (arvados.UserList, error) { +func (conn *Conn) batchUpdateUsers(ctx context.Context, + options arvados.ListOptions, + items []arvados.User) (err error) { + + id := conn.cluster.Login.LoginCluster logger := ctxlog.FromContext(ctx) - if id := conn.cluster.Login.LoginCluster; id != "" && id != conn.cluster.ClusterID { - resp, err := conn.chooseBackend(id).UserList(ctx, options) - if err != nil { - return resp, err + batchOpts := arvados.UserBatchUpdateOptions{Updates: map[string]map[string]interface{}{}} + for _, user := range items { + if !strings.HasPrefix(user.UUID, id) { + continue + } + logger.Debugf("cache user info for uuid %q", user.UUID) + + // If the remote cluster has null timestamps + // (e.g., test server with incomplete + // fixtures) use dummy timestamps (instead of + // the zero time, which causes a Rails API + // error "year too big to marshal: 1 UTC"). + if user.ModifiedAt.IsZero() { + user.ModifiedAt = time.Now() + } + if user.CreatedAt.IsZero() { + user.CreatedAt = time.Now() } - batchOpts := arvados.UserBatchUpdateOptions{Updates: map[string]map[string]interface{}{}} - for _, user := range resp.Items { - if !strings.HasPrefix(user.UUID, id) { - continue - } - logger.Debugf("cache user info for uuid %q", user.UUID) - - // If the remote cluster has null timestamps - // (e.g., test server with incomplete - // fixtures) use dummy timestamps (instead of - // the zero time, which causes a Rails API - // error "year too big to marshal: 1 UTC"). - if user.ModifiedAt.IsZero() { - user.ModifiedAt = time.Now() - } - if user.CreatedAt.IsZero() { - user.CreatedAt = time.Now() - } - var allFields map[string]interface{} - buf, err := json.Marshal(user) - if err != nil { - return arvados.UserList{}, fmt.Errorf("error encoding user record from remote response: %s", err) - } - err = json.Unmarshal(buf, &allFields) - if err != nil { - return arvados.UserList{}, fmt.Errorf("error transcoding user record from remote response: %s", err) - } - updates := allFields - if len(options.Select) > 0 { - updates = map[string]interface{}{} - for _, k := range options.Select { - if v, ok := allFields[k]; ok && userAttrsCachedFromLoginCluster[k] { - updates[k] = v - } + var allFields map[string]interface{} + buf, err := json.Marshal(user) + if err != nil { + return fmt.Errorf("error encoding user record from remote response: %s", err) + } + err = json.Unmarshal(buf, &allFields) + if err != nil { + return fmt.Errorf("error transcoding user record from remote response: %s", err) + } + updates := allFields + if len(options.Select) > 0 { + updates = map[string]interface{}{} + for _, k := range options.Select { + if v, ok := allFields[k]; ok && userAttrsCachedFromLoginCluster[k] { + updates[k] = v } - } else { - for k := range updates { - if !userAttrsCachedFromLoginCluster[k] { - delete(updates, k) - } + } + } else { + for k := range updates { + if !userAttrsCachedFromLoginCluster[k] { + delete(updates, k) } } - batchOpts.Updates[user.UUID] = updates } - if len(batchOpts.Updates) > 0 { - ctxRoot := auth.NewContext(ctx, &auth.Credentials{Tokens: []string{conn.cluster.SystemRootToken}}) - _, err = conn.local.UserBatchUpdate(ctxRoot, batchOpts) - if err != nil { - return arvados.UserList{}, fmt.Errorf("error updating local user records: %s", err) - } + batchOpts.Updates[user.UUID] = updates + } + if len(batchOpts.Updates) > 0 { + ctxRoot := auth.NewContext(ctx, &auth.Credentials{Tokens: []string{conn.cluster.SystemRootToken}}) + _, err = conn.local.UserBatchUpdate(ctxRoot, batchOpts) + if err != nil { + return fmt.Errorf("error updating local user records: %s", err) + } + } + return nil +} + +func (conn *Conn) UserList(ctx context.Context, options arvados.ListOptions) (arvados.UserList, error) { + if id := conn.cluster.Login.LoginCluster; id != "" && id != conn.cluster.ClusterID && !options.BypassFederation { + resp, err := conn.chooseBackend(id).UserList(ctx, options) + if err != nil { + return resp, err + } + err = conn.batchUpdateUsers(ctx, options, resp.Items) + if err != nil { + return arvados.UserList{}, err } return resp, nil } else { @@ -435,15 +447,18 @@ func (conn *Conn) UserCreate(ctx context.Context, options arvados.CreateOptions) } func (conn *Conn) UserUpdate(ctx context.Context, options arvados.UpdateOptions) (arvados.User, error) { + if options.BypassFederation { + return conn.local.UserUpdate(ctx, options) + } return conn.chooseBackend(options.UUID).UserUpdate(ctx, options) } func (conn *Conn) UserUpdateUUID(ctx context.Context, options arvados.UpdateUUIDOptions) (arvados.User, error) { - return conn.chooseBackend(options.UUID).UserUpdateUUID(ctx, options) + return conn.local.UserUpdateUUID(ctx, options) } func (conn *Conn) UserMerge(ctx context.Context, options arvados.UserMergeOptions) (arvados.User, error) { - return conn.chooseBackend(options.OldUserUUID).UserMerge(ctx, options) + return conn.local.UserMerge(ctx, options) } func (conn *Conn) UserActivate(ctx context.Context, options arvados.UserActivateOptions) (arvados.User, error) { @@ -478,6 +493,10 @@ func (conn *Conn) UserBatchUpdate(ctx context.Context, options arvados.UserBatch return conn.local.UserBatchUpdate(ctx, options) } +func (conn *Conn) UserAuthenticate(ctx context.Context, options arvados.UserAuthenticateOptions) (arvados.APIClientAuthorization, error) { + return conn.local.UserAuthenticate(ctx, options) +} + func (conn *Conn) APIClientAuthorizationCurrent(ctx context.Context, options arvados.GetOptions) (arvados.APIClientAuthorization, error) { return conn.chooseBackend(options.UUID).APIClientAuthorizationCurrent(ctx, options) }