16263: Decodes JSON numbers as strings instead of float64.
[arvados.git] / lib / controller / rpc / conn.go
index afe749fb0d9f3644f1814f7cf763d137bc9af092..b5c56dbc4d64897e4f44bbdbdc9c44f2f7931f56 100644 (file)
@@ -5,6 +5,7 @@
 package rpc
 
 import (
+       "bytes"
        "context"
        "crypto/tls"
        "encoding/json"
@@ -14,11 +15,12 @@ import (
        "net"
        "net/http"
        "net/url"
+       "strconv"
        "strings"
        "time"
 
-       "git.curoverse.com/arvados.git/sdk/go/arvados"
-       "git.curoverse.com/arvados.git/sdk/go/auth"
+       "git.arvados.org/arvados.git/sdk/go/arvados"
+       "git.arvados.org/arvados.git/sdk/go/auth"
 )
 
 type TokenProvider func(context.Context) ([]string, error)
@@ -100,19 +102,23 @@ func (conn *Conn) requestAndDecode(ctx context.Context, dst interface{}, ep arva
                return fmt.Errorf("%T: requestAndDecode: Marshal opts: %s", conn, err)
        }
        var params map[string]interface{}
-       err = json.Unmarshal(j, &params)
+       dec := json.NewDecoder(bytes.NewBuffer(j))
+       dec.UseNumber()
+       err = dec.Decode(&params)
        if err != nil {
-               return fmt.Errorf("%T: requestAndDecode: Unmarshal opts: %s", conn, err)
+               return fmt.Errorf("%T: requestAndDecode: Decode opts: %s", conn, err)
        }
        if attrs, ok := params["attrs"]; ok && ep.AttrsKey != "" {
                params[ep.AttrsKey] = attrs
                delete(params, "attrs")
        }
-       if limit, ok := params["limit"].(float64); ok && limit < 0 {
-               // Negative limit means "not specified" here, but some
-               // servers/versions do not accept that, so we need to
-               // remove it entirely.
-               delete(params, "limit")
+       if limitStr, ok := params["limit"]; ok {
+               if limit, err := strconv.ParseInt(string(limitStr.(json.Number)), 10, 64); err == nil && limit < 0 {
+                       // Negative limit means "not specified" here, but some
+                       // servers/versions do not accept that, so we need to
+                       // remove it entirely.
+                       delete(params, "limit")
+               }
        }
        if len(tokens) > 1 {
                params["reader_tokens"] = tokens[1:]
@@ -145,6 +151,14 @@ func (conn *Conn) Login(ctx context.Context, options arvados.LoginOptions) (arva
        return resp, err
 }
 
+func (conn *Conn) Logout(ctx context.Context, options arvados.LogoutOptions) (arvados.LogoutResponse, error) {
+       ep := arvados.EndpointLogout
+       var resp arvados.LogoutResponse
+       err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
+       resp.RedirectLocation = conn.relativeToBaseURL(resp.RedirectLocation)
+       return resp, err
+}
+
 // If the given location is a valid URL and its origin is the same as
 // conn.baseURL, return it as a relative URL. Otherwise, return it
 // unmodified.
@@ -308,6 +322,79 @@ func (conn *Conn) SpecimenDelete(ctx context.Context, options arvados.DeleteOpti
        return resp, err
 }
 
+func (conn *Conn) UserCreate(ctx context.Context, options arvados.CreateOptions) (arvados.User, error) {
+       ep := arvados.EndpointUserCreate
+       var resp arvados.User
+       err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
+       return resp, err
+}
+func (conn *Conn) UserUpdate(ctx context.Context, options arvados.UpdateOptions) (arvados.User, error) {
+       ep := arvados.EndpointUserUpdate
+       var resp arvados.User
+       err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
+       return resp, err
+}
+func (conn *Conn) UserUpdateUUID(ctx context.Context, options arvados.UpdateUUIDOptions) (arvados.User, error) {
+       ep := arvados.EndpointUserUpdateUUID
+       var resp arvados.User
+       err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
+       return resp, err
+}
+func (conn *Conn) UserMerge(ctx context.Context, options arvados.UserMergeOptions) (arvados.User, error) {
+       ep := arvados.EndpointUserMerge
+       var resp arvados.User
+       err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
+       return resp, err
+}
+func (conn *Conn) UserActivate(ctx context.Context, options arvados.UserActivateOptions) (arvados.User, error) {
+       ep := arvados.EndpointUserActivate
+       var resp arvados.User
+       err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
+       return resp, err
+}
+func (conn *Conn) UserSetup(ctx context.Context, options arvados.UserSetupOptions) (map[string]interface{}, error) {
+       ep := arvados.EndpointUserSetup
+       var resp map[string]interface{}
+       err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
+       return resp, err
+}
+func (conn *Conn) UserUnsetup(ctx context.Context, options arvados.GetOptions) (arvados.User, error) {
+       ep := arvados.EndpointUserUnsetup
+       var resp arvados.User
+       err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
+       return resp, err
+}
+func (conn *Conn) UserGet(ctx context.Context, options arvados.GetOptions) (arvados.User, error) {
+       ep := arvados.EndpointUserGet
+       var resp arvados.User
+       err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
+       return resp, err
+}
+func (conn *Conn) UserGetCurrent(ctx context.Context, options arvados.GetOptions) (arvados.User, error) {
+       ep := arvados.EndpointUserGetCurrent
+       var resp arvados.User
+       err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
+       return resp, err
+}
+func (conn *Conn) UserGetSystem(ctx context.Context, options arvados.GetOptions) (arvados.User, error) {
+       ep := arvados.EndpointUserGetSystem
+       var resp arvados.User
+       err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
+       return resp, err
+}
+func (conn *Conn) UserList(ctx context.Context, options arvados.ListOptions) (arvados.UserList, error) {
+       ep := arvados.EndpointUserList
+       var resp arvados.UserList
+       err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
+       return resp, err
+}
+func (conn *Conn) UserDelete(ctx context.Context, options arvados.DeleteOptions) (arvados.User, error) {
+       ep := arvados.EndpointUserDelete
+       var resp arvados.User
+       err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
+       return resp, err
+}
+
 func (conn *Conn) APIClientAuthorizationCurrent(ctx context.Context, options arvados.GetOptions) (arvados.APIClientAuthorization, error) {
        ep := arvados.EndpointAPIClientAuthorizationCurrent
        var resp arvados.APIClientAuthorization
@@ -320,6 +407,7 @@ type UserSessionAuthInfo struct {
        AlternateEmails []string `json:"alternate_emails"`
        FirstName       string   `json:"first_name"`
        LastName        string   `json:"last_name"`
+       Username        string   `json:"username"`
 }
 
 type UserSessionCreateOptions struct {
@@ -333,3 +421,10 @@ func (conn *Conn) UserSessionCreate(ctx context.Context, options UserSessionCrea
        err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
        return resp, err
 }
+
+func (conn *Conn) UserBatchUpdate(ctx context.Context, options arvados.UserBatchUpdateOptions) (arvados.UserList, error) {
+       ep := arvados.APIEndpoint{Method: "PATCH", Path: "arvados/v1/users/batch_update"}
+       var resp arvados.UserList
+       err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
+       return resp, err
+}