klesh commented on code in PR #1994:
URL: https://github.com/apache/incubator-devlake/pull/1994#discussion_r886318204
##########
plugins/gitlab/tasks/api_client.go:
##########
@@ -54,7 +54,7 @@ func NewGitlabApiClient(taskCtx core.TaskContext)
(*helper.ApiAsyncClient, error
}
apiClient.SetAfterFunction(func(res *http.Response) error {
if res.StatusCode == http.StatusUnauthorized {
- return fmt.Errorf("authentication failed, please check
your Basic Auth Token")
+ return fmt.Errorf("authentication failed, please check
your Basic Auth AccessToken")
Review Comment:
Same as above
##########
plugins/jira/api/connection.go:
##########
@@ -309,12 +203,12 @@ func ListConnections(input *core.ApiResourceInput)
(*core.ApiResourceOutput, err
if err != nil {
return nil, err
}
- encKey, err := getEncKey()
+ encKey, err := helper.GetEncKey()
if err != nil {
return nil, err
}
for i := range jiraConnections {
Review Comment:
Looks like this logic should be moved to helper function
##########
plugins/feishu/tasks/api_client.go:
##########
@@ -92,7 +92,7 @@ func NewFeishuApiClient(taskCtx core.TaskContext)
(*helper.ApiAsyncClient, error
apiClient.SetAfterFunction(func(res *http.Response) error {
if res.StatusCode == http.StatusUnauthorized {
- return fmt.Errorf("feishu authentication failed, please
check your Bearer Auth Token")
+ return fmt.Errorf("feishu authentication failed, please
check your Bearer Auth AccessToken")
Review Comment:
Doesn't sound right, maybe remove 'Bearer Auth'?
##########
plugins/helper/connection.go:
##########
@@ -0,0 +1,191 @@
+package helper
+
+import (
+ "encoding/base64"
+ "fmt"
+ "github.com/apache/incubator-devlake/config"
+ "github.com/apache/incubator-devlake/models/common"
+ "github.com/apache/incubator-devlake/plugins/core"
+ "github.com/go-playground/validator/v10"
+ "github.com/mitchellh/mapstructure"
+ "gorm.io/gorm"
+ "gorm.io/gorm/clause"
+ "reflect"
+ "strconv"
+)
+
+type BaseConnection struct {
+ Name string `gorm:"type:varchar(100);uniqueIndex" json:"name"
validate:"required"`
+ common.Model
+}
+
+type BasicAuth struct {
+ Username string `mapstructure:"username" validate:"required"
json:"username"`
+ Password string `mapstructure:"password" validate:"required"
json:"password" encrypt:"yes"`
+}
+
+func (ba BasicAuth) GetEncodedToken() string {
+ return base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%v:%v",
ba.Username, ba.Password)))
+}
+
+type AccessToken struct {
+ Token string `mapstructure:"token" validate:"required" json:"token"
encrypt:"yes"`
+}
+
+type RestConnection struct {
+ BaseConnection `mapstructure:",squash"`
+ Endpoint string `mapstructure:"endpoint" validate:"required"
json:"endpoint"`
+ Proxy string `mapstructure:"proxy" json:"proxy"`
+ RateLimit int `comment:"api request rate limt per hour"
json:"rateLimit"`
+}
+
+// RefreshAndSaveConnection populate from request input into connection which
come from REST functions to connection struct and save to DB
+// and only change value which `data` has
+// mergeFieldsToConnection merges fields from data
+// `connection` is the pointer of a plugin connection
+// `data` is http request input param
+func RefreshAndSaveConnection(connection interface{}, data
map[string]interface{}, db *gorm.DB) error {
+ var err error
+ // update fields from request body
+ err = mergeFieldsToConnection(connection, data)
+ if err != nil {
+ return err
+ }
+
+ err = saveToDb(connection, db)
+
+ if err != nil {
+ return err
+ }
+ return nil
+}
+
+func saveToDb(connection interface{}, db *gorm.DB) error {
+ dataVal := reflect.ValueOf(connection)
+ if dataVal.Kind() != reflect.Ptr {
+ panic("entityPtr is not a pointer")
+ }
+
+ encryptCode, err := GetEncKey()
+ if err != nil {
+ return err
+ }
+ dataType := reflect.Indirect(dataVal).Type()
+ fieldName := getEncryptField(dataType, "encrypt")
+ plainPwd := ""
+ if len(fieldName) > 0 {
+ plainPwd = dataVal.Elem().FieldByName(fieldName).String()
+ encyptedStr, err := core.Encrypt(encryptCode, plainPwd)
+
+ if err != nil {
+ return err
+ }
+
dataVal.Elem().FieldByName(fieldName).Set(reflect.ValueOf(encyptedStr))
+ }
+
+ err = db.Clauses(clause.OnConflict{UpdateAll:
true}).Save(connection).Error
+ if err != nil {
+ return err
+ }
+
+ dataVal.Elem().FieldByName(fieldName).Set(reflect.ValueOf(plainPwd))
+
+ return err
+}
+
+// mergeFieldsToConnection will populate all value in map to connection struct
and validate the struct
+func mergeFieldsToConnection(specificConnection interface{}, connections
...map[string]interface{}) error {
+ // decode
+ for _, connection := range connections {
+ err := mapstructure.Decode(connection, specificConnection)
+ if err != nil {
+ return err
+ }
+ }
+ // validate
+ vld := validator.New()
+ err := vld.Struct(specificConnection)
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+
+func GetEncKey() (string, error) {
+ // encrypt
+ v := config.GetConfig()
+ encKey := v.GetString(core.EncodeKeyEnvStr)
+ if encKey == "" {
+ // Randomly generate a bunch of encryption keys and set them to
config
+ encKey = core.RandomEncKey()
+ v.Set(core.EncodeKeyEnvStr, encKey)
+ err := config.WriteConfig(v)
+ if err != nil {
+ return encKey, err
+ }
+ }
+ return encKey, nil
+}
+
+func FindAuthConnectionByInput(input *core.ApiResourceInput, connection
interface{}, db *gorm.DB) error {
+ dataVal := reflect.ValueOf(connection)
+ if dataVal.Kind() != reflect.Ptr {
+ return fmt.Errorf("connection is not a pointer")
+ }
+
+ id, err := GetConnectionIdByInputParam(input)
+ if err != nil {
+ return fmt.Errorf("invalid connectionId")
+ }
+
+ err = db.First(connection, id).Error
+ if err != nil {
+ fmt.Printf("--- %s", err.Error())
+ return err
+ }
+
+ encryptCode, err := GetEncKey()
+ if err != nil {
+ return err
+ }
+ dataType := reflect.Indirect(dataVal).Type()
+
+ fieldName := getEncryptField(dataType, "encrypt")
+ if len(fieldName) > 0 {
+ decryptStr, err := core.Decrypt(encryptCode,
dataVal.Elem().FieldByName(fieldName).String())
+ if err != nil {
+ return err
Review Comment:
We should swallow this error, due to
https://github.com/apache/incubator-devlake/issues/2032 , oh, man, it was
reviewed by you.
##########
plugins/jira/models/connection.go:
##########
@@ -28,9 +28,9 @@ type EpicResponse struct {
}
type TestConnectionRequest struct {
- Endpoint string `json:"endpoint"`
- Auth string `json:"auth"`
- Proxy string `json:"proxy"`
+ Endpoint string `json:"endpoint"`
+ Proxy string `json:"proxy"`
+ helper.BasicAuth `mapstructure:",squash" encrypt:"yes"`
Review Comment:
Why do we need encryption for TestConnection when we don't need to store
them into database?
##########
plugins/jira/models/connection.go:
##########
@@ -40,15 +40,11 @@ type BoardResponse struct {
}
type JiraConnection struct {
- common.Model
- Name string `gorm:"type:varchar(100);uniqueIndex"
json:"name" validate:"required"`
- Endpoint string `json:"endpoint" validate:"required"`
- BasicAuthEncoded string `json:"basicAuthEncoded"
validate:"required"`
+ helper.RestConnection `mapstructure:",squash"`
+ helper.BasicAuth `mapstructure:",squash" encrypt:"yes"`
Review Comment:
Does `encrypt:"yes"` mean we gonna encrypt the whole struct?
##########
plugins/jira/models/migrationscripts/updateSchemas20220524.go:
##########
@@ -0,0 +1,72 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements. See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package migrationscripts
+
+import (
+ "context"
+ "github.com/apache/incubator-devlake/plugins/helper"
+ "gorm.io/gorm"
+)
+
+type JiraConnection20220524 struct {
+ helper.RestConnection
+ helper.BasicAuth
+ EpicKeyField string `gorm:"type:varchar(50);"
json:"epicKeyField"`
+ StoryPointField string `gorm:"type:varchar(50);"
json:"storyPointField"`
+ RemotelinkCommitShaPattern string
`gorm:"type:varchar(255);comment='golang regexp, the first group will be
recognized as commit sha, ref https://github.com/google/re2/wiki/Syntax'"
json:"remotelinkCommitShaPattern"`
+}
+
+func (JiraConnection20220524) TableName() string {
+ return "_tool_jira_connections"
+}
+
+type UpdateSchemas20220524 struct{}
+
+func (*UpdateSchemas20220524) Up(ctx context.Context, db *gorm.DB) error {
+ var err error
+ if !db.Migrator().HasColumn(&JiraConnection20220505{}, "password") {
+ err = db.Migrator().AddColumn(&JiraConnection20220524{},
"password")
+ if err != nil {
+ return err
+ }
+ }
+
+ if !db.Migrator().HasColumn(&JiraConnection20220505{}, "username") {
+ err = db.Migrator().AddColumn(&JiraConnection20220524{},
"username")
+ if err != nil {
+ return err
+ }
+ }
+
+ if db.Migrator().HasColumn(&JiraConnection20220505{},
"basic_auth_encoded") {
+ err = db.Migrator().DropColumn(&JiraConnection20220505{},
"basic_auth_encoded")
+ if err != nil {
+ return err
+ }
+ }
+
+ return nil
Review Comment:
I think we have to decode the `basic_auth_encoed` and spread them into
username/password accordingly before we drop them.
##########
plugins/jira/api/proxy.go:
##########
@@ -48,7 +49,14 @@ func Proxy(input *core.ApiResourceInput)
(*core.ApiResourceOutput, error) {
return nil, err
}
encKey := cfg.GetString(core.EncodeKeyEnvStr)
- basicAuth, err := core.Decrypt(encKey, jiraConnection.BasicAuthEncoded)
+
+ decodedPassword, err := core.Decrypt(encKey, jiraConnection.Password)
Review Comment:
Why not utilize `FindAuthConnectionByInput` ? and why it is called
`FindAuthConnectionByInput`? What doesn't `Auth` stand for?
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]