mirror of
				https://gitee.com/dromara/mayfly-go
				synced 2025-11-04 08:20:25 +08:00 
			
		
		
		
	fix: 问题修复与redis密码迁移至凭证
This commit is contained in:
		@@ -100,9 +100,6 @@ export function backEndRouterConverter(routes: any, callbackFunc: RouterConvCall
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
        // 将json字符串的meta转为对象
 | 
					        // 将json字符串的meta转为对象
 | 
				
			||||||
        item.meta = JSON.parse(item.meta);
 | 
					        item.meta = JSON.parse(item.meta);
 | 
				
			||||||
        if (item.meta.isHide) {
 | 
					 | 
				
			||||||
            continue;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // 将meta.comoponet 解析为route.component
 | 
					        // 将meta.comoponet 解析为route.component
 | 
				
			||||||
        if (item.meta.component) {
 | 
					        if (item.meta.component) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -73,7 +73,6 @@
 | 
				
			|||||||
                    <el-input v-model="form.remark" auto-complete="off" type="textarea"></el-input>
 | 
					                    <el-input v-model="form.remark" auto-complete="off" type="textarea"></el-input>
 | 
				
			||||||
                </el-form-item>
 | 
					                </el-form-item>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                <template v-if="form.type !== DbType.sqlite">
 | 
					 | 
				
			||||||
                <el-divider content-position="left">账号</el-divider>
 | 
					                <el-divider content-position="left">账号</el-divider>
 | 
				
			||||||
                <div>
 | 
					                <div>
 | 
				
			||||||
                    <ResourceAuthCertTableEdit
 | 
					                    <ResourceAuthCertTableEdit
 | 
				
			||||||
@@ -85,22 +84,6 @@
 | 
				
			|||||||
                        :disable-ciphertext-type="[AuthCertCiphertextTypeEnum.PrivateKey.value]"
 | 
					                        :disable-ciphertext-type="[AuthCertCiphertextTypeEnum.PrivateKey.value]"
 | 
				
			||||||
                    />
 | 
					                    />
 | 
				
			||||||
                </div>
 | 
					                </div>
 | 
				
			||||||
                </template>
 | 
					 | 
				
			||||||
                <!--
 | 
					 | 
				
			||||||
                <el-form-item v-if="form.type !== DbType.sqlite" prop="username" label="用户名" required>
 | 
					 | 
				
			||||||
                    <el-input v-model.trim="form.username" placeholder="请输入用户名"></el-input>
 | 
					 | 
				
			||||||
                </el-form-item>
 | 
					 | 
				
			||||||
                <el-form-item v-if="form.type !== DbType.sqlite" prop="password" label="密码">
 | 
					 | 
				
			||||||
                    <el-input type="password" show-password v-model.trim="form.password" placeholder="请输入密码" autocomplete="new-password">
 | 
					 | 
				
			||||||
                        <template v-if="form.id && form.id != 0" #suffix>
 | 
					 | 
				
			||||||
                            <el-popover @hide="pwd = ''" placement="right" title="原密码" :width="200" trigger="click" :content="pwd">
 | 
					 | 
				
			||||||
                                <template #reference>
 | 
					 | 
				
			||||||
                                    <el-link v-auth="'db:instance:save'" @click="getDbPwd" :underline="false" type="primary" class="mr5">原密码 </el-link>
 | 
					 | 
				
			||||||
                                </template>
 | 
					 | 
				
			||||||
                            </el-popover>
 | 
					 | 
				
			||||||
                        </template>
 | 
					 | 
				
			||||||
                    </el-input>
 | 
					 | 
				
			||||||
                </el-form-item> -->
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
                <el-divider content-position="left">其他</el-divider>
 | 
					                <el-divider content-position="left">其他</el-divider>
 | 
				
			||||||
                <el-form-item prop="params" label="连接参数">
 | 
					                <el-form-item prop="params" label="连接参数">
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -57,14 +57,15 @@
 | 
				
			|||||||
                                v-model.trim="form.password"
 | 
					                                v-model.trim="form.password"
 | 
				
			||||||
                                placeholder="请输入密码, 修改操作可不填"
 | 
					                                placeholder="请输入密码, 修改操作可不填"
 | 
				
			||||||
                                autocomplete="new-password"
 | 
					                                autocomplete="new-password"
 | 
				
			||||||
                                ><template v-if="form.id && form.id != 0" #suffix>
 | 
					                            >
 | 
				
			||||||
 | 
					                                <!-- <template v-if="form.id && form.id != 0" #suffix>
 | 
				
			||||||
                                    <el-popover @hide="pwd = ''" placement="right" title="原密码" :width="200" trigger="click" :content="pwd">
 | 
					                                    <el-popover @hide="pwd = ''" placement="right" title="原密码" :width="200" trigger="click" :content="pwd">
 | 
				
			||||||
                                        <template #reference>
 | 
					                                        <template #reference>
 | 
				
			||||||
                                            <el-link @click="getPwd" :underline="false" type="primary" class="mr5">原密码</el-link>
 | 
					                                            <el-link @click="getPwd" :underline="false" type="primary" class="mr5">原密码</el-link>
 | 
				
			||||||
                                        </template>
 | 
					                                        </template>
 | 
				
			||||||
                                    </el-popover>
 | 
					                                    </el-popover>
 | 
				
			||||||
                                </template></el-input
 | 
					                                </template> -->
 | 
				
			||||||
                            >
 | 
					                            </el-input>
 | 
				
			||||||
                        </el-form-item>
 | 
					                        </el-form-item>
 | 
				
			||||||
                        <el-form-item prop="db" label="库号" required>
 | 
					                        <el-form-item prop="db" label="库号" required>
 | 
				
			||||||
                            <el-select
 | 
					                            <el-select
 | 
				
			||||||
@@ -110,7 +111,6 @@
 | 
				
			|||||||
import { toRefs, reactive, watch, ref } from 'vue';
 | 
					import { toRefs, reactive, watch, ref } from 'vue';
 | 
				
			||||||
import { redisApi } from './api';
 | 
					import { redisApi } from './api';
 | 
				
			||||||
import { ElMessage } from 'element-plus';
 | 
					import { ElMessage } from 'element-plus';
 | 
				
			||||||
import { RsaEncrypt } from '@/common/rsa';
 | 
					 | 
				
			||||||
import TagTreeSelect from '../component/TagTreeSelect.vue';
 | 
					import TagTreeSelect from '../component/TagTreeSelect.vue';
 | 
				
			||||||
import SshTunnelSelect from '../component/SshTunnelSelect.vue';
 | 
					import SshTunnelSelect from '../component/SshTunnelSelect.vue';
 | 
				
			||||||
import ProcdefSelectFormItem from '@/views/flow/components/ProcdefSelectFormItem.vue';
 | 
					import ProcdefSelectFormItem from '@/views/flow/components/ProcdefSelectFormItem.vue';
 | 
				
			||||||
@@ -206,7 +206,7 @@ const state = reactive({
 | 
				
			|||||||
    pwd: '',
 | 
					    pwd: '',
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const { dialogVisible, tabActiveName, form, submitForm, dbList, pwd } = toRefs(state);
 | 
					const { dialogVisible, tabActiveName, form, submitForm, dbList } = toRefs(state);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const { isFetching: testConnBtnLoading, execute: testConnExec } = redisApi.testConn.useApi(submitForm);
 | 
					const { isFetching: testConnBtnLoading, execute: testConnExec } = redisApi.testConn.useApi(submitForm);
 | 
				
			||||||
const { isFetching: saveBtnLoading, execute: saveRedisExec } = redisApi.saveRedis.useApi(submitForm);
 | 
					const { isFetching: saveBtnLoading, execute: saveRedisExec } = redisApi.saveRedis.useApi(submitForm);
 | 
				
			||||||
@@ -238,10 +238,6 @@ const changeDb = () => {
 | 
				
			|||||||
    state.form.db = state.dbList.length == 0 ? '' : state.dbList.join(',');
 | 
					    state.form.db = state.dbList.length == 0 ? '' : state.dbList.join(',');
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const getPwd = async () => {
 | 
					 | 
				
			||||||
    state.pwd = await redisApi.getRedisPwd.request({ id: state.form.id });
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const getReqForm = async () => {
 | 
					const getReqForm = async () => {
 | 
				
			||||||
    const reqForm = { ...state.form };
 | 
					    const reqForm = { ...state.form };
 | 
				
			||||||
    if (reqForm.mode == 'sentinel' && reqForm.host.split('=').length != 2) {
 | 
					    if (reqForm.mode == 'sentinel' && reqForm.host.split('=').length != 2) {
 | 
				
			||||||
@@ -251,7 +247,6 @@ const getReqForm = async () => {
 | 
				
			|||||||
    if (!state.form.sshTunnelMachineId || state.form.sshTunnelMachineId <= 0) {
 | 
					    if (!state.form.sshTunnelMachineId || state.form.sshTunnelMachineId <= 0) {
 | 
				
			||||||
        reqForm.sshTunnelMachineId = -1;
 | 
					        reqForm.sshTunnelMachineId = -1;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    reqForm.password = await RsaEncrypt(reqForm.password);
 | 
					 | 
				
			||||||
    return reqForm;
 | 
					    return reqForm;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -140,7 +140,7 @@
 | 
				
			|||||||
        </el-dialog>
 | 
					        </el-dialog>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        <redis-edit
 | 
					        <redis-edit
 | 
				
			||||||
            @val-change="search"
 | 
					            @val-change="search()"
 | 
				
			||||||
            :title="redisEditDialog.title"
 | 
					            :title="redisEditDialog.title"
 | 
				
			||||||
            v-model:visible="redisEditDialog.visible"
 | 
					            v-model:visible="redisEditDialog.visible"
 | 
				
			||||||
            v-model:redis="redisEditDialog.data"
 | 
					            v-model:redis="redisEditDialog.data"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,7 +8,7 @@ type DbForm struct {
 | 
				
			|||||||
	Remark         string   `json:"remark"`
 | 
						Remark         string   `json:"remark"`
 | 
				
			||||||
	TagId          []uint64 `binding:"required" json:"tagId"`
 | 
						TagId          []uint64 `binding:"required" json:"tagId"`
 | 
				
			||||||
	InstanceId     uint64   `binding:"required" json:"instanceId"`
 | 
						InstanceId     uint64   `binding:"required" json:"instanceId"`
 | 
				
			||||||
	AuthCertName   string   `json: "authCertName`
 | 
						AuthCertName   string   `json: "authCertName"`
 | 
				
			||||||
	FlowProcdefKey string   `json:"flowProcdefKey"`
 | 
						FlowProcdefKey string   `json:"flowProcdefKey"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -92,7 +92,7 @@ func (d *dbSqlExecAppImpl) Exec(ctx context.Context, execSqlReq *DbSqlExecReq) (
 | 
				
			|||||||
		// 就算解析失败也执行sql,让数据库来判断错误。如果是查询sql则简单判断是否有limit分页参数信息(兼容pgsql)
 | 
							// 就算解析失败也执行sql,让数据库来判断错误。如果是查询sql则简单判断是否有limit分页参数信息(兼容pgsql)
 | 
				
			||||||
		// logx.Warnf("sqlparse解析sql[%s]失败: %s", sql, err.Error())
 | 
							// logx.Warnf("sqlparse解析sql[%s]失败: %s", sql, err.Error())
 | 
				
			||||||
		lowerSql := strings.ToLower(execSqlReq.Sql)
 | 
							lowerSql := strings.ToLower(execSqlReq.Sql)
 | 
				
			||||||
		isSelect := strings.HasPrefix(lowerSql, "select")
 | 
							isSelect := strings.HasPrefix(lowerSql, "select") || strings.HasPrefix(lowerSql, "explain")
 | 
				
			||||||
		if isSelect {
 | 
							if isSelect {
 | 
				
			||||||
			// 如果配置为0,则不校验分页参数
 | 
								// 如果配置为0,则不校验分页参数
 | 
				
			||||||
			maxCount := config.GetDbms().MaxResultSet
 | 
								maxCount := config.GetDbms().MaxResultSet
 | 
				
			||||||
@@ -129,6 +129,9 @@ func (d *dbSqlExecAppImpl) Exec(ctx context.Context, execSqlReq *DbSqlExecReq) (
 | 
				
			|||||||
	case *sqlparser.Select:
 | 
						case *sqlparser.Select:
 | 
				
			||||||
		isSelect = true
 | 
							isSelect = true
 | 
				
			||||||
		execRes, err = d.doSelect(ctx, stmt, execSqlReq)
 | 
							execRes, err = d.doSelect(ctx, stmt, execSqlReq)
 | 
				
			||||||
 | 
						case *sqlparser.ExplainStmt:
 | 
				
			||||||
 | 
							isSelect = true
 | 
				
			||||||
 | 
							execRes, err = d.doRead(ctx, execSqlReq)
 | 
				
			||||||
	case *sqlparser.Show:
 | 
						case *sqlparser.Show:
 | 
				
			||||||
		isSelect = true
 | 
							isSelect = true
 | 
				
			||||||
		execRes, err = d.doRead(ctx, execSqlReq)
 | 
							execRes, err = d.doRead(ctx, execSqlReq)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,6 +2,7 @@ package api
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
	"mayfly-go/internal/common/consts"
 | 
						"mayfly-go/internal/common/consts"
 | 
				
			||||||
	"mayfly-go/internal/redis/api/form"
 | 
						"mayfly-go/internal/redis/api/form"
 | 
				
			||||||
	"mayfly-go/internal/redis/api/vo"
 | 
						"mayfly-go/internal/redis/api/vo"
 | 
				
			||||||
@@ -14,7 +15,6 @@ import (
 | 
				
			|||||||
	"mayfly-go/pkg/model"
 | 
						"mayfly-go/pkg/model"
 | 
				
			||||||
	"mayfly-go/pkg/req"
 | 
						"mayfly-go/pkg/req"
 | 
				
			||||||
	"mayfly-go/pkg/utils/collx"
 | 
						"mayfly-go/pkg/utils/collx"
 | 
				
			||||||
	"mayfly-go/pkg/utils/cryptox"
 | 
					 | 
				
			||||||
	"mayfly-go/pkg/utils/stringx"
 | 
						"mayfly-go/pkg/utils/stringx"
 | 
				
			||||||
	"strconv"
 | 
						"strconv"
 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
@@ -54,39 +54,40 @@ func (r *Redis) TestConn(rc *req.Ctx) {
 | 
				
			|||||||
	form := &form.Redis{}
 | 
						form := &form.Redis{}
 | 
				
			||||||
	redis := req.BindJsonAndCopyTo[*entity.Redis](rc, form, new(entity.Redis))
 | 
						redis := req.BindJsonAndCopyTo[*entity.Redis](rc, form, new(entity.Redis))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// 密码解密,并使用解密后的赋值
 | 
						biz.ErrIsNil(r.RedisApp.TestConn(&application.SaveRedisParam{
 | 
				
			||||||
	originPwd, err := cryptox.DefaultRsaDecrypt(redis.Password, true)
 | 
							Redis:  redis,
 | 
				
			||||||
	biz.ErrIsNilAppendErr(err, "解密密码错误: %s")
 | 
							TagIds: form.TagId,
 | 
				
			||||||
	redis.Password = originPwd
 | 
							AuthCert: &tagentity.ResourceAuthCert{
 | 
				
			||||||
 | 
								Name:           fmt.Sprintf("redis_%s_ac", redis.Code),
 | 
				
			||||||
	biz.ErrIsNil(r.RedisApp.TestConn(redis))
 | 
								Username:       form.Username,
 | 
				
			||||||
 | 
								Ciphertext:     form.Password,
 | 
				
			||||||
 | 
								CiphertextType: tagentity.AuthCertCiphertextTypePassword,
 | 
				
			||||||
 | 
								Type:           tagentity.AuthCertTypePrivate,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (r *Redis) Save(rc *req.Ctx) {
 | 
					func (r *Redis) Save(rc *req.Ctx) {
 | 
				
			||||||
	form := &form.Redis{}
 | 
						form := &form.Redis{}
 | 
				
			||||||
	redis := req.BindJsonAndCopyTo[*entity.Redis](rc, form, new(entity.Redis))
 | 
						redis := req.BindJsonAndCopyTo[*entity.Redis](rc, form, new(entity.Redis))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// 密码解密,并使用解密后的赋值
 | 
					 | 
				
			||||||
	originPwd, err := cryptox.DefaultRsaDecrypt(redis.Password, true)
 | 
					 | 
				
			||||||
	biz.ErrIsNilAppendErr(err, "解密密码错误: %s")
 | 
					 | 
				
			||||||
	redis.Password = originPwd
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// 密码脱敏记录日志
 | 
						// 密码脱敏记录日志
 | 
				
			||||||
	form.Password = "****"
 | 
						form.Password = "****"
 | 
				
			||||||
	rc.ReqParam = form
 | 
						rc.ReqParam = form
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	biz.ErrIsNil(r.RedisApp.SaveRedis(rc.MetaCtx, redis, form.TagId...))
 | 
						redisParam := &application.SaveRedisParam{
 | 
				
			||||||
}
 | 
							Redis:  redis,
 | 
				
			||||||
 | 
							TagIds: form.TagId,
 | 
				
			||||||
// 获取redis实例密码,由于数据库是加密存储,故提供该接口展示原文密码
 | 
							AuthCert: &tagentity.ResourceAuthCert{
 | 
				
			||||||
func (r *Redis) GetRedisPwd(rc *req.Ctx) {
 | 
								Name:           fmt.Sprintf("redis_%s_ac", redis.Code),
 | 
				
			||||||
	rid := uint64(rc.PathParamInt("id"))
 | 
								Username:       form.Username,
 | 
				
			||||||
	re, err := r.RedisApp.GetById(new(entity.Redis), rid, "Password")
 | 
								Ciphertext:     form.Password,
 | 
				
			||||||
	biz.ErrIsNil(err, "redis信息不存在")
 | 
								CiphertextType: tagentity.AuthCertCiphertextTypePassword,
 | 
				
			||||||
	if err := re.PwdDecrypt(); err != nil {
 | 
								Type:           tagentity.AuthCertTypePrivate,
 | 
				
			||||||
		biz.ErrIsNil(err)
 | 
							},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	rc.ResData = re.Password
 | 
					
 | 
				
			||||||
 | 
						biz.ErrIsNil(r.RedisApp.SaveRedis(rc.MetaCtx, redisParam))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (r *Redis) DeleteRedis(rc *req.Ctx) {
 | 
					func (r *Redis) DeleteRedis(rc *req.Ctx) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,7 +9,7 @@ import (
 | 
				
			|||||||
	"mayfly-go/internal/redis/domain/repository"
 | 
						"mayfly-go/internal/redis/domain/repository"
 | 
				
			||||||
	"mayfly-go/internal/redis/rdm"
 | 
						"mayfly-go/internal/redis/rdm"
 | 
				
			||||||
	tagapp "mayfly-go/internal/tag/application"
 | 
						tagapp "mayfly-go/internal/tag/application"
 | 
				
			||||||
	tagenttiy "mayfly-go/internal/tag/domain/entity"
 | 
						tagentity "mayfly-go/internal/tag/domain/entity"
 | 
				
			||||||
	"mayfly-go/pkg/base"
 | 
						"mayfly-go/pkg/base"
 | 
				
			||||||
	"mayfly-go/pkg/errorx"
 | 
						"mayfly-go/pkg/errorx"
 | 
				
			||||||
	"mayfly-go/pkg/logx"
 | 
						"mayfly-go/pkg/logx"
 | 
				
			||||||
@@ -19,9 +19,16 @@ import (
 | 
				
			|||||||
	"strconv"
 | 
						"strconv"
 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/may-fly/cast"
 | 
				
			||||||
	"github.com/redis/go-redis/v9"
 | 
						"github.com/redis/go-redis/v9"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type SaveRedisParam struct {
 | 
				
			||||||
 | 
						Redis    *entity.Redis
 | 
				
			||||||
 | 
						AuthCert *tagentity.ResourceAuthCert
 | 
				
			||||||
 | 
						TagIds   []uint64
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type RunCmdParam struct {
 | 
					type RunCmdParam struct {
 | 
				
			||||||
	Id     uint64 `json:"id"`
 | 
						Id     uint64 `json:"id"`
 | 
				
			||||||
	Db     int    `json:"db"`
 | 
						Db     int    `json:"db"`
 | 
				
			||||||
@@ -37,9 +44,9 @@ type Redis interface {
 | 
				
			|||||||
	GetPageList(condition *entity.RedisQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error)
 | 
						GetPageList(condition *entity.RedisQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// 测试连接
 | 
						// 测试连接
 | 
				
			||||||
	TestConn(re *entity.Redis) error
 | 
						TestConn(re *SaveRedisParam) error
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	SaveRedis(ctx context.Context, re *entity.Redis, tagIds ...uint64) error
 | 
						SaveRedis(ctx context.Context, param *SaveRedisParam) error
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// 删除数据库信息
 | 
						// 删除数据库信息
 | 
				
			||||||
	Delete(ctx context.Context, id uint64) error
 | 
						Delete(ctx context.Context, id uint64) error
 | 
				
			||||||
@@ -58,6 +65,7 @@ type redisAppImpl struct {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	tagApp              tagapp.TagTree          `inject:"TagTreeApp"`
 | 
						tagApp              tagapp.TagTree          `inject:"TagTreeApp"`
 | 
				
			||||||
	procinstApp         flowapp.Procinst        `inject:"ProcinstApp"`
 | 
						procinstApp         flowapp.Procinst        `inject:"ProcinstApp"`
 | 
				
			||||||
 | 
						resourceAuthCertApp tagapp.ResourceAuthCert `inject:"ResourceAuthCertApp"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// 注入RedisRepo
 | 
					// 注入RedisRepo
 | 
				
			||||||
@@ -70,13 +78,28 @@ func (r *redisAppImpl) GetPageList(condition *entity.RedisQuery, pageParam *mode
 | 
				
			|||||||
	return r.GetRepo().GetRedisList(condition, pageParam, toEntity, orderBy...)
 | 
						return r.GetRepo().GetRedisList(condition, pageParam, toEntity, orderBy...)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (r *redisAppImpl) TestConn(re *entity.Redis) error {
 | 
					func (r *redisAppImpl) TestConn(param *SaveRedisParam) error {
 | 
				
			||||||
	db := 0
 | 
						db := 0
 | 
				
			||||||
 | 
						re := param.Redis
 | 
				
			||||||
	if re.Db != "" {
 | 
						if re.Db != "" {
 | 
				
			||||||
		db, _ = strconv.Atoi(strings.Split(re.Db, ",")[0])
 | 
							db = cast.ToInt(strings.Split(re.Db, ",")[0])
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	rc, err := re.ToRedisInfo(db).Conn()
 | 
						authCert := param.AuthCert
 | 
				
			||||||
 | 
						if authCert.Id != 0 {
 | 
				
			||||||
 | 
							// 密文可能被清除,故需要重新获取
 | 
				
			||||||
 | 
							authCert, _ = r.resourceAuthCertApp.GetAuthCert(authCert.Name)
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							if authCert.CiphertextType == tagentity.AuthCertCiphertextTypePublic {
 | 
				
			||||||
 | 
								publicAuthCert, err := r.resourceAuthCertApp.GetAuthCert(authCert.Ciphertext)
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									return err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								authCert = publicAuthCert
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rc, err := re.ToRedisInfo(db, authCert).Conn()
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -84,7 +107,9 @@ func (r *redisAppImpl) TestConn(re *entity.Redis) error {
 | 
				
			|||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (r *redisAppImpl) SaveRedis(ctx context.Context, re *entity.Redis, tagIds ...uint64) error {
 | 
					func (r *redisAppImpl) SaveRedis(ctx context.Context, param *SaveRedisParam) error {
 | 
				
			||||||
 | 
						re := param.Redis
 | 
				
			||||||
 | 
						tagIds := param.TagIds
 | 
				
			||||||
	// 查找是否存在该库
 | 
						// 查找是否存在该库
 | 
				
			||||||
	oldRedis := &entity.Redis{
 | 
						oldRedis := &entity.Redis{
 | 
				
			||||||
		Host:               re.Host,
 | 
							Host:               re.Host,
 | 
				
			||||||
@@ -100,18 +125,20 @@ func (r *redisAppImpl) SaveRedis(ctx context.Context, re *entity.Redis, tagIds .
 | 
				
			|||||||
			return errorx.NewBiz("该编码已存在")
 | 
								return errorx.NewBiz("该编码已存在")
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if errEnc := re.PwdEncrypt(); errEnc != nil {
 | 
					 | 
				
			||||||
			return errorx.NewBiz(errEnc.Error())
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		return r.Tx(ctx, func(ctx context.Context) error {
 | 
							return r.Tx(ctx, func(ctx context.Context) error {
 | 
				
			||||||
			return r.Insert(ctx, re)
 | 
								return r.Insert(ctx, re)
 | 
				
			||||||
		}, func(ctx context.Context) error {
 | 
							}, func(ctx context.Context) error {
 | 
				
			||||||
			return r.tagApp.SaveResourceTag(ctx, &tagapp.SaveResourceTagParam{
 | 
								return r.tagApp.SaveResourceTag(ctx, &tagapp.SaveResourceTagParam{
 | 
				
			||||||
				Type:         tagenttiy.TagTypeRedis,
 | 
									Type:         tagentity.TagTypeRedis,
 | 
				
			||||||
				Code:         re.Code,
 | 
									Code:         re.Code,
 | 
				
			||||||
				ParentTagIds: tagIds,
 | 
									ParentTagIds: tagIds,
 | 
				
			||||||
			})
 | 
								})
 | 
				
			||||||
 | 
							}, func(ctx context.Context) error {
 | 
				
			||||||
 | 
								return r.resourceAuthCertApp.RelateAuthCert(ctx, &tagapp.RelateAuthCertParam{
 | 
				
			||||||
 | 
									ResourceCode: re.Code,
 | 
				
			||||||
 | 
									ResourceType: tagentity.TagTypeRedis,
 | 
				
			||||||
 | 
									AuthCerts:    []*tagentity.ResourceAuthCert{param.AuthCert},
 | 
				
			||||||
 | 
								})
 | 
				
			||||||
		})
 | 
							})
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -131,18 +158,21 @@ func (r *redisAppImpl) SaveRedis(ctx context.Context, re *entity.Redis, tagIds .
 | 
				
			|||||||
		oldRedis, _ = r.GetById(new(entity.Redis), re.Id)
 | 
							oldRedis, _ = r.GetById(new(entity.Redis), re.Id)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if errEnc := re.PwdEncrypt(); errEnc != nil {
 | 
					 | 
				
			||||||
		return errorx.NewBiz(errEnc.Error())
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	re.Code = ""
 | 
						re.Code = ""
 | 
				
			||||||
	return r.Tx(ctx, func(ctx context.Context) error {
 | 
						return r.Tx(ctx, func(ctx context.Context) error {
 | 
				
			||||||
		return r.UpdateById(ctx, re)
 | 
							return r.UpdateById(ctx, re)
 | 
				
			||||||
	}, func(ctx context.Context) error {
 | 
						}, func(ctx context.Context) error {
 | 
				
			||||||
		return r.tagApp.SaveResourceTag(ctx, &tagapp.SaveResourceTagParam{
 | 
							return r.tagApp.SaveResourceTag(ctx, &tagapp.SaveResourceTagParam{
 | 
				
			||||||
			Type:         tagenttiy.TagTypeRedis,
 | 
								Type:         tagentity.TagTypeRedis,
 | 
				
			||||||
			Code:         oldRedis.Code,
 | 
								Code:         oldRedis.Code,
 | 
				
			||||||
			ParentTagIds: tagIds,
 | 
								ParentTagIds: tagIds,
 | 
				
			||||||
		})
 | 
							})
 | 
				
			||||||
 | 
						}, func(ctx context.Context) error {
 | 
				
			||||||
 | 
							return r.resourceAuthCertApp.RelateAuthCert(ctx, &tagapp.RelateAuthCertParam{
 | 
				
			||||||
 | 
								ResourceCode: oldRedis.Code,
 | 
				
			||||||
 | 
								ResourceType: tagentity.TagTypeRedis,
 | 
				
			||||||
 | 
								AuthCerts:    []*tagentity.ResourceAuthCert{param.AuthCert},
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -162,9 +192,14 @@ func (r *redisAppImpl) Delete(ctx context.Context, id uint64) error {
 | 
				
			|||||||
		return r.DeleteById(ctx, id)
 | 
							return r.DeleteById(ctx, id)
 | 
				
			||||||
	}, func(ctx context.Context) error {
 | 
						}, func(ctx context.Context) error {
 | 
				
			||||||
		return r.tagApp.SaveResourceTag(ctx, &tagapp.SaveResourceTagParam{
 | 
							return r.tagApp.SaveResourceTag(ctx, &tagapp.SaveResourceTagParam{
 | 
				
			||||||
			Type: tagenttiy.TagTypeRedis,
 | 
								Type: tagentity.TagTypeRedis,
 | 
				
			||||||
			Code: re.Code,
 | 
								Code: re.Code,
 | 
				
			||||||
		})
 | 
							})
 | 
				
			||||||
 | 
						}, func(ctx context.Context) error {
 | 
				
			||||||
 | 
							return r.resourceAuthCertApp.RelateAuthCert(ctx, &tagapp.RelateAuthCertParam{
 | 
				
			||||||
 | 
								ResourceCode: re.Code,
 | 
				
			||||||
 | 
								ResourceType: tagentity.TagTypeRedis,
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -176,10 +211,11 @@ func (r *redisAppImpl) GetRedisConn(id uint64, db int) (*rdm.RedisConn, error) {
 | 
				
			|||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			return nil, errorx.NewBiz("redis信息不存在")
 | 
								return nil, errorx.NewBiz("redis信息不存在")
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if err := re.PwdDecrypt(); err != nil {
 | 
							authCert, err := r.resourceAuthCertApp.GetResourceAuthCert(tagentity.TagTypeRedis, re.Code)
 | 
				
			||||||
			return nil, errorx.NewBiz(err.Error())
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return nil, err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return re.ToRedisInfo(db, r.tagApp.ListTagPathByTypeAndCode(consts.ResourceTypeRedis, re.Code)...), nil
 | 
							return re.ToRedisInfo(db, authCert, r.tagApp.ListTagPathByTypeAndCode(consts.ResourceTypeRedis, re.Code)...), nil
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,9 +1,8 @@
 | 
				
			|||||||
package entity
 | 
					package entity
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"errors"
 | 
					 | 
				
			||||||
	"mayfly-go/internal/common/utils"
 | 
					 | 
				
			||||||
	"mayfly-go/internal/redis/rdm"
 | 
						"mayfly-go/internal/redis/rdm"
 | 
				
			||||||
 | 
						tagentity "mayfly-go/internal/tag/domain/entity"
 | 
				
			||||||
	"mayfly-go/pkg/model"
 | 
						"mayfly-go/pkg/model"
 | 
				
			||||||
	"mayfly-go/pkg/utils/structx"
 | 
						"mayfly-go/pkg/utils/structx"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
@@ -15,38 +14,18 @@ type Redis struct {
 | 
				
			|||||||
	Name               string `orm:"column(name)" json:"name"`
 | 
						Name               string `orm:"column(name)" json:"name"`
 | 
				
			||||||
	Host               string `orm:"column(host)" json:"host"`
 | 
						Host               string `orm:"column(host)" json:"host"`
 | 
				
			||||||
	Mode               string `json:"mode"`
 | 
						Mode               string `json:"mode"`
 | 
				
			||||||
	Username           string `json:"username"`
 | 
					 | 
				
			||||||
	Password           string `orm:"column(password)" json:"-"`
 | 
					 | 
				
			||||||
	Db                 string `orm:"column(database)" json:"db"`
 | 
						Db                 string `orm:"column(database)" json:"db"`
 | 
				
			||||||
	SshTunnelMachineId int    `orm:"column(ssh_tunnel_machine_id)" json:"sshTunnelMachineId"` // ssh隧道机器id
 | 
						SshTunnelMachineId int    `orm:"column(ssh_tunnel_machine_id)" json:"sshTunnelMachineId"` // ssh隧道机器id
 | 
				
			||||||
	Remark             string
 | 
						Remark             string
 | 
				
			||||||
	FlowProcdefKey     *string `json:"flowProcdefKey"` // 审批流-流程定义key(有值则说明关键操作需要进行审批执行),使用指针为了方便更新空字符串(取消流程审批)
 | 
						FlowProcdefKey     *string `json:"flowProcdefKey"` // 审批流-流程定义key(有值则说明关键操作需要进行审批执行),使用指针为了方便更新空字符串(取消流程审批)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (r *Redis) PwdEncrypt() error {
 | 
					 | 
				
			||||||
	// 密码替换为加密后的密码
 | 
					 | 
				
			||||||
	password, err := utils.PwdAesEncrypt(r.Password)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return errors.New("加密 Redis 密码失败")
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	r.Password = password
 | 
					 | 
				
			||||||
	return nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (r *Redis) PwdDecrypt() error {
 | 
					 | 
				
			||||||
	// 密码替换为解密后的密码
 | 
					 | 
				
			||||||
	password, err := utils.PwdAesDecrypt(r.Password)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return errors.New("解密 Redis 密码失败")
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	r.Password = password
 | 
					 | 
				
			||||||
	return nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ToRedisInfo 转换为redisInfo进行连接
 | 
					// ToRedisInfo 转换为redisInfo进行连接
 | 
				
			||||||
func (r *Redis) ToRedisInfo(db int, tagPath ...string) *rdm.RedisInfo {
 | 
					func (r *Redis) ToRedisInfo(db int, authCert *tagentity.ResourceAuthCert, tagPath ...string) *rdm.RedisInfo {
 | 
				
			||||||
	redisInfo := new(rdm.RedisInfo)
 | 
						redisInfo := new(rdm.RedisInfo)
 | 
				
			||||||
	_ = structx.Copy(redisInfo, r)
 | 
						_ = structx.Copy(redisInfo, r)
 | 
				
			||||||
 | 
						redisInfo.Username = authCert.Username
 | 
				
			||||||
 | 
						redisInfo.Password = authCert.Ciphertext
 | 
				
			||||||
	redisInfo.Db = db
 | 
						redisInfo.Db = db
 | 
				
			||||||
	redisInfo.TagPath = tagPath
 | 
						redisInfo.TagPath = tagPath
 | 
				
			||||||
	return redisInfo
 | 
						return redisInfo
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -28,8 +28,6 @@ func InitRedisRouter(router *gin.RouterGroup) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		req.NewPost("", rs.Save).Log(req.NewLogSave("redis-保存信息")),
 | 
							req.NewPost("", rs.Save).Log(req.NewLogSave("redis-保存信息")),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		req.NewGet(":id/pwd", rs.GetRedisPwd),
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		req.NewDelete(":id", rs.DeleteRedis).Log(req.NewLogSave("redis-删除信息")),
 | 
							req.NewDelete(":id", rs.DeleteRedis).Log(req.NewLogSave("redis-删除信息")),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		req.NewGet("/:id/info", rs.RedisInfo),
 | 
							req.NewGet("/:id/info", rs.RedisInfo),
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -71,10 +71,10 @@ func (r *resourceAuthCertAppImpl) RelateAuthCert(ctx context.Context, params *Re
 | 
				
			|||||||
	resourceAuthCerts := params.AuthCerts
 | 
						resourceAuthCerts := params.AuthCerts
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if resourceCode == "" {
 | 
						if resourceCode == "" {
 | 
				
			||||||
		return errorx.NewBiz("资源授权凭证的资源编号不能为空")
 | 
							return errorx.NewBiz("授权凭证的资源编号不能为空")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if resourceType == 0 {
 | 
						if resourceType == 0 {
 | 
				
			||||||
		return errorx.NewBiz("资源类型不能为空")
 | 
							return errorx.NewBiz("授权凭证的资源类型不能为空")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// 删除授权信息
 | 
						// 删除授权信息
 | 
				
			||||||
@@ -413,6 +413,11 @@ func (r *resourceAuthCertAppImpl) updateAuthCert(ctx context.Context, rac *entit
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 密文存的不是公共授权凭证名,则进行密文加密处理
 | 
				
			||||||
 | 
						if rac.CiphertextType != entity.AuthCertCiphertextTypePublic {
 | 
				
			||||||
 | 
							rac.CiphertextEncrypt()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// 防止误更新
 | 
						// 防止误更新
 | 
				
			||||||
	rac.Name = ""
 | 
						rac.Name = ""
 | 
				
			||||||
	rac.ResourceCode = ""
 | 
						rac.ResourceCode = ""
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -532,8 +532,6 @@ CREATE TABLE `t_redis` (
 | 
				
			|||||||
  `code` varchar(32) COLLATE utf8mb4_bin DEFAULT NULL COMMENT 'code',
 | 
					  `code` varchar(32) COLLATE utf8mb4_bin DEFAULT NULL COMMENT 'code',
 | 
				
			||||||
  `name` varchar(255) DEFAULT NULL COMMENT '名称',
 | 
					  `name` varchar(255) DEFAULT NULL COMMENT '名称',
 | 
				
			||||||
  `host` varchar(255) NOT NULL,
 | 
					  `host` varchar(255) NOT NULL,
 | 
				
			||||||
  `username` varchar(32) DEFAULT NULL COMMENT '用户名',
 | 
					 | 
				
			||||||
  `password` varchar(100) DEFAULT NULL,
 | 
					 | 
				
			||||||
  `db` varchar(64)  DEFAULT NULL COMMENT '库号: 多个库用,分割',
 | 
					  `db` varchar(64)  DEFAULT NULL COMMENT '库号: 多个库用,分割',
 | 
				
			||||||
  `mode` varchar(32) DEFAULT NULL,
 | 
					  `mode` varchar(32) DEFAULT NULL,
 | 
				
			||||||
  `ssh_tunnel_machine_id` bigint(20) DEFAULT NULL COMMENT 'ssh隧道的机器id',
 | 
					  `ssh_tunnel_machine_id` bigint(20) DEFAULT NULL COMMENT 'ssh隧道的机器id',
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -221,3 +221,27 @@ INSERT INTO `t_sys_resource` (`id`, `pid`, `ui_path`, `type`, `status`, `name`,
 | 
				
			|||||||
INSERT INTO `t_sys_resource` (`id`, `pid`, `ui_path`, `type`, `status`, `name`, `code`, `weight`, `meta`, `creator_id`, `creator`, `modifier_id`, `modifier`, `create_time`, `update_time`, `is_deleted`, `delete_time`) VALUES(1712717337, 1712717290, 'tLb8TKLB/m2abQkA8/', 2, 1, '授权凭证密文查看', 'authcert:showciphertext', 1712717337, 'null', 1, 'admin', 1, 'admin', '2024-04-10 10:48:58', '2024-04-10 10:48:58', 0, NULL);
 | 
					INSERT INTO `t_sys_resource` (`id`, `pid`, `ui_path`, `type`, `status`, `name`, `code`, `weight`, `meta`, `creator_id`, `creator`, `modifier_id`, `modifier`, `create_time`, `update_time`, `is_deleted`, `delete_time`) VALUES(1712717337, 1712717290, 'tLb8TKLB/m2abQkA8/', 2, 1, '授权凭证密文查看', 'authcert:showciphertext', 1712717337, 'null', 1, 'admin', 1, 'admin', '2024-04-10 10:48:58', '2024-04-10 10:48:58', 0, NULL);
 | 
				
			||||||
commit;
 | 
					commit;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					begin;
 | 
				
			||||||
 | 
					-- 迁移redis账号密码
 | 
				
			||||||
 | 
					INSERT INTO t_resource_auth_cert ( NAME, resource_code, resource_type, type, ciphertext, ciphertext_type, create_time, creator_id, creator, update_time, modifier_id, modifier, is_deleted )
 | 
				
			||||||
 | 
					SELECT
 | 
				
			||||||
 | 
					    CONCAT('redis_', CODE, '_pwd' ),
 | 
				
			||||||
 | 
					    CODE,
 | 
				
			||||||
 | 
					    3,
 | 
				
			||||||
 | 
					    1,
 | 
				
			||||||
 | 
					    PASSWORD,
 | 
				
			||||||
 | 
					    1,
 | 
				
			||||||
 | 
					    DATE_FORMAT( NOW(), '%Y-%m-%d %H:%i:%s' ),
 | 
				
			||||||
 | 
					    1,
 | 
				
			||||||
 | 
					    'admin',
 | 
				
			||||||
 | 
					    DATE_FORMAT( NOW(), '%Y-%m-%d %H:%i:%s' ),
 | 
				
			||||||
 | 
					    1,
 | 
				
			||||||
 | 
					    'admin',
 | 
				
			||||||
 | 
					    0
 | 
				
			||||||
 | 
					FROM
 | 
				
			||||||
 | 
					    t_redis
 | 
				
			||||||
 | 
					WHERE
 | 
				
			||||||
 | 
					    is_deleted = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ALTER TABLE t_redis DROP COLUMN password;
 | 
				
			||||||
 | 
					commit;
 | 
				
			||||||
		Reference in New Issue
	
	Block a user