This is an automated email from the ASF dual-hosted git repository.

warren pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/incubator-devlake.git

commit 1980cb39b70c92e117b84d84e1801b3a39dc543c
Author: Yingchu Chen <[email protected]>
AuthorDate: Thu Jun 2 16:57:24 2022 +0800

    minor fixes
    
    Signed-off-by: Yingchu Chen <[email protected]>
---
 .../pages/configure/connections/ConnectionForm.jsx |   4 +-
 config-ui/webpack.config.js                        |  18 ++-
 config-ui/webpack.production.config.js             |  18 ++-
 plugins/gitlab/gitlab.go                           |   3 +
 plugins/helper/connection.go                       | 118 +++++++++-------
 plugins/helper/connection_test.go                  | 108 +++++++-------
 plugins/helper/worker_scheduler_test.go            |   2 +-
 plugins/jira/api/connection.go                     | 155 ++-------------------
 plugins/jira/api/init.go                           |   4 -
 plugins/jira/api/proxy.go                          |   2 +-
 plugins/jira/jira.go                               |   9 --
 plugins/jira/models/connection.go                  |  15 --
 .../migrationscripts/updateSchemas20220601.go      |   7 +-
 plugins/jira/tasks/api_client.go                   |   2 +-
 plugins/jira/tasks/apiv2models/issue.go            |  12 +-
 plugins/jira/tasks/issue_extractor.go              |   2 +-
 plugins/tapd/api/connection.go                     |  27 ----
 plugins/tapd/tapd.go                               |   8 +-
 runner/directrun.go                                |   3 +-
 19 files changed, 188 insertions(+), 329 deletions(-)

diff --git a/config-ui/src/pages/configure/connections/ConnectionForm.jsx 
b/config-ui/src/pages/configure/connections/ConnectionForm.jsx
index e5fe71d2..2e657c13 100644
--- a/config-ui/src/pages/configure/connections/ConnectionForm.jsx
+++ b/config-ui/src/pages/configure/connections/ConnectionForm.jsx
@@ -413,7 +413,7 @@ export default function ConnectionForm (props) {
                     ? labels.username
                     : (
                       <>Username</>
-                    )}
+                      )}
                   <span className='requiredStar'>*</span>
                 </Label>
                 <InputGroup
@@ -456,7 +456,7 @@ export default function ConnectionForm (props) {
                     ? labels.password
                     : (
                       <>Password</>
-                    )}
+                      )}
                   <span className='requiredStar'>*</span>
                 </Label>
                 <InputGroup
diff --git a/config-ui/webpack.config.js b/config-ui/webpack.config.js
index 5a253b25..51bd6a5f 100644
--- a/config-ui/webpack.config.js
+++ b/config-ui/webpack.config.js
@@ -1,4 +1,20 @@
-// DEVELOPMENT ONLY WEBPACK CONFIG
+/*
+ * 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.
+ *
+ */
 const path = require('path')
 const webpack = require('webpack')
 const BundleAnalyzerPlugin = 
require('webpack-bundle-analyzer').BundleAnalyzerPlugin
diff --git a/config-ui/webpack.production.config.js 
b/config-ui/webpack.production.config.js
index a8c34ae9..6989bd41 100644
--- a/config-ui/webpack.production.config.js
+++ b/config-ui/webpack.production.config.js
@@ -1,4 +1,20 @@
-/* eslint-disable import/no-extraneous-dependencies */
+/*
+ * 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.
+ *
+ */
 const path = require('path')
 const webpack = require('webpack')
 const BundleAnalyzerPlugin = 
require('webpack-bundle-analyzer').BundleAnalyzerPlugin
diff --git a/plugins/gitlab/gitlab.go b/plugins/gitlab/gitlab.go
index 7d2be2e5..e9a9f77d 100644
--- a/plugins/gitlab/gitlab.go
+++ b/plugins/gitlab/gitlab.go
@@ -41,6 +41,9 @@ func main() {
                }
                wsList := make([]*models.TapdWorkspace, 0)
                err = db.Find(&wsList, "parent_id = ?", 59169984).Error
