From eddda41291e05512b22654e8bc486b5f34ad6f14 Mon Sep 17 00:00:00 2001 From: "meilin.huang" <954537473@qq.com> Date: Tue, 7 Nov 2023 21:05:21 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=9C=BA=E5=99=A8=E5=88=97=E8=A1=A8?= =?UTF-8?q?=E6=96=B0=E5=A2=9E=E8=BF=90=E8=A1=8C=E7=8A=B6=E6=80=81=20&=20re?= =?UTF-8?q?factor:=20=E7=99=BB=E5=BD=95=E8=B4=A6=E5=8F=B7=E4=BF=A1?= =?UTF-8?q?=E6=81=AF=E5=AD=98=E5=82=A8=E4=B8=8Econtext?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mayfly_go_web/package.json | 4 +- .../src/views/ops/db/component/tab/Query.vue | 10 +- .../src/views/ops/machine/MachineList.vue | 45 ++++++ .../src/views/ops/machine/MachineStats.vue | 52 +++---- mayfly_go_web/yarn.lock | 144 +++++++++--------- server/internal/auth/api/account_login.go | 8 +- server/internal/auth/api/common.go | 5 +- server/internal/auth/api/ldap_login.go | 5 +- server/internal/auth/api/oauth2_login.go | 9 +- server/internal/auth/application/oauth2.go | 7 +- server/internal/common/api/index.go | 2 +- server/internal/db/api/db.go | 104 +++---------- server/internal/db/api/db_sql.go | 77 ++++++++++ server/internal/db/api/db_sql_exec.go | 2 +- server/internal/db/api/instance.go | 6 +- server/internal/db/application/application.go | 5 + server/internal/db/application/db.go | 19 +-- server/internal/db/application/db_sql.go | 21 +++ server/internal/db/application/db_sql_exec.go | 11 +- server/internal/db/application/instance.go | 15 +- server/internal/db/router/db.go | 9 -- server/internal/db/router/db_sql.go | 32 ++++ server/internal/db/router/router.go | 1 + server/internal/machine/api/auth_cert.go | 5 +- server/internal/machine/api/machine.go | 27 ++-- .../internal/machine/api/machine_cronjob.go | 8 +- server/internal/machine/api/machine_file.go | 11 +- server/internal/machine/api/machine_script.go | 8 +- server/internal/machine/api/vo/vo.go | 4 +- .../internal/machine/application/auth_cert.go | 9 +- .../internal/machine/application/machine.go | 63 ++++++-- .../machine/application/machine_cronjob.go | 55 +++---- .../machine/application/machine_file.go | 24 +-- .../machine/application/machine_script.go | 15 +- .../machine/domain/entity/machine_cronjob.go | 7 + .../internal/machine/domain/entity/query.go | 1 + .../machine/domain/repository/machine_file.go | 15 +- .../infrastructure/cache/machine_stats.go | 24 +++ .../infrastructure/persistence/machine.go | 1 + .../persistence/machine_file.go | 34 +---- server/internal/machine/init/init.go | 1 + server/internal/machine/mcm/client.go | 13 +- server/internal/machine/mcm/stats.go | 84 +++++----- server/internal/mongo/api/mongo.go | 9 +- server/internal/mongo/application/mongo.go | 15 +- server/internal/msg/api/msg.go | 2 +- server/internal/msg/application/msg.go | 9 +- server/internal/redis/api/redis.go | 11 +- server/internal/redis/application/redis.go | 15 +- server/internal/sys/api/account.go | 33 ++-- server/internal/sys/api/config.go | 5 +- server/internal/sys/api/resource.go | 9 +- server/internal/sys/api/role.go | 8 +- server/internal/sys/api/system.go | 6 +- server/internal/sys/application/account.go | 19 +-- server/internal/sys/application/config.go | 9 +- server/internal/sys/application/resource.go | 27 ++-- server/internal/sys/application/role.go | 22 +-- server/internal/sys/application/syslog.go | 5 +- server/internal/tag/api/tag_tree.go | 8 +- server/internal/tag/api/team.go | 21 +-- server/internal/tag/application/tag_tree.go | 17 ++- server/internal/tag/application/team.go | 43 +++--- server/pkg/base/app.go | 71 ++++----- server/pkg/base/repo.go | 69 +++++---- server/pkg/contextx/contextx.go | 14 +- server/pkg/logx/logx.go | 15 +- server/pkg/model/model.go | 16 ++ server/pkg/req/log_handler.go | 7 +- server/pkg/req/permission_handler.go | 11 +- server/pkg/req/req_ctx.go | 27 +++- server/pkg/utils/jsonx/jsonx.go | 5 + server/pkg/utils/stringx/rand.go | 11 +- server/pkg/utils/stringx/template_test.go | 26 ++++ 74 files changed, 915 insertions(+), 652 deletions(-) create mode 100644 server/internal/db/api/db_sql.go create mode 100644 server/internal/db/application/db_sql.go create mode 100644 server/internal/db/router/db_sql.go create mode 100644 server/internal/machine/infrastructure/cache/machine_stats.go create mode 100644 server/pkg/utils/stringx/template_test.go diff --git a/mayfly_go_web/package.json b/mayfly_go_web/package.json index 5d117391..97708e1f 100644 --- a/mayfly_go_web/package.json +++ b/mayfly_go_web/package.json @@ -15,7 +15,7 @@ "countup.js": "^2.7.0", "cropperjs": "^1.5.11", "echarts": "^5.4.3", - "element-plus": "^2.4.1", + "element-plus": "^2.4.2", "jsencrypt": "^3.3.1", "lodash": "^4.17.21", "mitt": "^3.0.1", @@ -29,7 +29,7 @@ "sortablejs": "^1.15.0", "sql-formatter": "^12.1.2", "uuid": "^9.0.1", - "vue": "^3.3.7", + "vue": "^3.3.8", "vue-clipboard3": "^1.0.1", "vue-router": "^4.2.5", "xterm": "^5.3.0", diff --git a/mayfly_go_web/src/views/ops/db/component/tab/Query.vue b/mayfly_go_web/src/views/ops/db/component/tab/Query.vue index e3c0db22..8790d9a1 100644 --- a/mayfly_go_web/src/views/ops/db/component/tab/Query.vue +++ b/mayfly_go_web/src/views/ops/db/component/tab/Query.vue @@ -118,10 +118,10 @@ const props = defineProps({ required: true, }, // sql脚本名,若有则去加载该sql内容 - sqlName: { - type: String, - default: '', - }, + // sqlName: { + // type: String, + // default: '', + // }, editorHeight: { type: String, default: '600', @@ -153,7 +153,7 @@ const state = reactive({ hasUpdatedFileds: false, }); -const { tableDataHeight, ti, execRes, table, loading, hasUpdatedFileds } = toRefs(state); +const { tableDataHeight, ti, execRes, table, sqlName, loading, hasUpdatedFileds } = toRefs(state); watch( () => props.editorHeight, diff --git a/mayfly_go_web/src/views/ops/machine/MachineList.vue b/mayfly_go_web/src/views/ops/machine/MachineList.vue index 085c4475..1bc30578 100644 --- a/mayfly_go_web/src/views/ops/machine/MachineList.vue +++ b/mayfly_go_web/src/views/ops/machine/MachineList.vue @@ -37,6 +37,36 @@ + + + + - {{ stats.Hostname }} + {{ stats.hostname }} - {{ stats.Uptime }} + {{ stats.uptime }} - {{ stats.TotalProcs }} + {{ stats.totalProcs }} - {{ stats.RunningProcs }} + {{ stats.runningProcs }} - {{ stats.Load1 }} {{ stats.Load5 }} {{ stats.Load10 }} + {{ stats.load1 }} {{ stats.load5 }} {{ stats.load10 }} @@ -35,16 +35,16 @@ 磁盘 - - - + + + @@ -54,16 +54,16 @@ 网卡 - - - + + + - + @@ -84,9 +84,6 @@ const props = defineProps({ visible: { type: Boolean, }, - stats: { - type: Object, - }, machineId: { type: Number, }, @@ -134,11 +131,12 @@ const onRefresh = async () => { }; const initMemStats = () => { + const mem = state.stats.memInfo; const data = [ - { name: '可用内存', value: state.stats.MemAvailable }, + { name: '可用内存', value: mem.available }, { name: '已用内存', - value: state.stats.MemTotal - state.stats.MemAvailable, + value: mem.total - mem.available, }, ]; const option = { @@ -192,20 +190,20 @@ const initMemStats = () => { }; const initCpuStats = () => { - const cpu = state.stats.CPU; + const cpu = state.stats.cpu; const data = [ - { name: 'Idle', value: cpu.Idle }, + { name: 'Idle', value: cpu.idle }, { name: 'Iowait', - value: cpu.Iowait, + value: cpu.iowait, }, { name: 'System', - value: cpu.System, + value: cpu.system, }, { name: 'User', - value: cpu.User, + value: cpu.user, }, ]; const option = { @@ -283,7 +281,7 @@ const initEchartsResize = () => { const parseNetInter = () => { state.netInter = []; - const netInter = state.stats.NetIntf; + const netInter = state.stats.netIntf; const keys = Object.keys(netInter); const values = Object.values(netInter); for (let i = 0; i < values.length; i++) { diff --git a/mayfly_go_web/yarn.lock b/mayfly_go_web/yarn.lock index 1c443571..c9550796 100644 --- a/mayfly_go_web/yarn.lock +++ b/mayfly_go_web/yarn.lock @@ -390,13 +390,13 @@ estree-walker "^2.0.2" source-map-js "^1.0.2" -"@vue/compiler-core@3.3.7": - version "3.3.7" - resolved "https://registry.npmmirror.com/@vue/compiler-core/-/compiler-core-3.3.7.tgz#865a5734c971686d9737d85a0c5a08de045b6162" - integrity sha512-pACdY6YnTNVLXsB86YD8OF9ihwpolzhhtdLVHhBL6do/ykr6kKXNYABRtNMGrsQXpEXXyAdwvWWkuTbs4MFtPQ== +"@vue/compiler-core@3.3.8": + version "3.3.8" + resolved "https://registry.npmmirror.com/@vue/compiler-core/-/compiler-core-3.3.8.tgz#301bb60d0245265a88ed5b30e200fbf223acb313" + integrity sha512-hN/NNBUECw8SusQvDSqqcVv6gWq8L6iAktUR0UF3vGu2OhzRqcOiAno0FmBJWwxhYEXRlQJT5XnoKsVq1WZx4g== dependencies: "@babel/parser" "^7.23.0" - "@vue/shared" "3.3.7" + "@vue/shared" "3.3.8" estree-walker "^2.0.2" source-map-js "^1.0.2" @@ -408,25 +408,25 @@ "@vue/compiler-core" "3.3.4" "@vue/shared" "3.3.4" -"@vue/compiler-dom@3.3.7": - version "3.3.7" - resolved "https://registry.npmmirror.com/@vue/compiler-dom/-/compiler-dom-3.3.7.tgz#a245aa03f9bfcdb537a239bf02842072de0644c9" - integrity sha512-0LwkyJjnUPssXv/d1vNJ0PKfBlDoQs7n81CbO6Q0zdL7H1EzqYRrTVXDqdBVqro0aJjo/FOa1qBAPVI4PGSHBw== +"@vue/compiler-dom@3.3.8": + version "3.3.8" + resolved "https://registry.npmmirror.com/@vue/compiler-dom/-/compiler-dom-3.3.8.tgz#09d832514b9b8d9415a3816b065d69dbefcc7e9b" + integrity sha512-+PPtv+p/nWDd0AvJu3w8HS0RIm/C6VGBIRe24b9hSyNWOAPEUosFZ5diwawwP8ip5sJ8n0Pe87TNNNHnvjs0FQ== dependencies: - "@vue/compiler-core" "3.3.7" - "@vue/shared" "3.3.7" + "@vue/compiler-core" "3.3.8" + "@vue/shared" "3.3.8" -"@vue/compiler-sfc@3.3.7": - version "3.3.7" - resolved "https://registry.npmmirror.com/@vue/compiler-sfc/-/compiler-sfc-3.3.7.tgz#219d04b3013c7b15fbc536e2279e07810b731cc2" - integrity sha512-7pfldWy/J75U/ZyYIXRVqvLRw3vmfxDo2YLMwVtWVNew8Sm8d6wodM+OYFq4ll/UxfqVr0XKiVwti32PCrruAw== +"@vue/compiler-sfc@3.3.8": + version "3.3.8" + resolved "https://registry.npmmirror.com/@vue/compiler-sfc/-/compiler-sfc-3.3.8.tgz#40b18e48aa00260950964d1d72157668521be0e1" + integrity sha512-WMzbUrlTjfYF8joyT84HfwwXo+8WPALuPxhy+BZ6R4Aafls+jDBnSz8PDz60uFhuqFbl3HxRfxvDzrUf3THwpA== dependencies: "@babel/parser" "^7.23.0" - "@vue/compiler-core" "3.3.7" - "@vue/compiler-dom" "3.3.7" - "@vue/compiler-ssr" "3.3.7" - "@vue/reactivity-transform" "3.3.7" - "@vue/shared" "3.3.7" + "@vue/compiler-core" "3.3.8" + "@vue/compiler-dom" "3.3.8" + "@vue/compiler-ssr" "3.3.8" + "@vue/reactivity-transform" "3.3.8" + "@vue/shared" "3.3.8" estree-walker "^2.0.2" magic-string "^0.30.5" postcss "^8.4.31" @@ -456,13 +456,13 @@ "@vue/compiler-dom" "3.3.4" "@vue/shared" "3.3.4" -"@vue/compiler-ssr@3.3.7": - version "3.3.7" - resolved "https://registry.npmmirror.com/@vue/compiler-ssr/-/compiler-ssr-3.3.7.tgz#eff4a70f7ceb800d60e68d208b96a030c0f1b636" - integrity sha512-TxOfNVVeH3zgBc82kcUv+emNHo+vKnlRrkv8YvQU5+Y5LJGJwSNzcmLUoxD/dNzv0bhQ/F0s+InlgV0NrApJZg== +"@vue/compiler-ssr@3.3.8": + version "3.3.8" + resolved "https://registry.npmmirror.com/@vue/compiler-ssr/-/compiler-ssr-3.3.8.tgz#136eed54411e4694815d961048a237191063fbce" + integrity sha512-hXCqQL/15kMVDBuoBYpUnSYT8doDNwsjvm3jTefnXr+ytn294ySnT8NlsFHmTgKNjwpuFy7XVV8yTeLtNl/P6w== dependencies: - "@vue/compiler-dom" "3.3.7" - "@vue/shared" "3.3.7" + "@vue/compiler-dom" "3.3.8" + "@vue/shared" "3.3.8" "@vue/devtools-api@^6.5.0": version "6.5.0" @@ -480,58 +480,58 @@ estree-walker "^2.0.2" magic-string "^0.30.0" -"@vue/reactivity-transform@3.3.7": - version "3.3.7" - resolved "https://registry.npmmirror.com/@vue/reactivity-transform/-/reactivity-transform-3.3.7.tgz#eb9f5110af5085079b851d162205394bc790d539" - integrity sha512-APhRmLVbgE1VPGtoLQoWBJEaQk4V8JUsqrQihImVqKT+8U6Qi3t5ATcg4Y9wGAPb3kIhetpufyZ1RhwbZCIdDA== +"@vue/reactivity-transform@3.3.8": + version "3.3.8" + resolved "https://registry.npmmirror.com/@vue/reactivity-transform/-/reactivity-transform-3.3.8.tgz#6d07649013b0be5c670f0ab6cc7ddd3150ad03f2" + integrity sha512-49CvBzmZNtcHua0XJ7GdGifM8GOXoUMOX4dD40Y5DxI3R8OUhMlvf2nvgUAcPxaXiV5MQQ1Nwy09ADpnLQUqRw== dependencies: "@babel/parser" "^7.23.0" - "@vue/compiler-core" "3.3.7" - "@vue/shared" "3.3.7" + "@vue/compiler-core" "3.3.8" + "@vue/shared" "3.3.8" estree-walker "^2.0.2" magic-string "^0.30.5" -"@vue/reactivity@3.3.7": - version "3.3.7" - resolved "https://registry.npmmirror.com/@vue/reactivity/-/reactivity-3.3.7.tgz#48b6671a45ba33039da2c0eb25ae702f924486a9" - integrity sha512-cZNVjWiw00708WqT0zRpyAgduG79dScKEPYJXq2xj/aMtk3SKvL3FBt2QKUlh6EHBJ1m8RhBY+ikBUzwc7/khg== +"@vue/reactivity@3.3.8": + version "3.3.8" + resolved "https://registry.npmmirror.com/@vue/reactivity/-/reactivity-3.3.8.tgz#cce8a03a3fd3539c3eeda53e277ba365d160dd4d" + integrity sha512-ctLWitmFBu6mtddPyOKpHg8+5ahouoTCRtmAHZAXmolDtuZXfjL2T3OJ6DL6ezBPQB1SmMnpzjiWjCiMYmpIuw== dependencies: - "@vue/shared" "3.3.7" + "@vue/shared" "3.3.8" -"@vue/runtime-core@3.3.7": - version "3.3.7" - resolved "https://registry.npmmirror.com/@vue/runtime-core/-/runtime-core-3.3.7.tgz#c1eece1c98f936dc69dd0667d11b464579b128fd" - integrity sha512-LHq9du3ubLZFdK/BP0Ysy3zhHqRfBn80Uc+T5Hz3maFJBGhci1MafccnL3rpd5/3wVfRHAe6c+PnlO2PAavPTQ== +"@vue/runtime-core@3.3.8": + version "3.3.8" + resolved "https://registry.npmmirror.com/@vue/runtime-core/-/runtime-core-3.3.8.tgz#fba5a632cbf2b5d29e171489570149cb6975dcdb" + integrity sha512-qurzOlb6q26KWQ/8IShHkMDOuJkQnQcTIp1sdP4I9MbCf9FJeGVRXJFr2mF+6bXh/3Zjr9TDgURXrsCr9bfjUw== dependencies: - "@vue/reactivity" "3.3.7" - "@vue/shared" "3.3.7" + "@vue/reactivity" "3.3.8" + "@vue/shared" "3.3.8" -"@vue/runtime-dom@3.3.7": - version "3.3.7" - resolved "https://registry.npmmirror.com/@vue/runtime-dom/-/runtime-dom-3.3.7.tgz#e7cf88cc01591fdf6e3164825554fdadc3137ffc" - integrity sha512-PFQU1oeJxikdDmrfoNQay5nD4tcPNYixUBruZzVX/l0eyZvFKElZUjW4KctCcs52nnpMGO6UDK+jF5oV4GT5Lw== +"@vue/runtime-dom@3.3.8": + version "3.3.8" + resolved "https://registry.npmmirror.com/@vue/runtime-dom/-/runtime-dom-3.3.8.tgz#e2d7aa795cf50914dda9a951887765a594b38af4" + integrity sha512-Noy5yM5UIf9UeFoowBVgghyGGPIDPy1Qlqt0yVsUdAVbqI8eeMSsTqBtauaEoT2UFXUk5S64aWVNJN4MJ2vRdA== dependencies: - "@vue/runtime-core" "3.3.7" - "@vue/shared" "3.3.7" + "@vue/runtime-core" "3.3.8" + "@vue/shared" "3.3.8" csstype "^3.1.2" -"@vue/server-renderer@3.3.7": - version "3.3.7" - resolved "https://registry.npmmirror.com/@vue/server-renderer/-/server-renderer-3.3.7.tgz#0cc3dc6ad39a54693e6e8f853caa3c7bb43b0364" - integrity sha512-UlpKDInd1hIZiNuVVVvLgxpfnSouxKQOSE2bOfQpBuGwxRV/JqqTCyyjXUWiwtVMyeRaZhOYYqntxElk8FhBhw== +"@vue/server-renderer@3.3.8": + version "3.3.8" + resolved "https://registry.npmmirror.com/@vue/server-renderer/-/server-renderer-3.3.8.tgz#9b1779010e75783edeed8fcfb97d9c95fc3ac5d2" + integrity sha512-zVCUw7RFskvPuNlPn/8xISbrf0zTWsTSdYTsUTN1ERGGZGVnRxM2QZ3x1OR32+vwkkCm0IW6HmJ49IsPm7ilLg== dependencies: - "@vue/compiler-ssr" "3.3.7" - "@vue/shared" "3.3.7" + "@vue/compiler-ssr" "3.3.8" + "@vue/shared" "3.3.8" "@vue/shared@3.3.4": version "3.3.4" resolved "https://registry.npmmirror.com/@vue/shared/-/shared-3.3.4.tgz#06e83c5027f464eef861c329be81454bc8b70780" integrity sha512-7OjdcV8vQ74eiz1TZLzZP4JwqM5fA94K6yntPS5Z25r9HDuGNzaGdgvwKYq6S+MxwF0TFRwe50fIR/MYnakdkQ== -"@vue/shared@3.3.7": - version "3.3.7" - resolved "https://registry.npmmirror.com/@vue/shared/-/shared-3.3.7.tgz#0091852fe5cc4237c8440fe32f3ab6bc920ae6d9" - integrity sha512-N/tbkINRUDExgcPTBvxNkvHGu504k8lzlNQRITVnm6YjOjwa4r0nnbd4Jb01sNpur5hAllyRJzSK5PvB9PPwRg== +"@vue/shared@3.3.8": + version "3.3.8" + resolved "https://registry.npmmirror.com/@vue/shared/-/shared-3.3.8.tgz#f044942142e1d3a395f24132e6203a784838542d" + integrity sha512-8PGwybFwM4x8pcfgqEQFy70NaQxASvOC5DJwLQfpArw1UDfUXrJkdxD3BhVTMS+0Lef/TU7YO0Jvr0jJY8T+mw== "@vueuse/core@^9.1.0": version "9.2.0" @@ -841,10 +841,10 @@ echarts@^5.4.3: tslib "2.3.0" zrender "5.4.4" -element-plus@^2.4.1: - version "2.4.1" - resolved "https://registry.npmmirror.com/element-plus/-/element-plus-2.4.1.tgz#8a5faa69e856d82494b94d77fb485d9e727c8bc1" - integrity sha512-t7nl+vQlkBKVk1Ag6AufSDyFV8YIXxTFsaya4Nz/0tiRlcz65WPN4WMFeNURuFJleu1HLNtP4YyQKMuS7El8uA== +element-plus@^2.4.2: + version "2.4.2" + resolved "https://registry.npmmirror.com/element-plus/-/element-plus-2.4.2.tgz#2a24632e0904ccd7bbbd64c269704f6b9969833c" + integrity sha512-E/HwXX7JF1LPvQSjs0fZ8WblIoc0quoXsRXQZiL7QDq7xJdNGSUaXtdk7xiEv7axPmLfEFtxE5du9fFspDrmJw== dependencies: "@ctrl/tinycolor" "^3.4.1" "@element-plus/icons-vue" "^2.0.6" @@ -1912,16 +1912,16 @@ vue-router@^4.2.5: dependencies: "@vue/devtools-api" "^6.5.0" -vue@^3.3.7: - version "3.3.7" - resolved "https://registry.npmmirror.com/vue/-/vue-3.3.7.tgz#972a218682443a3819d121261b2bff914417f4f0" - integrity sha512-YEMDia1ZTv1TeBbnu6VybatmSteGOS3A3YgfINOfraCbf85wdKHzscD6HSS/vB4GAtI7sa1XPX7HcQaJ1l24zA== +vue@^3.3.8: + version "3.3.8" + resolved "https://registry.npmmirror.com/vue/-/vue-3.3.8.tgz#532ff071af24f6a69e5ecc53a66858a9ee874ffc" + integrity sha512-5VSX/3DabBikOXMsxzlW8JyfeLKlG9mzqnWgLQLty88vdZL7ZJgrdgBOmrArwxiLtmS+lNNpPcBYqrhE6TQW5w== dependencies: - "@vue/compiler-dom" "3.3.7" - "@vue/compiler-sfc" "3.3.7" - "@vue/runtime-dom" "3.3.7" - "@vue/server-renderer" "3.3.7" - "@vue/shared" "3.3.7" + "@vue/compiler-dom" "3.3.8" + "@vue/compiler-sfc" "3.3.8" + "@vue/runtime-dom" "3.3.8" + "@vue/server-renderer" "3.3.8" + "@vue/shared" "3.3.8" which@^2.0.1: version "2.0.2" diff --git a/server/internal/auth/api/account_login.go b/server/internal/auth/api/account_login.go index dacb7f90..dd8b23d4 100644 --- a/server/internal/auth/api/account_login.go +++ b/server/internal/auth/api/account_login.go @@ -1,6 +1,7 @@ package api import ( + "context" "encoding/json" "fmt" "mayfly-go/internal/auth/api/form" @@ -107,7 +108,7 @@ func (a *AccountLogin) OtpVerify(rc *req.Ctx) { update := &sysentity.Account{OtpSecret: otpSecret} update.Id = accountId update.OtpSecretEncrypt() - biz.ErrIsNil(a.AccountApp.Update(update)) + biz.ErrIsNil(a.AccountApp.Update(context.Background(), update)) } la := &sysentity.Account{Username: otpInfo.Username} @@ -119,6 +120,7 @@ func (a *AccountLogin) OtpVerify(rc *req.Ctx) { } func (a *AccountLogin) Logout(rc *req.Ctx) { - req.GetPermissionCodeRegistery().Remove(rc.LoginAccount.Id) - ws.CloseClient(ws.UserId(rc.LoginAccount.Id)) + la := rc.GetLoginAccount() + req.GetPermissionCodeRegistery().Remove(la.Id) + ws.CloseClient(ws.UserId(la.Id)) } diff --git a/server/internal/auth/api/common.go b/server/internal/auth/api/common.go index ee6349ac..ba423a93 100644 --- a/server/internal/auth/api/common.go +++ b/server/internal/auth/api/common.go @@ -1,6 +1,7 @@ package api import ( + "context" "fmt" "mayfly-go/internal/auth/config" msgapp "mayfly-go/internal/msg/application" @@ -108,7 +109,7 @@ func saveLogin(account *sysentity.Account, ip string) { updateAccount.Id = account.Id updateAccount.LastLoginIp = ip // 偷懒为了方便直接获取accountApp - biz.ErrIsNil(sysapp.GetAccountApp().Update(updateAccount)) + biz.ErrIsNil(sysapp.GetAccountApp().Update(context.TODO(), updateAccount)) // 创建登录消息 loginMsg := &msgentity.Msg{ @@ -119,5 +120,5 @@ func saveLogin(account *sysentity.Account, ip string) { loginMsg.CreateTime = &now loginMsg.Creator = account.Username loginMsg.CreatorId = account.Id - msgapp.GetMsgApp().Create(loginMsg) + msgapp.GetMsgApp().Create(context.TODO(), loginMsg) } diff --git a/server/internal/auth/api/ldap_login.go b/server/internal/auth/api/ldap_login.go index 752d54cb..fe42f9be 100644 --- a/server/internal/auth/api/ldap_login.go +++ b/server/internal/auth/api/ldap_login.go @@ -1,6 +1,7 @@ package api import ( + "context" "crypto/tls" "fmt" "mayfly-go/internal/auth/api/form" @@ -88,10 +89,10 @@ func (a *LdapLogin) createUser(userName, displayName string) { account := &sysentity.Account{Username: userName} account.SetBaseInfo(nil) account.Name = displayName - biz.ErrIsNil(a.AccountApp.Create(account)) + biz.ErrIsNil(a.AccountApp.Create(context.TODO(), account)) // 将 LADP 用户本地密码设置为空,不允许本地登录 account.Password = cryptox.PwdHash("") - biz.ErrIsNil(a.AccountApp.Update(account)) + biz.ErrIsNil(a.AccountApp.Update(context.TODO(), account)) } func (a *LdapLogin) getOrCreateUserWithLdap(userName string, password string, cols ...string) (*sysentity.Account, error) { diff --git a/server/internal/auth/api/oauth2_login.go b/server/internal/auth/api/oauth2_login.go index 565239de..ae886455 100644 --- a/server/internal/auth/api/oauth2_login.go +++ b/server/internal/auth/api/oauth2_login.go @@ -1,6 +1,7 @@ package api import ( + "context" "fmt" "io" "mayfly-go/internal/auth/api/vo" @@ -42,7 +43,7 @@ func (a *Oauth2Login) OAuth2Login(rc *req.Ctx) { func (a *Oauth2Login) OAuth2Bind(rc *req.Ctx) { client, _ := a.getOAuthClient() state := stringx.Rand(32) - cache.SetStr("oauth2:state:"+state, "bind:"+strconv.FormatUint(rc.LoginAccount.Id, 10), + cache.SetStr("oauth2:state:"+state, "bind:"+strconv.FormatUint(rc.GetLoginAccount().Id, 10), 5*time.Minute) rc.GinCtx.Redirect(http.StatusFound, client.AuthCodeURL(state)) } @@ -152,7 +153,7 @@ func (a *Oauth2Login) doLoginAction(rc *req.Ctx, userId string, oauth *config.Oa Name: userId, Username: userId, } - biz.ErrIsNil(a.AccountApp.Create(account)) + biz.ErrIsNil(a.AccountApp.Create(context.TODO(), account)) // 绑定 err := a.Oauth2App.BindOAuthAccount(&entity.Oauth2Account{ AccountId: account.Id, @@ -207,7 +208,7 @@ func (a *Oauth2Login) Oauth2Status(ctx *req.Ctx) { res.Enable = oauth2LoginConfig.Enable if res.Enable { err := a.Oauth2App.GetOAuthAccount(&entity.Oauth2Account{ - AccountId: ctx.LoginAccount.Id, + AccountId: ctx.GetLoginAccount().Id, }, "account_id", "identity") res.Bind = err == nil } @@ -216,7 +217,7 @@ func (a *Oauth2Login) Oauth2Status(ctx *req.Ctx) { } func (a *Oauth2Login) Oauth2Unbind(rc *req.Ctx) { - a.Oauth2App.Unbind(rc.LoginAccount.Id) + a.Oauth2App.Unbind(rc.GetLoginAccount().Id) } // 获取oauth2登录配置信息,因为有些字段是敏感字段,故单独使用接口获取 diff --git a/server/internal/auth/application/oauth2.go b/server/internal/auth/application/oauth2.go index 19032dd6..6f19b1fb 100644 --- a/server/internal/auth/application/oauth2.go +++ b/server/internal/auth/application/oauth2.go @@ -1,6 +1,7 @@ package application import ( + "context" "mayfly-go/internal/auth/domain/entity" "mayfly-go/internal/auth/domain/repository" ) @@ -29,11 +30,11 @@ func (a *oauth2AppImpl) GetOAuthAccount(condition *entity.Oauth2Account, cols .. func (a *oauth2AppImpl) BindOAuthAccount(e *entity.Oauth2Account) error { if e.Id == 0 { - return a.oauthAccountRepo.Insert(e) + return a.oauthAccountRepo.Insert(context.Background(), e) } - return a.oauthAccountRepo.UpdateById(e) + return a.oauthAccountRepo.UpdateById(context.Background(), e) } func (a *oauth2AppImpl) Unbind(accountId uint64) { - a.oauthAccountRepo.DeleteByCond(&entity.Oauth2Account{AccountId: accountId}) + a.oauthAccountRepo.DeleteByCond(context.Background(), &entity.Oauth2Account{AccountId: accountId}) } diff --git a/server/internal/common/api/index.go b/server/internal/common/api/index.go index 279a59c0..4f9ce1e0 100644 --- a/server/internal/common/api/index.go +++ b/server/internal/common/api/index.go @@ -23,7 +23,7 @@ type Index struct { } func (i *Index) Count(rc *req.Ctx) { - accountId := rc.LoginAccount.Id + accountId := rc.GetLoginAccount().Id tagIds := i.TagApp.ListTagIdByAccountId(accountId) var mongoNum int64 diff --git a/server/internal/db/api/db.go b/server/internal/db/api/db.go index 5e82e2f3..c1e22795 100644 --- a/server/internal/db/api/db.go +++ b/server/internal/db/api/db.go @@ -13,7 +13,6 @@ import ( tagapp "mayfly-go/internal/tag/application" "mayfly-go/pkg/biz" "mayfly-go/pkg/ginx" - "mayfly-go/pkg/gormx" "mayfly-go/pkg/logx" "mayfly-go/pkg/model" "mayfly-go/pkg/req" @@ -42,7 +41,7 @@ func (d *Db) Dbs(rc *req.Ctx) { queryCond, page := ginx.BindQueryAndPage[*entity.DbQuery](rc.GinCtx, new(entity.DbQuery)) // 不存在可访问标签id,即没有可操作数据 - tagIds := d.TagApp.ListTagIdByAccountId(rc.LoginAccount.Id) + tagIds := d.TagApp.ListTagIdByAccountId(rc.GetLoginAccount().Id) if len(tagIds) == 0 { rc.ResData = model.EmptyPageResult[any]() return @@ -55,7 +54,7 @@ func (d *Db) Dbs(rc *req.Ctx) { } func (d *Db) DbTags(rc *req.Ctx) { - rc.ResData = d.TagApp.ListTagByAccountIdAndResource(rc.LoginAccount.Id, new(entity.Db)) + rc.ResData = d.TagApp.ListTagByAccountIdAndResource(rc.GetLoginAccount().Id, new(entity.Db)) } func (d *Db) Save(rc *req.Ctx) { @@ -64,8 +63,7 @@ func (d *Db) Save(rc *req.Ctx) { rc.ReqParam = form - db.SetBaseInfo(rc.LoginAccount) - biz.ErrIsNil(d.DbApp.Save(db)) + biz.ErrIsNil(d.DbApp.Save(rc.MetaCtx, db)) } func (d *Db) DeleteDb(rc *req.Ctx) { @@ -73,13 +71,14 @@ func (d *Db) DeleteDb(rc *req.Ctx) { rc.ReqParam = idsStr ids := strings.Split(idsStr, ",") + ctx := rc.MetaCtx for _, v := range ids { value, err := strconv.Atoi(v) biz.ErrIsNilAppendErr(err, "string类型转换为int异常: %s") dbId := uint64(value) - d.DbApp.Delete(dbId) + d.DbApp.Delete(ctx, dbId) // 删除该库的sql执行记录 - d.DbSqlExecApp.DeleteBy(&entity.DbSqlExec{DbId: dbId}) + d.DbSqlExecApp.DeleteBy(ctx, &entity.DbSqlExec{DbId: dbId}) } } @@ -91,7 +90,7 @@ func (d *Db) ExecSql(rc *req.Ctx) { dbId := getDbId(g) dbConn, err := d.DbApp.GetDbConn(dbId, form.Db) biz.ErrIsNil(err) - biz.ErrIsNilAppendErr(d.TagApp.CanAccess(rc.LoginAccount.Id, dbConn.Info.TagPath), "%s") + biz.ErrIsNilAppendErr(d.TagApp.CanAccess(rc.GetLoginAccount().Id, dbConn.Info.TagPath), "%s") rc.ReqParam = fmt.Sprintf("%s\n-> %s", dbConn.Info.GetLogDesc(), form.Sql) biz.NotEmpty(form.Sql, "sql不能为空") @@ -104,7 +103,7 @@ func (d *Db) ExecSql(rc *req.Ctx) { Db: form.Db, Remark: form.Remark, DbConn: dbConn, - LoginAccount: rc.LoginAccount, + LoginAccount: rc.GetLoginAccount(), } sqls, err := sqlparser.SplitStatementToPieces(sql, sqlparser.WithDialect(dbConn.Info.Type.Dialect())) @@ -163,7 +162,7 @@ func (d *Db) ExecSqlFile(rc *req.Ctx) { dbConn, err := d.DbApp.GetDbConn(dbId, dbName) biz.ErrIsNil(err) - biz.ErrIsNilAppendErr(d.TagApp.CanAccess(rc.LoginAccount.Id, dbConn.Info.TagPath), "%s") + biz.ErrIsNilAppendErr(d.TagApp.CanAccess(rc.GetLoginAccount().Id, dbConn.Info.TagPath), "%s") rc.ReqParam = fmt.Sprintf("filename: %s -> %s", filename, dbConn.Info.GetLogDesc()) defer func() { @@ -172,7 +171,7 @@ func (d *Db) ExecSqlFile(rc *req.Ctx) { if len(errInfo) > 300 { errInfo = errInfo[:300] + "..." } - d.MsgApp.CreateAndSend(rc.LoginAccount, msgdto.ErrSysMsg("sql脚本执行失败", fmt.Sprintf("[%s][%s]执行失败: [%s]", filename, dbConn.Info.GetLogDesc(), errInfo)).WithClientId(clientId)) + d.MsgApp.CreateAndSend(rc.GetLoginAccount(), msgdto.ErrSysMsg("sql脚本执行失败", fmt.Sprintf("[%s][%s]执行失败: [%s]", filename, dbConn.Info.GetLogDesc(), errInfo)).WithClientId(clientId)) } }() @@ -181,7 +180,7 @@ func (d *Db) ExecSqlFile(rc *req.Ctx) { Db: dbName, Remark: filename, DbConn: dbConn, - LoginAccount: rc.LoginAccount, + LoginAccount: rc.GetLoginAccount(), } var sql string @@ -191,7 +190,8 @@ func (d *Db) ExecSqlFile(rc *req.Ctx) { executedStatements := 0 progressId := stringx.Rand(32) - defer ws.SendJsonMsg(ws.UserId(rc.LoginAccount.Id), clientId, msgdto.InfoSysMsg("sql脚本执行进度", &progressMsg{ + laId := rc.GetLoginAccount().Id + defer ws.SendJsonMsg(ws.UserId(laId), clientId, msgdto.InfoSysMsg("sql脚本执行进度", &progressMsg{ Id: progressId, Title: filename, ExecutedStatements: executedStatements, @@ -202,7 +202,7 @@ func (d *Db) ExecSqlFile(rc *req.Ctx) { for { select { case <-ticker.C: - ws.SendJsonMsg(ws.UserId(rc.LoginAccount.Id), clientId, msgdto.InfoSysMsg("sql脚本执行进度", &progressMsg{ + ws.SendJsonMsg(ws.UserId(laId), clientId, msgdto.InfoSysMsg("sql脚本执行进度", &progressMsg{ Id: progressId, Title: filename, ExecutedStatements: executedStatements, @@ -231,7 +231,7 @@ func (d *Db) ExecSqlFile(rc *req.Ctx) { } dbConn, err = d.DbApp.GetDbConn(dbId, stmtUse.DBName.String()) biz.ErrIsNil(err) - biz.ErrIsNilAppendErr(d.TagApp.CanAccess(rc.LoginAccount.Id, dbConn.Info.TagPath), "%s") + biz.ErrIsNilAppendErr(d.TagApp.CanAccess(laId, dbConn.Info.TagPath), "%s") execReq.DbConn = dbConn } // 需要记录执行记录 @@ -245,7 +245,7 @@ func (d *Db) ExecSqlFile(rc *req.Ctx) { biz.ErrIsNilAppendErr(err, "%s") } - d.MsgApp.CreateAndSend(rc.LoginAccount, msgdto.SuccessSysMsg("sql脚本执行成功", fmt.Sprintf("sql脚本执行完成:%s", rc.ReqParam)).WithClientId(clientId)) + d.MsgApp.CreateAndSend(rc.GetLoginAccount(), msgdto.SuccessSysMsg("sql脚本执行成功", fmt.Sprintf("sql脚本执行完成:%s", rc.ReqParam)).WithClientId(clientId)) } // 数据库dump @@ -268,9 +268,10 @@ func (d *Db) DumpSql(rc *req.Ctx) { // 是否需要导出数据 needData := dumpType == "2" || dumpType == "3" + la := rc.GetLoginAccount() db, err := d.DbApp.GetById(new(entity.Db), dbId) biz.ErrIsNil(err, "该数据库不存在") - biz.ErrIsNilAppendErr(d.TagApp.CanAccess(rc.LoginAccount.Id, db.TagPath), "%s") + biz.ErrIsNilAppendErr(d.TagApp.CanAccess(la.Id, db.TagPath), "%s") now := time.Now() filename := fmt.Sprintf("%s.%s.sql%s", db.Name, now.Format("20060102150405"), extName) @@ -294,7 +295,7 @@ func (d *Db) DumpSql(rc *req.Ctx) { if len(msg) > 0 { msg = "数据库导出失败: " + msg writer.WriteString(msg) - d.MsgApp.CreateAndSend(rc.LoginAccount, msgdto.ErrSysMsg("数据库导出失败", msg)) + d.MsgApp.CreateAndSend(la, msgdto.ErrSysMsg("数据库导出失败", msg)) } writer.Close() }() @@ -444,73 +445,6 @@ func (d *Db) GetCreateTableDdl(rc *req.Ctx) { rc.ResData = res } -// @router /api/db/:dbId/sql [post] -func (d *Db) SaveSql(rc *req.Ctx) { - g := rc.GinCtx - account := rc.LoginAccount - dbSqlForm := &form.DbSqlSaveForm{} - ginx.BindJsonAndValid(g, dbSqlForm) - rc.ReqParam = dbSqlForm - - dbId := getDbId(g) - // 判断dbId是否存在 - err := gormx.GetById(new(entity.Db), dbId) - biz.ErrIsNil(err, "该数据库信息不存在") - - // 获取用于是否有该dbsql的保存记录,有则更改,否则新增 - dbSql := &entity.DbSql{Type: dbSqlForm.Type, DbId: dbId, Name: dbSqlForm.Name, Db: dbSqlForm.Db} - dbSql.CreatorId = account.Id - e := gormx.GetBy(dbSql) - - dbSql.SetBaseInfo(account) - // 更新sql信息 - dbSql.Sql = dbSqlForm.Sql - if e == nil { - gormx.UpdateById(dbSql) - } else { - gormx.Insert(dbSql) - } -} - -// 获取所有保存的sql names -func (d *Db) GetSqlNames(rc *req.Ctx) { - dbId := getDbId(rc.GinCtx) - dbName := getDbName(rc.GinCtx) - // 获取用于是否有该dbsql的保存记录,有则更改,否则新增 - dbSql := &entity.DbSql{Type: 1, DbId: dbId, Db: dbName} - dbSql.CreatorId = rc.LoginAccount.Id - var sqls []entity.DbSql - gormx.ListBy(dbSql, &sqls, "id", "name") - - rc.ResData = sqls -} - -// 删除保存的sql -func (d *Db) DeleteSql(rc *req.Ctx) { - dbSql := &entity.DbSql{Type: 1, DbId: getDbId(rc.GinCtx)} - dbSql.CreatorId = rc.LoginAccount.Id - dbSql.Name = rc.GinCtx.Query("name") - dbSql.Db = rc.GinCtx.Query("db") - - biz.ErrIsNil(gormx.DeleteBy(dbSql)) -} - -// @router /api/db/:dbId/sql [get] -func (d *Db) GetSql(rc *req.Ctx) { - dbId := getDbId(rc.GinCtx) - dbName := getDbName(rc.GinCtx) - // 根据创建者id, 数据库id,以及sql模板名称查询保存的sql信息 - dbSql := &entity.DbSql{Type: 1, DbId: dbId, Db: dbName} - dbSql.CreatorId = rc.LoginAccount.Id - dbSql.Name = rc.GinCtx.Query("name") - - e := gormx.GetBy(dbSql) - if e != nil { - return - } - rc.ResData = dbSql -} - func getDbId(g *gin.Context) uint64 { dbId, _ := strconv.Atoi(g.Param("dbId")) biz.IsTrue(dbId > 0, "dbId错误") diff --git a/server/internal/db/api/db_sql.go b/server/internal/db/api/db_sql.go new file mode 100644 index 00000000..90c1be7e --- /dev/null +++ b/server/internal/db/api/db_sql.go @@ -0,0 +1,77 @@ +package api + +import ( + "mayfly-go/internal/db/api/form" + "mayfly-go/internal/db/application" + "mayfly-go/internal/db/domain/entity" + "mayfly-go/pkg/biz" + "mayfly-go/pkg/ginx" + "mayfly-go/pkg/req" +) + +type DbSql struct { + DbSqlApp application.DbSql +} + +// @router /api/db/:dbId/sql [post] +func (d *DbSql) SaveSql(rc *req.Ctx) { + g := rc.GinCtx + dbSqlForm := &form.DbSqlSaveForm{} + ginx.BindJsonAndValid(g, dbSqlForm) + rc.ReqParam = dbSqlForm + + dbId := getDbId(g) + + account := rc.GetLoginAccount() + // 获取用于是否有该dbsql的保存记录,有则更改,否则新增 + dbSql := &entity.DbSql{Type: dbSqlForm.Type, DbId: dbId, Name: dbSqlForm.Name, Db: dbSqlForm.Db} + dbSql.CreatorId = account.Id + e := d.DbSqlApp.GetBy(dbSql) + + // 更新sql信息 + dbSql.Sql = dbSqlForm.Sql + if e == nil { + d.DbSqlApp.UpdateById(rc.MetaCtx, dbSql) + } else { + d.DbSqlApp.Insert(rc.MetaCtx, dbSql) + } +} + +// 获取所有保存的sql names +func (d *DbSql) GetSqlNames(rc *req.Ctx) { + dbId := getDbId(rc.GinCtx) + dbName := getDbName(rc.GinCtx) + // 获取用于是否有该dbsql的保存记录,有则更改,否则新增 + dbSql := &entity.DbSql{Type: 1, DbId: dbId, Db: dbName} + dbSql.CreatorId = rc.GetLoginAccount().Id + var sqls []entity.DbSql + d.DbSqlApp.ListByCond(dbSql, &sqls, "id", "name") + + rc.ResData = sqls +} + +// 删除保存的sql +func (d *DbSql) DeleteSql(rc *req.Ctx) { + dbSql := &entity.DbSql{Type: 1, DbId: getDbId(rc.GinCtx)} + dbSql.CreatorId = rc.GetLoginAccount().Id + dbSql.Name = rc.GinCtx.Query("name") + dbSql.Db = rc.GinCtx.Query("db") + + biz.ErrIsNil(d.DbSqlApp.DeleteByCond(rc.MetaCtx, dbSql)) +} + +// @router /api/db/:dbId/sql [get] +func (d *DbSql) GetSql(rc *req.Ctx) { + dbId := getDbId(rc.GinCtx) + dbName := getDbName(rc.GinCtx) + // 根据创建者id, 数据库id,以及sql模板名称查询保存的sql信息 + dbSql := &entity.DbSql{Type: 1, DbId: dbId, Db: dbName} + dbSql.CreatorId = rc.GetLoginAccount().Id + dbSql.Name = rc.GinCtx.Query("name") + + e := d.DbSqlApp.GetBy(dbSql) + if e != nil { + return + } + rc.ResData = dbSql +} diff --git a/server/internal/db/api/db_sql_exec.go b/server/internal/db/api/db_sql_exec.go index a984dee0..83cf0f75 100644 --- a/server/internal/db/api/db_sql_exec.go +++ b/server/internal/db/api/db_sql_exec.go @@ -14,7 +14,7 @@ type DbSqlExec struct { func (d *DbSqlExec) DbSqlExecs(rc *req.Ctx) { queryCond, page := ginx.BindQueryAndPage(rc.GinCtx, new(entity.DbSqlExecQuery)) - queryCond.CreatorId = rc.LoginAccount.Id + queryCond.CreatorId = rc.GetLoginAccount().Id res, err := d.DbSqlExecApp.GetPageList(queryCond, page, new([]entity.DbSqlExec)) biz.ErrIsNil(err) rc.ResData = res diff --git a/server/internal/db/api/instance.go b/server/internal/db/api/instance.go index b7bb8567..1ee536c9 100644 --- a/server/internal/db/api/instance.go +++ b/server/internal/db/api/instance.go @@ -43,9 +43,7 @@ func (d *Instance) SaveInstance(rc *req.Ctx) { // 密码脱敏记录日志 form.Password = "****" rc.ReqParam = form - - instance.SetBaseInfo(rc.LoginAccount) - biz.ErrIsNil(d.InstanceApp.Save(instance)) + biz.ErrIsNil(d.InstanceApp.Save(rc.MetaCtx, instance)) } // GetInstance 获取数据库实例密码,由于数据库是加密存储,故提供该接口展示原文密码 @@ -84,7 +82,7 @@ func (d *Instance) DeleteInstance(rc *req.Ctx) { biz.ErrIsNil(err, "获取数据库实例错误,数据库实例ID为: %d", instance.Id) biz.IsTrue(false, "不能删除数据库实例【%s】,请先删除其关联的数据库资源。", instance.Name) } - d.InstanceApp.Delete(instanceId) + d.InstanceApp.Delete(rc.MetaCtx, instanceId) } } diff --git a/server/internal/db/application/application.go b/server/internal/db/application/application.go index 910a0e09..578c7e65 100644 --- a/server/internal/db/application/application.go +++ b/server/internal/db/application/application.go @@ -8,6 +8,7 @@ var ( instanceApp Instance = newInstanceApp(persistence.GetInstanceRepo()) dbApp Db = newDbApp(persistence.GetDbRepo(), persistence.GetDbSqlRepo(), instanceApp) dbSqlExecApp DbSqlExec = newDbSqlExecApp(persistence.GetDbSqlExecRepo()) + dbSqlApp DbSql = newDbSqlApp(persistence.GetDbSqlRepo()) ) func GetInstanceApp() Instance { @@ -18,6 +19,10 @@ func GetDbApp() Db { return dbApp } +func GetDbSqlApp() DbSql { + return dbSqlApp +} + func GetDbSqlExecApp() DbSqlExec { return dbSqlExecApp } diff --git a/server/internal/db/application/db.go b/server/internal/db/application/db.go index 0e0075b3..5c037d4e 100644 --- a/server/internal/db/application/db.go +++ b/server/internal/db/application/db.go @@ -1,6 +1,7 @@ package application import ( + "context" "mayfly-go/internal/db/dbm" "mayfly-go/internal/db/domain/entity" "mayfly-go/internal/db/domain/repository" @@ -20,10 +21,10 @@ type Db interface { Count(condition *entity.DbQuery) int64 - Save(entity *entity.Db) error + Save(ctx context.Context, entity *entity.Db) error // 删除数据库信息 - Delete(id uint64) error + Delete(ctx context.Context, id uint64) error // 获取数据库连接实例 // @param id 数据库id @@ -56,7 +57,7 @@ func (d *dbAppImpl) Count(condition *entity.DbQuery) int64 { return d.GetRepo().Count(condition) } -func (d *dbAppImpl) Save(dbEntity *entity.Db) error { +func (d *dbAppImpl) Save(ctx context.Context, dbEntity *entity.Db) error { // 查找是否存在 oldDb := &entity.Db{Name: dbEntity.Name, InstanceId: dbEntity.InstanceId} err := d.GetBy(oldDb) @@ -65,7 +66,7 @@ func (d *dbAppImpl) Save(dbEntity *entity.Db) error { if err == nil { return errorx.NewBiz("该实例下数据库名已存在") } - return d.Insert(dbEntity) + return d.Insert(ctx, dbEntity) } // 如果存在该库,则校验修改的库是否为该库 @@ -90,13 +91,13 @@ func (d *dbAppImpl) Save(dbEntity *entity.Db) error { // 关闭数据库连接 dbm.CloseDb(dbEntity.Id, v) // 删除该库关联的所有sql记录 - d.dbSqlRepo.DeleteByCond(&entity.DbSql{DbId: dbId, Db: v}) + d.dbSqlRepo.DeleteByCond(ctx, &entity.DbSql{DbId: dbId, Db: v}) } - return d.UpdateById(dbEntity) + return d.UpdateById(ctx, dbEntity) } -func (d *dbAppImpl) Delete(id uint64) error { +func (d *dbAppImpl) Delete(ctx context.Context, id uint64) error { db, err := d.GetById(new(entity.Db), id) if err != nil { return errorx.NewBiz("该数据库不存在") @@ -107,8 +108,8 @@ func (d *dbAppImpl) Delete(id uint64) error { dbm.CloseDb(id, v) } // 删除该库下用户保存的所有sql信息 - d.dbSqlRepo.DeleteByCond(&entity.DbSql{DbId: id}) - return d.DeleteById(id) + d.dbSqlRepo.DeleteByCond(ctx, &entity.DbSql{DbId: id}) + return d.DeleteById(ctx, id) } func (d *dbAppImpl) GetDbConn(dbId uint64, dbName string) (*dbm.DbConn, error) { diff --git a/server/internal/db/application/db_sql.go b/server/internal/db/application/db_sql.go new file mode 100644 index 00000000..2d110258 --- /dev/null +++ b/server/internal/db/application/db_sql.go @@ -0,0 +1,21 @@ +package application + +import ( + "mayfly-go/internal/db/domain/entity" + "mayfly-go/internal/db/domain/repository" + "mayfly-go/pkg/base" +) + +type DbSql interface { + base.App[*entity.DbSql] +} + +type dbSqlAppImpl struct { + base.AppImpl[*entity.DbSql, repository.DbSql] +} + +func newDbSqlApp(dbSqlRepo repository.DbSql) DbSql { + app := new(dbSqlAppImpl) + app.Repo = dbSqlRepo + return app +} diff --git a/server/internal/db/application/db_sql_exec.go b/server/internal/db/application/db_sql_exec.go index 79f54034..b5d10509 100644 --- a/server/internal/db/application/db_sql_exec.go +++ b/server/internal/db/application/db_sql_exec.go @@ -1,6 +1,7 @@ package application import ( + "context" "encoding/json" "fmt" "mayfly-go/internal/db/config" @@ -49,7 +50,7 @@ type DbSqlExec interface { Exec(execSqlReq *DbSqlExecReq) (*DbSqlExecRes, error) // 根据条件删除sql执行记录 - DeleteBy(condition *entity.DbSqlExec) + DeleteBy(ctx context.Context, condition *entity.DbSqlExec) // 分页获取 GetPageList(condition *entity.DbSqlExecQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error) @@ -139,19 +140,19 @@ func (d *dbSqlExecAppImpl) Exec(execSqlReq *DbSqlExecReq) (*DbSqlExecRes, error) // 保存sql执行记录,如果是查询类则根据系统配置判断是否保存 func (d *dbSqlExecAppImpl) saveSqlExecLog(isQuery bool, dbSqlExecRecord *entity.DbSqlExec) { if !isQuery { - d.dbSqlExecRepo.Insert(dbSqlExecRecord) + d.dbSqlExecRepo.Insert(context.TODO(), dbSqlExecRecord) return } if config.GetDbSaveQuerySql() { dbSqlExecRecord.Table = "-" dbSqlExecRecord.OldValue = "-" dbSqlExecRecord.Type = entity.DbSqlExecTypeQuery - d.dbSqlExecRepo.Insert(dbSqlExecRecord) + d.dbSqlExecRepo.Insert(context.TODO(), dbSqlExecRecord) } } -func (d *dbSqlExecAppImpl) DeleteBy(condition *entity.DbSqlExec) { - d.dbSqlExecRepo.DeleteByCond(condition) +func (d *dbSqlExecAppImpl) DeleteBy(ctx context.Context, condition *entity.DbSqlExec) { + d.dbSqlExecRepo.DeleteByCond(ctx, condition) } func (d *dbSqlExecAppImpl) GetPageList(condition *entity.DbSqlExecQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error) { diff --git a/server/internal/db/application/instance.go b/server/internal/db/application/instance.go index 106b449d..d5edde63 100644 --- a/server/internal/db/application/instance.go +++ b/server/internal/db/application/instance.go @@ -1,6 +1,7 @@ package application import ( + "context" "mayfly-go/internal/db/domain/entity" "mayfly-go/internal/db/domain/repository" "mayfly-go/pkg/base" @@ -16,10 +17,10 @@ type Instance interface { Count(condition *entity.InstanceQuery) int64 - Save(instanceEntity *entity.DbInstance) error + Save(ctx context.Context, instanceEntity *entity.DbInstance) error // Delete 删除数据库信息 - Delete(id uint64) error + Delete(ctx context.Context, id uint64) error // GetDatabases 获取数据库实例的所有数据库列表 GetDatabases(entity *entity.DbInstance) ([]string, error) @@ -44,7 +45,7 @@ func (app *instanceAppImpl) Count(condition *entity.InstanceQuery) int64 { return app.CountByCond(condition) } -func (app *instanceAppImpl) Save(instanceEntity *entity.DbInstance) error { +func (app *instanceAppImpl) Save(ctx context.Context, instanceEntity *entity.DbInstance) error { // 默认tcp连接 instanceEntity.Network = instanceEntity.GetNetwork() @@ -72,7 +73,7 @@ func (app *instanceAppImpl) Save(instanceEntity *entity.DbInstance) error { return errorx.NewBiz("该数据库实例已存在") } instanceEntity.PwdEncrypt() - return app.Insert(instanceEntity) + return app.Insert(ctx, instanceEntity) } // 如果存在该库,则校验修改的库是否为该库 @@ -80,11 +81,11 @@ func (app *instanceAppImpl) Save(instanceEntity *entity.DbInstance) error { return errorx.NewBiz("该数据库实例已存在") } instanceEntity.PwdEncrypt() - return app.UpdateById(instanceEntity) + return app.UpdateById(ctx, instanceEntity) } -func (app *instanceAppImpl) Delete(id uint64) error { - return app.DeleteById(id) +func (app *instanceAppImpl) Delete(ctx context.Context, id uint64) error { + return app.DeleteById(ctx, id) } func (app *instanceAppImpl) GetDatabases(ed *entity.DbInstance) ([]string, error) { diff --git a/server/internal/db/router/db.go b/server/internal/db/router/db.go index 99831f9a..620eed4a 100644 --- a/server/internal/db/router/db.go +++ b/server/internal/db/router/db.go @@ -46,15 +46,6 @@ func InitDbRouter(router *gin.RouterGroup) { req.NewGet(":dbId/c-metadata", d.ColumnMA), req.NewGet(":dbId/hint-tables", d.HintTables), - - // 用户sql相关 - req.NewPost(":dbId/sql", d.SaveSql), - - req.NewGet(":dbId/sql", d.GetSql), - - req.NewDelete(":dbId/sql", d.DeleteSql), - - req.NewGet(":dbId/sql-names", d.GetSqlNames), } req.BatchSetGroup(db, reqs[:]) diff --git a/server/internal/db/router/db_sql.go b/server/internal/db/router/db_sql.go new file mode 100644 index 00000000..9f7f7150 --- /dev/null +++ b/server/internal/db/router/db_sql.go @@ -0,0 +1,32 @@ +package router + +import ( + "mayfly-go/internal/db/api" + "mayfly-go/internal/db/application" + "mayfly-go/pkg/req" + + "github.com/gin-gonic/gin" +) + +func InitDbSqlRouter(router *gin.RouterGroup) { + db := router.Group("dbs") + + dbSql := &api.DbSql{ + DbSqlApp: application.GetDbSqlApp(), + } + + reqs := [...]*req.Conf{ + + // 用户sql相关 + req.NewPost(":dbId/sql", dbSql.SaveSql), + + req.NewGet(":dbId/sql", dbSql.GetSql), + + req.NewDelete(":dbId/sql", dbSql.DeleteSql), + + req.NewGet(":dbId/sql-names", dbSql.GetSqlNames), + } + + req.BatchSetGroup(db, reqs[:]) + +} diff --git a/server/internal/db/router/router.go b/server/internal/db/router/router.go index 8808b91f..c6622b32 100644 --- a/server/internal/db/router/router.go +++ b/server/internal/db/router/router.go @@ -5,5 +5,6 @@ import "github.com/gin-gonic/gin" func Init(router *gin.RouterGroup) { InitInstanceRouter(router) InitDbRouter(router) + InitDbSqlRouter(router) InitDbSqlExecRouter(router) } diff --git a/server/internal/machine/api/auth_cert.go b/server/internal/machine/api/auth_cert.go index 9b929636..d6a2b3ab 100644 --- a/server/internal/machine/api/auth_cert.go +++ b/server/internal/machine/api/auth_cert.go @@ -44,8 +44,7 @@ func (c *AuthCert) SaveAuthCert(rc *req.Ctx) { acForm.Password = "***" rc.ReqParam = acForm - ac.SetBaseInfo(rc.LoginAccount) - biz.ErrIsNil(c.AuthCertApp.Save(ac)) + biz.ErrIsNil(c.AuthCertApp.Save(rc.MetaCtx, ac)) } func (c *AuthCert) Delete(rc *req.Ctx) { @@ -56,6 +55,6 @@ func (c *AuthCert) Delete(rc *req.Ctx) { for _, v := range ids { value, err := strconv.Atoi(v) biz.ErrIsNilAppendErr(err, "string类型转换为int异常: %s") - c.AuthCertApp.DeleteById(uint64(value)) + c.AuthCertApp.DeleteById(rc.MetaCtx, uint64(value)) } } diff --git a/server/internal/machine/api/machine.go b/server/internal/machine/api/machine.go index 0f04a9d9..062390f6 100644 --- a/server/internal/machine/api/machine.go +++ b/server/internal/machine/api/machine.go @@ -39,7 +39,7 @@ func (m *Machine) Machines(rc *req.Ctx) { condition, pageParam := ginx.BindQueryAndPage(rc.GinCtx, new(entity.MachineQuery)) // 不存在可访问标签id,即没有可操作数据 - tagIds := m.TagApp.ListTagIdByAccountId(rc.LoginAccount.Id) + tagIds := m.TagApp.ListTagIdByAccountId(rc.GetLoginAccount().Id) if len(tagIds) == 0 { rc.ResData = model.EmptyPageResult[any]() return @@ -55,12 +55,20 @@ func (m *Machine) Machines(rc *req.Ctx) { for _, mv := range *res.List { mv.HasCli = mcm.HasCli(mv.Id) + if machineStats, err := m.MachineApp.GetMachineStats(mv.Id); err == nil { + mv.Stat = collx.M{ + "cpuIdle": machineStats.CPU.Idle, + "memAvailable": machineStats.MemInfo.Available, + "memTotal": machineStats.MemInfo.Total, + "fsInfos": machineStats.FSInfos, + } + } } rc.ResData = res } func (m *Machine) MachineTags(rc *req.Ctx) { - rc.ResData = m.TagApp.ListTagByAccountIdAndResource(rc.LoginAccount.Id, new(entity.Machine)) + rc.ResData = m.TagApp.ListTagByAccountIdAndResource(rc.GetLoginAccount().Id, new(entity.Machine)) } func (m *Machine) MachineStats(rc *req.Ctx) { @@ -77,8 +85,7 @@ func (m *Machine) SaveMachine(rc *req.Ctx) { machineForm.Password = "******" rc.ReqParam = machineForm - me.SetBaseInfo(rc.LoginAccount) - biz.ErrIsNil(m.MachineApp.Save(me)) + biz.ErrIsNil(m.MachineApp.Save(rc.MetaCtx, me)) } func (m *Machine) TestConn(rc *req.Ctx) { @@ -92,7 +99,7 @@ func (m *Machine) ChangeStatus(rc *req.Ctx) { id := uint64(ginx.PathParamInt(g, "machineId")) status := int8(ginx.PathParamInt(g, "status")) rc.ReqParam = collx.Kvs("id", id, "status", status) - biz.ErrIsNil(m.MachineApp.ChangeStatus(id, status)) + biz.ErrIsNil(m.MachineApp.ChangeStatus(rc.MetaCtx, id, status)) } func (m *Machine) DeleteMachine(rc *req.Ctx) { @@ -103,7 +110,7 @@ func (m *Machine) DeleteMachine(rc *req.Ctx) { for _, v := range ids { value, err := strconv.Atoi(v) biz.ErrIsNilAppendErr(err, "string类型转换为int异常: %s") - m.MachineApp.Delete(uint64(value)) + m.MachineApp.Delete(rc.MetaCtx, uint64(value)) } } @@ -133,7 +140,7 @@ func (m *Machine) GetProcess(rc *req.Ctx) { cli, err := m.MachineApp.GetCli(GetMachineId(rc.GinCtx)) biz.ErrIsNilAppendErr(err, "获取客户端连接失败: %s") - biz.ErrIsNilAppendErr(m.TagApp.CanAccess(rc.LoginAccount.Id, cli.Info.TagPath), "%s") + biz.ErrIsNilAppendErr(m.TagApp.CanAccess(rc.GetLoginAccount().Id, cli.Info.TagPath), "%s") res, err := cli.Run(cmd) biz.ErrIsNilAppendErr(err, "获取进程信息失败: %s") @@ -147,7 +154,7 @@ func (m *Machine) KillProcess(rc *req.Ctx) { cli, err := m.MachineApp.GetCli(GetMachineId(rc.GinCtx)) biz.ErrIsNilAppendErr(err, "获取客户端连接失败: %s") - biz.ErrIsNilAppendErr(m.TagApp.CanAccess(rc.LoginAccount.Id, cli.Info.TagPath), "%s") + biz.ErrIsNilAppendErr(m.TagApp.CanAccess(rc.GetLoginAccount().Id, cli.Info.TagPath), "%s") res, err := cli.Run("sudo kill -9 " + pid) biz.ErrIsNil(err, "终止进程失败: %s", res) @@ -173,7 +180,7 @@ func (m *Machine) WsSSH(g *gin.Context) { cli, err := m.MachineApp.GetCli(GetMachineId(g)) biz.ErrIsNilAppendErr(err, "获取客户端连接失败: %s") - biz.ErrIsNilAppendErr(m.TagApp.CanAccess(rc.LoginAccount.Id, cli.Info.TagPath), "%s") + biz.ErrIsNilAppendErr(m.TagApp.CanAccess(rc.GetLoginAccount().Id, cli.Info.TagPath), "%s") cols := ginx.QueryInt(g, "cols", 80) rows := ginx.QueryInt(g, "rows", 40) @@ -182,7 +189,7 @@ func (m *Machine) WsSSH(g *gin.Context) { if cli.Info.EnableRecorder == 1 { now := time.Now() // 回放文件路径为: 基础配置路径/机器id/操作日期/操作者账号/操作时间.cast - recPath := fmt.Sprintf("%s/%d/%s/%s", config.Conf.Server.GetMachineRecPath(), cli.Info.Id, now.Format("20060102"), rc.LoginAccount.Username) + recPath := fmt.Sprintf("%s/%d/%s/%s", config.Conf.Server.GetMachineRecPath(), cli.Info.Id, now.Format("20060102"), rc.GetLoginAccount().Username) os.MkdirAll(recPath, 0766) fileName := path.Join(recPath, fmt.Sprintf("%s.cast", now.Format("20060102_150405"))) f, err := os.OpenFile(fileName, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0766) diff --git a/server/internal/machine/api/machine_cronjob.go b/server/internal/machine/api/machine_cronjob.go index ba220b99..90c1af8a 100644 --- a/server/internal/machine/api/machine_cronjob.go +++ b/server/internal/machine/api/machine_cronjob.go @@ -35,12 +35,12 @@ func (m *MachineCronJob) Save(rc *req.Ctx) { jobForm := new(form.MachineCronJobForm) mcj := ginx.BindJsonAndCopyTo[*entity.MachineCronJob](rc.GinCtx, jobForm, new(entity.MachineCronJob)) rc.ReqParam = jobForm - mcj.SetBaseInfo(rc.LoginAccount) - cronJobId, err := m.MachineCronJobApp.Save(mcj) + + cronJobId, err := m.MachineCronJobApp.Save(rc.MetaCtx, mcj) biz.ErrIsNil(err) // 关联机器 - m.MachineCronJobApp.CronJobRelateMachines(cronJobId, jobForm.MachineIds, rc.LoginAccount) + m.MachineCronJobApp.CronJobRelateMachines(rc.MetaCtx, cronJobId, jobForm.MachineIds) } func (m *MachineCronJob) Delete(rc *req.Ctx) { @@ -51,7 +51,7 @@ func (m *MachineCronJob) Delete(rc *req.Ctx) { for _, v := range ids { value, err := strconv.Atoi(v) biz.ErrIsNilAppendErr(err, "string类型转换为int异常: %s") - m.MachineCronJobApp.Delete(uint64(value)) + m.MachineCronJobApp.Delete(rc.MetaCtx, uint64(value)) } } diff --git a/server/internal/machine/api/machine_file.go b/server/internal/machine/api/machine_file.go index b4fa640c..67f56459 100644 --- a/server/internal/machine/api/machine_file.go +++ b/server/internal/machine/api/machine_file.go @@ -52,14 +52,13 @@ func (m *MachineFile) MachineFiles(rc *req.Ctx) { func (m *MachineFile) SaveMachineFiles(rc *req.Ctx) { fileForm := new(form.MachineFileForm) entity := ginx.BindJsonAndCopyTo[*entity.MachineFile](rc.GinCtx, fileForm, new(entity.MachineFile)) - entity.SetBaseInfo(rc.LoginAccount) rc.ReqParam = fileForm - biz.ErrIsNil(m.MachineFileApp.Save(entity)) + biz.ErrIsNil(m.MachineFileApp.Save(rc.MetaCtx, entity)) } func (m *MachineFile) DeleteFile(rc *req.Ctx) { - biz.ErrIsNil(m.MachineFileApp.Delete(GetMachineFileId(rc.GinCtx))) + biz.ErrIsNil(m.MachineFileApp.Delete(rc.MetaCtx, GetMachineFileId(rc.GinCtx))) } /*** sftp相关操作 */ @@ -190,7 +189,7 @@ func (m *MachineFile) UploadFile(rc *req.Ctx) { file, _ := fileheader.Open() defer file.Close() - la := rc.LoginAccount + la := rc.GetLoginAccount() defer func() { if anyx.ToString(recover()) != "" { logx.Errorf("文件上传失败: %s", err) @@ -262,7 +261,7 @@ func (m *MachineFile) UploadFolder(rc *req.Ctx) { wg.Add(len(chunks)) isSuccess := true - la := rc.LoginAccount + la := rc.GetLoginAccount() for _, chunk := range chunks { go func(files []FolderFile, wg *sync.WaitGroup) { defer func() { @@ -298,7 +297,7 @@ func (m *MachineFile) UploadFolder(rc *req.Ctx) { wg.Wait() if isSuccess { // 保存消息并发送文件上传成功通知 - m.MsgApp.CreateAndSend(rc.LoginAccount, msgdto.SuccessSysMsg("文件上传成功", fmt.Sprintf("[%s]文件夹已成功上传至 %s[%s:%s]", folderName, mi.Name, mi.Ip, basePath))) + m.MsgApp.CreateAndSend(la, msgdto.SuccessSysMsg("文件上传成功", fmt.Sprintf("[%s]文件夹已成功上传至 %s[%s:%s]", folderName, mi.Name, mi.Ip, basePath))) } } diff --git a/server/internal/machine/api/machine_script.go b/server/internal/machine/api/machine_script.go index b1fa68a5..78b17255 100644 --- a/server/internal/machine/api/machine_script.go +++ b/server/internal/machine/api/machine_script.go @@ -37,9 +37,7 @@ func (m *MachineScript) SaveMachineScript(rc *req.Ctx) { machineScript := ginx.BindJsonAndCopyTo(rc.GinCtx, form, new(entity.MachineScript)) rc.ReqParam = form - machineScript.SetBaseInfo(rc.LoginAccount) - - biz.ErrIsNil(m.MachineScriptApp.Save(machineScript)) + biz.ErrIsNil(m.MachineScriptApp.Save(rc.MetaCtx, machineScript)) } func (m *MachineScript) DeleteMachineScript(rc *req.Ctx) { @@ -50,7 +48,7 @@ func (m *MachineScript) DeleteMachineScript(rc *req.Ctx) { for _, v := range ids { value, err := strconv.Atoi(v) biz.ErrIsNilAppendErr(err, "string类型转换为int异常: %s") - m.MachineScriptApp.Delete(uint64(value)) + m.MachineScriptApp.Delete(rc.MetaCtx, uint64(value)) } } @@ -71,7 +69,7 @@ func (m *MachineScript) RunMachineScript(rc *req.Ctx) { } cli, err := m.MachineApp.GetCli(machineId) biz.ErrIsNilAppendErr(err, "获取客户端连接失败: %s") - biz.ErrIsNilAppendErr(m.TagApp.CanAccess(rc.LoginAccount.Id, cli.Info.TagPath), "%s") + biz.ErrIsNilAppendErr(m.TagApp.CanAccess(rc.GetLoginAccount().Id, cli.Info.TagPath), "%s") res, err := cli.Run(script) // 记录请求参数 diff --git a/server/internal/machine/api/vo/vo.go b/server/internal/machine/api/vo/vo.go index 685f5510..bc00a651 100644 --- a/server/internal/machine/api/vo/vo.go +++ b/server/internal/machine/api/vo/vo.go @@ -26,11 +26,13 @@ type MachineVO struct { UpdateTime *time.Time `json:"updateTime"` Modifier *string `json:"modifier"` ModifierId *int64 `json:"modifierId"` - HasCli bool `json:"hasCli" gorm:"-"` Remark *string `json:"remark"` EnableRecorder int8 `json:"enableRecorder"` TagId uint64 `json:"tagId"` TagPath string `json:"tagPath"` + + HasCli bool `json:"hasCli" gorm:"-"` + Stat map[string]any `json:"stat" gorm:"-"` } type MachineScriptVO struct { diff --git a/server/internal/machine/application/auth_cert.go b/server/internal/machine/application/auth_cert.go index ccba8ff6..d95647ef 100644 --- a/server/internal/machine/application/auth_cert.go +++ b/server/internal/machine/application/auth_cert.go @@ -1,6 +1,7 @@ package application import ( + "context" "mayfly-go/internal/machine/domain/entity" "mayfly-go/internal/machine/domain/repository" "mayfly-go/pkg/base" @@ -13,7 +14,7 @@ type AuthCert interface { GetPageList(condition *entity.AuthCertQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error) - Save(ac *entity.AuthCert) error + Save(ctx context.Context, ac *entity.AuthCert) error GetByIds(ids ...uint64) []*entity.AuthCert } @@ -32,7 +33,7 @@ func (a *authCertAppImpl) GetPageList(condition *entity.AuthCertQuery, pageParam return a.GetRepo().GetPageList(condition, pageParam, toEntity) } -func (a *authCertAppImpl) Save(ac *entity.AuthCert) error { +func (a *authCertAppImpl) Save(ctx context.Context, ac *entity.AuthCert) error { oldAc := &entity.AuthCert{Name: ac.Name} err := a.GetBy(oldAc, "Id", "Name") @@ -41,14 +42,14 @@ func (a *authCertAppImpl) Save(ac *entity.AuthCert) error { if err == nil { return errorx.NewBiz("该凭证名已存在") } - return a.Insert(ac) + return a.Insert(ctx, ac) } // 如果存在该库,则校验修改的库是否为该库 if err == nil && oldAc.Id != ac.Id { return errorx.NewBiz("该凭证名已存在") } - return a.UpdateById(ac) + return a.UpdateById(ctx, ac) } func (a *authCertAppImpl) GetByIds(ids ...uint64) []*entity.AuthCert { diff --git a/server/internal/machine/application/machine.go b/server/internal/machine/application/machine.go index 251b16aa..6ef8623c 100644 --- a/server/internal/machine/application/machine.go +++ b/server/internal/machine/application/machine.go @@ -1,14 +1,20 @@ package application import ( + "context" + "fmt" "mayfly-go/internal/machine/api/vo" "mayfly-go/internal/machine/domain/entity" "mayfly-go/internal/machine/domain/repository" + "mayfly-go/internal/machine/infrastructure/cache" "mayfly-go/internal/machine/mcm" "mayfly-go/pkg/base" "mayfly-go/pkg/errorx" "mayfly-go/pkg/gormx" + "mayfly-go/pkg/logx" "mayfly-go/pkg/model" + "mayfly-go/pkg/scheduler" + "time" "gorm.io/gorm" ) @@ -16,17 +22,17 @@ import ( type Machine interface { base.App[*entity.Machine] - Save(*entity.Machine) error + Save(ctx context.Context, m *entity.Machine) error // 测试机器连接 TestConn(me *entity.Machine) error // 调整机器状态 - ChangeStatus(id uint64, status int8) error + ChangeStatus(ctx context.Context, id uint64, status int8) error Count(condition *entity.MachineQuery) int64 - Delete(id uint64) error + Delete(ctx context.Context, id uint64) error // 分页获取机器信息列表 GetMachineList(condition *entity.MachineQuery, pageParam *model.PageParam, toEntity *[]*vo.MachineVO, orderBy ...string) (*model.PageResult[*[]*vo.MachineVO], error) @@ -36,6 +42,12 @@ type Machine interface { // 获取ssh隧道机器连接 GetSshTunnelMachine(id int) (*mcm.SshTunnelMachine, error) + + // 定时更新机器状态信息 + TimerUpdateStats() + + // 获取机器运行时状态信息 + GetMachineStats(machineId uint64) (*mcm.Stats, error) } func newMachineApp(machineRepo repository.Machine, authCertApp AuthCert) Machine { @@ -61,7 +73,7 @@ func (m *machineAppImpl) Count(condition *entity.MachineQuery) int64 { return m.GetRepo().Count(condition) } -func (m *machineAppImpl) Save(me *entity.Machine) error { +func (m *machineAppImpl) Save(ctx context.Context, me *entity.Machine) error { oldMachine := &entity.Machine{Ip: me.Ip, Port: me.Port, Username: me.Username} if me.SshTunnelMachineId > 0 { oldMachine.SshTunnelMachineId = me.SshTunnelMachineId @@ -75,7 +87,7 @@ func (m *machineAppImpl) Save(me *entity.Machine) error { } // 新增机器,默认启用状态 me.Status = entity.MachineStatusEnable - return m.Insert(me) + return m.Insert(ctx, me) } // 如果存在该库,则校验修改的库是否为该库 @@ -85,7 +97,7 @@ func (m *machineAppImpl) Save(me *entity.Machine) error { // 关闭连接 mcm.DeleteCli(me.Id) - return m.UpdateById(me) + return m.UpdateById(ctx, me) } func (m *machineAppImpl) TestConn(me *entity.Machine) error { @@ -102,7 +114,7 @@ func (m *machineAppImpl) TestConn(me *entity.Machine) error { return nil } -func (m *machineAppImpl) ChangeStatus(id uint64, status int8) error { +func (m *machineAppImpl) ChangeStatus(ctx context.Context, id uint64, status int8) error { if status == entity.MachineStatusDisable { // 关闭连接 mcm.DeleteCli(id) @@ -110,11 +122,11 @@ func (m *machineAppImpl) ChangeStatus(id uint64, status int8) error { machine := new(entity.Machine) machine.Id = id machine.Status = status - return m.UpdateById(machine) + return m.UpdateById(ctx, machine) } // 根据条件获取机器信息 -func (m *machineAppImpl) Delete(id uint64) error { +func (m *machineAppImpl) Delete(ctx context.Context, id uint64) error { // 关闭连接 mcm.DeleteCli(id) return gormx.Tx( @@ -145,6 +157,39 @@ func (m *machineAppImpl) GetSshTunnelMachine(machineId int) (*mcm.SshTunnelMachi }) } +func (m *machineAppImpl) TimerUpdateStats() { + logx.Debug("开始定时收集并缓存服务器状态信息...") + scheduler.AddFun("@every 2m", func() { + machineIds := new([]entity.Machine) + m.GetRepo().ListByCond(&entity.Machine{Status: entity.MachineStatusEnable}, machineIds, "id") + for _, ma := range *machineIds { + go func(mid uint64) { + defer func() { + if err := recover(); err != nil { + logx.ErrorTrace(fmt.Sprintf("定时获取机器[id=%d]状态信息失败", mid), err.(error)) + } + }() + logx.Debugf("定时获取机器[id=%d]状态信息开始", mid) + cli, err := m.GetCli(mid) + // ssh获取客户端失败,则更新机器状态为禁用 + if err != nil { + updateMachine := &entity.Machine{Status: entity.MachineStatusDisable} + updateMachine.Id = mid + now := time.Now() + updateMachine.UpdateTime = &now + m.UpdateById(context.TODO(), updateMachine) + } + cache.SaveMachineStats(mid, cli.GetAllStats()) + logx.Debugf("定时获取机器[id=%d]状态信息结束", mid) + }(ma.Id) + } + }) +} + +func (m *machineAppImpl) GetMachineStats(machineId uint64) (*mcm.Stats, error) { + return cache.GetMachineStats(machineId) +} + // 生成机器信息,根据授权凭证id填充用户密码等 func (m *machineAppImpl) toMachineInfoById(machineId uint64) (*mcm.MachineInfo, error) { me, err := m.GetById(new(entity.Machine), machineId) diff --git a/server/internal/machine/application/machine_cronjob.go b/server/internal/machine/application/machine_cronjob.go index 8b8a097f..e5b111c5 100644 --- a/server/internal/machine/application/machine_cronjob.go +++ b/server/internal/machine/application/machine_cronjob.go @@ -1,6 +1,7 @@ package application import ( + "context" "mayfly-go/internal/machine/domain/entity" "mayfly-go/internal/machine/domain/repository" "mayfly-go/pkg/base" @@ -25,9 +26,9 @@ type MachineCronJob interface { // 获取分页执行结果列表 GetExecPageList(condition *entity.MachineCronJobExec, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error) - Save(entity *entity.MachineCronJob) (uint64, error) + Save(ctx context.Context, entity *entity.MachineCronJob) (uint64, error) - Delete(id uint64) + Delete(ctx context.Context, id uint64) // 获取计划任务关联的机器列表id GetRelateMachineIds(cronJobId uint64) []uint64 @@ -36,10 +37,10 @@ type MachineCronJob interface { GetRelateCronJobIds(machineId uint64) []uint64 // 计划任务关联机器 - CronJobRelateMachines(cronJobId uint64, machineIds []uint64, la *model.LoginAccount) + CronJobRelateMachines(ctx context.Context, cronJobId uint64, machineIds []uint64) // 机器关联计划任务 - MachineRelateCronJobs(machineId uint64, cronJobs []uint64, la *model.LoginAccount) + MachineRelateCronJobs(ctx context.Context, machineId uint64, cronJobs []uint64) // 初始化计划任务 InitCronJob() @@ -79,10 +80,10 @@ func (m *machineCropJobAppImpl) GetExecPageList(condition *entity.MachineCronJob } // 保存机器任务信息 -func (m *machineCropJobAppImpl) Save(mcj *entity.MachineCronJob) (uint64, error) { +func (m *machineCropJobAppImpl) Save(ctx context.Context, mcj *entity.MachineCronJob) (uint64, error) { // 更新操作 if mcj.Id != 0 { - m.UpdateById(mcj) + m.UpdateById(ctx, mcj) cj, err := m.GetById(new(entity.MachineCronJob), mcj.Id) if err != nil { return 0, errorx.NewBiz("该任务不存在") @@ -93,16 +94,16 @@ func (m *machineCropJobAppImpl) Save(mcj *entity.MachineCronJob) (uint64, error) } m.addCronJob(mcj) - if err := m.Insert(mcj); err != nil { + if err := m.Insert(ctx, mcj); err != nil { return 0, err } return mcj.Id, nil } -func (m *machineCropJobAppImpl) Delete(id uint64) { - m.DeleteById(id) - m.machineCropJobExecRepo.DeleteByCond(&entity.MachineCronJobExec{CronJobId: id}) - m.machineCropJobRelateRepo.DeleteByCond(&entity.MachineCronJobRelate{CronJobId: id}) +func (m *machineCropJobAppImpl) Delete(ctx context.Context, id uint64) { + m.DeleteById(ctx, id) + m.machineCropJobExecRepo.DeleteByCond(ctx, &entity.MachineCronJobExec{CronJobId: id}) + m.machineCropJobRelateRepo.DeleteByCond(ctx, &entity.MachineCronJobRelate{CronJobId: id}) } func (m *machineCropJobAppImpl) GetRelateMachineIds(cronJobId uint64) []uint64 { @@ -113,47 +114,39 @@ func (m *machineCropJobAppImpl) GetRelateCronJobIds(machineId uint64) []uint64 { return m.machineCropJobRelateRepo.GetCronJobIds(machineId) } -func (m *machineCropJobAppImpl) CronJobRelateMachines(cronJobId uint64, machineIds []uint64, la *model.LoginAccount) { +func (m *machineCropJobAppImpl) CronJobRelateMachines(ctx context.Context, cronJobId uint64, machineIds []uint64) { oldMachineIds := m.machineCropJobRelateRepo.GetMachineIds(cronJobId) addIds, delIds, _ := collx.ArrayCompare[uint64](machineIds, oldMachineIds, func(u1, u2 uint64) bool { return u1 == u2 }) addVals := make([]*entity.MachineCronJobRelate, 0) - now := time.Now() for _, addId := range addIds { addVals = append(addVals, &entity.MachineCronJobRelate{ - MachineId: addId, - CronJobId: cronJobId, - Creator: la.Username, - CreatorId: la.Id, - CreateTime: &now, + MachineId: addId, + CronJobId: cronJobId, }) } - m.machineCropJobRelateRepo.BatchInsert(addVals) + m.machineCropJobRelateRepo.BatchInsert(ctx, addVals) for _, delId := range delIds { - m.machineCropJobRelateRepo.DeleteByCond(&entity.MachineCronJobRelate{CronJobId: cronJobId, MachineId: delId}) + m.machineCropJobRelateRepo.DeleteByCond(ctx, &entity.MachineCronJobRelate{CronJobId: cronJobId, MachineId: delId}) } } -func (m *machineCropJobAppImpl) MachineRelateCronJobs(machineId uint64, cronJobs []uint64, la *model.LoginAccount) { +func (m *machineCropJobAppImpl) MachineRelateCronJobs(ctx context.Context, machineId uint64, cronJobs []uint64) { oldCronIds := m.machineCropJobRelateRepo.GetCronJobIds(machineId) addIds, delIds, _ := collx.ArrayCompare[uint64](cronJobs, oldCronIds, func(u1, u2 uint64) bool { return u1 == u2 }) addVals := make([]*entity.MachineCronJobRelate, 0) - now := time.Now() for _, addId := range addIds { addVals = append(addVals, &entity.MachineCronJobRelate{ - MachineId: machineId, - CronJobId: addId, - Creator: la.Username, - CreatorId: la.Id, - CreateTime: &now, + MachineId: machineId, + CronJobId: addId, }) } - m.machineCropJobRelateRepo.BatchInsert(addVals) + m.machineCropJobRelateRepo.BatchInsert(ctx, addVals) for _, delId := range delIds { - m.machineCropJobRelateRepo.DeleteByCond(&entity.MachineCronJobRelate{CronJobId: delId, MachineId: machineId}) + m.machineCropJobRelateRepo.DeleteByCond(ctx, &entity.MachineCronJobRelate{CronJobId: delId, MachineId: machineId}) } } @@ -240,7 +233,7 @@ func (m *machineCropJobAppImpl) runCronJob0(mid uint64, cronJob *entity.MachineC defer func() { if err := recover(); err != nil { res := anyx.ToString(err) - m.machineCropJobExecRepo.Insert(&entity.MachineCronJobExec{ + m.machineCropJobExecRepo.Insert(context.TODO(), &entity.MachineCronJobExec{ MachineId: mid, CronJobId: cronJob.Id, ExecTime: time.Now(), @@ -280,5 +273,5 @@ func (m *machineCropJobAppImpl) runCronJob0(mid uint64, cronJob *entity.MachineC execRes.Status = entity.MachineCronJobExecStatusError } // 保存执行记录 - m.machineCropJobExecRepo.Insert(execRes) + m.machineCropJobExecRepo.Insert(context.TODO(), execRes) } diff --git a/server/internal/machine/application/machine_file.go b/server/internal/machine/application/machine_file.go index f30dcff7..1a363674 100644 --- a/server/internal/machine/application/machine_file.go +++ b/server/internal/machine/application/machine_file.go @@ -1,6 +1,7 @@ package application import ( + "context" "errors" "fmt" "io" @@ -27,9 +28,9 @@ type MachineFile interface { // 根据id获取 GetById(id uint64, cols ...string) *entity.MachineFile - Save(entity *entity.MachineFile) error + Save(ctx context.Context, entity *entity.MachineFile) error - Delete(id uint64) error + Delete(ctx context.Context, id uint64) error // 获取文件关联的机器信息,主要用于记录日志使用 // GetMachine(fileId uint64) *mcm.Info @@ -91,31 +92,34 @@ func (m *machineFileAppImpl) GetPageList(condition *entity.MachineFile, pagePara // 根据条件获取 func (m *machineFileAppImpl) GetMachineFile(condition *entity.MachineFile, cols ...string) error { - return m.machineFileRepo.GetMachineFile(condition, cols...) + return m.machineFileRepo.GetBy(condition, cols...) } // 根据id获取 func (m *machineFileAppImpl) GetById(id uint64, cols ...string) *entity.MachineFile { - return m.machineFileRepo.GetById(id, cols...) + mf := new(entity.MachineFile) + if err := m.machineFileRepo.GetById(mf, id, cols...); err == nil { + return mf + } + return nil } // 保存机器文件配置 -func (m *machineFileAppImpl) Save(mf *entity.MachineFile) error { +func (m *machineFileAppImpl) Save(ctx context.Context, mf *entity.MachineFile) error { _, err := m.machineApp.GetById(new(entity.Machine), mf.MachineId, "Name") if err != nil { return errorx.NewBiz("该机器不存在") } if mf.Id != 0 { - return m.machineFileRepo.UpdateById(mf) + return m.machineFileRepo.UpdateById(ctx, mf) } - return m.machineFileRepo.Create(mf) + return m.machineFileRepo.Insert(ctx, mf) } -// 根据id删除 -func (m *machineFileAppImpl) Delete(id uint64) error { - return m.machineFileRepo.Delete(id) +func (m *machineFileAppImpl) Delete(ctx context.Context, id uint64) error { + return m.machineFileRepo.DeleteById(ctx, id) } func (m *machineFileAppImpl) ReadDir(fid uint64, path string) ([]fs.FileInfo, error) { diff --git a/server/internal/machine/application/machine_script.go b/server/internal/machine/application/machine_script.go index 20f015f4..16faef67 100644 --- a/server/internal/machine/application/machine_script.go +++ b/server/internal/machine/application/machine_script.go @@ -1,6 +1,7 @@ package application import ( + "context" "mayfly-go/internal/machine/domain/entity" "mayfly-go/internal/machine/domain/repository" "mayfly-go/pkg/base" @@ -14,9 +15,9 @@ type MachineScript interface { // 分页获取机器脚本信息列表 GetPageList(condition *entity.MachineScript, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error) - Save(entity *entity.MachineScript) error + Save(ctx context.Context, entity *entity.MachineScript) error - Delete(id uint64) + Delete(ctx context.Context, id uint64) } func newMachineScriptApp(machineScriptRepo repository.MachineScript, machineApp Machine) MachineScript { @@ -39,7 +40,7 @@ func (m *machineScriptAppImpl) GetPageList(condition *entity.MachineScript, page } // 保存机器脚本 -func (m *machineScriptAppImpl) Save(ms *entity.MachineScript) error { +func (m *machineScriptAppImpl) Save(ctx context.Context, ms *entity.MachineScript) error { // 如果机器id不为公共脚本id,则校验机器是否存在 if machineId := ms.MachineId; machineId != Common_Script_Machine_Id { _, err := m.machineApp.GetById(new(entity.Machine), machineId, "Name") @@ -49,12 +50,12 @@ func (m *machineScriptAppImpl) Save(ms *entity.MachineScript) error { } if ms.Id != 0 { - return m.UpdateById(ms) + return m.UpdateById(ctx, ms) } - return m.Insert(ms) + return m.Insert(ctx, ms) } // 根据id删除 -func (m *machineScriptAppImpl) Delete(id uint64) { - m.DeleteById(id) +func (m *machineScriptAppImpl) Delete(ctx context.Context, id uint64) { + m.DeleteById(ctx, id) } diff --git a/server/internal/machine/domain/entity/machine_cronjob.go b/server/internal/machine/domain/entity/machine_cronjob.go index 3b900250..a25d3ead 100644 --- a/server/internal/machine/domain/entity/machine_cronjob.go +++ b/server/internal/machine/domain/entity/machine_cronjob.go @@ -30,6 +30,13 @@ type MachineCronJobRelate struct { CreateTime *time.Time } +func (m *MachineCronJobRelate) SetBaseInfo(la *model.LoginAccount) { + now := time.Now() + m.CreateTime = &now + m.Creator = la.Username + m.CreatorId = la.Id +} + // 机器任务执行记录 type MachineCronJobExec struct { model.DeletedModel diff --git a/server/internal/machine/domain/entity/query.go b/server/internal/machine/domain/entity/query.go index ce07db8e..398165cf 100644 --- a/server/internal/machine/domain/entity/query.go +++ b/server/internal/machine/domain/entity/query.go @@ -3,6 +3,7 @@ package entity type MachineQuery struct { Ids string `json:"ids" form:"ids"` Name string `json:"name" form:"name"` + Status int8 `json:"status" form:"status"` Ip string `json:"ip" form:"ip"` // IP地址 TagPath string `json:"tagPath" form:"tagPath"` TagIds []uint64 diff --git a/server/internal/machine/domain/repository/machine_file.go b/server/internal/machine/domain/repository/machine_file.go index a3d91a9a..daac7f75 100644 --- a/server/internal/machine/domain/repository/machine_file.go +++ b/server/internal/machine/domain/repository/machine_file.go @@ -2,22 +2,13 @@ package repository import ( "mayfly-go/internal/machine/domain/entity" + "mayfly-go/pkg/base" "mayfly-go/pkg/model" ) type MachineFile interface { + base.Repo[*entity.MachineFile] + // 分页获取机器脚本信息列表 GetPageList(condition *entity.MachineFile, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error) - - // 根据条件获取 - GetMachineFile(condition *entity.MachineFile, cols ...string) error - - // 根据id获取 - GetById(id uint64, cols ...string) *entity.MachineFile - - Delete(id uint64) error - - Create(entity *entity.MachineFile) error - - UpdateById(entity *entity.MachineFile) error } diff --git a/server/internal/machine/infrastructure/cache/machine_stats.go b/server/internal/machine/infrastructure/cache/machine_stats.go new file mode 100644 index 00000000..e763c406 --- /dev/null +++ b/server/internal/machine/infrastructure/cache/machine_stats.go @@ -0,0 +1,24 @@ +package cache + +import ( + "errors" + "fmt" + "mayfly-go/internal/machine/mcm" + global_cache "mayfly-go/pkg/cache" + "mayfly-go/pkg/utils/jsonx" + "time" +) + +const MachineStatCackeKey = "mayfly:machine:%d:stat" + +func SaveMachineStats(machineId uint64, stat *mcm.Stats) error { + return global_cache.SetStr(fmt.Sprintf(MachineStatCackeKey, machineId), jsonx.ToStr(stat), 10*time.Minute) +} + +func GetMachineStats(machineId uint64) (*mcm.Stats, error) { + cacheStr := global_cache.GetStr(fmt.Sprintf(MachineStatCackeKey, machineId)) + if cacheStr == "" { + return nil, errors.New("不存在该值") + } + return jsonx.To(cacheStr, new(mcm.Stats)) +} diff --git a/server/internal/machine/infrastructure/persistence/machine.go b/server/internal/machine/infrastructure/persistence/machine.go index c15a4d6b..6e126ba8 100644 --- a/server/internal/machine/infrastructure/persistence/machine.go +++ b/server/internal/machine/infrastructure/persistence/machine.go @@ -23,6 +23,7 @@ func newMachineRepo() repository.Machine { // 分页获取机器信息列表 func (m *machineRepoImpl) GetMachineList(condition *entity.MachineQuery, pageParam *model.PageParam, toEntity *[]*vo.MachineVO, orderBy ...string) (*model.PageResult[*[]*vo.MachineVO], error) { qd := gormx.NewQuery(new(entity.Machine)). + Eq("status", condition.Status). Like("ip", condition.Ip). Like("name", condition.Name). In("tag_id", condition.TagIds). diff --git a/server/internal/machine/infrastructure/persistence/machine_file.go b/server/internal/machine/infrastructure/persistence/machine_file.go index e6b36529..cd408f87 100644 --- a/server/internal/machine/infrastructure/persistence/machine_file.go +++ b/server/internal/machine/infrastructure/persistence/machine_file.go @@ -3,14 +3,17 @@ package persistence import ( "mayfly-go/internal/machine/domain/entity" "mayfly-go/internal/machine/domain/repository" + "mayfly-go/pkg/base" "mayfly-go/pkg/gormx" "mayfly-go/pkg/model" ) -type machineFileRepoImpl struct{} +type machineFileRepoImpl struct { + base.RepoImpl[*entity.MachineFile] +} func newMachineFileRepo() repository.MachineFile { - return new(machineFileRepoImpl) + return &machineFileRepoImpl{base.RepoImpl[*entity.MachineFile]{M: new(entity.MachineFile)}} } // 分页获取机器文件信息列表 @@ -18,30 +21,3 @@ func (m *machineFileRepoImpl) GetPageList(condition *entity.MachineFile, pagePar qd := gormx.NewQuery(condition).WithCondModel(condition).WithOrderBy(orderBy...) return gormx.PageQuery(qd, pageParam, toEntity) } - -// 根据条件获取账号信息 -func (m *machineFileRepoImpl) GetMachineFile(condition *entity.MachineFile, cols ...string) error { - return gormx.GetBy(condition, cols...) -} - -// 根据id获取 -func (m *machineFileRepoImpl) GetById(id uint64, cols ...string) *entity.MachineFile { - ms := new(entity.MachineFile) - if err := gormx.GetById(ms, id, cols...); err != nil { - return nil - } - return ms -} - -// 根据id获取 -func (m *machineFileRepoImpl) Delete(id uint64) error { - return gormx.DeleteById(new(entity.MachineFile), id) -} - -func (m *machineFileRepoImpl) Create(entity *entity.MachineFile) error { - return gormx.Insert(entity) -} - -func (m *machineFileRepoImpl) UpdateById(entity *entity.MachineFile) error { - return gormx.UpdateById(entity) -} diff --git a/server/internal/machine/init/init.go b/server/internal/machine/init/init.go index 1e458a52..659dec38 100644 --- a/server/internal/machine/init/init.go +++ b/server/internal/machine/init/init.go @@ -4,4 +4,5 @@ import "mayfly-go/internal/machine/application" func Init() { application.GetMachineCronJobApp().InitCronJob() + application.GetMachineApp().TimerUpdateStats() } diff --git a/server/internal/machine/mcm/client.go b/server/internal/machine/mcm/client.go index 984aa293..00ea8ca9 100644 --- a/server/internal/machine/mcm/client.go +++ b/server/internal/machine/mcm/client.go @@ -42,7 +42,13 @@ func (c *Cli) GetSession() (*ssh.Session, error) { if c.sshClient == nil { return nil, errorx.NewBiz("请先进行机器客户端连接") } - return c.sshClient.NewSession() + session, err := c.sshClient.NewSession() + if err != nil { + // 获取session失败,则关闭cli,重试 + DeleteCli(c.Info.Id) + return nil, errorx.NewBiz("请重试...") + } + return session, nil } // 执行shell @@ -51,7 +57,6 @@ func (c *Cli) GetSession() (*ssh.Session, error) { func (c *Cli) Run(shell string) (string, error) { session, err := c.GetSession() if err != nil { - c.Close() return "", err } defer session.Close() @@ -67,6 +72,10 @@ func (c *Cli) GetAllStats() *Stats { res, _ := c.Run(StatsShell) infos := strings.Split(res, "-----") stats := new(Stats) + if len(infos) < 8 { + logx.Warnf("获取机器[id=%d, name=%s]的状态信息失败", c.Info.Id, c.Info.Name) + return stats + } getUptime(infos[0], stats) getHostname(infos[1], stats) getLoad(infos[2], stats) diff --git a/server/internal/machine/mcm/stats.go b/server/internal/machine/mcm/stats.go index 55e15740..e0ffd330 100644 --- a/server/internal/machine/mcm/stats.go +++ b/server/internal/machine/mcm/stats.go @@ -9,48 +9,52 @@ import ( ) type FSInfo struct { - MountPoint string - Used uint64 - Free uint64 + MountPoint string `json:"mountPoint"` + Used uint64 `json:"used"` + Free uint64 `json:"free"` } type NetIntfInfo struct { - IPv4 string - IPv6 string - Rx uint64 - Tx uint64 + IPv4 string `json:"ipv4"` + IPv6 string `json:"ipv6"` + Rx uint64 `json:"rx"` + Tx uint64 `json:"tx"` +} + +type MemInfo struct { + Total uint64 `json:"total"` + Free uint64 `json:"free"` + Buffers uint64 `json:"buffers"` + Available uint64 `json:"available"` + Cached uint64 `json:"cached"` + SwapTotal uint64 `json:"swapTotal"` + SwapFree uint64 `json:"swapFree"` } type CPUInfo struct { - User float32 - Nice float32 - System float32 - Idle float32 - Iowait float32 - Irq float32 - SoftIrq float32 - Steal float32 - Guest float32 + User float32 `json:"user"` + Nice float32 `json:"nice"` + System float32 `json:"system"` + Idle float32 `json:"idle"` + Iowait float32 `json:"iowait"` + Irq float32 `json:"irq"` + SoftIrq float32 `json:"softIrq"` + Steal float32 `json:"steal"` + Guest float32 `json:"guest"` } type Stats struct { - Uptime string - Hostname string - Load1 string - Load5 string - Load10 string - RunningProcs string - TotalProcs string - MemTotal uint64 - MemFree uint64 - MemBuffers uint64 - MemAvailable uint64 - MemCached uint64 - SwapTotal uint64 - SwapFree uint64 - FSInfos []FSInfo - NetIntf map[string]NetIntfInfo - CPU CPUInfo // or []CPUInfo to get all the cpu-core's stats? + Uptime string `json:"uptime"` + Hostname string `json:"hostname"` + Load1 string `json:"load1"` + Load5 string `json:"load5"` + Load10 string `json:"load10"` + RunningProcs string `json:"runningProcs"` + TotalProcs string `json:"totalProcs"` + MemInfo MemInfo `json:"memInfo"` + FSInfos []FSInfo `json:"fSInfos"` + NetIntf map[string]NetIntfInfo `json:"netIntf"` + CPU CPUInfo `json:"cpu"` // or []CPUInfo to get all the cpu-core's stats? } const StatsShell = ` @@ -141,19 +145,19 @@ func getMemInfo(memInfo string, stats *Stats) (err error) { val *= 1024 switch parts[0] { case "MemTotal:": - stats.MemTotal = val + stats.MemInfo.Total = val case "MemFree:": - stats.MemFree = val + stats.MemInfo.Free = val case "Buffers:": - stats.MemBuffers = val + stats.MemInfo.Buffers = val case "Cached:": - stats.MemCached = val + stats.MemInfo.Cached = val case "SwapTotal:": - stats.SwapTotal = val + stats.MemInfo.SwapTotal = val case "SwapFree:": - stats.SwapFree = val + stats.MemInfo.SwapFree = val case "MemAvailable:": - stats.MemAvailable = val + stats.MemInfo.Available = val } } } diff --git a/server/internal/mongo/api/mongo.go b/server/internal/mongo/api/mongo.go index ea6cee0d..826b099b 100644 --- a/server/internal/mongo/api/mongo.go +++ b/server/internal/mongo/api/mongo.go @@ -30,7 +30,7 @@ func (m *Mongo) Mongos(rc *req.Ctx) { queryCond, page := ginx.BindQueryAndPage[*entity.MongoQuery](rc.GinCtx, new(entity.MongoQuery)) // 不存在可访问标签id,即没有可操作数据 - tagIds := m.TagApp.ListTagIdByAccountId(rc.LoginAccount.Id) + tagIds := m.TagApp.ListTagIdByAccountId(rc.GetLoginAccount().Id) if len(tagIds) == 0 { rc.ResData = model.EmptyPageResult[any]() return @@ -43,7 +43,7 @@ func (m *Mongo) Mongos(rc *req.Ctx) { } func (m *Mongo) MongoTags(rc *req.Ctx) { - rc.ResData = m.TagApp.ListTagByAccountIdAndResource(rc.LoginAccount.Id, new(entity.Mongo)) + rc.ResData = m.TagApp.ListTagByAccountIdAndResource(rc.GetLoginAccount().Id, new(entity.Mongo)) } func (m *Mongo) Save(rc *req.Ctx) { @@ -57,8 +57,7 @@ func (m *Mongo) Save(rc *req.Ctx) { }(form.Uri) rc.ReqParam = form - mongo.SetBaseInfo(rc.LoginAccount) - biz.ErrIsNil(m.MongoApp.Save(mongo)) + biz.ErrIsNil(m.MongoApp.Save(rc.MetaCtx, mongo)) } func (m *Mongo) DeleteMongo(rc *req.Ctx) { @@ -69,7 +68,7 @@ func (m *Mongo) DeleteMongo(rc *req.Ctx) { for _, v := range ids { value, err := strconv.Atoi(v) biz.ErrIsNilAppendErr(err, "string类型转换为int异常: %s") - m.MongoApp.Delete(uint64(value)) + m.MongoApp.Delete(rc.MetaCtx, uint64(value)) } } diff --git a/server/internal/mongo/application/mongo.go b/server/internal/mongo/application/mongo.go index 11dbcc19..7cc83c73 100644 --- a/server/internal/mongo/application/mongo.go +++ b/server/internal/mongo/application/mongo.go @@ -1,6 +1,7 @@ package application import ( + "context" "mayfly-go/internal/mongo/domain/entity" "mayfly-go/internal/mongo/domain/repository" "mayfly-go/internal/mongo/mgm" @@ -17,10 +18,10 @@ type Mongo interface { Count(condition *entity.MongoQuery) int64 - Save(entity *entity.Mongo) error + Save(ctx context.Context, entity *entity.Mongo) error // 删除数据库信息 - Delete(id uint64) error + Delete(ctx context.Context, id uint64) error // 获取mongo连接实例 // @param id mongo id @@ -46,19 +47,19 @@ func (d *mongoAppImpl) Count(condition *entity.MongoQuery) int64 { return d.GetRepo().Count(condition) } -func (d *mongoAppImpl) Delete(id uint64) error { +func (d *mongoAppImpl) Delete(ctx context.Context, id uint64) error { mgm.CloseConn(id) - return d.GetRepo().DeleteById(id) + return d.GetRepo().DeleteById(ctx, id) } -func (d *mongoAppImpl) Save(m *entity.Mongo) error { +func (d *mongoAppImpl) Save(ctx context.Context, m *entity.Mongo) error { if m.Id == 0 { - return d.GetRepo().Insert(m) + return d.GetRepo().Insert(ctx, m) } // 先关闭连接 mgm.CloseConn(m.Id) - return d.GetRepo().UpdateById(m) + return d.GetRepo().UpdateById(ctx, m) } func (d *mongoAppImpl) GetMongoConn(id uint64) (*mgm.MongoConn, error) { diff --git a/server/internal/msg/api/msg.go b/server/internal/msg/api/msg.go index 20735c03..d018c72f 100644 --- a/server/internal/msg/api/msg.go +++ b/server/internal/msg/api/msg.go @@ -15,7 +15,7 @@ type Msg struct { // 获取账号接收的消息列表 func (m *Msg) GetMsgs(rc *req.Ctx) { condition := &entity.Msg{ - RecipientId: int64(rc.LoginAccount.Id), + RecipientId: int64(rc.GetLoginAccount().Id), } res, err := m.MsgApp.GetPageList(condition, ginx.GetPageParam(rc.GinCtx), new([]entity.Msg)) biz.ErrIsNil(err) diff --git a/server/internal/msg/application/msg.go b/server/internal/msg/application/msg.go index 548bd319..49e10fea 100644 --- a/server/internal/msg/application/msg.go +++ b/server/internal/msg/application/msg.go @@ -1,6 +1,7 @@ package application import ( + "context" "mayfly-go/internal/msg/application/dto" "mayfly-go/internal/msg/domain/entity" "mayfly-go/internal/msg/domain/repository" @@ -12,7 +13,7 @@ import ( type Msg interface { GetPageList(condition *entity.Msg, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error) - Create(msg *entity.Msg) + Create(ctx context.Context, msg *entity.Msg) // 创建消息,并通过ws发送 CreateAndSend(la *model.LoginAccount, msg *dto.SysMsg) @@ -32,13 +33,13 @@ func (a *msgAppImpl) GetPageList(condition *entity.Msg, pageParam *model.PagePar return a.msgRepo.GetPageList(condition, pageParam, toEntity) } -func (a *msgAppImpl) Create(msg *entity.Msg) { - a.msgRepo.Insert(msg) +func (a *msgAppImpl) Create(ctx context.Context, msg *entity.Msg) { + a.msgRepo.Insert(ctx, msg) } func (a *msgAppImpl) CreateAndSend(la *model.LoginAccount, wmsg *dto.SysMsg) { now := time.Now() msg := &entity.Msg{Type: 2, Msg: wmsg.Msg, RecipientId: int64(la.Id), CreateTime: &now, CreatorId: la.Id, Creator: la.Username} - a.msgRepo.Insert(msg) + a.msgRepo.Insert(context.TODO(), msg) ws.SendJsonMsg(ws.UserId(la.Id), wmsg.ClientId, wmsg) } diff --git a/server/internal/redis/api/redis.go b/server/internal/redis/api/redis.go index abf10e2e..b0c0fa25 100644 --- a/server/internal/redis/api/redis.go +++ b/server/internal/redis/api/redis.go @@ -31,7 +31,7 @@ func (r *Redis) RedisList(rc *req.Ctx) { queryCond, page := ginx.BindQueryAndPage[*entity.RedisQuery](rc.GinCtx, new(entity.RedisQuery)) // 不存在可访问标签id,即没有可操作数据 - tagIds := r.TagApp.ListTagIdByAccountId(rc.LoginAccount.Id) + tagIds := r.TagApp.ListTagIdByAccountId(rc.GetLoginAccount().Id) if len(tagIds) == 0 { rc.ResData = model.EmptyPageResult[any]() return @@ -44,7 +44,7 @@ func (r *Redis) RedisList(rc *req.Ctx) { } func (r *Redis) RedisTags(rc *req.Ctx) { - rc.ResData = r.TagApp.ListTagByAccountIdAndResource(rc.LoginAccount.Id, new(entity.Redis)) + rc.ResData = r.TagApp.ListTagByAccountIdAndResource(rc.GetLoginAccount().Id, new(entity.Redis)) } func (r *Redis) Save(rc *req.Ctx) { @@ -60,8 +60,7 @@ func (r *Redis) Save(rc *req.Ctx) { form.Password = "****" rc.ReqParam = form - redis.SetBaseInfo(rc.LoginAccount) - biz.ErrIsNil(r.RedisApp.Save(redis)) + biz.ErrIsNil(r.RedisApp.Save(rc.MetaCtx, redis)) } // 获取redis实例密码,由于数据库是加密存储,故提供该接口展示原文密码 @@ -81,7 +80,7 @@ func (r *Redis) DeleteRedis(rc *req.Ctx) { for _, v := range ids { value, err := strconv.Atoi(v) biz.ErrIsNilAppendErr(err, "string类型转换为int异常: %s") - r.RedisApp.Delete(uint64(value)) + r.RedisApp.Delete(rc.MetaCtx, uint64(value)) } } @@ -218,7 +217,7 @@ func (r *Redis) checkKeyAndGetRedisConn(rc *req.Ctx) (*rdm.RedisConn, string) { func (r *Redis) getRedisConn(rc *req.Ctx) *rdm.RedisConn { ri, err := r.RedisApp.GetRedisConn(getIdAndDbNum(rc.GinCtx)) biz.ErrIsNil(err) - biz.ErrIsNilAppendErr(r.TagApp.CanAccess(rc.LoginAccount.Id, ri.Info.TagPath), "%s") + biz.ErrIsNilAppendErr(r.TagApp.CanAccess(rc.GetLoginAccount().Id, ri.Info.TagPath), "%s") return ri } diff --git a/server/internal/redis/application/redis.go b/server/internal/redis/application/redis.go index 77db9b9d..7aa647bc 100644 --- a/server/internal/redis/application/redis.go +++ b/server/internal/redis/application/redis.go @@ -1,6 +1,7 @@ package application import ( + "context" "mayfly-go/internal/redis/domain/entity" "mayfly-go/internal/redis/domain/repository" "mayfly-go/internal/redis/rdm" @@ -19,10 +20,10 @@ type Redis interface { Count(condition *entity.RedisQuery) int64 - Save(re *entity.Redis) error + Save(ctx context.Context, re *entity.Redis) error // 删除数据库信息 - Delete(id uint64) error + Delete(ctx context.Context, id uint64) error // 获取数据库连接实例 // id: 数据库实例id @@ -52,7 +53,7 @@ func (r *redisAppImpl) Count(condition *entity.RedisQuery) int64 { return r.GetRepo().Count(condition) } -func (r *redisAppImpl) Save(re *entity.Redis) error { +func (r *redisAppImpl) Save(ctx context.Context, re *entity.Redis) error { // ’修改信息且密码不为空‘ or ‘新增’需要测试是否可连接 if (re.Id != 0 && re.Password != "") || re.Id == 0 { if err := r.TestConn(re); err != nil { @@ -72,7 +73,7 @@ func (r *redisAppImpl) Save(re *entity.Redis) error { return errorx.NewBiz("该实例已存在") } re.PwdEncrypt() - return r.Insert(re) + return r.Insert(ctx, re) } // 如果存在该库,则校验修改的库是否为该库 @@ -87,11 +88,11 @@ func (r *redisAppImpl) Save(re *entity.Redis) error { } } re.PwdEncrypt() - return r.UpdateById(re) + return r.UpdateById(ctx, re) } // 删除Redis信息 -func (r *redisAppImpl) Delete(id uint64) error { +func (r *redisAppImpl) Delete(ctx context.Context, id uint64) error { re, err := r.GetById(new(entity.Redis), id) if err != nil { return errorx.NewBiz("该redis信息不存在") @@ -101,7 +102,7 @@ func (r *redisAppImpl) Delete(id uint64) error { db, _ := strconv.Atoi(dbStr) rdm.CloseConn(re.Id, db) } - return r.DeleteById(id) + return r.DeleteById(ctx, id) } // 获取数据库连接实例 diff --git a/server/internal/sys/api/account.go b/server/internal/sys/api/account.go index 22e31923..5120d724 100644 --- a/server/internal/sys/api/account.go +++ b/server/internal/sys/api/account.go @@ -35,7 +35,7 @@ type Account struct { // 获取当前登录用户的菜单与权限码 func (a *Account) GetPermissions(rc *req.Ctx) { - account := rc.LoginAccount + account := rc.GetLoginAccount() var resources vo.AccountResourceVOList // 获取账号菜单资源 @@ -78,15 +78,13 @@ func (a *Account) ChangePassword(rc *req.Ctx) { updateAccount := new(entity.Account) updateAccount.Id = account.Id updateAccount.Password = cryptox.PwdHash(originNewPwd) - biz.ErrIsNil(a.AccountApp.Update(updateAccount), "更新账号密码失败") + biz.ErrIsNil(a.AccountApp.Update(rc.MetaCtx, updateAccount), "更新账号密码失败") // 赋值loginAccount 主要用于记录操作日志,因为操作日志保存请求上下文没有该信息不保存日志 - if rc.LoginAccount == nil { - rc.LoginAccount = &model.LoginAccount{ - Id: account.Id, - Username: account.Username, - } - } + contextx.WithLoginAccount(rc.MetaCtx, &model.LoginAccount{ + Id: account.Id, + Username: account.Username, + }) } // 获取个人账号信息 @@ -94,7 +92,7 @@ func (a *Account) AccountInfo(rc *req.Ctx) { ap := new(vo.AccountPersonVO) // 角色信息 roles := new([]vo.AccountRoleVO) - a.RoleApp.GetAccountRoles(rc.LoginAccount.Id, roles) + a.RoleApp.GetAccountRoles(rc.GetLoginAccount().Id, roles) ap.Roles = *roles rc.ResData = ap @@ -104,7 +102,7 @@ func (a *Account) AccountInfo(rc *req.Ctx) { func (a *Account) UpdateAccount(rc *req.Ctx) { updateAccount := ginx.BindJsonAndCopyTo[*entity.Account](rc.GinCtx, new(form.AccountUpdateForm), new(entity.Account)) // 账号id为登录者账号 - updateAccount.Id = rc.LoginAccount.Id + updateAccount.Id = rc.GetLoginAccount().Id if updateAccount.Password != "" { biz.IsTrue(utils.CheckAccountPasswordLever(updateAccount.Password), "密码强度必须8位以上且包含字⺟⼤⼩写+数字+特殊符号") @@ -118,7 +116,7 @@ func (a *Account) UpdateAccount(rc *req.Ctx) { // 禁止更新用户名,防止误传被更新 updateAccount.Username = "" } - biz.ErrIsNil(a.AccountApp.Update(updateAccount)) + biz.ErrIsNil(a.AccountApp.Update(rc.MetaCtx, updateAccount)) } /** 后台账号操作 **/ @@ -139,10 +137,9 @@ func (a *Account) SaveAccount(rc *req.Ctx) { form.Password = "*****" rc.ReqParam = form - account.SetBaseInfo(rc.LoginAccount) if account.Id == 0 { - biz.ErrIsNil(a.AccountApp.Create(account)) + biz.ErrIsNil(a.AccountApp.Create(rc.MetaCtx, account)) } else { if account.Password != "" { biz.IsTrue(utils.CheckAccountPasswordLever(account.Password), "密码强度必须8位以上且包含字⺟⼤⼩写+数字+特殊符号") @@ -150,7 +147,7 @@ func (a *Account) SaveAccount(rc *req.Ctx) { } // 更新操作不允许修改用户名、防止误传更新 account.Username = "" - biz.ErrIsNil(a.AccountApp.Update(account)) + biz.ErrIsNil(a.AccountApp.Update(rc.MetaCtx, account)) } } @@ -161,7 +158,7 @@ func (a *Account) ChangeStatus(rc *req.Ctx) { account.Id = uint64(ginx.PathParamInt(g, "id")) account.Status = int8(ginx.PathParamInt(g, "status")) rc.ReqParam = collx.Kvs("accountId", account.Id, "status", account.Status) - biz.ErrIsNil(a.AccountApp.Update(account)) + biz.ErrIsNil(a.AccountApp.Update(rc.MetaCtx, account)) } func (a *Account) DeleteAccount(rc *req.Ctx) { @@ -172,7 +169,7 @@ func (a *Account) DeleteAccount(rc *req.Ctx) { for _, v := range ids { value, err := strconv.Atoi(v) biz.ErrIsNilAppendErr(err, "string类型转换为int异常: %s") - biz.ErrIsNilAppendErr(a.AccountApp.Delete(uint64(value)), "删除失败:%s") + biz.ErrIsNilAppendErr(a.AccountApp.Delete(rc.MetaCtx, uint64(value)), "删除失败:%s") } } @@ -207,7 +204,7 @@ func (a *Account) SaveRoles(rc *req.Ctx) { return uint64(id) }) - a.RoleApp.SaveAccountRole(contextx.NewLoginAccount(rc.LoginAccount), form.Id, newIds) + a.RoleApp.SaveAccountRole(rc.MetaCtx, form.Id, newIds) } // 重置otp秘钥 @@ -216,5 +213,5 @@ func (a *Account) ResetOtpSecret(rc *req.Ctx) { accountId := uint64(ginx.PathParamInt(rc.GinCtx, "id")) account.Id = accountId rc.ReqParam = collx.Kvs("accountId", accountId) - biz.ErrIsNil(a.AccountApp.Update(account)) + biz.ErrIsNil(a.AccountApp.Update(rc.MetaCtx, account)) } diff --git a/server/internal/sys/api/config.go b/server/internal/sys/api/config.go index e8a0e53d..a564d4d0 100644 --- a/server/internal/sys/api/config.go +++ b/server/internal/sys/api/config.go @@ -16,7 +16,7 @@ type Config struct { func (c *Config) Configs(rc *req.Ctx) { g := rc.GinCtx condition := &entity.Config{Key: g.Query("key")} - condition.Permission = rc.LoginAccount.Username + condition.Permission = rc.GetLoginAccount().Username res, err := c.ConfigApp.GetPageList(condition, ginx.GetPageParam(g), new([]entity.Config)) biz.ErrIsNil(err) rc.ResData = res @@ -40,6 +40,5 @@ func (c *Config) SaveConfig(rc *req.Ctx) { form := &form.ConfigForm{} config := ginx.BindJsonAndCopyTo(rc.GinCtx, form, new(entity.Config)) rc.ReqParam = form - config.SetBaseInfo(rc.LoginAccount) - biz.ErrIsNil(c.ConfigApp.Save(config)) + biz.ErrIsNil(c.ConfigApp.Save(rc.MetaCtx, config)) } diff --git a/server/internal/sys/api/resource.go b/server/internal/sys/api/resource.go index 8c65a36e..093e1de9 100644 --- a/server/internal/sys/api/resource.go +++ b/server/internal/sys/api/resource.go @@ -39,19 +39,18 @@ func (r *Resource) SaveResource(rc *req.Ctx) { bytes, _ := json.Marshal(form.Meta) entity.Meta = string(bytes) - entity.SetBaseInfo(rc.LoginAccount) - biz.ErrIsNil(r.ResourceApp.Save(entity)) + biz.ErrIsNil(r.ResourceApp.Save(rc.MetaCtx, entity)) } func (r *Resource) DelResource(rc *req.Ctx) { - biz.ErrIsNil(r.ResourceApp.Delete(uint64(ginx.PathParamInt(rc.GinCtx, "id")))) + biz.ErrIsNil(r.ResourceApp.Delete(rc.MetaCtx, uint64(ginx.PathParamInt(rc.GinCtx, "id")))) } func (r *Resource) ChangeStatus(rc *req.Ctx) { rid := uint64(ginx.PathParamInt(rc.GinCtx, "id")) status := int8(ginx.PathParamInt(rc.GinCtx, "status")) rc.ReqParam = collx.Kvs("id", rid, "status", status) - biz.ErrIsNil(r.ResourceApp.ChangeStatus(rid, status)) + biz.ErrIsNil(r.ResourceApp.ChangeStatus(rc.MetaCtx, rid, status)) } func (r *Resource) Sort(rc *req.Ctx) { @@ -62,6 +61,6 @@ func (r *Resource) Sort(rc *req.Ctx) { for _, v := range rs { sortE := &entity.Resource{Pid: v.Pid, Weight: v.Weight} sortE.Id = uint64(v.Id) - r.ResourceApp.Sort(sortE) + r.ResourceApp.Sort(rc.MetaCtx, sortE) } } diff --git a/server/internal/sys/api/role.go b/server/internal/sys/api/role.go index 6d538a2b..de86130f 100644 --- a/server/internal/sys/api/role.go +++ b/server/internal/sys/api/role.go @@ -6,7 +6,6 @@ import ( "mayfly-go/internal/sys/application" "mayfly-go/internal/sys/domain/entity" "mayfly-go/pkg/biz" - "mayfly-go/pkg/contextx" "mayfly-go/pkg/ginx" "mayfly-go/pkg/req" "mayfly-go/pkg/utils/collx" @@ -32,9 +31,8 @@ func (r *Role) SaveRole(rc *req.Ctx) { form := &form.RoleForm{} role := ginx.BindJsonAndCopyTo(rc.GinCtx, form, new(entity.Role)) rc.ReqParam = form - role.SetBaseInfo(rc.LoginAccount) - r.RoleApp.SaveRole(role) + r.RoleApp.SaveRole(rc.MetaCtx, role) } // 删除角色及其资源关联关系 @@ -46,7 +44,7 @@ func (r *Role) DelRole(rc *req.Ctx) { for _, v := range ids { value, err := strconv.Atoi(v) biz.ErrIsNilAppendErr(err, "string类型转换为int异常: %s") - r.RoleApp.DeleteRole(uint64(value)) + r.RoleApp.DeleteRole(rc.MetaCtx, uint64(value)) } } @@ -77,5 +75,5 @@ func (r *Role) SaveResource(rc *req.Ctx) { return uint64(id) }) - r.RoleApp.SaveRoleResource(contextx.NewLoginAccount(rc.LoginAccount), form.Id, newIds) + r.RoleApp.SaveRoleResource(rc.MetaCtx, form.Id, newIds) } diff --git a/server/internal/sys/api/system.go b/server/internal/sys/api/system.go index f653ef25..5dffca51 100644 --- a/server/internal/sys/api/system.go +++ b/server/internal/sys/api/system.go @@ -38,8 +38,6 @@ func (s *System) ConnectWs(g *gin.Context) { biz.ErrIsNil(err, "sys websocket没有权限连接") // 登录账号信息 - la := rc.LoginAccount - if la != nil { - ws.AddClient(ws.UserId(la.Id), clientId, wsConn) - } + la := rc.GetLoginAccount() + ws.AddClient(ws.UserId(la.Id), clientId, wsConn) } diff --git a/server/internal/sys/application/account.go b/server/internal/sys/application/account.go index f44331ec..ec79103a 100644 --- a/server/internal/sys/application/account.go +++ b/server/internal/sys/application/account.go @@ -1,6 +1,7 @@ package application import ( + "context" "mayfly-go/internal/sys/domain/entity" "mayfly-go/internal/sys/domain/repository" "mayfly-go/pkg/base" @@ -17,11 +18,11 @@ type Account interface { GetPageList(condition *entity.Account, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error) - Create(account *entity.Account) error + Create(ctx context.Context, account *entity.Account) error - Update(account *entity.Account) error + Update(ctx context.Context, account *entity.Account) error - Delete(id uint64) error + Delete(ctx context.Context, id uint64) error } func newAccountApp(accountRepo repository.Account) Account { @@ -36,17 +37,17 @@ func (a *accountAppImpl) GetPageList(condition *entity.Account, pageParam *model return a.GetRepo().GetPageList(condition, pageParam, toEntity) } -func (a *accountAppImpl) Create(account *entity.Account) error { +func (a *accountAppImpl) Create(ctx context.Context, account *entity.Account) error { if a.GetBy(&entity.Account{Username: account.Username}) == nil { return errorx.NewBiz("该账号用户名已存在") } // 默认密码为账号用户名 account.Password = cryptox.PwdHash(account.Username) account.Status = entity.AccountEnableStatus - return a.Insert(account) + return a.Insert(ctx, account) } -func (a *accountAppImpl) Update(account *entity.Account) error { +func (a *accountAppImpl) Update(ctx context.Context, account *entity.Account) error { if account.Username != "" { unAcc := &entity.Account{Username: account.Username} err := a.GetBy(unAcc) @@ -55,14 +56,14 @@ func (a *accountAppImpl) Update(account *entity.Account) error { } } - return a.UpdateById(account) + return a.UpdateById(ctx, account) } -func (a *accountAppImpl) Delete(id uint64) error { +func (a *accountAppImpl) Delete(ctx context.Context, id uint64) error { return gormx.Tx( func(db *gorm.DB) error { // 删除account信息 - return a.DeleteByIdWithDb(db, id) + return a.DeleteByIdWithDb(ctx, db, id) }, func(db *gorm.DB) error { // 删除账号关联的角色信息 diff --git a/server/internal/sys/application/config.go b/server/internal/sys/application/config.go index bd70f606..4e261448 100644 --- a/server/internal/sys/application/config.go +++ b/server/internal/sys/application/config.go @@ -1,6 +1,7 @@ package application import ( + "context" "encoding/json" "mayfly-go/internal/sys/domain/entity" "mayfly-go/internal/sys/domain/repository" @@ -20,7 +21,7 @@ type Config interface { GetPageList(condition *entity.Config, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error) - Save(config *entity.Config) error + Save(ctx context.Context, config *entity.Config) error // GetConfig 获取指定key的配置信息, 不会返回nil, 若不存在则值都默认值即空字符串 GetConfig(key string) *entity.Config @@ -41,9 +42,9 @@ func (a *configAppImpl) GetPageList(condition *entity.Config, pageParam *model.P return a.GetRepo().GetPageList(condition, pageParam, toEntity) } -func (a *configAppImpl) Save(config *entity.Config) error { +func (a *configAppImpl) Save(ctx context.Context, config *entity.Config) error { if config.Id == 0 { - if err := a.Insert(config); err != nil { + if err := a.Insert(ctx, config); err != nil { return err } } else { @@ -52,7 +53,7 @@ func (a *configAppImpl) Save(config *entity.Config) error { return errorx.NewBiz("您无权修改该配置") } - if err := a.UpdateById(config); err != nil { + if err := a.UpdateById(ctx, config); err != nil { return err } } diff --git a/server/internal/sys/application/resource.go b/server/internal/sys/application/resource.go index 2d896e66..e153ede7 100644 --- a/server/internal/sys/application/resource.go +++ b/server/internal/sys/application/resource.go @@ -1,6 +1,7 @@ package application import ( + "context" "mayfly-go/internal/common/consts" "mayfly-go/internal/sys/domain/entity" "mayfly-go/internal/sys/domain/repository" @@ -15,13 +16,13 @@ import ( type Resource interface { base.App[*entity.Resource] - Save(entity *entity.Resource) error + Save(ctx context.Context, entity *entity.Resource) error - Delete(id uint64) error + Delete(ctx context.Context, id uint64) error - ChangeStatus(resourceId uint64, status int8) error + ChangeStatus(ctx context.Context, resourceId uint64, status int8) error - Sort(re *entity.Resource) error + Sort(ctx context.Context, re *entity.Resource) error GetAccountResources(accountId uint64, toEntity any) error } @@ -36,7 +37,7 @@ type resourceAppImpl struct { base.AppImpl[*entity.Resource, repository.Resource] } -func (r *resourceAppImpl) Save(resource *entity.Resource) error { +func (r *resourceAppImpl) Save(ctx context.Context, resource *entity.Resource) error { // 更新操作 if resource.Id != 0 { if resource.Code != "" { @@ -51,7 +52,7 @@ func (r *resourceAppImpl) Save(resource *entity.Resource) error { } } } - return gormx.UpdateById(resource) + return r.UpdateById(ctx, resource) } // 生成随机八位唯一标识符 @@ -73,10 +74,10 @@ func (r *resourceAppImpl) Save(resource *entity.Resource) error { return err } resource.Weight = int(time.Now().Unix()) - return gormx.Insert(resource) + return r.Insert(ctx, resource) } -func (r *resourceAppImpl) ChangeStatus(resourceId uint64, status int8) error { +func (r *resourceAppImpl) ChangeStatus(ctx context.Context, resourceId uint64, status int8) error { resource, err := r.GetById(new(entity.Resource), resourceId) if err != nil { return errorx.NewBiz("资源不存在") @@ -85,7 +86,7 @@ func (r *resourceAppImpl) ChangeStatus(resourceId uint64, status int8) error { return r.GetRepo().UpdateByUiPathLike(resource) } -func (r *resourceAppImpl) Sort(sortResource *entity.Resource) error { +func (r *resourceAppImpl) Sort(ctx context.Context, sortResource *entity.Resource) error { resource, err := r.GetById(new(entity.Resource), sortResource.Id) if err != nil { return errorx.NewBiz("资源不存在") @@ -95,7 +96,7 @@ func (r *resourceAppImpl) Sort(sortResource *entity.Resource) error { if sortResource.Pid == resource.Pid { saveE := &entity.Resource{Weight: sortResource.Weight} saveE.Id = sortResource.Id - return r.Save(saveE) + return r.Save(ctx, saveE) } // 若资源原本唯一标识路径为:xxxx/yyyy/zzzz/,则获取其父节点路径标识 xxxx/yyyy/ 与自身节点标识 zzzz/ @@ -131,7 +132,7 @@ func (r *resourceAppImpl) Sort(sortResource *entity.Resource) error { } else { updateUiPath.UiPath = strings.ReplaceAll(v.UiPath, parentResourceUiPath, newParentResourceUiPath) } - r.Save(updateUiPath) + r.Save(ctx, updateUiPath) } // 更新零值使用map,因为pid=0表示根节点 @@ -155,7 +156,7 @@ func (r *resourceAppImpl) checkCode(code string) error { return nil } -func (r *resourceAppImpl) Delete(id uint64) error { +func (r *resourceAppImpl) Delete(ctx context.Context, id uint64) error { resource, err := r.GetById(new(entity.Resource), id) if err != nil { return errorx.NewBiz("资源不存在") @@ -164,7 +165,7 @@ func (r *resourceAppImpl) Delete(id uint64) error { // 删除当前节点及其所有子节点 children := r.GetRepo().GetChildren(resource.UiPath) for _, v := range children { - r.GetRepo().DeleteById(v.Id) + r.GetRepo().DeleteById(ctx, v.Id) // 删除角色关联的资源信息 gormx.DeleteBy(&entity.RoleResource{ResourceId: v.Id}) } diff --git a/server/internal/sys/application/role.go b/server/internal/sys/application/role.go index 0ce00d1e..ba81eb1f 100644 --- a/server/internal/sys/application/role.go +++ b/server/internal/sys/application/role.go @@ -17,9 +17,9 @@ import ( type Role interface { GetPageList(condition *entity.Role, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error) - SaveRole(role *entity.Role) error + SaveRole(ctx context.Context, role *entity.Role) error - DeleteRole(id uint64) error + DeleteRole(ctx context.Context, id uint64) error GetRoleResourceIds(roleId uint64) []uint64 @@ -29,7 +29,7 @@ type Role interface { SaveRoleResource(ctx context.Context, roleId uint64, resourceIds []uint64) // 删除角色资源关联记录 - DeleteRoleResource(roleId uint64, resourceId uint64) + DeleteRoleResource(ctx context.Context, roleId uint64, resourceId uint64) // 获取账号角色id列表 GetAccountRoleIds(accountId uint64) []uint64 @@ -37,7 +37,7 @@ type Role interface { // 保存账号角色关联信息 SaveAccountRole(ctx context.Context, accountId uint64, roleIds []uint64) - DeleteAccountRole(accountId, roleId uint64) + DeleteAccountRole(ctx context.Context, accountId, roleId uint64) GetAccountRoles(accountId uint64, toEntity any) } @@ -56,7 +56,7 @@ func (m *roleAppImpl) GetPageList(condition *entity.Role, pageParam *model.PageP return m.roleRepo.GetPageList(condition, pageParam, toEntity, orderBy...) } -func (m *roleAppImpl) SaveRole(role *entity.Role) error { +func (m *roleAppImpl) SaveRole(ctx context.Context, role *entity.Role) error { role.Code = strings.ToUpper(role.Code) if role.Id != 0 { // code不可更改,防止误传 @@ -68,11 +68,11 @@ func (m *roleAppImpl) SaveRole(role *entity.Role) error { return gormx.Insert(role) } -func (m *roleAppImpl) DeleteRole(id uint64) error { +func (m *roleAppImpl) DeleteRole(ctx context.Context, id uint64) error { // 删除角色与资源的关联关系 return gormx.Tx( func(db *gorm.DB) error { - return m.roleRepo.DeleteByIdWithDb(db, id) + return m.roleRepo.DeleteByIdWithDb(ctx, db, id) }, func(db *gorm.DB) error { return gormx.DeleteByWithDb(db, &entity.RoleResource{RoleId: id}) @@ -110,11 +110,11 @@ func (m *roleAppImpl) SaveRoleResource(ctx context.Context, roleId uint64, resou m.roleRepo.SaveRoleResource(addVals) for _, v := range delIds { - m.DeleteRoleResource(roleId, v) + m.DeleteRoleResource(ctx, roleId, v) } } -func (m *roleAppImpl) DeleteRoleResource(roleId uint64, resourceId uint64) { +func (m *roleAppImpl) DeleteRoleResource(ctx context.Context, roleId uint64, resourceId uint64) { m.roleRepo.DeleteRoleResource(roleId, resourceId) } @@ -140,11 +140,11 @@ func (m *roleAppImpl) SaveAccountRole(ctx context.Context, accountId uint64, rol m.roleRepo.SaveAccountRole(rr) } for _, v := range delIds { - m.DeleteAccountRole(accountId, v) + m.DeleteAccountRole(ctx, accountId, v) } } -func (m *roleAppImpl) DeleteAccountRole(accountId, roleId uint64) { +func (m *roleAppImpl) DeleteAccountRole(ctx context.Context, accountId, roleId uint64) { m.roleRepo.DeleteAccountRole(accountId, roleId) } diff --git a/server/internal/sys/application/syslog.go b/server/internal/sys/application/syslog.go index db15f0cc..50b5d002 100644 --- a/server/internal/sys/application/syslog.go +++ b/server/internal/sys/application/syslog.go @@ -5,6 +5,7 @@ import ( "fmt" "mayfly-go/internal/sys/domain/entity" "mayfly-go/internal/sys/domain/repository" + "mayfly-go/pkg/contextx" "mayfly-go/pkg/errorx" "mayfly-go/pkg/model" "mayfly-go/pkg/req" @@ -34,7 +35,7 @@ func (m *syslogAppImpl) GetPageList(condition *entity.SysLogQuery, pageParam *mo } func (m *syslogAppImpl) SaveFromReq(req *req.Ctx) { - lg := req.LoginAccount + lg := contextx.GetLoginAccount(req.MetaCtx) if lg == nil { lg = &model.LoginAccount{Id: 0, Username: "-"} } @@ -74,5 +75,5 @@ func (m *syslogAppImpl) SaveFromReq(req *req.Ctx) { syslog.Type = entity.SyslogTypeNorman } - m.syslogRepo.Insert(syslog) + m.syslogRepo.Insert(req.MetaCtx, syslog) } diff --git a/server/internal/tag/api/tag_tree.go b/server/internal/tag/api/tag_tree.go index 8a92c05c..b8cc1810 100644 --- a/server/internal/tag/api/tag_tree.go +++ b/server/internal/tag/api/tag_tree.go @@ -16,7 +16,7 @@ type TagTree struct { } func (p *TagTree) GetAccountTags(rc *req.Ctx) { - tagPaths := p.TagTreeApp.ListTagByAccountId(rc.LoginAccount.Id) + tagPaths := p.TagTreeApp.ListTagByAccountId(rc.GetLoginAccount().Id) allTagPath := make([]string, 0) if len(tagPaths) > 0 { tags := p.TagTreeApp.ListTagByPath(tagPaths...) @@ -46,13 +46,11 @@ func (p *TagTree) SaveTagTree(rc *req.Ctx) { tagTree := &entity.TagTree{} ginx.BindJsonAndValid(rc.GinCtx, tagTree) - loginAccount := rc.LoginAccount - tagTree.SetBaseInfo(loginAccount) rc.ReqParam = fmt.Sprintf("tagTreeId: %d, tagName: %s, codePath: %s", tagTree.Id, tagTree.Name, tagTree.CodePath) - biz.ErrIsNil(p.TagTreeApp.Save(tagTree)) + biz.ErrIsNil(p.TagTreeApp.Save(rc.MetaCtx, tagTree)) } func (p *TagTree) DelTagTree(rc *req.Ctx) { - biz.ErrIsNil(p.TagTreeApp.Delete(uint64(ginx.PathParamInt(rc.GinCtx, "id")))) + biz.ErrIsNil(p.TagTreeApp.Delete(rc.MetaCtx, uint64(ginx.PathParamInt(rc.GinCtx, "id")))) } diff --git a/server/internal/tag/api/team.go b/server/internal/tag/api/team.go index c2334911..9fcd83a8 100644 --- a/server/internal/tag/api/team.go +++ b/server/internal/tag/api/team.go @@ -35,9 +35,8 @@ func (p *Team) SaveTeam(rc *req.Ctx) { rc.ReqParam = team isAdd := team.Id == 0 - loginAccount := rc.LoginAccount - team.SetBaseInfo(loginAccount) - p.TeamApp.Save(team) + loginAccount := rc.GetLoginAccount() + p.TeamApp.Save(rc.MetaCtx, team) // 如果是新增团队则默认将自己加入该团队 if isAdd { @@ -46,8 +45,7 @@ func (p *Team) SaveTeam(rc *req.Ctx) { teamMem.Username = loginAccount.Username teamMem.TeamId = team.Id - teamMem.SetBaseInfo(rc.LoginAccount) - p.TeamApp.SaveMember(teamMem) + p.TeamApp.SaveMember(rc.MetaCtx, teamMem) } } @@ -59,7 +57,7 @@ func (p *Team) DelTeam(rc *req.Ctx) { for _, v := range ids { value, err := strconv.Atoi(v) biz.ErrIsNilAppendErr(err, "string类型转换为int异常: %s") - p.TeamApp.Delete(uint64(value)) + p.TeamApp.Delete(rc.MetaCtx, uint64(value)) } } @@ -94,8 +92,7 @@ func (p *Team) SaveTeamMember(rc *req.Ctx) { teamMember.TeamId = teamId teamMember.AccountId = accountId teamMember.Username = account.Username - teamMember.SetBaseInfo(rc.LoginAccount) - p.TeamApp.SaveMember(teamMember) + p.TeamApp.SaveMember(rc.MetaCtx, teamMember) } rc.ReqParam = teamMems @@ -108,7 +105,7 @@ func (p *Team) DelTeamMember(rc *req.Ctx) { aid := ginx.PathParamInt(g, "accountId") rc.ReqParam = fmt.Sprintf("teamId: %d, accountId: %d", tid, aid) - p.TeamApp.DeleteMember(uint64(tid), uint64(aid)) + p.TeamApp.DeleteMember(rc.MetaCtx, uint64(tid), uint64(aid)) } // 获取团队关联的标签id @@ -133,18 +130,16 @@ func (p *Team) SaveTags(rc *req.Ctx) { return i1 == i2 }) - loginAccount := rc.LoginAccount for _, v := range addIds { tagId := v tag, err := p.TagApp.GetById(new(entity.TagTree), tagId) biz.ErrIsNil(err, "存在非法标签id") ptt := &entity.TagTreeTeam{TeamId: teamId, TagId: tagId, TagPath: tag.CodePath} - ptt.SetBaseInfo(loginAccount) - p.TeamApp.SaveTag(ptt) + p.TeamApp.SaveTag(rc.MetaCtx, ptt) } for _, v := range delIds { - p.TeamApp.DeleteTag(teamId, v) + p.TeamApp.DeleteTag(rc.MetaCtx, teamId, v) } rc.ReqParam = form diff --git a/server/internal/tag/application/tag_tree.go b/server/internal/tag/application/tag_tree.go index 478589ad..1418c7c3 100644 --- a/server/internal/tag/application/tag_tree.go +++ b/server/internal/tag/application/tag_tree.go @@ -1,6 +1,7 @@ package application import ( + "context" dbapp "mayfly-go/internal/db/application" dbentity "mayfly-go/internal/db/domain/entity" machineapp "mayfly-go/internal/machine/application" @@ -23,9 +24,9 @@ type TagTree interface { ListByQuery(condition *entity.TagTreeQuery, toEntity any) - Save(tt *entity.TagTree) error + Save(ctx context.Context, tt *entity.TagTree) error - Delete(id uint64) error + Delete(ctx context.Context, id uint64) error // 获取账号id拥有的可访问的标签id ListTagIdByAccountId(accountId uint64) []uint64 @@ -74,7 +75,7 @@ type tagTreeAppImpl struct { dbApp dbapp.Db } -func (p *tagTreeAppImpl) Save(tag *entity.TagTree) error { +func (p *tagTreeAppImpl) Save(ctx context.Context, tag *entity.TagTree) error { // 新建项目树节点信息 if tag.Id == 0 { if strings.Contains(tag.Code, entity.CodePathSeparator) { @@ -96,13 +97,13 @@ func (p *tagTreeAppImpl) Save(tag *entity.TagTree) error { return errorx.NewBiz("已存在该标签路径开头的标签, 请修改该标识code") } - return p.GetRepo().Insert(tag) + return p.Insert(ctx, tag) } // 防止误传导致被更新 tag.Code = "" tag.CodePath = "" - return p.GetRepo().UpdateById(tag) + return p.UpdateById(ctx, tag) } func (p *tagTreeAppImpl) ListByQuery(condition *entity.TagTreeQuery, toEntity any) { @@ -161,7 +162,7 @@ func (p *tagTreeAppImpl) CanAccess(accountId uint64, tagPath string) error { return errorx.NewBiz("您无权操作该资源") } -func (p *tagTreeAppImpl) Delete(id uint64) error { +func (p *tagTreeAppImpl) Delete(ctx context.Context, id uint64) error { tagIds := [1]uint64{id} if p.machineApp.Count(&machineentity.MachineQuery{TagIds: tagIds[:]}) > 0 { return errorx.NewBiz("请先删除该标签关联的机器信息") @@ -176,7 +177,7 @@ func (p *tagTreeAppImpl) Delete(id uint64) error { return errorx.NewBiz("请先删除该标签关联的Mongo信息") } - p.DeleteById(id) + p.DeleteById(ctx, id) // 删除该标签关联的团队信息 - return p.tagTreeTeamRepo.DeleteByCond(&entity.TagTreeTeam{TagId: id}) + return p.tagTreeTeamRepo.DeleteByCond(ctx, &entity.TagTreeTeam{TagId: id}) } diff --git a/server/internal/tag/application/team.go b/server/internal/tag/application/team.go index d0b3860c..053b06b6 100644 --- a/server/internal/tag/application/team.go +++ b/server/internal/tag/application/team.go @@ -1,6 +1,7 @@ package application import ( + "context" "mayfly-go/internal/tag/domain/entity" "mayfly-go/internal/tag/domain/repository" "mayfly-go/pkg/biz" @@ -14,17 +15,17 @@ type Team interface { // 分页获取项目团队信息列表 GetPageList(condition *entity.Team, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error) - Save(team *entity.Team) error + Save(ctx context.Context, team *entity.Team) error - Delete(id uint64) error + Delete(ctx context.Context, id uint64) error //--------------- 团队成员相关接口 --------------- GetMemberPage(condition *entity.TeamMember, pageParam *model.PageParam, toEntity any) (*model.PageResult[any], error) - SaveMember(tagTeamMember *entity.TeamMember) + SaveMember(ctx context.Context, tagTeamMember *entity.TeamMember) - DeleteMember(teamId, accountId uint64) + DeleteMember(tx context.Context, teamId, accountId uint64) IsExistMember(teamId, accounId uint64) bool @@ -32,9 +33,9 @@ type Team interface { ListTagIds(teamId uint64) []uint64 - SaveTag(tagTeam *entity.TagTreeTeam) error + SaveTag(ctx context.Context, tagTeam *entity.TagTreeTeam) error - DeleteTag(teamId, tagId uint64) error + DeleteTag(tx context.Context, teamId, tagId uint64) error } func newTeamApp(teamRepo repository.Team, @@ -58,23 +59,23 @@ func (p *teamAppImpl) GetPageList(condition *entity.Team, pageParam *model.PageP return p.teamRepo.GetPageList(condition, pageParam, toEntity, orderBy...) } -func (p *teamAppImpl) Save(team *entity.Team) error { +func (p *teamAppImpl) Save(ctx context.Context, team *entity.Team) error { if team.Id == 0 { - return p.teamRepo.Insert(team) + return p.teamRepo.Insert(ctx, team) } - return p.teamRepo.UpdateById(team) + return p.teamRepo.UpdateById(ctx, team) } -func (p *teamAppImpl) Delete(id uint64) error { +func (p *teamAppImpl) Delete(ctx context.Context, id uint64) error { return gormx.Tx( func(db *gorm.DB) error { - return p.teamRepo.DeleteByIdWithDb(db, id) + return p.teamRepo.DeleteByIdWithDb(ctx, db, id) }, func(db *gorm.DB) error { - return p.teamMemberRepo.DeleteByCondWithDb(db, &entity.TeamMember{TeamId: id}) + return p.teamMemberRepo.DeleteByCondWithDb(ctx, db, &entity.TeamMember{TeamId: id}) }, func(db *gorm.DB) error { - return p.tagTreeTeamRepo.DeleteByCondWithDb(db, &entity.TagTreeTeam{TeamId: id}) + return p.tagTreeTeamRepo.DeleteByCondWithDb(ctx, db, &entity.TagTreeTeam{TeamId: id}) }, ) } @@ -86,15 +87,15 @@ func (p *teamAppImpl) GetMemberPage(condition *entity.TeamMember, pageParam *mod } // 保存团队成员信息 -func (p *teamAppImpl) SaveMember(teamMember *entity.TeamMember) { +func (p *teamAppImpl) SaveMember(ctx context.Context, teamMember *entity.TeamMember) { teamMember.Id = 0 biz.IsTrue(!p.teamMemberRepo.IsExist(teamMember.TeamId, teamMember.AccountId), "该成员已存在") - p.teamMemberRepo.Insert(teamMember) + p.teamMemberRepo.Insert(ctx, teamMember) } // 删除团队成员信息 -func (p *teamAppImpl) DeleteMember(teamId, accountId uint64) { - p.teamMemberRepo.DeleteByCond(&entity.TeamMember{TeamId: teamId, AccountId: accountId}) +func (p *teamAppImpl) DeleteMember(ctx context.Context, teamId, accountId uint64) { + p.teamMemberRepo.DeleteByCond(ctx, &entity.TeamMember{TeamId: teamId, AccountId: accountId}) } func (p *teamAppImpl) IsExistMember(teamId, accounId uint64) bool { @@ -114,12 +115,12 @@ func (p *teamAppImpl) ListTagIds(teamId uint64) []uint64 { } // 保存关联项目信息 -func (p *teamAppImpl) SaveTag(tagTreeTeam *entity.TagTreeTeam) error { +func (p *teamAppImpl) SaveTag(ctx context.Context, tagTreeTeam *entity.TagTreeTeam) error { tagTreeTeam.Id = 0 - return p.tagTreeTeamRepo.Insert(tagTreeTeam) + return p.tagTreeTeamRepo.Insert(ctx, tagTreeTeam) } // 删除关联项目信息 -func (p *teamAppImpl) DeleteTag(teamId, tagId uint64) error { - return p.tagTreeTeamRepo.DeleteByCond(&entity.TagTreeTeam{TeamId: teamId, TagId: tagId}) +func (p *teamAppImpl) DeleteTag(ctx context.Context, teamId, tagId uint64) error { + return p.tagTreeTeamRepo.DeleteByCond(ctx, &entity.TagTreeTeam{TeamId: teamId, TagId: tagId}) } diff --git a/server/pkg/base/app.go b/server/pkg/base/app.go index 74205ed0..3168f3c8 100644 --- a/server/pkg/base/app.go +++ b/server/pkg/base/app.go @@ -1,44 +1,47 @@ package base import ( + "context" + "mayfly-go/pkg/model" + "gorm.io/gorm" ) // 基础application接口 -type App[T any] interface { +type App[T model.ModelI] interface { // 新增一个实体 - Insert(e T) error + Insert(ctx context.Context, e T) error // 使用指定gorm db执行,主要用于事务执行 - InsertWithDb(db *gorm.DB, e T) error + InsertWithDb(ctx context.Context, db *gorm.DB, e T) error // 批量新增实体 - BatchInsert(models []T) error + BatchInsert(ctx context.Context, models []T) error // 使用指定gorm db执行,主要用于事务执行 - BatchInsertWithDb(db *gorm.DB, es []T) error + BatchInsertWithDb(ctx context.Context, db *gorm.DB, es []T) error // 根据实体id更新实体信息 - UpdateById(e T) error + UpdateById(ctx context.Context, e T) error // 使用指定gorm db执行,主要用于事务执行 - UpdateByIdWithDb(db *gorm.DB, e T) error + UpdateByIdWithDb(ctx context.Context, db *gorm.DB, e T) error // 根据实体主键删除实体 - DeleteById(id uint64) error + DeleteById(ctx context.Context, id uint64) error // 使用指定gorm db执行,主要用于事务执行 - DeleteByIdWithDb(db *gorm.DB, id uint64) error + DeleteByIdWithDb(ctx context.Context, db *gorm.DB, id uint64) error // 根据实体条件,更新参数udpateFields指定字段 - Updates(cond any, udpateFields map[string]any) error + Updates(ctx context.Context, cond any, udpateFields map[string]any) error // 根据实体条件删除实体 - DeleteByCond(cond any) error + DeleteByCond(ctx context.Context, cond any) error // 使用指定gorm db执行,主要用于事务执行 - DeleteByCondWithDb(db *gorm.DB, cond any) error + DeleteByCondWithDb(ctx context.Context, db *gorm.DB, cond any) error // 根据实体id查询 GetById(e T, id uint64, cols ...string) (T, error) @@ -62,7 +65,7 @@ type App[T any] interface { } // 基础application接口实现 -type AppImpl[T any, R Repo[T]] struct { +type AppImpl[T model.ModelI, R Repo[T]] struct { Repo R // repo接口 } @@ -72,57 +75,57 @@ func (ai *AppImpl[T, R]) GetRepo() R { } // 新增一个实体 (单纯新增,不做其他业务逻辑处理) -func (ai *AppImpl[T, R]) Insert(e T) error { - return ai.GetRepo().Insert(e) +func (ai *AppImpl[T, R]) Insert(ctx context.Context, e T) error { + return ai.GetRepo().Insert(ctx, e) } // 使用指定gorm db执行,主要用于事务执行 -func (ai *AppImpl[T, R]) InsertWithDb(db *gorm.DB, e T) error { - return ai.GetRepo().InsertWithDb(db, e) +func (ai *AppImpl[T, R]) InsertWithDb(ctx context.Context, db *gorm.DB, e T) error { + return ai.GetRepo().InsertWithDb(ctx, db, e) } // 批量新增实体 (单纯新增,不做其他业务逻辑处理) -func (ai *AppImpl[T, R]) BatchInsert(es []T) error { - return ai.GetRepo().BatchInsert(es) +func (ai *AppImpl[T, R]) BatchInsert(ctx context.Context, es []T) error { + return ai.GetRepo().BatchInsert(ctx, es) } // 使用指定gorm db执行,主要用于事务执行 -func (ai *AppImpl[T, R]) BatchInsertWithDb(db *gorm.DB, es []T) error { - return ai.GetRepo().BatchInsertWithDb(db, es) +func (ai *AppImpl[T, R]) BatchInsertWithDb(ctx context.Context, db *gorm.DB, es []T) error { + return ai.GetRepo().BatchInsertWithDb(ctx, db, es) } // 根据实体id更新实体信息 (单纯更新,不做其他业务逻辑处理) -func (ai *AppImpl[T, R]) UpdateById(e T) error { - return ai.GetRepo().UpdateById(e) +func (ai *AppImpl[T, R]) UpdateById(ctx context.Context, e T) error { + return ai.GetRepo().UpdateById(ctx, e) } // 使用指定gorm db执行,主要用于事务执行 -func (ai *AppImpl[T, R]) UpdateByIdWithDb(db *gorm.DB, e T) error { - return ai.GetRepo().UpdateByIdWithDb(db, e) +func (ai *AppImpl[T, R]) UpdateByIdWithDb(ctx context.Context, db *gorm.DB, e T) error { + return ai.GetRepo().UpdateByIdWithDb(ctx, db, e) } // 根据实体条件,更新参数udpateFields指定字段 (单纯更新,不做其他业务逻辑处理) -func (ai *AppImpl[T, R]) Updates(cond any, udpateFields map[string]any) error { +func (ai *AppImpl[T, R]) Updates(ctx context.Context, cond any, udpateFields map[string]any) error { return ai.GetRepo().Updates(cond, udpateFields) } // 根据实体主键删除实体 (单纯删除实体,不做其他业务逻辑处理) -func (ai *AppImpl[T, R]) DeleteById(id uint64) error { - return ai.GetRepo().DeleteById(id) +func (ai *AppImpl[T, R]) DeleteById(ctx context.Context, id uint64) error { + return ai.GetRepo().DeleteById(ctx, id) } -func (ai *AppImpl[T, R]) DeleteByIdWithDb(db *gorm.DB, id uint64) error { - return ai.GetRepo().DeleteByCondWithDb(db, id) +func (ai *AppImpl[T, R]) DeleteByIdWithDb(ctx context.Context, db *gorm.DB, id uint64) error { + return ai.GetRepo().DeleteByCondWithDb(ctx, db, id) } // 根据指定条件删除实体 (单纯删除实体,不做其他业务逻辑处理) -func (ai *AppImpl[T, R]) DeleteByCond(cond any) error { - return ai.GetRepo().DeleteByCond(cond) +func (ai *AppImpl[T, R]) DeleteByCond(ctx context.Context, cond any) error { + return ai.GetRepo().DeleteByCond(ctx, cond) } // 使用指定gorm db执行,主要用于事务执行 -func (ai *AppImpl[T, R]) DeleteByCondWithDb(db *gorm.DB, cond any) error { - return ai.GetRepo().DeleteByCondWithDb(db, cond) +func (ai *AppImpl[T, R]) DeleteByCondWithDb(ctx context.Context, db *gorm.DB, cond any) error { + return ai.GetRepo().DeleteByCondWithDb(ctx, db, cond) } // 根据实体id查询 diff --git a/server/pkg/base/repo.go b/server/pkg/base/repo.go index 8f669177..d4901524 100644 --- a/server/pkg/base/repo.go +++ b/server/pkg/base/repo.go @@ -1,47 +1,50 @@ package base import ( + "context" "mayfly-go/pkg/biz" + "mayfly-go/pkg/contextx" "mayfly-go/pkg/gormx" + "mayfly-go/pkg/model" "gorm.io/gorm" ) // 基础repo接口 -type Repo[T any] interface { +type Repo[T model.ModelI] interface { // 新增一个实体 - Insert(e T) error + Insert(ctx context.Context, e T) error // 使用指定gorm db执行,主要用于事务执行 - InsertWithDb(db *gorm.DB, e T) error + InsertWithDb(ctx context.Context, db *gorm.DB, e T) error // 批量新增实体 - BatchInsert(models []T) error + BatchInsert(ctx context.Context, models []T) error // 使用指定gorm db执行,主要用于事务执行 - BatchInsertWithDb(db *gorm.DB, es []T) error + BatchInsertWithDb(ctx context.Context, db *gorm.DB, es []T) error // 根据实体id更新实体信息 - UpdateById(e T) error + UpdateById(ctx context.Context, e T) error // 使用指定gorm db执行,主要用于事务执行 - UpdateByIdWithDb(db *gorm.DB, e T) error + UpdateByIdWithDb(ctx context.Context, db *gorm.DB, e T) error // 根据实体主键删除实体 - DeleteById(id uint64) error + DeleteById(ctx context.Context, id uint64) error // 使用指定gorm db执行,主要用于事务执行 - DeleteByIdWithDb(db *gorm.DB, id uint64) error + DeleteByIdWithDb(ctx context.Context, db *gorm.DB, id uint64) error // 根据实体条件,更新参数udpateFields指定字段 Updates(cond any, udpateFields map[string]any) error // 根据实体条件删除实体 - DeleteByCond(cond any) error + DeleteByCond(ctx context.Context, cond any) error // 使用指定gorm db执行,主要用于事务执行 - DeleteByCondWithDb(db *gorm.DB, cond any) error + DeleteByCondWithDb(ctx context.Context, db *gorm.DB, cond any) error // 根据实体id查询 GetById(e T, id uint64, cols ...string) error @@ -66,52 +69,58 @@ type Repo[T any] interface { } // 基础repo接口 -type RepoImpl[T any] struct { +type RepoImpl[T model.ModelI] struct { M any // 模型实例 } -func (br *RepoImpl[T]) Insert(e T) error { - return gormx.Insert(e) +func (br *RepoImpl[T]) Insert(ctx context.Context, e T) error { + return gormx.Insert(br.setBaseInfo(ctx, e)) } -func (br *RepoImpl[T]) InsertWithDb(db *gorm.DB, e T) error { - return gormx.InsertWithDb(db, e) +func (br *RepoImpl[T]) InsertWithDb(ctx context.Context, db *gorm.DB, e T) error { + return gormx.InsertWithDb(db, br.setBaseInfo(ctx, e)) } -func (br *RepoImpl[T]) BatchInsert(es []T) error { +func (br *RepoImpl[T]) BatchInsert(ctx context.Context, es []T) error { + for _, e := range es { + br.setBaseInfo(ctx, e) + } return gormx.BatchInsert(es) } // 使用指定gorm db执行,主要用于事务执行 -func (br *RepoImpl[T]) BatchInsertWithDb(db *gorm.DB, es []T) error { +func (br *RepoImpl[T]) BatchInsertWithDb(ctx context.Context, db *gorm.DB, es []T) error { + for _, e := range es { + br.setBaseInfo(ctx, e) + } return gormx.BatchInsertWithDb(db, es) } -func (br *RepoImpl[T]) UpdateById(e T) error { - return gormx.UpdateById(e) +func (br *RepoImpl[T]) UpdateById(ctx context.Context, e T) error { + return gormx.UpdateById(br.setBaseInfo(ctx, e)) } -func (br *RepoImpl[T]) UpdateByIdWithDb(db *gorm.DB, e T) error { - return gormx.UpdateByIdWithDb(db, e) +func (br *RepoImpl[T]) UpdateByIdWithDb(ctx context.Context, db *gorm.DB, e T) error { + return gormx.UpdateByIdWithDb(db, br.setBaseInfo(ctx, e)) } func (br *RepoImpl[T]) Updates(cond any, udpateFields map[string]any) error { return gormx.Updates(cond, udpateFields) } -func (br *RepoImpl[T]) DeleteById(id uint64) error { +func (br *RepoImpl[T]) DeleteById(ctx context.Context, id uint64) error { return gormx.DeleteById(br.getModel(), id) } -func (br *RepoImpl[T]) DeleteByIdWithDb(db *gorm.DB, id uint64) error { +func (br *RepoImpl[T]) DeleteByIdWithDb(ctx context.Context, db *gorm.DB, id uint64) error { return gormx.DeleteByCondWithDb(db, br.getModel(), id) } -func (br *RepoImpl[T]) DeleteByCond(cond any) error { +func (br *RepoImpl[T]) DeleteByCond(ctx context.Context, cond any) error { return gormx.DeleteByCond(br.getModel(), cond) } -func (br *RepoImpl[T]) DeleteByCondWithDb(db *gorm.DB, cond any) error { +func (br *RepoImpl[T]) DeleteByCondWithDb(ctx context.Context, db *gorm.DB, cond any) error { return gormx.DeleteByCondWithDb(db, br.getModel(), cond) } @@ -147,3 +156,11 @@ func (br *RepoImpl[T]) getModel() any { biz.IsTrue(br.M != nil, "base.RepoImpl的M字段不能为空") return br.M } + +// 从上下文获取登录账号信息,并赋值至实体 +func (br *RepoImpl[T]) setBaseInfo(ctx context.Context, e T) T { + if la := contextx.GetLoginAccount(ctx); la != nil { + e.SetBaseInfo(la) + } + return e +} diff --git a/server/pkg/contextx/contextx.go b/server/pkg/contextx/contextx.go index 94272e63..bf5f53a6 100644 --- a/server/pkg/contextx/contextx.go +++ b/server/pkg/contextx/contextx.go @@ -21,9 +21,12 @@ func WithLoginAccount(ctx context.Context, la *model.LoginAccount) context.Conte return context.WithValue(ctx, LoginAccountKey, la) } -// 从context中获取登录账号信息 +// 从context中获取登录账号信息,不存在返回nil func GetLoginAccount(ctx context.Context) *model.LoginAccount { - return ctx.Value(LoginAccountKey).(*model.LoginAccount) + if la, ok := ctx.Value(LoginAccountKey).(*model.LoginAccount); ok { + return la + } + return nil } func NewTraceId() context.Context { @@ -31,10 +34,13 @@ func NewTraceId() context.Context { } func WithTraceId(ctx context.Context) context.Context { - return context.WithValue(ctx, TraceIdKey, stringx.Rand(16)) + return context.WithValue(ctx, TraceIdKey, stringx.RandByChars(16, stringx.Nums+stringx.LowerChars)) } // 从context中获取traceId func GetTraceId(ctx context.Context) string { - return ctx.Value(TraceIdKey).(string) + if val, ok := ctx.Value(TraceIdKey).(string); ok { + return val + } + return "" } diff --git a/server/pkg/logx/logx.go b/server/pkg/logx/logx.go index 1481976b..5e18cf66 100644 --- a/server/pkg/logx/logx.go +++ b/server/pkg/logx/logx.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "log/slog" + "mayfly-go/pkg/contextx" "mayfly-go/pkg/utils/runtimex" "path/filepath" "runtime" @@ -47,7 +48,7 @@ func Debugf(format string, args ...any) { Log(context.Background(), slog.LevelDebug, fmt.Sprintf(format, args...)) } -func DebugWithFields(msg string, mapFields map[string]any) { +func DebugWithFields(ctx context.Context, msg string, mapFields map[string]any) { Log(context.Background(), slog.LevelDebug, msg, map2Attrs(mapFields)...) } @@ -68,8 +69,8 @@ func Infof(format string, args ...any) { Log(context.Background(), slog.LevelInfo, fmt.Sprintf(format, args...)) } -func InfoWithFields(msg string, mapFields map[string]any) { - Log(context.Background(), slog.LevelInfo, msg, map2Attrs(mapFields)...) +func InfoWithFields(ctx context.Context, msg string, mapFields map[string]any) { + Log(ctx, slog.LevelInfo, msg, map2Attrs(mapFields)...) } func Warn(msg string, args ...any) { @@ -97,8 +98,8 @@ func ErrorTrace(msg string, err error) { Log(context.Background(), slog.LevelError, fmt.Sprintf(msg+" %s\n%s", err.Error(), runtimex.StatckStr(2, 10))) } -func ErrorWithFields(msg string, mapFields map[string]any) { - Log(context.Background(), slog.LevelError, msg, map2Attrs(mapFields)...) +func ErrorWithFields(ctx context.Context, msg string, mapFields map[string]any) { + Log(ctx, slog.LevelError, msg, map2Attrs(mapFields)...) } func Panic(msg string, args ...any) { @@ -120,6 +121,10 @@ func Log(ctx context.Context, level slog.Level, msg string, args ...any) { func getCommonAttr(ctx context.Context, level slog.Level) []any { commonAttrs := make([]any, 0) + // 尝试从上下文获取traceId,若存在则记录 + if traceId := contextx.GetTraceId(ctx); traceId != "" { + commonAttrs = append(commonAttrs, "tid", traceId) + } // 如果系统配置添加方法信息或者为错误级别时则 记录方法信息及行号 if GetConfig().AddSource || level == slog.LevelError { // skip [runtime.Callers, getCommonAttr, appendCommonAttr, logx.Log, logx.Info|Debug|Warn|Error..] diff --git a/server/pkg/model/model.go b/server/pkg/model/model.go index 8744c32b..6a5f4d0b 100644 --- a/server/pkg/model/model.go +++ b/server/pkg/model/model.go @@ -12,6 +12,15 @@ const ( ModelUndeleted int8 = 0 ) +// 实体接口 +type ModelI interface { + + // 使用当前登录账号信息设置实体结构体的基础信息 + // + // 如创建时间,修改时间,创建者,修改者信息 + SetBaseInfo(account *LoginAccount) +} + // 含有删除字段模型 type DeletedModel struct { Id uint64 `json:"id"` @@ -19,6 +28,13 @@ type DeletedModel struct { DeleteTime *time.Time `json:"-"` } +func (m *DeletedModel) SetBaseInfo(account *LoginAccount) { + isCreate := m.Id == 0 + if isCreate { + m.IsDeleted = ModelUndeleted + } +} + // 基础实体模型,数据表最基础字段,每张表必备字段 type Model struct { DeletedModel diff --git a/server/pkg/req/log_handler.go b/server/pkg/req/log_handler.go index df87a2d3..a1e07fec 100644 --- a/server/pkg/req/log_handler.go +++ b/server/pkg/req/log_handler.go @@ -2,6 +2,7 @@ package req import ( "fmt" + "mayfly-go/pkg/contextx" "mayfly-go/pkg/errorx" "mayfly-go/pkg/logx" "mayfly-go/pkg/utils/anyx" @@ -54,7 +55,7 @@ func LogHandler(rc *Ctx) error { req := rc.GinCtx.Request attrMap[req.Method] = req.URL.Path - if la := rc.LoginAccount; la != nil { + if la := contextx.GetLoginAccount(rc.MetaCtx); la != nil { attrMap["uid"] = la.Id attrMap["uname"] = la.Username } @@ -93,10 +94,10 @@ func LogHandler(rc *Ctx) error { } if err := rc.Err; err != nil { - logx.ErrorWithFields(logMsg, attrMap) + logx.ErrorWithFields(rc.MetaCtx, logMsg, attrMap) return nil } - logx.InfoWithFields(logMsg, attrMap) + logx.InfoWithFields(rc.MetaCtx, logMsg, attrMap) return nil } diff --git a/server/pkg/req/permission_handler.go b/server/pkg/req/permission_handler.go index 23218da7..c0858484 100644 --- a/server/pkg/req/permission_handler.go +++ b/server/pkg/req/permission_handler.go @@ -5,6 +5,7 @@ import ( "fmt" "mayfly-go/pkg/cache" "mayfly-go/pkg/config" + "mayfly-go/pkg/contextx" "mayfly-go/pkg/errorx" "mayfly-go/pkg/model" "mayfly-go/pkg/rediscli" @@ -60,12 +61,10 @@ func PermissionHandler(rc *Ctx) error { return errorx.PermissionErr } } - if rc.LoginAccount == nil { - rc.LoginAccount = &model.LoginAccount{ - Id: userId, - Username: userName, - } - } + rc.MetaCtx = contextx.WithLoginAccount(rc.MetaCtx, &model.LoginAccount{ + Id: userId, + Username: userName, + }) return nil } diff --git a/server/pkg/req/req_ctx.go b/server/pkg/req/req_ctx.go index 997670e2..c03630d5 100644 --- a/server/pkg/req/req_ctx.go +++ b/server/pkg/req/req_ctx.go @@ -1,7 +1,10 @@ package req import ( + "context" "io" + "mayfly-go/pkg/biz" + "mayfly-go/pkg/contextx" "mayfly-go/pkg/ginx" "mayfly-go/pkg/model" "mayfly-go/pkg/utils/assert" @@ -16,12 +19,13 @@ type HandlerFunc func(*Ctx) type Ctx struct { Conf *Conf // 请求配置 - GinCtx *gin.Context // gin context - LoginAccount *model.LoginAccount // 登录账号信息,只有校验token后才会有值 - ReqParam any // 请求参数,主要用于记录日志 - ResData any // 响应结果 - Err any // 请求错误 - timed int64 // 执行时间 + GinCtx *gin.Context // gin context + ReqParam any // 请求参数,主要用于记录日志 + ResData any // 响应结果 + Err any // 请求错误 + timed int64 // 执行时间 + + MetaCtx context.Context // 元数据上下文信息,如登录账号(只有校验token后才会有值),traceId等 } func (rc *Ctx) Handle(handler HandlerFunc) { @@ -59,6 +63,15 @@ func (rc *Ctx) Download(reader io.Reader, filename string) { ginx.Download(rc.GinCtx, reader, filename) } +// 获取当前登录账号信息,不存在则会报错。 +// +// 若不需要报错,则使用contextx.GetLoginAccount方法 +func (rc *Ctx) GetLoginAccount() *model.LoginAccount { + la := contextx.GetLoginAccount(rc.MetaCtx) + biz.IsTrue(la != nil, "获取登录账号信息失败, 请确认该接口是否通过鉴权") + return la +} + func (rc *Ctx) WithConf(conf *Conf) *Ctx { rc.Conf = conf return rc @@ -87,7 +100,7 @@ func (rc *Ctx) GetLogInfo() *LogInfo { } func NewCtxWithGin(g *gin.Context) *Ctx { - return &Ctx{GinCtx: g} + return &Ctx{GinCtx: g, MetaCtx: contextx.NewTraceId()} } // 处理器拦截器函数 diff --git a/server/pkg/utils/jsonx/jsonx.go b/server/pkg/utils/jsonx/jsonx.go index 1d408048..b50acc0d 100644 --- a/server/pkg/utils/jsonx/jsonx.go +++ b/server/pkg/utils/jsonx/jsonx.go @@ -13,6 +13,11 @@ func ToMap(jsonStr string) map[string]any { return ToMapByBytes([]byte(jsonStr)) } +// json字符串转结构体 +func To[T any](jsonStr string, res T) (T, error) { + return res, json.Unmarshal([]byte(jsonStr), &res) +} + // json字节数组转map func ToMapByBytes(bytes []byte) map[string]any { var res map[string]any diff --git a/server/pkg/utils/stringx/rand.go b/server/pkg/utils/stringx/rand.go index b4de7bb7..4c9c476c 100644 --- a/server/pkg/utils/stringx/rand.go +++ b/server/pkg/utils/stringx/rand.go @@ -5,11 +5,18 @@ import ( "time" ) -const randChar = "0123456789abcdefghigklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" +const Nums = "0123456789" +const LowerChars = "abcdefghigklmnopqrstuvwxyz" +const UpperChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" // 生成随机字符串 func Rand(l int) string { - strList := []byte(randChar) + return RandByChars(l, Nums+LowerChars+UpperChars) +} + +// 根据传入的chars,随机生成指定位数的字符串 +func RandByChars(l int, chars string) string { + strList := []byte(chars) result := []byte{} i := 0 diff --git a/server/pkg/utils/stringx/template_test.go b/server/pkg/utils/stringx/template_test.go new file mode 100644 index 00000000..61039ecf --- /dev/null +++ b/server/pkg/utils/stringx/template_test.go @@ -0,0 +1,26 @@ +package stringx + +import ( + "fmt" + "mayfly-go/pkg/utils/collx" + "strings" + "testing" +) + +func TestTemplateParse(t *testing.T) { + tmpl := ` + {{if gt .cpu 10*5}} + 当前服务器[{{.asset.host}}]cpu使用率为{{.cpu}} + {{end}} + ` + vars := collx.M{ + "cpu": 60, + "asset": collx.M{ + "host": "localhost:121", + }, + } + + res, _ := TemplateParse(tmpl, vars) + res2 := strings.TrimSpace(res) + fmt.Println(res2) +}