You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@devlake.apache.org by wa...@apache.org on 2022/06/06 15:49:52 UTC
[incubator-devlake] 04/04: minor fixes
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 <yi...@merico.dev>
AuthorDate: Thu Jun 2 16:57:24 2022 +0800
minor fixes
Signed-off-by: Yingchu Chen <yi...@merico.dev>
---
.../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,