From 9e6f0750b17315b9000b67798b6b57f5388708c9 Mon Sep 17 00:00:00 2001 From: yinghan Date: Thu, 21 May 2020 21:17:51 +0800 Subject: [PATCH 1/8] feat(api): Support query to select all authorized columns Check and replace `*` in the select query to all authorized columns separated by comma Close #8 --- controller/db/select.go | 44 +++++++++++++++++++++++++++++++---------- 1 file changed, 34 insertions(+), 10 deletions(-) diff --git a/controller/db/select.go b/controller/db/select.go index 06370a4..b59fe9f 100644 --- a/controller/db/select.go +++ b/controller/db/select.go @@ -2,10 +2,6 @@ package controller import ( "encoding/json" - "io/ioutil" - - "net/http" - "github.com/DropKit/DropKit-Adapter/constants" "github.com/DropKit/DropKit-Adapter/logger" "github.com/DropKit/DropKit-Adapter/package/crypto/account" @@ -16,8 +12,30 @@ import ( "github.com/DropKit/DropKit-Adapter/package/utils" "github.com/DropKit/DropKit-Adapter/services" "github.com/spf13/viper" + "io/ioutil" + "net/http" + "strings" ) +func checkSelectAll(sqlCommand string, columnsCanSelect []string) string { + var idx int = -1 + for i, v := range sqlCommand { + if v == '*' { + idx = i + break + } + } + if idx == -1 { + return sqlCommand + } + + sqlSlice := []byte(sqlCommand[0:idx]) + columnsStr := strings.Join(columnsCanSelect, ",") + sqlSlice = append(sqlSlice, []byte(columnsStr)...) + sqlSlice = append(sqlSlice, []byte(sqlCommand[idx+1:])...) + return string(sqlSlice) +} + func HandleDBSelection(w http.ResponseWriter, r *http.Request) { body, err := ioutil.ReadAll(r.Body) if err != nil { @@ -39,6 +57,7 @@ func HandleDBSelection(w http.ResponseWriter, r *http.Request) { } sqlCommand := newStatement.Statement + callerPriavteKey := newStatement.PrivateKey callerAddress, err := account.PrivateKeyToPublicKey(callerPriavteKey) if err != nil { @@ -52,12 +71,6 @@ func HandleDBSelection(w http.ResponseWriter, r *http.Request) { return } - columnsNames, err := columns.GetSelectColumns(sqlCommand) - if err != nil { - services.NormalResponse(w, response.SQLResponseBadSQLStatement()) - return - } - result, err := services.HasTableUserRole(callerPriavteKey, callerAddress, tableName) if err != nil { services.NormalResponse(w, response.ResponseInternalError()) @@ -66,11 +79,22 @@ func HandleDBSelection(w http.ResponseWriter, r *http.Request) { switch result { case true: + columnsCanSelect, err := services.GetColumnsRole(callerPriavteKey, callerAddress, tableName) + if err != nil { services.NormalResponse(w, response.ResponseInternalError()) return } + + sqlCommand = checkSelectAll(sqlCommand, columnsCanSelect) + + columnsNames, err := columns.GetSelectColumns(sqlCommand) + if err != nil { + services.NormalResponse(w, response.SQLResponseBadSQLStatement()) + return + } + columnsAuth := utils.CompareColumns(columnsCanSelect, columnsNames) switch columnsAuth { From 8077abfce1141009923f94d14ba6adb8de11c7d8 Mon Sep 17 00:00:00 2001 From: yinghan Date: Fri, 22 May 2020 00:32:19 +0800 Subject: [PATCH 2/8] cleanup: Format source tree using `gofmt -w ...` --- package/utils/compare.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package/utils/compare.go b/package/utils/compare.go index 450a89f..a0e2b02 100644 --- a/package/utils/compare.go +++ b/package/utils/compare.go @@ -1,4 +1,5 @@ package utils + import ( "github.com/wxnacy/wgo/arrays" ) @@ -11,4 +12,4 @@ func CompareColumns(columnsPermission []string, columnsRequest []string) bool { } } return true -} \ No newline at end of file +} From f846b6ec83ff2eb12c760e7ae8633c148f1dfb1c Mon Sep 17 00:00:00 2001 From: yinghan Date: Fri, 22 May 2020 03:23:08 +0800 Subject: [PATCH 3/8] test(parser): Implement tests of parser for SELECT query --- package/parser/columns/select_test.go | 28 +++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 package/parser/columns/select_test.go diff --git a/package/parser/columns/select_test.go b/package/parser/columns/select_test.go new file mode 100644 index 0000000..4c3e69e --- /dev/null +++ b/package/parser/columns/select_test.go @@ -0,0 +1,28 @@ +package parser + +import ( + "reflect" + "testing" +) + +func TestGetSelectColumns(t *testing.T) { + var tests = []struct { + testName string + sqlCommand string + expectColumns []string + }{ + {"Asterisk", "SELECT * FROM t WHERE id = 1", []string{""}}, + {"Case", "SELECT QWERTYUIOPASDFGHJKLZXCVBNM, qwertyuiopasdfghjklzxcvbnm FROM t WHERE id = 1", + []string{"QWERTYUIOPASDFGHJKLZXCVBNM", "qwertyuiopasdfghjklzxcvbnm"}}, + {"Number", "SELECT num1234567890 FROM t WHERE id = 1", []string{"num1234567890"}}, + } + + for _, tt := range tests { + t.Run(tt.testName, func(t *testing.T) { + result, _ := GetSelectColumns(tt.sqlCommand) + if !reflect.DeepEqual(tt.expectColumns, result) { + t.Errorf("got %v, expect %v", result, tt.expectColumns) + } + }) + } +} From ece5c653b787b1a72c5d4f3648bd5add7d464274 Mon Sep 17 00:00:00 2001 From: yinghan Date: Fri, 22 May 2020 03:53:26 +0800 Subject: [PATCH 4/8] test(parser): Implement tests of parser for INSERT query --- package/parser/columns/insert_test.go | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 package/parser/columns/insert_test.go diff --git a/package/parser/columns/insert_test.go b/package/parser/columns/insert_test.go new file mode 100644 index 0000000..da0ef1d --- /dev/null +++ b/package/parser/columns/insert_test.go @@ -0,0 +1,27 @@ +package parser + +import ( + "reflect" + "testing" +) + +func TestGetInsertColumns(t *testing.T) { + var tests = []struct { + testName string + sqlCommand string + expectColumns []string + }{ + {"Case", "INSERT INTO t (QWERTYUIOPASDFGHJKLZXCVBNM, qwertyuiopasdfghjklzxcvbnm) VALUES(`aaa`,`bbb`)", + []string{"QWERTYUIOPASDFGHJKLZXCVBNM", "qwertyuiopasdfghjklzxcvbnm"}}, + {"Number", "INSERT INTO t (num1234567890) VALUES (1)", []string{"num1234567890"}}, + } + + for _, tt := range tests { + t.Run(tt.testName, func(t *testing.T) { + result, _ := GetInsertColumns(tt.sqlCommand) + if !reflect.DeepEqual(tt.expectColumns, result) { + t.Errorf("got %v, expect %v", result, tt.expectColumns) + } + }) + } +} From fe40b509fb619c412d76d0dfe0d1116d06c86303 Mon Sep 17 00:00:00 2001 From: yinghan Date: Tue, 26 May 2020 02:45:29 +0800 Subject: [PATCH 5/8] test(parser): Implement tests of parser for CREATE and UPDATE query --- package/parser/columns/create_test.go | 27 +++++++++++++++++++++++++++ package/parser/columns/update_test.go | 27 +++++++++++++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100644 package/parser/columns/create_test.go create mode 100644 package/parser/columns/update_test.go diff --git a/package/parser/columns/create_test.go b/package/parser/columns/create_test.go new file mode 100644 index 0000000..eca7c99 --- /dev/null +++ b/package/parser/columns/create_test.go @@ -0,0 +1,27 @@ +package parser + +import ( + "reflect" + "testing" +) + +func TestGetCreateColumns(t *testing.T) { + var tests = []struct { + testName string + sqlCommand string + expectColumns []string + }{ + {"Case", "CREATE TABLE t (QWERTYUIOPASDFGHJKLZXCVBNM INT PRIMARY KEY, qwertyuiopasdfghjklzxcvbnm INT);", + []string{"QWERTYUIOPASDFGHJKLZXCVBNM", "qwertyuiopasdfghjklzxcvbnm"}}, + {"Number", "CREATE TABLE t (num1234567890 INT PRIMARY KEY);", []string{"num1234567890"}}, + } + + for _, tt := range tests { + t.Run(tt.testName, func(t *testing.T) { + result, _ := GetCreateColumns(tt.sqlCommand) + if !reflect.DeepEqual(tt.expectColumns, result) { + t.Errorf("got %v, expect %v", result, tt.expectColumns) + } + }) + } +} diff --git a/package/parser/columns/update_test.go b/package/parser/columns/update_test.go new file mode 100644 index 0000000..9109d51 --- /dev/null +++ b/package/parser/columns/update_test.go @@ -0,0 +1,27 @@ +package parser + +import ( + "reflect" + "testing" +) + +func TestGetUpdateColumns(t *testing.T) { + var tests = []struct { + testName string + sqlCommand string + expectColumns []string + }{ + {"Case", "UPDATE t set QWERTYUIOPASDFGHJKLZXCVBNM = `ABC` , qwertyuiopasdfghjklzxcvbnm = `abc` WHERE id = 1", + []string{"QWERTYUIOPASDFGHJKLZXCVBNM", "qwertyuiopasdfghjklzxcvbnm"}}, + {"Number", "UPDATE t set num1234567890 = -1 WHERE id = 1", []string{"num1234567890"}}, + } + + for _, tt := range tests { + t.Run(tt.testName, func(t *testing.T) { + result, _ := GetUpdateColumns(tt.sqlCommand) + if !reflect.DeepEqual(tt.expectColumns, result) { + t.Errorf("got %v, expect %v", result, tt.expectColumns) + } + }) + } +} From c935b05da2f647129a543cb40075ef766dde5019 Mon Sep 17 00:00:00 2001 From: yinghan Date: Tue, 26 May 2020 03:07:57 +0800 Subject: [PATCH 6/8] test(parser): Add tests for double quoted columns --- package/parser/columns/create_test.go | 4 +++- package/parser/columns/insert_test.go | 4 +++- package/parser/columns/select_test.go | 4 +++- package/parser/columns/update_test.go | 4 +++- 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/package/parser/columns/create_test.go b/package/parser/columns/create_test.go index eca7c99..915e397 100644 --- a/package/parser/columns/create_test.go +++ b/package/parser/columns/create_test.go @@ -11,8 +11,10 @@ func TestGetCreateColumns(t *testing.T) { sqlCommand string expectColumns []string }{ - {"Case", "CREATE TABLE t (QWERTYUIOPASDFGHJKLZXCVBNM INT PRIMARY KEY, qwertyuiopasdfghjklzxcvbnm INT);", + {"DoubleQuoted", "CREATE TABLE t (\"QWERTYUIOPASDFGHJKLZXCVBNM\" INT PRIMARY KEY, \"qwertyuiopasdfghjklzxcvbnm\" INT);", []string{"QWERTYUIOPASDFGHJKLZXCVBNM", "qwertyuiopasdfghjklzxcvbnm"}}, + {"NoQuoted", "CREATE TABLE t (QWERTYUIOPASDFGHJKLZXCVBNM INT PRIMARY KEY, qwertyuiopasdfghjklzxcvbnm INT);", + []string{"qwertyuiopasdfghjklzxcvbnm", "qwertyuiopasdfghjklzxcvbnm"}}, {"Number", "CREATE TABLE t (num1234567890 INT PRIMARY KEY);", []string{"num1234567890"}}, } diff --git a/package/parser/columns/insert_test.go b/package/parser/columns/insert_test.go index da0ef1d..86ce746 100644 --- a/package/parser/columns/insert_test.go +++ b/package/parser/columns/insert_test.go @@ -11,8 +11,10 @@ func TestGetInsertColumns(t *testing.T) { sqlCommand string expectColumns []string }{ - {"Case", "INSERT INTO t (QWERTYUIOPASDFGHJKLZXCVBNM, qwertyuiopasdfghjklzxcvbnm) VALUES(`aaa`,`bbb`)", + {"DoubleQuoted", "INSERT INTO t (\"QWERTYUIOPASDFGHJKLZXCVBNM\", \"qwertyuiopasdfghjklzxcvbnm\") VALUES(`aaa`,`bbb`)", []string{"QWERTYUIOPASDFGHJKLZXCVBNM", "qwertyuiopasdfghjklzxcvbnm"}}, + {"NoQuoted", "INSERT INTO t (QWERTYUIOPASDFGHJKLZXCVBNM, qwertyuiopasdfghjklzxcvbnm) VALUES(`aaa`,`bbb`)", + []string{"qwertyuiopasdfghjklzxcvbnm", "qwertyuiopasdfghjklzxcvbnm"}}, {"Number", "INSERT INTO t (num1234567890) VALUES (1)", []string{"num1234567890"}}, } diff --git a/package/parser/columns/select_test.go b/package/parser/columns/select_test.go index 4c3e69e..5d1cc3e 100644 --- a/package/parser/columns/select_test.go +++ b/package/parser/columns/select_test.go @@ -12,8 +12,10 @@ func TestGetSelectColumns(t *testing.T) { expectColumns []string }{ {"Asterisk", "SELECT * FROM t WHERE id = 1", []string{""}}, - {"Case", "SELECT QWERTYUIOPASDFGHJKLZXCVBNM, qwertyuiopasdfghjklzxcvbnm FROM t WHERE id = 1", + {"DoubleQuoted", "SELECT \"QWERTYUIOPASDFGHJKLZXCVBNM\", \"qwertyuiopasdfghjklzxcvbnm\" FROM t WHERE id = 1", []string{"QWERTYUIOPASDFGHJKLZXCVBNM", "qwertyuiopasdfghjklzxcvbnm"}}, + {"NoQuoted", "SELECT QWERTYUIOPASDFGHJKLZXCVBNM, qwertyuiopasdfghjklzxcvbnm FROM t WHERE id = 1", + []string{"qwertyuiopasdfghjklzxcvbnm", "qwertyuiopasdfghjklzxcvbnm"}}, {"Number", "SELECT num1234567890 FROM t WHERE id = 1", []string{"num1234567890"}}, } diff --git a/package/parser/columns/update_test.go b/package/parser/columns/update_test.go index 9109d51..a3192ae 100644 --- a/package/parser/columns/update_test.go +++ b/package/parser/columns/update_test.go @@ -11,8 +11,10 @@ func TestGetUpdateColumns(t *testing.T) { sqlCommand string expectColumns []string }{ - {"Case", "UPDATE t set QWERTYUIOPASDFGHJKLZXCVBNM = `ABC` , qwertyuiopasdfghjklzxcvbnm = `abc` WHERE id = 1", + {"DoubleQuoted", "UPDATE t set \"QWERTYUIOPASDFGHJKLZXCVBNM\" = `ABC` , \"qwertyuiopasdfghjklzxcvbnm\" = `abc` WHERE id = 1", []string{"QWERTYUIOPASDFGHJKLZXCVBNM", "qwertyuiopasdfghjklzxcvbnm"}}, + {"NoQuoted", "UPDATE t set QWERTYUIOPASDFGHJKLZXCVBNM = `ABC` , qwertyuiopasdfghjklzxcvbnm = `abc` WHERE id = 1", + []string{"qwertyuiopasdfghjklzxcvbnm", "qwertyuiopasdfghjklzxcvbnm"}}, {"Number", "UPDATE t set num1234567890 = -1 WHERE id = 1", []string{"num1234567890"}}, } From c0b4d70fe87a1e68eabf016dcd30e3f5012b8f2d Mon Sep 17 00:00:00 2001 From: yinghan Date: Tue, 26 May 2020 03:34:08 +0800 Subject: [PATCH 7/8] fix(parser): Remove quotes around columns after parsing close #10 --- package/parser/columns/create.go | 2 +- package/parser/columns/insert.go | 2 +- package/parser/columns/select.go | 2 +- package/parser/columns/update.go | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package/parser/columns/create.go b/package/parser/columns/create.go index e59637a..b3bc439 100644 --- a/package/parser/columns/create.go +++ b/package/parser/columns/create.go @@ -38,7 +38,7 @@ func GetCreateColumns(sqlCommand string) ([]string, error) { json.Unmarshal(statement, &newStatement) for i := 0; i < len(newStatement.RawStmt.Stmt.CreateStmt.TableElts); i++ { statementString, _ := json.Marshal(newStatement.RawStmt.Stmt.CreateStmt.TableElts[i].Col.Name) - columnNames = append(columnNames, string(statementString)) + columnNames = append(columnNames, string(statementString[1:len(statementString)-1])) } return columnNames, nil diff --git a/package/parser/columns/insert.go b/package/parser/columns/insert.go index 47cc76f..200bed8 100644 --- a/package/parser/columns/insert.go +++ b/package/parser/columns/insert.go @@ -39,7 +39,7 @@ func GetInsertColumns(sqlCommand string) ([]string, error) { json.Unmarshal(statement, &newStatement) for i := 0; i < len(newStatement.RawStmt.Stmt.InsertStmt.Cols); i++ { statementString, _ := json.Marshal(newStatement.RawStmt.Stmt.InsertStmt.Cols[i].Col.Name) - columnNames = append(columnNames, string(statementString)) + columnNames = append(columnNames, string(statementString[1:len(statementString)-1])) } return columnNames, nil diff --git a/package/parser/columns/select.go b/package/parser/columns/select.go index bdace42..3d4239a 100644 --- a/package/parser/columns/select.go +++ b/package/parser/columns/select.go @@ -49,7 +49,7 @@ func GetSelectColumns(sqlCommand string) ([]string, error) { json.Unmarshal(statement, &newStatement) for i := 0; i < len(newStatement.RawStmt.Stmt.SelectStmt.TargetList); i++ { statementString, _ := json.Marshal(newStatement.RawStmt.Stmt.SelectStmt.TargetList[i].ResTarget.Val.ColumnRef.Fields[0].Col.Name) - columnNames = append(columnNames, string(statementString)) + columnNames = append(columnNames, string(statementString[1:len(statementString)-1])) } return columnNames, nil diff --git a/package/parser/columns/update.go b/package/parser/columns/update.go index 6afa2fe..833b0a6 100644 --- a/package/parser/columns/update.go +++ b/package/parser/columns/update.go @@ -39,7 +39,7 @@ func GetUpdateColumns(sqlCommand string) ([]string, error) { json.Unmarshal(statement, &newStatement) for i := 0; i < len(newStatement.RawStmt.Stmt.UpdateStmt.Cols); i++ { statementString, _ := json.Marshal(newStatement.RawStmt.Stmt.UpdateStmt.Cols[i].Col.Name) - columnNames = append(columnNames, string(statementString)) + columnNames = append(columnNames, string(statementString[1:len(statementString)-1])) } return columnNames, nil From 9844f14ce664909a7d0ba5f98b2876d382cc6389 Mon Sep 17 00:00:00 2001 From: yinghan Date: Tue, 26 May 2020 10:53:04 +0800 Subject: [PATCH 8/8] fix(api): Remove additional quotes around authorizing columns --- controller/role/create.go | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/controller/role/create.go b/controller/role/create.go index d222ec2..2e0dfbe 100644 --- a/controller/role/create.go +++ b/controller/role/create.go @@ -2,16 +2,13 @@ package controller import ( "encoding/json" - "io/ioutil" - "strconv" - - "net/http" - "github.com/DropKit/DropKit-Adapter/constants" "github.com/DropKit/DropKit-Adapter/logger" "github.com/DropKit/DropKit-Adapter/package/crypto/account" "github.com/DropKit/DropKit-Adapter/package/response" "github.com/DropKit/DropKit-Adapter/services" + "io/ioutil" + "net/http" ) func CreateColumnRole(w http.ResponseWriter, r *http.Request) { @@ -47,7 +44,7 @@ func CreateColumnRole(w http.ResponseWriter, r *http.Request) { columnsList := []string{} for _, column := range columns { - columnsList = append(columnsList, strconv.Quote(column)) + columnsList = append(columnsList, column) } result, err := services.HasTableMaintainerRole(callerPriavteKey, callerAddress, tableName)