From a80221a95005cad8ecf8c58364df4ef4a918b25f Mon Sep 17 00:00:00 2001 From: "meilin.huang" <954537473@qq.com> Date: Fri, 5 Jul 2024 13:14:31 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E6=95=B0=E6=8D=AE=E5=BA=93=E5=AE=9E?= =?UTF-8?q?=E4=BE=8B=E5=88=A0=E9=99=A4=E7=AD=89=E9=97=AE=E9=A2=98=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mayfly_go_web/package.json | 12 ++-- mayfly_go_web/src/common/utils/object.ts | 27 +++++++- server/go.mod | 12 ++-- server/internal/db/application/db_instance.go | 18 ++---- server/internal/db/dbm/dbi/dialect.go | 8 ++- server/internal/db/dbm/dbi/metadata.go | 21 +++---- .../internal/db/domain/entity/db_instance.go | 2 +- .../internal/machine/application/machine.go | 14 +---- server/internal/redis/application/redis.go | 15 +---- .../tag/application/resouce_auth_cert.go | 22 +++++++ server/pkg/utils/jsonx/jsonx.go | 13 ++-- server/pkg/utils/jsonx/jsonx_test.go | 61 +------------------ 12 files changed, 94 insertions(+), 131 deletions(-) diff --git a/mayfly_go_web/package.json b/mayfly_go_web/package.json index db6e1218..9dd62029 100644 --- a/mayfly_go_web/package.json +++ b/mayfly_go_web/package.json @@ -16,7 +16,7 @@ "clipboard": "^2.0.11", "cropperjs": "^1.6.1", "dayjs": "^1.11.11", - "echarts": "^5.5.0", + "echarts": "^5.5.1", "element-plus": "^2.7.6", "js-base64": "^3.7.7", "jsencrypt": "^3.3.2", @@ -34,7 +34,7 @@ "sql-formatter": "^15.0.2", "trzsz": "^1.1.5", "uuid": "^9.0.1", - "vue": "^3.4.30", + "vue": "^3.4.31", "vue-router": "^4.4.0", "xterm": "^5.3.0", "xterm-addon-fit": "^0.8.0", @@ -48,16 +48,16 @@ "@types/sortablejs": "^1.15.8", "@typescript-eslint/eslint-plugin": "^6.7.4", "@typescript-eslint/parser": "^6.7.4", - "@vitejs/plugin-vue": "^5.0.4", - "@vue/compiler-sfc": "^3.4.30", + "@vitejs/plugin-vue": "^5.0.5", + "@vue/compiler-sfc": "^3.4.31", "code-inspector-plugin": "^0.4.5", "dotenv": "^16.3.1", "eslint": "^8.35.0", "eslint-plugin-vue": "^9.25.0", "prettier": "^3.2.5", "sass": "^1.77.6", - "typescript": "^5.5.2", - "vite": "^5.3.1", + "typescript": "^5.5.3", + "vite": "^5.3.3", "vue-eslint-parser": "^9.4.2" }, "browserslist": [ diff --git a/mayfly_go_web/src/common/utils/object.ts b/mayfly_go_web/src/common/utils/object.ts index b8f7834c..8d6087fe 100644 --- a/mayfly_go_web/src/common/utils/object.ts +++ b/mayfly_go_web/src/common/utils/object.ts @@ -9,7 +9,19 @@ export function getValueByPath(obj: any, path: string) { const keys = path.split('.'); let result = obj; for (let key of keys) { - if (!result || typeof result !== 'object') { + if (!result) { + return undefined; + } + // 如果是字符串,则尝试使用json解析 + if (typeof result == 'string') { + try { + result = JSON.parse(result); + } catch (e) { + console.error(e); + return undefined; + } + } + if (typeof result !== 'object') { return undefined; } @@ -23,7 +35,18 @@ export function getValueByPath(obj: any, path: string) { } const index = parseInt(matchIndex[1]); - result = Array.isArray(result[arrayKey]) ? result[arrayKey][index] : undefined; + + let arrValue = result[arrayKey]; + if (typeof arrValue == 'string') { + try { + arrValue = JSON.parse(arrValue); + } catch (e) { + result = undefined; + break; + } + } + + result = Array.isArray(arrValue) ? arrValue[index] : undefined; } else { result = result[key]; } diff --git a/server/go.mod b/server/go.mod index 3f50d128..395063f0 100644 --- a/server/go.mod +++ b/server/go.mod @@ -3,9 +3,8 @@ module mayfly-go go 1.22 require ( - gitee.com/chunanyong/dm v1.8.14 + gitee.com/chunanyong/dm v1.8.15 gitee.com/liuzongyang/libpq v1.0.9 - github.com/buger/jsonparser v1.1.1 github.com/emirpasic/gods v1.18.1 github.com/gin-gonic/gin v1.10.0 github.com/glebarez/sqlite v1.11.0 @@ -21,7 +20,7 @@ require ( github.com/kanzihuang/vitess/go/vt/sqlparser v0.0.0-20231018071450-ac8d9f0167e9 github.com/lionsoul2014/ip2region/binding/golang v0.0.0-20230712084735-068dc2aee82d github.com/may-fly/cast v1.6.1 - github.com/microsoft/go-mssqldb v1.7.1 + github.com/microsoft/go-mssqldb v1.7.2 github.com/mojocn/base64Captcha v1.3.6 // 验证码 github.com/pkg/errors v0.9.1 github.com/pkg/sftp v1.13.6 @@ -30,8 +29,9 @@ require ( github.com/robfig/cron/v3 v3.0.1 // 定时任务 github.com/sijms/go-ora/v2 v2.8.19 github.com/stretchr/testify v1.9.0 + github.com/tidwall/gjson v1.17.1 github.com/veops/go-ansiterm v0.0.5 - go.mongodb.org/mongo-driver v1.15.0 // mongo + go.mongodb.org/mongo-driver v1.16.0 // mongo golang.org/x/crypto v0.24.0 // ssh golang.org/x/oauth2 v0.21.0 golang.org/x/sync v0.7.0 @@ -77,12 +77,14 @@ require ( github.com/mattn/go-sqlite3 v1.14.17 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect - github.com/montanaflynn/stats v0.7.0 // indirect + github.com/montanaflynn/stats v0.7.1 // indirect github.com/pelletier/go-toml/v2 v2.2.2 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect github.com/rivo/uniseg v0.4.3 // indirect github.com/spf13/pflag v1.0.5 // indirect + github.com/tidwall/match v1.1.1 // indirect + github.com/tidwall/pretty v1.2.1 // indirect github.com/tjfoc/gmsm v1.4.1 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/ugorji/go/codec v1.2.12 // indirect diff --git a/server/internal/db/application/db_instance.go b/server/internal/db/application/db_instance.go index dd93d0c0..68b05528 100644 --- a/server/internal/db/application/db_instance.go +++ b/server/internal/db/application/db_instance.go @@ -67,17 +67,9 @@ func (app *instanceAppImpl) GetPageList(condition *entity.InstanceQuery, pagePar func (app *instanceAppImpl) TestConn(instanceEntity *entity.DbInstance, authCert *tagentity.ResourceAuthCert) error { instanceEntity.Network = instanceEntity.GetNetwork() - if authCert.Id != 0 { - // 密文可能被清除,故需要重新获取 - authCert, _ = app.resourceAuthCertApp.GetAuthCert(authCert.Name) - } else { - if authCert.CiphertextType == tagentity.AuthCertCiphertextTypePublic { - publicAuthCert, err := app.resourceAuthCertApp.GetAuthCert(authCert.Ciphertext) - if err != nil { - return err - } - authCert = publicAuthCert - } + authCert, err := app.resourceAuthCertApp.GetRealAuthCert(authCert) + if err != nil { + return err } dbConn, err := dbm.Conn(app.toDbInfoByAc(instanceEntity, authCert, "")) @@ -176,7 +168,7 @@ func (app *instanceAppImpl) Delete(ctx context.Context, instanceId uint64) error DbInstanceId: instanceId, } err = app.restoreApp.restoreRepo.GetByCond(restore) - if err != nil { + if err == nil { return errorx.NewBiz("不能删除数据库实例【%s】,请先删除关联的数据库恢复任务。", instance.Name) } @@ -184,7 +176,7 @@ func (app *instanceAppImpl) Delete(ctx context.Context, instanceId uint64) error DbInstanceId: instanceId, } err = app.backupApp.backupRepo.GetByCond(backup) - if err != nil { + if err == nil { return errorx.NewBiz("不能删除数据库实例【%s】,请先删除关联的数据库备份任务。", instance.Name) } diff --git a/server/internal/db/dbm/dbi/dialect.go b/server/internal/db/dbm/dbi/dialect.go index 92618911..35b35676 100644 --- a/server/internal/db/dbm/dbi/dialect.go +++ b/server/internal/db/dbm/dbi/dialect.go @@ -28,17 +28,19 @@ type Dialect interface { // GetDbProgram 获取数据库程序模块,用于数据库备份与恢复 GetDbProgram() (DbProgram, error) - // 批量保存数据 + // BatchInsert 批量insert数据 BatchInsert(tx *sql.Tx, tableName string, columns []string, values [][]any, duplicateStrategy int) (int64, error) - // 拷贝表 + // CopyTable 拷贝表 CopyTable(copy *DbCopyTable) error + // CreateTable 创建表 CreateTable(columns []Column, tableInfo Table, dropOldTable bool) (int, error) + // CreateIndex 创建索引 CreateIndex(tableInfo Table, indexs []Index) error - // 有些数据库迁移完数据之后,需要更新表自增序列为当前表最大值 + // UpdateSequence 有些数据库迁移完数据之后,需要更新表自增序列为当前表最大值 UpdateSequence(tableName string, columns []Column) } diff --git a/server/internal/db/dbm/dbi/metadata.go b/server/internal/db/dbm/dbi/metadata.go index 35017e5b..90869e34 100644 --- a/server/internal/db/dbm/dbi/metadata.go +++ b/server/internal/db/dbm/dbi/metadata.go @@ -13,37 +13,36 @@ import ( type MetaData interface { BaseMetaData - // 获取数据库服务实例信息 + // GetDbServer 获取数据库服务实例信息 GetDbServer() (*DbServer, error) - // 获取数据库名称列表 + // GetDbNames 获取数据库名称列表 GetDbNames() ([]string, error) - // 获取表信息 + // GetTables 获取表信息 GetTables(tableNames ...string) ([]Table, error) - // 获取指定表名的所有列元信息 + // GetColumns 获取指定表名的所有列元信息 GetColumns(tableNames ...string) ([]Column, error) - // 根据数据库类型修复字段长度、精度等 - // FixColumn(column *Column) - - // 获取表主键字段名,没有主键标识则默认第一个字段 + // GetPrimaryKey 获取表主键字段名,没有主键标识则默认第一个字段 GetPrimaryKey(tableName string) (string, error) - // 获取表索引信息 + // GetTableIndex 获取表索引信息 GetTableIndex(tableName string) ([]Index, error) - // 获取建表ddl + // GetTableDDL 获取建表ddl GetTableDDL(tableName string, dropBeforeCreate bool) (string, error) + // GenerateTableDDL 生成建表ddl GenerateTableDDL(columns []Column, tableInfo Table, dropBeforeCreate bool) []string + // GenerateIndexDDL 生成索引ddl GenerateIndexDDL(indexs []Index, tableInfo Table) []string GetSchemas() ([]string, error) - // 获取数据处理助手 用于解析格式化列数据等 + // GetDataHelper 获取数据处理助手 用于解析格式化列数据等 GetDataHelper() DataHelper } diff --git a/server/internal/db/domain/entity/db_instance.go b/server/internal/db/domain/entity/db_instance.go index 2426e61b..2e94f0da 100644 --- a/server/internal/db/domain/entity/db_instance.go +++ b/server/internal/db/domain/entity/db_instance.go @@ -16,7 +16,7 @@ type DbInstance struct { Network string `json:"network"` Extra *string `json:"extra"` // 连接需要的其他额外参数(json格式), 如oracle需要sid等 Params *string `json:"params"` // 使用指针类型,可更新为零值(空字符串) - Remark string `json:"remark"` + Remark *string `json:"remark"` SshTunnelMachineId int `json:"sshTunnelMachineId"` // ssh隧道机器id } diff --git a/server/internal/machine/application/machine.go b/server/internal/machine/application/machine.go index 9aa13148..e3f1e9fc 100644 --- a/server/internal/machine/application/machine.go +++ b/server/internal/machine/application/machine.go @@ -159,17 +159,9 @@ func (m *machineAppImpl) SaveMachine(ctx context.Context, param *dto.SaveMachine func (m *machineAppImpl) TestConn(me *entity.Machine, authCert *tagentity.ResourceAuthCert) error { me.Id = 0 - if authCert.Id != 0 { - // 密文可能被清除,故需要重新获取 - authCert, _ = m.resourceAuthCertApp.GetAuthCert(authCert.Name) - } else { - if authCert.CiphertextType == tagentity.AuthCertCiphertextTypePublic { - publicAuthCert, err := m.resourceAuthCertApp.GetAuthCert(authCert.Ciphertext) - if err != nil { - return err - } - authCert = publicAuthCert - } + authCert, err := m.resourceAuthCertApp.GetRealAuthCert(authCert) + if err != nil { + return err } mi, err := m.toMi(me, authCert) diff --git a/server/internal/redis/application/redis.go b/server/internal/redis/application/redis.go index a156c8f4..7c070aae 100644 --- a/server/internal/redis/application/redis.go +++ b/server/internal/redis/application/redis.go @@ -76,18 +76,9 @@ func (r *redisAppImpl) TestConn(param *dto.SaveRedis) error { db = cast.ToInt(strings.Split(re.Db, ",")[0]) } - authCert := param.AuthCert - if authCert.Id != 0 { - // 密文可能被清除,故需要重新获取 - authCert, _ = r.resourceAuthCertApp.GetAuthCert(authCert.Name) - } else { - if authCert.CiphertextType == tagentity.AuthCertCiphertextTypePublic { - publicAuthCert, err := r.resourceAuthCertApp.GetAuthCert(authCert.Ciphertext) - if err != nil { - return err - } - authCert = publicAuthCert - } + authCert, err := r.resourceAuthCertApp.GetRealAuthCert(param.AuthCert) + if err != nil { + return err } rc, err := re.ToRedisInfo(db, authCert).Conn() diff --git a/server/internal/tag/application/resouce_auth_cert.go b/server/internal/tag/application/resouce_auth_cert.go index 55df42ab..15861547 100644 --- a/server/internal/tag/application/resouce_auth_cert.go +++ b/server/internal/tag/application/resouce_auth_cert.go @@ -26,6 +26,9 @@ type ResourceAuthCert interface { // GetAuthCert 根据授权凭证名称获取授权凭证 GetAuthCert(authCertName string) (*entity.ResourceAuthCert, error) + //GetRealAuthCert 获取真实可连接鉴权的授权凭证,主要用于资源测试连接时 + GetRealAuthCert(authCert *entity.ResourceAuthCert) (*entity.ResourceAuthCert, error) + // GetResourceAuthCert 获取资源授权凭证,优先获取默认账号,若不存在默认账号则返回特权账号,都不存在则返回第一个 GetResourceAuthCert(resourceType entity.TagType, resourceCode string) (*entity.ResourceAuthCert, error) @@ -211,6 +214,25 @@ func (r *resourceAuthCertAppImpl) GetAuthCert(authCertName string) (*entity.Reso return r.decryptAuthCert(authCert) } +func (r *resourceAuthCertAppImpl) GetRealAuthCert(authCert *entity.ResourceAuthCert) (*entity.ResourceAuthCert, error) { + // 如果使用的是公共授权凭证,则密文为凭证名称 + if authCert.CiphertextType == entity.AuthCertCiphertextTypePublic { + return r.GetAuthCert(authCert.Ciphertext) + } + + if authCert.Id != 0 && authCert.Ciphertext == "" { + // 密文可能被清除,故需要重新获取 + ac, err := r.GetAuthCert(authCert.Name) + if err != nil { + return nil, err + } + authCert.Ciphertext = ac.Ciphertext + return authCert, nil + } + + return authCert, nil +} + func (r *resourceAuthCertAppImpl) GetResourceAuthCert(resourceType entity.TagType, resourceCode string) (*entity.ResourceAuthCert, error) { resourceAuthCerts, err := r.ListByCond(&entity.ResourceAuthCert{ ResourceType: int8(resourceType), diff --git a/server/pkg/utils/jsonx/jsonx.go b/server/pkg/utils/jsonx/jsonx.go index b50acc0d..07ae9c50 100644 --- a/server/pkg/utils/jsonx/jsonx.go +++ b/server/pkg/utils/jsonx/jsonx.go @@ -3,9 +3,8 @@ package jsonx import ( "encoding/json" "mayfly-go/pkg/logx" - "strings" - "github.com/buger/jsonparser" + "github.com/tidwall/gjson" ) // json字符串转map @@ -42,35 +41,35 @@ func ToStr(val any) string { // // @param fieldPath字段路径。如user.username等 func GetStringByBytes(bytes []byte, fieldPath string) (string, error) { - return jsonparser.GetString(bytes, strings.Split(fieldPath, ".")...) + return gjson.GetBytes(bytes, fieldPath).String(), nil } // 根据json字符串获取对应字段路径的string类型值 // // @param fieldPath字段路径。如user.username等 func GetString(jsonStr string, fieldPath string) (string, error) { - return GetStringByBytes([]byte(jsonStr), fieldPath) + return gjson.Get(jsonStr, fieldPath).String(), nil } // 根据json字节数组获取对应字段路径的int类型值 // // @param fieldPath字段路径。如user.age等 func GetIntByBytes(bytes []byte, fieldPath string) (int64, error) { - return jsonparser.GetInt(bytes, strings.Split(fieldPath, ".")...) + return gjson.GetBytes(bytes, fieldPath).Int(), nil } // 根据json字符串获取对应字段路径的int类型值 // // @param fieldPath字段路径。如user.age等 func GetInt(jsonStr string, fieldPath string) (int64, error) { - return GetIntByBytes([]byte(jsonStr), fieldPath) + return gjson.Get(jsonStr, fieldPath).Int(), nil } // 根据json字节数组获取对应字段路径的bool类型值 // // @param fieldPath字段路径。如user.isDeleted等 func GetBoolByBytes(bytes []byte, fieldPath string) (bool, error) { - return jsonparser.GetBoolean(bytes, strings.Split(fieldPath, ".")...) + return gjson.GetBytes(bytes, fieldPath).Bool(), nil } // 根据json字符串获取对应字段路径的bool类型值 diff --git a/server/pkg/utils/jsonx/jsonx_test.go b/server/pkg/utils/jsonx/jsonx_test.go index 343adb50..98f10a4b 100644 --- a/server/pkg/utils/jsonx/jsonx_test.go +++ b/server/pkg/utils/jsonx/jsonx_test.go @@ -3,8 +3,6 @@ package jsonx import ( "fmt" "testing" - - "github.com/buger/jsonparser" ) const jsonStr = `{ @@ -36,7 +34,7 @@ func TestGetString(t *testing.T) { // val, err := GetString(jsonStr, "username1") // 含有数组的 - val, err := GetString(jsonStr, "person.avatars.[0].url") + val, err := GetString(jsonStr, "person.avatars.0.url") if err != nil { fmt.Println("error: ", err.Error()) @@ -50,60 +48,3 @@ func TestGetInt(t *testing.T) { val2, _ := GetInt(jsonStr, "person.github.followers") fmt.Println(val, ",", val2) } - -// 官方demo -func TestJsonParser(t *testing.T) { - data := []byte(jsonStr) - // You can specify key path by providing arguments to Get function - jsonparser.Get(data, "person", "name", "fullName") - - // There is `GetInt` and `GetBoolean` helpers if you exactly know key data type - jsonparser.GetInt(data, "person", "github", "followers") - - // When you try to get object, it will return you []byte slice pointer to data containing it - // In `company` it will be `{"name": "Acme"}` - jsonparser.Get(data, "company") - - // If the key doesn't exist it will throw an error - var size int64 - if value, err := jsonparser.GetInt(data, "company", "size"); err == nil { - size = value - fmt.Println(size) - } - - // You can use `ArrayEach` helper to iterate items [item1, item2 .... itemN] - jsonparser.ArrayEach(data, func(value []byte, dataType jsonparser.ValueType, offset int, err error) { - fmt.Println(jsonparser.Get(value, "url")) - }, "person", "avatars") - - // Or use can access fields by index! - jsonparser.GetString(data, "person", "avatars", "[0]", "url") - - // You can use `ObjectEach` helper to iterate objects { "key1":object1, "key2":object2, .... "keyN":objectN } - jsonparser.ObjectEach(data, func(key []byte, value []byte, dataType jsonparser.ValueType, offset int) error { - fmt.Printf("Key: '%s'\n Value: '%s'\n Type: %s\n", string(key), string(value), dataType) - return nil - }, "person", "name") - - // The most efficient way to extract multiple keys is `EachKey` - - paths := [][]string{ - []string{"person", "name", "fullName"}, - []string{"person", "avatars", "[0]", "url"}, - []string{"company", "url"}, - } - - jsonparser.EachKey(data, func(idx int, value []byte, vt jsonparser.ValueType, err error) { - switch idx { - case 0: // []string{"person", "name", "fullName"} - { - } - case 1: // []string{"person", "avatars", "[0]", "url"} - { - } - case 2: // []string{"company", "url"}, - { - } - } - }, paths...) -}