+               if err != nil {
+                       panic(err)
+               }
                projectList := []uint64{63281714,
                        34276182,
                        46319043,
diff --git a/plugins/helper/connection.go b/plugins/helper/connection.go
index 17933a5c..30e9ab0d 100644
--- a/plugins/helper/connection.go
+++ b/plugins/helper/connection.go
@@ -1,3 +1,20 @@
+/*
+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 helper
 
 import (
@@ -21,7 +38,7 @@ type BaseConnection struct {
 
 type BasicAuth struct {
        Username string `mapstructure:"username" validate:"required" 
json:"username"`
-       Password string `mapstructure:"password" validate:"required" 
json:"password" encryptField:"yes"`
+       Password string `mapstructure:"password" validate:"required" 
json:"password" encrypt:"yes"`
 }
 
 func (ba BasicAuth) GetEncodedToken() string {
@@ -29,7 +46,7 @@ func (ba BasicAuth) GetEncodedToken() string {
 }
 
 type AccessToken struct {
-       Token string `mapstructure:"token" validate:"required" json:"token" 
encryptField:"yes"`
+       Token string `mapstructure:"token" validate:"required" json:"token" 
encrypt:"yes"`
 }
 
 type RestConnection struct {
@@ -39,55 +56,50 @@ type RestConnection struct {
        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
+// CreateConnection 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 {
+func CreateConnection(data map[string]interface{}, connection 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")
-       }
-       encKey, err := getEncKey()
+func PatchConnection(input *core.ApiResourceInput, connection interface{}, db 
*gorm.DB) error {
+       err := GetConnection(input.Params, connection, db)
        if err != nil {
                return err
        }
-       dataType := reflect.Indirect(dataVal).Type()
-       fieldName := firstFieldNameWithTag(dataType, "encryptField")
-       plainPwd := ""
-       err = encryptField(dataVal, fieldName, encKey)
+
+       err = CreateConnection(input.Body, connection, db)
        if err != nil {
                return err
        }
-       err = db.Clauses(clause.OnConflict{UpdateAll: 
true}).Save(connection).Error
+
+       return nil
+}
+
+func saveToDb(connection interface{}, db *gorm.DB) error {
+       err := EncryptConnection(connection)
        if err != nil {
                return err
        }
-
-       err = decryptField(dataVal, fieldName, encKey)
+       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
+       return DecryptConnection(connection)
 }
 
 // mergeFieldsToConnection will populate all value in map to connection struct 
and validate the struct
@@ -110,7 +122,6 @@ func mergeFieldsToConnection(specificConnection 
interface{}, connections ...map[
 }
 
 func getEncKey() (string, error) {
-       // encryptField
        v := config.GetConfig()
        encKey := v.GetString(core.EncodeKeyEnvStr)
        if encKey == "" {
@@ -125,34 +136,44 @@ func getEncKey() (string, error) {
        return encKey, nil
 }
 
-// FindConnectionByInput finds connection from db  by parsing request input 
and decrypt it
-func FindConnectionByInput(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)
+// GetConnection finds connection from db  by parsing request input and 
decrypt it
+func GetConnection(data map[string]string, connection interface{}, db 
*gorm.DB) error {
+       id, err := GetConnectionIdByInputParam(data)
        if err != nil {
                return fmt.Errorf("invalid connectionId")
        }
 
        err = db.First(connection, id).Error
        if err != nil {
-               fmt.Printf("--- %s", err.Error())
                return err
        }
 
-       dataType := reflect.Indirect(dataVal).Type()
+       return DecryptConnection(connection)
 
-       fieldName := firstFieldNameWithTag(dataType, "encryptField")
-       return decryptField(dataVal, fieldName, "")
+}
 
+// ListConnections returns all connections with password/token decrypted
+func ListConnections(connections interface{}, db *gorm.DB) error {
+       err := db.Find(connections).Error
+       connPtr := reflect.ValueOf(connections)
+       connVal := reflect.Indirect(connPtr)
+       if err != nil {
+               return err
+       }
+       for i := 0; i < connVal.Len(); i++ {
+               //connVal.Index(i) returns value of ith elem in connections, 
.Elem() reutrns the original elem
+               tmp := connVal.Index(i).Elem()
+               err = DecryptConnection(tmp.Addr().Interface())
+               if err != nil {
+                       return err
+               }
+       }
+       return nil
 }
 
 // GetConnectionIdByInputParam gets connectionId by parsing request input
-func GetConnectionIdByInputParam(input *core.ApiResourceInput) (uint64, error) 
{
-       connectionId := input.Params["connectionId"]
+func GetConnectionIdByInputParam(data map[string]string) (uint64, error) {
+       connectionId := data["connectionId"]
        if connectionId == "" {
                return 0, fmt.Errorf("missing connectionId")
        }
@@ -175,7 +196,7 @@ func firstFieldNameWithTag(t reflect.Type, tag string) 
string {
 }
 
 // DecryptConnection decrypts password/token field for connection
-func DecryptConnection(connection interface{}, fieldName string) error {
+func DecryptConnection(connection interface{}) error {
        dataVal := reflect.ValueOf(connection)
        if dataVal.Kind() != reflect.Ptr {
                panic("connection is not a pointer")
@@ -184,23 +205,26 @@ func DecryptConnection(connection interface{}, fieldName 
string) error {
        if err != nil {
                return nil
        }
-       if len(fieldName) == 0 {
-               dataType := reflect.Indirect(dataVal).Type()
-               fieldName = firstFieldNameWithTag(dataType, "encryptField")
-       }
-       return decryptField(dataVal, fieldName, encKey)
-}
-
-func decryptField(dataVal reflect.Value, fieldName string, encKey string) 
error {
+       dataType := reflect.Indirect(dataVal).Type()
+       fieldName := firstFieldNameWithTag(dataType, "encrypt")
        if len(fieldName) > 0 {
                decryptStr, _ := core.Decrypt(encKey, 
dataVal.Elem().FieldByName(fieldName).String())
-
                
dataVal.Elem().FieldByName(fieldName).Set(reflect.ValueOf(decryptStr))
        }
        return nil
 }
 
-func encryptField(dataVal reflect.Value, fieldName string, encKey string) 
error {
+func EncryptConnection(connection interface{}) error {
+       dataVal := reflect.ValueOf(connection)
+       if dataVal.Kind() != reflect.Ptr {
+               panic("connection is not a pointer")
+       }
+       encKey, err := getEncKey()
+       if err != nil {
+               return err
+       }
+       dataType := reflect.Indirect(dataVal).Type()
+       fieldName := firstFieldNameWithTag(dataType, "encrypt")
        if len(fieldName) > 0 {
                plainPwd := dataVal.Elem().FieldByName(fieldName).String()
                encyptedStr, err := core.Encrypt(encKey, plainPwd)
diff --git a/plugins/helper/connection_test.go 
b/plugins/helper/connection_test.go
index 606730f3..bd1c7cc2 100644
--- a/plugins/helper/connection_test.go
+++ b/plugins/helper/connection_test.go
@@ -18,24 +18,24 @@ limitations under the License.
 package helper
 
 import (
-       "github.com/apache/incubator-devlake/config"
-       "github.com/apache/incubator-devlake/plugins/core"
+       "github.com/stretchr/testify/assert"
        "reflect"
        "testing"
-
-       "github.com/stretchr/testify/assert"
 )
 
-type TestConnection struct {
+type MockConnection struct {
        RestConnection             `mapstructure:",squash"`
        BasicAuth                  `mapstructure:",squash"`
-       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 (MockConnection) TableName() string {
+       return "_tool_jira_connections"
+}
+
 func TestMergeFieldsToConnection(t *testing.T) {
-       v := &TestConnection{
+       v := &MockConnection{
                RestConnection: RestConnection{
                        BaseConnection: BaseConnection{
                                Name: "1",
@@ -48,8 +48,6 @@ func TestMergeFieldsToConnection(t *testing.T) {
                        Username: "4",
                        Password: "5",
                },
-               EpicKeyField:               "6",
-               StoryPointField:            "7",
                RemotelinkCommitShaPattern: "8",
        }
        data := make(map[string]interface{})
@@ -58,9 +56,7 @@ func TestMergeFieldsToConnection(t *testing.T) {
        data["Password"] = "5-5"
 
        err := mergeFieldsToConnection(v, data)
-       if err != nil {
-               return
-       }
+       assert.Nil(t, err)
 
        assert.Equal(t, "4-4", v.Username)
        assert.Equal(t, "2-2", v.Endpoint)
@@ -68,7 +64,7 @@ func TestMergeFieldsToConnection(t *testing.T) {
 }
 
 func TestDecryptAndEncrypt(t *testing.T) {
-       v := &TestConnection{
+       v := &MockConnection{
                RestConnection: RestConnection{
                        BaseConnection: BaseConnection{
                                Name: "1",
@@ -81,28 +77,21 @@ func TestDecryptAndEncrypt(t *testing.T) {
                        Username: "4",
                        Password: "5",
                },
-               EpicKeyField:               "6",
-               StoryPointField:            "7",
                RemotelinkCommitShaPattern: "8",
        }
-       dataVal := reflect.ValueOf(v)
-       encKey := "test"
-       err := encryptField(dataVal, "Password", encKey)
-       if err != nil {
-               return
-       }
+       err := EncryptConnection(v)
+       assert.Nil(t, err)
+
        assert.NotEqual(t, "5", v.Password)
-       err = decryptField(dataVal, "Password", encKey)
-       if err != nil {
-               return
-       }
+       err = DecryptConnection(v)
+       assert.Nil(t, err)
 
        assert.Equal(t, "5", v.Password)
 
 }
 
 func TestDecryptConnection(t *testing.T) {
-       v := &TestConnection{
+       v := &MockConnection{
                RestConnection: RestConnection{
                        BaseConnection: BaseConnection{
                                Name: "1",
@@ -115,46 +104,20 @@ func TestDecryptConnection(t *testing.T) {
                        Username: "4",
                        Password: "5",
                },
-               EpicKeyField:               "6",
-               StoryPointField:            "7",
                RemotelinkCommitShaPattern: "8",
        }
-       encKey, err := getEncKey()
-       if err != nil {
-               return
-       }
-       dataVal := reflect.ValueOf(v)
-       err = encryptField(dataVal, "Password", encKey)
-       if err != nil {
-               return
-       }
+       err := EncryptConnection(v)
+       assert.Nil(t, err)
+
        encryptedPwd := v.Password
-       err = DecryptConnection(v, "Password")
-       if err != nil {
-               return
-       }
+       err = DecryptConnection(v)
+       assert.Nil(t, err)
        assert.NotEqual(t, encryptedPwd, v.Password)
        assert.Equal(t, "5", v.Password)
 }
 
-func TestGetEncKey(t *testing.T) {
-       // encryptField
-       v := config.GetConfig()
-       encKey := v.GetString(core.EncodeKeyEnvStr)
-       str, err := getEncKey()
-       if err != nil {
-               return
-       }
-       if len(encKey) > 0 {
-               assert.Equal(t, encKey, str)
-       } else {
-               assert.NotEqual(t, 0, len(str))
-       }
-
-}
-
 func TestFirstFieldNameWithTag(t *testing.T) {
-       v := &TestConnection{
+       v := &MockConnection{
                RestConnection: RestConnection{
                        BaseConnection: BaseConnection{
                                Name: "1",
@@ -167,12 +130,37 @@ func TestFirstFieldNameWithTag(t *testing.T) {
                        Username: "4",
                        Password: "5",
                },
-               EpicKeyField:               "6",
                StoryPointField:            "7",
                RemotelinkCommitShaPattern: "8",
        }
        dataVal := reflect.ValueOf(v)
        dataType := reflect.Indirect(dataVal).Type()
-       fieldName := firstFieldNameWithTag(dataType, "encryptField")
+       fieldName := firstFieldNameWithTag(dataType, "encrypt")
        assert.Equal(t, "Password", fieldName)
 }
+
+//func TestListConnections(t *testing.T) {
+//     jiraConnections := make([]*MockConnection, 0)
+//     cfg := config.GetConfig()
+//     dbUrl := cfg.GetString("DB_URL")
+//     u, err := url.Parse(dbUrl)
+//     dbUrl = fmt.Sprintf("%s@tcp(%s)%s?%s", u.User.String(), u.Host, u.Path, 
u.RawQuery)
+//     dbConfig := &gorm.Config{
+//             Logger: gormLogger.New(
+//                     log.Default(),
+//                     gormLogger.Config{
+//                             SlowThreshold:             time.Second,      // 
Slow SQL threshold
+//                             LogLevel:                  gormLogger.Error, // 
Log level
+//                             IgnoreRecordNotFoundError: true,             // 
Ignore ErrRecordNotFound error for logger
+//                             Colorful:                  true,             // 
Disable color
+//                     },
+//             ),
+//             // most of our operation are in batch, this can improve 
performance
+//             PrepareStmt: true,
+//     }
+//     db, err := gorm.Open(mysql.Open(dbUrl), dbConfig)
+//
+//     err = ListConnections(&jiraConnections, db)
+//
+//     assert.Nil(t, err)
+//}
diff --git a/plugins/helper/worker_scheduler_test.go 
b/plugins/helper/worker_scheduler_test.go
index a3de7adb..4f65e7a0 100644
--- a/plugins/helper/worker_scheduler_test.go
+++ b/plugins/helper/worker_scheduler_test.go
@@ -88,7 +88,7 @@ func TestNewWorkerSchedulerWithoutSecond(t *testing.T) {
 func TestNewWorkerSchedulerWithPanic(t *testing.T) {
        testChannel := make(chan int, 100)
        ctx, cancel := context.WithCancel(context.Background())
-       s, _ := NewWorkerScheduler(1, 1, ctx)
+       s,_ := NewWorkerScheduler(1, 1, ctx)
        defer s.Release()
        _ = s.Submit(func() error {
                testChannel <- 1
diff --git a/plugins/jira/api/connection.go b/plugins/jira/api/connection.go
index aa94537a..0c422bbe 100644
--- a/plugins/jira/api/connection.go
+++ b/plugins/jira/api/connection.go
@@ -21,7 +21,6 @@ import (
        "fmt"
        "net/http"
        "net/url"
-       "strconv"
        "strings"
        "time"
 
@@ -103,19 +102,8 @@ POST /plugins/jira/connections
 {
        "name": "jira data connection name",
        "endpoint": "jira api endpoint, i.e. https://merico.atlassian.net/rest";,
-       "basicAuthEncoded": "generated by `echo -n <jira login email>:<jira 
token> | base64`",
-       "epicKeyField": "name of customfield of epic key",
-       "storyPointField": "name of customfield of story point",
-       "typeMappings": { // optional, send empty object to delete all 
typeMappings of the data connection
-               "userType": {
-                       "standardType": "devlake standard type",
-                       "statusMappings": {  // optional, send empt object to 
delete all status mapping for the user type
-                               "userStatus": {
-                                       "standardStatus": "devlake standard 
status"
-                               }
-                       }
-               }
-       }
+       "username": "username, usually should be email address",
+       "password": "jira api access token"
 }
 */
 func PostConnections(input *core.ApiResourceInput) (*core.ApiResourceOutput, 
error) {
@@ -123,7 +111,7 @@ func PostConnections(input *core.ApiResourceInput) 
(*core.ApiResourceOutput, err
        jiraConnection := &models.JiraConnection{}
 
        // update from request and save to database
-       err := helper.RefreshAndSaveConnection(jiraConnection, input.Body, db)
+       err := helper.CreateConnection(input.Body, jiraConnection, db)
        if err != nil {
                return nil, err
        }
@@ -136,31 +124,13 @@ PATCH /plugins/jira/connections/:connectionId
 {
        "name": "jira data connection name",
        "endpoint": "jira api endpoint, i.e. https://merico.atlassian.net/rest";,
-       "basicAuthEncoded": "generated by `echo -n <jira login email>:<jira 
token> | base64`",
-       "epicKeyField": "name of customfield of epic key",
-       "storyPointField": "name of customfield of story point",
-       "typeMappings": { // optional, send empty object to delete all 
typeMappings of the data connection
-               "userType": {
-                       "standardType": "devlake standard type",
-                       "statusMappings": {  // optional, send empt object to 
delete all status mapping for the user type
-                               "userStatus": {
-                                       "standardStatus": "devlake standard 
status"
-                               }
-                       }
-               }
-       }
+       "username": "username, usually should be email address",
+       "password": "jira api access token"
 }
 */
 func PatchConnection(input *core.ApiResourceInput) (*core.ApiResourceOutput, 
error) {
        jiraConnection := &models.JiraConnection{}
-       // load from db
-       err := helper.FindConnectionByInput(input, jiraConnection, db)
-       if err != nil {
-               return nil, err
-       }
-
-       // update from request and save to database
-       err = helper.RefreshAndSaveConnection(jiraConnection, input.Body, db)
+       err := helper.PatchConnection(input, jiraConnection, db)
        if err != nil {
                return nil, err
        }
@@ -173,7 +143,7 @@ DELETE /plugins/jira/connections/:connectionId
 */
 func DeleteConnection(input *core.ApiResourceInput) (*core.ApiResourceOutput, 
error) {
        // load from db
-       jiraConnectionID, err := helper.GetConnectionIdByInputParam(input)
+       jiraConnectionID, err := 
helper.GetConnectionIdByInputParam(input.Params)
        if err != nil {
                return nil, err
        }
@@ -182,15 +152,6 @@ func DeleteConnection(input *core.ApiResourceInput) 
(*core.ApiResourceOutput, er
        if err != nil {
                return nil, err
        }
-       err = db.Where("connection_id = ?", 
jiraConnectionID).Delete(&models.JiraIssueTypeMapping{}).Error
-       if err != nil {
-               return nil, err
-       }
-       err = db.Where("connection_id = ?", 
jiraConnectionID).Delete(&models.JiraIssueStatusMapping{}).Error
-       if err != nil {
-               return nil, err
-       }
-
        return &core.ApiResourceOutput{Body: jiraConnectionID}, nil
 }
 
@@ -199,17 +160,11 @@ GET /plugins/jira/connections
 */
 func ListConnections(input *core.ApiResourceInput) (*core.ApiResourceOutput, 
error) {
        jiraConnections := make([]*models.JiraConnection, 0)
-       err := db.Find(&jiraConnections).Error
+
+       err := helper.ListConnections(&jiraConnections, db)
        if err != nil {
                return nil, err
        }
-       for i, _ := range jiraConnections {
-               err = helper.DecryptConnection(jiraConnections[i], "Password")
-               if err != nil {
-                       return nil, err
-               }
-       }
-
        return &core.ApiResourceOutput{Body: jiraConnections, Status: 
http.StatusOK}, nil
 }
 
@@ -220,100 +175,16 @@ GET /plugins/jira/connections/:connectionId
 {
        "name": "jira data connection name",
        "endpoint": "jira api endpoint, i.e. https://merico.atlassian.net/rest";,
-       "basicAuthEncoded": "generated by `echo -n <jira login email>:<jira 
token> | base64`",
-       "epicKeyField": "name of customfield of epic key",
-       "storyPointField": "name of customfield of story point",
-       "typeMappings": { // optional, send empty object to delete all 
typeMappings of the data connection
-               "userType": {
-                       "standardType": "devlake standard type",
-                       "statusMappings": {  // optional, send empt object to 
delete all status mapping for the user type
-                               "userStatus": {
-                                       "standardStatus": "devlake standard 
status"
-                               }
-                       }
-               }
-       }
+       "username": "username, usually should be email address",
+       "password": "jira api access token"
 }
 */
 func GetConnection(input *core.ApiResourceInput) (*core.ApiResourceOutput, 
error) {
        jiraConnection := &models.JiraConnection{}
-       err := helper.FindConnectionByInput(input, jiraConnection, db)
+       err := helper.GetConnection(input.Params, jiraConnection, db)
        if err != nil {
                return nil, err
        }
 
-       detail := &models.JiraConnectionDetail{
-               JiraConnection: *jiraConnection,
-       }
-
-       if err != nil {
-               return nil, err
-       }
-
-       return &core.ApiResourceOutput{Body: detail}, nil
-}
-
-// GET /plugins/jira/connections/:connectionId/epics
-func GetEpicsByConnectionId(input *core.ApiResourceInput) 
(*core.ApiResourceOutput, error) {
-       jiraConnection := &models.JiraConnection{}
-       err := helper.FindConnectionByInput(input, jiraConnection, db)
-       if err != nil {
-               return nil, err
-       }
-       return &core.ApiResourceOutput{Body: [1]models.EpicResponse{{
-               Id:    1,
-               Title: jiraConnection.EpicKeyField,
-               Value: jiraConnection.EpicKeyField,
-       }}}, nil
-}
-
-// GET /plugins/jira/connections/:connectionId/granularities
-type GranularitiesResponse struct {
-       Id    int
-       Title string
-       Value string
-}
-
-func GetGranularitiesByConnectionId(input *core.ApiResourceInput) 
(*core.ApiResourceOutput, error) {
-       jiraConnection := &models.JiraConnection{}
-       err := helper.FindConnectionByInput(input, jiraConnection, db)
-       if err != nil {
-               return nil, err
-       }
-       if err != nil {
-               return nil, err
-       }
-       return &core.ApiResourceOutput{Body: [1]GranularitiesResponse{
-               {
-                       Id:    1,
-                       Title: "Story Point Field",
-                       Value: jiraConnection.StoryPointField,
-               },
-       }}, nil
-}
-
-// GET /plugins/jira/connections/:connectionId/boards
-func GetBoardsByConnectionId(input *core.ApiResourceInput) 
(*core.ApiResourceOutput, error) {
-       connectionId := input.Params["connectionId"]
-       if connectionId == "" {
-               return nil, fmt.Errorf("missing connectionid")
-       }
-       jiraConnectionId, err := strconv.ParseUint(connectionId, 10, 64)
-       if err != nil {
-               return nil, fmt.Errorf("invalid connectionId")
-       }
-       var jiraBoards []models.JiraBoard
-       err = db.Where("connection_Id = ?", 
jiraConnectionId).Find(&jiraBoards).Error
-       if err != nil {
-               return nil, err
-       }
-       var boardResponses []models.BoardResponse
-       for _, board := range jiraBoards {
-               boardResponses = append(boardResponses, models.BoardResponse{
-                       Id:    int(board.BoardId),
-                       Title: board.Name,
-                       Value: fmt.Sprintf("%v", board.BoardId),
-               })
-       }
-       return &core.ApiResourceOutput{Body: boardResponses}, nil
+       return &core.ApiResourceOutput{Body: jiraConnection}, nil
 }
diff --git a/plugins/jira/api/init.go b/plugins/jira/api/init.go
index 663d5033..acaa495e 100644
--- a/plugins/jira/api/init.go
+++ b/plugins/jira/api/init.go
@@ -24,11 +24,7 @@ import (
 )
 
 var db *gorm.DB
-var cfg *viper.Viper
-var log core.Logger
 
 func Init(config *viper.Viper, logger core.Logger, database *gorm.DB) {
        db = database
-       cfg = config
-       log = logger
 }
diff --git a/plugins/jira/api/proxy.go b/plugins/jira/api/proxy.go
index e4a3eb90..398f4f1f 100644
--- a/plugins/jira/api/proxy.go
+++ b/plugins/jira/api/proxy.go
@@ -35,7 +35,7 @@ const (
 
 func Proxy(input *core.ApiResourceInput) (*core.ApiResourceOutput, error) {
        jiraConnection := &models.JiraConnection{}
-       err := helper.FindConnectionByInput(input, jiraConnection, db)
+       err := helper.GetConnection(input.Params, jiraConnection, db)
        if err != nil {
                return nil, err
        }
diff --git a/plugins/jira/jira.go b/plugins/jira/jira.go
index a36177da..37313972 100644
--- a/plugins/jira/jira.go
+++ b/plugins/jira/jira.go
@@ -176,15 +176,6 @@ func (plugin Jira) ApiResources() 
map[string]map[string]core.ApiResourceHandler
                        "DELETE": api.DeleteConnection,
                        "GET":    api.GetConnection,
                },
-               "connections/:connectionId/epics": {
-                       "GET": api.GetEpicsByConnectionId,
-               },
-               "connections/:connectionId/granularities": {
-                       "GET": api.GetGranularitiesByConnectionId,
-               },
-               "connections/:connectionId/boards": {
-                       "GET": api.GetBoardsByConnectionId,
-               },
                "connections/:connectionId/proxy/rest/*path": {
                        "GET": api.Proxy,
                },
diff --git a/plugins/jira/models/connection.go 
b/plugins/jira/models/connection.go
index f1ed2f8a..fa0664f6 100644
--- a/plugins/jira/models/connection.go
+++ b/plugins/jira/models/connection.go
@@ -42,8 +42,6 @@ type BoardResponse struct {
 type JiraConnection struct {
        helper.RestConnection      `mapstructure:",squash"`
        helper.BasicAuth           `mapstructure:",squash"`
-       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"`
 }
 
@@ -60,19 +58,6 @@ type JiraIssueStatusMapping struct {
        StandardStatus string `gorm:"type:varchar(50)" json:"standardStatus" 
validate:"required"`
 }
 
-type JiraConnectionDetail struct {
-       JiraConnection
-       TypeMappings map[string]map[string]interface{} `json:"typeMappings"`
-}
-
 func (JiraConnection) TableName() string {
        return "_tool_jira_connections"
 }
-
-func (JiraIssueTypeMapping) TableName() string {
-       return "_tool_jira_issue_type_mappings"
-}
-
-func (JiraIssueStatusMapping) TableName() string {
-       return "_tool_jira_issue_status_mappings"
-}
diff --git a/plugins/jira/models/migrationscripts/updateSchemas20220601.go 
b/plugins/jira/models/migrationscripts/updateSchemas20220601.go
index ec528dcb..24d3786c 100644
--- a/plugins/jira/models/migrationscripts/updateSchemas20220601.go
+++ b/plugins/jira/models/migrationscripts/updateSchemas20220601.go
@@ -58,9 +58,12 @@ func (*UpdateSchemas20220601) Up(ctx context.Context, db 
*gorm.DB) error {
 
        if db.Migrator().HasColumn(&JiraConnection20220505{}, 
"basic_auth_encoded") {
                connections := make([]*JiraConnection20220505, 0)
-               db.Find(&connections)
+               err = db.Find(&connections).Error
+               if err != nil {
+                       return err
+               }
                for i, _ := range connections {
-                       err = helper.DecryptConnection(connections[i], 
"BasicAuthEncoded")
+                       err = helper.DecryptConnection(connections[i])
                        if err != nil {
                                return err
                        }
diff --git a/plugins/jira/tasks/api_client.go b/plugins/jira/tasks/api_client.go
index 811c0b6a..b44b024b 100644
--- a/plugins/jira/tasks/api_client.go
+++ b/plugins/jira/tasks/api_client.go
@@ -28,7 +28,7 @@ import (
 
 func NewJiraApiClient(taskCtx core.TaskContext, connection 
*models.JiraConnection) (*helper.ApiAsyncClient, error) {
        // decrypt connection first
-       err := helper.DecryptConnection(connection, "Password")
+       err := helper.DecryptConnection(connection)
        if err != nil {
                return nil, fmt.Errorf("Failed to decrypt Auth AccessToken: 
%w", err)
        }
diff --git a/plugins/jira/tasks/apiv2models/issue.go 
b/plugins/jira/tasks/apiv2models/issue.go
index 3544150e..591ff7b7 100644
--- a/plugins/jira/tasks/apiv2models/issue.go
+++ b/plugins/jira/tasks/apiv2models/issue.go
@@ -151,11 +151,8 @@ type Issue struct {
        } `json:"changelog"`
 }
 
-func (i Issue) toToolLayer(connectionId uint64, epicField, storyPointField 
string) *models.JiraIssue {
+func (i Issue) toToolLayer(connectionId uint64) *models.JiraIssue {
        var workload float64
-       if storyPointField != "" {
-               workload, _ = i.Fields.AllFields[storyPointField].(float64)
-       }
        result := &models.JiraIssue{
                ConnectionId:       connectionId,
                IssueId:            i.ID,
@@ -177,9 +174,6 @@ func (i Issue) toToolLayer(connectionId uint64, epicField, 
storyPointField strin
        if i.Fields.Epic != nil {
                result.EpicKey = i.Fields.Epic.Key
        }
-       if epicField != "" {
-               result.EpicKey, _ = i.Fields.AllFields[epicField].(string)
-       }
        if i.Fields.Assignee != nil {
                result.AssigneeAccountId = i.Fields.Assignee.getAccountId()
                result.AssigneeDisplayName = i.Fields.Assignee.DisplayName
@@ -227,8 +221,8 @@ func (i *Issue) SetAllFields(raw datatypes.JSON) error {
        return nil
 }
 
-func (i Issue) ExtractEntities(connectionId uint64, epicField, storyPointField 
string) ([]uint64, *models.JiraIssue, bool, []*models.JiraWorklog, 
[]*models.JiraChangelog, []*models.JiraChangelogItem, []*models.JiraUser) {
-       issue := i.toToolLayer(connectionId, epicField, storyPointField)
+func (i Issue) ExtractEntities(connectionId uint64) ([]uint64, 
*models.JiraIssue, bool, []*models.JiraWorklog, []*models.JiraChangelog, 
[]*models.JiraChangelogItem, []*models.JiraUser) {
+       issue := i.toToolLayer(connectionId)
        var worklogs []*models.JiraWorklog
        var changelogs []*models.JiraChangelog
        var changelogItems []*models.JiraChangelogItem
diff --git a/plugins/jira/tasks/issue_extractor.go 
b/plugins/jira/tasks/issue_extractor.go
index 17882df8..266be502 100644
--- a/plugins/jira/tasks/issue_extractor.go
+++ b/plugins/jira/tasks/issue_extractor.go
@@ -106,7 +106,7 @@ func ExtractIssues(taskCtx core.SubTaskContext) error {
                                return nil, err
                        }
                        var results []interface{}
-                       sprints, issue, _, worklogs, changelogs, 
changelogItems, users := apiIssue.ExtractEntities(data.Connection.ID, 
data.Connection.EpicKeyField, data.Connection.StoryPointField)
+                       sprints, issue, _, worklogs, changelogs, 
changelogItems, users := apiIssue.ExtractEntities(data.Connection.ID)
                        for _, sprintId := range sprints {
                                sprintIssue := &models.JiraSprintIssue{
                                        ConnectionId:     data.Connection.ID,
diff --git a/plugins/tapd/api/connection.go b/plugins/tapd/api/connection.go
index 5065f096..96c6bbba 100644
--- a/plugins/tapd/api/connection.go
+++ b/plugins/tapd/api/connection.go
@@ -281,30 +281,3 @@ func GetConnection(input *core.ApiResourceInput) 
(*core.ApiResourceOutput, error
        }
        return &core.ApiResourceOutput{Body: detail}, nil
 }
-
-// GET /plugins/tapd/connections/:connectionId/boards
-
-func GetBoardsByConnectionId(input *core.ApiResourceInput) 
(*core.ApiResourceOutput, error) {
-       connectionId := input.Params["connectionId"]
-       if connectionId == "" {
-               return nil, fmt.Errorf("missing connectionId")
-       }
-       tapdConnectionId, err := strconv.ParseUint(connectionId, 10, 64)
-       if err != nil {
-               return nil, fmt.Errorf("invalid connectionId")
-       }
-       var tapdWorkspaces []models.TapdWorkspace
-       err = db.Where("connection_Id = ?", 
tapdConnectionId).Find(&tapdWorkspaces).Error
-       if err != nil {
-               return nil, err
-       }
-       var workSpaceResponses []models.WorkspaceResponse
-       for _, workSpace := range tapdWorkspaces {
-               workSpaceResponses = append(workSpaceResponses, 
models.WorkspaceResponse{
-                       Id:    uint64(workSpace.ID),
-                       Title: workSpace.Name,
-                       Value: fmt.Sprintf("%v", workSpace.ID),
-               })
-       }
-       return &core.ApiResourceOutput{Body: workSpaceResponses}, nil
-}
diff --git a/plugins/tapd/tapd.go b/plugins/tapd/tapd.go
index ea556438..c74d278d 100644
--- a/plugins/tapd/tapd.go
+++ b/plugins/tapd/tapd.go
@@ -180,9 +180,6 @@ func (plugin Tapd) ApiResources() 
map[string]map[string]core.ApiResourceHandler
                        "DELETE": api.DeleteConnection,
                        "GET":    api.GetConnection,
                },
-               "connections/:connectionId/boards": {
-                       "GET": api.GetBoardsByConnectionId,
-               },
                "connections/:connectionId/proxy/rest/*path": {
                        "GET": api.Proxy,
                },
@@ -220,7 +217,10 @@ func main() {
                        panic(err)
                }
                wsList := make([]*models.TapdWorkspace, 0)
-               err = db.Find(&wsList, "parent_id = ?", 59169984).Error 
//nolint TODO: fix the unused err
+               err = db.Find(&wsList, "parent_id = ?", 59169984).Error
+               if err != nil {
+                       panic(err)
+               }
                for _, v := range wsList {
                        *workspaceId = v.ID
                        runner.DirectRun(c, args, PluginEntry, []string{}, 
map[string]interface{}{
diff --git a/runner/directrun.go b/runner/directrun.go
index 6ab5b83d..e2343cd4 100644
--- a/runner/directrun.go
+++ b/runner/directrun.go
@@ -47,7 +47,6 @@ func DirectRun(cmd *cobra.Command, args []string, pluginTask 
core.PluginTask, su
        if err != nil {
                panic(err)
        }
-       subtasks = tasks
        cfg := config.GetConfig()
        log := logger.Global.Nested(cmd.Use)
        db, err := NewGormDb(cfg, log)
@@ -102,7 +101,7 @@ func DirectRun(cmd *cobra.Command, args []string, 
pluginTask core.PluginTask, su
                db,
                ctx,
                cmd.Use,
-               subtasks,
+               tasks,
                options,
                pluginTask,
                nil,

Reply via email to