From 1f877987001eed21cfa04131a7734f2265bc244e Mon Sep 17 00:00:00 2001 From: Nhat Nguyen Date: Thu, 14 Nov 2019 13:36:14 +0700 Subject: [PATCH 01/70] remove os env variable app test --- app_test.go | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/app_test.go b/app_test.go index d9e8f7b..393a06b 100644 --- a/app_test.go +++ b/app_test.go @@ -7,34 +7,38 @@ package kintone import ( "bytes" "io/ioutil" - "os" "strings" "testing" "time" ) +const KINTONE_DOMAIN = "YOUR_DOMAIN" +const KINTONE_USER = "YOUR_KINTONE_USER" +const KINTONE_PASSWORD = "YOUR_KINTONE_PASSWORD" +const KINTONE_API_TOKEN = "YOUR_API_TOKEN" + func newApp(appID uint64) *App { return &App{ - Domain: os.Getenv("KINTONE_DOMAIN"), - User: os.Getenv("KINTONE_USER"), - Password: os.Getenv("KINTONE_PASSWORD"), + Domain: KINTONE_DOMAIN, + User: KINTONE_USER, + Password: KINTONE_PASSWORD, AppId: appID, } } func newAppWithApiToken(appId uint64) *App { return &App{ - Domain: os.Getenv("KINTONE_DOMAIN"), - ApiToken: os.Getenv("KINTONE_API_TOKEN"), + Domain: KINTONE_DOMAIN, + ApiToken: KINTONE_API_TOKEN, AppId: appId, } } func newAppInGuestSpace(appId uint64, guestSpaceId uint64) *App { return &App{ - Domain: os.Getenv("KINTONE_DOMAIN"), - User: os.Getenv("KINTONE_USER"), - Password: os.Getenv("KINTONE_PASSWORD"), + Domain: KINTONE_DOMAIN, + User: KINTONE_USER, + Password: KINTONE_PASSWORD, AppId: appId, GuestSpaceId: guestSpaceId, } From 0cd7353108216303d11679ea6a643c475af3d810 Mon Sep 17 00:00:00 2001 From: huong Date: Fri, 13 Dec 2019 17:19:13 +0700 Subject: [PATCH 02/70] create cursor --- app.go | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/app.go b/app.go index 6fa1fa0..faee1d3 100644 --- a/app.go +++ b/app.go @@ -46,6 +46,28 @@ type AppError struct { Errors string `json:"errors"` // Error Description. } +func (app *App) createCursor(fields []string) ([]byte, error) { + type cursor struct { + App uint64 `json:"app"` + Fields []string `json:"fields"` + } + var data = cursor{App: app.AppId, Fields: fields} + jsonData, _ := json.Marshal(data) + req, err := app.newRequest("POST", "records/cursor", bytes.NewBuffer(jsonData), "") + if err != nil { + return nil, err + } + res, err := app.do(req) + if err != nil { + return nil, err + } + body, err := parseResponse(res) + if err != nil { + return nil, err + } + return body, nil +} + func (e *AppError) Error() string { if len(e.Message) == 0 { return "HTTP error: " + e.HttpStatus From 83eb194e7967ab962c70a58f6d81dd0979d9570b Mon Sep 17 00:00:00 2001 From: huong Date: Fri, 13 Dec 2019 17:19:28 +0700 Subject: [PATCH 03/70] get cursor --- app.go | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/app.go b/app.go index faee1d3..4ff5e17 100644 --- a/app.go +++ b/app.go @@ -91,6 +91,26 @@ func (f UpdateKey) MarshalJSON() ([]byte, error) { }) } +func (app *App) getCurSor(idCursor string) ([]byte, error) { + type requestBody struct { + Id string `json:"id,string"` + } + + req, err := app.newRequest("GET", "records/cursor", nil, "id="+idCursor) + if err != nil { + return nil, err + } + resGetCursor, err := app.do(req) + if err != nil { + return nil, err + } + result, err := parseResponse(resGetCursor) + if err != nil { + return nil, err + } + return result, nil +} + // App provides kintone application API client. // // You need to provide Domain, User, Password, and AppId. From 11ed28cbbde3bde8940078f0d44f496d3c4a7727 Mon Sep 17 00:00:00 2001 From: huong Date: Fri, 13 Dec 2019 17:20:38 +0700 Subject: [PATCH 04/70] fix New Request --- app.go | 43 +++++++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/app.go b/app.go index 4ff5e17..eef73d1 100644 --- a/app.go +++ b/app.go @@ -202,7 +202,7 @@ func (app *App) GetUserAgentHeader() string { return app.userAgentHeader } -func (app *App) newRequest(method, api string, body io.Reader) (*http.Request, error) { +func (app *App) newRequest(method, api string, body io.Reader, query string) (*http.Request, error) { if len(app.token) == 0 { app.token = base64.StdEncoding.EncodeToString( []byte(app.User + ":" + app.Password)) @@ -232,7 +232,10 @@ func (app *App) newRequest(method, api string, body io.Reader) (*http.Request, e } else { req.Header.Set("X-Cybozu-API-Token", app.ApiToken) } - req.Header.Set("Content-Type", "application/json") + + if method != "GET" { + req.Header.Set("Content-Type", "application/json") + } if len(app.GetUserAgentHeader()) != 0 { req.Header.Set("User-Agent", app.userAgentHeader) @@ -339,7 +342,7 @@ func (app *App) GetRecord(id uint64) (*Record, error) { Id uint64 `json:"id,string"` } data, _ := json.Marshal(request_body{app.AppId, id}) - req, err := app.newRequest("GET", "record", bytes.NewReader(data)) + req, err := app.newRequest("GET", "record", bytes.NewReader(data), "") if err != nil { return nil, err } @@ -374,7 +377,7 @@ func (app *App) GetRecords(fields []string, query string) ([]*Record, error) { Query string `json:"query"` } data, _ := json.Marshal(request_body{app.AppId, fields, query}) - req, err := app.newRequest("GET", "records", bytes.NewReader(data)) + req, err := app.newRequest("GET", "records", bytes.NewReader(data), "") if err != nil { return nil, err } @@ -409,7 +412,7 @@ func (app *App) GetAllRecords(fields []string) ([]*Record, error) { query = fmt.Sprintf("limit 100 offset %v", len(recs)) } data, _ := json.Marshal(request_body{app.AppId, fields, query}) - req, err := app.newRequest("GET", "records", bytes.NewReader(data)) + req, err := app.newRequest("GET", "records", bytes.NewReader(data), "") if err != nil { return nil, err } @@ -459,7 +462,7 @@ func (app *App) GetProcess(lang string) (process *Process, err error) { return } data, _ := json.Marshal(request_body{app.AppId, lang}) - req, err := app.newRequest("GET", "app/status", bytes.NewReader(data)) + req, err := app.newRequest("GET", "app/status", bytes.NewReader(data), "") if err != nil { return } @@ -492,7 +495,7 @@ func (app *App) Download(fileKey string) (*FileData, error) { FileKey string `json:"fileKey"` } data, _ := json.Marshal(request_body{fileKey}) - req, err := app.newRequest("GET", "file", bytes.NewReader(data)) + req, err := app.newRequest("GET", "file", bytes.NewReader(data), "") if err != nil { return nil, err } @@ -564,7 +567,7 @@ func (app *App) Upload(fileName, contentType string, data io.Reader) (key string return } - req, err := app.newRequest("POST", "file", f) + req, err := app.newRequest("POST", "file", f, "") if err != nil { return } @@ -597,7 +600,7 @@ func (app *App) AddRecord(rec *Record) (id string, err error) { Record *Record `json:"record"` } data, _ := json.Marshal(request_body{app.AppId, rec}) - req, err := app.newRequest("POST", "record", bytes.NewReader(data)) + req, err := app.newRequest("POST", "record", bytes.NewReader(data), "") if err != nil { return } @@ -635,7 +638,7 @@ func (app *App) AddRecords(recs []*Record) ([]string, error) { Records []*Record `json:"records"` } data, _ := json.Marshal(request_body{app.AppId, recs}) - req, err := app.newRequest("POST", "records", bytes.NewReader(data)) + req, err := app.newRequest("POST", "records", bytes.NewReader(data), "") if err != nil { return nil, err } @@ -674,7 +677,7 @@ func (app *App) UpdateRecord(rec *Record, ignoreRevision bool) error { rev = -1 } data, _ := json.Marshal(request_body{app.AppId, rec.id, rev, rec}) - req, err := app.newRequest("PUT", "record", bytes.NewReader(data)) + req, err := app.newRequest("PUT", "record", bytes.NewReader(data), "") if err != nil { return err } @@ -708,7 +711,7 @@ func (app *App) UpdateRecordByKey(rec *Record, ignoreRevision bool, keyField str } data, _ := json.Marshal(request_body{app.AppId, UpdateKey{keyField, updateKey.(UpdateKeyField)}, rev, &_rec}) - req, err := app.newRequest("PUT", "record", bytes.NewReader(data)) + req, err := app.newRequest("PUT", "record", bytes.NewReader(data), "") if err != nil { return err } @@ -747,7 +750,7 @@ func (app *App) UpdateRecords(recs []*Record, ignoreRevision bool) error { t_recs = append(t_recs, update_t{rec.Id(), rev, rec}) } data, _ := json.Marshal(request_body{app.AppId, t_recs}) - req, err := app.newRequest("PUT", "records", bytes.NewReader(data)) + req, err := app.newRequest("PUT", "records", bytes.NewReader(data), "") if err != nil { return err } @@ -791,7 +794,7 @@ func (app *App) UpdateRecordsByKey(recs []*Record, ignoreRevision bool, keyField t_recs = append(t_recs, update_t{UpdateKey{keyField, updateKey.(UpdateKeyField)}, rev, &_rec}) } data, _ := json.Marshal(request_body{app.AppId, t_recs}) - req, err := app.newRequest("PUT", "records", bytes.NewReader(data)) + req, err := app.newRequest("PUT", "records", bytes.NewReader(data), "") if err != nil { return err } @@ -821,7 +824,7 @@ func (app *App) UpdateRecordStatus(rec *Record, action *ProcessAction, assignee code = assignee.Code } data, _ := json.Marshal(request_body{app.AppId, rec.id, rev, action.Name, code}) - req, err := app.newRequest("PUT", "record/status", bytes.NewReader(data)) + req, err := app.newRequest("PUT", "record/status", bytes.NewReader(data), "") if err != nil { return } @@ -846,7 +849,7 @@ func (app *App) DeleteRecords(ids []uint64) error { Ids []uint64 `json:"ids,string"` } data, _ := json.Marshal(request_body{app.AppId, ids}) - req, err := app.newRequest("DELETE", "records", bytes.NewReader(data)) + req, err := app.newRequest("DELETE", "records", bytes.NewReader(data), "") if err != nil { return err } @@ -871,7 +874,7 @@ func (app *App) GetRecordComments(recordID uint64, order string, offset, limit u } data, _ := json.Marshal(requestBody{app.AppId, recordID, order, offset, limit}) - req, err := app.newRequest("GET", "record/comments", bytes.NewReader(data)) + req, err := app.newRequest("GET", "record/comments", bytes.NewReader(data), "") if err != nil { return nil, err } @@ -901,7 +904,7 @@ func (app *App) AddRecordComment(recordId uint64, comment *Comment) (id string, Comment *Comment `json:"comment"` } data, _ := json.Marshal(requestBody{app.AppId, recordId, comment}) - req, err := app.newRequest("POST", "record/comment", bytes.NewReader(data)) + req, err := app.newRequest("POST", "record/comment", bytes.NewReader(data), "") if err != nil { return } @@ -934,7 +937,7 @@ func (app *App) DeleteComment(recordId uint64, commentId uint64) error { requestData := requestBody{app.AppId, recordId, commentId} data, _ := json.Marshal(requestData) - req, err := app.newRequest("DELETE", "record/comment", bytes.NewReader(data)) + req, err := app.newRequest("DELETE", "record/comment", bytes.NewReader(data), "") if err != nil { return err } @@ -1014,7 +1017,7 @@ func (app *App) Fields() (map[string]*FieldInfo, error) { App uint64 `json:"app,string"` } data, _ := json.Marshal(request_body{app.AppId}) - req, err := app.newRequest("GET", "form", bytes.NewReader(data)) + req, err := app.newRequest("GET", "form", bytes.NewReader(data), "") if err != nil { return nil, err } From 722870b5c0094d7b8fe81142705756217c8dc842 Mon Sep 17 00:00:00 2001 From: huong Date: Fri, 13 Dec 2019 17:21:02 +0700 Subject: [PATCH 05/70] create function delete cursor --- app.go | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/app.go b/app.go index eef73d1..f35bebb 100644 --- a/app.go +++ b/app.go @@ -538,6 +538,32 @@ func escapeQuotes(s string) string { return quoteEscaper.Replace(s) } +func (app *App) deleteCursor(cursorId string) (string, error) { + type requestBody struct { + Id string `json:"id"` + } + data, err := json.Marshal(requestBody{Id: cursorId}) + if err != nil { + return "", err + } + req, err := app.newRequest("DELETE", "records/cursor", bytes.NewBuffer(data), "") + if err != nil { + return "", err + } + res, err := app.do(req) + if err != nil { + return "", err + } + + result, err := parseResponse(res) + if err != nil { + return "", err + } + if result != nil { + } + return "delete success", nil +} + // Upload uploads a file. // // If successfully uploaded, the key string of the uploaded file is returned. From 0827b6685a1a743d8225643ee04f7957a4771f15 Mon Sep 17 00:00:00 2001 From: huong Date: Fri, 13 Dec 2019 17:22:13 +0700 Subject: [PATCH 06/70] write unit test for api cursor --- app_test.go | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/app_test.go b/app_test.go index d9e8f7b..e583e9a 100644 --- a/app_test.go +++ b/app_test.go @@ -6,6 +6,7 @@ package kintone import ( "bytes" + "fmt" "io/ioutil" "os" "strings" @@ -171,6 +172,32 @@ func TestDeleteRecord(t *testing.T) { } } +func TestGetCursor(t *testing.T) { + app := newApp(18) + result, err := app.getCurSor("2e17d05f-d046-494e-ae8a-e2f82d68ff05") + if err != nil { + t.Errorf("error %v", err) + } + fmt.Println(string(result)) + +} +func TestDeleteCursor(t *testing.T) { + app := newApp(18) + result, err := app.deleteCursor("b997c4d6-b514-4567-9c00-1014770ead5c") + if err != nil { + t.Errorf("error %v", err) + } + fmt.Println(result) +} +func TestCreateCurSor(t *testing.T) { + app := newAppWithApiToken(18) + result, err := app.createCursor([]string{"$id", "date"}) + if err != nil { + t.Errorf("error %v", err) + } + fmt.Println("result", string(result)) +} + func TestFields(t *testing.T) { a := newApp(8326) if len(a.Password) == 0 { From 782838b5546ab54bd4123fbf7cbd67347bacdb2c Mon Sep 17 00:00:00 2001 From: huong Date: Mon, 16 Dec 2019 13:19:35 +0700 Subject: [PATCH 07/70] refactor code review 1 --- app.go | 137 ++++++++++++++++++++++++++-------------------------- app_test.go | 24 +++++++-- 2 files changed, 88 insertions(+), 73 deletions(-) diff --git a/app.go b/app.go index f35bebb..0142ffe 100644 --- a/app.go +++ b/app.go @@ -46,28 +46,6 @@ type AppError struct { Errors string `json:"errors"` // Error Description. } -func (app *App) createCursor(fields []string) ([]byte, error) { - type cursor struct { - App uint64 `json:"app"` - Fields []string `json:"fields"` - } - var data = cursor{App: app.AppId, Fields: fields} - jsonData, _ := json.Marshal(data) - req, err := app.newRequest("POST", "records/cursor", bytes.NewBuffer(jsonData), "") - if err != nil { - return nil, err - } - res, err := app.do(req) - if err != nil { - return nil, err - } - body, err := parseResponse(res) - if err != nil { - return nil, err - } - return body, nil -} - func (e *AppError) Error() string { if len(e.Message) == 0 { return "HTTP error: " + e.HttpStatus @@ -91,26 +69,6 @@ func (f UpdateKey) MarshalJSON() ([]byte, error) { }) } -func (app *App) getCurSor(idCursor string) ([]byte, error) { - type requestBody struct { - Id string `json:"id,string"` - } - - req, err := app.newRequest("GET", "records/cursor", nil, "id="+idCursor) - if err != nil { - return nil, err - } - resGetCursor, err := app.do(req) - if err != nil { - return nil, err - } - result, err := parseResponse(resGetCursor) - if err != nil { - return nil, err - } - return result, nil -} - // App provides kintone application API client. // // You need to provide Domain, User, Password, and AppId. @@ -232,7 +190,6 @@ func (app *App) newRequest(method, api string, body io.Reader, query string) (*h } else { req.Header.Set("X-Cybozu-API-Token", app.ApiToken) } - if method != "GET" { req.Header.Set("Content-Type", "application/json") } @@ -538,32 +495,6 @@ func escapeQuotes(s string) string { return quoteEscaper.Replace(s) } -func (app *App) deleteCursor(cursorId string) (string, error) { - type requestBody struct { - Id string `json:"id"` - } - data, err := json.Marshal(requestBody{Id: cursorId}) - if err != nil { - return "", err - } - req, err := app.newRequest("DELETE", "records/cursor", bytes.NewBuffer(data), "") - if err != nil { - return "", err - } - res, err := app.do(req) - if err != nil { - return "", err - } - - result, err := parseResponse(res) - if err != nil { - return "", err - } - if result != nil { - } - return "delete success", nil -} - // Upload uploads a file. // // If successfully uploaded, the key string of the uploaded file is returned. @@ -1071,3 +1002,71 @@ func (app *App) Fields() (map[string]*FieldInfo, error) { } return ret, nil } + +func (app *App) createCursor(fields []string) ([]byte, error) { + type cursor struct { + App uint64 `json:"app"` + Fields []string `json:"fields"` + } + var data = cursor{App: app.AppId, Fields: fields} + jsonData, _ := json.Marshal(data) + req, err := app.newRequest("POST", "records/cursor", bytes.NewBuffer(jsonData), "") + if err != nil { + return nil, err + } + res, err := app.do(req) + if err != nil { + return nil, err + } + body, err := parseResponse(res) + if err != nil { + return nil, err + } + return body, nil +} + +func (app *App) deleteCursor(cursorId string) (string, error) { + type requestBody struct { + Id string `json:"id"` + } + data, err := json.Marshal(requestBody{Id: cursorId}) + if err != nil { + return "", err + } + req, err := app.newRequest("DELETE", "records/cursor", bytes.NewBuffer(data), "") + if err != nil { + return "", err + } + res, err := app.do(req) + if err != nil { + return "", err + } + + result, err := parseResponse(res) + if err != nil { + return "", err + } + if result != nil { + } + return "delete success", nil +} + +func (app *App) getCurSor(idCursor string) ([]byte, error) { + type requestBody struct { + Id string `json:"id,string"` + } + + req, err := app.newRequest("GET", "records/cursor", nil, "id="+idCursor) + if err != nil { + return nil, err + } + resGetCursor, err := app.do(req) + if err != nil { + return nil, err + } + result, err := parseResponse(resGetCursor) + if err != nil { + return nil, err + } + return result, nil +} diff --git a/app_test.go b/app_test.go index e583e9a..595b2ea 100644 --- a/app_test.go +++ b/app_test.go @@ -83,7 +83,14 @@ func TestGetRecord(t *testing.T) { t.Log(len(recs)) } } - +func TestGetAllRecord(t *testing.T) { + os.Setenv("KINTONE_DOMAIN", "tgbn0.kintone.com") + os.Setenv("KINTONE_USER", "Administrator") + os.Setenv("KINTONE_PASSWORD", "cybozu123") + a := newApp(18) + result, _ := a.GetAllRecords([]string{"id"}) + fmt.Println(result) +} func TestAddRecord(t *testing.T) { a := newApp(9004) if len(a.Password) == 0 { @@ -175,25 +182,34 @@ func TestDeleteRecord(t *testing.T) { func TestGetCursor(t *testing.T) { app := newApp(18) result, err := app.getCurSor("2e17d05f-d046-494e-ae8a-e2f82d68ff05") + if len(app.Password) == 0 { + t.Skip() + } if err != nil { - t.Errorf("error %v", err) + t.Errorf("get cursor is fail: %v", err) } fmt.Println(string(result)) } func TestDeleteCursor(t *testing.T) { app := newApp(18) + if len(app.Password) == 0 { + t.Skip() + } result, err := app.deleteCursor("b997c4d6-b514-4567-9c00-1014770ead5c") if err != nil { - t.Errorf("error %v", err) + t.Errorf("delete cursor is fail: %v", err) } fmt.Println(result) } func TestCreateCurSor(t *testing.T) { app := newAppWithApiToken(18) + if len(app.ApiToken) == 0 { + t.Skip() + } result, err := app.createCursor([]string{"$id", "date"}) if err != nil { - t.Errorf("error %v", err) + t.Errorf("create cursor is fail: %v", err) } fmt.Println("result", string(result)) } From 1547e3ab589629263049f40f57d624f638c7b115 Mon Sep 17 00:00:00 2001 From: huong Date: Mon, 16 Dec 2019 14:38:50 +0700 Subject: [PATCH 08/70] remove query newRequest --- app.go | 45 ++++++++++++++++++++++++++------------------- 1 file changed, 26 insertions(+), 19 deletions(-) diff --git a/app.go b/app.go index 0142ffe..ed75883 100644 --- a/app.go +++ b/app.go @@ -160,7 +160,7 @@ func (app *App) GetUserAgentHeader() string { return app.userAgentHeader } -func (app *App) newRequest(method, api string, body io.Reader, query string) (*http.Request, error) { +func (app *App) newRequest(method, api string, body io.Reader) (*http.Request, error) { if len(app.token) == 0 { app.token = base64.StdEncoding.EncodeToString( []byte(app.User + ":" + app.Password)) @@ -193,6 +193,7 @@ func (app *App) newRequest(method, api string, body io.Reader, query string) (*h if method != "GET" { req.Header.Set("Content-Type", "application/json") } + req.Header.Set("Content-Type", "application/json") if len(app.GetUserAgentHeader()) != 0 { req.Header.Set("User-Agent", app.userAgentHeader) @@ -221,6 +222,7 @@ func (app *App) do(req *http.Request) (*http.Response, error) { done := make(chan result, 1) go func() { resp, err := app.Client.Do(req) + done <- result{resp, err} }() @@ -230,6 +232,7 @@ func (app *App) do(req *http.Request) (*http.Response, error) { select { case r := <-done: + return r.resp, r.err case <-time.After(app.Timeout): if canceller, ok := app.Client.Transport.(requestCanceler); ok { @@ -239,6 +242,7 @@ func (app *App) do(req *http.Request) (*http.Response, error) { r := <-done if r.err == nil { r.resp.Body.Close() + } }() } @@ -299,7 +303,7 @@ func (app *App) GetRecord(id uint64) (*Record, error) { Id uint64 `json:"id,string"` } data, _ := json.Marshal(request_body{app.AppId, id}) - req, err := app.newRequest("GET", "record", bytes.NewReader(data), "") + req, err := app.newRequest("GET", "record", bytes.NewReader(data)) if err != nil { return nil, err } @@ -334,7 +338,7 @@ func (app *App) GetRecords(fields []string, query string) ([]*Record, error) { Query string `json:"query"` } data, _ := json.Marshal(request_body{app.AppId, fields, query}) - req, err := app.newRequest("GET", "records", bytes.NewReader(data), "") + req, err := app.newRequest("GET", "records", bytes.NewReader(data)) if err != nil { return nil, err } @@ -368,8 +372,9 @@ func (app *App) GetAllRecords(fields []string) ([]*Record, error) { if len(recs) > 0 { query = fmt.Sprintf("limit 100 offset %v", len(recs)) } + data, _ := json.Marshal(request_body{app.AppId, fields, query}) - req, err := app.newRequest("GET", "records", bytes.NewReader(data), "") + req, err := app.newRequest("GET", "records", bytes.NewReader(data)) if err != nil { return nil, err } @@ -419,7 +424,7 @@ func (app *App) GetProcess(lang string) (process *Process, err error) { return } data, _ := json.Marshal(request_body{app.AppId, lang}) - req, err := app.newRequest("GET", "app/status", bytes.NewReader(data), "") + req, err := app.newRequest("GET", "app/status", bytes.NewReader(data)) if err != nil { return } @@ -452,7 +457,7 @@ func (app *App) Download(fileKey string) (*FileData, error) { FileKey string `json:"fileKey"` } data, _ := json.Marshal(request_body{fileKey}) - req, err := app.newRequest("GET", "file", bytes.NewReader(data), "") + req, err := app.newRequest("GET", "file", bytes.NewReader(data)) if err != nil { return nil, err } @@ -524,7 +529,7 @@ func (app *App) Upload(fileName, contentType string, data io.Reader) (key string return } - req, err := app.newRequest("POST", "file", f, "") + req, err := app.newRequest("POST", "file", f) if err != nil { return } @@ -557,7 +562,7 @@ func (app *App) AddRecord(rec *Record) (id string, err error) { Record *Record `json:"record"` } data, _ := json.Marshal(request_body{app.AppId, rec}) - req, err := app.newRequest("POST", "record", bytes.NewReader(data), "") + req, err := app.newRequest("POST", "record", bytes.NewReader(data)) if err != nil { return } @@ -595,7 +600,7 @@ func (app *App) AddRecords(recs []*Record) ([]string, error) { Records []*Record `json:"records"` } data, _ := json.Marshal(request_body{app.AppId, recs}) - req, err := app.newRequest("POST", "records", bytes.NewReader(data), "") + req, err := app.newRequest("POST", "records", bytes.NewReader(data)) if err != nil { return nil, err } @@ -634,7 +639,7 @@ func (app *App) UpdateRecord(rec *Record, ignoreRevision bool) error { rev = -1 } data, _ := json.Marshal(request_body{app.AppId, rec.id, rev, rec}) - req, err := app.newRequest("PUT", "record", bytes.NewReader(data), "") + req, err := app.newRequest("PUT", "record", bytes.NewReader(data)) if err != nil { return err } @@ -668,7 +673,7 @@ func (app *App) UpdateRecordByKey(rec *Record, ignoreRevision bool, keyField str } data, _ := json.Marshal(request_body{app.AppId, UpdateKey{keyField, updateKey.(UpdateKeyField)}, rev, &_rec}) - req, err := app.newRequest("PUT", "record", bytes.NewReader(data), "") + req, err := app.newRequest("PUT", "record", bytes.NewReader(data)) if err != nil { return err } @@ -707,7 +712,7 @@ func (app *App) UpdateRecords(recs []*Record, ignoreRevision bool) error { t_recs = append(t_recs, update_t{rec.Id(), rev, rec}) } data, _ := json.Marshal(request_body{app.AppId, t_recs}) - req, err := app.newRequest("PUT", "records", bytes.NewReader(data), "") + req, err := app.newRequest("PUT", "records", bytes.NewReader(data)) if err != nil { return err } @@ -751,7 +756,7 @@ func (app *App) UpdateRecordsByKey(recs []*Record, ignoreRevision bool, keyField t_recs = append(t_recs, update_t{UpdateKey{keyField, updateKey.(UpdateKeyField)}, rev, &_rec}) } data, _ := json.Marshal(request_body{app.AppId, t_recs}) - req, err := app.newRequest("PUT", "records", bytes.NewReader(data), "") + req, err := app.newRequest("PUT", "records", bytes.NewReader(data)) if err != nil { return err } @@ -781,7 +786,7 @@ func (app *App) UpdateRecordStatus(rec *Record, action *ProcessAction, assignee code = assignee.Code } data, _ := json.Marshal(request_body{app.AppId, rec.id, rev, action.Name, code}) - req, err := app.newRequest("PUT", "record/status", bytes.NewReader(data), "") + req, err := app.newRequest("PUT", "record/status", bytes.NewReader(data)) if err != nil { return } @@ -806,7 +811,7 @@ func (app *App) DeleteRecords(ids []uint64) error { Ids []uint64 `json:"ids,string"` } data, _ := json.Marshal(request_body{app.AppId, ids}) - req, err := app.newRequest("DELETE", "records", bytes.NewReader(data), "") + req, err := app.newRequest("DELETE", "records", bytes.NewReader(data)) if err != nil { return err } @@ -831,7 +836,7 @@ func (app *App) GetRecordComments(recordID uint64, order string, offset, limit u } data, _ := json.Marshal(requestBody{app.AppId, recordID, order, offset, limit}) - req, err := app.newRequest("GET", "record/comments", bytes.NewReader(data), "") + req, err := app.newRequest("GET", "record/comments", bytes.NewReader(data)) if err != nil { return nil, err } @@ -861,7 +866,7 @@ func (app *App) AddRecordComment(recordId uint64, comment *Comment) (id string, Comment *Comment `json:"comment"` } data, _ := json.Marshal(requestBody{app.AppId, recordId, comment}) - req, err := app.newRequest("POST", "record/comment", bytes.NewReader(data), "") + req, err := app.newRequest("POST", "record/comment", bytes.NewReader(data)) if err != nil { return } @@ -894,7 +899,7 @@ func (app *App) DeleteComment(recordId uint64, commentId uint64) error { requestData := requestBody{app.AppId, recordId, commentId} data, _ := json.Marshal(requestData) - req, err := app.newRequest("DELETE", "record/comment", bytes.NewReader(data), "") + req, err := app.newRequest("DELETE", "record/comment", bytes.NewReader(data)) if err != nil { return err } @@ -974,11 +979,13 @@ func (app *App) Fields() (map[string]*FieldInfo, error) { App uint64 `json:"app,string"` } data, _ := json.Marshal(request_body{app.AppId}) - req, err := app.newRequest("GET", "form", bytes.NewReader(data), "") + req, err := app.newRequest("GET", "form", bytes.NewReader(data)) if err != nil { return nil, err } resp, err := app.do(req) + fmt.Println(resp) + if err != nil { return nil, err } From 58292fb0f5605b2726296fe291a44afdfd44eee6 Mon Sep 17 00:00:00 2001 From: huong Date: Mon, 16 Dec 2019 17:08:54 +0700 Subject: [PATCH 09/70] add function NewRequest and createUrl --- app.go | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 62 insertions(+), 7 deletions(-) diff --git a/app.go b/app.go index ed75883..84bf027 100644 --- a/app.go +++ b/app.go @@ -160,6 +160,63 @@ func (app *App) GetUserAgentHeader() string { return app.userAgentHeader } +func (app *App) createUrl(api string, body io.Reader, query string) url.URL { + var path string + if app.GuestSpaceId == 0 { + path = fmt.Sprintf("/k/v1/%s.json", api) + } else { + path = fmt.Sprintf("/k/guest/%d/v1/%s.json", app.GuestSpaceId, api) + } + u := url.URL{} + if body != nil { + u = url.URL{ + Scheme: "https", + Host: app.Domain, + Path: path, + } + } else { + u = url.URL{ + Scheme: "https", + Host: app.Domain, + Path: path, + RawQuery: query, + } + } + return u + +} +func (app *App) NewRequest(method, url string, body io.Reader, query string) (*http.Request, error) { + if len(app.token) == 0 { + app.token = base64.StdEncoding.EncodeToString( + []byte(app.User + ":" + app.Password)) + } + u := app.createUrl(url, body, query) + req, err := http.NewRequest(method, u.String(), nil) + if body != nil { + req, err = http.NewRequest(method, u.String(), body) + } + if err != nil { + return nil, err + } + if app.basicAuth { + req.SetBasicAuth(app.basicAuthUser, app.basicAuthPassword) + } + if len(app.ApiToken) == 0 { + req.Header.Set("X-Cybozu-Authorization", app.token) + } else { + req.Header.Set("X-Cybozu-API-Token", app.ApiToken) + } + if method != "GET" { + req.Header.Set("Content-Type", "application/json") + } + + if len(app.GetUserAgentHeader()) != 0 { + req.Header.Set("User-Agent", app.userAgentHeader) + } else { + req.Header.Set("User-Agent", NAME+"/"+VERSION) + } + return req, nil +} func (app *App) newRequest(method, api string, body io.Reader) (*http.Request, error) { if len(app.token) == 0 { app.token = base64.StdEncoding.EncodeToString( @@ -190,9 +247,7 @@ func (app *App) newRequest(method, api string, body io.Reader) (*http.Request, e } else { req.Header.Set("X-Cybozu-API-Token", app.ApiToken) } - if method != "GET" { - req.Header.Set("Content-Type", "application/json") - } + req.Header.Set("Content-Type", "application/json") if len(app.GetUserAgentHeader()) != 0 { @@ -219,6 +274,7 @@ func (app *App) do(req *http.Request) (*http.Response, error) { resp *http.Response err error } + done := make(chan result, 1) go func() { resp, err := app.Client.Do(req) @@ -372,7 +428,6 @@ func (app *App) GetAllRecords(fields []string) ([]*Record, error) { if len(recs) > 0 { query = fmt.Sprintf("limit 100 offset %v", len(recs)) } - data, _ := json.Marshal(request_body{app.AppId, fields, query}) req, err := app.newRequest("GET", "records", bytes.NewReader(data)) if err != nil { @@ -1017,7 +1072,7 @@ func (app *App) createCursor(fields []string) ([]byte, error) { } var data = cursor{App: app.AppId, Fields: fields} jsonData, _ := json.Marshal(data) - req, err := app.newRequest("POST", "records/cursor", bytes.NewBuffer(jsonData), "") + req, err := app.NewRequest("POST", "records/cursor", bytes.NewBuffer(jsonData), "") if err != nil { return nil, err } @@ -1040,7 +1095,7 @@ func (app *App) deleteCursor(cursorId string) (string, error) { if err != nil { return "", err } - req, err := app.newRequest("DELETE", "records/cursor", bytes.NewBuffer(data), "") + req, err := app.NewRequest("DELETE", "records/cursor", bytes.NewBuffer(data), "") if err != nil { return "", err } @@ -1063,7 +1118,7 @@ func (app *App) getCurSor(idCursor string) ([]byte, error) { Id string `json:"id,string"` } - req, err := app.newRequest("GET", "records/cursor", nil, "id="+idCursor) + req, err := app.NewRequest("GET", "records/cursor", nil, "id="+idCursor) if err != nil { return nil, err } From 01988853f8567218855c6319ee78d9bb4cbac45c Mon Sep 17 00:00:00 2001 From: huong Date: Mon, 16 Dec 2019 17:40:23 +0700 Subject: [PATCH 10/70] update logic for unit test --- app_test.go | 41 ++++++++++++++++++++++++++++------------- 1 file changed, 28 insertions(+), 13 deletions(-) diff --git a/app_test.go b/app_test.go index 595b2ea..86e0124 100644 --- a/app_test.go +++ b/app_test.go @@ -6,6 +6,7 @@ package kintone import ( "bytes" + "encoding/json" "fmt" "io/ioutil" "os" @@ -83,14 +84,6 @@ func TestGetRecord(t *testing.T) { t.Log(len(recs)) } } -func TestGetAllRecord(t *testing.T) { - os.Setenv("KINTONE_DOMAIN", "tgbn0.kintone.com") - os.Setenv("KINTONE_USER", "Administrator") - os.Setenv("KINTONE_PASSWORD", "cybozu123") - a := newApp(18) - result, _ := a.GetAllRecords([]string{"id"}) - fmt.Println(result) -} func TestAddRecord(t *testing.T) { a := newApp(9004) if len(a.Password) == 0 { @@ -181,22 +174,44 @@ func TestDeleteRecord(t *testing.T) { func TestGetCursor(t *testing.T) { app := newApp(18) - result, err := app.getCurSor("2e17d05f-d046-494e-ae8a-e2f82d68ff05") + + resultCreateCursor, err := app.createCursor([]string{"$id", "date"}) + if err != nil { + t.Errorf("create cursor is fail: %v", err) + } + var objMap map[string]*json.RawMessage + json.Unmarshal(resultCreateCursor, &objMap) + type id string + var idCursor id + json.Unmarshal(*objMap["id"], &idCursor) + + result, err := app.getCurSor(string(idCursor)) if len(app.Password) == 0 { t.Skip() } if err != nil { t.Errorf("get cursor is fail: %v", err) } - fmt.Println(string(result)) + fmt.Println(string(result)) } + func TestDeleteCursor(t *testing.T) { app := newApp(18) if len(app.Password) == 0 { t.Skip() } - result, err := app.deleteCursor("b997c4d6-b514-4567-9c00-1014770ead5c") + resultCreateCursor, err := app.createCursor([]string{"$id", "date"}) + if err != nil { + t.Errorf("create cursor is fail: %v", err) + } + var objMap map[string]*json.RawMessage + json.Unmarshal(resultCreateCursor, &objMap) + type id string + var idCursor id + json.Unmarshal(*objMap["id"], &idCursor) + + result, err := app.deleteCursor(string(idCursor)) if err != nil { t.Errorf("delete cursor is fail: %v", err) } @@ -207,11 +222,11 @@ func TestCreateCurSor(t *testing.T) { if len(app.ApiToken) == 0 { t.Skip() } - result, err := app.createCursor([]string{"$id", "date"}) + _, err := app.createCursor([]string{"$id", "date"}) if err != nil { t.Errorf("create cursor is fail: %v", err) } - fmt.Println("result", string(result)) + } func TestFields(t *testing.T) { From c5e0ee00ac82cb2324540170862211191845a48f Mon Sep 17 00:00:00 2001 From: huong Date: Mon, 16 Dec 2019 17:44:39 +0700 Subject: [PATCH 11/70] clearly name variable --- app.go | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/app.go b/app.go index 84bf027..0bc316f 100644 --- a/app.go +++ b/app.go @@ -1072,15 +1072,15 @@ func (app *App) createCursor(fields []string) ([]byte, error) { } var data = cursor{App: app.AppId, Fields: fields} jsonData, _ := json.Marshal(data) - req, err := app.NewRequest("POST", "records/cursor", bytes.NewBuffer(jsonData), "") + request, err := app.NewRequest("POST", "records/cursor", bytes.NewBuffer(jsonData), "") if err != nil { return nil, err } - res, err := app.do(req) + response, err := app.do(request) if err != nil { return nil, err } - body, err := parseResponse(res) + body, err := parseResponse(response) if err != nil { return nil, err } @@ -1095,16 +1095,16 @@ func (app *App) deleteCursor(cursorId string) (string, error) { if err != nil { return "", err } - req, err := app.NewRequest("DELETE", "records/cursor", bytes.NewBuffer(data), "") + request, err := app.NewRequest("DELETE", "records/cursor", bytes.NewBuffer(data), "") if err != nil { return "", err } - res, err := app.do(req) + response, err := app.do(request) if err != nil { return "", err } - result, err := parseResponse(res) + result, err := parseResponse(response) if err != nil { return "", err } @@ -1118,15 +1118,15 @@ func (app *App) getCurSor(idCursor string) ([]byte, error) { Id string `json:"id,string"` } - req, err := app.NewRequest("GET", "records/cursor", nil, "id="+idCursor) + request, err := app.NewRequest("GET", "records/cursor", nil, "id="+idCursor) if err != nil { return nil, err } - resGetCursor, err := app.do(req) + response, err := app.do(request) if err != nil { return nil, err } - result, err := parseResponse(resGetCursor) + result, err := parseResponse(response) if err != nil { return nil, err } From 95168c72a063cf5992b0f631821b8042c0343b05 Mon Sep 17 00:00:00 2001 From: huong Date: Tue, 17 Dec 2019 13:11:10 +0700 Subject: [PATCH 12/70] change logic function NewRequest and createURL --- app.go | 42 +++++++++++++++++++----------------------- app_test.go | 2 +- 2 files changed, 20 insertions(+), 24 deletions(-) diff --git a/app.go b/app.go index 0bc316f..6ed8a7a 100644 --- a/app.go +++ b/app.go @@ -160,41 +160,37 @@ func (app *App) GetUserAgentHeader() string { return app.userAgentHeader } -func (app *App) createUrl(api string, body io.Reader, query string) url.URL { +func (app *App) createUrl(api string, query string) url.URL { var path string if app.GuestSpaceId == 0 { path = fmt.Sprintf("/k/v1/%s.json", api) } else { path = fmt.Sprintf("/k/guest/%d/v1/%s.json", app.GuestSpaceId, api) } - u := url.URL{} - if body != nil { - u = url.URL{ + if query == "" { + return url.URL{ Scheme: "https", Host: app.Domain, Path: path, } - } else { - u = url.URL{ - Scheme: "https", - Host: app.Domain, - Path: path, - RawQuery: query, - } } - return u - + return url.URL{ + Scheme: "https", + Host: app.Domain, + Path: path, + RawQuery: query, + } } -func (app *App) NewRequest(method, url string, body io.Reader, query string) (*http.Request, error) { +func (app *App) NewRequest(method, url string, body io.Reader) (*http.Request, error) { if len(app.token) == 0 { app.token = base64.StdEncoding.EncodeToString( []byte(app.User + ":" + app.Password)) } - u := app.createUrl(url, body, query) - req, err := http.NewRequest(method, u.String(), nil) + var bodyData io.Reader = nil if body != nil { - req, err = http.NewRequest(method, u.String(), body) + bodyData = body } + req, err := http.NewRequest(method, url, bodyData) if err != nil { return nil, err } @@ -1039,8 +1035,6 @@ func (app *App) Fields() (map[string]*FieldInfo, error) { return nil, err } resp, err := app.do(req) - fmt.Println(resp) - if err != nil { return nil, err } @@ -1072,7 +1066,8 @@ func (app *App) createCursor(fields []string) ([]byte, error) { } var data = cursor{App: app.AppId, Fields: fields} jsonData, _ := json.Marshal(data) - request, err := app.NewRequest("POST", "records/cursor", bytes.NewBuffer(jsonData), "") + url := app.createUrl("records/cursor", "") + request, err := app.NewRequest("POST", url.String(), bytes.NewBuffer(jsonData)) if err != nil { return nil, err } @@ -1095,7 +1090,8 @@ func (app *App) deleteCursor(cursorId string) (string, error) { if err != nil { return "", err } - request, err := app.NewRequest("DELETE", "records/cursor", bytes.NewBuffer(data), "") + url := app.createUrl("records/cursor", "") + request, err := app.NewRequest("DELETE", url.String(), bytes.NewBuffer(data)) if err != nil { return "", err } @@ -1117,8 +1113,8 @@ func (app *App) getCurSor(idCursor string) ([]byte, error) { type requestBody struct { Id string `json:"id,string"` } - - request, err := app.NewRequest("GET", "records/cursor", nil, "id="+idCursor) + url := app.createUrl("records/cursor", "id="+idCursor) + request, err := app.NewRequest("GET", url.String(), nil) if err != nil { return nil, err } diff --git a/app_test.go b/app_test.go index 86e0124..15bc4fa 100644 --- a/app_test.go +++ b/app_test.go @@ -173,6 +173,7 @@ func TestDeleteRecord(t *testing.T) { } func TestGetCursor(t *testing.T) { + app := newApp(18) resultCreateCursor, err := app.createCursor([]string{"$id", "date"}) @@ -226,7 +227,6 @@ func TestCreateCurSor(t *testing.T) { if err != nil { t.Errorf("create cursor is fail: %v", err) } - } func TestFields(t *testing.T) { From f79f09e92956384b8be8d2c47e8bf8fcf58da221 Mon Sep 17 00:00:00 2001 From: huong Date: Tue, 17 Dec 2019 13:22:14 +0700 Subject: [PATCH 13/70] remove empty row --- app.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/app.go b/app.go index 6ed8a7a..04d30f0 100644 --- a/app.go +++ b/app.go @@ -270,11 +270,9 @@ func (app *App) do(req *http.Request) (*http.Response, error) { resp *http.Response err error } - done := make(chan result, 1) go func() { resp, err := app.Client.Do(req) - done <- result{resp, err} }() @@ -284,7 +282,6 @@ func (app *App) do(req *http.Request) (*http.Response, error) { select { case r := <-done: - return r.resp, r.err case <-time.After(app.Timeout): if canceller, ok := app.Client.Transport.(requestCanceler); ok { @@ -294,7 +291,6 @@ func (app *App) do(req *http.Request) (*http.Response, error) { r := <-done if r.err == nil { r.resp.Body.Close() - } }() } From ec228fb2bf0952da5b3751b61207843aac26e1ee Mon Sep 17 00:00:00 2001 From: huong Date: Tue, 17 Dec 2019 13:23:01 +0700 Subject: [PATCH 14/70] remove empty row --- app.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/app.go b/app.go index 04d30f0..61fcee6 100644 --- a/app.go +++ b/app.go @@ -243,9 +243,7 @@ func (app *App) newRequest(method, api string, body io.Reader) (*http.Request, e } else { req.Header.Set("X-Cybozu-API-Token", app.ApiToken) } - req.Header.Set("Content-Type", "application/json") - if len(app.GetUserAgentHeader()) != 0 { req.Header.Set("User-Agent", app.userAgentHeader) } else { From 67d64fb56d09262222b9a71c943c3c4a74538705 Mon Sep 17 00:00:00 2001 From: huong Date: Tue, 17 Dec 2019 15:17:16 +0700 Subject: [PATCH 15/70] refactor code --- app.go | 69 ++++++++++++++++++++++++++++++----------------------- app_test.go | 34 ++++++++++++++++---------- 2 files changed, 60 insertions(+), 43 deletions(-) diff --git a/app.go b/app.go index 61fcee6..701863f 100644 --- a/app.go +++ b/app.go @@ -157,11 +157,14 @@ func (app *App) SetUserAgentHeader(userAgentHeader string) { // GetUserAgentHeader get user-agent header string func (app *App) GetUserAgentHeader() string { - return app.userAgentHeader + if len(app.userAgentHeader) > 0 { + return app.userAgentHeader + } + return NAME + "/" + VERSION } func (app *App) createUrl(api string, query string) url.URL { - var path string + path := "" if app.GuestSpaceId == 0 { path = fmt.Sprintf("/k/v1/%s.json", api) } else { @@ -181,38 +184,43 @@ func (app *App) createUrl(api string, query string) url.URL { RawQuery: query, } } -func (app *App) NewRequest(method, url string, body io.Reader) (*http.Request, error) { - if len(app.token) == 0 { - app.token = base64.StdEncoding.EncodeToString( - []byte(app.User + ":" + app.Password)) +func (app *App) setAuth(request *http.Request) { + if app.basicAuth { + request.SetBasicAuth(app.basicAuthUser, app.basicAuthPassword) + } + + if len(app.ApiToken) > 0 { + request.Header.Set("X-Cybozu-API-Token", app.ApiToken) } - var bodyData io.Reader = nil + + if len(app.User) > 0 && len(app.Password) > 0 { + request.Header.Set("X-Cybozu-Authorization", base64.StdEncoding.EncodeToString( + []byte(app.User+":"+app.Password))) + } +} + +func (app *App) NewRequest(method, url string, body io.Reader) (*http.Request, error) { + bodyData := io.Reader(nil) if body != nil { bodyData = body } - req, err := http.NewRequest(method, url, bodyData) + + request, err := http.NewRequest(method, url, bodyData) if err != nil { return nil, err } - if app.basicAuth { - req.SetBasicAuth(app.basicAuthUser, app.basicAuthPassword) - } - if len(app.ApiToken) == 0 { - req.Header.Set("X-Cybozu-Authorization", app.token) - } else { - req.Header.Set("X-Cybozu-API-Token", app.ApiToken) - } + + request.Header.Set("User-Agent", app.GetUserAgentHeader()) + if method != "GET" { - req.Header.Set("Content-Type", "application/json") + request.Header.Set("Content-Type", "application/json") } - if len(app.GetUserAgentHeader()) != 0 { - req.Header.Set("User-Agent", app.userAgentHeader) - } else { - req.Header.Set("User-Agent", NAME+"/"+VERSION) - } - return req, nil + app.setAuth(request) + + return request, nil } + func (app *App) newRequest(method, api string, body io.Reader) (*http.Request, error) { if len(app.token) == 0 { app.token = base64.StdEncoding.EncodeToString( @@ -244,11 +252,8 @@ func (app *App) newRequest(method, api string, body io.Reader) (*http.Request, e req.Header.Set("X-Cybozu-API-Token", app.ApiToken) } req.Header.Set("Content-Type", "application/json") - if len(app.GetUserAgentHeader()) != 0 { - req.Header.Set("User-Agent", app.userAgentHeader) - } else { - req.Header.Set("User-Agent", NAME+"/"+VERSION) - } + req.Header.Set("User-Agent", app.GetUserAgentHeader()) + return req, nil } @@ -1053,12 +1058,15 @@ func (app *App) Fields() (map[string]*FieldInfo, error) { return ret, nil } -func (app *App) createCursor(fields []string) ([]byte, error) { +func (app *App) createCursor(fields []string, query string, size uint64) ([]byte, error) { type cursor struct { App uint64 `json:"app"` Fields []string `json:"fields"` + Size uint64 `json:"size"` + Query string `json:"query"` } - var data = cursor{App: app.AppId, Fields: fields} + data := cursor{App: app.AppId, Fields: fields, Size: size, Query: query} + fmt.Println("data", data) jsonData, _ := json.Marshal(data) url := app.createUrl("records/cursor", "") request, err := app.NewRequest("POST", url.String(), bytes.NewBuffer(jsonData)) @@ -1066,6 +1074,7 @@ func (app *App) createCursor(fields []string) ([]byte, error) { return nil, err } response, err := app.do(request) + if err != nil { return nil, err } diff --git a/app_test.go b/app_test.go index 15bc4fa..dfdf9dd 100644 --- a/app_test.go +++ b/app_test.go @@ -173,10 +173,9 @@ func TestDeleteRecord(t *testing.T) { } func TestGetCursor(t *testing.T) { - app := newApp(18) - resultCreateCursor, err := app.createCursor([]string{"$id", "date"}) + resultCreateCursor, err := app.createCursor([]string{"$id", "date"}, "", 100) if err != nil { t.Errorf("create cursor is fail: %v", err) } @@ -197,33 +196,42 @@ func TestGetCursor(t *testing.T) { fmt.Println(string(result)) } +func (app *App) createCursorForTest() string { + cursor, err := app.createCursor([]string{"$id", "Status"}, "", 600) + if err != nil { + fmt.Println("create cursor is fail: ", err) + } + + var objMap map[string]*json.RawMessage + json.Unmarshal(cursor, &objMap) + + var id string + json.Unmarshal(*objMap["id"], &id) + return id +} + func TestDeleteCursor(t *testing.T) { app := newApp(18) if len(app.Password) == 0 { t.Skip() } - resultCreateCursor, err := app.createCursor([]string{"$id", "date"}) - if err != nil { - t.Errorf("create cursor is fail: %v", err) - } - var objMap map[string]*json.RawMessage - json.Unmarshal(resultCreateCursor, &objMap) - type id string - var idCursor id - json.Unmarshal(*objMap["id"], &idCursor) - result, err := app.deleteCursor(string(idCursor)) + id := app.createCursorForTest() + result, err := app.deleteCursor(string(id)) + if err != nil { t.Errorf("delete cursor is fail: %v", err) } fmt.Println(result) } + func TestCreateCurSor(t *testing.T) { + app := newAppWithApiToken(18) if len(app.ApiToken) == 0 { t.Skip() } - _, err := app.createCursor([]string{"$id", "date"}) + _, err := app.createCursor([]string{"$id", "date"}, "", 100) if err != nil { t.Errorf("create cursor is fail: %v", err) } From 72c8f673b83e7ce6d157faff55349dadae650874 Mon Sep 17 00:00:00 2001 From: huong Date: Wed, 18 Dec 2019 11:44:23 +0700 Subject: [PATCH 16/70] refactor code review --- app.go | 35 +++++++++++++++-------------------- app_test.go | 14 +++----------- 2 files changed, 18 insertions(+), 31 deletions(-) diff --git a/app.go b/app.go index 701863f..1ccf253 100644 --- a/app.go +++ b/app.go @@ -164,25 +164,21 @@ func (app *App) GetUserAgentHeader() string { } func (app *App) createUrl(api string, query string) url.URL { - path := "" - if app.GuestSpaceId == 0 { - path = fmt.Sprintf("/k/v1/%s.json", api) - } else { + path := fmt.Sprintf("/k/v1/%s.json", api) + if app.GuestSpaceId > 0 { path = fmt.Sprintf("/k/guest/%d/v1/%s.json", app.GuestSpaceId, api) } - if query == "" { - return url.URL{ - Scheme: "https", - Host: app.Domain, - Path: path, - } + + resultUrl := url.URL{ + Scheme: "https", + Host: app.Domain, + Path: path, } - return url.URL{ - Scheme: "https", - Host: app.Domain, - Path: path, - RawQuery: query, + + if len(query) > 0 { + resultUrl.RawQuery = query } + return resultUrl } func (app *App) setAuth(request *http.Request) { if app.basicAuth { @@ -1066,7 +1062,6 @@ func (app *App) createCursor(fields []string, query string, size uint64) ([]byte Query string `json:"query"` } data := cursor{App: app.AppId, Fields: fields, Size: size, Query: query} - fmt.Println("data", data) jsonData, _ := json.Marshal(data) url := app.createUrl("records/cursor", "") request, err := app.NewRequest("POST", url.String(), bytes.NewBuffer(jsonData)) @@ -1085,11 +1080,11 @@ func (app *App) createCursor(fields []string, query string, size uint64) ([]byte return body, nil } -func (app *App) deleteCursor(cursorId string) (string, error) { +func (app *App) deleteCursor(id string) (string, error) { type requestBody struct { Id string `json:"id"` } - data, err := json.Marshal(requestBody{Id: cursorId}) + data, err := json.Marshal(requestBody{Id: id}) if err != nil { return "", err } @@ -1112,11 +1107,11 @@ func (app *App) deleteCursor(cursorId string) (string, error) { return "delete success", nil } -func (app *App) getCurSor(idCursor string) ([]byte, error) { +func (app *App) getCurSor(id string) ([]byte, error) { type requestBody struct { Id string `json:"id,string"` } - url := app.createUrl("records/cursor", "id="+idCursor) + url := app.createUrl("records/cursor", "id="+id) request, err := app.NewRequest("GET", url.String(), nil) if err != nil { return nil, err diff --git a/app_test.go b/app_test.go index dfdf9dd..3782f81 100644 --- a/app_test.go +++ b/app_test.go @@ -175,17 +175,9 @@ func TestDeleteRecord(t *testing.T) { func TestGetCursor(t *testing.T) { app := newApp(18) - resultCreateCursor, err := app.createCursor([]string{"$id", "date"}, "", 100) - if err != nil { - t.Errorf("create cursor is fail: %v", err) - } - var objMap map[string]*json.RawMessage - json.Unmarshal(resultCreateCursor, &objMap) - type id string - var idCursor id - json.Unmarshal(*objMap["id"], &idCursor) + id := app.createCursorForTest() + result, err := app.getCurSor(string(id)) - result, err := app.getCurSor(string(idCursor)) if len(app.Password) == 0 { t.Skip() } @@ -199,7 +191,7 @@ func TestGetCursor(t *testing.T) { func (app *App) createCursorForTest() string { cursor, err := app.createCursor([]string{"$id", "Status"}, "", 600) if err != nil { - fmt.Println("create cursor is fail: ", err) + fmt.Println("createCursorForTest failed: ", err) } var objMap map[string]*json.RawMessage From 5ffed2026be29adb393a21687439eacb1385cdf3 Mon Sep 17 00:00:00 2001 From: huong Date: Wed, 18 Dec 2019 14:14:37 +0700 Subject: [PATCH 17/70] refactor code review 3 --- app.go | 22 +++++++++++----------- app_test.go | 15 +++++++-------- 2 files changed, 18 insertions(+), 19 deletions(-) diff --git a/app.go b/app.go index 1ccf253..8f3aaa8 100644 --- a/app.go +++ b/app.go @@ -1069,7 +1069,6 @@ func (app *App) createCursor(fields []string, query string, size uint64) ([]byte return nil, err } response, err := app.do(request) - if err != nil { return nil, err } @@ -1080,34 +1079,35 @@ func (app *App) createCursor(fields []string, query string, size uint64) ([]byte return body, nil } -func (app *App) deleteCursor(id string) (string, error) { +func (app *App) deleteCursor(id string) error { type requestBody struct { Id string `json:"id"` } data, err := json.Marshal(requestBody{Id: id}) if err != nil { - return "", err + return err } + url := app.createUrl("records/cursor", "") request, err := app.NewRequest("DELETE", url.String(), bytes.NewBuffer(data)) if err != nil { - return "", err + return err } + response, err := app.do(request) if err != nil { - return "", err + return err } - result, err := parseResponse(response) + _, err = parseResponse(response) if err != nil { - return "", err - } - if result != nil { + return err } - return "delete success", nil + + return nil } -func (app *App) getCurSor(id string) ([]byte, error) { +func (app *App) getCursor(id string) ([]byte, error) { type requestBody struct { Id string `json:"id,string"` } diff --git a/app_test.go b/app_test.go index 3782f81..e794510 100644 --- a/app_test.go +++ b/app_test.go @@ -175,12 +175,13 @@ func TestDeleteRecord(t *testing.T) { func TestGetCursor(t *testing.T) { app := newApp(18) - id := app.createCursorForTest() - result, err := app.getCurSor(string(id)) - if len(app.Password) == 0 { t.Skip() } + + id := app.createCursorForTest() + result, err := app.getCursor(string(id)) + if err != nil { t.Errorf("get cursor is fail: %v", err) } @@ -209,23 +210,21 @@ func TestDeleteCursor(t *testing.T) { } id := app.createCursorForTest() - result, err := app.deleteCursor(string(id)) + err := app.deleteCursor(string(id)) if err != nil { - t.Errorf("delete cursor is fail: %v", err) + t.Errorf("TestDeleteCursor is failed: %v", err) } - fmt.Println(result) } func TestCreateCurSor(t *testing.T) { - app := newAppWithApiToken(18) if len(app.ApiToken) == 0 { t.Skip() } _, err := app.createCursor([]string{"$id", "date"}, "", 100) if err != nil { - t.Errorf("create cursor is fail: %v", err) + t.Errorf("TestCreateCurSor is failed: %v", err) } } From ed8438bc842f720effb48a876bc4861906046b71 Mon Sep 17 00:00:00 2001 From: huong Date: Wed, 18 Dec 2019 14:33:10 +0700 Subject: [PATCH 18/70] change name TestCreateCurSor function --- app_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app_test.go b/app_test.go index e794510..149039f 100644 --- a/app_test.go +++ b/app_test.go @@ -217,7 +217,7 @@ func TestDeleteCursor(t *testing.T) { } } -func TestCreateCurSor(t *testing.T) { +func TestCreateCursor(t *testing.T) { app := newAppWithApiToken(18) if len(app.ApiToken) == 0 { t.Skip() From 013ebc4c532d5899f32d663a6b0b5a155655695e Mon Sep 17 00:00:00 2001 From: huong Date: Wed, 18 Dec 2019 15:43:27 +0700 Subject: [PATCH 19/70] refactor code review 4 --- app.go | 3 --- app_test.go | 4 ++-- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/app.go b/app.go index 8f3aaa8..7969c81 100644 --- a/app.go +++ b/app.go @@ -1108,9 +1108,6 @@ func (app *App) deleteCursor(id string) error { } func (app *App) getCursor(id string) ([]byte, error) { - type requestBody struct { - Id string `json:"id,string"` - } url := app.createUrl("records/cursor", "id="+id) request, err := app.NewRequest("GET", url.String(), nil) if err != nil { diff --git a/app_test.go b/app_test.go index 149039f..e0df00a 100644 --- a/app_test.go +++ b/app_test.go @@ -183,14 +183,14 @@ func TestGetCursor(t *testing.T) { result, err := app.getCursor(string(id)) if err != nil { - t.Errorf("get cursor is fail: %v", err) + t.Errorf("TestGetCursor is failed: %v", err) } fmt.Println(string(result)) } func (app *App) createCursorForTest() string { - cursor, err := app.createCursor([]string{"$id", "Status"}, "", 600) + cursor, err := app.createCursor([]string{"$id", "Status"}, "", 400) if err != nil { fmt.Println("createCursorForTest failed: ", err) } From 80e2468f9a2e4310479d9c18591196e7019b397b Mon Sep 17 00:00:00 2001 From: huong Date: Wed, 18 Dec 2019 15:50:20 +0700 Subject: [PATCH 20/70] change logic getUserAgentHeader --- app.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/app.go b/app.go index 7969c81..d32fbb6 100644 --- a/app.go +++ b/app.go @@ -24,7 +24,7 @@ import ( ) const ( - NAME = "kintone-go-SDK" + NAME = "go-kintone" VERSION = "0.1.2" DEFAULT_TIMEOUT = time.Second * 600 // Default value for App.Timeout ) @@ -157,10 +157,11 @@ func (app *App) SetUserAgentHeader(userAgentHeader string) { // GetUserAgentHeader get user-agent header string func (app *App) GetUserAgentHeader() string { + goUserAgent := NAME + "/" + VERSION if len(app.userAgentHeader) > 0 { - return app.userAgentHeader + return goUserAgent + " " + app.userAgentHeader } - return NAME + "/" + VERSION + return goUserAgent } func (app *App) createUrl(api string, query string) url.URL { From af018824da387deb90404912ccca31ebe410b6af Mon Sep 17 00:00:00 2001 From: huong Date: Thu, 19 Dec 2019 10:44:48 +0700 Subject: [PATCH 21/70] change variable name user agent --- app.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/app.go b/app.go index d32fbb6..17aa16e 100644 --- a/app.go +++ b/app.go @@ -124,7 +124,7 @@ type App struct { basicAuth bool // true to use Basic Authentication. basicAuthUser string // User name for Basic Authentication. basicAuthPassword string // Password for Basic Authentication. - userAgentHeader string // User-agent request header string + extUserAgent string // User-agent request header string } // SetBasicAuth enables use of HTTP basic authentication for access @@ -152,16 +152,16 @@ func (app *App) GetBasicAuthPassword() string { // SetUserAgentHeader set custom user-agent header for http request func (app *App) SetUserAgentHeader(userAgentHeader string) { - app.userAgentHeader = userAgentHeader + app.extUserAgent = userAgentHeader } // GetUserAgentHeader get user-agent header string func (app *App) GetUserAgentHeader() string { - goUserAgent := NAME + "/" + VERSION - if len(app.userAgentHeader) > 0 { - return goUserAgent + " " + app.userAgentHeader + userAgent := NAME + "/" + VERSION + if len(app.extUserAgent) > 0 { + return userAgent + " " + app.extUserAgent } - return goUserAgent + return userAgent } func (app *App) createUrl(api string, query string) url.URL { From 97aa012c439026ef39d6475354e23ffef4a84222 Mon Sep 17 00:00:00 2001 From: huong Date: Thu, 19 Dec 2019 15:09:05 +0700 Subject: [PATCH 22/70] add function decode cursor --- app.go | 18 ++++++++++++------ app_test.go | 33 +++++++++++++-------------------- cursor.go | 18 ++++++++++++++++++ 3 files changed, 43 insertions(+), 26 deletions(-) create mode 100644 cursor.go diff --git a/app.go b/app.go index 17aa16e..f65287d 100644 --- a/app.go +++ b/app.go @@ -1055,7 +1055,8 @@ func (app *App) Fields() (map[string]*FieldInfo, error) { return ret, nil } -func (app *App) createCursor(fields []string, query string, size uint64) ([]byte, error) { +//CreateCursor return the meta data of the Cursor in this application +func (app *App) CreateCursor(fields []string, query string, size uint64) (*Cursor, error) { type cursor struct { App uint64 `json:"app"` Fields []string `json:"fields"` @@ -1077,10 +1078,12 @@ func (app *App) createCursor(fields []string, query string, size uint64) ([]byte if err != nil { return nil, err } - return body, nil + result, err := decodeCursor(body) + return result, nil } -func (app *App) deleteCursor(id string) error { +//Delete a cursorID +func (app *App) DeleteCursor(id string) error { type requestBody struct { Id string `json:"id"` } @@ -1108,7 +1111,9 @@ func (app *App) deleteCursor(id string) error { return nil } -func (app *App) getCursor(id string) ([]byte, error) { +//Using Cursor Id to get all records +//GetRecordsByCursor return the meta data of the Record in this application +func (app *App) GetRecordsByCursor(id string) ([]*Record, error) { url := app.createUrl("records/cursor", "id="+id) request, err := app.NewRequest("GET", url.String(), nil) if err != nil { @@ -1118,9 +1123,10 @@ func (app *App) getCursor(id string) ([]byte, error) { if err != nil { return nil, err } - result, err := parseResponse(response) + data, err := parseResponse(response) if err != nil { return nil, err } - return result, nil + record, _ := DecodeRecords(data) + return record, nil } diff --git a/app_test.go b/app_test.go index e0df00a..1cec4da 100644 --- a/app_test.go +++ b/app_test.go @@ -6,7 +6,6 @@ package kintone import ( "bytes" - "encoding/json" "fmt" "io/ioutil" "os" @@ -172,35 +171,28 @@ func TestDeleteRecord(t *testing.T) { } } -func TestGetCursor(t *testing.T) { +func TestGetRecordsByCursor(t *testing.T) { app := newApp(18) if len(app.Password) == 0 { t.Skip() } - id := app.createCursorForTest() - result, err := app.getCursor(string(id)) + cursor := app.createCursorForTest() + _, err := app.GetRecordsByCursor(string(cursor.Id)) if err != nil { t.Errorf("TestGetCursor is failed: %v", err) } - - fmt.Println(string(result)) } -func (app *App) createCursorForTest() string { - cursor, err := app.createCursor([]string{"$id", "Status"}, "", 400) +func (app *App) createCursorForTest() *Cursor { + cursor, err := app.CreateCursor([]string{"$id", "Status"}, "", 400) + fmt.Println("cursor", cursor) if err != nil { fmt.Println("createCursorForTest failed: ", err) } - - var objMap map[string]*json.RawMessage - json.Unmarshal(cursor, &objMap) - - var id string - json.Unmarshal(*objMap["id"], &id) - return id + return cursor } func TestDeleteCursor(t *testing.T) { @@ -209,8 +201,9 @@ func TestDeleteCursor(t *testing.T) { t.Skip() } - id := app.createCursorForTest() - err := app.deleteCursor(string(id)) + cursor := app.createCursorForTest() + fmt.Println("cursor", cursor) + err := app.DeleteCursor(string(cursor.Id)) if err != nil { t.Errorf("TestDeleteCursor is failed: %v", err) @@ -218,11 +211,11 @@ func TestDeleteCursor(t *testing.T) { } func TestCreateCursor(t *testing.T) { - app := newAppWithApiToken(18) - if len(app.ApiToken) == 0 { + app := newApp(18) + if len(app.Password) == 0 { t.Skip() } - _, err := app.createCursor([]string{"$id", "date"}, "", 100) + _, err := app.CreateCursor([]string{"$id", "date"}, "", 100) if err != nil { t.Errorf("TestCreateCurSor is failed: %v", err) } diff --git a/cursor.go b/cursor.go new file mode 100644 index 0000000..90b2bc3 --- /dev/null +++ b/cursor.go @@ -0,0 +1,18 @@ +package kintone + +import ( + "encoding/json" +) + +type Cursor struct { + Id string `json:"id"` + TotalCount string `json:"totalCount"` +} + +func decodeCursor(b []byte) (c *Cursor, err error) { + err = json.Unmarshal(b, &c) + if err != nil { + return nil, err + } + return c, nil +} From ba1fb5f8426e7568968c1fee8059aee4f0b3763c Mon Sep 17 00:00:00 2001 From: huong Date: Thu, 19 Dec 2019 16:27:54 +0700 Subject: [PATCH 23/70] refactor code review --- app.go | 2 +- app_test.go | 4 +++- cursor.go | 1 + 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/app.go b/app.go index f65287d..21383f9 100644 --- a/app.go +++ b/app.go @@ -1082,7 +1082,7 @@ func (app *App) CreateCursor(fields []string, query string, size uint64) (*Curso return result, nil } -//Delete a cursorID +//Delete cursor func (app *App) DeleteCursor(id string) error { type requestBody struct { Id string `json:"id"` diff --git a/app_test.go b/app_test.go index 1cec4da..dddea6c 100644 --- a/app_test.go +++ b/app_test.go @@ -179,11 +179,13 @@ func TestGetRecordsByCursor(t *testing.T) { } cursor := app.createCursorForTest() - _, err := app.GetRecordsByCursor(string(cursor.Id)) + record, err := app.GetRecordsByCursor(string(cursor.Id)) if err != nil { t.Errorf("TestGetCursor is failed: %v", err) } + fmt.Println(record) + } func (app *App) createCursorForTest() *Cursor { diff --git a/cursor.go b/cursor.go index 90b2bc3..9bf2e2e 100644 --- a/cursor.go +++ b/cursor.go @@ -4,6 +4,7 @@ import ( "encoding/json" ) +//object Cursor structure type Cursor struct { Id string `json:"id"` TotalCount string `json:"totalCount"` From b4ebaff04259f10c55484bb7b0632797c4fea0c9 Mon Sep 17 00:00:00 2001 From: huong Date: Thu, 19 Dec 2019 16:44:18 +0700 Subject: [PATCH 24/70] add unit test cursor --- cursor.go | 1 + cursor_test.go | 16 ++++++++++++++++ 2 files changed, 17 insertions(+) create mode 100644 cursor_test.go diff --git a/cursor.go b/cursor.go index 9bf2e2e..df88a26 100644 --- a/cursor.go +++ b/cursor.go @@ -10,6 +10,7 @@ type Cursor struct { TotalCount string `json:"totalCount"` } +//decode cursor func decodeCursor(b []byte) (c *Cursor, err error) { err = json.Unmarshal(b, &c) if err != nil { diff --git a/cursor_test.go b/cursor_test.go new file mode 100644 index 0000000..c7a207c --- /dev/null +++ b/cursor_test.go @@ -0,0 +1,16 @@ +package kintone + +import ( + "fmt" + "testing" +) + +func TestDecodeCursor(t *testing.T) { + data := []byte(`{"id":"aaaaaaaaaaaaaaaaaa","totalCount":"null"}`) + cursor, err := decodeCursor(data) + if err != nil { + t.Errorf("TestDecodeCursor is failed: %v", err) + + } + fmt.Println(cursor) +} From afb1dd7b9672c275d22b0473c1c984f46855bd61 Mon Sep 17 00:00:00 2001 From: huong Date: Thu, 19 Dec 2019 17:48:13 +0700 Subject: [PATCH 25/70] Refactor code review change comment --- app.go | 3 ++- cursor.go | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/app.go b/app.go index 21383f9..49887fe 100644 --- a/app.go +++ b/app.go @@ -196,6 +196,7 @@ func (app *App) setAuth(request *http.Request) { } } +//NewRequest create a request connect to kintone api. func (app *App) NewRequest(method, url string, body io.Reader) (*http.Request, error) { bodyData := io.Reader(nil) if body != nil { @@ -1082,7 +1083,7 @@ func (app *App) CreateCursor(fields []string, query string, size uint64) (*Curso return result, nil } -//Delete cursor +// DeleteCursor - Delete cursor by id func (app *App) DeleteCursor(id string) error { type requestBody struct { Id string `json:"id"` diff --git a/cursor.go b/cursor.go index df88a26..4fa09dc 100644 --- a/cursor.go +++ b/cursor.go @@ -4,13 +4,13 @@ import ( "encoding/json" ) -//object Cursor structure +//Object Cursor structure type Cursor struct { Id string `json:"id"` TotalCount string `json:"totalCount"` } -//decode cursor +//decodeCursor decodes JSON response for cursor api func decodeCursor(b []byte) (c *Cursor, err error) { err = json.Unmarshal(b, &c) if err != nil { From f8fffce6ae39c861874b8d8c7becb3858995b47c Mon Sep 17 00:00:00 2001 From: huong Date: Tue, 24 Dec 2019 10:35:08 +0700 Subject: [PATCH 26/70] add field next to record --- record.go | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/record.go b/record.go index 88f93b1..0c72ce3 100644 --- a/record.go +++ b/record.go @@ -23,20 +23,21 @@ type Record struct { id uint64 revision int64 Fields map[string]interface{} + next bool } // NewRecord creates an instance of Record. // // The revision number is initialized to -1. func NewRecord(fields map[string]interface{}) *Record { - return &Record{0, -1, fields} + return &Record{0, -1, fields, false} } // NewRecordWithId creates using an existing record id. // // The revision number is initialized to -1. func NewRecordWithId(id uint64, fields map[string]interface{}) *Record { - return &Record{id, -1, fields} + return &Record{id, -1, fields, false} } // MarshalJSON marshals field data of a record into JSON. @@ -51,6 +52,11 @@ func (rec Record) Id() uint64 { return rec.id } +// Next return the status the record +func (rec Record) Next() bool { + return rec.next +} + // Revision returns the record revision number. func (rec Record) Revision() int64 { return rec.revision @@ -125,9 +131,9 @@ type recordData map[string]struct { Value interface{} `json:"value"` } -func decodeRecordData(data recordData) (*Record, error) { +func decodeRecordData(data recordData, next bool) (*Record, error) { fields := make(map[string]interface{}) - rec := &Record{0, -1, fields} + rec := &Record{0, -1, fields, next} for key, v := range data { switch v.Type { case FT_SINGLE_LINE_TEXT: @@ -284,7 +290,7 @@ func decodeRecordData(data recordData) (*Record, error) { if err != nil { return nil, err } - r, err := decodeRecordData(recordData(rd)) + r, err := decodeRecordData(recordData(rd), false) if err != nil { return nil, err } @@ -319,14 +325,16 @@ func decodeRecordData(data recordData) (*Record, error) { func DecodeRecords(b []byte) ([]*Record, error) { var t struct { Records []recordData `json:"records"` + Next bool `json:"next"` } err := json.Unmarshal(b, &t) if err != nil { return nil, errors.New("Invalid JSON format") } + rec_list := make([]*Record, len(t.Records)) for i, rd := range t.Records { - r, err := decodeRecordData(rd) + r, err := decodeRecordData(rd, t.Next) if err != nil { return nil, err } @@ -344,7 +352,7 @@ func DecodeRecord(b []byte) (*Record, error) { if err != nil { return nil, errors.New("Invalid JSON format") } - rec, err := decodeRecordData(t.RecordData) + rec, err := decodeRecordData(t.RecordData, false) if err != nil { return nil, err } From 9c754ef91b9bc7d233819dc0913e33cf49083a30 Mon Sep 17 00:00:00 2001 From: huong Date: Tue, 24 Dec 2019 11:19:51 +0700 Subject: [PATCH 27/70] add struct record cursor --- app.go | 4 ++-- cursor.go | 19 +++++++++++++++++++ record.go | 21 +++++++-------------- 3 files changed, 28 insertions(+), 16 deletions(-) diff --git a/app.go b/app.go index 49887fe..0bbf3f0 100644 --- a/app.go +++ b/app.go @@ -1114,7 +1114,7 @@ func (app *App) DeleteCursor(id string) error { //Using Cursor Id to get all records //GetRecordsByCursor return the meta data of the Record in this application -func (app *App) GetRecordsByCursor(id string) ([]*Record, error) { +func (app *App) GetRecordsByCursor(id string) (*RecordCursor, error) { url := app.createUrl("records/cursor", "id="+id) request, err := app.NewRequest("GET", url.String(), nil) if err != nil { @@ -1128,6 +1128,6 @@ func (app *App) GetRecordsByCursor(id string) ([]*Record, error) { if err != nil { return nil, err } - record, _ := DecodeRecords(data) + record, _ := decodeRecordCursor(data) return record, nil } diff --git a/cursor.go b/cursor.go index 4fa09dc..1fb3233 100644 --- a/cursor.go +++ b/cursor.go @@ -9,6 +9,10 @@ type Cursor struct { Id string `json:"id"` TotalCount string `json:"totalCount"` } +type RecordCursor struct { + Records []*Record `json:"records"` + Next bool `json:"next"` +} //decodeCursor decodes JSON response for cursor api func decodeCursor(b []byte) (c *Cursor, err error) { @@ -18,3 +22,18 @@ func decodeCursor(b []byte) (c *Cursor, err error) { } return c, nil } +func decodeRecordCursor(b []byte) (rc *RecordCursor, err error) { + var t struct { + next bool + } + err = json.Unmarshal(b, &t) + if err != nil { + return nil, err + } + listRecord, err := DecodeRecords(b) + if err != nil { + return nil, err + } + records := &RecordCursor{Records: listRecord, Next: t.next} + return records, nil +} diff --git a/record.go b/record.go index 0c72ce3..e2ec6c3 100644 --- a/record.go +++ b/record.go @@ -23,21 +23,20 @@ type Record struct { id uint64 revision int64 Fields map[string]interface{} - next bool } // NewRecord creates an instance of Record. // // The revision number is initialized to -1. func NewRecord(fields map[string]interface{}) *Record { - return &Record{0, -1, fields, false} + return &Record{0, -1, fields} } // NewRecordWithId creates using an existing record id. // // The revision number is initialized to -1. func NewRecordWithId(id uint64, fields map[string]interface{}) *Record { - return &Record{id, -1, fields, false} + return &Record{id, -1, fields} } // MarshalJSON marshals field data of a record into JSON. @@ -52,11 +51,6 @@ func (rec Record) Id() uint64 { return rec.id } -// Next return the status the record -func (rec Record) Next() bool { - return rec.next -} - // Revision returns the record revision number. func (rec Record) Revision() int64 { return rec.revision @@ -131,9 +125,9 @@ type recordData map[string]struct { Value interface{} `json:"value"` } -func decodeRecordData(data recordData, next bool) (*Record, error) { +func decodeRecordData(data recordData) (*Record, error) { fields := make(map[string]interface{}) - rec := &Record{0, -1, fields, next} + rec := &Record{0, -1, fields} for key, v := range data { switch v.Type { case FT_SINGLE_LINE_TEXT: @@ -290,7 +284,7 @@ func decodeRecordData(data recordData, next bool) (*Record, error) { if err != nil { return nil, err } - r, err := decodeRecordData(recordData(rd), false) + r, err := decodeRecordData(recordData(rd)) if err != nil { return nil, err } @@ -325,7 +319,6 @@ func decodeRecordData(data recordData, next bool) (*Record, error) { func DecodeRecords(b []byte) ([]*Record, error) { var t struct { Records []recordData `json:"records"` - Next bool `json:"next"` } err := json.Unmarshal(b, &t) if err != nil { @@ -334,7 +327,7 @@ func DecodeRecords(b []byte) ([]*Record, error) { rec_list := make([]*Record, len(t.Records)) for i, rd := range t.Records { - r, err := decodeRecordData(rd, t.Next) + r, err := decodeRecordData(rd) if err != nil { return nil, err } @@ -352,7 +345,7 @@ func DecodeRecord(b []byte) (*Record, error) { if err != nil { return nil, errors.New("Invalid JSON format") } - rec, err := decodeRecordData(t.RecordData, false) + rec, err := decodeRecordData(t.RecordData) if err != nil { return nil, err } From 6abce35cf966a8d8dca0a99840f27eff1285cb30 Mon Sep 17 00:00:00 2001 From: huong Date: Tue, 24 Dec 2019 11:24:35 +0700 Subject: [PATCH 28/70] expose decode record cursor --- app.go | 2 +- cursor.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app.go b/app.go index 0bbf3f0..575afba 100644 --- a/app.go +++ b/app.go @@ -1128,6 +1128,6 @@ func (app *App) GetRecordsByCursor(id string) (*RecordCursor, error) { if err != nil { return nil, err } - record, _ := decodeRecordCursor(data) + record, _ := DecodeRecordCursor(data) return record, nil } diff --git a/cursor.go b/cursor.go index 1fb3233..80587a0 100644 --- a/cursor.go +++ b/cursor.go @@ -22,7 +22,7 @@ func decodeCursor(b []byte) (c *Cursor, err error) { } return c, nil } -func decodeRecordCursor(b []byte) (rc *RecordCursor, err error) { +func DecodeRecordCursor(b []byte) (rc *RecordCursor, err error) { var t struct { next bool } From 0c05caef81c98459e0ffcff51a61c76713229ed6 Mon Sep 17 00:00:00 2001 From: huong Date: Tue, 24 Dec 2019 13:18:38 +0700 Subject: [PATCH 29/70] create record cursor response struct --- app.go | 9 ++++++--- cursor.go | 8 ++++---- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/app.go b/app.go index 575afba..7986947 100644 --- a/app.go +++ b/app.go @@ -1114,7 +1114,7 @@ func (app *App) DeleteCursor(id string) error { //Using Cursor Id to get all records //GetRecordsByCursor return the meta data of the Record in this application -func (app *App) GetRecordsByCursor(id string) (*RecordCursor, error) { +func (app *App) GetRecordsByCursor(id string) (*GetRecordsCursorResponse, error) { url := app.createUrl("records/cursor", "id="+id) request, err := app.NewRequest("GET", url.String(), nil) if err != nil { @@ -1128,6 +1128,9 @@ func (app *App) GetRecordsByCursor(id string) (*RecordCursor, error) { if err != nil { return nil, err } - record, _ := DecodeRecordCursor(data) - return record, nil + recordsCursorResponse, err := DecodeGetRecordsCursorResponse(data) + if err != nil { + return nil, err + } + return recordsCursorResponse, nil } diff --git a/cursor.go b/cursor.go index 80587a0..00579db 100644 --- a/cursor.go +++ b/cursor.go @@ -9,7 +9,7 @@ type Cursor struct { Id string `json:"id"` TotalCount string `json:"totalCount"` } -type RecordCursor struct { +type GetRecordsCursorResponse struct { Records []*Record `json:"records"` Next bool `json:"next"` } @@ -22,7 +22,7 @@ func decodeCursor(b []byte) (c *Cursor, err error) { } return c, nil } -func DecodeRecordCursor(b []byte) (rc *RecordCursor, err error) { +func DecodeGetRecordsCursorResponse(b []byte) (rc *GetRecordsCursorResponse, err error) { var t struct { next bool } @@ -34,6 +34,6 @@ func DecodeRecordCursor(b []byte) (rc *RecordCursor, err error) { if err != nil { return nil, err } - records := &RecordCursor{Records: listRecord, Next: t.next} - return records, nil + getRecordsCursorResponse := &GetRecordsCursorResponse{Records: listRecord, Next: t.next} + return getRecordsCursorResponse, nil } From b56ee5da2a75f13284d092372eb3a0763eb255db Mon Sep 17 00:00:00 2001 From: huong Date: Tue, 24 Dec 2019 14:18:07 +0700 Subject: [PATCH 30/70] change struct decode record response --- cursor.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cursor.go b/cursor.go index 00579db..9494987 100644 --- a/cursor.go +++ b/cursor.go @@ -24,7 +24,7 @@ func decodeCursor(b []byte) (c *Cursor, err error) { } func DecodeGetRecordsCursorResponse(b []byte) (rc *GetRecordsCursorResponse, err error) { var t struct { - next bool + Next bool `json:"next"` } err = json.Unmarshal(b, &t) if err != nil { @@ -34,6 +34,6 @@ func DecodeGetRecordsCursorResponse(b []byte) (rc *GetRecordsCursorResponse, err if err != nil { return nil, err } - getRecordsCursorResponse := &GetRecordsCursorResponse{Records: listRecord, Next: t.next} + getRecordsCursorResponse := &GetRecordsCursorResponse{Records: listRecord, Next: t.Next} return getRecordsCursorResponse, nil } From 803b30cf401330c50e7708a58184642a600a1e24 Mon Sep 17 00:00:00 2001 From: Vo Duy Khanh Date: Tue, 31 Dec 2019 12:04:18 +0700 Subject: [PATCH 31/70] Change version to 0.3.0 --- README.md | 2 +- app.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 82d5521..f37fc34 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ to access [kintone][] with its official REST API ([en][APIen], [ja][APIja]). ## Version -0.2.0 +0.3.0 ## License diff --git a/app.go b/app.go index aace325..6599fa7 100644 --- a/app.go +++ b/app.go @@ -25,7 +25,7 @@ import ( const ( NAME = "kintone-go-SDK" - VERSION = "0.2.0" + VERSION = "0.3.0" DEFAULT_TIMEOUT = time.Second * 600 // Default value for App.Timeout ) From 1391b42b9e2e053d44b12b28427acd329a9894da Mon Sep 17 00:00:00 2001 From: huong Date: Thu, 2 Jan 2020 16:22:58 +0700 Subject: [PATCH 32/70] Create app test --- app_test.go | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/app_test.go b/app_test.go index d9e8f7b..16331eb 100644 --- a/app_test.go +++ b/app_test.go @@ -6,13 +6,27 @@ package kintone import ( "bytes" + "crypto/tls" + "fmt" "io/ioutil" + "net" + "net/http" + "net/http/httptest" "os" "strings" "testing" "time" ) +func newAppForTest(domain string, user string, password string, appID uint64) *App { + return &App{ + Domain: domain, + User: user, + Password: password, + AppId: appID, + } +} + func newApp(appID uint64) *App { return &App{ Domain: os.Getenv("KINTONE_DOMAIN"), From ceede49828d94e0b72de609097225104ce1bbe15 Mon Sep 17 00:00:00 2001 From: huong Date: Thu, 2 Jan 2020 16:23:17 +0700 Subject: [PATCH 33/70] create response test json --- app_test.go | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/app_test.go b/app_test.go index 16331eb..7fc2446 100644 --- a/app_test.go +++ b/app_test.go @@ -44,6 +44,17 @@ func newAppWithApiToken(appId uint64) *App { } } +func createResponseLocalTestServer(data string) (*httptest.Server, error) { + ts, err := NewLocalHTTPSTestServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + fmt.Fprint(w, data) + })) + if err != nil { + return nil, err + } + + return ts, nil +} + func newAppInGuestSpace(appId uint64, guestSpaceId uint64) *App { return &App{ Domain: os.Getenv("KINTONE_DOMAIN"), From 441e96cb538242aa8d65b272113b2e1367b6ab36 Mon Sep 17 00:00:00 2001 From: huong Date: Thu, 2 Jan 2020 16:24:17 +0700 Subject: [PATCH 34/70] create local test server --- app_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/app_test.go b/app_test.go index 7fc2446..d951cc7 100644 --- a/app_test.go +++ b/app_test.go @@ -55,6 +55,7 @@ func createResponseLocalTestServer(data string) (*httptest.Server, error) { return ts, nil } + ts.Listener = l func newAppInGuestSpace(appId uint64, guestSpaceId uint64) *App { return &App{ Domain: os.Getenv("KINTONE_DOMAIN"), From 9672c2f7fc9f9f5d4f0219489f49a9e42c105b3c Mon Sep 17 00:00:00 2001 From: huong Date: Thu, 2 Jan 2020 16:25:30 +0700 Subject: [PATCH 35/70] create local test server --- app_test.go | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/app_test.go b/app_test.go index d951cc7..8c36620 100644 --- a/app_test.go +++ b/app_test.go @@ -55,7 +55,22 @@ func createResponseLocalTestServer(data string) (*httptest.Server, error) { return ts, nil } +func NewLocalHTTPSTestServer(handler http.Handler) (*httptest.Server, error) { + ts := httptest.NewUnstartedServer(handler) + http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true} + + l, err := net.Listen("tcp", "localhost:8088") + if err != nil { + fmt.Println(err) + } + + ts.Listener.Close() ts.Listener = l + ts.StartTLS() + + return ts, nil +} + func newAppInGuestSpace(appId uint64, guestSpaceId uint64) *App { return &App{ Domain: os.Getenv("KINTONE_DOMAIN"), From 6911f69dca8f653deeaa439b6ef481252e86b9b8 Mon Sep 17 00:00:00 2001 From: huong Date: Thu, 2 Jan 2020 16:26:28 +0700 Subject: [PATCH 36/70] create func TestGetRecordComments --- app_test.go | 58 ++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 53 insertions(+), 5 deletions(-) diff --git a/app_test.go b/app_test.go index 8c36620..b78dc7c 100644 --- a/app_test.go +++ b/app_test.go @@ -252,14 +252,62 @@ func TestGuestSpace(t *testing.T) { } func TestGetRecordComments(t *testing.T) { - a := newApp(13) - var offset uint64 = 5 + json := ` + { + "comments": [ + { + "id": "3", + "text": "user14 Thank you! Looks great.", + "createdAt": "2016-05-09T18:29:05Z", + "creator": { + "code": "user13", + "name": "user13" + }, + "mentions": [ + { + "code": "user14", + "type": "USER" + } + ] + }, + { + "id": "2", + "text": "user13 Global Sales APAC Taskforce \nHere is today's report.", + "createdAt": "2016-05-09T18:27:54Z", + "creator": { + "code": "user14", + "name": "user14" + }, + "mentions": [ + { + "code": "user13", + "type": "USER" + }, + { + "code": "Global Sales_1BNZeQ", + "type": "ORGANIZATION" + }, + { + "code": "APAC Taskforce_DJrvzu", + "type": "GROUP" + } + ] + } + ], + "older": false, + "newer": false + } + ` + ts, _ := createResponseLocalTestServer(json) + defer ts.Close() + a := newAppForTest("127.0.0.1:8088", "test", "test", 2) + var offset uint64 = 0 var limit uint64 = 10 - if rec, err := a.GetRecordComments(3, "asc", offset, limit); err != nil { + if rec, err := a.GetRecordComments(1, "asc", offset, limit); err != nil { t.Error(err) } else { - if !strings.Contains(rec[0].Id, "6") { - t.Errorf("the first comment id mismatch. expected is 6 but actual %v", rec[0].Id) + if !strings.Contains(rec[0].Id, "3") { + t.Errorf("the first comment id mismatch. expected is 3 but actual %v", rec[0].Id) } } } From 1f88ec20177cffaf165ffc2a55113387de38dfb5 Mon Sep 17 00:00:00 2001 From: huong Date: Thu, 2 Jan 2020 16:27:00 +0700 Subject: [PATCH 37/70] update test get record --- app_test.go | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/app_test.go b/app_test.go index b78dc7c..184161d 100644 --- a/app_test.go +++ b/app_test.go @@ -82,15 +82,31 @@ func newAppInGuestSpace(appId uint64, guestSpaceId uint64) *App { } func TestGetRecord(t *testing.T) { - a := newApp(4799) - if len(a.Password) == 0 { - t.Skip() - } - if rec, err := a.GetRecord(116); err != nil { + json := `{ + "record": { + "Updated_by": { + "type": "MODIFIER", + "value": { + "code": "Administrator", + "name": "Administrator" + } + }, + "$id": { + "type": "__ID__", + "value": "1" + } + } +} +` + ts, _ := createResponseLocalTestServer(json) + defer ts.Close() + a := newAppForTest("127.0.0.1:8088", "test", "test", 2) + + if rec, err := a.GetRecord(1); err != nil { t.Error(err) } else { - if rec.Id() != 116 { + if rec.Id() != 1 { t.Errorf("Unexpected Id: %d", rec.Id()) } for _, f := range rec.Fields { From 45d93582df4d45145e488011c995dea5d6afa6f8 Mon Sep 17 00:00:00 2001 From: huong Date: Thu, 2 Jan 2020 16:42:22 +0700 Subject: [PATCH 38/70] update newAppForTest --- app_test.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/app_test.go b/app_test.go index 184161d..9a4c0c4 100644 --- a/app_test.go +++ b/app_test.go @@ -18,12 +18,12 @@ import ( "time" ) -func newAppForTest(domain string, user string, password string, appID uint64) *App { +func newAppForTest() *App { return &App{ - Domain: domain, - User: user, - Password: password, - AppId: appID, + Domain: "127.0.0.1:8088", + User: "test", + Password: "test", + AppId: 1, } } From b10ab6b8a197998365b458895606012d781e42e1 Mon Sep 17 00:00:00 2001 From: huong Date: Thu, 2 Jan 2020 16:42:52 +0700 Subject: [PATCH 39/70] change parameter newAppForTest --- app_test.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app_test.go b/app_test.go index 9a4c0c4..6acc2d5 100644 --- a/app_test.go +++ b/app_test.go @@ -101,7 +101,7 @@ func TestGetRecord(t *testing.T) { ` ts, _ := createResponseLocalTestServer(json) defer ts.Close() - a := newAppForTest("127.0.0.1:8088", "test", "test", 2) + a := newAppForTest() if rec, err := a.GetRecord(1); err != nil { t.Error(err) @@ -138,6 +138,7 @@ func TestGetRecord(t *testing.T) { } else { t.Log(len(recs)) } + } func TestAddRecord(t *testing.T) { @@ -316,7 +317,7 @@ func TestGetRecordComments(t *testing.T) { ` ts, _ := createResponseLocalTestServer(json) defer ts.Close() - a := newAppForTest("127.0.0.1:8088", "test", "test", 2) + a := newAppForTest() var offset uint64 = 0 var limit uint64 = 10 if rec, err := a.GetRecordComments(1, "asc", offset, limit); err != nil { From 4d3990e201d70de63bee2713ddf6cfb6ff9d0727 Mon Sep 17 00:00:00 2001 From: huong Date: Fri, 3 Jan 2020 15:29:40 +0700 Subject: [PATCH 40/70] create multiple serve test --- app_test.go | 194 ++++++++++++++++++++++------------------------------ 1 file changed, 83 insertions(+), 111 deletions(-) diff --git a/app_test.go b/app_test.go index 7468413..b1d0c3c 100644 --- a/app_test.go +++ b/app_test.go @@ -5,9 +5,9 @@ package kintone import ( - "bytes" "crypto/tls" "fmt" + "io" "io/ioutil" "net" "net/http" @@ -17,92 +17,106 @@ import ( "time" ) -func newAppForTest() *App { - return &App{ - Domain: "127.0.0.1:8088", - User: "test", - Password: "test", - AppId: 1, - } -} - -func newApp(appID uint64) *App { - return &App{ - Domain: KINTONE_DOMAIN, - User: KINTONE_USER, - Password: KINTONE_PASSWORD, - AppId: appID, - } -} +const ( + KINTONE_DOMAIN = "localhost:8088" + KINTONE_USERNAME = "test" + KINTONE_PASSWORD = "test" + KINTONE_APP_ID = 1 + KINTONE_API_TOKEN = "1e42da75-8432-4adb-9a2b-dbb6e7cb3c6b" + KINTONE_GUEST_SPACE_ID = 0 +) -func newAppWithApiToken(appId uint64) *App { - return &App{ - Domain: KINTONE_DOMAIN, - ApiToken: KINTONE_API_TOKEN, - AppId: appId, - } -} +func createServerTest(mux *http.ServeMux) (*httptest.Server, error) { + ts := httptest.NewUnstartedServer(mux) + listen, err := net.Listen("tcp", KINTONE_DOMAIN) -func createResponseLocalTestServer(data string) (*httptest.Server, error) { - ts, err := NewLocalHTTPSTestServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - fmt.Fprint(w, data) - })) if err != nil { - return nil, err + fmt.Println(err) } + ts.Listener.Close() + ts.Listener = listen + ts.StartTLS() + http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true} return ts, nil } -func NewLocalHTTPSTestServer(handler http.Handler) (*httptest.Server, error) { - ts := httptest.NewUnstartedServer(handler) - http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true} +func createServerMux() (*http.ServeMux, error) { + mux := http.NewServeMux() + mux.HandleFunc("/k/v1/record.json", handleResponseGetRecord) + return mux, nil +} - l, err := net.Listen("tcp", "localhost:8088") +// handler +func handleResponseGetRecord(response http.ResponseWriter, r *http.Request) { + testData := GetTestDataGetRecord() + fmt.Fprint(response, testData.output) +} + +func TestMain(m *testing.M) { + mux, err := createServerMux() if err != nil { - fmt.Println(err) + fmt.Println("StartServerTest", err) } - - ts.Listener.Close() - ts.Listener = l - ts.StartTLS() - - return ts, nil + ts, err := createServerTest(mux) + if err != nil { + fmt.Println("createServerTest", err) + } + m.Run() + ts.Close() } -func newAppInGuestSpace(appId uint64, guestSpaceId uint64) *App { +func newApp() *App { return &App{ Domain: KINTONE_DOMAIN, - User: KINTONE_USER, + User: KINTONE_USERNAME, Password: KINTONE_PASSWORD, - AppId: appId, - GuestSpaceId: guestSpaceId, + AppId: KINTONE_APP_ID, + ApiToken: KINTONE_API_TOKEN, + GuestSpaceId: KINTONE_GUEST_SPACE_ID, } } -func TestGetRecord(t *testing.T) { +func TestAddRecord(t *testing.T) { + testData := GetDataTestAddRecord() + a := newApp() - json := `{ - "record": { - "Updated_by": { - "type": "MODIFIER", - "value": { - "code": "Administrator", - "name": "Administrator" - } + fileKey, err := a.Upload(testData.input[0].(string), "text/html", + testData.input[1].(io.Reader)) + if err != nil { + t.Error("Upload failed", err) + } + + rec := NewRecord(map[string]interface{}{ + "title": SingleLineTextField("test!"), + "file": FileField{ + {FileKey: fileKey}, }, - "$id": { - "type": "__ID__", - "value": "1" - } - } -} -` - ts, _ := createResponseLocalTestServer(json) - defer ts.Close() - a := newAppForTest() + }) + _, err = a.AddRecord(rec) + if err != nil { + t.Error("AddRecord failed", rec) + } - if rec, err := a.GetRecord(1); err != nil { + recs := []*Record{ + NewRecord(map[string]interface{}{ + "title": SingleLineTextField("multi add 1"), + }), + NewRecord(map[string]interface{}{ + "title": SingleLineTextField("multi add 2"), + }), + } + ids, err := a.AddRecords(recs) + if err != nil { + t.Error("AddRecords failed", recs) + } else { + t.Log(ids) + } +} +func TestGetRecord(t *testing.T) { + testData := GetTestDataGetRecord() + a := newApp() + if rec, err := a.GetRecord(uint64(testData.input[0].(int))); err != nil { t.Error(err) } else { if rec.Id() != 1 { @@ -139,57 +153,15 @@ func TestGetRecord(t *testing.T) { } } -func TestAddRecord(t *testing.T) { - a := newApp(9004) - if len(a.Password) == 0 { - t.Skip() - } - - fileKey, err := a.Upload("ほげ春巻.txta", "text/html", - bytes.NewReader([]byte(`abc -hoge -`))) - if err != nil { - t.Error("Upload failed", err) - } - - rec := NewRecord(map[string]interface{}{ - "title": SingleLineTextField("test!"), - "file": FileField{ - {FileKey: fileKey}, - }, - }) - _, err = a.AddRecord(rec) - if err != nil { - t.Error("AddRecord failed", rec) - } - - recs := []*Record{ - NewRecord(map[string]interface{}{ - "title": SingleLineTextField("multi add 1"), - }), - NewRecord(map[string]interface{}{ - "title": SingleLineTextField("multi add 2"), - }), - } - ids, err := a.AddRecords(recs) - if err != nil { - t.Error("AddRecords failed", recs) - } else { - t.Log(ids) - } -} - func TestUpdateRecord(t *testing.T) { - a := newApp(9004) - if len(a.Password) == 0 { - t.Skip() - } + testData := GetTestDataGetRecord() + a := newApp() - rec, err := a.GetRecord(4) + rec, err := a.GetRecord(uint64(testData.input[0].(int))) if err != nil { t.Fatal(err) } + rec.Fields["title"] = SingleLineTextField("new title") if err := a.UpdateRecord(rec, true); err != nil { t.Error("UpdateRecord failed", err) From ab6ec7d75d24ed10e1088ce4bcb630f2f2270a10 Mon Sep 17 00:00:00 2001 From: huong Date: Fri, 3 Jan 2020 17:02:22 +0700 Subject: [PATCH 41/70] add handler --- app_test.go | 5 + app_test_json.go | 256 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 261 insertions(+) create mode 100644 app_test_json.go diff --git a/app_test.go b/app_test.go index b1d0c3c..333dc69 100644 --- a/app_test.go +++ b/app_test.go @@ -44,6 +44,11 @@ func createServerTest(mux *http.ServeMux) (*httptest.Server, error) { func createServerMux() (*http.ServeMux, error) { mux := http.NewServeMux() mux.HandleFunc("/k/v1/record.json", handleResponseGetRecord) + mux.HandleFunc("/k/v1/records.json", handleResponseGetRecords) + mux.HandleFunc("/k/v1/record/comments.json", handleResponseGetRecordsComments) + mux.HandleFunc("/k/v1/file.json", handleResponseUploadFile) + mux.HandleFunc("/k/v1/record/comment.json", handleResponseAddRecordComments) + mux.HandleFunc("/k/v1/records/cursor.json", handleResponseRecordsCursor) return mux, nil } diff --git a/app_test_json.go b/app_test_json.go new file mode 100644 index 0000000..6f22b56 --- /dev/null +++ b/app_test_json.go @@ -0,0 +1,256 @@ +package kintone + +import ( + "bytes" +) + +type TestData struct { + input []interface{} + output string +} + +func GetTestDataDeleteRecords() *TestData { + return &TestData{ + output: `{}`, + } +} +func GetTestDataGetRecord() *TestData { + return &TestData{ + input: []interface{}{1}, + output: `{ + "record": { + "Updated_by": { + "type": "MODIFIER", + "value": { + "code": "Administrator", + "name": "Administrator" + }, + "key": "hehehe" + + + }, + + "$id": { + "type": "__ID__", + "value": "1" + } + } + }`, + } +} + +func GetTestDataGetRecords() *TestData { + return &TestData{ + output: `{ + "records": [ + { + "Created_datetime": { + "type": "CREATED_TIME", + "value": "2019-03-11T04:50:00Z" + }, + "Created_by": { + "type": "CREATOR", + "value": { + "code": "Administrator", + "name": "Administrator" + } + }, + "$id": { + "type": "__ID__", + "value": "1" + } + }, + { + "Created_datetime": { + "type": "CREATED_TIME", + "value": "2019-03-11T06:42:00Z" + }, + "Created_by": { + "type": "CREATOR", + "value": { + "code": "Administrator", + "name": "Administrator" + } + }, + "$id": { + "type": "__ID__", + "value": "2" + } + } + ], + "totalCount": null + }`, + } +} + +func GetDataTestUploadFile() *TestData { + return &TestData{ + output: `{ + "app": 3, + "id": 6, + "record": { + "attached_file": { + "value": [ + { + "fileKey": " c15b3870-7505-4ab6-9d8d-b9bdbc74f5d6" + } + ] + } + } + }`, + } +} + +func GetDataTestRecordComments() *TestData { + return &TestData{ + output: `{ + "comments": [ + { + "id": "3", + "text": "user14 Thank you! Looks great.", + "createdAt": "2016-05-09T18:29:05Z", + "creator": { + "code": "user13", + "name": "user13" + }, + "mentions": [ + { + "code": "user14", + "type": "USER" + } + ] + }, + { + "id": "2", + "text": "user13 Global Sales APAC Taskforce \nHere is today's report.", + "createdAt": "2016-05-09T18:27:54Z", + "creator": { + "code": "user14", + "name": "user14" + }, + "mentions": [ + { + "code": "user13", + "type": "USER" + }, + { + "code": "Global Sales_1BNZeQ", + "type": "ORGANIZATION" + }, + { + "code": "APAC Taskforce_DJrvzu", + "type": "GROUP" + } + ] + } + ], + "older": false, + "newer": false + }`, + } +} + +func GetDataTestAddRecord() *TestData { + return &TestData{ + input: []interface{}{ + "ほげ春巻.txta", + bytes.NewReader([]byte(`abc + hoge + `)), + }, + output: `{ + "id": "1", + "revision": "1" + }`, + } +} +func getDataTestCreateCursor() *TestData { + return &TestData{ + output: `{ + "id": "9a9716fe-1394-4677-a1c7-2199a5d28215", + "totalCount": 123456 + }`, + } + +} +func GetDataTestGetRecordsByCursor() *TestData { + + return &TestData{ + input: []interface{}{"9a9716fe-1394-4677-a1c7-2199a5d28215"}, + output: `{ + "records": [ + { + "$id": { + "type": "__ID__", + "value": "1" + }, + "Created_by": { + "type": "CREATOR", + "value": { + "code": "Administrator", + "name": "Administrator" + } + }, + "Created_datetime": { + "type": "CREATED_TIME", + "value": "2019-05-23T04:50:00Z" + } + } + ], + "next": false + }`, + } +} + +func GetTestDataDeleteCursor() *TestData { + return &TestData{ + input: []interface{}{"9a9716fe-1394-4677-a1c7-2199a5d28215"}, + output: `{}`, + } +} + +func GetTestDataCreateCursor() *TestData { + return &TestData{ + input: []interface{}{[]string{"$id", "date"}, "", 100}, + output: `{"id":"9a9716fe-1394-4677-a1c7-2199a5d28215"}`, + } +} + +func GetTestDataAddRecordComment() *TestData { + return &TestData{ + input: []interface{}{2}, + output: `{"id": "4"}`, + } +} +func GetTestDataUpdateRecordByKey() *TestData { + return &TestData{ + input: []interface{}{2}, + output: `{ + "app": 1, + "records": [ + { + "updateKey": { + "field": "unique_key", + "value": "CODE123" + }, + "record": { + "Text": { + "value": "Silver plates" + } + } + }, + { + "updateKey": { + "field": "unique_key", + "value": "CODE456" + }, + "record": { + "Text": { + "value": "The quick brown fox." + } + } + } + ] + }`, + } +} From 061b97c0bf8eab1f2d5f2f3faf10ef43a3e8fcc1 Mon Sep 17 00:00:00 2001 From: huong Date: Fri, 3 Jan 2020 17:05:30 +0700 Subject: [PATCH 42/70] create handleResponseRecordsCursor, handleResponseAddRecordComments, handleResponseUploadFile, handleResponseGetRecord, handleResponseGetRecords, handleResponseGetRecordsComments --- app_test.go | 67 +++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 62 insertions(+), 5 deletions(-) diff --git a/app_test.go b/app_test.go index 333dc69..65e5509 100644 --- a/app_test.go +++ b/app_test.go @@ -31,7 +31,7 @@ func createServerTest(mux *http.ServeMux) (*httptest.Server, error) { listen, err := net.Listen("tcp", KINTONE_DOMAIN) if err != nil { - fmt.Println(err) + return nil, err } ts.Listener.Close() @@ -52,10 +52,59 @@ func createServerMux() (*http.ServeMux, error) { return mux, nil } -// handler +// handler mux +func handleResponseRecordsCursor(response http.ResponseWriter, r *http.Request) { + if r.Method == "GET" { + testData := GetDataTestGetRecordsByCursor() + fmt.Fprint(response, testData.output) + } else if r.Method == "DELETE" { + testData := GetTestDataDeleteCursor() + fmt.Fprint(response, testData.output) + } else if r.Method == "POST" { + testData := GetTestDataCreateCursor() + fmt.Fprint(response, testData.output) + } +} +func handleResponseAddRecordComments(response http.ResponseWriter, r *http.Request) { + if r.Method == "POST" { + testData := GetTestDataAddRecordComment() + fmt.Fprint(response, testData.output) + } +} + +func handleResponseUploadFile(response http.ResponseWriter, r *http.Request) { + if r.Method == "POST" { + testData := GetDataTestUploadFile() + fmt.Fprint(response, testData.output) + } +} + func handleResponseGetRecord(response http.ResponseWriter, r *http.Request) { - testData := GetTestDataGetRecord() + if r.Method == "GET" { + testData := GetTestDataGetRecord() + fmt.Fprint(response, testData.output) + } else if r.Method == "PUT" { + testData := GetTestDataUpdateRecordByKey() + fmt.Fprint(response, testData.output) + } + +} + +func handleResponseGetRecords(response http.ResponseWriter, r *http.Request) { + if r.Method == "GET" { + testData := GetTestDataGetRecords() + fmt.Fprint(response, testData.output) + } else if r.Method == "DELETE" { + testData := GetTestDataDeleteRecords() + fmt.Fprint(response, testData.output) + } + +} + +func handleResponseGetRecordsComments(response http.ResponseWriter, r *http.Request) { + testData := GetDataTestRecordComments() fmt.Fprint(response, testData.output) + } func TestMain(m *testing.M) { @@ -166,22 +215,30 @@ func TestUpdateRecord(t *testing.T) { if err != nil { t.Fatal(err) } - rec.Fields["title"] = SingleLineTextField("new title") if err := a.UpdateRecord(rec, true); err != nil { t.Error("UpdateRecord failed", err) } + rec.Fields["key"] = SingleLineTextField(` { + "field": "unique_key", + "value": "unique_code" + }`) if err := a.UpdateRecordByKey(rec, true, "key"); err != nil { + t.Error("UpdateRecordByKey failed", err) } - recs, err := a.GetRecords(nil, "limit 3") if err != nil { t.Fatal(err) } + for _, rec := range recs { rec.Fields["title"] = SingleLineTextField(time.Now().String()) + rec.Fields["key"] = SingleLineTextField(` { + "field": "unique_key", + "value": "unique_code" + }`) } if err := a.UpdateRecords(recs, true); err != nil { t.Error("UpdateRecords failed", err) From f417e5a8ad68fe5eb25d897b9be2182c16f963b1 Mon Sep 17 00:00:00 2001 From: huong Date: Fri, 3 Jan 2020 17:47:42 +0700 Subject: [PATCH 43/70] defined app test --- app_test.go | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/app_test.go b/app_test.go index 65e5509..123ac35 100644 --- a/app_test.go +++ b/app_test.go @@ -23,7 +23,7 @@ const ( KINTONE_PASSWORD = "test" KINTONE_APP_ID = 1 KINTONE_API_TOKEN = "1e42da75-8432-4adb-9a2b-dbb6e7cb3c6b" - KINTONE_GUEST_SPACE_ID = 0 + KINTONE_GUEST_SPACE_ID = 1 ) func createServerTest(mux *http.ServeMux) (*httptest.Server, error) { @@ -121,15 +121,28 @@ func TestMain(m *testing.M) { } func newApp() *App { + return &App{ + Domain: KINTONE_DOMAIN, + User: KINTONE_USERNAME, + Password: KINTONE_PASSWORD, + AppId: KINTONE_APP_ID, + ApiToken: KINTONE_API_TOKEN, + } +} +func newAppWithGuest() *App { return &App{ Domain: KINTONE_DOMAIN, - User: KINTONE_USERNAME, - Password: KINTONE_PASSWORD, AppId: KINTONE_APP_ID, ApiToken: KINTONE_API_TOKEN, GuestSpaceId: KINTONE_GUEST_SPACE_ID, } } +func newAppWithToken() *App { + return &App{ + Domain: KINTONE_DOMAIN, + ApiToken: KINTONE_API_TOKEN, + } +} func TestAddRecord(t *testing.T) { testData := GetDataTestAddRecord() From bb120f1de87f218b27cc2671b5c178fc64ee29f0 Mon Sep 17 00:00:00 2001 From: huong Date: Fri, 3 Jan 2020 17:48:23 +0700 Subject: [PATCH 44/70] defined handler test form , add record comment --- app_test.go | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/app_test.go b/app_test.go index 123ac35..8e0e7db 100644 --- a/app_test.go +++ b/app_test.go @@ -47,12 +47,21 @@ func createServerMux() (*http.ServeMux, error) { mux.HandleFunc("/k/v1/records.json", handleResponseGetRecords) mux.HandleFunc("/k/v1/record/comments.json", handleResponseGetRecordsComments) mux.HandleFunc("/k/v1/file.json", handleResponseUploadFile) - mux.HandleFunc("/k/v1/record/comment.json", handleResponseAddRecordComments) + mux.HandleFunc("/k/v1/record/comment.json", handleResponseRecordComments) mux.HandleFunc("/k/v1/records/cursor.json", handleResponseRecordsCursor) + mux.HandleFunc("/k/v1/form.json", handleResponseForm) + mux.HandleFunc("/k/guest/1/v1/form.json", handleResponseForm) return mux, nil } // handler mux +func handleResponseForm(response http.ResponseWriter, r *http.Request) { + if r.Method == "GET" { + testData := GetDataTestForm() + fmt.Fprint(response, testData.output) + } +} + func handleResponseRecordsCursor(response http.ResponseWriter, r *http.Request) { if r.Method == "GET" { testData := GetDataTestGetRecordsByCursor() @@ -65,10 +74,13 @@ func handleResponseRecordsCursor(response http.ResponseWriter, r *http.Request) fmt.Fprint(response, testData.output) } } -func handleResponseAddRecordComments(response http.ResponseWriter, r *http.Request) { +func handleResponseRecordComments(response http.ResponseWriter, r *http.Request) { if r.Method == "POST" { testData := GetTestDataAddRecordComment() fmt.Fprint(response, testData.output) + } else if r.Method == "DELETE" { + testData := GetDataTestDeleteRecordComment() + fmt.Fprint(response, testData.output) } } From 40aa7c0643fff6db74c8f80369263e9112ccf855 Mon Sep 17 00:00:00 2001 From: huong Date: Fri, 3 Jan 2020 17:49:29 +0700 Subject: [PATCH 45/70] implement function test TestAddRecordComment, TestGetRecordComments, TestGuestSpace, TestApiToken, TestFields, TestCreateCursor, TestDeleteCursor, TestGetRecordsByCursor --- app_test.go | 128 ++++++++++------------------------------------------ 1 file changed, 25 insertions(+), 103 deletions(-) diff --git a/app_test.go b/app_test.go index 8e0e7db..ab2a21f 100644 --- a/app_test.go +++ b/app_test.go @@ -98,6 +98,9 @@ func handleResponseGetRecord(response http.ResponseWriter, r *http.Request) { } else if r.Method == "PUT" { testData := GetTestDataUpdateRecordByKey() fmt.Fprint(response, testData.output) + } else if r.Method == "POST" { + testData := GetTestDataAddRecord() + fmt.Fprint(response, testData.output) } } @@ -109,6 +112,9 @@ func handleResponseGetRecords(response http.ResponseWriter, r *http.Request) { } else if r.Method == "DELETE" { testData := GetTestDataDeleteRecords() fmt.Fprint(response, testData.output) + } else if r.Method == "POST" { + testData := GetTestDataAddRecords() + fmt.Fprint(response, testData.output) } } @@ -176,7 +182,6 @@ func TestAddRecord(t *testing.T) { if err != nil { t.Error("AddRecord failed", rec) } - recs := []*Record{ NewRecord(map[string]interface{}{ "title": SingleLineTextField("multi add 1"), @@ -275,10 +280,7 @@ func TestUpdateRecord(t *testing.T) { } func TestDeleteRecord(t *testing.T) { - a := newApp(9004) - if len(a.Password) == 0 { - t.Skip() - } + a := newApp() ids := []uint64{6, 7} if err := a.DeleteRecords(ids); err != nil { @@ -287,62 +289,35 @@ func TestDeleteRecord(t *testing.T) { } func TestGetRecordsByCursor(t *testing.T) { - app := newApp(18) - - if len(app.Password) == 0 { - t.Skip() - } - - cursor := app.createCursorForTest() - record, err := app.GetRecordsByCursor(string(cursor.Id)) - + testData := GetDataTestGetRecordsByCursor() + app := newApp() + _, err := app.GetRecordsByCursor(testData.input[0].(string)) if err != nil { t.Errorf("TestGetCursor is failed: %v", err) } - fmt.Println(record) - -} -func (app *App) createCursorForTest() *Cursor { - cursor, err := app.CreateCursor([]string{"$id", "Status"}, "", 400) - fmt.Println("cursor", cursor) - if err != nil { - fmt.Println("createCursorForTest failed: ", err) - } - return cursor } func TestDeleteCursor(t *testing.T) { - app := newApp(18) - if len(app.Password) == 0 { - t.Skip() - } - - cursor := app.createCursorForTest() - fmt.Println("cursor", cursor) - err := app.DeleteCursor(string(cursor.Id)) - + testData := GetTestDataDeleteCursor() + app := newApp() + err := app.DeleteCursor(testData.input[0].(string)) if err != nil { t.Errorf("TestDeleteCursor is failed: %v", err) } } func TestCreateCursor(t *testing.T) { - app := newApp(18) - if len(app.Password) == 0 { - t.Skip() - } - _, err := app.CreateCursor([]string{"$id", "date"}, "", 100) + testData := GetTestDataCreateCursor() + app := newApp() + _, err := app.CreateCursor(testData.input[0].([]string), testData.input[1].(string), uint64(testData.input[2].(int))) if err != nil { t.Errorf("TestCreateCurSor is failed: %v", err) } } func TestFields(t *testing.T) { - a := newApp(8326) - if len(a.Password) == 0 { - t.Skip() - } + a := newApp() fi, err := a.Fields() if err != nil { @@ -354,11 +329,7 @@ func TestFields(t *testing.T) { } func TestApiToken(t *testing.T) { - a := newAppWithApiToken(9974) - if len(a.ApiToken) == 0 { - t.Skip() - } - + a := newAppWithToken() _, err := a.Fields() if err != nil { t.Error("Api token failed", err) @@ -366,10 +337,7 @@ func TestApiToken(t *testing.T) { } func TestGuestSpace(t *testing.T) { - a := newAppInGuestSpace(185, 9) - if len(a.Password) == 0 { - t.Skip() - } + a := newAppWithGuest() _, err := a.Fields() if err != nil { @@ -378,55 +346,7 @@ func TestGuestSpace(t *testing.T) { } func TestGetRecordComments(t *testing.T) { - json := ` - { - "comments": [ - { - "id": "3", - "text": "user14 Thank you! Looks great.", - "createdAt": "2016-05-09T18:29:05Z", - "creator": { - "code": "user13", - "name": "user13" - }, - "mentions": [ - { - "code": "user14", - "type": "USER" - } - ] - }, - { - "id": "2", - "text": "user13 Global Sales APAC Taskforce \nHere is today's report.", - "createdAt": "2016-05-09T18:27:54Z", - "creator": { - "code": "user14", - "name": "user14" - }, - "mentions": [ - { - "code": "user13", - "type": "USER" - }, - { - "code": "Global Sales_1BNZeQ", - "type": "ORGANIZATION" - }, - { - "code": "APAC Taskforce_DJrvzu", - "type": "GROUP" - } - ] - } - ], - "older": false, - "newer": false - } - ` - ts, _ := createResponseLocalTestServer(json) - defer ts.Close() - a := newAppForTest() + a := newApp() var offset uint64 = 0 var limit uint64 = 10 if rec, err := a.GetRecordComments(1, "asc", offset, limit); err != nil { @@ -437,15 +357,17 @@ func TestGetRecordComments(t *testing.T) { } } } + func TestAddRecordComment(t *testing.T) { - appTest := newApp(12) + testData := GetTestDataAddRecordComment() + appTest := newApp() mentionMemberCybozu := &ObjMention{Code: "cybozu", Type: ConstCommentMentionTypeUser} mentionGroupAdmin := &ObjMention{Code: "Administrators", Type: ConstCommentMentionTypeGroup} mentionDepartmentAdmin := &ObjMention{Code: "Admin", Type: ConstCommentMentionTypeDepartment} var cmt Comment cmt.Text = "Test comment 222" cmt.Mentions = []*ObjMention{mentionGroupAdmin, mentionMemberCybozu, mentionDepartmentAdmin} - cmtID, err := appTest.AddRecordComment(2, &cmt) + cmtID, err := appTest.AddRecordComment(uint64(testData.input[0].(int)), &cmt) if err != nil { t.Error(err) @@ -455,7 +377,7 @@ func TestAddRecordComment(t *testing.T) { } func TestDeleteComment(t *testing.T) { - appTest := newApp(4) + appTest := newApp() var cmtID uint64 = 14 err := appTest.DeleteComment(3, 12) From 0f7e370ef18970e957843a72513dc42484b1a72b Mon Sep 17 00:00:00 2001 From: huong Date: Fri, 3 Jan 2020 17:49:56 +0700 Subject: [PATCH 46/70] add data test json --- app_test_json.go | 75 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/app_test_json.go b/app_test_json.go index 6f22b56..78bbd20 100644 --- a/app_test_json.go +++ b/app_test_json.go @@ -150,6 +150,81 @@ func GetDataTestRecordComments() *TestData { } } +func GetDataTestForm() *TestData { + return &TestData{ + output: `{ + "properties": [ + { + "code": "string_1", + "defaultValue": "", + "expression": "", + "hideExpression": "false", + "maxLength": "64", + "minLength": null, + "label": "string_1", + "noLabel": "false", + "required": "true", + "type": "SINGLE_LINE_TEXT", + "unique": "true" + }, + { + "code": "number_1", + "defaultValue": "12345", + "digit": "true", + "displayScale": "4", + "expression": "", + "maxValue": null, + "minValue": null, + "label": "number_1", + "noLabel": "true", + "required": "false", + "type": "NUMBER", + "unique": "false" + }, + { + "code": "checkbox_1", + "defaultValue": [ + "sample1", + "sample3" + ], + "label": "checkbox_1", + "noLabel": "false", + "options": [ + "sample1", + "sample2", + "sample3" + ], + "required": "false", + "type": "CHECK_BOX" + } + ] + }`, + } +} + +func GetDataTestDeleteRecordComment() *TestData { + return &TestData{ + output: `{}`, + } +} +func GetTestDataAddRecord() *TestData { + return &TestData{ + output: `{ + "id": "1", + "revision": "1" + }`, + } +} + +func GetTestDataAddRecords() *TestData { + return &TestData{ + output: `{ + "ids": ["77","78"], + "revisions": ["1","1"] + }`, + } +} + func GetDataTestAddRecord() *TestData { return &TestData{ input: []interface{}{ From ef36d729919f630e972f7e4aeb24b8bcf36f9ccd Mon Sep 17 00:00:00 2001 From: huong Date: Mon, 6 Jan 2020 11:10:34 +0700 Subject: [PATCH 47/70] add check header --- app_test.go | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/app_test.go b/app_test.go index ab2a21f..5d4ac53 100644 --- a/app_test.go +++ b/app_test.go @@ -12,6 +12,7 @@ import ( "net" "net/http" "net/http/httptest" + "os" "strings" "testing" "time" @@ -24,6 +25,8 @@ const ( KINTONE_APP_ID = 1 KINTONE_API_TOKEN = "1e42da75-8432-4adb-9a2b-dbb6e7cb3c6b" KINTONE_GUEST_SPACE_ID = 1 + AUTH_HEADER_TOKEN = "X-Cybozu-API-Token" + AUTH_HEADER_PASSWORD = "X-Cybozu-Authorization" ) func createServerTest(mux *http.ServeMux) (*httptest.Server, error) { @@ -54,8 +57,23 @@ func createServerMux() (*http.ServeMux, error) { return mux, nil } +// header check +func checkHeader(response http.ResponseWriter, r *http.Request) { + contentType := r.Header.Get("Content-Type") + authPassword := r.Header.Get(AUTH_HEADER_PASSWORD) + authToken := r.Header.Get(AUTH_HEADER_TOKEN) + if contentType != "application/json" { + fmt.Println("Content-type is invalid") + os.Exit(1) + } else if authPassword == "" && authToken == "" { + fmt.Println("Authenticated is fail") + os.Exit(1) + } +} + // handler mux func handleResponseForm(response http.ResponseWriter, r *http.Request) { + checkHeader(response, r) if r.Method == "GET" { testData := GetDataTestForm() fmt.Fprint(response, testData.output) @@ -67,14 +85,17 @@ func handleResponseRecordsCursor(response http.ResponseWriter, r *http.Request) testData := GetDataTestGetRecordsByCursor() fmt.Fprint(response, testData.output) } else if r.Method == "DELETE" { + checkHeader(response, r) testData := GetTestDataDeleteCursor() fmt.Fprint(response, testData.output) } else if r.Method == "POST" { + checkHeader(response, r) testData := GetTestDataCreateCursor() fmt.Fprint(response, testData.output) } } func handleResponseRecordComments(response http.ResponseWriter, r *http.Request) { + checkHeader(response, r) if r.Method == "POST" { testData := GetTestDataAddRecordComment() fmt.Fprint(response, testData.output) @@ -85,6 +106,7 @@ func handleResponseRecordComments(response http.ResponseWriter, r *http.Request) } func handleResponseUploadFile(response http.ResponseWriter, r *http.Request) { + // checkHeader(response, r) if r.Method == "POST" { testData := GetDataTestUploadFile() fmt.Fprint(response, testData.output) @@ -92,6 +114,7 @@ func handleResponseUploadFile(response http.ResponseWriter, r *http.Request) { } func handleResponseGetRecord(response http.ResponseWriter, r *http.Request) { + checkHeader(response, r) if r.Method == "GET" { testData := GetTestDataGetRecord() fmt.Fprint(response, testData.output) @@ -106,6 +129,7 @@ func handleResponseGetRecord(response http.ResponseWriter, r *http.Request) { } func handleResponseGetRecords(response http.ResponseWriter, r *http.Request) { + checkHeader(response, r) if r.Method == "GET" { testData := GetTestDataGetRecords() fmt.Fprint(response, testData.output) @@ -120,6 +144,7 @@ func handleResponseGetRecords(response http.ResponseWriter, r *http.Request) { } func handleResponseGetRecordsComments(response http.ResponseWriter, r *http.Request) { + checkHeader(response, r) testData := GetDataTestRecordComments() fmt.Fprint(response, testData.output) From fc42a6a734000052c578feca3188b8455782b320 Mon Sep 17 00:00:00 2001 From: huong Date: Mon, 6 Jan 2020 11:37:17 +0700 Subject: [PATCH 48/70] spli function check content type and check auth --- app_test.go | 46 +++++++++++++++++++++++++++++++--------------- 1 file changed, 31 insertions(+), 15 deletions(-) diff --git a/app_test.go b/app_test.go index 5d4ac53..b06b197 100644 --- a/app_test.go +++ b/app_test.go @@ -12,7 +12,6 @@ import ( "net" "net/http" "net/http/httptest" - "os" "strings" "testing" "time" @@ -58,55 +57,65 @@ func createServerMux() (*http.ServeMux, error) { } // header check -func checkHeader(response http.ResponseWriter, r *http.Request) { - contentType := r.Header.Get("Content-Type") +func checkAuth(response http.ResponseWriter, r *http.Request) { authPassword := r.Header.Get(AUTH_HEADER_PASSWORD) authToken := r.Header.Get(AUTH_HEADER_TOKEN) + if authPassword == "" && authToken == "" { + http.Error(response, "Authenticated is fail!", http.StatusForbidden) + + response.WriteHeader(http.StatusInternalServerError) + response.Write([]byte("500 - Authenticated is fail!")) + } +} +func checkContentType(response http.ResponseWriter, r *http.Request) { + contentType := r.Header.Get("Content-Type") if contentType != "application/json" { fmt.Println("Content-type is invalid") - os.Exit(1) - } else if authPassword == "" && authToken == "" { - fmt.Println("Authenticated is fail") - os.Exit(1) + http.Error(response, http.StatusText(http.StatusNotFound), http.StatusNotFound) + } } // handler mux func handleResponseForm(response http.ResponseWriter, r *http.Request) { - checkHeader(response, r) + checkAuth(response, r) if r.Method == "GET" { + checkContentType(response, r) testData := GetDataTestForm() fmt.Fprint(response, testData.output) } } func handleResponseRecordsCursor(response http.ResponseWriter, r *http.Request) { + checkAuth(response, r) if r.Method == "GET" { testData := GetDataTestGetRecordsByCursor() fmt.Fprint(response, testData.output) } else if r.Method == "DELETE" { - checkHeader(response, r) + checkContentType(response, r) testData := GetTestDataDeleteCursor() fmt.Fprint(response, testData.output) } else if r.Method == "POST" { - checkHeader(response, r) + checkContentType(response, r) testData := GetTestDataCreateCursor() fmt.Fprint(response, testData.output) } } func handleResponseRecordComments(response http.ResponseWriter, r *http.Request) { - checkHeader(response, r) + checkAuth(response, r) if r.Method == "POST" { + checkContentType(response, r) testData := GetTestDataAddRecordComment() fmt.Fprint(response, testData.output) } else if r.Method == "DELETE" { + checkContentType(response, r) testData := GetDataTestDeleteRecordComment() fmt.Fprint(response, testData.output) } } func handleResponseUploadFile(response http.ResponseWriter, r *http.Request) { - // checkHeader(response, r) + checkAuth(response, r) if r.Method == "POST" { testData := GetDataTestUploadFile() fmt.Fprint(response, testData.output) @@ -114,14 +123,17 @@ func handleResponseUploadFile(response http.ResponseWriter, r *http.Request) { } func handleResponseGetRecord(response http.ResponseWriter, r *http.Request) { - checkHeader(response, r) + checkAuth(response, r) if r.Method == "GET" { + checkContentType(response, r) testData := GetTestDataGetRecord() fmt.Fprint(response, testData.output) } else if r.Method == "PUT" { + checkContentType(response, r) testData := GetTestDataUpdateRecordByKey() fmt.Fprint(response, testData.output) } else if r.Method == "POST" { + checkContentType(response, r) testData := GetTestDataAddRecord() fmt.Fprint(response, testData.output) } @@ -129,14 +141,17 @@ func handleResponseGetRecord(response http.ResponseWriter, r *http.Request) { } func handleResponseGetRecords(response http.ResponseWriter, r *http.Request) { - checkHeader(response, r) + checkAuth(response, r) if r.Method == "GET" { + checkContentType(response, r) testData := GetTestDataGetRecords() fmt.Fprint(response, testData.output) } else if r.Method == "DELETE" { + checkContentType(response, r) testData := GetTestDataDeleteRecords() fmt.Fprint(response, testData.output) } else if r.Method == "POST" { + checkContentType(response, r) testData := GetTestDataAddRecords() fmt.Fprint(response, testData.output) } @@ -144,7 +159,8 @@ func handleResponseGetRecords(response http.ResponseWriter, r *http.Request) { } func handleResponseGetRecordsComments(response http.ResponseWriter, r *http.Request) { - checkHeader(response, r) + checkAuth(response, r) + checkContentType(response, r) testData := GetDataTestRecordComments() fmt.Fprint(response, testData.output) From 63b5f34340cf5fd622c1fdbe6eb4edd6b045ab7d Mon Sep 17 00:00:00 2001 From: huong Date: Mon, 6 Jan 2020 11:39:00 +0700 Subject: [PATCH 49/70] change throw error check response --- app_test.go | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/app_test.go b/app_test.go index b06b197..7be7e3d 100644 --- a/app_test.go +++ b/app_test.go @@ -24,7 +24,7 @@ const ( KINTONE_APP_ID = 1 KINTONE_API_TOKEN = "1e42da75-8432-4adb-9a2b-dbb6e7cb3c6b" KINTONE_GUEST_SPACE_ID = 1 - AUTH_HEADER_TOKEN = "X-Cybozu-API-Token" + AUTH_HEADER_TOKEN = "X-Cybozu1-API-Token" AUTH_HEADER_PASSWORD = "X-Cybozu-Authorization" ) @@ -61,16 +61,12 @@ func checkAuth(response http.ResponseWriter, r *http.Request) { authPassword := r.Header.Get(AUTH_HEADER_PASSWORD) authToken := r.Header.Get(AUTH_HEADER_TOKEN) if authPassword == "" && authToken == "" { - http.Error(response, "Authenticated is fail!", http.StatusForbidden) - - response.WriteHeader(http.StatusInternalServerError) - response.Write([]byte("500 - Authenticated is fail!")) + http.Error(response, http.StatusText(http.StatusNotFound), http.StatusNotFound) } } func checkContentType(response http.ResponseWriter, r *http.Request) { contentType := r.Header.Get("Content-Type") if contentType != "application/json" { - fmt.Println("Content-type is invalid") http.Error(response, http.StatusText(http.StatusNotFound), http.StatusNotFound) } From 84eef96937f9889f8052807ed9d1867fd1ebd23f Mon Sep 17 00:00:00 2001 From: huong Date: Mon, 6 Jan 2020 11:49:52 +0700 Subject: [PATCH 50/70] const token-valid --- app_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app_test.go b/app_test.go index 7be7e3d..40e0311 100644 --- a/app_test.go +++ b/app_test.go @@ -24,7 +24,7 @@ const ( KINTONE_APP_ID = 1 KINTONE_API_TOKEN = "1e42da75-8432-4adb-9a2b-dbb6e7cb3c6b" KINTONE_GUEST_SPACE_ID = 1 - AUTH_HEADER_TOKEN = "X-Cybozu1-API-Token" + AUTH_HEADER_TOKEN = "X-Cybozu-API-Token" AUTH_HEADER_PASSWORD = "X-Cybozu-Authorization" ) From 2c82ec765241b94b5d9cb4b4ce3a5fa071ba349f Mon Sep 17 00:00:00 2001 From: huong Date: Mon, 6 Jan 2020 13:49:22 +0700 Subject: [PATCH 51/70] fix review #4 --- app_test.go | 102 +++++++++++++++++++++++++++------------------------- 1 file changed, 53 insertions(+), 49 deletions(-) diff --git a/app_test.go b/app_test.go index 40e0311..8494c9a 100644 --- a/app_test.go +++ b/app_test.go @@ -6,6 +6,7 @@ package kintone import ( "crypto/tls" + "encoding/base64" "fmt" "io" "io/ioutil" @@ -57,15 +58,18 @@ func createServerMux() (*http.ServeMux, error) { } // header check -func checkAuth(response http.ResponseWriter, r *http.Request) { - authPassword := r.Header.Get(AUTH_HEADER_PASSWORD) - authToken := r.Header.Get(AUTH_HEADER_TOKEN) - if authPassword == "" && authToken == "" { +func checkAuth(response http.ResponseWriter, request *http.Request) { + authPassword := request.Header.Get(AUTH_HEADER_PASSWORD) + authToken := request.Header.Get(AUTH_HEADER_TOKEN) + userAndPass := base64.StdEncoding.EncodeToString( + []byte(KINTONE_USERNAME + ":" + KINTONE_USERNAME)) + if authPassword != userAndPass && authToken != KINTONE_API_TOKEN { http.Error(response, http.StatusText(http.StatusNotFound), http.StatusNotFound) } + } -func checkContentType(response http.ResponseWriter, r *http.Request) { - contentType := r.Header.Get("Content-Type") +func checkContentType(response http.ResponseWriter, request *http.Request) { + contentType := request.Header.Get("Content-Type") if contentType != "application/json" { http.Error(response, http.StatusText(http.StatusNotFound), http.StatusNotFound) @@ -73,90 +77,90 @@ func checkContentType(response http.ResponseWriter, r *http.Request) { } // handler mux -func handleResponseForm(response http.ResponseWriter, r *http.Request) { - checkAuth(response, r) - if r.Method == "GET" { - checkContentType(response, r) +func handleResponseForm(response http.ResponseWriter, request *http.Request) { + checkAuth(response, request) + if request.Method == "GET" { + checkContentType(response, request) testData := GetDataTestForm() fmt.Fprint(response, testData.output) } } -func handleResponseRecordsCursor(response http.ResponseWriter, r *http.Request) { - checkAuth(response, r) - if r.Method == "GET" { +func handleResponseRecordsCursor(response http.ResponseWriter, request *http.Request) { + checkAuth(response, request) + if request.Method == "GET" { testData := GetDataTestGetRecordsByCursor() fmt.Fprint(response, testData.output) - } else if r.Method == "DELETE" { - checkContentType(response, r) + } else if request.Method == "DELETE" { + checkContentType(response, request) testData := GetTestDataDeleteCursor() fmt.Fprint(response, testData.output) - } else if r.Method == "POST" { - checkContentType(response, r) + } else if request.Method == "POST" { + checkContentType(response, request) testData := GetTestDataCreateCursor() fmt.Fprint(response, testData.output) } } -func handleResponseRecordComments(response http.ResponseWriter, r *http.Request) { - checkAuth(response, r) - if r.Method == "POST" { - checkContentType(response, r) +func handleResponseRecordComments(response http.ResponseWriter, request *http.Request) { + checkAuth(response, request) + if request.Method == "POST" { + checkContentType(response, request) testData := GetTestDataAddRecordComment() fmt.Fprint(response, testData.output) - } else if r.Method == "DELETE" { - checkContentType(response, r) + } else if request.Method == "DELETE" { + checkContentType(response, request) testData := GetDataTestDeleteRecordComment() fmt.Fprint(response, testData.output) } } -func handleResponseUploadFile(response http.ResponseWriter, r *http.Request) { - checkAuth(response, r) - if r.Method == "POST" { +func handleResponseUploadFile(response http.ResponseWriter, request *http.Request) { + checkAuth(response, request) + if request.Method == "POST" { testData := GetDataTestUploadFile() fmt.Fprint(response, testData.output) } } -func handleResponseGetRecord(response http.ResponseWriter, r *http.Request) { - checkAuth(response, r) - if r.Method == "GET" { - checkContentType(response, r) +func handleResponseGetRecord(response http.ResponseWriter, request *http.Request) { + checkAuth(response, request) + if request.Method == "GET" { + checkContentType(response, request) testData := GetTestDataGetRecord() fmt.Fprint(response, testData.output) - } else if r.Method == "PUT" { - checkContentType(response, r) + } else if request.Method == "PUT" { + checkContentType(response, request) testData := GetTestDataUpdateRecordByKey() fmt.Fprint(response, testData.output) - } else if r.Method == "POST" { - checkContentType(response, r) + } else if request.Method == "POST" { + checkContentType(response, request) testData := GetTestDataAddRecord() fmt.Fprint(response, testData.output) } } -func handleResponseGetRecords(response http.ResponseWriter, r *http.Request) { - checkAuth(response, r) - if r.Method == "GET" { - checkContentType(response, r) +func handleResponseGetRecords(response http.ResponseWriter, request *http.Request) { + checkAuth(response, request) + if request.Method == "GET" { + checkContentType(response, request) testData := GetTestDataGetRecords() fmt.Fprint(response, testData.output) - } else if r.Method == "DELETE" { - checkContentType(response, r) + } else if request.Method == "DELETE" { + checkContentType(response, request) testData := GetTestDataDeleteRecords() fmt.Fprint(response, testData.output) - } else if r.Method == "POST" { - checkContentType(response, r) + } else if request.Method == "POST" { + checkContentType(response, request) testData := GetTestDataAddRecords() fmt.Fprint(response, testData.output) } } -func handleResponseGetRecordsComments(response http.ResponseWriter, r *http.Request) { - checkAuth(response, r) - checkContentType(response, r) +func handleResponseGetRecordsComments(response http.ResponseWriter, request *http.Request) { + checkAuth(response, request) + checkContentType(response, request) testData := GetDataTestRecordComments() fmt.Fprint(response, testData.output) @@ -201,9 +205,9 @@ func newAppWithToken() *App { func TestAddRecord(t *testing.T) { testData := GetDataTestAddRecord() - a := newApp() + app := newApp() - fileKey, err := a.Upload(testData.input[0].(string), "text/html", + fileKey, err := app.Upload(testData.input[0].(string), testData.input[2].(string), testData.input[1].(io.Reader)) if err != nil { t.Error("Upload failed", err) @@ -215,7 +219,7 @@ func TestAddRecord(t *testing.T) { {FileKey: fileKey}, }, }) - _, err = a.AddRecord(rec) + _, err = app.AddRecord(rec) if err != nil { t.Error("AddRecord failed", rec) } @@ -227,7 +231,7 @@ func TestAddRecord(t *testing.T) { "title": SingleLineTextField("multi add 2"), }), } - ids, err := a.AddRecords(recs) + ids, err := app.AddRecords(recs) if err != nil { t.Error("AddRecords failed", recs) } else { From 7e2ec0d8074fde5dc2639e752bac4da35b16972a Mon Sep 17 00:00:00 2001 From: huong Date: Mon, 6 Jan 2020 13:51:06 +0700 Subject: [PATCH 52/70] CHANGE SPACE JSON --- app_test_json.go | 187 ++++++++++++++++++++++++----------------------- 1 file changed, 94 insertions(+), 93 deletions(-) diff --git a/app_test_json.go b/app_test_json.go index 78bbd20..2456e47 100644 --- a/app_test_json.go +++ b/app_test_json.go @@ -18,31 +18,31 @@ func GetTestDataGetRecord() *TestData { return &TestData{ input: []interface{}{1}, output: `{ - "record": { - "Updated_by": { - "type": "MODIFIER", - "value": { - "code": "Administrator", - "name": "Administrator" - }, - "key": "hehehe" + "record": { + "Updated_by": { + "type": "MODIFIER", + "value": { + "code": "Administrator", + "name": "Administrator" + }, + "key": "hehehe" - }, + }, - "$id": { - "type": "__ID__", - "value": "1" - } - } - }`, + "$id": { + "type": "__ID__", + "value": "1" + } + } + }`, } } func GetTestDataGetRecords() *TestData { return &TestData{ output: `{ - "records": [ + "records": [ { "Created_datetime": { "type": "CREATED_TIME", @@ -79,32 +79,32 @@ func GetTestDataGetRecords() *TestData { } ], "totalCount": null - }`, + }`, } } func GetDataTestUploadFile() *TestData { return &TestData{ output: `{ - "app": 3, - "id": 6, - "record": { - "attached_file": { - "value": [ - { - "fileKey": " c15b3870-7505-4ab6-9d8d-b9bdbc74f5d6" - } - ] - } - } - }`, + "app": 3, + "id": 6, + "record": { + "attached_file": { + "value": [ + { + "fileKey": " c15b3870-7505-4ab6-9d8d-b9bdbc74f5d6" + } + ] + } + } + }`, } } func GetDataTestRecordComments() *TestData { return &TestData{ output: `{ - "comments": [ + "comments": [ { "id": "3", "text": "user14 Thank you! Looks great.", @@ -146,14 +146,14 @@ func GetDataTestRecordComments() *TestData { ], "older": false, "newer": false - }`, + }`, } } func GetDataTestForm() *TestData { return &TestData{ output: `{ - "properties": [ + "properties": [ { "code": "string_1", "defaultValue": "", @@ -198,7 +198,7 @@ func GetDataTestForm() *TestData { "type": "CHECK_BOX" } ] - }`, + }`, } } @@ -210,18 +210,18 @@ func GetDataTestDeleteRecordComment() *TestData { func GetTestDataAddRecord() *TestData { return &TestData{ output: `{ - "id": "1", + "id": "1", "revision": "1" - }`, + }`, } } func GetTestDataAddRecords() *TestData { return &TestData{ output: `{ - "ids": ["77","78"], - "revisions": ["1","1"] - }`, + "ids": ["77","78"], + "revisions": ["1","1"] + }`, } } @@ -230,21 +230,22 @@ func GetDataTestAddRecord() *TestData { input: []interface{}{ "ほげ春巻.txta", bytes.NewReader([]byte(`abc - hoge - `)), + hoge + `)), + "text/html", }, output: `{ - "id": "1", - "revision": "1" - }`, + "id": "1", + "revision": "1" + }`, } } func getDataTestCreateCursor() *TestData { return &TestData{ output: `{ - "id": "9a9716fe-1394-4677-a1c7-2199a5d28215", - "totalCount": 123456 - }`, + "id": "9a9716fe-1394-4677-a1c7-2199a5d28215", + "totalCount": 123456 + }`, } } @@ -253,27 +254,27 @@ func GetDataTestGetRecordsByCursor() *TestData { return &TestData{ input: []interface{}{"9a9716fe-1394-4677-a1c7-2199a5d28215"}, output: `{ - "records": [ - { - "$id": { - "type": "__ID__", - "value": "1" - }, - "Created_by": { - "type": "CREATOR", - "value": { - "code": "Administrator", - "name": "Administrator" - } - }, - "Created_datetime": { - "type": "CREATED_TIME", - "value": "2019-05-23T04:50:00Z" - } - } - ], - "next": false - }`, + "records": [ + { + "$id": { + "type": "__ID__", + "value": "1" + }, + "Created_by": { + "type": "CREATOR", + "value": { + "code": "Administrator", + "name": "Administrator" + } + }, + "Created_datetime": { + "type": "CREATED_TIME", + "value": "2019-05-23T04:50:00Z" + } + } + ], + "next": false + }`, } } @@ -301,31 +302,31 @@ func GetTestDataUpdateRecordByKey() *TestData { return &TestData{ input: []interface{}{2}, output: `{ - "app": 1, - "records": [ - { - "updateKey": { - "field": "unique_key", - "value": "CODE123" - }, - "record": { - "Text": { - "value": "Silver plates" - } - } - }, - { - "updateKey": { - "field": "unique_key", - "value": "CODE456" - }, - "record": { - "Text": { - "value": "The quick brown fox." - } - } - } - ] - }`, + "app": 1, + "records": [ + { + "updateKey": { + "field": "unique_key", + "value": "CODE123" + }, + "record": { + "Text": { + "value": "Silver plates" + } + } + }, + { + "updateKey": { + "field": "unique_key", + "value": "CODE456" + }, + "record": { + "Text": { + "value": "The quick brown fox." + } + } + } + ] + }`, } } From f9313133275532db499d0714fd81a7c5e505fded Mon Sep 17 00:00:00 2001 From: huong Date: Mon, 6 Jan 2020 14:03:52 +0700 Subject: [PATCH 53/70] formart json --- app_test.go | 1 + app_test_json.go | 80 ++++++++++++++++++++++++------------------------ 2 files changed, 41 insertions(+), 40 deletions(-) diff --git a/app_test.go b/app_test.go index 8494c9a..0ef1e44 100644 --- a/app_test.go +++ b/app_test.go @@ -101,6 +101,7 @@ func handleResponseRecordsCursor(response http.ResponseWriter, request *http.Req fmt.Fprint(response, testData.output) } } + func handleResponseRecordComments(response http.ResponseWriter, request *http.Request) { checkAuth(response, request) if request.Method == "POST" { diff --git a/app_test_json.go b/app_test_json.go index 2456e47..044e04a 100644 --- a/app_test_json.go +++ b/app_test_json.go @@ -22,18 +22,18 @@ func GetTestDataGetRecord() *TestData { "Updated_by": { "type": "MODIFIER", "value": { - "code": "Administrator", - "name": "Administrator" + "code": "Administrator", + "name": "Administrator" }, "key": "hehehe" }, - "$id": { - "type": "__ID__", - "value": "1" - } + "$id": { + "type": "__ID__", + "value": "1" + } } }`, } @@ -91,9 +91,9 @@ func GetDataTestUploadFile() *TestData { "record": { "attached_file": { "value": [ - { - "fileKey": " c15b3870-7505-4ab6-9d8d-b9bdbc74f5d6" - } + { + "fileKey": " c15b3870-7505-4ab6-9d8d-b9bdbc74f5d6" + } ] } } @@ -146,14 +146,14 @@ func GetDataTestRecordComments() *TestData { ], "older": false, "newer": false - }`, + }`, } } func GetDataTestForm() *TestData { return &TestData{ output: `{ - "properties": [ + "properties": [ { "code": "string_1", "defaultValue": "", @@ -197,8 +197,8 @@ func GetDataTestForm() *TestData { "required": "false", "type": "CHECK_BOX" } - ] - }`, + ] + }`, } } @@ -211,7 +211,7 @@ func GetTestDataAddRecord() *TestData { return &TestData{ output: `{ "id": "1", - "revision": "1" + "revision": "1" }`, } } @@ -255,23 +255,23 @@ func GetDataTestGetRecordsByCursor() *TestData { input: []interface{}{"9a9716fe-1394-4677-a1c7-2199a5d28215"}, output: `{ "records": [ - { - "$id": { - "type": "__ID__", - "value": "1" - }, - "Created_by": { - "type": "CREATOR", - "value": { - "code": "Administrator", - "name": "Administrator" - } - }, - "Created_datetime": { - "type": "CREATED_TIME", - "value": "2019-05-23T04:50:00Z" - } + { + "$id": { + "type": "__ID__", + "value": "1" + }, + "Created_by": { + "type": "CREATOR", + "value": { + "code": "Administrator", + "name": "Administrator" + } + }, + "Created_datetime": { + "type": "CREATED_TIME", + "value": "2019-05-23T04:50:00Z" } + } ], "next": false }`, @@ -306,24 +306,24 @@ func GetTestDataUpdateRecordByKey() *TestData { "records": [ { "updateKey": { - "field": "unique_key", - "value": "CODE123" + "field": "unique_key", + "value": "CODE123" }, "record": { - "Text": { - "value": "Silver plates" - } + "Text": { + "value": "Silver plates" + } } }, { "updateKey": { - "field": "unique_key", - "value": "CODE456" + "field": "unique_key", + "value": "CODE456" }, "record": { - "Text": { - "value": "The quick brown fox." - } + "Text": { + "value": "The quick brown fox." + } } } ] From ec2ce23998367d05e1d4f05cdd37fb61338f3566 Mon Sep 17 00:00:00 2001 From: huong Date: Mon, 6 Jan 2020 14:12:38 +0700 Subject: [PATCH 54/70] add appid to newAppWithToken --- app_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/app_test.go b/app_test.go index 0ef1e44..c24c79f 100644 --- a/app_test.go +++ b/app_test.go @@ -199,6 +199,7 @@ func newAppWithGuest() *App { } func newAppWithToken() *App { return &App{ + AppId: KINTONE_APP_ID, Domain: KINTONE_DOMAIN, ApiToken: KINTONE_API_TOKEN, } From b6de386a488f6d7bf9db7eb7b2faa598b0a86f25 Mon Sep 17 00:00:00 2001 From: huong Date: Mon, 6 Jan 2020 15:05:40 +0700 Subject: [PATCH 55/70] remove kintone api token from app struct --- app_test.go | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/app_test.go b/app_test.go index c24c79f..d7cecd6 100644 --- a/app_test.go +++ b/app_test.go @@ -64,15 +64,14 @@ func checkAuth(response http.ResponseWriter, request *http.Request) { userAndPass := base64.StdEncoding.EncodeToString( []byte(KINTONE_USERNAME + ":" + KINTONE_USERNAME)) if authPassword != userAndPass && authToken != KINTONE_API_TOKEN { - http.Error(response, http.StatusText(http.StatusNotFound), http.StatusNotFound) + http.Error(response, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized) } } func checkContentType(response http.ResponseWriter, request *http.Request) { contentType := request.Header.Get("Content-Type") if contentType != "application/json" { - http.Error(response, http.StatusText(http.StatusNotFound), http.StatusNotFound) - + http.Error(response, http.StatusText(http.StatusNoContent), http.StatusNoContent) } } @@ -186,7 +185,6 @@ func newApp() *App { User: KINTONE_USERNAME, Password: KINTONE_PASSWORD, AppId: KINTONE_APP_ID, - ApiToken: KINTONE_API_TOKEN, } } func newAppWithGuest() *App { From 8b1f377823a21c5e8fb2fa9d22afdd52e056e3db Mon Sep 17 00:00:00 2001 From: huong Date: Mon, 6 Jan 2020 15:32:20 +0700 Subject: [PATCH 56/70] check auth --- app_test.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app_test.go b/app_test.go index d7cecd6..7fe373e 100644 --- a/app_test.go +++ b/app_test.go @@ -63,8 +63,11 @@ func checkAuth(response http.ResponseWriter, request *http.Request) { authToken := request.Header.Get(AUTH_HEADER_TOKEN) userAndPass := base64.StdEncoding.EncodeToString( []byte(KINTONE_USERNAME + ":" + KINTONE_USERNAME)) - if authPassword != userAndPass && authToken != KINTONE_API_TOKEN { + if authToken != KINTONE_API_TOKEN { http.Error(response, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized) + } else if authPassword != userAndPass { + http.Error(response, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized) + } } From c137fd1c766784358e25ee2df9371946dd104bce Mon Sep 17 00:00:00 2001 From: huong Date: Mon, 6 Jan 2020 16:08:37 +0700 Subject: [PATCH 57/70] change variable app --- app_test.go | 47 +++++++++++++++++++++++------------------------ 1 file changed, 23 insertions(+), 24 deletions(-) diff --git a/app_test.go b/app_test.go index 7fe373e..1b9a20c 100644 --- a/app_test.go +++ b/app_test.go @@ -63,11 +63,10 @@ func checkAuth(response http.ResponseWriter, request *http.Request) { authToken := request.Header.Get(AUTH_HEADER_TOKEN) userAndPass := base64.StdEncoding.EncodeToString( []byte(KINTONE_USERNAME + ":" + KINTONE_USERNAME)) - if authToken != KINTONE_API_TOKEN { + if authToken != "" && authToken != KINTONE_API_TOKEN { http.Error(response, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized) } else if authPassword != userAndPass { http.Error(response, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized) - } } @@ -243,8 +242,8 @@ func TestAddRecord(t *testing.T) { } func TestGetRecord(t *testing.T) { testData := GetTestDataGetRecord() - a := newApp() - if rec, err := a.GetRecord(uint64(testData.input[0].(int))); err != nil { + app := newApp() + if rec, err := app.GetRecord(uint64(testData.input[0].(int))); err != nil { t.Error(err) } else { if rec.Id() != 1 { @@ -255,7 +254,7 @@ func TestGetRecord(t *testing.T) { if len(files) == 0 { continue } - fd, err := a.Download(files[0].FileKey) + fd, err := app.Download(files[0].FileKey) if err != nil { t.Error(err) } else { @@ -266,7 +265,7 @@ func TestGetRecord(t *testing.T) { } } - if recs, err := a.GetRecords(nil, "limit 3 offset 3"); err != nil { + if recs, err := app.GetRecords(nil, "limit 3 offset 3"); err != nil { t.Error(err) } else { if len(recs) > 3 { @@ -274,7 +273,7 @@ func TestGetRecord(t *testing.T) { } } - if recs, err := a.GetAllRecords([]string{"レコード番号"}); err != nil { + if recs, err := app.GetAllRecords([]string{"レコード番号"}); err != nil { t.Error(err) } else { t.Log(len(recs)) @@ -283,14 +282,14 @@ func TestGetRecord(t *testing.T) { } func TestUpdateRecord(t *testing.T) { testData := GetTestDataGetRecord() - a := newApp() + app := newApp() - rec, err := a.GetRecord(uint64(testData.input[0].(int))) + rec, err := app.GetRecord(uint64(testData.input[0].(int))) if err != nil { t.Fatal(err) } rec.Fields["title"] = SingleLineTextField("new title") - if err := a.UpdateRecord(rec, true); err != nil { + if err := app.UpdateRecord(rec, true); err != nil { t.Error("UpdateRecord failed", err) } @@ -298,11 +297,11 @@ func TestUpdateRecord(t *testing.T) { "field": "unique_key", "value": "unique_code" }`) - if err := a.UpdateRecordByKey(rec, true, "key"); err != nil { + if err := app.UpdateRecordByKey(rec, true, "key"); err != nil { t.Error("UpdateRecordByKey failed", err) } - recs, err := a.GetRecords(nil, "limit 3") + recs, err := app.GetRecords(nil, "limit 3") if err != nil { t.Fatal(err) } @@ -314,20 +313,20 @@ func TestUpdateRecord(t *testing.T) { "value": "unique_code" }`) } - if err := a.UpdateRecords(recs, true); err != nil { + if err := app.UpdateRecords(recs, true); err != nil { t.Error("UpdateRecords failed", err) } - if err := a.UpdateRecordsByKey(recs, true, "key"); err != nil { + if err := app.UpdateRecordsByKey(recs, true, "key"); err != nil { t.Error("UpdateRecordsByKey failed", err) } } func TestDeleteRecord(t *testing.T) { - a := newApp() + app := newApp() ids := []uint64{6, 7} - if err := a.DeleteRecords(ids); err != nil { + if err := app.DeleteRecords(ids); err != nil { t.Error("DeleteRecords failed", err) } } @@ -361,9 +360,9 @@ func TestCreateCursor(t *testing.T) { } func TestFields(t *testing.T) { - a := newApp() + app := newApp() - fi, err := a.Fields() + fi, err := app.Fields() if err != nil { t.Error("Fields failed", err) } @@ -373,27 +372,27 @@ func TestFields(t *testing.T) { } func TestApiToken(t *testing.T) { - a := newAppWithToken() - _, err := a.Fields() + app := newAppWithToken() + _, err := app.Fields() if err != nil { t.Error("Api token failed", err) } } func TestGuestSpace(t *testing.T) { - a := newAppWithGuest() + app := newAppWithGuest() - _, err := a.Fields() + _, err := app.Fields() if err != nil { t.Error("GuestSpace failed", err) } } func TestGetRecordComments(t *testing.T) { - a := newApp() + app := newApp() var offset uint64 = 0 var limit uint64 = 10 - if rec, err := a.GetRecordComments(1, "asc", offset, limit); err != nil { + if rec, err := app.GetRecordComments(1, "asc", offset, limit); err != nil { t.Error(err) } else { if !strings.Contains(rec[0].Id, "3") { From add223330c1212fa6932571c4835566017e5703c Mon Sep 17 00:00:00 2001 From: huong Date: Tue, 7 Jan 2020 09:19:07 +0700 Subject: [PATCH 58/70] fix review #6 --- app_test.go | 32 +++++++++++++------------------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/app_test.go b/app_test.go index 1b9a20c..ab231a3 100644 --- a/app_test.go +++ b/app_test.go @@ -27,6 +27,8 @@ const ( KINTONE_GUEST_SPACE_ID = 1 AUTH_HEADER_TOKEN = "X-Cybozu-API-Token" AUTH_HEADER_PASSWORD = "X-Cybozu-Authorization" + CONTENT_TYPE = "Content-Type" + APPLICATION_JSON = "application/json" ) func createServerTest(mux *http.ServeMux) (*httptest.Server, error) { @@ -44,7 +46,7 @@ func createServerTest(mux *http.ServeMux) (*httptest.Server, error) { return ts, nil } -func createServerMux() (*http.ServeMux, error) { +func createServerMux() *http.ServeMux { mux := http.NewServeMux() mux.HandleFunc("/k/v1/record.json", handleResponseGetRecord) mux.HandleFunc("/k/v1/records.json", handleResponseGetRecords) @@ -54,7 +56,7 @@ func createServerMux() (*http.ServeMux, error) { mux.HandleFunc("/k/v1/records/cursor.json", handleResponseRecordsCursor) mux.HandleFunc("/k/v1/form.json", handleResponseForm) mux.HandleFunc("/k/guest/1/v1/form.json", handleResponseForm) - return mux, nil + return mux } // header check @@ -68,11 +70,10 @@ func checkAuth(response http.ResponseWriter, request *http.Request) { } else if authPassword != userAndPass { http.Error(response, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized) } - } func checkContentType(response http.ResponseWriter, request *http.Request) { - contentType := request.Header.Get("Content-Type") - if contentType != "application/json" { + contentType := request.Header.Get(CONTENT_TYPE) + if contentType != APPLICATION_JSON { http.Error(response, http.StatusText(http.StatusNoContent), http.StatusNoContent) } } @@ -105,12 +106,11 @@ func handleResponseRecordsCursor(response http.ResponseWriter, request *http.Req func handleResponseRecordComments(response http.ResponseWriter, request *http.Request) { checkAuth(response, request) + checkContentType(response, request) if request.Method == "POST" { - checkContentType(response, request) testData := GetTestDataAddRecordComment() fmt.Fprint(response, testData.output) } else if request.Method == "DELETE" { - checkContentType(response, request) testData := GetDataTestDeleteRecordComment() fmt.Fprint(response, testData.output) } @@ -126,16 +126,14 @@ func handleResponseUploadFile(response http.ResponseWriter, request *http.Reques func handleResponseGetRecord(response http.ResponseWriter, request *http.Request) { checkAuth(response, request) + checkContentType(response, request) if request.Method == "GET" { - checkContentType(response, request) testData := GetTestDataGetRecord() fmt.Fprint(response, testData.output) } else if request.Method == "PUT" { - checkContentType(response, request) testData := GetTestDataUpdateRecordByKey() fmt.Fprint(response, testData.output) } else if request.Method == "POST" { - checkContentType(response, request) testData := GetTestDataAddRecord() fmt.Fprint(response, testData.output) } @@ -144,16 +142,14 @@ func handleResponseGetRecord(response http.ResponseWriter, request *http.Request func handleResponseGetRecords(response http.ResponseWriter, request *http.Request) { checkAuth(response, request) + checkContentType(response, request) if request.Method == "GET" { - checkContentType(response, request) testData := GetTestDataGetRecords() fmt.Fprint(response, testData.output) } else if request.Method == "DELETE" { - checkContentType(response, request) testData := GetTestDataDeleteRecords() fmt.Fprint(response, testData.output) } else if request.Method == "POST" { - checkContentType(response, request) testData := GetTestDataAddRecords() fmt.Fprint(response, testData.output) } @@ -169,10 +165,7 @@ func handleResponseGetRecordsComments(response http.ResponseWriter, request *htt } func TestMain(m *testing.M) { - mux, err := createServerMux() - if err != nil { - fmt.Println("StartServerTest", err) - } + mux := createServerMux() ts, err := createServerTest(mux) if err != nil { fmt.Println("createServerTest", err) @@ -193,7 +186,8 @@ func newAppWithGuest() *App { return &App{ Domain: KINTONE_DOMAIN, AppId: KINTONE_APP_ID, - ApiToken: KINTONE_API_TOKEN, + User: KINTONE_USERNAME, + Password: KINTONE_PASSWORD, GuestSpaceId: KINTONE_GUEST_SPACE_ID, } } @@ -265,7 +259,7 @@ func TestGetRecord(t *testing.T) { } } - if recs, err := app.GetRecords(nil, "limit 3 offset 3"); err != nil { + if recs, err := app.GetRecords(nil, testData.input[0].(string)); err != nil { t.Error(err) } else { if len(recs) > 3 { From f6bd0be82311196879571fb15a9610b62d226146 Mon Sep 17 00:00:00 2001 From: huong Date: Tue, 7 Jan 2020 09:19:26 +0700 Subject: [PATCH 59/70] add json input --- app_test_json.go | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/app_test_json.go b/app_test_json.go index 044e04a..934a0c3 100644 --- a/app_test_json.go +++ b/app_test_json.go @@ -16,7 +16,7 @@ func GetTestDataDeleteRecords() *TestData { } func GetTestDataGetRecord() *TestData { return &TestData{ - input: []interface{}{1}, + input: []interface{}{"limit 100"}, output: `{ "record": { "Updated_by": { @@ -41,9 +41,13 @@ func GetTestDataGetRecord() *TestData { func GetTestDataGetRecords() *TestData { return &TestData{ + input: []interface{}{ + nil, + "limit 3 offset 3", + }, output: `{ - "records": [ - { + "records": [ + { "Created_datetime": { "type": "CREATED_TIME", "value": "2019-03-11T04:50:00Z" From 2e8448f8e9baa4b804916db633e523f96e4c7df2 Mon Sep 17 00:00:00 2001 From: huong Date: Tue, 7 Jan 2020 09:46:15 +0700 Subject: [PATCH 60/70] formart json --- app_test_json.go | 465 ++++++++++++++++++++++++----------------------- 1 file changed, 236 insertions(+), 229 deletions(-) diff --git a/app_test_json.go b/app_test_json.go index 934a0c3..215cfee 100644 --- a/app_test_json.go +++ b/app_test_json.go @@ -16,26 +16,24 @@ func GetTestDataDeleteRecords() *TestData { } func GetTestDataGetRecord() *TestData { return &TestData{ - input: []interface{}{"limit 100"}, - output: `{ - "record": { - "Updated_by": { - "type": "MODIFIER", - "value": { - "code": "Administrator", - "name": "Administrator" - }, - "key": "hehehe" - - - }, - - "$id": { - "type": "__ID__", - "value": "1" - } - } - }`, + input: []interface{}{1}, + output: ` + { + "record":{ + "Updated_by":{ + "type":"MODIFIER", + "value":{ + "code":"Administrator", + "name":"Administrator" + }, + "key":"hehehe" + }, + "$id":{ + "type":"__ID__", + "value":"1" + } + } + }`, } } @@ -45,164 +43,168 @@ func GetTestDataGetRecords() *TestData { nil, "limit 3 offset 3", }, - output: `{ - "records": [ - { - "Created_datetime": { - "type": "CREATED_TIME", - "value": "2019-03-11T04:50:00Z" - }, - "Created_by": { - "type": "CREATOR", - "value": { - "code": "Administrator", - "name": "Administrator" - } - }, - "$id": { - "type": "__ID__", - "value": "1" - } - }, - { - "Created_datetime": { - "type": "CREATED_TIME", - "value": "2019-03-11T06:42:00Z" - }, - "Created_by": { - "type": "CREATOR", - "value": { - "code": "Administrator", - "name": "Administrator" - } - }, - "$id": { - "type": "__ID__", - "value": "2" - } - } - ], - "totalCount": null - }`, + output: ` + { + "records":[ + { + "Created_datetime":{ + "type":"CREATED_TIME", + "value":"2019-03-11T04:50:00Z" + }, + "Created_by":{ + "type":"CREATOR", + "value":{ + "code":"Administrator", + "name":"Administrator" + } + }, + "$id":{ + "type":"__ID__", + "value":"1" + } + }, + { + "Created_datetime":{ + "type":"CREATED_TIME", + "value":"2019-03-11T06:42:00Z" + }, + "Created_by":{ + "type":"CREATOR", + "value":{ + "code":"Administrator", + "name":"Administrator" + } + }, + "$id":{ + "type":"__ID__", + "value":"2" + } + } + ], + "totalCount":null + }`, } } func GetDataTestUploadFile() *TestData { return &TestData{ - output: `{ - "app": 3, - "id": 6, - "record": { - "attached_file": { - "value": [ - { - "fileKey": " c15b3870-7505-4ab6-9d8d-b9bdbc74f5d6" - } - ] - } - } - }`, + output: ` + { + "app":3, + "id":6, + "record":{ + "attached_file":{ + "value":[ + { + "fileKey":" c15b3870-7505-4ab6-9d8d-b9bdbc74f5d6" + } + ] + } + } + }`, } } func GetDataTestRecordComments() *TestData { return &TestData{ - output: `{ - "comments": [ - { - "id": "3", - "text": "user14 Thank you! Looks great.", - "createdAt": "2016-05-09T18:29:05Z", - "creator": { - "code": "user13", - "name": "user13" - }, - "mentions": [ - { - "code": "user14", - "type": "USER" - } - ] - }, - { - "id": "2", - "text": "user13 Global Sales APAC Taskforce \nHere is today's report.", - "createdAt": "2016-05-09T18:27:54Z", - "creator": { - "code": "user14", - "name": "user14" - }, - "mentions": [ - { - "code": "user13", - "type": "USER" - }, - { - "code": "Global Sales_1BNZeQ", - "type": "ORGANIZATION" - }, - { - "code": "APAC Taskforce_DJrvzu", - "type": "GROUP" - } - ] - } - ], - "older": false, - "newer": false - }`, + output: ` + { + "comments":[ + { + "id":"3", + "text":"user14 Thank you! Looks great.", + "createdAt":"2016-05-09T18:29:05Z", + "creator":{ + "code":"user13", + "name":"user13" + }, + "mentions":[ + { + "code":"user14", + "type":"USER" + } + ] + }, + { + "id":"2", + "text":"user13 Global Sales APAC Taskforce \nHere is today's report.", + "createdAt":"2016-05-09T18:27:54Z", + "creator":{ + "code":"user14", + "name":"user14" + }, + "mentions":[ + { + "code":"user13", + "type":"USER" + }, + { + "code":"Global Sales_1BNZeQ", + "type":"ORGANIZATION" + }, + { + "code":"APAC Taskforce_DJrvzu", + "type":"GROUP" + } + ] + } + ], + "older":false, + "newer":false + }`, } } func GetDataTestForm() *TestData { return &TestData{ - output: `{ - "properties": [ - { - "code": "string_1", - "defaultValue": "", - "expression": "", - "hideExpression": "false", - "maxLength": "64", - "minLength": null, - "label": "string_1", - "noLabel": "false", - "required": "true", - "type": "SINGLE_LINE_TEXT", - "unique": "true" - }, - { - "code": "number_1", - "defaultValue": "12345", - "digit": "true", - "displayScale": "4", - "expression": "", - "maxValue": null, - "minValue": null, - "label": "number_1", - "noLabel": "true", - "required": "false", - "type": "NUMBER", - "unique": "false" - }, - { - "code": "checkbox_1", - "defaultValue": [ - "sample1", - "sample3" - ], - "label": "checkbox_1", - "noLabel": "false", - "options": [ - "sample1", - "sample2", - "sample3" - ], - "required": "false", - "type": "CHECK_BOX" - } - ] - }`, + output: ` + { + "properties":[ + { + "code":"string_1", + "defaultValue":"", + "expression":"", + "hideExpression":"false", + "maxLength":"64", + "minLength":null, + "label":"string_1", + "noLabel":"false", + "required":"true", + "type":"SINGLE_LINE_TEXT", + "unique":"true" + }, + { + "code":"number_1", + "defaultValue":"12345", + "digit":"true", + "displayScale":"4", + "expression":"", + "maxValue":null, + "minValue":null, + "label":"number_1", + "noLabel":"true", + "required":"false", + "type":"NUMBER", + "unique":"false" + }, + { + "code":"checkbox_1", + "defaultValue":[ + "sample1", + "sample3" + ], + "label":"checkbox_1", + "noLabel":"false", + "options":[ + "sample1", + "sample2", + "sample3" + ], + "required":"false", + "type":"CHECK_BOX" + } + ] + }`, } } @@ -214,18 +216,19 @@ func GetDataTestDeleteRecordComment() *TestData { func GetTestDataAddRecord() *TestData { return &TestData{ output: `{ - "id": "1", - "revision": "1" - }`, + "id": "1", + "revision": "1" + }`, } } func GetTestDataAddRecords() *TestData { return &TestData{ - output: `{ - "ids": ["77","78"], - "revisions": ["1","1"] - }`, + output: ` + { + "ids": ["77","78"], + "revisions": ["1","1"] + }`, } } @@ -234,22 +237,24 @@ func GetDataTestAddRecord() *TestData { input: []interface{}{ "ほげ春巻.txta", bytes.NewReader([]byte(`abc - hoge - `)), + hoge + `)), "text/html", }, - output: `{ - "id": "1", - "revision": "1" - }`, + output: ` + { + "id": "1", + "revision": "1" + }`, } } func getDataTestCreateCursor() *TestData { return &TestData{ - output: `{ - "id": "9a9716fe-1394-4677-a1c7-2199a5d28215", - "totalCount": 123456 - }`, + output: ` + { + "id": "9a9716fe-1394-4677-a1c7-2199a5d28215", + "totalCount": 123456 + }`, } } @@ -257,28 +262,29 @@ func GetDataTestGetRecordsByCursor() *TestData { return &TestData{ input: []interface{}{"9a9716fe-1394-4677-a1c7-2199a5d28215"}, - output: `{ - "records": [ - { - "$id": { - "type": "__ID__", - "value": "1" - }, - "Created_by": { - "type": "CREATOR", - "value": { - "code": "Administrator", - "name": "Administrator" - } - }, - "Created_datetime": { - "type": "CREATED_TIME", - "value": "2019-05-23T04:50:00Z" - } - } - ], - "next": false - }`, + output: ` + { + "records":[ + { + "$id":{ + "type":"__ID__", + "value":"1" + }, + "Created_by":{ + "type":"CREATOR", + "value":{ + "code":"Administrator", + "name":"Administrator" + } + }, + "Created_datetime":{ + "type":"CREATED_TIME", + "value":"2019-05-23T04:50:00Z" + } + } + ], + "next":false + }`, } } @@ -305,32 +311,33 @@ func GetTestDataAddRecordComment() *TestData { func GetTestDataUpdateRecordByKey() *TestData { return &TestData{ input: []interface{}{2}, - output: `{ - "app": 1, - "records": [ - { - "updateKey": { - "field": "unique_key", - "value": "CODE123" - }, - "record": { - "Text": { - "value": "Silver plates" - } - } - }, - { - "updateKey": { - "field": "unique_key", - "value": "CODE456" - }, - "record": { - "Text": { - "value": "The quick brown fox." - } - } - } - ] - }`, + output: ` + { + "app":1, + "records":[ + { + "updateKey":{ + "field":"unique_key", + "value":"CODE123" + }, + "record":{ + "Text":{ + "value":"Silver plates" + } + } + }, + { + "updateKey":{ + "field":"unique_key", + "value":"CODE456" + }, + "record":{ + "Text":{ + "value":"The quick brown fox." + } + } + } + ] + }`, } } From ae0cda2ea1879c0b7f167d511c977584ff055f0b Mon Sep 17 00:00:00 2001 From: huong Date: Tue, 7 Jan 2020 10:30:24 +0700 Subject: [PATCH 61/70] add basic auth and add input json for something function --- app_test.go | 60 +++++++++++++++++++++++++++++++++-------------------- 1 file changed, 38 insertions(+), 22 deletions(-) diff --git a/app_test.go b/app_test.go index ab231a3..f1f706c 100644 --- a/app_test.go +++ b/app_test.go @@ -27,8 +27,12 @@ const ( KINTONE_GUEST_SPACE_ID = 1 AUTH_HEADER_TOKEN = "X-Cybozu-API-Token" AUTH_HEADER_PASSWORD = "X-Cybozu-Authorization" + AUTH_HEADER_BASIC = "Authorization" CONTENT_TYPE = "Content-Type" APPLICATION_JSON = "application/json" + BASIC_AUTH = true + BASIC_AUTH_USER = "basic" + BASIC_AUTH_PASSWORD = "basic" ) func createServerTest(mux *http.ServeMux) (*httptest.Server, error) { @@ -63,14 +67,28 @@ func createServerMux() *http.ServeMux { func checkAuth(response http.ResponseWriter, request *http.Request) { authPassword := request.Header.Get(AUTH_HEADER_PASSWORD) authToken := request.Header.Get(AUTH_HEADER_TOKEN) + authBasic := request.Header.Get(AUTH_HEADER_BASIC) + userAndPass := base64.StdEncoding.EncodeToString( []byte(KINTONE_USERNAME + ":" + KINTONE_USERNAME)) + + userAndPassBasic := "Basic " + base64.StdEncoding.EncodeToString( + []byte(BASIC_AUTH_USER+":"+BASIC_AUTH_PASSWORD)) + + if authToken != "" && authPassword != "" && authBasic != "" { + http.Error(response, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized) + } + if BASIC_AUTH && authBasic != userAndPassBasic { + http.Error(response, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized) + } if authToken != "" && authToken != KINTONE_API_TOKEN { http.Error(response, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized) - } else if authPassword != userAndPass { + } + if authPassword != "" && authPassword != userAndPass { http.Error(response, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized) } } + func checkContentType(response http.ResponseWriter, request *http.Request) { contentType := request.Header.Get(CONTENT_TYPE) if contentType != APPLICATION_JSON { @@ -236,6 +254,7 @@ func TestAddRecord(t *testing.T) { } func TestGetRecord(t *testing.T) { testData := GetTestDataGetRecord() + testDataRecords := GetTestDataGetRecords() app := newApp() if rec, err := app.GetRecord(uint64(testData.input[0].(int))); err != nil { t.Error(err) @@ -259,7 +278,7 @@ func TestGetRecord(t *testing.T) { } } - if recs, err := app.GetRecords(nil, testData.input[0].(string)); err != nil { + if recs, err := app.GetRecords(testDataRecords.input[0].([]string), testDataRecords.input[1].(string)); err != nil { t.Error(err) } else { if len(recs) > 3 { @@ -267,7 +286,7 @@ func TestGetRecord(t *testing.T) { } } - if recs, err := app.GetAllRecords([]string{"レコード番号"}); err != nil { + if recs, err := app.GetAllRecords(testDataRecords.input[0].([]string)); err != nil { t.Error(err) } else { t.Log(len(recs)) @@ -276,6 +295,9 @@ func TestGetRecord(t *testing.T) { } func TestUpdateRecord(t *testing.T) { testData := GetTestDataGetRecord() + testDataRecords := GetTestDataGetRecords() + testDataRecordByKey := GetTestDataUpdateRecordByKey() + app := newApp() rec, err := app.GetRecord(uint64(testData.input[0].(int))) @@ -283,19 +305,18 @@ func TestUpdateRecord(t *testing.T) { t.Fatal(err) } rec.Fields["title"] = SingleLineTextField("new title") - if err := app.UpdateRecord(rec, true); err != nil { + if err := app.UpdateRecord(rec, testData.input[1].(bool)); err != nil { t.Error("UpdateRecord failed", err) } - rec.Fields["key"] = SingleLineTextField(` { + rec.Fields[testDataRecordByKey.input[1].(string)] = SingleLineTextField(` { "field": "unique_key", "value": "unique_code" }`) - if err := app.UpdateRecordByKey(rec, true, "key"); err != nil { - + if err := app.UpdateRecordByKey(rec, testData.input[1].(bool), testDataRecordByKey.input[1].(string)); err != nil { t.Error("UpdateRecordByKey failed", err) } - recs, err := app.GetRecords(nil, "limit 3") + recs, err := app.GetRecords(testDataRecords.input[0].([]string), testDataRecords.input[1].(string)) if err != nil { t.Fatal(err) } @@ -307,20 +328,19 @@ func TestUpdateRecord(t *testing.T) { "value": "unique_code" }`) } - if err := app.UpdateRecords(recs, true); err != nil { + if err := app.UpdateRecords(recs, testData.input[1].(bool)); err != nil { t.Error("UpdateRecords failed", err) } - if err := app.UpdateRecordsByKey(recs, true, "key"); err != nil { + if err := app.UpdateRecordsByKey(recs, testDataRecordByKey.input[2].(bool), testDataRecordByKey.input[1].(string)); err != nil { t.Error("UpdateRecordsByKey failed", err) } } func TestDeleteRecord(t *testing.T) { + testData := GetTestDataDeleteRecords() app := newApp() - - ids := []uint64{6, 7} - if err := app.DeleteRecords(ids); err != nil { + if err := app.DeleteRecords(testData.input[0].([]uint64)); err != nil { t.Error("DeleteRecords failed", err) } } @@ -355,7 +375,6 @@ func TestCreateCursor(t *testing.T) { func TestFields(t *testing.T) { app := newApp() - fi, err := app.Fields() if err != nil { t.Error("Fields failed", err) @@ -375,7 +394,6 @@ func TestApiToken(t *testing.T) { func TestGuestSpace(t *testing.T) { app := newAppWithGuest() - _, err := app.Fields() if err != nil { t.Error("GuestSpace failed", err) @@ -383,10 +401,9 @@ func TestGuestSpace(t *testing.T) { } func TestGetRecordComments(t *testing.T) { + testData := GetDataTestRecordComments() app := newApp() - var offset uint64 = 0 - var limit uint64 = 10 - if rec, err := app.GetRecordComments(1, "asc", offset, limit); err != nil { + if rec, err := app.GetRecordComments(uint64(testData.input[0].(int)), testData.input[1].(string), uint64(testData.input[2].(int)), uint64(testData.input[3].(int))); err != nil { t.Error(err) } else { if !strings.Contains(rec[0].Id, "3") { @@ -414,13 +431,12 @@ func TestAddRecordComment(t *testing.T) { } func TestDeleteComment(t *testing.T) { + testData := GetDataTestDeleteRecordComment() appTest := newApp() - var cmtID uint64 = 14 - err := appTest.DeleteComment(3, 12) - + err := appTest.DeleteComment(uint64(testData.input[0].(int)), uint64(testData.input[1].(int))) if err != nil { t.Error(err) } else { - t.Logf("The comment with id = %v has been deleted successefully!", cmtID) + t.Logf("The comment with id = %v has been deleted successefully!", uint64(testData.input[0].(int))) } } From 9d87cf5bce991d56916885979dc5de2abdae4712 Mon Sep 17 00:00:00 2001 From: huong Date: Tue, 7 Jan 2020 10:30:35 +0700 Subject: [PATCH 62/70] add input json --- app_test_json.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/app_test_json.go b/app_test_json.go index 215cfee..d390786 100644 --- a/app_test_json.go +++ b/app_test_json.go @@ -11,12 +11,13 @@ type TestData struct { func GetTestDataDeleteRecords() *TestData { return &TestData{ + input: []interface{}{[]uint64{6, 7}}, output: `{}`, } } func GetTestDataGetRecord() *TestData { return &TestData{ - input: []interface{}{1}, + input: []interface{}{1, true}, output: ` { "record":{ @@ -107,6 +108,7 @@ func GetDataTestUploadFile() *TestData { func GetDataTestRecordComments() *TestData { return &TestData{ + input: []interface{}{1, "asc", 0, 10}, output: ` { "comments":[ @@ -210,6 +212,7 @@ func GetDataTestForm() *TestData { func GetDataTestDeleteRecordComment() *TestData { return &TestData{ + input: []interface{}{3, 14}, output: `{}`, } } @@ -310,7 +313,7 @@ func GetTestDataAddRecordComment() *TestData { } func GetTestDataUpdateRecordByKey() *TestData { return &TestData{ - input: []interface{}{2}, + input: []interface{}{2, "key", true}, output: ` { "app":1, From 882ae7ebcfabf724616953e98f98a45670721c28 Mon Sep 17 00:00:00 2001 From: huong Date: Tue, 7 Jan 2020 11:04:12 +0700 Subject: [PATCH 63/70] fix unit test --- app_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app_test.go b/app_test.go index f1f706c..6e59862 100644 --- a/app_test.go +++ b/app_test.go @@ -75,10 +75,10 @@ func checkAuth(response http.ResponseWriter, request *http.Request) { userAndPassBasic := "Basic " + base64.StdEncoding.EncodeToString( []byte(BASIC_AUTH_USER+":"+BASIC_AUTH_PASSWORD)) - if authToken != "" && authPassword != "" && authBasic != "" { + if authToken == "" && authPassword == "" && authBasic == "" { http.Error(response, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized) } - if BASIC_AUTH && authBasic != userAndPassBasic { + if BASIC_AUTH && authBasic != "" && authBasic != userAndPassBasic { http.Error(response, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized) } if authToken != "" && authToken != KINTONE_API_TOKEN { From c8265c66db80582cba755f703b1bb7032b11e645 Mon Sep 17 00:00:00 2001 From: huong Date: Tue, 7 Jan 2020 11:04:31 +0700 Subject: [PATCH 64/70] fix value json get test data records --- app_test_json.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app_test_json.go b/app_test_json.go index d390786..34b20d9 100644 --- a/app_test_json.go +++ b/app_test_json.go @@ -41,7 +41,7 @@ func GetTestDataGetRecord() *TestData { func GetTestDataGetRecords() *TestData { return &TestData{ input: []interface{}{ - nil, + []string{"Created_datetime"}, "limit 3 offset 3", }, output: ` From 958b54ec38a5650f45ad73c78633fc4a120da0e7 Mon Sep 17 00:00:00 2001 From: huong Date: Tue, 7 Jan 2020 11:19:38 +0700 Subject: [PATCH 65/70] remove filed data test --- app_test_json.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app_test_json.go b/app_test_json.go index 34b20d9..70e2e40 100644 --- a/app_test_json.go +++ b/app_test_json.go @@ -41,7 +41,7 @@ func GetTestDataGetRecord() *TestData { func GetTestDataGetRecords() *TestData { return &TestData{ input: []interface{}{ - []string{"Created_datetime"}, + []string{}, "limit 3 offset 3", }, output: ` From b80c04c546819dbe03c7176e1229a9f5875c0e58 Mon Sep 17 00:00:00 2001 From: huong Date: Tue, 7 Jan 2020 12:58:43 +0700 Subject: [PATCH 66/70] fix review --- app_test.go | 7 +++++-- cursor_test.go | 5 +---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/app_test.go b/app_test.go index 6e59862..01b7004 100644 --- a/app_test.go +++ b/app_test.go @@ -13,6 +13,7 @@ import ( "net" "net/http" "net/http/httptest" + "os" "strings" "testing" "time" @@ -186,10 +187,12 @@ func TestMain(m *testing.M) { mux := createServerMux() ts, err := createServerTest(mux) if err != nil { - fmt.Println("createServerTest", err) + fmt.Println("createServerTest: ", err) + os.Exit(1) } - m.Run() + code := m.Run() ts.Close() + os.Exit(code) } func newApp() *App { diff --git a/cursor_test.go b/cursor_test.go index c7a207c..112bb24 100644 --- a/cursor_test.go +++ b/cursor_test.go @@ -1,16 +1,13 @@ package kintone import ( - "fmt" "testing" ) func TestDecodeCursor(t *testing.T) { data := []byte(`{"id":"aaaaaaaaaaaaaaaaaa","totalCount":"null"}`) - cursor, err := decodeCursor(data) + _, err := decodeCursor(data) if err != nil { t.Errorf("TestDecodeCursor is failed: %v", err) - } - fmt.Println(cursor) } From 3a33005ecf312cfdc520d65bccd7a281ffb84d99 Mon Sep 17 00:00:00 2001 From: huong Date: Tue, 7 Jan 2020 13:02:08 +0700 Subject: [PATCH 67/70] rm space --- app_test.go | 1 - 1 file changed, 1 deletion(-) diff --git a/app_test.go b/app_test.go index 01b7004..78b2b47 100644 --- a/app_test.go +++ b/app_test.go @@ -156,7 +156,6 @@ func handleResponseGetRecord(response http.ResponseWriter, request *http.Request testData := GetTestDataAddRecord() fmt.Fprint(response, testData.output) } - } func handleResponseGetRecords(response http.ResponseWriter, request *http.Request) { From 309fa8dad24d5573e7a03405d8fd1fcb6e44d573 Mon Sep 17 00:00:00 2001 From: huong Date: Tue, 7 Jan 2020 13:20:07 +0700 Subject: [PATCH 68/70] remove space --- app_test.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/app_test.go b/app_test.go index 78b2b47..ac05fa9 100644 --- a/app_test.go +++ b/app_test.go @@ -171,7 +171,6 @@ func handleResponseGetRecords(response http.ResponseWriter, request *http.Reques testData := GetTestDataAddRecords() fmt.Fprint(response, testData.output) } - } func handleResponseGetRecordsComments(response http.ResponseWriter, request *http.Request) { @@ -179,7 +178,6 @@ func handleResponseGetRecordsComments(response http.ResponseWriter, request *htt checkContentType(response, request) testData := GetDataTestRecordComments() fmt.Fprint(response, testData.output) - } func TestMain(m *testing.M) { From eefdd0f96d76d50ff2a5bbbe331ba1a06c9dd6ee Mon Sep 17 00:00:00 2001 From: huong Date: Tue, 7 Jan 2020 14:22:02 +0700 Subject: [PATCH 69/70] unit test get process --- app_test.go | 16 +++++++++++ app_test_json.go | 75 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 91 insertions(+) diff --git a/app_test.go b/app_test.go index ac05fa9..c1fe851 100644 --- a/app_test.go +++ b/app_test.go @@ -59,6 +59,7 @@ func createServerMux() *http.ServeMux { mux.HandleFunc("/k/v1/file.json", handleResponseUploadFile) mux.HandleFunc("/k/v1/record/comment.json", handleResponseRecordComments) mux.HandleFunc("/k/v1/records/cursor.json", handleResponseRecordsCursor) + mux.HandleFunc("/k/v1/app/status.json", handleResponseProcess) mux.HandleFunc("/k/v1/form.json", handleResponseForm) mux.HandleFunc("/k/guest/1/v1/form.json", handleResponseForm) return mux @@ -98,6 +99,12 @@ func checkContentType(response http.ResponseWriter, request *http.Request) { } // handler mux +func handleResponseProcess(response http.ResponseWriter, request *http.Request) { + checkAuth(response, request) + TestData := GetTestDataProcess() + fmt.Fprint(response, TestData.output) +} + func handleResponseForm(response http.ResponseWriter, request *http.Request) { checkAuth(response, request) if request.Method == "GET" { @@ -440,3 +447,12 @@ func TestDeleteComment(t *testing.T) { t.Logf("The comment with id = %v has been deleted successefully!", uint64(testData.input[0].(int))) } } + +func TestGetProcess(t *testing.T) { + TestData := GetTestDataProcess() + app := newApp() + _, err := app.GetProcess(TestData.input[0].(string)) + if err != nil { + t.Error("TestGetProcess failed: ", err) + } +} diff --git a/app_test_json.go b/app_test_json.go index 70e2e40..100b258 100644 --- a/app_test_json.go +++ b/app_test_json.go @@ -9,6 +9,81 @@ type TestData struct { output string } +func GetTestDataProcess() *TestData { + return &TestData{ + input: []interface{}{"en"}, + output: ` + { + "enable": true, + "states": { + "Not started": { + "name": "Not started", + "index": "0", + "assignee": { + "type": "ONE", + "entities": [ + ] + } + }, + "In progress": { + "name": "In progress", + "index": "1", + "assignee": { + "type": "ALL", + "entities": [ + { + "entity": { + "type": "USER", + "code": "user1" + }, + "includeSubs": false + }, + { + "entity": { + "type": "FIELD_ENTITY", + "code": "creator" + }, + "includeSubs": false + }, + { + "entity": { + "type": "CUSTOM_FIELD", + "code": "Boss" + }, + "includeSubs": false + } + ] + } + }, + "Completed": { + "name": "Completed", + "index": "2", + "assignee": { + "type": "ONE", + "entities": [ + ] + } + } + }, + "actions": [ + { + "name": "Start", + "from": "Not started", + "to": "In progress", + "filterCond": "Record_number = \"1\"" + }, + { + "name": "Complete", + "from": "In progress", + "to": "Completed", + "filterCond": "" + } + ], + "revision": "3" + }`, + } +} + func GetTestDataDeleteRecords() *TestData { return &TestData{ input: []interface{}{[]uint64{6, 7}}, From bbfba1120ca7bb3922dec6e36753e36e56df1a21 Mon Sep 17 00:00:00 2001 From: huong Date: Wed, 8 Jan 2020 09:24:25 +0700 Subject: [PATCH 70/70] formart space --- app_test_json.go | 122 +++++++++++++++++++++++------------------------ 1 file changed, 60 insertions(+), 62 deletions(-) diff --git a/app_test_json.go b/app_test_json.go index 100b258..f38d07d 100644 --- a/app_test_json.go +++ b/app_test_json.go @@ -14,72 +14,70 @@ func GetTestDataProcess() *TestData { input: []interface{}{"en"}, output: ` { - "enable": true, - "states": { - "Not started": { - "name": "Not started", - "index": "0", - "assignee": { - "type": "ONE", - "entities": [ - ] - } - }, - "In progress": { - "name": "In progress", - "index": "1", - "assignee": { - "type": "ALL", - "entities": [ - { - "entity": { - "type": "USER", - "code": "user1" - }, - "includeSubs": false - }, - { - "entity": { - "type": "FIELD_ENTITY", - "code": "creator" - }, - "includeSubs": false - }, - { - "entity": { - "type": "CUSTOM_FIELD", - "code": "Boss" - }, - "includeSubs": false - } - ] - } - }, - "Completed": { - "name": "Completed", - "index": "2", - "assignee": { - "type": "ONE", - "entities": [ - ] + "enable":true, + "states":{ + "Not started":{ + "name":"Not started", + "index":"0", + "assignee":{ + "type":"ONE", + "entities":[] + } + }, + "In progress":{ + "name":"In progress", + "index":"1", + "assignee":{ + "type":"ALL", + "entities":[ + { + "entity":{ + "type":"USER", + "code":"user1" + }, + "includeSubs":false + }, + { + "entity":{ + "type":"FIELD_ENTITY", + "code":"creator" + }, + "includeSubs":false + }, + { + "entity":{ + "type":"CUSTOM_FIELD", + "code":"Boss" + }, + "includeSubs":false } + ] } - }, - "actions": [ - { - "name": "Start", - "from": "Not started", - "to": "In progress", - "filterCond": "Record_number = \"1\"" - }, - { - "name": "Complete", - "from": "In progress", - "to": "Completed", - "filterCond": "" + }, + "Completed":{ + "name":"Completed", + "index":"2", + "assignee":{ + "type":"ONE", + "entities":[] } + } + }, + "actions":[ + { + "name":"Start", + "from":"Not started", + "to":"In progress", + "filterCond":"Record_number = \"1\"" + }, + { + "name":"Complete", + "from":"In progress", + "to":"Completed", + "filterCond":"" + } ], - "revision": "3" + "revision":"3" }`, } }