refactor: 新增base.Repo与base.App,重构repo与app层代码

This commit is contained in:
meilin.huang
2023-10-26 17:15:49 +08:00
parent 10f6b03fb5
commit a1303b52eb
115 changed files with 1867 additions and 1696 deletions

View File

@@ -12,6 +12,7 @@ import (
"mayfly-go/pkg/biz"
"mayfly-go/pkg/cache"
"mayfly-go/pkg/captcha"
"mayfly-go/pkg/errorx"
"mayfly-go/pkg/ginx"
"mayfly-go/pkg/otp"
"mayfly-go/pkg/req"
@@ -49,7 +50,7 @@ func (a *AccountLogin) Login(rc *req.Ctx) {
biz.ErrIsNilAppendErr(err, "解密密码错误: %s")
account := &sysentity.Account{Username: username}
err = a.AccountApp.GetAccount(account, "Id", "Name", "Username", "Password", "Status", "LastLoginTime", "LastLoginIp", "OtpSecret")
err = a.AccountApp.GetBy(account, "Id", "Name", "Username", "Password", "Status", "LastLoginTime", "LastLoginIp", "OtpSecret")
failCountKey := fmt.Sprintf("account:login:failcount:%s", username)
nowFailCount := cache.GetInt(failCountKey)
@@ -60,11 +61,11 @@ func (a *AccountLogin) Login(rc *req.Ctx) {
if err != nil || !cryptox.CheckPwdHash(originPwd, account.Password) {
nowFailCount++
cache.SetStr(failCountKey, strconv.Itoa(nowFailCount), time.Minute*time.Duration(loginFailMin))
panic(biz.NewBizErr(fmt.Sprintf("用户名或密码错误【当前登录失败%d次】", nowFailCount)))
panic(errorx.NewBiz(fmt.Sprintf("用户名或密码错误【当前登录失败%d次】", nowFailCount)))
}
// 校验密码强度(新用户第一次登录密码与账号名一致)
biz.IsTrueBy(utils.CheckAccountPasswordLever(originPwd), biz.NewBizErrCode(401, "您的密码安全等级较低,请修改后重新登录"))
biz.IsTrueBy(utils.CheckAccountPasswordLever(originPwd), errorx.NewBizCode(401, "您的密码安全等级较低,请修改后重新登录"))
rc.ResData = LastLoginCheck(account, accountLoginSecurity, clientIp)
}
@@ -98,7 +99,7 @@ func (a *AccountLogin) OtpVerify(rc *req.Ctx) {
if !otp.Validate(otpVerify.Code, otpSecret) {
cache.SetStr(failCountKey, strconv.Itoa(failCount+1), time.Minute*time.Duration(10))
panic(biz.NewBizErr("双因素认证授权码不正确"))
panic(errorx.NewBiz("双因素认证授权码不正确"))
}
// 如果是未注册状态则更新account表的otpSecret信息
@@ -106,7 +107,7 @@ func (a *AccountLogin) OtpVerify(rc *req.Ctx) {
update := &sysentity.Account{OtpSecret: otpSecret}
update.Id = accountId
update.OtpSecretEncrypt()
a.AccountApp.Update(update)
biz.ErrIsNil(a.AccountApp.Update(update))
}
la := &sysentity.Account{Username: otpInfo.Username}

View File

@@ -40,7 +40,9 @@ func LastLoginCheck(account *sysentity.Account, accountLoginSecurity *config.Acc
// 默认为不校验otp
otpStatus := OtpStatusNone
// 访问系统使用的token
accessToken := req.CreateToken(account.Id, username)
accessToken, err := req.CreateToken(account.Id, username)
biz.ErrIsNilAppendErr(err, "token创建失败: %s")
// 若系统配置中设置开启otp双因素校验则进行otp校验
if accountLoginSecurity.UseOtp {
otpInfo, otpurl, otpToken := useOtp(account, accountLoginSecurity.OtpIssuer, accessToken)
@@ -106,7 +108,7 @@ func saveLogin(account *sysentity.Account, ip string) {
updateAccount.Id = account.Id
updateAccount.LastLoginIp = ip
// 偷懒为了方便直接获取accountApp
sysapp.GetAccountApp().Update(updateAccount)
biz.ErrIsNil(sysapp.GetAccountApp().Update(updateAccount))
// 创建登录消息
loginMsg := &msgentity.Msg{

View File

@@ -11,6 +11,7 @@ import (
"mayfly-go/pkg/biz"
"mayfly-go/pkg/cache"
"mayfly-go/pkg/captcha"
"mayfly-go/pkg/errorx"
"mayfly-go/pkg/ginx"
"mayfly-go/pkg/req"
"mayfly-go/pkg/utils/collx"
@@ -69,7 +70,7 @@ func (a *LdapLogin) Login(rc *req.Ctx) {
if err != nil {
nowFailCount++
cache.SetStr(failCountKey, strconv.Itoa(nowFailCount), time.Minute*time.Duration(loginFailMin))
panic(biz.NewBizErr(fmt.Sprintf("用户名或密码错误【当前登录失败%d次】", nowFailCount)))
panic(errorx.NewBiz(fmt.Sprintf("用户名或密码错误【当前登录失败%d次】", nowFailCount)))
}
rc.ResData = LastLoginCheck(account, accountLoginSecurity, clientIp)
@@ -77,7 +78,7 @@ func (a *LdapLogin) Login(rc *req.Ctx) {
func (a *LdapLogin) getUser(userName string, cols ...string) (*sysentity.Account, error) {
account := &sysentity.Account{Username: userName}
if err := a.AccountApp.GetAccount(account, cols...); err != nil {
if err := a.AccountApp.GetBy(account, cols...); err != nil {
return nil, err
}
return account, nil
@@ -87,10 +88,10 @@ func (a *LdapLogin) createUser(userName, displayName string) {
account := &sysentity.Account{Username: userName}
account.SetBaseInfo(nil)
account.Name = displayName
a.AccountApp.Create(account)
biz.ErrIsNil(a.AccountApp.Create(account))
// 将 LADP 用户本地密码设置为空,不允许本地登录
account.Password = cryptox.PwdHash("")
a.AccountApp.Update(account)
biz.ErrIsNil(a.AccountApp.Update(account))
}
func (a *LdapLogin) getOrCreateUserWithLdap(userName string, password string, cols ...string) (*sysentity.Account, error) {

View File

@@ -12,6 +12,7 @@ import (
sysentity "mayfly-go/internal/sys/domain/entity"
"mayfly-go/pkg/biz"
"mayfly-go/pkg/cache"
"mayfly-go/pkg/errorx"
"mayfly-go/pkg/model"
"mayfly-go/pkg/req"
"mayfly-go/pkg/utils/collx"
@@ -97,7 +98,7 @@ func (a *Oauth2Login) OAuth2Callback(rc *req.Ctx) {
account := new(sysentity.Account)
account.Id = accountId
err = a.AccountApp.GetAccount(account, "username")
err = a.AccountApp.GetBy(account, "username")
biz.ErrIsNilAppendErr(err, "该账号不存在")
rc.ReqParam = collx.Kvs("username", account.Username, "type", "bind")
@@ -125,7 +126,7 @@ func (a *Oauth2Login) OAuth2Callback(rc *req.Ctx) {
}
rc.ResData = res
} else {
panic(biz.NewBizErr("state不合法"))
panic(errorx.NewBiz("state不合法"))
}
}
@@ -151,7 +152,7 @@ func (a *Oauth2Login) doLoginAction(rc *req.Ctx, userId string, oauth *config.Oa
Name: userId,
Username: userId,
}
a.AccountApp.Create(account)
biz.ErrIsNil(a.AccountApp.Create(account))
// 绑定
err := a.Oauth2App.BindOAuthAccount(&entity.Oauth2Account{
AccountId: account.Id,
@@ -170,7 +171,7 @@ func (a *Oauth2Login) doLoginAction(rc *req.Ctx, userId string, oauth *config.Oa
account := &sysentity.Account{
Model: model.Model{DeletedModel: model.DeletedModel{Id: accountId}},
}
err = a.AccountApp.GetAccount(account, "Id", "Name", "Username", "Password", "Status", "LastLoginTime", "LastLoginIp", "OtpSecret")
err = a.AccountApp.GetBy(account, "Id", "Name", "Username", "Password", "Status", "LastLoginTime", "LastLoginIp", "OtpSecret")
biz.ErrIsNilAppendErr(err, "获取用户信息失败: %s")
clientIp := getIpAndRegion(rc)

View File

@@ -3,9 +3,6 @@ package application
import (
"mayfly-go/internal/auth/domain/entity"
"mayfly-go/internal/auth/domain/repository"
"mayfly-go/pkg/biz"
"gorm.io/gorm"
)
type Oauth2 interface {
@@ -27,18 +24,16 @@ type oauth2AppImpl struct {
}
func (a *oauth2AppImpl) GetOAuthAccount(condition *entity.Oauth2Account, cols ...string) error {
err := a.oauthAccountRepo.GetOAuthAccount(condition, cols...)
if err != nil {
// 排除其他报错,如表不存在等
biz.IsTrue(err == gorm.ErrRecordNotFound, "查询失败: %s", err.Error())
}
return err
return a.oauthAccountRepo.GetBy(condition, cols...)
}
func (a *oauth2AppImpl) BindOAuthAccount(e *entity.Oauth2Account) error {
return a.oauthAccountRepo.SaveOAuthAccount(e)
if e.Id == 0 {
return a.oauthAccountRepo.Insert(e)
}
return a.oauthAccountRepo.UpdateById(e)
}
func (a *oauth2AppImpl) Unbind(accountId uint64) {
a.oauthAccountRepo.DeleteBy(&entity.Oauth2Account{AccountId: accountId})
a.oauthAccountRepo.DeleteByCond(&entity.Oauth2Account{AccountId: accountId})
}

View File

@@ -1,12 +1,10 @@
package repository
import "mayfly-go/internal/auth/domain/entity"
import (
"mayfly-go/internal/auth/domain/entity"
"mayfly-go/pkg/base"
)
type Oauth2Account interface {
// GetOAuthAccount 根据identity获取第三方账号信息
GetOAuthAccount(condition *entity.Oauth2Account, cols ...string) error
SaveOAuthAccount(e *entity.Oauth2Account) error
DeleteBy(e *entity.Oauth2Account)
base.Repo[*entity.Oauth2Account]
}

View File

@@ -3,26 +3,13 @@ package persistence
import (
"mayfly-go/internal/auth/domain/entity"
"mayfly-go/internal/auth/domain/repository"
"mayfly-go/pkg/gormx"
"mayfly-go/pkg/base"
)
type oauth2AccountRepoImpl struct{}
type oauth2AccountRepoImpl struct {
base.RepoImpl[*entity.Oauth2Account]
}
func newAuthAccountRepo() repository.Oauth2Account {
return new(oauth2AccountRepoImpl)
}
func (a *oauth2AccountRepoImpl) GetOAuthAccount(condition *entity.Oauth2Account, cols ...string) error {
return gormx.GetBy(condition, cols...)
}
func (a *oauth2AccountRepoImpl) SaveOAuthAccount(e *entity.Oauth2Account) error {
if e.Id == 0 {
return gormx.Insert(e)
}
return gormx.UpdateById(e)
}
func (a *oauth2AccountRepoImpl) DeleteBy(e *entity.Oauth2Account) {
gormx.DeleteByCondition(e)
return &oauth2AccountRepoImpl{base.RepoImpl[*entity.Oauth2Account]{M: new(entity.Oauth2Account)}}
}

View File

@@ -48,7 +48,9 @@ func (d *Db) Dbs(rc *req.Ctx) {
}
queryCond.TagIds = tagIds
rc.ResData = d.DbApp.GetPageList(queryCond, page, new([]vo.SelectDataDbVO))
res, err := d.DbApp.GetPageList(queryCond, page, new([]vo.SelectDataDbVO))
biz.ErrIsNil(err)
rc.ResData = res
}
func (d *Db) DbTags(rc *req.Ctx) {
@@ -62,7 +64,7 @@ func (d *Db) Save(rc *req.Ctx) {
rc.ReqParam = form
db.SetBaseInfo(rc.LoginAccount)
d.DbApp.Save(db)
biz.ErrIsNil(d.DbApp.Save(db))
}
func (d *Db) DeleteDb(rc *req.Ctx) {
@@ -81,23 +83,31 @@ func (d *Db) DeleteDb(rc *req.Ctx) {
}
func (d *Db) getDbConnection(g *gin.Context) *application.DbConnection {
return d.DbApp.GetDbConnection(getDbId(g), getDbName(g))
dc, err := d.DbApp.GetDbConnection(getDbId(g), getDbName(g))
biz.ErrIsNil(err)
return dc
}
func (d *Db) TableInfos(rc *req.Ctx) {
rc.ResData = d.getDbConnection(rc.GinCtx).GetMeta().GetTableInfos()
res, err := d.getDbConnection(rc.GinCtx).GetMeta().GetTableInfos()
biz.ErrIsNilAppendErr(err, "获取表信息失败: %s")
rc.ResData = res
}
func (d *Db) TableIndex(rc *req.Ctx) {
tn := rc.GinCtx.Query("tableName")
biz.NotEmpty(tn, "tableName不能为空")
rc.ResData = d.getDbConnection(rc.GinCtx).GetMeta().GetTableIndex(tn)
res, err := d.getDbConnection(rc.GinCtx).GetMeta().GetTableIndex(tn)
biz.ErrIsNilAppendErr(err, "获取表索引信息失败: %s")
rc.ResData = res
}
func (d *Db) GetCreateTableDdl(rc *req.Ctx) {
tn := rc.GinCtx.Query("tableName")
biz.NotEmpty(tn, "tableName不能为空")
rc.ResData = d.getDbConnection(rc.GinCtx).GetMeta().GetCreateTableDdl(tn)
res, err := d.getDbConnection(rc.GinCtx).GetMeta().GetCreateTableDdl(tn)
biz.ErrIsNilAppendErr(err, "获取表ddl失败: %s")
rc.ResData = res
}
func (d *Db) ExecSql(rc *req.Ctx) {
@@ -106,7 +116,8 @@ func (d *Db) ExecSql(rc *req.Ctx) {
ginx.BindJsonAndValid(g, form)
dbId := getDbId(g)
dbConn := d.DbApp.GetDbConnection(dbId, form.Db)
dbConn, err := d.DbApp.GetDbConnection(dbId, form.Db)
biz.ErrIsNil(err)
biz.ErrIsNilAppendErr(d.TagApp.CanAccess(rc.LoginAccount.Id, dbConn.Info.TagPath), "%s")
rc.ReqParam = fmt.Sprintf("%s\n-> %s", dbConn.Info.GetLogDesc(), form.Sql)
@@ -177,7 +188,8 @@ func (d *Db) ExecSqlFile(rc *req.Ctx) {
dbName := getDbName(g)
clientId := g.Query("clientId")
dbConn := d.DbApp.GetDbConnection(dbId, dbName)
dbConn, err := d.DbApp.GetDbConnection(dbId, dbName)
biz.ErrIsNil(err)
biz.ErrIsNilAppendErr(d.TagApp.CanAccess(rc.LoginAccount.Id, dbConn.Info.TagPath), "%s")
rc.ReqParam = fmt.Sprintf("filename: %s -> %s", filename, dbConn.Info.GetLogDesc())
@@ -244,7 +256,8 @@ func (d *Db) ExecSqlFile(rc *req.Ctx) {
if !ok {
logx.Warnf("sql解析失败: %s", sql)
}
dbConn = d.DbApp.GetDbConnection(dbId, stmtUse.DBName.String())
dbConn, err = d.DbApp.GetDbConnection(dbId, stmtUse.DBName.String())
biz.ErrIsNil(err)
biz.ErrIsNilAppendErr(d.TagApp.CanAccess(rc.LoginAccount.Id, dbConn.Info.TagPath), "%s")
execReq.DbConn = dbConn
}
@@ -282,7 +295,8 @@ func (d *Db) DumpSql(rc *req.Ctx) {
// 是否需要导出数据
needData := dumpType == "2" || dumpType == "3"
db := d.DbApp.GetById(dbId)
db, err := d.DbApp.GetById(new(entity.Db), dbId)
biz.ErrIsNil(err, "该数据库不存在")
biz.ErrIsNilAppendErr(d.TagApp.CanAccess(rc.LoginAccount.Id, db.TagPath), "%s")
now := time.Now()
@@ -320,7 +334,8 @@ func (d *Db) DumpSql(rc *req.Ctx) {
}
func (d *Db) dumpDb(writer *gzipWriter, dbId uint64, dbName string, tables []string, needStruct bool, needData bool) {
dbConn := d.DbApp.GetDbConnection(dbId, dbName)
dbConn, err := d.DbApp.GetDbConnection(dbId, dbName)
biz.ErrIsNil(err)
writer.WriteString("\n-- ----------------------------")
writer.WriteString("\n-- 导出平台: mayfly-go")
writer.WriteString(fmt.Sprintf("\n-- 导出时间: %s ", time.Now().Format("2006-01-02 15:04:05")))
@@ -332,7 +347,8 @@ func (d *Db) dumpDb(writer *gzipWriter, dbId uint64, dbName string, tables []str
dbMeta := dbConn.GetMeta()
if len(tables) == 0 {
ti := dbMeta.GetTableInfos()
ti, err := dbMeta.GetTableInfos()
biz.ErrIsNil(err)
tables = make([]string, len(ti))
for i, table := range ti {
tables[i] = table.TableName
@@ -345,7 +361,9 @@ func (d *Db) dumpDb(writer *gzipWriter, dbId uint64, dbName string, tables []str
if needStruct {
writer.WriteString(fmt.Sprintf("\n-- ----------------------------\n-- 表结构: %s \n-- ----------------------------\n", table))
writer.WriteString(fmt.Sprintf("DROP TABLE IF EXISTS %s;\n", quotedTable))
writer.WriteString(dbMeta.GetCreateTableDdl(table) + "\n")
ddl, err := dbMeta.GetCreateTableDdl(table)
biz.ErrIsNil(err)
writer.WriteString(ddl + "\n")
}
if !needData {
continue
@@ -380,7 +398,9 @@ func (d *Db) dumpDb(writer *gzipWriter, dbId uint64, dbName string, tables []str
// @router /api/db/:dbId/t-metadata [get]
func (d *Db) TableMA(rc *req.Ctx) {
dbi := d.getDbConnection(rc.GinCtx)
rc.ResData = dbi.GetMeta().GetTables()
res, err := dbi.GetMeta().GetTables()
biz.ErrIsNilAppendErr(err, "获取表基础信息失败: %s")
rc.ResData = res
}
// @router /api/db/:dbId/c-metadata [get]
@@ -390,7 +410,9 @@ func (d *Db) ColumnMA(rc *req.Ctx) {
biz.NotEmpty(tn, "tableName不能为空")
dbi := d.getDbConnection(rc.GinCtx)
rc.ResData = dbi.GetMeta().GetColumns(tn)
res, err := dbi.GetMeta().GetColumns(tn)
biz.ErrIsNilAppendErr(err, "获取数据库列信息失败: %s")
rc.ResData = res
}
// @router /api/db/:dbId/hint-tables [get]
@@ -399,7 +421,8 @@ func (d *Db) HintTables(rc *req.Ctx) {
dm := dbi.GetMeta()
// 获取所有表
tables := dm.GetTables()
tables, err := dm.GetTables()
biz.ErrIsNil(err)
tableNames := make([]string, 0)
for _, v := range tables {
tableNames = append(tableNames, v.TableName)
@@ -414,7 +437,8 @@ func (d *Db) HintTables(rc *req.Ctx) {
}
// 获取所有表下的所有列信息
columnMds := dm.GetColumns(tableNames...)
columnMds, err := dm.GetColumns(tableNames...)
biz.ErrIsNil(err)
for _, v := range columnMds {
tName := v.TableName
if res[tName] == nil {
@@ -481,8 +505,7 @@ func (d *Db) DeleteSql(rc *req.Ctx) {
dbSql.Name = rc.GinCtx.Query("name")
dbSql.Db = rc.GinCtx.Query("db")
gormx.DeleteByCondition(dbSql)
biz.ErrIsNil(gormx.DeleteBy(dbSql))
}
// @router /api/db/:dbId/sql [get]

View File

@@ -3,6 +3,7 @@ package api
import (
"mayfly-go/internal/db/application"
"mayfly-go/internal/db/domain/entity"
"mayfly-go/pkg/biz"
"mayfly-go/pkg/ginx"
"mayfly-go/pkg/req"
)
@@ -14,5 +15,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
rc.ResData = d.DbSqlExecApp.GetPageList(queryCond, page, new([]entity.DbSqlExec))
res, err := d.DbSqlExecApp.GetPageList(queryCond, page, new([]entity.DbSqlExec))
biz.ErrIsNil(err)
rc.ResData = res
}

View File

@@ -24,7 +24,9 @@ type Instance struct {
// @router /api/instances [get]
func (d *Instance) Instances(rc *req.Ctx) {
queryCond, page := ginx.BindQueryAndPage[*entity.InstanceQuery](rc.GinCtx, new(entity.InstanceQuery))
rc.ResData = d.InstanceApp.GetPageList(queryCond, page, new([]vo.SelectDataInstanceVO))
res, err := d.InstanceApp.GetPageList(queryCond, page, new([]vo.SelectDataInstanceVO))
biz.ErrIsNil(err)
rc.ResData = res
}
// SaveInstance 保存数据库实例信息
@@ -43,15 +45,15 @@ func (d *Instance) SaveInstance(rc *req.Ctx) {
rc.ReqParam = form
instance.SetBaseInfo(rc.LoginAccount)
d.InstanceApp.Save(instance)
biz.ErrIsNil(d.InstanceApp.Save(instance))
}
// GetInstance 获取数据库实例密码,由于数据库是加密存储,故提供该接口展示原文密码
// @router /api/instances/:instance [GET]
func (d *Instance) GetInstance(rc *req.Ctx) {
dbId := getInstanceId(rc.GinCtx)
dbEntity := d.InstanceApp.GetById(dbId)
biz.IsTrue(dbEntity != nil, "获取数据库实例错误")
dbEntity, err := d.InstanceApp.GetById(new(entity.Instance), dbId)
biz.ErrIsNil(err, "获取数据库实例错误")
dbEntity.Password = ""
rc.ResData = dbEntity
}
@@ -60,8 +62,8 @@ func (d *Instance) GetInstance(rc *req.Ctx) {
// @router /api/instances/:instance/pwd [GET]
func (d *Instance) GetInstancePwd(rc *req.Ctx) {
instanceId := getInstanceId(rc.GinCtx)
instanceEntity := d.InstanceApp.GetById(instanceId, "Password")
biz.IsTrue(instanceEntity != nil, "获取数据库实例错误")
instanceEntity, err := d.InstanceApp.GetById(new(entity.Instance), instanceId, "Password")
biz.ErrIsNil(err, "获取数据库实例错误")
instanceEntity.PwdDecrypt()
rc.ResData = instanceEntity.Password
}
@@ -78,8 +80,8 @@ func (d *Instance) DeleteInstance(rc *req.Ctx) {
biz.ErrIsNilAppendErr(err, "string类型转换为int异常: %s")
instanceId := uint64(value)
if d.DbApp.Count(&entity.DbQuery{InstanceId: instanceId}) != 0 {
instance := d.InstanceApp.GetById(instanceId, "name")
biz.NotNil(instance, "获取数据库实例错误数据库实例ID为%d", instance.Id)
instance, err := d.InstanceApp.GetById(new(entity.Instance), instanceId, "name")
biz.ErrIsNil(err, "获取数据库实例错误数据库实例ID为: %d", instance.Id)
biz.IsTrue(false, "不能删除数据库实例【%s】请先删除其关联的数据库资源。", instance.Name)
}
d.InstanceApp.Delete(instanceId)
@@ -89,10 +91,12 @@ func (d *Instance) DeleteInstance(rc *req.Ctx) {
// 获取数据库实例的所有数据库名
func (d *Instance) GetDatabaseNames(rc *req.Ctx) {
instanceId := getInstanceId(rc.GinCtx)
instance := d.InstanceApp.GetById(instanceId, "Password")
biz.IsTrue(instance != nil, "获取数据库实例错误")
instance, err := d.InstanceApp.GetById(new(entity.Instance), instanceId, "Password")
biz.ErrIsNil(err, "获取数据库实例错误")
instance.PwdDecrypt()
rc.ResData = d.InstanceApp.GetDatabases(instance)
res, err := d.InstanceApp.GetDatabases(instance)
biz.ErrIsNil(err)
rc.ResData = res
}
func getInstanceId(g *gin.Context) uint64 {

View File

@@ -7,8 +7,9 @@ import (
"mayfly-go/internal/db/domain/entity"
"mayfly-go/internal/db/domain/repository"
"mayfly-go/internal/machine/infrastructure/machine"
"mayfly-go/pkg/biz"
"mayfly-go/pkg/base"
"mayfly-go/pkg/cache"
"mayfly-go/pkg/errorx"
"mayfly-go/pkg/logx"
"mayfly-go/pkg/model"
"mayfly-go/pkg/utils/collx"
@@ -20,79 +21,71 @@ import (
)
type Db interface {
base.App[*entity.Db]
// 分页获取
GetPageList(condition *entity.DbQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any]
GetPageList(condition *entity.DbQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error)
Count(condition *entity.DbQuery) int64
// 根据条件获取
GetDbBy(condition *entity.Db, cols ...string) error
// 根据id获取
GetById(id uint64, cols ...string) *entity.Db
Save(entity *entity.Db)
Save(entity *entity.Db) error
// 删除数据库信息
Delete(id uint64)
Delete(id uint64) error
// 获取数据库连接实例
// @param id 数据库实例id
// @param db 数据库
GetDbConnection(dbId uint64, dbName string) *DbConnection
GetDbConnection(dbId uint64, dbName string) (*DbConnection, error)
}
func newDbApp(dbRepo repository.Db, dbSqlRepo repository.DbSql, dbInstanceApp Instance) Db {
return &dbAppImpl{
dbRepo: dbRepo,
app := &dbAppImpl{
dbSqlRepo: dbSqlRepo,
dbInstanceApp: dbInstanceApp,
}
app.Repo = dbRepo
return app
}
type dbAppImpl struct {
dbRepo repository.Db
base.AppImpl[*entity.Db, repository.Db]
dbSqlRepo repository.DbSql
dbInstanceApp Instance
}
// 分页获取数据库信息列表
func (d *dbAppImpl) GetPageList(condition *entity.DbQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any] {
return d.dbRepo.GetDbList(condition, pageParam, toEntity, orderBy...)
func (d *dbAppImpl) GetPageList(condition *entity.DbQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error) {
return d.GetRepo().GetDbList(condition, pageParam, toEntity, orderBy...)
}
func (d *dbAppImpl) Count(condition *entity.DbQuery) int64 {
return d.dbRepo.Count(condition)
return d.GetRepo().Count(condition)
}
// 根据条件获取
func (d *dbAppImpl) GetDbBy(condition *entity.Db, cols ...string) error {
return d.dbRepo.GetDb(condition, cols...)
}
// 根据id获取
func (d *dbAppImpl) GetById(id uint64, cols ...string) *entity.Db {
return d.dbRepo.GetById(id, cols...)
}
func (d *dbAppImpl) Save(dbEntity *entity.Db) {
func (d *dbAppImpl) Save(dbEntity *entity.Db) error {
// 查找是否存在
oldDb := &entity.Db{Name: dbEntity.Name, InstanceId: dbEntity.InstanceId}
err := d.GetDbBy(oldDb)
err := d.GetBy(oldDb)
if dbEntity.Id == 0 {
biz.IsTrue(err != nil, "该实例下数据库名已存在")
d.dbRepo.Insert(dbEntity)
return
if err == nil {
return errorx.NewBiz("该实例下数据库名已存在")
}
return d.Insert(dbEntity)
}
// 如果存在该库,则校验修改的库是否为该库
if err == nil {
biz.IsTrue(oldDb.Id == dbEntity.Id, "该实例下数据库名已存在")
if err == nil && oldDb.Id != dbEntity.Id {
return errorx.NewBiz("该实例下数据库名已存在")
}
dbId := dbEntity.Id
old := d.GetById(dbId)
old, err := d.GetById(new(entity.Db), dbId)
if err != nil {
return errorx.NewBiz("该数据库不存在")
}
oldDbs := strings.Split(old.Database, " ")
newDbs := strings.Split(dbEntity.Database, " ")
@@ -105,27 +98,30 @@ func (d *dbAppImpl) Save(dbEntity *entity.Db) {
// 关闭数据库连接
CloseDb(dbEntity.Id, v)
// 删除该库关联的所有sql记录
d.dbSqlRepo.DeleteBy(&entity.DbSql{DbId: dbId, Db: v})
d.dbSqlRepo.DeleteByCond(&entity.DbSql{DbId: dbId, Db: v})
}
d.dbRepo.Update(dbEntity)
return d.UpdateById(dbEntity)
}
func (d *dbAppImpl) Delete(id uint64) {
db := d.GetById(id)
func (d *dbAppImpl) Delete(id uint64) error {
db, err := d.GetById(new(entity.Db), id)
if err != nil {
return errorx.NewBiz("该数据库不存在")
}
dbs := strings.Split(db.Database, " ")
for _, v := range dbs {
// 关闭连接
CloseDb(id, v)
}
d.dbRepo.Delete(id)
// 删除该库下用户保存的所有sql信息
d.dbSqlRepo.DeleteBy(&entity.DbSql{DbId: id})
d.dbSqlRepo.DeleteByCond(&entity.DbSql{DbId: id})
return d.DeleteById(id)
}
var mutex sync.Mutex
func (d *dbAppImpl) GetDbConnection(dbId uint64, dbName string) *DbConnection {
func (d *dbAppImpl) GetDbConnection(dbId uint64, dbName string) (*DbConnection, error) {
cacheKey := GetDbCacheKey(dbId, dbName)
// Id不为0则为需要缓存
@@ -133,18 +129,24 @@ func (d *dbAppImpl) GetDbConnection(dbId uint64, dbName string) *DbConnection {
if needCache {
load, ok := dbCache.Get(cacheKey)
if ok {
return load.(*DbConnection)
return load.(*DbConnection), nil
}
}
mutex.Lock()
defer mutex.Unlock()
db := d.GetById(dbId)
biz.NotNil(db, "数据库信息不存在")
biz.IsTrue(strings.Contains(" "+db.Database+" ", " "+dbName+" "), "未配置数据库【%s】的操作权限", dbName)
db, err := d.GetById(new(entity.Db), dbId)
if err != nil {
return nil, errorx.NewBiz("数据库信息不存在")
}
if !strings.Contains(" "+db.Database+" ", " "+dbName+" ") {
return nil, errorx.NewBiz("未配置数据库【%s】的操作权限", dbName)
}
instance := d.dbInstanceApp.GetById(db.InstanceId)
biz.NotNil(instance, "数据库实例不存在")
instance, err := d.dbInstanceApp.GetById(new(entity.Instance), db.InstanceId)
if err != nil {
return nil, errorx.NewBiz("数据库实例不存在")
}
// 密码解密
instance.PwdDecrypt()
@@ -156,7 +158,7 @@ func (d *dbAppImpl) GetDbConnection(dbId uint64, dbName string) *DbConnection {
if err != nil {
dbi.Close()
logx.Errorf("连接db失败: %s:%d/%s", dbInfo.Host, dbInfo.Port, dbName)
panic(biz.NewBizErr(fmt.Sprintf("数据库连接失败: %s", err.Error())))
return nil, errorx.NewBiz(fmt.Sprintf("数据库连接失败: %s", err.Error()))
}
// 最大连接周期超过时间的连接就close
@@ -171,7 +173,7 @@ func (d *dbAppImpl) GetDbConnection(dbId uint64, dbName string) *DbConnection {
if needCache {
dbCache.Put(cacheKey, dbi)
}
return dbi
return dbi, nil
}
//---------------------------------------- db instance ------------------------------------

View File

@@ -6,7 +6,7 @@ import (
"mayfly-go/internal/db/config"
"mayfly-go/internal/db/domain/entity"
"mayfly-go/internal/db/domain/repository"
"mayfly-go/pkg/biz"
"mayfly-go/pkg/errorx"
"mayfly-go/pkg/model"
"strconv"
"strings"
@@ -51,7 +51,7 @@ type DbSqlExec interface {
DeleteBy(condition *entity.DbSqlExec)
// 分页获取
GetPageList(condition *entity.DbSqlExecQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any]
GetPageList(condition *entity.DbSqlExecQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error)
}
func newDbSqlExecApp(dbExecSqlRepo repository.DbSqlExec) DbSqlExec {
@@ -91,7 +91,9 @@ func (d *dbSqlExecAppImpl) Exec(execSqlReq *DbSqlExecReq) (*DbSqlExecRes, error)
// 如果配置为0则不校验分页参数
maxCount := config.GetDbQueryMaxCount()
if maxCount != 0 {
biz.IsTrue(strings.Contains(lowerSql, "limit"), "请完善分页信息后执行")
if !strings.Contains(lowerSql, "limit") {
return nil, errorx.NewBiz("请完善分页信息后执行")
}
}
}
var execErr error
@@ -148,10 +150,10 @@ func (d *dbSqlExecAppImpl) saveSqlExecLog(isQuery bool, dbSqlExecRecord *entity.
}
func (d *dbSqlExecAppImpl) DeleteBy(condition *entity.DbSqlExec) {
d.dbSqlExecRepo.DeleteBy(condition)
d.dbSqlExecRepo.DeleteByCond(condition)
}
func (d *dbSqlExecAppImpl) GetPageList(condition *entity.DbSqlExecQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any] {
func (d *dbSqlExecAppImpl) GetPageList(condition *entity.DbSqlExecQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error) {
return d.dbSqlExecRepo.GetPageList(condition, pageParam, toEntity, orderBy...)
}
@@ -163,10 +165,18 @@ func doSelect(selectStmt *sqlparser.Select, execSqlReq *DbSqlExecReq) (*DbSqlExe
maxCount := config.GetDbQueryMaxCount()
if maxCount != 0 {
limit := selectStmt.Limit
biz.NotNil(limit, "请完善分页信息后执行")
if limit == nil {
return nil, errorx.NewBiz("请完善分页信息后执行")
}
count, err := strconv.Atoi(sqlparser.String(limit.Rowcount))
biz.ErrIsNil(err, "分页参数有误")
biz.IsTrue(count <= maxCount, "查询结果集数需小于系统配置的%d条", maxCount)
if err != nil {
return nil, errorx.NewBiz("分页参数有误")
}
if count > maxCount {
return nil, errorx.NewBiz("查询结果集数需小于系统配置的%d条", maxCount)
}
}
}
@@ -193,7 +203,9 @@ func doUpdate(update *sqlparser.Update, execSqlReq *DbSqlExecReq, dbSqlExec *ent
// 可能使用别名,故空格切割
tableName := strings.Split(tableStr, " ")[0]
where := sqlparser.String(update.Where)
biz.IsTrue(len(where) > 0, "SQL[%s]未执行. 请完善 where 条件后再执行", execSqlReq.Sql)
if len(where) == 0 {
return nil, errorx.NewBiz("SQL[%s]未执行. 请完善 where 条件后再执行", execSqlReq.Sql)
}
updateExprs := update.Exprs
updateColumns := make([]string, 0)
@@ -202,7 +214,10 @@ func doUpdate(update *sqlparser.Update, execSqlReq *DbSqlExecReq, dbSqlExec *ent
}
// 获取表主键列名,排除使用别名
primaryKey := dbConn.GetMeta().GetPrimaryKey(tableName)
primaryKey, err := dbConn.GetMeta().GetPrimaryKey(tableName)
if err != nil {
return nil, errorx.NewBiz("获取表主键信息失败")
}
updateColumnsAndPrimaryKey := strings.Join(updateColumns, ",") + "," + primaryKey
// 查询要更新字段数据的旧值,以及主键值
@@ -228,7 +243,9 @@ func doDelete(delete *sqlparser.Delete, execSqlReq *DbSqlExecReq, dbSqlExec *ent
// 可能使用别名,故空格切割
table := strings.Split(tableStr, " ")[0]
where := sqlparser.String(delete.Where)
biz.IsTrue(len(where) > 0, "SQL[%s]未执行. 请完善 where 条件后再执行", execSqlReq.Sql)
if len(where) == 0 {
return nil, errorx.NewBiz("SQL[%s]未执行. 请完善 where 条件后再执行", execSqlReq.Sql)
}
// 查询删除数据
selectSql := fmt.Sprintf("SELECT * FROM %s %s LIMIT 200", tableStr, where)

View File

@@ -5,67 +5,56 @@ import (
"fmt"
"mayfly-go/internal/db/domain/entity"
"mayfly-go/internal/db/domain/repository"
"mayfly-go/pkg/biz"
"mayfly-go/pkg/base"
"mayfly-go/pkg/errorx"
"mayfly-go/pkg/model"
)
type Instance interface {
base.App[*entity.Instance]
// GetPageList 分页获取数据库实例
GetPageList(condition *entity.InstanceQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any]
GetPageList(condition *entity.InstanceQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error)
Count(condition *entity.InstanceQuery) int64
// GetInstanceBy 根据条件获取数据库实例
GetInstanceBy(condition *entity.Instance, cols ...string) error
// GetById 根据id获取数据库实例
GetById(id uint64, cols ...string) *entity.Instance
Save(instanceEntity *entity.Instance)
Save(instanceEntity *entity.Instance) error
// Delete 删除数据库信息
Delete(id uint64)
Delete(id uint64) error
// GetDatabases 获取数据库实例的所有数据库列表
GetDatabases(entity *entity.Instance) []string
GetDatabases(entity *entity.Instance) ([]string, error)
}
func newInstanceApp(InstanceRepo repository.Instance) Instance {
return &instanceAppImpl{
instanceRepo: InstanceRepo,
}
func newInstanceApp(instanceRepo repository.Instance) Instance {
app := new(instanceAppImpl)
app.Repo = instanceRepo
return app
}
type instanceAppImpl struct {
instanceRepo repository.Instance
base.AppImpl[*entity.Instance, repository.Instance]
}
// GetPageList 分页获取数据库实例
func (app *instanceAppImpl) GetPageList(condition *entity.InstanceQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any] {
return app.instanceRepo.GetInstanceList(condition, pageParam, toEntity, orderBy...)
func (app *instanceAppImpl) GetPageList(condition *entity.InstanceQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error) {
return app.GetRepo().GetInstanceList(condition, pageParam, toEntity, orderBy...)
}
func (app *instanceAppImpl) Count(condition *entity.InstanceQuery) int64 {
return app.instanceRepo.Count(condition)
return app.CountByCond(condition)
}
// GetInstanceBy 根据条件获取数据库实例
func (app *instanceAppImpl) GetInstanceBy(condition *entity.Instance, cols ...string) error {
return app.instanceRepo.GetInstance(condition, cols...)
}
// GetById 根据id获取数据库实例
func (app *instanceAppImpl) GetById(id uint64, cols ...string) *entity.Instance {
return app.instanceRepo.GetById(id, cols...)
}
func (app *instanceAppImpl) Save(instanceEntity *entity.Instance) {
func (app *instanceAppImpl) Save(instanceEntity *entity.Instance) error {
// 默认tcp连接
instanceEntity.Network = instanceEntity.GetNetwork()
// 测试连接
if instanceEntity.Password != "" {
testConnection(instanceEntity)
if err := testConnection(instanceEntity); err != nil {
return errorx.NewBiz("数据库连接失败: %s", err.Error())
}
}
// 查找是否存在该库
@@ -74,24 +63,28 @@ func (app *instanceAppImpl) Save(instanceEntity *entity.Instance) {
oldInstance.SshTunnelMachineId = instanceEntity.SshTunnelMachineId
}
err := app.GetInstanceBy(oldInstance)
err := app.GetBy(oldInstance)
if instanceEntity.Id == 0 {
biz.NotEmpty(instanceEntity.Password, "密码不能为空")
biz.IsTrue(err != nil, "该数据库实例已存在")
instanceEntity.PwdEncrypt()
app.instanceRepo.Insert(instanceEntity)
} else {
// 如果存在该库,则校验修改的库是否为该库
if instanceEntity.Password == "" {
return errorx.NewBiz("密码不能为空")
}
if err == nil {
biz.IsTrue(oldInstance.Id == instanceEntity.Id, "该数据库实例已存在")
return errorx.NewBiz("该数据库实例已存在")
}
instanceEntity.PwdEncrypt()
app.instanceRepo.Update(instanceEntity)
return app.Insert(instanceEntity)
}
// 如果存在该库,则校验修改的库是否为该库
if err == nil && oldInstance.Id != instanceEntity.Id {
return errorx.NewBiz("该数据库实例已存在")
}
instanceEntity.PwdEncrypt()
return app.UpdateById(instanceEntity)
}
func (app *instanceAppImpl) Delete(id uint64) {
app.instanceRepo.Delete(id)
func (app *instanceAppImpl) Delete(id uint64) error {
return app.DeleteById(id)
}
// getInstanceConn 获取数据库连接数据库实例
@@ -119,14 +112,17 @@ func getInstanceConn(instance *entity.Instance, db string) (*sql.DB, error) {
return conn, nil
}
func testConnection(d *entity.Instance) {
func testConnection(d *entity.Instance) error {
// 不指定数据库名称
conn, err := getInstanceConn(d, "")
biz.ErrIsNilAppendErr(err, "数据库连接失败: %s")
if err != nil {
return err
}
defer conn.Close()
return nil
}
func (app *instanceAppImpl) GetDatabases(ed *entity.Instance) []string {
func (app *instanceAppImpl) GetDatabases(ed *entity.Instance) ([]string, error) {
ed.Network = ed.GetNetwork()
databases := make([]string, 0)
var dbConn *sql.DB
@@ -134,14 +130,18 @@ func (app *instanceAppImpl) GetDatabases(ed *entity.Instance) []string {
getDatabasesSql := ed.Type.StmtSelectDbName()
dbConn, err := getInstanceConn(ed, metaDb)
biz.ErrIsNilAppendErr(err, "数据库连接失败: %s")
if err != nil {
return nil, errorx.NewBiz("数据库连接失败: %s", err.Error())
}
defer dbConn.Close()
_, res, err := selectDataByDb(dbConn, getDatabasesSql)
biz.ErrIsNilAppendErr(err, "获取数据库列表失败")
if err != nil {
return nil, err
}
for _, re := range res {
databases = append(databases, re["dbname"].(string))
}
return databases
return databases, nil
}

View File

@@ -44,22 +44,22 @@ type Index struct {
type DbMetadata interface {
// 获取表基础元信息
GetTables() []Table
GetTables() ([]Table, error)
// 获取指定表名的所有列元信息
GetColumns(tableNames ...string) []Column
GetColumns(tableNames ...string) ([]Column, error)
// 获取表主键字段名,没有主键标识则默认第一个字段
GetPrimaryKey(tablename string) string
GetPrimaryKey(tablename string) (string, error)
// 获取表信息比GetTables获取更详细的表信息
GetTableInfos() []Table
GetTableInfos() ([]Table, error)
// 获取表索引信息
GetTableIndex(tableName string) []Index
GetTableIndex(tableName string) ([]Index, error)
// 获取建表ddl
GetCreateTableDdl(tableName string) string
GetCreateTableDdl(tableName string) (string, error)
// 获取指定表的数据-分页查询
// @return columns: 列字段名result: 结果集error: 错误

View File

@@ -6,7 +6,7 @@ import (
"fmt"
"mayfly-go/internal/db/domain/entity"
machineapp "mayfly-go/internal/machine/application"
"mayfly-go/pkg/biz"
"mayfly-go/pkg/errorx"
"mayfly-go/pkg/utils/anyx"
"net"
@@ -16,7 +16,10 @@ import (
func getMysqlDB(d *entity.Instance, db string) (*sql.DB, error) {
// SSH Conect
if d.SshTunnelMachineId > 0 {
sshTunnelMachine := machineapp.GetMachineApp().GetSshTunnelMachine(d.SshTunnelMachineId)
sshTunnelMachine, err := machineapp.GetMachineApp().GetSshTunnelMachine(d.SshTunnelMachineId)
if err != nil {
return nil, err
}
mysql.RegisterDialContext(d.Network, func(ctx context.Context, addr string) (net.Conn, error) {
return sshTunnelMachine.GetDialConn("tcp", addr)
})
@@ -43,9 +46,11 @@ type MysqlMetadata struct {
}
// 获取表基础元信息, 如表名等
func (mm *MysqlMetadata) GetTables() []Table {
func (mm *MysqlMetadata) GetTables() ([]Table, error) {
_, res, err := mm.di.SelectData(GetLocalSql(MYSQL_META_FILE, MYSQL_TABLE_MA_KEY))
biz.ErrIsNilAppendErr(err, "获取表基本信息失败: %s")
if err != nil {
return nil, err
}
tables := make([]Table, 0)
for _, re := range res {
@@ -54,11 +59,11 @@ func (mm *MysqlMetadata) GetTables() []Table {
TableComment: anyx.ConvString(re["tableComment"]),
})
}
return tables
return tables, nil
}
// 获取列元信息, 如列名等
func (mm *MysqlMetadata) GetColumns(tableNames ...string) []Column {
func (mm *MysqlMetadata) GetColumns(tableNames ...string) ([]Column, error) {
tableName := ""
for i := 0; i < len(tableNames); i++ {
if i != 0 {
@@ -68,7 +73,10 @@ func (mm *MysqlMetadata) GetColumns(tableNames ...string) []Column {
}
_, res, err := mm.di.SelectData(fmt.Sprintf(GetLocalSql(MYSQL_META_FILE, MYSQL_COLUMN_MA_KEY), tableName))
biz.ErrIsNilAppendErr(err, "获取数据库列信息失败: %s")
if err != nil {
return nil, err
}
columns := make([]Column, 0)
for _, re := range res {
columns = append(columns, Column{
@@ -81,26 +89,34 @@ func (mm *MysqlMetadata) GetColumns(tableNames ...string) []Column {
ColumnDefault: anyx.ConvString(re["columnDefault"]),
})
}
return columns
return columns, nil
}
// 获取表主键字段名,不存在主键标识则默认第一个字段
func (mm *MysqlMetadata) GetPrimaryKey(tablename string) string {
columns := mm.GetColumns(tablename)
biz.IsTrue(len(columns) > 0, "[%s] 表不存在", tablename)
func (mm *MysqlMetadata) GetPrimaryKey(tablename string) (string, error) {
columns, err := mm.GetColumns(tablename)
if err != nil {
return "", err
}
if len(columns) == 0 {
return "", errorx.NewBiz("[%s] 表不存在", tablename)
}
for _, v := range columns {
if v.ColumnKey == "PRI" {
return v.ColumnName
return v.ColumnName, nil
}
}
return columns[0].ColumnName
return columns[0].ColumnName, nil
}
// 获取表信息比GetTableMetedatas获取更详细的表信息
func (mm *MysqlMetadata) GetTableInfos() []Table {
func (mm *MysqlMetadata) GetTableInfos() ([]Table, error) {
_, res, err := mm.di.SelectData(GetLocalSql(MYSQL_META_FILE, MYSQL_TABLE_INFO_KEY))
biz.ErrIsNilAppendErr(err, "获取表信息失败: %s")
if err != nil {
return nil, err
}
tables := make([]Table, 0)
for _, re := range res {
@@ -113,13 +129,16 @@ func (mm *MysqlMetadata) GetTableInfos() []Table {
IndexLength: anyx.ConvInt64(re["indexLength"]),
})
}
return tables
return tables, nil
}
// 获取表索引信息
func (mm *MysqlMetadata) GetTableIndex(tableName string) []Index {
func (mm *MysqlMetadata) GetTableIndex(tableName string) ([]Index, error) {
_, res, err := mm.di.SelectData(fmt.Sprintf(GetLocalSql(MYSQL_META_FILE, MYSQL_INDEX_INFO_KEY), tableName))
biz.ErrIsNilAppendErr(err, "获取表索引信息失败: %s")
if err != nil {
return nil, err
}
indexs := make([]Index, 0)
for _, re := range res {
indexs = append(indexs, Index{
@@ -147,14 +166,16 @@ func (mm *MysqlMetadata) GetTableIndex(tableName string) []Index {
result = append(result, v)
}
}
return result
return result, nil
}
// 获取建表ddl
func (mm *MysqlMetadata) GetCreateTableDdl(tableName string) string {
func (mm *MysqlMetadata) GetCreateTableDdl(tableName string) (string, error) {
_, res, err := mm.di.SelectData(fmt.Sprintf("show create table `%s` ", tableName))
biz.ErrIsNilAppendErr(err, "获取表结构失败: %s")
return res[0]["Create Table"].(string) + ";"
if err != nil {
return "", err
}
return res[0]["Create Table"].(string) + ";", nil
}
func (mm *MysqlMetadata) GetTableRecord(tableName string, pageNum, pageSize int) ([]string, []map[string]any, error) {

View File

@@ -6,7 +6,7 @@ import (
"fmt"
"mayfly-go/internal/db/domain/entity"
machineapp "mayfly-go/internal/machine/application"
"mayfly-go/pkg/biz"
"mayfly-go/pkg/errorx"
"mayfly-go/pkg/utils/anyx"
"mayfly-go/pkg/utils/collx"
"net"
@@ -49,7 +49,11 @@ func (d *PqSqlDialer) Open(name string) (driver.Conn, error) {
}
func (pd *PqSqlDialer) Dial(network, address string) (net.Conn, error) {
if sshConn, err := machineapp.GetMachineApp().GetSshTunnelMachine(pd.sshTunnelMachineId).GetDialConn("tcp", address); err == nil {
sshTunnel, err := machineapp.GetMachineApp().GetSshTunnelMachine(pd.sshTunnelMachineId)
if err != nil {
return nil, err
}
if sshConn, err := sshTunnel.GetDialConn("tcp", address); err == nil {
return sshConn, nil
} else {
return nil, err
@@ -75,9 +79,11 @@ type PgsqlMetadata struct {
}
// 获取表基础元信息, 如表名等
func (pm *PgsqlMetadata) GetTables() []Table {
func (pm *PgsqlMetadata) GetTables() ([]Table, error) {
_, res, err := pm.di.SelectData(GetLocalSql(PGSQL_META_FILE, PGSQL_TABLE_MA_KEY))
biz.ErrIsNilAppendErr(err, "获取表基本信息失败: %s")
if err != nil {
return nil, err
}
tables := make([]Table, 0)
for _, re := range res {
@@ -86,11 +92,11 @@ func (pm *PgsqlMetadata) GetTables() []Table {
TableComment: anyx.ConvString(re["tableComment"]),
})
}
return tables
return tables, nil
}
// 获取列元信息, 如列名等
func (pm *PgsqlMetadata) GetColumns(tableNames ...string) []Column {
func (pm *PgsqlMetadata) GetColumns(tableNames ...string) ([]Column, error) {
tableName := ""
for i := 0; i < len(tableNames); i++ {
if i != 0 {
@@ -100,7 +106,10 @@ func (pm *PgsqlMetadata) GetColumns(tableNames ...string) []Column {
}
_, res, err := pm.di.SelectData(fmt.Sprintf(GetLocalSql(PGSQL_META_FILE, PGSQL_COLUMN_MA_KEY), tableName))
biz.ErrIsNilAppendErr(err, "获取数据库列信息失败: %s")
if err != nil {
return nil, err
}
columns := make([]Column, 0)
for _, re := range res {
columns = append(columns, Column{
@@ -113,25 +122,32 @@ func (pm *PgsqlMetadata) GetColumns(tableNames ...string) []Column {
ColumnDefault: anyx.ConvString(re["columnDefault"]),
})
}
return columns
return columns, nil
}
func (pm *PgsqlMetadata) GetPrimaryKey(tablename string) string {
columns := pm.GetColumns(tablename)
biz.IsTrue(len(columns) > 0, "[%s] 表不存在", tablename)
func (pm *PgsqlMetadata) GetPrimaryKey(tablename string) (string, error) {
columns, err := pm.GetColumns(tablename)
if err != nil {
return "", err
}
if len(columns) == 0 {
return "", errorx.NewBiz("[%s] 表不存在", tablename)
}
for _, v := range columns {
if v.ColumnKey == "PRI" {
return v.ColumnName
return v.ColumnName, nil
}
}
return columns[0].ColumnName
return columns[0].ColumnName, nil
}
// 获取表信息比GetTables获取更详细的表信息
func (pm *PgsqlMetadata) GetTableInfos() []Table {
func (pm *PgsqlMetadata) GetTableInfos() ([]Table, error) {
_, res, err := pm.di.SelectData(GetLocalSql(PGSQL_META_FILE, PGSQL_TABLE_INFO_KEY))
biz.ErrIsNilAppendErr(err, "获取表信息失败: %s")
if err != nil {
return nil, err
}
tables := make([]Table, 0)
for _, re := range res {
@@ -144,13 +160,16 @@ func (pm *PgsqlMetadata) GetTableInfos() []Table {
IndexLength: anyx.ConvInt64(re["indexLength"]),
})
}
return tables
return tables, nil
}
// 获取表索引信息
func (pm *PgsqlMetadata) GetTableIndex(tableName string) []Index {
func (pm *PgsqlMetadata) GetTableIndex(tableName string) ([]Index, error) {
_, res, err := pm.di.SelectData(fmt.Sprintf(GetLocalSql(PGSQL_META_FILE, PGSQL_INDEX_INFO_KEY), tableName))
biz.ErrIsNilAppendErr(err, "获取表索引信息失败: %s")
if err != nil {
return nil, err
}
indexs := make([]Index, 0)
for _, re := range res {
indexs = append(indexs, Index{
@@ -162,22 +181,26 @@ func (pm *PgsqlMetadata) GetTableIndex(tableName string) []Index {
SeqInIndex: anyx.ConvInt(re["seqInIndex"]),
})
}
return indexs
return indexs, nil
}
// 获取建表ddl
func (pm *PgsqlMetadata) GetCreateTableDdl(tableName string) string {
func (pm *PgsqlMetadata) GetCreateTableDdl(tableName string) (string, error) {
_, err := pm.di.Exec(GetLocalSql(PGSQL_META_FILE, PGSQL_TABLE_DDL_KEY))
biz.ErrIsNilAppendErr(err, "创建ddl函数失败: %s")
if err != nil {
return "", err
}
_, schemaRes, _ := pm.di.SelectData("select current_schema() as schema")
schemaName := schemaRes[0]["schema"].(string)
ddlSql := fmt.Sprintf("select showcreatetable('%s','%s') as sql", schemaName, tableName)
_, res, err := pm.di.SelectData(ddlSql)
if err != nil {
return "", err
}
biz.ErrIsNilAppendErr(err, "获取表ddl失败: %s")
return res[0]["sql"].(string)
return res[0]["sql"].(string), nil
}
func (pm *PgsqlMetadata) GetTableRecord(tableName string, pageNum, pageSize int) ([]string, []map[string]any, error) {

View File

@@ -2,24 +2,15 @@ package repository
import (
"mayfly-go/internal/db/domain/entity"
"mayfly-go/pkg/base"
"mayfly-go/pkg/model"
)
type Db interface {
base.Repo[*entity.Db]
// 分页获取数据信息列表
GetDbList(condition *entity.DbQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any]
GetDbList(condition *entity.DbQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error)
Count(condition *entity.DbQuery) int64
// 根据条件获取数据库信息
GetDb(condition *entity.Db, cols ...string) error
// 根据id获取
GetById(id uint64, cols ...string) *entity.Db
Insert(db *entity.Db)
Update(db *entity.Db)
Delete(id uint64)
}

View File

@@ -1,7 +1,10 @@
package repository
import "mayfly-go/internal/db/domain/entity"
import (
"mayfly-go/internal/db/domain/entity"
"mayfly-go/pkg/base"
)
type DbSql interface {
DeleteBy(condition *entity.DbSql)
base.Repo[*entity.DbSql]
}

View File

@@ -2,14 +2,13 @@ package repository
import (
"mayfly-go/internal/db/domain/entity"
"mayfly-go/pkg/base"
"mayfly-go/pkg/model"
)
type DbSqlExec interface {
Insert(d *entity.DbSqlExec)
DeleteBy(condition *entity.DbSqlExec)
base.Repo[*entity.DbSqlExec]
// 分页获取
GetPageList(condition *entity.DbSqlExecQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any]
GetPageList(condition *entity.DbSqlExecQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error)
}

View File

@@ -2,24 +2,13 @@ package repository
import (
"mayfly-go/internal/db/domain/entity"
"mayfly-go/pkg/base"
"mayfly-go/pkg/model"
)
type Instance interface {
base.Repo[*entity.Instance]
// 分页获取数据库实例信息列表
GetInstanceList(condition *entity.InstanceQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any]
Count(condition *entity.InstanceQuery) int64
// 根据条件获取实例信息
GetInstance(condition *entity.Instance, cols ...string) error
// 根据id获取
GetById(id uint64, cols ...string) *entity.Instance
Insert(db *entity.Instance)
Update(db *entity.Instance)
Delete(id uint64)
GetInstanceList(condition *entity.InstanceQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error)
}

View File

@@ -3,19 +3,21 @@ package persistence
import (
"mayfly-go/internal/db/domain/entity"
"mayfly-go/internal/db/domain/repository"
"mayfly-go/pkg/biz"
"mayfly-go/pkg/base"
"mayfly-go/pkg/gormx"
"mayfly-go/pkg/model"
)
type dbRepoImpl struct{}
type dbRepoImpl struct {
base.RepoImpl[*entity.Db]
}
func newDbRepo() repository.Db {
return new(dbRepoImpl)
return &dbRepoImpl{base.RepoImpl[*entity.Db]{M: new(entity.Db)}}
}
// 分页获取数据库信息列表
func (d *dbRepoImpl) GetDbList(condition *entity.DbQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any] {
func (d *dbRepoImpl) GetDbList(condition *entity.DbQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error) {
qd := gormx.NewQueryWithTableName("t_db db").
Select("db.*, inst.name instance_name, inst.type instance_type").
Joins("JOIN t_db_instance inst ON db.instance_id = inst.id").
@@ -38,32 +40,5 @@ func (d *dbRepoImpl) Count(condition *entity.DbQuery) int64 {
if condition.InstanceId > 0 {
where["instance_id"] = condition.InstanceId
}
return gormx.CountByCond(new(entity.Db), where)
}
// 根据条件获取账号信息
func (d *dbRepoImpl) GetDb(condition *entity.Db, cols ...string) error {
return gormx.GetBy(condition, cols...)
}
// 根据id获取
func (d *dbRepoImpl) GetById(id uint64, cols ...string) *entity.Db {
db := new(entity.Db)
if err := gormx.GetById(db, id, cols...); err != nil {
return nil
}
return db
}
func (d *dbRepoImpl) Insert(db *entity.Db) {
biz.ErrIsNil(gormx.Insert(db), "新增数据库信息失败")
}
func (d *dbRepoImpl) Update(db *entity.Db) {
biz.ErrIsNil(gormx.UpdateById(db), "更新数据库信息失败")
}
func (d *dbRepoImpl) Delete(id uint64) {
gormx.DeleteById(new(entity.Db), id)
return d.CountByCond(where)
}

View File

@@ -3,17 +3,13 @@ package persistence
import (
"mayfly-go/internal/db/domain/entity"
"mayfly-go/internal/db/domain/repository"
"mayfly-go/pkg/biz"
"mayfly-go/pkg/gormx"
"mayfly-go/pkg/base"
)
type dbSqlRepoImpl struct{}
type dbSqlRepoImpl struct {
base.RepoImpl[*entity.DbSql]
}
func newDbSqlRepo() repository.DbSql {
return new(dbSqlRepoImpl)
}
// 分页获取数据库信息列表
func (d *dbSqlRepoImpl) DeleteBy(condition *entity.DbSql) {
biz.ErrIsNil(gormx.DeleteByCondition(condition), "删除sql失败")
return &dbSqlRepoImpl{base.RepoImpl[*entity.DbSql]{M: new(entity.DbSql)}}
}

View File

@@ -3,27 +3,21 @@ package persistence
import (
"mayfly-go/internal/db/domain/entity"
"mayfly-go/internal/db/domain/repository"
"mayfly-go/pkg/biz"
"mayfly-go/pkg/base"
"mayfly-go/pkg/gormx"
"mayfly-go/pkg/model"
)
type dbSqlExecRepoImpl struct{}
type dbSqlExecRepoImpl struct {
base.RepoImpl[*entity.DbSqlExec]
}
func newDbSqlExecRepo() repository.DbSqlExec {
return new(dbSqlExecRepoImpl)
}
func (d *dbSqlExecRepoImpl) Insert(dse *entity.DbSqlExec) {
gormx.Insert(dse)
}
func (d *dbSqlExecRepoImpl) DeleteBy(condition *entity.DbSqlExec) {
biz.ErrIsNil(gormx.DeleteByCondition(condition), "删除sql执行记录失败")
return &dbSqlExecRepoImpl{base.RepoImpl[*entity.DbSqlExec]{M: new(entity.DbSqlExec)}}
}
// 分页获取
func (d *dbSqlExecRepoImpl) GetPageList(condition *entity.DbSqlExecQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any] {
func (d *dbSqlExecRepoImpl) GetPageList(condition *entity.DbSqlExecQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error) {
qd := gormx.NewQuery(new(entity.DbSqlExec)).WithCondModel(condition).WithOrderBy(orderBy...)
return gormx.PageQuery(qd, pageParam, toEntity)
}

View File

@@ -3,53 +3,24 @@ package persistence
import (
"mayfly-go/internal/db/domain/entity"
"mayfly-go/internal/db/domain/repository"
"mayfly-go/pkg/biz"
"mayfly-go/pkg/base"
"mayfly-go/pkg/gormx"
"mayfly-go/pkg/model"
)
type instanceRepoImpl struct{}
type instanceRepoImpl struct {
base.RepoImpl[*entity.Instance]
}
func newInstanceRepo() repository.Instance {
return new(instanceRepoImpl)
return &instanceRepoImpl{base.RepoImpl[*entity.Instance]{M: new(entity.Instance)}}
}
// 分页获取数据库信息列表
func (d *instanceRepoImpl) GetInstanceList(condition *entity.InstanceQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any] {
func (d *instanceRepoImpl) GetInstanceList(condition *entity.InstanceQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error) {
qd := gormx.NewQuery(new(entity.Instance)).
Eq("id", condition.Id).
Eq("host", condition.Host).
Like("name", condition.Name)
return gormx.PageQuery(qd, pageParam, toEntity)
}
func (d *instanceRepoImpl) Count(condition *entity.InstanceQuery) int64 {
where := make(map[string]any)
return gormx.CountByCond(new(entity.Instance), where)
}
// 根据条件获数据库实例信息
func (d *instanceRepoImpl) GetInstance(condition *entity.Instance, cols ...string) error {
return gormx.GetBy(condition, cols...)
}
// 根据id获取数据库实例
func (d *instanceRepoImpl) GetById(id uint64, cols ...string) *entity.Instance {
instance := new(entity.Instance)
if err := gormx.GetById(instance, id, cols...); err != nil {
return nil
}
return instance
}
func (d *instanceRepoImpl) Insert(db *entity.Instance) {
biz.ErrIsNil(gormx.Insert(db), "新增数据库实例失败")
}
func (d *instanceRepoImpl) Update(db *entity.Instance) {
biz.ErrIsNil(gormx.UpdateById(db), "更新数据库实例失败")
}
func (d *instanceRepoImpl) Delete(id uint64) {
gormx.DeleteById(new(entity.Instance), id)
}

View File

@@ -18,14 +18,17 @@ type AuthCert struct {
func (ac *AuthCert) BaseAuthCerts(rc *req.Ctx) {
queryCond, page := ginx.BindQueryAndPage(rc.GinCtx, new(entity.AuthCertQuery))
rc.ResData = ac.AuthCertApp.GetPageList(queryCond, page, new([]vo.AuthCertBaseVO))
res, err := ac.AuthCertApp.GetPageList(queryCond, page, new([]vo.AuthCertBaseVO))
biz.ErrIsNil(err)
rc.ResData = res
}
func (ac *AuthCert) AuthCerts(rc *req.Ctx) {
queryCond, page := ginx.BindQueryAndPage(rc.GinCtx, new(entity.AuthCertQuery))
res := new([]*entity.AuthCert)
pageRes := ac.AuthCertApp.GetPageList(queryCond, page, res)
pageRes, err := ac.AuthCertApp.GetPageList(queryCond, page, res)
biz.ErrIsNil(err)
for _, r := range *res {
r.PwdDecrypt()
}
@@ -42,7 +45,7 @@ func (c *AuthCert) SaveAuthCert(rc *req.Ctx) {
rc.ReqParam = acForm
ac.SetBaseInfo(rc.LoginAccount)
c.AuthCertApp.Save(ac)
biz.ErrIsNil(c.AuthCertApp.Save(ac))
}
func (c *AuthCert) Delete(rc *req.Ctx) {

View File

@@ -11,9 +11,11 @@ import (
tagapp "mayfly-go/internal/tag/application"
"mayfly-go/pkg/biz"
"mayfly-go/pkg/config"
"mayfly-go/pkg/errorx"
"mayfly-go/pkg/ginx"
"mayfly-go/pkg/model"
"mayfly-go/pkg/req"
"mayfly-go/pkg/utils/anyx"
"mayfly-go/pkg/utils/collx"
"mayfly-go/pkg/utils/stringx"
"mayfly-go/pkg/ws"
@@ -44,7 +46,8 @@ func (m *Machine) Machines(rc *req.Ctx) {
}
condition.TagIds = tagIds
res := m.MachineApp.GetMachineList(condition, pageParam, new([]*vo.MachineVO))
res, err := m.MachineApp.GetMachineList(condition, pageParam, new([]*vo.MachineVO))
biz.ErrIsNil(err)
if res.Total == 0 {
rc.ResData = res
return
@@ -61,8 +64,9 @@ func (m *Machine) MachineTags(rc *req.Ctx) {
}
func (m *Machine) MachineStats(rc *req.Ctx) {
stats := m.MachineApp.GetCli(GetMachineId(rc.GinCtx)).GetAllStats()
rc.ResData = stats
cli, err := m.MachineApp.GetCli(GetMachineId(rc.GinCtx))
biz.ErrIsNilAppendErr(err, "获取客户端连接失败: %s")
rc.ResData = cli.GetAllStats()
}
// 保存机器信息
@@ -74,12 +78,13 @@ func (m *Machine) SaveMachine(rc *req.Ctx) {
rc.ReqParam = machineForm
me.SetBaseInfo(rc.LoginAccount)
m.MachineApp.Save(me)
biz.ErrIsNil(m.MachineApp.Save(me))
}
func (m *Machine) TestConn(rc *req.Ctx) {
me := ginx.BindJsonAndCopyTo(rc.GinCtx, new(form.MachineForm), new(entity.Machine))
m.MachineApp.TestConn(me)
// 测试连接
biz.ErrIsNilAppendErr(m.MachineApp.TestConn(me), "该机器无法连接: %s")
}
func (m *Machine) ChangeStatus(rc *req.Ctx) {
@@ -87,7 +92,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)
m.MachineApp.ChangeStatus(id, status)
biz.ErrIsNil(m.MachineApp.ChangeStatus(id, status))
}
func (m *Machine) DeleteMachine(rc *req.Ctx) {
@@ -126,7 +131,8 @@ func (m *Machine) GetProcess(rc *req.Ctx) {
count := ginx.QueryInt(g, "count", 10)
cmd += "| head -n " + fmt.Sprintf("%d", count)
cli := m.MachineApp.GetCli(GetMachineId(rc.GinCtx))
cli, err := m.MachineApp.GetCli(GetMachineId(rc.GinCtx))
biz.ErrIsNilAppendErr(err, "获取客户端连接失败: %s")
biz.ErrIsNilAppendErr(m.TagApp.CanAccess(rc.LoginAccount.Id, cli.GetMachine().TagPath), "%s")
res, err := cli.Run(cmd)
@@ -139,7 +145,8 @@ func (m *Machine) KillProcess(rc *req.Ctx) {
pid := rc.GinCtx.Query("pid")
biz.NotEmpty(pid, "进程id不能为空")
cli := m.MachineApp.GetCli(GetMachineId(rc.GinCtx))
cli, err := m.MachineApp.GetCli(GetMachineId(rc.GinCtx))
biz.ErrIsNilAppendErr(err, "获取客户端连接失败: %s")
biz.ErrIsNilAppendErr(m.TagApp.CanAccess(rc.LoginAccount.Id, cli.GetMachine().TagPath), "%s")
res, err := cli.Run("sudo kill -9 " + pid)
@@ -151,7 +158,7 @@ func (m *Machine) WsSSH(g *gin.Context) {
defer func() {
if wsConn != nil {
if err := recover(); err != nil {
wsConn.WriteMessage(websocket.TextMessage, []byte(err.(error).Error()))
wsConn.WriteMessage(websocket.TextMessage, []byte(anyx.ToString(err)))
}
wsConn.Close()
}
@@ -161,10 +168,11 @@ func (m *Machine) WsSSH(g *gin.Context) {
// 权限校验
rc := req.NewCtxWithGin(g).WithRequiredPermission(req.NewPermission("machine:terminal"))
if err = req.PermissionHandler(rc); err != nil {
panic(biz.NewBizErr("\033[1;31m您没有权限操作该机器终端,请重新登录后再试~\033[0m"))
panic(errorx.NewBiz("\033[1;31m您没有权限操作该机器终端,请重新登录后再试~\033[0m"))
}
cli := m.MachineApp.GetCli(GetMachineId(g))
cli, err := m.MachineApp.GetCli(GetMachineId(g))
biz.ErrIsNilAppendErr(err, "获取客户端连接失败: %s")
biz.ErrIsNilAppendErr(m.TagApp.CanAccess(rc.LoginAccount.Id, cli.GetMachine().TagPath), "%s")
cols := ginx.QueryInt(g, "cols", 80)

View File

@@ -22,12 +22,13 @@ func (m *MachineCronJob) MachineCronJobs(rc *req.Ctx) {
cond, pageParam := ginx.BindQueryAndPage(rc.GinCtx, new(entity.MachineCronJob))
vos := new([]*vo.MachineCronJobVO)
pr := m.MachineCronJobApp.GetPageList(cond, pageParam, vos)
pageRes, err := m.MachineCronJobApp.GetPageList(cond, pageParam, vos)
biz.ErrIsNil(err)
for _, mcj := range *vos {
mcj.Running = scheduler.ExistKey(mcj.Key)
}
rc.ResData = pr
rc.ResData = pageRes
}
func (m *MachineCronJob) Save(rc *req.Ctx) {
@@ -35,7 +36,8 @@ func (m *MachineCronJob) Save(rc *req.Ctx) {
mcj := ginx.BindJsonAndCopyTo[*entity.MachineCronJob](rc.GinCtx, jobForm, new(entity.MachineCronJob))
rc.ReqParam = jobForm
mcj.SetBaseInfo(rc.LoginAccount)
cronJobId := m.MachineCronJobApp.Save(mcj)
cronJobId, err := m.MachineCronJobApp.Save(mcj)
biz.ErrIsNil(err)
// 关联机器
m.MachineCronJobApp.CronJobRelateMachines(cronJobId, jobForm.MachineIds, rc.LoginAccount)
@@ -63,5 +65,7 @@ func (m *MachineCronJob) GetRelateCronJobIds(rc *req.Ctx) {
func (m *MachineCronJob) CronJobExecs(rc *req.Ctx) {
cond, pageParam := ginx.BindQueryAndPage[*entity.MachineCronJobExec](rc.GinCtx, new(entity.MachineCronJobExec))
rc.ResData = m.MachineCronJobApp.GetExecPageList(cond, pageParam, new([]entity.MachineCronJobExec))
res, err := m.MachineCronJobApp.GetExecPageList(cond, pageParam, new([]entity.MachineCronJobExec))
biz.ErrIsNil(err)
rc.ResData = res
}

View File

@@ -12,6 +12,7 @@ import (
msgapp "mayfly-go/internal/msg/application"
msgdto "mayfly-go/internal/msg/application/dto"
"mayfly-go/pkg/biz"
"mayfly-go/pkg/errorx"
"mayfly-go/pkg/ginx"
"mayfly-go/pkg/logx"
"mayfly-go/pkg/req"
@@ -43,7 +44,9 @@ const (
func (m *MachineFile) MachineFiles(rc *req.Ctx) {
g := rc.GinCtx
condition := &entity.MachineFile{MachineId: GetMachineId(g)}
rc.ResData = m.MachineFileApp.GetPageList(condition, ginx.GetPageParam(g), new([]vo.MachineFileVO))
res, err := m.MachineFileApp.GetPageList(condition, ginx.GetPageParam(g), new([]vo.MachineFileVO))
biz.ErrIsNil(err)
rc.ResData = res
}
func (m *MachineFile) SaveMachineFiles(rc *req.Ctx) {
@@ -52,11 +55,11 @@ func (m *MachineFile) SaveMachineFiles(rc *req.Ctx) {
entity.SetBaseInfo(rc.LoginAccount)
rc.ReqParam = fileForm
m.MachineFileApp.Save(entity)
biz.ErrIsNil(m.MachineFileApp.Save(entity))
}
func (m *MachineFile) DeleteFile(rc *req.Ctx) {
m.MachineFileApp.Delete(GetMachineFileId(rc.GinCtx))
biz.ErrIsNil(m.MachineFileApp.Delete(GetMachineFileId(rc.GinCtx)))
}
/*** sftp相关操作 */
@@ -121,7 +124,9 @@ func (m *MachineFile) GetDirEntry(rc *req.Ctx) {
if !strings.HasSuffix(readPath, "/") {
readPath = readPath + "/"
}
fis := m.MachineFileApp.ReadDir(fid, readPath)
fis, err := m.MachineFileApp.ReadDir(fid, readPath)
biz.ErrIsNilAppendErr(err, "读取目录失败: %s")
fisVO := make([]vo.MachineFileInfo, 0)
for _, fi := range fis {
fisVO = append(fisVO, vo.MachineFileInfo{
@@ -143,7 +148,9 @@ func (m *MachineFile) GetDirSize(rc *req.Ctx) {
fid := GetMachineFileId(g)
readPath := g.Query("path")
rc.ResData = m.MachineFileApp.GetDirSize(fid, readPath)
size, err := m.MachineFileApp.GetDirSize(fid, readPath)
biz.ErrIsNil(err)
rc.ResData = size
}
func (m *MachineFile) GetFileStat(rc *req.Ctx) {
@@ -151,7 +158,9 @@ func (m *MachineFile) GetFileStat(rc *req.Ctx) {
fid := GetMachineFileId(g)
readPath := g.Query("path")
rc.ResData = m.MachineFileApp.FileStat(fid, readPath)
res, err := m.MachineFileApp.FileStat(fid, readPath)
biz.ErrIsNil(err, res)
rc.ResData = res
}
func (m *MachineFile) WriteFileContent(rc *req.Ctx) {
@@ -220,9 +229,12 @@ func (m *MachineFile) UploadFolder(rc *req.Ctx) {
paths := mf.Value["paths"]
folderName := filepath.Dir(paths[0])
mcli := m.MachineFileApp.GetMachineCli(fid, basePath+"/"+folderName)
mcli, err := m.MachineFileApp.GetMachineCli(fid, basePath+"/"+folderName)
biz.ErrIsNil(err)
mi := mcli.GetMachine()
sftpCli := mcli.GetSftpCli()
sftpCli, err := mcli.GetSftpCli()
biz.ErrIsNil(err)
rc.ReqParam = collx.Kvs("machine", mi, "path", fmt.Sprintf("%s/%s", basePath, folderName))
folderFiles := make([]FolderFile, len(paths))
@@ -258,7 +270,7 @@ func (m *MachineFile) UploadFolder(rc *req.Ctx) {
if err := recover(); err != nil {
logx.Errorf("文件上传失败: %s", err)
switch t := err.(type) {
case biz.BizError:
case errorx.BizError:
m.MsgApp.CreateAndSend(la, msgdto.ErrSysMsg("文件上传失败", fmt.Sprintf("执行文件上传失败:\n<-e errCode: %d, errMsg: %s", t.Code(), t.Error())))
}
}

View File

@@ -27,7 +27,9 @@ type MachineScript struct {
func (m *MachineScript) MachineScripts(rc *req.Ctx) {
g := rc.GinCtx
condition := &entity.MachineScript{MachineId: GetMachineId(g)}
rc.ResData = m.MachineScriptApp.GetPageList(condition, ginx.GetPageParam(g), new([]vo.MachineScriptVO))
res, err := m.MachineScriptApp.GetPageList(condition, ginx.GetPageParam(g), new([]vo.MachineScriptVO))
biz.ErrIsNil(err)
rc.ResData = res
}
func (m *MachineScript) SaveMachineScript(rc *req.Ctx) {
@@ -37,7 +39,7 @@ func (m *MachineScript) SaveMachineScript(rc *req.Ctx) {
rc.ReqParam = form
machineScript.SetBaseInfo(rc.LoginAccount)
m.MachineScriptApp.Save(machineScript)
biz.ErrIsNil(m.MachineScriptApp.Save(machineScript))
}
func (m *MachineScript) DeleteMachineScript(rc *req.Ctx) {
@@ -57,8 +59,8 @@ func (m *MachineScript) RunMachineScript(rc *req.Ctx) {
scriptId := GetMachineScriptId(g)
machineId := GetMachineId(g)
ms := m.MachineScriptApp.GetById(scriptId, "MachineId", "Name", "Script")
biz.NotNil(ms, "该脚本不存在")
ms, err := m.MachineScriptApp.GetById(new(entity.MachineScript), scriptId, "MachineId", "Name", "Script")
biz.ErrIsNil(err, "该脚本不存在")
biz.IsTrue(ms.MachineId == application.Common_Script_Machine_Id || ms.MachineId == machineId, "该脚本不属于该机器")
script := ms.Script
@@ -66,7 +68,8 @@ func (m *MachineScript) RunMachineScript(rc *req.Ctx) {
if params := g.Query("params"); params != "" {
script = stringx.TemplateParse(ms.Script, jsonx.ToMap(params))
}
cli := m.MachineApp.GetCli(machineId)
cli, err := m.MachineApp.GetCli(machineId)
biz.ErrIsNilAppendErr(err, "获取客户端连接失败: %s")
biz.ErrIsNilAppendErr(m.TagApp.CanAccess(rc.LoginAccount.Id, cli.GetMachine().TagPath), "%s")
res, err := cli.Run(script)

View File

@@ -5,17 +5,23 @@ import (
)
var (
machineFileApp MachineFile = newMachineFileApp(persistence.GetMachineFileRepo(), persistence.GetMachineRepo())
machineScriptApp MachineScript = newMachineScriptApp(persistence.GetMachineScriptRepo(), persistence.GetMachineRepo())
authCertApp AuthCert = newAuthCertApp(persistence.GetAuthCertRepo())
machineApp Machine = newMachineApp(
persistence.GetMachineRepo(),
GetAuthCertApp(),
)
machineFileApp MachineFile = newMachineFileApp(
persistence.GetMachineFileRepo(),
GetMachineApp(),
)
machineScriptApp MachineScript = newMachineScriptApp(
persistence.GetMachineScriptRepo(),
GetMachineApp(),
)
authCertApp AuthCert = newAuthCertApp(persistence.GetAuthCertRepo())
machineCropJobApp MachineCronJob = newMachineCronJobApp(
persistence.GetMachineCronJobRepo(),
persistence.GetMachineCronJobRelateRepo(),

View File

@@ -3,62 +3,56 @@ package application
import (
"mayfly-go/internal/machine/domain/entity"
"mayfly-go/internal/machine/domain/repository"
"mayfly-go/pkg/biz"
"mayfly-go/pkg/base"
"mayfly-go/pkg/errorx"
"mayfly-go/pkg/model"
)
type AuthCert interface {
GetPageList(condition *entity.AuthCertQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any]
base.App[*entity.AuthCert]
Save(ac *entity.AuthCert)
GetPageList(condition *entity.AuthCertQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error)
GetById(id uint64) *entity.AuthCert
Save(ac *entity.AuthCert) error
GetByIds(ids ...uint64) []*entity.AuthCert
DeleteById(id uint64)
}
func newAuthCertApp(authCertRepo repository.AuthCert) AuthCert {
return &authCertAppImpl{
authCertRepo: authCertRepo,
base.AppImpl[*entity.AuthCert, repository.AuthCert]{Repo: authCertRepo},
}
}
type authCertAppImpl struct {
authCertRepo repository.AuthCert
base.AppImpl[*entity.AuthCert, repository.AuthCert]
}
func (a *authCertAppImpl) GetPageList(condition *entity.AuthCertQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any] {
return a.authCertRepo.GetPageList(condition, pageParam, toEntity)
func (a *authCertAppImpl) GetPageList(condition *entity.AuthCertQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error) {
return a.GetRepo().GetPageList(condition, pageParam, toEntity)
}
func (a *authCertAppImpl) Save(ac *entity.AuthCert) {
func (a *authCertAppImpl) Save(ac *entity.AuthCert) error {
oldAc := &entity.AuthCert{Name: ac.Name}
err := a.authCertRepo.GetByCondition(oldAc, "Id", "Name")
err := a.GetBy(oldAc, "Id", "Name")
ac.PwdEncrypt()
if ac.Id == 0 {
biz.IsTrue(err != nil, "该凭证名已存在")
a.authCertRepo.Insert(ac)
return
if err == nil {
return errorx.NewBiz("该凭证名已存在")
}
return a.Insert(ac)
}
// 如果存在该库,则校验修改的库是否为该库
if err == nil {
biz.IsTrue(oldAc.Id == ac.Id, "该凭证名已存在")
if err == nil && oldAc.Id != ac.Id {
return errorx.NewBiz("该凭证名已存在")
}
a.authCertRepo.Update(ac)
}
func (a *authCertAppImpl) GetById(id uint64) *entity.AuthCert {
return a.authCertRepo.GetById(id)
return a.UpdateById(ac)
}
func (a *authCertAppImpl) GetByIds(ids ...uint64) []*entity.AuthCert {
return a.authCertRepo.GetByIds(ids...)
}
func (a *authCertAppImpl) DeleteById(id uint64) {
a.authCertRepo.DeleteById(id)
acs := new([]*entity.AuthCert)
a.GetByIdIn(acs, ids)
return *acs
}

View File

@@ -5,7 +5,8 @@ import (
"mayfly-go/internal/machine/domain/entity"
"mayfly-go/internal/machine/domain/repository"
"mayfly-go/internal/machine/infrastructure/machine"
"mayfly-go/pkg/biz"
"mayfly-go/pkg/base"
"mayfly-go/pkg/errorx"
"mayfly-go/pkg/gormx"
"mayfly-go/pkg/model"
@@ -13,90 +14,93 @@ import (
)
type Machine interface {
// 根据条件获取账号信息
GetMachine(condition *entity.Machine, cols ...string) error
base.App[*entity.Machine]
Save(*entity.Machine)
Save(*entity.Machine) error
// 测试机器连接
TestConn(me *entity.Machine)
TestConn(me *entity.Machine) error
// 调整机器状态
ChangeStatus(id uint64, status int8)
ChangeStatus(id uint64, status int8) error
Count(condition *entity.MachineQuery) int64
Delete(id uint64)
// 根据id获取
GetById(id uint64, cols ...string) *entity.Machine
Delete(id uint64) error
// 分页获取机器信息列表
GetMachineList(condition *entity.MachineQuery, pageParam *model.PageParam, toEntity *[]*vo.MachineVO, orderBy ...string) *model.PageResult[*[]*vo.MachineVO]
GetMachineList(condition *entity.MachineQuery, pageParam *model.PageParam, toEntity *[]*vo.MachineVO, orderBy ...string) (*model.PageResult[*[]*vo.MachineVO], error)
// 获取机器连接
GetCli(id uint64) *machine.Cli
GetCli(id uint64) (*machine.Cli, error)
// 获取ssh隧道机器连接
GetSshTunnelMachine(id int) *machine.SshTunnelMachine
GetSshTunnelMachine(id int) (*machine.SshTunnelMachine, error)
}
func newMachineApp(machineRepo repository.Machine, authCertApp AuthCert) Machine {
return &machineAppImpl{
machineRepo: machineRepo,
app := &machineAppImpl{
authCertApp: authCertApp,
}
app.Repo = machineRepo
return app
}
type machineAppImpl struct {
machineRepo repository.Machine
base.AppImpl[*entity.Machine, repository.Machine]
authCertApp AuthCert
}
// 分页获取机器信息列表
func (m *machineAppImpl) GetMachineList(condition *entity.MachineQuery, pageParam *model.PageParam, toEntity *[]*vo.MachineVO, orderBy ...string) *model.PageResult[*[]*vo.MachineVO] {
return m.machineRepo.GetMachineList(condition, pageParam, toEntity, orderBy...)
func (m *machineAppImpl) GetMachineList(condition *entity.MachineQuery, pageParam *model.PageParam, toEntity *[]*vo.MachineVO, orderBy ...string) (*model.PageResult[*[]*vo.MachineVO], error) {
return m.GetRepo().GetMachineList(condition, pageParam, toEntity, orderBy...)
}
func (m *machineAppImpl) Count(condition *entity.MachineQuery) int64 {
return m.machineRepo.Count(condition)
return m.GetRepo().Count(condition)
}
func (m *machineAppImpl) Save(me *entity.Machine) {
func (m *machineAppImpl) Save(me *entity.Machine) error {
oldMachine := &entity.Machine{Ip: me.Ip, Port: me.Port, Username: me.Username}
if me.SshTunnelMachineId > 0 {
oldMachine.SshTunnelMachineId = me.SshTunnelMachineId
}
err := m.GetMachine(oldMachine)
err := m.GetBy(oldMachine)
me.PwdEncrypt()
if me.Id == 0 {
biz.IsTrue(err != nil, "该机器信息已存在")
if err == nil {
return errorx.NewBiz("该机器信息已存在")
}
// 新增机器,默认启用状态
me.Status = entity.MachineStatusEnable
m.machineRepo.Create(me)
return
return m.Insert(me)
}
// 如果存在该库,则校验修改的库是否为该库
if err == nil {
biz.IsTrue(oldMachine.Id == me.Id, "该机器信息已存在")
if err == nil && oldMachine.Id != me.Id {
return errorx.NewBiz("该机器信息已存在")
}
// 关闭连接
machine.DeleteCli(me.Id)
m.machineRepo.UpdateById(me)
return m.UpdateById(me)
}
func (m *machineAppImpl) TestConn(me *entity.Machine) {
func (m *machineAppImpl) TestConn(me *entity.Machine) error {
me.Id = 0
// 测试连接
biz.ErrIsNilAppendErr(machine.TestConn(*m.toMachineInfo(me), func(u uint64) *machine.Info {
mi, err := m.toMachineInfo(me)
if err != nil {
return err
}
return machine.TestConn(*mi, func(u uint64) (*machine.Info, error) {
return m.toMachineInfoById(u)
}), "该机器无法连接: %s")
})
}
func (m *machineAppImpl) ChangeStatus(id uint64, status int8) {
func (m *machineAppImpl) ChangeStatus(id uint64, status int8) error {
if status == entity.MachineStatusDisable {
// 关闭连接
machine.DeleteCli(id)
@@ -104,63 +108,55 @@ func (m *machineAppImpl) ChangeStatus(id uint64, status int8) {
machine := new(entity.Machine)
machine.Id = id
machine.Status = status
m.machineRepo.UpdateById(machine)
return m.UpdateById(machine)
}
// 根据条件获取机器信息
func (m *machineAppImpl) Delete(id uint64) {
func (m *machineAppImpl) Delete(id uint64) error {
// 关闭连接
machine.DeleteCli(id)
gormx.Tx(
return gormx.Tx(
func(db *gorm.DB) error {
// 删除machine表信息
return gormx.DeleteByIdWithDb(db, new(entity.Machine), id)
},
func(db *gorm.DB) error {
// 删除machine_file
return gormx.DeleteByConditionWithDb(db, &entity.MachineFile{MachineId: id})
return gormx.DeleteByWithDb(db, &entity.MachineFile{MachineId: id})
},
func(db *gorm.DB) error {
// 删除machine_script
return gormx.DeleteByConditionWithDb(db, &entity.MachineScript{MachineId: id})
return gormx.DeleteByWithDb(db, &entity.MachineScript{MachineId: id})
},
)
}
// 根据条件获取机器信息
func (m *machineAppImpl) GetMachine(condition *entity.Machine, cols ...string) error {
return m.machineRepo.GetMachine(condition, cols...)
}
func (m *machineAppImpl) GetById(id uint64, cols ...string) *entity.Machine {
return m.machineRepo.GetById(id, cols...)
}
func (m *machineAppImpl) GetCli(machineId uint64) *machine.Cli {
cli, err := machine.GetCli(machineId, func(mid uint64) *machine.Info {
func (m *machineAppImpl) GetCli(machineId uint64) (*machine.Cli, error) {
return machine.GetCli(machineId, func(mid uint64) (*machine.Info, error) {
return m.toMachineInfoById(mid)
})
biz.ErrIsNilAppendErr(err, "获取客户端错误: %s")
return cli
}
func (m *machineAppImpl) GetSshTunnelMachine(machineId int) *machine.SshTunnelMachine {
sshTunnel, err := machine.GetSshTunnelMachine(machineId, func(mid uint64) *machine.Info {
func (m *machineAppImpl) GetSshTunnelMachine(machineId int) (*machine.SshTunnelMachine, error) {
return machine.GetSshTunnelMachine(machineId, func(mid uint64) (*machine.Info, error) {
return m.toMachineInfoById(mid)
})
biz.ErrIsNilAppendErr(err, "获取ssh隧道连接失败: %s")
return sshTunnel
}
// 生成机器信息根据授权凭证id填充用户密码等
func (m *machineAppImpl) toMachineInfoById(machineId uint64) *machine.Info {
me := m.GetById(machineId)
biz.IsTrue(me.Status == entity.MachineStatusEnable, "该机器已被停用")
func (m *machineAppImpl) toMachineInfoById(machineId uint64) (*machine.Info, error) {
me, err := m.GetById(new(entity.Machine), machineId)
if err != nil {
return nil, errorx.NewBiz("机器信息不存在")
}
if me.Status != entity.MachineStatusEnable {
return nil, errorx.NewBiz("该机器已被停用")
}
return m.toMachineInfo(me)
}
func (m *machineAppImpl) toMachineInfo(me *entity.Machine) *machine.Info {
func (m *machineAppImpl) toMachineInfo(me *entity.Machine) (*machine.Info, error) {
mi := new(machine.Info)
mi.Id = me.Id
mi.Name = me.Name
@@ -173,8 +169,10 @@ func (m *machineAppImpl) toMachineInfo(me *entity.Machine) *machine.Info {
mi.SshTunnelMachineId = me.SshTunnelMachineId
if me.UseAuthCert() {
ac := m.authCertApp.GetById(uint64(me.AuthCertId))
biz.NotNil(ac, "授权凭证信息已不存在,请重新关联")
ac, err := m.authCertApp.GetById(new(entity.AuthCert), uint64(me.AuthCertId))
if err != nil {
return nil, errorx.NewBiz("授权凭证信息已不存在,请重新关联")
}
mi.AuthMethod = ac.AuthMethod
ac.PwdDecrypt()
mi.Password = ac.Password
@@ -186,5 +184,5 @@ func (m *machineAppImpl) toMachineInfo(me *entity.Machine) *machine.Info {
}
mi.Password = me.Password
}
return mi
return mi, nil
}

View File

@@ -3,30 +3,33 @@ package application
import (
"mayfly-go/internal/machine/domain/entity"
"mayfly-go/internal/machine/domain/repository"
"mayfly-go/pkg/base"
"mayfly-go/pkg/biz"
"mayfly-go/pkg/errorx"
"mayfly-go/pkg/logx"
"mayfly-go/pkg/model"
"mayfly-go/pkg/rediscli"
"mayfly-go/pkg/scheduler"
"mayfly-go/pkg/utils/anyx"
"mayfly-go/pkg/utils/collx"
"mayfly-go/pkg/utils/stringx"
"time"
)
type MachineCronJob interface {
base.App[*entity.MachineCronJob]
// 分页获取机器任务列表信息
GetPageList(condition *entity.MachineCronJob, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any]
GetPageList(condition *entity.MachineCronJob, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error)
// 获取分页执行结果列表
GetExecPageList(condition *entity.MachineCronJobExec, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any]
GetExecPageList(condition *entity.MachineCronJobExec, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error)
// 根据id获取
GetById(id uint64, cols ...string) *entity.MachineCronJob
Save(entity *entity.MachineCronJob) uint64
Save(entity *entity.MachineCronJob) (uint64, error)
Delete(id uint64)
// 获取管理的机器列表id
// 获取计划任务关联的机器列表id
GetRelateMachineIds(cronJobId uint64) []uint64
// 获取机器关联的计划任务列表
@@ -43,7 +46,8 @@ type MachineCronJob interface {
}
type machineCropJobAppImpl struct {
machineCropJobRepo repository.MachineCronJob
base.AppImpl[*entity.MachineCronJob, repository.MachineCronJob]
machineCropJobRelateRepo repository.MachineCronJobRelate
machineCropJobExecRepo repository.MachineCronJobExec
machineApp Machine
@@ -55,48 +59,50 @@ func newMachineCronJobApp(
machineCropJobExecRepo repository.MachineCronJobExec,
machineApp Machine,
) MachineCronJob {
return &machineCropJobAppImpl{
machineCropJobRepo: machineCropJobRepo,
app := &machineCropJobAppImpl{
machineCropJobRelateRepo: machineCropJobRelateRepo,
machineCropJobExecRepo: machineCropJobExecRepo,
machineApp: machineApp,
}
app.Repo = machineCropJobRepo
return app
}
// 分页获取机器脚本任务列表
func (m *machineCropJobAppImpl) GetPageList(condition *entity.MachineCronJob, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any] {
return m.machineCropJobRepo.GetPageList(condition, pageParam, toEntity, orderBy...)
func (m *machineCropJobAppImpl) GetPageList(condition *entity.MachineCronJob, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error) {
return m.GetRepo().GetPageList(condition, pageParam, toEntity, orderBy...)
}
// 获取分页执行结果列表
func (m *machineCropJobAppImpl) GetExecPageList(condition *entity.MachineCronJobExec, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any] {
func (m *machineCropJobAppImpl) GetExecPageList(condition *entity.MachineCronJobExec, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error) {
return m.machineCropJobExecRepo.GetPageList(condition, pageParam, toEntity, orderBy...)
}
// 根据id获取
func (m *machineCropJobAppImpl) GetById(id uint64, cols ...string) *entity.MachineCronJob {
return m.machineCropJobRepo.GetById(id, cols...)
}
// 保存机器任务信息
func (m *machineCropJobAppImpl) Save(mcj *entity.MachineCronJob) uint64 {
func (m *machineCropJobAppImpl) Save(mcj *entity.MachineCronJob) (uint64, error) {
// 更新操作
if mcj.Id != 0 {
m.machineCropJobRepo.UpdateById(mcj)
m.UpdateById(mcj)
cj, err := m.GetById(new(entity.MachineCronJob), mcj.Id)
if err != nil {
return 0, errorx.NewBiz("该任务不存在")
}
// 处理最新的计划任务
m.addCronJob(m.GetById(mcj.Id))
return mcj.Id
m.addCronJob(cj)
return mcj.Id, nil
}
m.addCronJob(mcj)
m.machineCropJobRepo.Insert(mcj)
return mcj.Id
if err := m.Insert(mcj); err != nil {
return 0, err
}
return mcj.Id, nil
}
func (m *machineCropJobAppImpl) Delete(id uint64) {
m.machineCropJobRepo.Delete(id)
m.machineCropJobExecRepo.Delete(&entity.MachineCronJobExec{CronJobId: id})
m.machineCropJobRelateRepo.Delete(&entity.MachineCronJobRelate{CronJobId: id})
m.DeleteById(id)
m.machineCropJobExecRepo.DeleteByCond(&entity.MachineCronJobExec{CronJobId: id})
m.machineCropJobRelateRepo.DeleteByCond(&entity.MachineCronJobRelate{CronJobId: id})
}
func (m *machineCropJobAppImpl) GetRelateMachineIds(cronJobId uint64) []uint64 {
@@ -125,7 +131,7 @@ func (m *machineCropJobAppImpl) CronJobRelateMachines(cronJobId uint64, machineI
m.machineCropJobRelateRepo.BatchInsert(addVals)
for _, delId := range delIds {
m.machineCropJobRelateRepo.Delete(&entity.MachineCronJobRelate{CronJobId: cronJobId, MachineId: delId})
m.machineCropJobRelateRepo.DeleteByCond(&entity.MachineCronJobRelate{CronJobId: cronJobId, MachineId: delId})
}
}
@@ -147,14 +153,14 @@ func (m *machineCropJobAppImpl) MachineRelateCronJobs(machineId uint64, cronJobs
m.machineCropJobRelateRepo.BatchInsert(addVals)
for _, delId := range delIds {
m.machineCropJobRelateRepo.Delete(&entity.MachineCronJobRelate{CronJobId: delId, MachineId: machineId})
m.machineCropJobRelateRepo.DeleteByCond(&entity.MachineCronJobRelate{CronJobId: delId, MachineId: machineId})
}
}
func (m *machineCropJobAppImpl) InitCronJob() {
defer func() {
if err := recover(); err != nil {
logx.Errorf("机器计划任务初始化失败: %s", err.(error).Error())
logx.ErrorTrace("机器计划任务初始化失败: %s", err.(error))
}
}()
@@ -166,7 +172,7 @@ func (m *machineCropJobAppImpl) InitCronJob() {
cond.Status = entity.MachineCronJobStatusEnable
mcjs := new([]entity.MachineCronJob)
pr := m.GetPageList(cond, pageParam, mcjs)
pr, _ := m.GetPageList(cond, pageParam, mcjs)
total := pr.Total
add := 0
@@ -218,7 +224,7 @@ func (m *machineCropJobAppImpl) runCronJob(key string) {
cronJob := new(entity.MachineCronJob)
cronJob.Key = key
err := m.machineCropJobRepo.GetBy(cronJob)
err := m.GetBy(cronJob)
// 不存在或禁用,则移除该任务
if err != nil || cronJob.Status == entity.MachineCronJobStatusDisable {
scheduler.RemoveByKey(key)
@@ -233,7 +239,7 @@ func (m *machineCropJobAppImpl) runCronJob(key string) {
func (m *machineCropJobAppImpl) runCronJob0(mid uint64, cronJob *entity.MachineCronJob) {
defer func() {
if err := recover(); err != nil {
res := err.(error).Error()
res := anyx.ToString(err)
m.machineCropJobExecRepo.Insert(&entity.MachineCronJobExec{
MachineId: mid,
CronJobId: cronJob.Id,
@@ -245,7 +251,9 @@ func (m *machineCropJobAppImpl) runCronJob0(mid uint64, cronJob *entity.MachineC
}
}()
res, err := m.machineApp.GetCli(uint64(mid)).Run(cronJob.Script)
machineCli, err := m.machineApp.GetCli(uint64(mid))
biz.ErrIsNilAppendErr(err, "获取客户端连接失败: %s")
res, err := machineCli.Run(cronJob.Script)
if err != nil {
if res == "" {
res = err.Error()

View File

@@ -8,7 +8,7 @@ import (
"mayfly-go/internal/machine/domain/entity"
"mayfly-go/internal/machine/domain/repository"
"mayfly-go/internal/machine/infrastructure/machine"
"mayfly-go/pkg/biz"
"mayfly-go/pkg/errorx"
"mayfly-go/pkg/logx"
"mayfly-go/pkg/model"
"os"
@@ -19,7 +19,7 @@ import (
type MachineFile interface {
// 分页获取机器文件信息列表
GetPageList(condition *entity.MachineFile, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any]
GetPageList(condition *entity.MachineFile, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error)
// 根据条件获取
GetMachineFile(condition *entity.MachineFile, cols ...string) error
@@ -27,15 +27,15 @@ type MachineFile interface {
// 根据id获取
GetById(id uint64, cols ...string) *entity.MachineFile
Save(entity *entity.MachineFile)
Save(entity *entity.MachineFile) error
Delete(id uint64)
Delete(id uint64) error
// 获取文件关联的机器信息,主要用于记录日志使用
// GetMachine(fileId uint64) *machine.Info
// 检查文件路径并返回机器id
GetMachineCli(fileId uint64, path ...string) *machine.Cli
GetMachineCli(fileId uint64, path ...string) (*machine.Cli, error)
/** sftp 相关操作 **/
@@ -46,13 +46,13 @@ type MachineFile interface {
CreateFile(fid uint64, path string) (*machine.Info, error)
// 读取目录
ReadDir(fid uint64, path string) []fs.FileInfo
ReadDir(fid uint64, path string) ([]fs.FileInfo, error)
// 获取指定目录内容大小
GetDirSize(fid uint64, path string) string
GetDirSize(fid uint64, path string) (string, error)
// 获取文件stat
FileStat(fid uint64, path string) string
FileStat(fid uint64, path string) (string, error)
// 读取文件内容
ReadFile(fileId uint64, path string) (*sftp.File, *machine.Info, error)
@@ -73,18 +73,19 @@ type MachineFile interface {
Rename(fileId uint64, oldname string, newname string) (*machine.Info, error)
}
func newMachineFileApp(machineFileRepo repository.MachineFile, machineRepo repository.Machine) MachineFile {
return &machineFileAppImpl{machineRepo: machineRepo, machineFileRepo: machineFileRepo}
func newMachineFileApp(machineFileRepo repository.MachineFile, machineApp Machine) MachineFile {
return &machineFileAppImpl{machineApp: machineApp, machineFileRepo: machineFileRepo}
}
type machineFileAppImpl struct {
machineFileRepo repository.MachineFile
machineRepo repository.Machine
machineApp Machine
}
// 分页获取机器脚本信息列表
func (m *machineFileAppImpl) GetPageList(condition *entity.MachineFile, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any] {
func (m *machineFileAppImpl) GetPageList(condition *entity.MachineFile, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error) {
return m.machineFileRepo.GetPageList(condition, pageParam, toEntity, orderBy...)
}
@@ -99,34 +100,41 @@ func (m *machineFileAppImpl) GetById(id uint64, cols ...string) *entity.MachineF
}
// 保存机器文件配置
func (m *machineFileAppImpl) Save(entity *entity.MachineFile) {
biz.NotNil(m.machineRepo.GetById(entity.MachineId, "Name"), "该机器不存在")
if entity.Id != 0 {
m.machineFileRepo.UpdateById(entity)
} else {
m.machineFileRepo.Create(entity)
func (m *machineFileAppImpl) Save(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.Create(mf)
}
// 根据id删除
func (m *machineFileAppImpl) Delete(id uint64) {
m.machineFileRepo.Delete(id)
func (m *machineFileAppImpl) Delete(id uint64) error {
return m.machineFileRepo.Delete(id)
}
func (m *machineFileAppImpl) ReadDir(fid uint64, path string) []fs.FileInfo {
mcli := m.GetMachineCli(fid, path)
func (m *machineFileAppImpl) ReadDir(fid uint64, path string) ([]fs.FileInfo, error) {
if !strings.HasSuffix(path, "/") {
path = path + "/"
}
fis, err := mcli.GetSftpCli().ReadDir(path)
biz.ErrIsNilAppendErr(err, "读取目录失败: %s")
return fis
_, sftpCli, err := m.GetMachineSftpCli(fid, path)
if err != nil {
return nil, err
}
return sftpCli.ReadDir(path)
}
func (m *machineFileAppImpl) GetDirSize(fid uint64, path string) string {
mcli := m.GetMachineCli(fid, path)
func (m *machineFileAppImpl) GetDirSize(fid uint64, path string) (string, error) {
mcli, err := m.GetMachineCli(fid, path)
if err != nil {
return "", err
}
res, err := mcli.Run(fmt.Sprintf("du -sh %s", path))
if err != nil {
// 若存在目录为空,则可能会返回如下内容。最后一行即为真正目录内容所占磁盘空间大小
@@ -134,56 +142,74 @@ func (m *machineFileAppImpl) GetDirSize(fid uint64, path string) string {
//du: cannot access /proc/19087/fdinfo/3: No such file or directory\n
//18G /\n
if res == "" {
panic(biz.NewBizErr(fmt.Sprintf("获取目录大小失败: %s", err.Error())))
return "", errorx.NewBiz("获取目录大小失败: %s", err.Error())
}
strs := strings.Split(res, "\n")
res = strs[len(strs)-2]
if !strings.Contains(res, "\t") {
panic(biz.NewBizErr(res))
return "", errorx.NewBiz(res)
}
}
// 返回 32K\t/tmp\n
return strings.Split(res, "\t")[0]
return strings.Split(res, "\t")[0], nil
}
func (m *machineFileAppImpl) FileStat(fid uint64, path string) string {
mcli := m.GetMachineCli(fid, path)
res, err := mcli.Run(fmt.Sprintf("stat -L %s", path))
biz.ErrIsNil(err, res)
return res
func (m *machineFileAppImpl) FileStat(fid uint64, path string) (string, error) {
mcli, err := m.GetMachineCli(fid, path)
if err != nil {
return "", err
}
return mcli.Run(fmt.Sprintf("stat -L %s", path))
}
func (m *machineFileAppImpl) MkDir(fid uint64, path string) (*machine.Info, error) {
mcli := m.GetMachineCli(fid, path)
if !strings.HasSuffix(path, "/") {
path = path + "/"
}
err := mcli.GetSftpCli().MkdirAll(path)
return mcli.GetMachine(), err
mi, sftpCli, err := m.GetMachineSftpCli(fid, path)
if err != nil {
return nil, err
}
sftpCli.MkdirAll(path)
return mi, err
}
func (m *machineFileAppImpl) CreateFile(fid uint64, path string) (*machine.Info, error) {
mcli := m.GetMachineCli(fid, path)
file, err := mcli.GetSftpCli().Create(path)
biz.ErrIsNilAppendErr(err, "创建文件失败: %s")
mi, sftpCli, err := m.GetMachineSftpCli(fid, path)
if err != nil {
return nil, err
}
file, err := sftpCli.Create(path)
if err != nil {
return nil, errorx.NewBiz("创建文件失败: %s", err.Error())
}
defer file.Close()
return mcli.GetMachine(), err
return mi, err
}
func (m *machineFileAppImpl) ReadFile(fileId uint64, path string) (*sftp.File, *machine.Info, error) {
mcli := m.GetMachineCli(fileId, path)
mi, sftpCli, err := m.GetMachineSftpCli(fileId, path)
if err != nil {
return nil, nil, err
}
// 读取文件内容
fc, err := mcli.GetSftpCli().Open(path)
return fc, mcli.GetMachine(), err
fc, err := sftpCli.Open(path)
return fc, mi, err
}
// 写文件内容
func (m *machineFileAppImpl) WriteFileContent(fileId uint64, path string, content []byte) (*machine.Info, error) {
mcli := m.GetMachineCli(fileId, path)
mi := mcli.GetMachine()
f, err := mcli.GetSftpCli().OpenFile(path, os.O_WRONLY|os.O_TRUNC|os.O_CREATE|os.O_RDWR)
mi, sftpCli, err := m.GetMachineSftpCli(fileId, path)
if err != nil {
return nil, err
}
f, err := sftpCli.OpenFile(path, os.O_WRONLY|os.O_TRUNC|os.O_CREATE|os.O_RDWR)
if err != nil {
return mi, err
}
@@ -194,13 +220,16 @@ func (m *machineFileAppImpl) WriteFileContent(fileId uint64, path string, conten
// 上传文件
func (m *machineFileAppImpl) UploadFile(fileId uint64, path, filename string, reader io.Reader) (*machine.Info, error) {
mcli := m.GetMachineCli(fileId, path)
mi := mcli.GetMachine()
if !strings.HasSuffix(path, "/") {
path = path + "/"
}
createfile, err := mcli.GetSftpCli().Create(path + filename)
mi, sftpCli, err := m.GetMachineSftpCli(fileId, path)
if err != nil {
return nil, err
}
createfile, err := sftpCli.Create(path + filename)
if err != nil {
return mi, err
}
@@ -211,7 +240,10 @@ func (m *machineFileAppImpl) UploadFile(fileId uint64, path, filename string, re
// 删除文件
func (m *machineFileAppImpl) RemoveFile(fileId uint64, path ...string) (*machine.Info, error) {
mcli := m.GetMachineCli(fileId, path...)
mcli, err := m.GetMachineCli(fileId, path...)
if err != nil {
return nil, err
}
minfo := mcli.GetMachine()
// 优先使用命令删除速度快sftp需要递归遍历删除子文件等
@@ -221,7 +253,11 @@ func (m *machineFileAppImpl) RemoveFile(fileId uint64, path ...string) (*machine
}
logx.Errorf("使用命令rm删除文件失败: %s", res)
sftpCli := mcli.GetSftpCli()
sftpCli, err := mcli.GetSftpCli()
if err != nil {
return minfo, err
}
for _, p := range path {
err = sftpCli.RemoveAll(p)
if err != nil {
@@ -232,7 +268,11 @@ func (m *machineFileAppImpl) RemoveFile(fileId uint64, path ...string) (*machine
}
func (m *machineFileAppImpl) Copy(fileId uint64, toPath string, paths ...string) (*machine.Info, error) {
mcli := m.GetMachineCli(fileId, paths...)
mcli, err := m.GetMachineCli(fileId, paths...)
if err != nil {
return nil, err
}
mi := mcli.GetMachine()
res, err := mcli.Run(fmt.Sprintf("cp -r %s %s", strings.Join(paths, " "), toPath))
if err != nil {
@@ -242,28 +282,54 @@ func (m *machineFileAppImpl) Copy(fileId uint64, toPath string, paths ...string)
}
func (m *machineFileAppImpl) Mv(fileId uint64, toPath string, paths ...string) (*machine.Info, error) {
mcli := m.GetMachineCli(fileId, paths...)
mcli, err := m.GetMachineCli(fileId, paths...)
if err != nil {
return nil, err
}
mi := mcli.GetMachine()
res, err := mcli.Run(fmt.Sprintf("mv %s %s", strings.Join(paths, " "), toPath))
if err != nil {
return mi, errors.New(res)
return mi, errorx.NewBiz(res)
}
return mi, err
}
func (m *machineFileAppImpl) Rename(fileId uint64, oldname string, newname string) (*machine.Info, error) {
mcli := m.GetMachineCli(fileId, newname)
return mcli.GetMachine(), mcli.GetSftpCli().Rename(oldname, newname)
mi, sftpCli, err := m.GetMachineSftpCli(fileId, newname)
if err != nil {
return nil, err
}
return mi, sftpCli.Rename(oldname, newname)
}
// 获取文件机器cli
func (m *machineFileAppImpl) GetMachineCli(fid uint64, inputPath ...string) *machine.Cli {
biz.IsTrue(fid != 0, "文件id不能为空")
func (m *machineFileAppImpl) GetMachineCli(fid uint64, inputPath ...string) (*machine.Cli, error) {
mf := m.GetById(fid)
biz.NotNil(mf, "文件不存在")
if mf == nil {
return nil, errorx.NewBiz("文件不存在")
}
for _, path := range inputPath {
// 接口传入的地址需为配置路径的子路径
biz.IsTrue(strings.HasPrefix(path, mf.Path), "无权访问该目录或文件: %s", path)
if !strings.HasPrefix(path, mf.Path) {
return nil, errorx.NewBiz("无权访问该目录或文件: %s", path)
}
}
return GetMachineApp().GetCli(mf.MachineId)
return m.machineApp.GetCli(mf.MachineId)
}
// 获取文件机器 sftp cli
func (m *machineFileAppImpl) GetMachineSftpCli(fid uint64, inputPath ...string) (*machine.Info, *sftp.Client, error) {
mcli, err := m.GetMachineCli(fid, inputPath...)
if err != nil {
return nil, nil, err
}
sftpCli, err := mcli.GetSftpCli()
if err != nil {
return nil, nil, err
}
return mcli.GetMachine(), sftpCli, nil
}

View File

@@ -3,68 +3,58 @@ package application
import (
"mayfly-go/internal/machine/domain/entity"
"mayfly-go/internal/machine/domain/repository"
"mayfly-go/pkg/biz"
"mayfly-go/pkg/gormx"
"mayfly-go/pkg/base"
"mayfly-go/pkg/errorx"
"mayfly-go/pkg/model"
)
type MachineScript interface {
base.App[*entity.MachineScript]
// 分页获取机器脚本信息列表
GetPageList(condition *entity.MachineScript, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any]
GetPageList(condition *entity.MachineScript, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error)
// 根据条件获取
GetMachineScript(condition *entity.MachineScript, cols ...string) error
// 根据id获取
GetById(id uint64, cols ...string) *entity.MachineScript
Save(entity *entity.MachineScript)
Save(entity *entity.MachineScript) error
Delete(id uint64)
}
func newMachineScriptApp(machineScriptRepo repository.MachineScript, machineRepo repository.Machine) MachineScript {
return &machineScriptAppImpl{machineRepo: machineRepo, machineScriptRepo: machineScriptRepo}
func newMachineScriptApp(machineScriptRepo repository.MachineScript, machineApp Machine) MachineScript {
app := &machineScriptAppImpl{machineApp: machineApp}
app.Repo = machineScriptRepo
return app
}
type machineScriptAppImpl struct {
machineScriptRepo repository.MachineScript
machineRepo repository.Machine
base.AppImpl[*entity.MachineScript, repository.MachineScript]
machineApp Machine
}
const Common_Script_Machine_Id = 9999999
// 分页获取机器脚本信息列表
func (m *machineScriptAppImpl) GetPageList(condition *entity.MachineScript, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any] {
return m.machineScriptRepo.GetPageList(condition, pageParam, toEntity, orderBy...)
}
// 根据条件获取
func (m *machineScriptAppImpl) GetMachineScript(condition *entity.MachineScript, cols ...string) error {
return m.machineScriptRepo.GetMachineScript(condition, cols...)
}
// 根据id获取
func (m *machineScriptAppImpl) GetById(id uint64, cols ...string) *entity.MachineScript {
return m.machineScriptRepo.GetById(id, cols...)
func (m *machineScriptAppImpl) GetPageList(condition *entity.MachineScript, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error) {
return m.GetRepo().GetPageList(condition, pageParam, toEntity, orderBy...)
}
// 保存机器脚本
func (m *machineScriptAppImpl) Save(entity *entity.MachineScript) {
func (m *machineScriptAppImpl) Save(ms *entity.MachineScript) error {
// 如果机器id不为公共脚本id则校验机器是否存在
if machineId := entity.MachineId; machineId != Common_Script_Machine_Id {
biz.NotNil(m.machineRepo.GetById(machineId, "Name"), "该机器不存在")
if machineId := ms.MachineId; machineId != Common_Script_Machine_Id {
_, err := m.machineApp.GetById(new(entity.Machine), machineId, "Name")
if err != nil {
return errorx.NewBiz("该机器不存在")
}
}
if entity.Id != 0 {
gormx.UpdateById(entity)
} else {
gormx.Insert(entity)
if ms.Id != 0 {
return m.UpdateById(ms)
}
return m.Insert(ms)
}
// 根据id删除
func (m *machineScriptAppImpl) Delete(id uint64) {
m.machineScriptRepo.Delete(id)
m.DeleteById(id)
}

View File

@@ -2,21 +2,14 @@ package repository
import (
"mayfly-go/internal/machine/domain/entity"
"mayfly-go/pkg/base"
"mayfly-go/pkg/model"
)
type AuthCert interface {
GetPageList(condition *entity.AuthCertQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any]
base.Repo[*entity.AuthCert]
Insert(ac *entity.AuthCert)
GetPageList(condition *entity.AuthCertQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error)
Update(ac *entity.AuthCert)
GetById(id uint64) *entity.AuthCert
GetByIds(ids ...uint64) []*entity.AuthCert
GetByCondition(condition *entity.AuthCert, cols ...string) error
DeleteById(id uint64)
// GetByIds(ids ...uint64) []*entity.AuthCert
}

View File

@@ -3,22 +3,15 @@ package repository
import (
"mayfly-go/internal/machine/api/vo"
"mayfly-go/internal/machine/domain/entity"
"mayfly-go/pkg/base"
"mayfly-go/pkg/model"
)
type Machine interface {
base.Repo[*entity.Machine]
// 分页获取机器信息列表
GetMachineList(condition *entity.MachineQuery, pageParam *model.PageParam, toEntity *[]*vo.MachineVO, orderBy ...string) *model.PageResult[*[]*vo.MachineVO]
GetMachineList(condition *entity.MachineQuery, pageParam *model.PageParam, toEntity *[]*vo.MachineVO, orderBy ...string) (*model.PageResult[*[]*vo.MachineVO], error)
Count(condition *entity.MachineQuery) int64
// 根据条件获取账号信息
GetMachine(condition *entity.Machine, cols ...string) error
// 根据id获取
GetById(id uint64, cols ...string) *entity.Machine
Create(entity *entity.Machine)
UpdateById(entity *entity.Machine)
}

View File

@@ -2,41 +2,28 @@ package repository
import (
"mayfly-go/internal/machine/domain/entity"
"mayfly-go/pkg/base"
"mayfly-go/pkg/model"
)
type MachineCronJob interface {
GetPageList(condition *entity.MachineCronJob, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any]
base.Repo[*entity.MachineCronJob]
// 根据条件获取
GetBy(condition *entity.MachineCronJob, cols ...string) error
// 根据id获取
GetById(id uint64, cols ...string) *entity.MachineCronJob
Delete(id uint64)
Insert(entity *entity.MachineCronJob)
UpdateById(entity *entity.MachineCronJob)
GetPageList(condition *entity.MachineCronJob, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error)
}
type MachineCronJobRelate interface {
base.Repo[*entity.MachineCronJobRelate]
GetList(condition *entity.MachineCronJobRelate) []entity.MachineCronJobRelate
GetMachineIds(cronJobId uint64) []uint64
GetCronJobIds(machineId uint64) []uint64
Delete(condition *entity.MachineCronJobRelate)
BatchInsert(mcjrs []*entity.MachineCronJobRelate)
}
type MachineCronJobExec interface {
GetPageList(condition *entity.MachineCronJobExec, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any]
base.Repo[*entity.MachineCronJobExec]
Insert(mcje *entity.MachineCronJobExec)
Delete(m *entity.MachineCronJobExec)
GetPageList(condition *entity.MachineCronJobExec, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error)
}

View File

@@ -7,7 +7,7 @@ import (
type MachineFile interface {
// 分页获取机器脚本信息列表
GetPageList(condition *entity.MachineFile, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any]
GetPageList(condition *entity.MachineFile, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error)
// 根据条件获取
GetMachineFile(condition *entity.MachineFile, cols ...string) error
@@ -15,9 +15,9 @@ type MachineFile interface {
// 根据id获取
GetById(id uint64, cols ...string) *entity.MachineFile
Delete(id uint64)
Delete(id uint64) error
Create(entity *entity.MachineFile)
Create(entity *entity.MachineFile) error
UpdateById(entity *entity.MachineFile)
UpdateById(entity *entity.MachineFile) error
}

View File

@@ -2,22 +2,13 @@ package repository
import (
"mayfly-go/internal/machine/domain/entity"
"mayfly-go/pkg/base"
"mayfly-go/pkg/model"
)
type MachineScript interface {
base.Repo[*entity.MachineScript]
// 分页获取机器脚本信息列表
GetPageList(condition *entity.MachineScript, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any]
// 根据条件获取
GetMachineScript(condition *entity.MachineScript, cols ...string) error
// 根据id获取
GetById(id uint64, cols ...string) *entity.MachineScript
Delete(id uint64)
Create(entity *entity.MachineScript)
UpdateById(entity *entity.MachineScript)
GetPageList(condition *entity.MachineScript, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error)
}

View File

@@ -1,12 +1,11 @@
package machine
import (
"errors"
"fmt"
"mayfly-go/internal/common/consts"
"mayfly-go/internal/machine/domain/entity"
"mayfly-go/pkg/biz"
"mayfly-go/pkg/cache"
"mayfly-go/pkg/errorx"
"mayfly-go/pkg/logx"
"net"
"time"
@@ -87,10 +86,10 @@ func (c *Cli) Close() {
}
// 获取sftp client
func (c *Cli) GetSftpCli() *sftp.Client {
func (c *Cli) GetSftpCli() (*sftp.Client, error) {
if c.client == nil {
if err := c.connect(); err != nil {
panic(biz.NewBizErr("连接ssh失败" + err.Error()))
return nil, errorx.NewBiz("连接ssh失败: %s", err.Error())
}
}
sftpclient := c.sftpClient
@@ -98,13 +97,13 @@ func (c *Cli) GetSftpCli() *sftp.Client {
if sftpclient == nil {
sc, serr := sftp.NewClient(c.client)
if serr != nil {
panic(biz.NewBizErr("获取sftp client失败" + serr.Error()))
return nil, errorx.NewBiz("获取sftp client失败: %s", serr.Error())
}
sftpclient = sc
c.sftpClient = sftpclient
}
return sftpclient
return sftpclient, nil
}
// 获取session
@@ -172,15 +171,19 @@ func DeleteCli(id uint64) {
}
// 从缓存中获取客户端信息,不存在则回调获取机器信息函数,并新建
func GetCli(machineId uint64, getMachine func(uint64) *Info) (*Cli, error) {
func GetCli(machineId uint64, getMachine func(uint64) (*Info, error)) (*Cli, error) {
if load, ok := cliCache.Get(machineId); ok {
return load.(*Cli), nil
}
me := getMachine(machineId)
err := IfUseSshTunnelChangeIpPort(me, getMachine)
me, err := getMachine(machineId)
if err != nil {
return nil, fmt.Errorf("ssh隧道连接失败: %s", err.Error())
return nil, err
}
err = IfUseSshTunnelChangeIpPort(me, getMachine)
if err != nil {
return nil, errorx.NewBiz("ssh隧道连接失败: %s", err.Error())
}
c, err := newClient(me)
if err != nil {
@@ -194,7 +197,7 @@ func GetCli(machineId uint64, getMachine func(uint64) *Info) (*Cli, error) {
}
// 测试连接使用传值的方式而非引用。因为如果使用了ssh隧道则ip和端口会变为本地映射地址与端口
func TestConn(me Info, getSshTunnelMachine func(uint64) *Info) error {
func TestConn(me Info, getSshTunnelMachine func(uint64) (*Info, error)) error {
originId := me.Id
if originId == 0 {
// 随机设置一个ip如果使用了隧道则用于临时保存隧道
@@ -202,7 +205,9 @@ func TestConn(me Info, getSshTunnelMachine func(uint64) *Info) error {
}
err := IfUseSshTunnelChangeIpPort(&me, getSshTunnelMachine)
biz.ErrIsNilAppendErr(err, "ssh隧道连接失败: %s")
if err != nil {
return fmt.Errorf("ssh隧道连接失败: %s", err.Error())
}
if me.UseSshTunnel() {
defer CloseSshTunnelMachine(me.SshTunnelMachineId, me.Id)
}
@@ -215,11 +220,11 @@ func TestConn(me Info, getSshTunnelMachine func(uint64) *Info) error {
}
// 如果使用了ssh隧道则修改机器ip port为暴露的ip port
func IfUseSshTunnelChangeIpPort(me *Info, getMachine func(uint64) *Info) error {
func IfUseSshTunnelChangeIpPort(me *Info, getMachine func(uint64) (*Info, error)) error {
if !me.UseSshTunnel() {
return nil
}
sshTunnelMachine, err := GetSshTunnelMachine(me.SshTunnelMachineId, func(u uint64) *Info {
sshTunnelMachine, err := GetSshTunnelMachine(me.SshTunnelMachineId, func(u uint64) (*Info, error) {
return getMachine(u)
})
if err != nil {
@@ -272,7 +277,7 @@ func GetSshClient(m *Info) (*ssh.Client, error) {
// 根据机器信息创建客户端对象
func newClient(machine *Info) (*Cli, error) {
if machine == nil {
return nil, errors.New("机器不存在")
return nil, errorx.NewBiz("机器不存在")
}
logx.Infof("[%s]机器连接:%s:%d", machine.Name, machine.Ip, machine.Port)

View File

@@ -136,7 +136,7 @@ func (stm *SshTunnelMachine) Close() {
}
// 获取ssh隧道机器方便统一管理充当ssh隧道的机器避免创建多个ssh client
func GetSshTunnelMachine(machineId int, getMachine func(uint64) *Info) (*SshTunnelMachine, error) {
func GetSshTunnelMachine(machineId int, getMachine func(uint64) (*Info, error)) (*SshTunnelMachine, error) {
sshTunnelMachine := sshTunnelMachines[machineId]
if sshTunnelMachine != nil {
return sshTunnelMachine, nil
@@ -145,7 +145,11 @@ func GetSshTunnelMachine(machineId int, getMachine func(uint64) *Info) (*SshTunn
mutex.Lock()
defer mutex.Unlock()
me := getMachine(uint64(machineId))
me, err := getMachine(uint64(machineId))
if err != nil {
return nil, err
}
sshClient, err := GetSshClient(me)
if err != nil {
return nil, err

View File

@@ -3,49 +3,26 @@ package persistence
import (
"mayfly-go/internal/machine/domain/entity"
"mayfly-go/internal/machine/domain/repository"
"mayfly-go/pkg/biz"
"mayfly-go/pkg/base"
"mayfly-go/pkg/gormx"
"mayfly-go/pkg/model"
)
type authCertRepoImpl struct{}
func newAuthCertRepo() repository.AuthCert {
return new(authCertRepoImpl)
type authCertRepoImpl struct {
base.RepoImpl[*entity.AuthCert]
}
func (m *authCertRepoImpl) GetPageList(condition *entity.AuthCertQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any] {
func newAuthCertRepo() repository.AuthCert {
return &authCertRepoImpl{base.RepoImpl[*entity.AuthCert]{M: new(entity.AuthCert)}}
}
func (m *authCertRepoImpl) GetPageList(condition *entity.AuthCertQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error) {
qd := gormx.NewQuery(new(entity.AuthCert)).WithCondModel(condition).WithOrderBy(orderBy...)
return gormx.PageQuery(qd, pageParam, toEntity)
}
func (m *authCertRepoImpl) Insert(ac *entity.AuthCert) {
biz.ErrIsNil(gormx.Insert(ac), "新增授权凭证失败")
}
func (m *authCertRepoImpl) Update(ac *entity.AuthCert) {
biz.ErrIsNil(gormx.UpdateById(ac), "更新授权凭证失败")
}
func (m *authCertRepoImpl) GetById(id uint64) *entity.AuthCert {
ac := new(entity.AuthCert)
err := gormx.GetById(ac, id)
if err != nil {
return nil
}
return ac
}
func (m *authCertRepoImpl) GetByIds(ids ...uint64) []*entity.AuthCert {
acs := new([]*entity.AuthCert)
gormx.GetByIdIn(new(entity.AuthCert), acs, ids)
return *acs
}
func (m *authCertRepoImpl) GetByCondition(condition *entity.AuthCert, cols ...string) error {
return gormx.GetBy(condition, cols...)
}
func (m *authCertRepoImpl) DeleteById(id uint64) {
gormx.DeleteById(new(entity.AuthCert), id)
}
// func (m *authCertRepoImpl) GetByIds(ids ...uint64) []*entity.AuthCert {
// acs := new([]*entity.AuthCert)
// gormx.GetByIdIn(new(entity.AuthCert), acs, ids)
// return *acs
// }

View File

@@ -4,7 +4,7 @@ import (
"mayfly-go/internal/machine/api/vo"
"mayfly-go/internal/machine/domain/entity"
"mayfly-go/internal/machine/domain/repository"
"mayfly-go/pkg/biz"
"mayfly-go/pkg/base"
"mayfly-go/pkg/gormx"
"mayfly-go/pkg/model"
"mayfly-go/pkg/utils/collx"
@@ -12,14 +12,16 @@ import (
"strings"
)
type machineRepoImpl struct{}
type machineRepoImpl struct {
base.RepoImpl[*entity.Machine]
}
func newMachineRepo() repository.Machine {
return new(machineRepoImpl)
return &machineRepoImpl{base.RepoImpl[*entity.Machine]{M: new(entity.Machine)}}
}
// 分页获取机器信息列表
func (m *machineRepoImpl) GetMachineList(condition *entity.MachineQuery, pageParam *model.PageParam, toEntity *[]*vo.MachineVO, orderBy ...string) *model.PageResult[*[]*vo.MachineVO] {
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)).
Like("ip", condition.Ip).
Like("name", condition.Name).
@@ -44,28 +46,5 @@ func (m *machineRepoImpl) Count(condition *entity.MachineQuery) int64 {
where["tag_id"] = condition.TagIds
}
return gormx.CountByCond(new(entity.Machine), where)
}
// 根据条件获取账号信息
func (m *machineRepoImpl) GetMachine(condition *entity.Machine, cols ...string) error {
return gormx.GetBy(condition, cols...)
}
// 根据id获取
func (m *machineRepoImpl) GetById(id uint64, cols ...string) *entity.Machine {
machine := new(entity.Machine)
if err := gormx.GetById(machine, id, cols...); err != nil {
return nil
}
return machine
}
func (m *machineRepoImpl) Create(entity *entity.Machine) {
biz.ErrIsNilAppendErr(gormx.Insert(entity), "创建机器信息失败: %s")
}
func (m *machineRepoImpl) UpdateById(entity *entity.Machine) {
biz.ErrIsNilAppendErr(gormx.UpdateById(entity), "更新机器信息失败: %s")
return m.CountByCond(where)
}

View File

@@ -3,44 +3,21 @@ package persistence
import (
"mayfly-go/internal/machine/domain/entity"
"mayfly-go/internal/machine/domain/repository"
"mayfly-go/pkg/biz"
"mayfly-go/pkg/base"
"mayfly-go/pkg/gormx"
"mayfly-go/pkg/model"
)
type machineCropJobRepoImpl struct{}
type machineCropJobRepoImpl struct {
base.RepoImpl[*entity.MachineCronJob]
}
func newMachineCronJobRepo() repository.MachineCronJob {
return new(machineCropJobRepoImpl)
return &machineCropJobRepoImpl{base.RepoImpl[*entity.MachineCronJob]{M: new(entity.MachineCronJob)}}
}
// 分页获取机器信息列表
func (m *machineCropJobRepoImpl) GetPageList(condition *entity.MachineCronJob, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any] {
func (m *machineCropJobRepoImpl) GetPageList(condition *entity.MachineCronJob, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error) {
qd := gormx.NewQuery(condition).Like("name", condition.Name).Eq("status", condition.Status).WithOrderBy(orderBy...)
return gormx.PageQuery(qd, pageParam, toEntity)
}
func (m *machineCropJobRepoImpl) GetBy(cond *entity.MachineCronJob, cols ...string) error {
return gormx.GetBy(cond, cols...)
}
func (m *machineCropJobRepoImpl) GetById(id uint64, cols ...string) *entity.MachineCronJob {
res := new(entity.MachineCronJob)
if err := gormx.GetById(res, id, cols...); err == nil {
return res
} else {
return nil
}
}
func (m *machineCropJobRepoImpl) Delete(id uint64) {
biz.ErrIsNil(gormx.DeleteById(new(entity.MachineCronJob), id), "删除失败")
}
func (m *machineCropJobRepoImpl) Insert(entity *entity.MachineCronJob) {
gormx.Insert(entity)
}
func (m *machineCropJobRepoImpl) UpdateById(entity *entity.MachineCronJob) {
gormx.UpdateById(entity)
}

View File

@@ -3,26 +3,21 @@ 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 machineCropJobExecRepoImpl struct{}
type machineCropJobExecRepoImpl struct {
base.RepoImpl[*entity.MachineCronJobExec]
}
func newMachineCronJobExecRepo() repository.MachineCronJobExec {
return new(machineCropJobExecRepoImpl)
return &machineCropJobExecRepoImpl{base.RepoImpl[*entity.MachineCronJobExec]{M: new(entity.MachineCronJobExec)}}
}
// 分页获取机器信息列表
func (m *machineCropJobExecRepoImpl) GetPageList(condition *entity.MachineCronJobExec, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any] {
func (m *machineCropJobExecRepoImpl) GetPageList(condition *entity.MachineCronJobExec, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error) {
qd := gormx.NewQuery(condition).WithCondModel(condition).WithOrderBy(orderBy...)
return gormx.PageQuery(qd, pageParam, toEntity)
}
func (m *machineCropJobExecRepoImpl) Insert(entity *entity.MachineCronJobExec) {
gormx.Insert(entity)
}
func (m *machineCropJobExecRepoImpl) Delete(mcje *entity.MachineCronJobExec) {
gormx.DeleteByCondition(mcje)
}

View File

@@ -3,24 +3,27 @@ package persistence
import (
"mayfly-go/internal/machine/domain/entity"
"mayfly-go/internal/machine/domain/repository"
"mayfly-go/pkg/base"
"mayfly-go/pkg/gormx"
)
type machineCropJobRelateRepoImpl struct{}
type machineCropJobRelateRepoImpl struct {
base.RepoImpl[*entity.MachineCronJobRelate]
}
func newMachineCropJobRelateRepo() repository.MachineCronJobRelate {
return new(machineCropJobRelateRepoImpl)
return &machineCropJobRelateRepoImpl{base.RepoImpl[*entity.MachineCronJobRelate]{M: new(entity.MachineCronJobRelate)}}
}
func (m *machineCropJobRelateRepoImpl) GetList(condition *entity.MachineCronJobRelate) []entity.MachineCronJobRelate {
list := new([]entity.MachineCronJobRelate)
gormx.ListByOrder(condition, list)
m.ListByCond(condition, list)
return *list
}
func (m *machineCropJobRelateRepoImpl) GetMachineIds(cronJobId uint64) []uint64 {
var machineIds []uint64
gormx.ListBy(&entity.MachineCronJobRelate{CronJobId: cronJobId}, &machineIds, "machine_id")
m.ListByCond(&entity.MachineCronJobRelate{CronJobId: cronJobId}, &machineIds, "machine_id")
return machineIds
}
@@ -29,11 +32,3 @@ func (m *machineCropJobRelateRepoImpl) GetCronJobIds(machineId uint64) []uint64
gormx.ListBy(&entity.MachineCronJobRelate{MachineId: machineId}, &cronJobIds, "cron_job_id")
return cronJobIds
}
func (m *machineCropJobRelateRepoImpl) Delete(condition *entity.MachineCronJobRelate) {
gormx.DeleteByCondition(condition)
}
func (m *machineCropJobRelateRepoImpl) BatchInsert(mcjrs []*entity.MachineCronJobRelate) {
gormx.BatchInsert(mcjrs)
}

View File

@@ -3,7 +3,6 @@ package persistence
import (
"mayfly-go/internal/machine/domain/entity"
"mayfly-go/internal/machine/domain/repository"
"mayfly-go/pkg/biz"
"mayfly-go/pkg/gormx"
"mayfly-go/pkg/model"
)
@@ -15,7 +14,7 @@ func newMachineFileRepo() repository.MachineFile {
}
// 分页获取机器文件信息列表
func (m *machineFileRepoImpl) GetPageList(condition *entity.MachineFile, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any] {
func (m *machineFileRepoImpl) GetPageList(condition *entity.MachineFile, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error) {
qd := gormx.NewQuery(condition).WithCondModel(condition).WithOrderBy(orderBy...)
return gormx.PageQuery(qd, pageParam, toEntity)
}
@@ -35,14 +34,14 @@ func (m *machineFileRepoImpl) GetById(id uint64, cols ...string) *entity.Machine
}
// 根据id获取
func (m *machineFileRepoImpl) Delete(id uint64) {
biz.ErrIsNil(gormx.DeleteById(new(entity.MachineFile), id), "删除失败")
func (m *machineFileRepoImpl) Delete(id uint64) error {
return gormx.DeleteById(new(entity.MachineFile), id)
}
func (m *machineFileRepoImpl) Create(entity *entity.MachineFile) {
biz.ErrIsNil(gormx.Insert(entity), "新增机器文件配置失败")
func (m *machineFileRepoImpl) Create(entity *entity.MachineFile) error {
return gormx.Insert(entity)
}
func (m *machineFileRepoImpl) UpdateById(entity *entity.MachineFile) {
biz.ErrIsNil(gormx.UpdateById(entity), "更新机器文件失败")
func (m *machineFileRepoImpl) UpdateById(entity *entity.MachineFile) error {
return gormx.UpdateById(entity)
}

View File

@@ -3,47 +3,21 @@ package persistence
import (
"mayfly-go/internal/machine/domain/entity"
"mayfly-go/internal/machine/domain/repository"
"mayfly-go/pkg/biz"
"mayfly-go/pkg/base"
"mayfly-go/pkg/gormx"
"mayfly-go/pkg/model"
)
type machineScriptRepoImpl struct{}
type machineScriptRepoImpl struct {
base.RepoImpl[*entity.MachineScript]
}
func newMachineScriptRepo() repository.MachineScript {
return new(machineScriptRepoImpl)
return &machineScriptRepoImpl{base.RepoImpl[*entity.MachineScript]{M: new(entity.MachineScript)}}
}
// 分页获取机器信息列表
func (m *machineScriptRepoImpl) GetPageList(condition *entity.MachineScript, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any] {
func (m *machineScriptRepoImpl) GetPageList(condition *entity.MachineScript, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error) {
qd := gormx.NewQuery(condition).WithCondModel(condition).WithOrderBy(orderBy...)
return gormx.PageQuery(qd, pageParam, toEntity)
}
// 根据条件获取账号信息
func (m *machineScriptRepoImpl) GetMachineScript(condition *entity.MachineScript, cols ...string) error {
return gormx.GetBy(condition, cols...)
}
// 根据id获取
func (m *machineScriptRepoImpl) GetById(id uint64, cols ...string) *entity.MachineScript {
ms := new(entity.MachineScript)
if err := gormx.GetById(ms, id, cols...); err != nil {
return nil
}
return ms
}
// 根据id获取
func (m *machineScriptRepoImpl) Delete(id uint64) {
biz.ErrIsNil(gormx.DeleteById(new(entity.MachineScript), id), "删除失败")
}
func (m *machineScriptRepoImpl) Create(entity *entity.MachineScript) {
gormx.Insert(entity)
}
func (m *machineScriptRepoImpl) UpdateById(entity *entity.MachineScript) {
gormx.UpdateById(entity)
}

View File

@@ -37,7 +37,9 @@ func (m *Mongo) Mongos(rc *req.Ctx) {
}
queryCond.TagIds = tagIds
rc.ResData = m.MongoApp.GetPageList(queryCond, page, new([]entity.Mongo))
res, err := m.MongoApp.GetPageList(queryCond, page, new([]entity.Mongo))
biz.ErrIsNil(err)
rc.ResData = res
}
func (m *Mongo) MongoTags(rc *req.Ctx) {
@@ -56,7 +58,7 @@ func (m *Mongo) Save(rc *req.Ctx) {
rc.ReqParam = form
mongo.SetBaseInfo(rc.LoginAccount)
m.MongoApp.Save(mongo)
biz.ErrIsNil(m.MongoApp.Save(mongo))
}
func (m *Mongo) DeleteMongo(rc *req.Ctx) {

View File

@@ -8,6 +8,7 @@ import (
"mayfly-go/internal/machine/infrastructure/machine"
"mayfly-go/internal/mongo/domain/entity"
"mayfly-go/internal/mongo/domain/repository"
"mayfly-go/pkg/base"
"mayfly-go/pkg/biz"
"mayfly-go/pkg/cache"
"mayfly-go/pkg/logx"
@@ -23,21 +24,17 @@ import (
)
type Mongo interface {
base.App[*entity.Mongo]
// 分页获取机器脚本信息列表
GetPageList(condition *entity.MongoQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any]
GetPageList(condition *entity.MongoQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error)
Count(condition *entity.MongoQuery) int64
// 根据条件获取
GetBy(condition *entity.Mongo, cols ...string) error
// 根据id获取
GetById(id uint64, cols ...string) *entity.Mongo
Save(entity *entity.Mongo)
Save(entity *entity.Mongo) error
// 删除数据库信息
Delete(id uint64)
Delete(id uint64) error
// 获取mongo连接实例
// @param id mongo id
@@ -46,53 +43,45 @@ type Mongo interface {
func newMongoAppImpl(mongoRepo repository.Mongo) Mongo {
return &mongoAppImpl{
mongoRepo: mongoRepo,
base.AppImpl[*entity.Mongo, repository.Mongo]{Repo: mongoRepo},
}
}
type mongoAppImpl struct {
mongoRepo repository.Mongo
base.AppImpl[*entity.Mongo, repository.Mongo]
}
// 分页获取数据库信息列表
func (d *mongoAppImpl) GetPageList(condition *entity.MongoQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any] {
return d.mongoRepo.GetList(condition, pageParam, toEntity, orderBy...)
func (d *mongoAppImpl) GetPageList(condition *entity.MongoQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error) {
return d.GetRepo().GetList(condition, pageParam, toEntity, orderBy...)
}
func (d *mongoAppImpl) Count(condition *entity.MongoQuery) int64 {
return d.mongoRepo.Count(condition)
return d.GetRepo().Count(condition)
}
// 根据条件获取
func (d *mongoAppImpl) GetBy(condition *entity.Mongo, cols ...string) error {
return d.mongoRepo.Get(condition, cols...)
}
// 根据id获取
func (d *mongoAppImpl) GetById(id uint64, cols ...string) *entity.Mongo {
return d.mongoRepo.GetById(id, cols...)
}
func (d *mongoAppImpl) Delete(id uint64) {
d.mongoRepo.Delete(id)
func (d *mongoAppImpl) Delete(id uint64) error {
DeleteMongoCache(id)
return d.GetRepo().DeleteById(id)
}
func (d *mongoAppImpl) Save(m *entity.Mongo) {
func (d *mongoAppImpl) Save(m *entity.Mongo) error {
if m.Id == 0 {
d.mongoRepo.Insert(m)
} else {
// 先关闭连接
DeleteMongoCache(m.Id)
d.mongoRepo.Update(m)
return d.GetRepo().Insert(m)
}
// 先关闭连接
DeleteMongoCache(m.Id)
return d.GetRepo().UpdateById(m)
}
func (d *mongoAppImpl) GetMongoInst(id uint64) *MongoInstance {
mongoInstance, err := GetMongoInstance(id, func(u uint64) *entity.Mongo {
mongo := d.GetById(u)
biz.NotNil(mongo, "mongo信息不存在")
return mongo
mongoInstance, err := GetMongoInstance(id, func(u uint64) (*entity.Mongo, error) {
mongo, err := d.GetById(new(entity.Mongo), u)
if err != nil {
return nil, err
}
return mongo, nil
})
biz.ErrIsNilAppendErr(err, "连接mongo失败: %s")
return mongoInstance
@@ -122,9 +111,14 @@ func init() {
}
// 获取mongo的连接实例
func GetMongoInstance(mongoId uint64, getMongoEntity func(uint64) *entity.Mongo) (*MongoInstance, error) {
func GetMongoInstance(mongoId uint64, getMongoEntity func(uint64) (*entity.Mongo, error)) (*MongoInstance, error) {
mi, err := mongoCliCache.ComputeIfAbsent(mongoId, func(_ any) (any, error) {
c, err := connect(getMongoEntity(mongoId))
mongoEntity, err := getMongoEntity(mongoId)
if err != nil {
return nil, err
}
c, err := connect(mongoEntity)
if err != nil {
return nil, err
}
@@ -211,7 +205,11 @@ type MongoSshDialer struct {
}
func (sd *MongoSshDialer) DialContext(ctx context.Context, network, address string) (net.Conn, error) {
if sshConn, err := machineapp.GetMachineApp().GetSshTunnelMachine(sd.machineId).GetDialConn(network, address); err == nil {
stm, err := machineapp.GetMachineApp().GetSshTunnelMachine(sd.machineId)
if err != nil {
return nil, err
}
if sshConn, err := stm.GetDialConn(network, address); err == nil {
// 将ssh conn包装否则内部部设置超时会报错,ssh conn不支持设置超时会返回错误: ssh: tcpChan: deadline not supported
return &netx.WrapSshConn{Conn: sshConn}, nil
} else {

View File

@@ -2,24 +2,15 @@ package repository
import (
"mayfly-go/internal/mongo/domain/entity"
"mayfly-go/pkg/base"
"mayfly-go/pkg/model"
)
type Mongo interface {
base.Repo[*entity.Mongo]
// 分页获取列表
GetList(condition *entity.MongoQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any]
GetList(condition *entity.MongoQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error)
Count(condition *entity.MongoQuery) int64
// 根据条件获取
Get(condition *entity.Mongo, cols ...string) error
// 根据id获取
GetById(id uint64, cols ...string) *entity.Mongo
Insert(db *entity.Mongo)
Update(db *entity.Mongo)
Delete(id uint64)
}

View File

@@ -3,19 +3,21 @@ package persistence
import (
"mayfly-go/internal/mongo/domain/entity"
"mayfly-go/internal/mongo/domain/repository"
"mayfly-go/pkg/biz"
"mayfly-go/pkg/base"
"mayfly-go/pkg/gormx"
"mayfly-go/pkg/model"
)
type mongoRepoImpl struct{}
type mongoRepoImpl struct {
base.RepoImpl[*entity.Mongo]
}
func newMongoRepo() repository.Mongo {
return new(mongoRepoImpl)
return &mongoRepoImpl{base.RepoImpl[*entity.Mongo]{M: new(entity.Mongo)}}
}
// 分页获取数据库信息列表
func (d *mongoRepoImpl) GetList(condition *entity.MongoQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any] {
func (d *mongoRepoImpl) GetList(condition *entity.MongoQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error) {
qd := gormx.NewQuery(new(entity.Mongo)).
Like("name", condition.Name).
In("tag_id", condition.TagIds).
@@ -31,30 +33,3 @@ func (d *mongoRepoImpl) Count(condition *entity.MongoQuery) int64 {
}
return gormx.CountByCond(new(entity.Mongo), where)
}
// 根据条件获取
func (d *mongoRepoImpl) Get(condition *entity.Mongo, cols ...string) error {
return gormx.GetBy(condition, cols...)
}
// 根据id获取
func (d *mongoRepoImpl) GetById(id uint64, cols ...string) *entity.Mongo {
db := new(entity.Mongo)
if err := gormx.GetById(db, id, cols...); err != nil {
return nil
}
return db
}
func (d *mongoRepoImpl) Insert(db *entity.Mongo) {
biz.ErrIsNil(gormx.Insert(db), "新增mongo信息失败")
}
func (d *mongoRepoImpl) Update(db *entity.Mongo) {
biz.ErrIsNil(gormx.UpdateById(db), "更新mongo信息失败")
}
func (d *mongoRepoImpl) Delete(id uint64) {
gormx.DeleteById(new(entity.Mongo), id)
}

View File

@@ -3,6 +3,7 @@ package api
import (
"mayfly-go/internal/msg/application"
"mayfly-go/internal/msg/domain/entity"
"mayfly-go/pkg/biz"
"mayfly-go/pkg/ginx"
"mayfly-go/pkg/req"
)
@@ -16,5 +17,7 @@ func (m *Msg) GetMsgs(rc *req.Ctx) {
condition := &entity.Msg{
RecipientId: int64(rc.LoginAccount.Id),
}
rc.ResData = m.MsgApp.GetPageList(condition, ginx.GetPageParam(rc.GinCtx), new([]entity.Msg))
res, err := m.MsgApp.GetPageList(condition, ginx.GetPageParam(rc.GinCtx), new([]entity.Msg))
biz.ErrIsNil(err)
rc.ResData = res
}

View File

@@ -10,7 +10,7 @@ import (
)
type Msg interface {
GetPageList(condition *entity.Msg, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any]
GetPageList(condition *entity.Msg, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error)
Create(msg *entity.Msg)
@@ -28,7 +28,7 @@ type msgAppImpl struct {
msgRepo repository.Msg
}
func (a *msgAppImpl) GetPageList(condition *entity.Msg, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any] {
func (a *msgAppImpl) GetPageList(condition *entity.Msg, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error) {
return a.msgRepo.GetPageList(condition, pageParam, toEntity)
}

View File

@@ -2,11 +2,12 @@ package repository
import (
"mayfly-go/internal/msg/domain/entity"
"mayfly-go/pkg/base"
"mayfly-go/pkg/model"
)
type Msg interface {
GetPageList(condition *entity.Msg, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any]
base.Repo[*entity.Msg]
Insert(msg *entity.Msg)
GetPageList(condition *entity.Msg, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error)
}

View File

@@ -3,22 +3,20 @@ package persistence
import (
"mayfly-go/internal/msg/domain/entity"
"mayfly-go/internal/msg/domain/repository"
"mayfly-go/pkg/biz"
"mayfly-go/pkg/base"
"mayfly-go/pkg/gormx"
"mayfly-go/pkg/model"
)
type msgRepoImpl struct{}
func newMsgRepo() repository.Msg {
return new(msgRepoImpl)
type msgRepoImpl struct {
base.RepoImpl[*entity.Msg]
}
func (m *msgRepoImpl) GetPageList(condition *entity.Msg, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any] {
func newMsgRepo() repository.Msg {
return &msgRepoImpl{base.RepoImpl[*entity.Msg]{M: new(entity.Msg)}}
}
func (m *msgRepoImpl) GetPageList(condition *entity.Msg, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error) {
qd := gormx.NewQuery(condition).WithCondModel(condition).WithOrderBy(orderBy...)
return gormx.PageQuery(qd, pageParam, toEntity)
}
func (m *msgRepoImpl) Insert(account *entity.Msg) {
biz.ErrIsNil(gormx.Insert(account), "新增消息记录失败")
}

View File

@@ -48,7 +48,8 @@ func (r *Redis) ScanKeys(rc *req.Ctx) {
redisAddr := ri.Cli.Options().Addr
cursorRes[redisAddr] = form.Cursor[redisAddr]
for {
ks, cursor := ri.Scan(cursorRes[redisAddr], form.Match, form.Count)
ks, cursor, err := ri.Scan(cursorRes[redisAddr], form.Match, form.Count)
biz.ErrIsNil(err)
cursorRes[redisAddr] = cursor
if len(ks) > 0 {
// 返回了数据则追加总集合中

View File

@@ -37,7 +37,9 @@ func (r *Redis) RedisList(rc *req.Ctx) {
}
queryCond.TagIds = tagIds
rc.ResData = r.RedisApp.GetPageList(queryCond, page, new([]vo.Redis))
res, err := r.RedisApp.GetPageList(queryCond, page, new([]vo.Redis))
biz.ErrIsNil(err)
rc.ResData = res
}
func (r *Redis) RedisTags(rc *req.Ctx) {
@@ -58,13 +60,14 @@ func (r *Redis) Save(rc *req.Ctx) {
rc.ReqParam = form
redis.SetBaseInfo(rc.LoginAccount)
r.RedisApp.Save(redis)
biz.ErrIsNil(r.RedisApp.Save(redis))
}
// 获取redis实例密码由于数据库是加密存储故提供该接口展示原文密码
func (r *Redis) GetRedisPwd(rc *req.Ctx) {
rid := uint64(ginx.PathParamInt(rc.GinCtx, "id"))
re := r.RedisApp.GetById(rid, "Password")
re, err := r.RedisApp.GetById(new(entity.Redis), rid, "Password")
biz.ErrIsNil(err, "redis信息不存在")
re.PwdDecrypt()
rc.ResData = re.Password
}
@@ -83,7 +86,8 @@ func (r *Redis) DeleteRedis(rc *req.Ctx) {
func (r *Redis) RedisInfo(rc *req.Ctx) {
g := rc.GinCtx
ri := r.RedisApp.GetRedisInstance(uint64(ginx.PathParamInt(g, "id")), 0)
ri, err := r.RedisApp.GetRedisInstance(uint64(ginx.PathParamInt(g, "id")), 0)
biz.ErrIsNil(err)
section := rc.GinCtx.Query("section")
mode := ri.Info.Mode
@@ -116,7 +120,6 @@ func (r *Redis) RedisInfo(rc *req.Ctx) {
}
var res string
var err error
if section == "" {
res, err = redisCli.Info(ctx).Result()
} else {
@@ -161,7 +164,8 @@ func (r *Redis) RedisInfo(rc *req.Ctx) {
func (r *Redis) ClusterInfo(rc *req.Ctx) {
g := rc.GinCtx
ri := r.RedisApp.GetRedisInstance(uint64(ginx.PathParamInt(g, "id")), 0)
ri, err := r.RedisApp.GetRedisInstance(uint64(ginx.PathParamInt(g, "id")), 0)
biz.ErrIsNil(err)
biz.IsEquals(ri.Info.Mode, entity.RedisModeCluster, "非集群模式")
info, _ := ri.ClusterCli.ClusterInfo(context.Background()).Result()
nodesStr, _ := ri.ClusterCli.ClusterNodes(context.Background()).Result()
@@ -211,7 +215,8 @@ func (r *Redis) checkKeyAndGetRedisIns(rc *req.Ctx) (*application.RedisInstance,
}
func (r *Redis) getRedisIns(rc *req.Ctx) *application.RedisInstance {
ri := r.RedisApp.GetRedisInstance(getIdAndDbNum(rc.GinCtx))
ri, err := r.RedisApp.GetRedisInstance(getIdAndDbNum(rc.GinCtx))
biz.ErrIsNil(err)
biz.ErrIsNilAppendErr(r.TagApp.CanAccess(rc.LoginAccount.Id, ri.Info.TagPath), "%s")
return ri
}

View File

@@ -8,8 +8,9 @@ import (
"mayfly-go/internal/machine/infrastructure/machine"
"mayfly-go/internal/redis/domain/entity"
"mayfly-go/internal/redis/domain/repository"
"mayfly-go/pkg/biz"
"mayfly-go/pkg/base"
"mayfly-go/pkg/cache"
"mayfly-go/pkg/errorx"
"mayfly-go/pkg/logx"
"mayfly-go/pkg/model"
"mayfly-go/pkg/utils/netx"
@@ -23,61 +24,49 @@ import (
)
type Redis interface {
base.App[*entity.Redis]
// 分页获取机器脚本信息列表
GetPageList(condition *entity.RedisQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any]
GetPageList(condition *entity.RedisQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error)
Count(condition *entity.RedisQuery) int64
// 根据id获取
GetById(id uint64, cols ...string) *entity.Redis
// 根据条件获取
GetRedisBy(condition *entity.Redis, cols ...string) error
Save(entity *entity.Redis)
Save(entity *entity.Redis) error
// 删除数据库信息
Delete(id uint64)
Delete(id uint64) error
// 获取数据库连接实例
// id: 数据库实例id
// db: 库号
GetRedisInstance(id uint64, db int) *RedisInstance
GetRedisInstance(id uint64, db int) (*RedisInstance, error)
}
func newRedisApp(redisRepo repository.Redis) Redis {
return &redisAppImpl{
redisRepo: redisRepo,
base.AppImpl[*entity.Redis, repository.Redis]{Repo: redisRepo},
}
}
type redisAppImpl struct {
redisRepo repository.Redis
base.AppImpl[*entity.Redis, repository.Redis]
}
// 分页获取机器脚本信息列表
func (r *redisAppImpl) GetPageList(condition *entity.RedisQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any] {
return r.redisRepo.GetRedisList(condition, pageParam, toEntity, orderBy...)
func (r *redisAppImpl) GetPageList(condition *entity.RedisQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error) {
return r.GetRepo().GetRedisList(condition, pageParam, toEntity, orderBy...)
}
func (r *redisAppImpl) Count(condition *entity.RedisQuery) int64 {
return r.redisRepo.Count(condition)
return r.GetRepo().Count(condition)
}
// 根据id获取
func (r *redisAppImpl) GetById(id uint64, cols ...string) *entity.Redis {
return r.redisRepo.GetById(id, cols...)
}
// 根据条件获取
func (r *redisAppImpl) GetRedisBy(condition *entity.Redis, cols ...string) error {
return r.redisRepo.GetRedis(condition, cols...)
}
func (r *redisAppImpl) Save(re *entity.Redis) {
func (r *redisAppImpl) Save(re *entity.Redis) error {
// ’修改信息且密码不为空‘ or ‘新增’需要测试是否可连接
if (re.Id != 0 && re.Password != "") || re.Id == 0 {
TestRedisConnection(re)
if err := TestRedisConnection(re); err != nil {
return errorx.NewBiz("Redis连接失败: %s", err.Error())
}
}
// 查找是否存在该库
@@ -85,55 +74,61 @@ func (r *redisAppImpl) Save(re *entity.Redis) {
if re.SshTunnelMachineId > 0 {
oldRedis.SshTunnelMachineId = re.SshTunnelMachineId
}
err := r.GetRedisBy(oldRedis)
err := r.GetBy(oldRedis)
if re.Id == 0 {
biz.IsTrue(err != nil, "该实例已存在")
re.PwdEncrypt()
r.redisRepo.Insert(re)
} else {
// 如果存在该库,则校验修改的库是否为该库
if err == nil {
biz.IsTrue(oldRedis.Id == re.Id, "该实例已存在")
}
// 如果修改了redis实例的库信息则关闭旧库的连接
if oldRedis.Db != re.Db || oldRedis.SshTunnelMachineId != re.SshTunnelMachineId {
for _, dbStr := range strings.Split(oldRedis.Db, ",") {
db, _ := strconv.Atoi(dbStr)
CloseRedis(re.Id, db)
}
return errorx.NewBiz("该实例已存在")
}
re.PwdEncrypt()
r.redisRepo.Update(re)
return r.Insert(re)
}
// 如果存在该库,则校验修改的库是否为该库
if err == nil && oldRedis.Id != re.Id {
return errorx.NewBiz("该实例已存在")
}
// 如果修改了redis实例的库信息则关闭旧库的连接
if oldRedis.Db != re.Db || oldRedis.SshTunnelMachineId != re.SshTunnelMachineId {
for _, dbStr := range strings.Split(oldRedis.Db, ",") {
db, _ := strconv.Atoi(dbStr)
CloseRedis(re.Id, db)
}
}
re.PwdEncrypt()
return r.UpdateById(re)
}
// 删除Redis信息
func (r *redisAppImpl) Delete(id uint64) {
re := r.GetById(id)
biz.NotNil(re, "该redis信息不存在")
func (r *redisAppImpl) Delete(id uint64) error {
re, err := r.GetById(new(entity.Redis), id)
if err != nil {
return errorx.NewBiz("该redis信息不存在")
}
// 如果存在连接,则关闭所有库连接信息
for _, dbStr := range strings.Split(re.Db, ",") {
db, _ := strconv.Atoi(dbStr)
CloseRedis(re.Id, db)
}
r.redisRepo.Delete(id)
return r.DeleteById(id)
}
// 获取数据库连接实例
func (r *redisAppImpl) GetRedisInstance(id uint64, db int) *RedisInstance {
func (r *redisAppImpl) GetRedisInstance(id uint64, db int) (*RedisInstance, error) {
// Id不为0则为需要缓存
needCache := id != 0
if needCache {
load, ok := redisCache.Get(getRedisCacheKey(id, db))
if ok {
return load.(*RedisInstance)
return load.(*RedisInstance), nil
}
}
// 缓存不存在则回调获取redis信息
re := r.GetById(id)
re, err := r.GetById(new(entity.Redis), id)
if err != nil {
return nil, errorx.NewBiz("redis信息不存在")
}
re.PwdDecrypt()
biz.NotNil(re, "redis信息不存在")
redisMode := re.Mode
var ri *RedisInstance
@@ -143,7 +138,7 @@ func (r *redisAppImpl) GetRedisInstance(id uint64, db int) *RedisInstance {
_, e := ri.Cli.Ping(context.Background()).Result()
if e != nil {
ri.Close()
panic(biz.NewBizErr(fmt.Sprintf("redis连接失败: %s", e.Error())))
return nil, errorx.NewBiz("redis连接失败: %s", e.Error())
}
} else if redisMode == entity.RedisModeCluster {
ri = getRedisClusterClient(re)
@@ -151,7 +146,7 @@ func (r *redisAppImpl) GetRedisInstance(id uint64, db int) *RedisInstance {
_, e := ri.ClusterCli.Ping(context.Background()).Result()
if e != nil {
ri.Close()
panic(biz.NewBizErr(fmt.Sprintf("redis集群连接失败: %s", e.Error())))
return nil, errorx.NewBiz("redis集群连接失败: %s", e.Error())
}
} else if redisMode == entity.RedisModeSentinel {
ri = getRedisSentinelCient(re, db)
@@ -159,7 +154,7 @@ func (r *redisAppImpl) GetRedisInstance(id uint64, db int) *RedisInstance {
_, e := ri.Cli.Ping(context.Background()).Result()
if e != nil {
ri.Close()
panic(biz.NewBizErr(fmt.Sprintf("redis sentinel连接失败: %s", e.Error())))
return nil, errorx.NewBiz("redis sentinel连接失败: %s", e.Error())
}
}
@@ -167,7 +162,7 @@ func (r *redisAppImpl) GetRedisInstance(id uint64, db int) *RedisInstance {
if needCache {
redisCache.Put(getRedisCacheKey(id, db), ri)
}
return ri
return ri, nil
}
// 生成redis连接缓存key
@@ -240,8 +235,12 @@ func getRedisSentinelCient(re *entity.Redis, db int) *RedisInstance {
}
func getRedisDialer(machineId int) func(ctx context.Context, network, addr string) (net.Conn, error) {
sshTunnel := machineapp.GetMachineApp().GetSshTunnelMachine(machineId)
return func(_ context.Context, network, addr string) (net.Conn, error) {
sshTunnel, err := machineapp.GetMachineApp().GetSshTunnelMachine(machineId)
if err != nil {
return nil, err
}
if sshConn, err := sshTunnel.GetDialConn(network, addr); err == nil {
// 将ssh conn包装否则redis内部设置超时会报错,ssh conn不支持设置超时会返回错误: ssh: tcpChan: deadline not supported
return &netx.WrapSshConn{Conn: sshConn}, nil
@@ -279,7 +278,7 @@ func init() {
})
}
func TestRedisConnection(re *entity.Redis) {
func TestRedisConnection(re *entity.Redis) error {
var cmd redis.Cmdable
// 取第一个库测试连接即可
dbStr := strings.Split(re.Db, ",")[0]
@@ -300,7 +299,7 @@ func TestRedisConnection(re *entity.Redis) {
// 测试连接
_, e := cmd.Ping(context.Background()).Result()
biz.ErrIsNilAppendErr(e, "Redis连接失败: %s")
return e
}
type RedisInfo struct {
@@ -340,10 +339,8 @@ func (r *RedisInstance) GetCmdable() redis.Cmdable {
return nil
}
func (r *RedisInstance) Scan(cursor uint64, match string, count int64) ([]string, uint64) {
keys, newcursor, err := r.GetCmdable().Scan(context.Background(), cursor, match, count).Result()
biz.ErrIsNilAppendErr(err, "scan失败: %s")
return keys, newcursor
func (r *RedisInstance) Scan(cursor uint64, match string, count int64) ([]string, uint64, error) {
return r.GetCmdable().Scan(context.Background(), cursor, match, count).Result()
}
func (r *RedisInstance) Close() {

View File

@@ -2,23 +2,15 @@ package repository
import (
"mayfly-go/internal/redis/domain/entity"
"mayfly-go/pkg/base"
"mayfly-go/pkg/model"
)
type Redis interface {
base.Repo[*entity.Redis]
// 分页获取机器信息列表
GetRedisList(condition *entity.RedisQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any]
GetRedisList(condition *entity.RedisQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error)
Count(condition *entity.RedisQuery) int64
// 根据id获取
GetById(id uint64, cols ...string) *entity.Redis
GetRedis(condition *entity.Redis, cols ...string) error
Insert(redis *entity.Redis)
Update(redis *entity.Redis)
Delete(id uint64)
}

View File

@@ -3,19 +3,21 @@ package persistence
import (
"mayfly-go/internal/redis/domain/entity"
"mayfly-go/internal/redis/domain/repository"
"mayfly-go/pkg/biz"
"mayfly-go/pkg/base"
"mayfly-go/pkg/gormx"
"mayfly-go/pkg/model"
)
type redisRepoImpl struct{}
type redisRepoImpl struct {
base.RepoImpl[*entity.Redis]
}
func newRedisRepo() repository.Redis {
return new(redisRepoImpl)
return &redisRepoImpl{base.RepoImpl[*entity.Redis]{M: new(entity.Redis)}}
}
// 分页获取机器信息列表
func (r *redisRepoImpl) GetRedisList(condition *entity.RedisQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any] {
func (r *redisRepoImpl) GetRedisList(condition *entity.RedisQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error) {
qd := gormx.NewQuery(new(entity.Redis)).
Like("host", condition.Host).
In("tag_id", condition.TagIds).
@@ -32,28 +34,3 @@ func (r *redisRepoImpl) Count(condition *entity.RedisQuery) int64 {
return gormx.CountByCond(new(entity.Redis), where)
}
// 根据id获取
func (r *redisRepoImpl) GetById(id uint64, cols ...string) *entity.Redis {
rd := new(entity.Redis)
if err := gormx.GetById(rd, id, cols...); err != nil {
return nil
}
return rd
}
func (r *redisRepoImpl) GetRedis(condition *entity.Redis, cols ...string) error {
return gormx.GetBy(condition, cols...)
}
func (r *redisRepoImpl) Insert(redis *entity.Redis) {
biz.ErrIsNilAppendErr(gormx.Insert(redis), "新增失败: %s")
}
func (r *redisRepoImpl) Update(redis *entity.Redis) {
biz.ErrIsNilAppendErr(gormx.UpdateById(redis), "更新失败: %s")
}
func (r *redisRepoImpl) Delete(id uint64) {
biz.ErrIsNilAppendErr(gormx.DeleteById(new(entity.Redis), id), "删除失败: %s")
}

View File

@@ -39,7 +39,7 @@ func (a *Account) GetPermissions(rc *req.Ctx) {
var resources vo.AccountResourceVOList
// 获取账号菜单资源
a.ResourceApp.GetAccountResources(account.Id, &resources)
biz.ErrIsNil(a.ResourceApp.GetAccountResources(account.Id, &resources))
// 菜单树与权限code数组
var menus vo.AccountResourceVOList
var permissions []string
@@ -66,7 +66,7 @@ func (a *Account) ChangePassword(rc *req.Ctx) {
biz.ErrIsNilAppendErr(err, "解密旧密码错误: %s")
account := &entity.Account{Username: form.Username}
err = a.AccountApp.GetAccount(account, "Id", "Username", "Password", "Status")
err = a.AccountApp.GetBy(account, "Id", "Username", "Password", "Status")
biz.ErrIsNil(err, "旧密码错误")
biz.IsTrue(cryptox.CheckPwdHash(originOldPwd, account.Password), "旧密码错误")
biz.IsTrue(account.IsEnable(), "该账号不可用")
@@ -78,7 +78,7 @@ func (a *Account) ChangePassword(rc *req.Ctx) {
updateAccount := new(entity.Account)
updateAccount.Id = account.Id
updateAccount.Password = cryptox.PwdHash(originNewPwd)
a.AccountApp.Update(updateAccount)
biz.ErrIsNil(a.AccountApp.Update(updateAccount), "更新账号密码失败")
// 赋值loginAccount 主要用于记录操作日志,因为操作日志保存请求上下文没有该信息不保存日志
if rc.LoginAccount == nil {
@@ -111,13 +111,14 @@ func (a *Account) UpdateAccount(rc *req.Ctx) {
updateAccount.Password = cryptox.PwdHash(updateAccount.Password)
}
oldAcc := a.AccountApp.GetById(updateAccount.Id)
oldAcc, err := a.AccountApp.GetById(new(entity.Account), updateAccount.Id)
biz.ErrIsNil(err, "账号信息不存在")
// 账号创建十分钟内允许修改用户名兼容oauth2首次登录修改用户名否则不允许修改
if oldAcc.CreateTime.Add(10 * time.Minute).Before(time.Now()) {
// 禁止更新用户名,防止误传被更新
updateAccount.Username = ""
}
a.AccountApp.Update(updateAccount)
biz.ErrIsNil(a.AccountApp.Update(updateAccount))
}
/** 后台账号操作 **/
@@ -126,7 +127,9 @@ func (a *Account) UpdateAccount(rc *req.Ctx) {
func (a *Account) Accounts(rc *req.Ctx) {
condition := &entity.Account{}
condition.Username = rc.GinCtx.Query("username")
rc.ResData = a.AccountApp.GetPageList(condition, ginx.GetPageParam(rc.GinCtx), new([]vo.AccountManageVO))
res, err := a.AccountApp.GetPageList(condition, ginx.GetPageParam(rc.GinCtx), new([]vo.AccountManageVO))
biz.ErrIsNil(err)
rc.ResData = res
}
// @router /accounts
@@ -139,7 +142,7 @@ func (a *Account) SaveAccount(rc *req.Ctx) {
account.SetBaseInfo(rc.LoginAccount)
if account.Id == 0 {
a.AccountApp.Create(account)
biz.ErrIsNil(a.AccountApp.Create(account))
} else {
if account.Password != "" {
biz.IsTrue(utils.CheckAccountPasswordLever(account.Password), "密码强度必须8位以上且包含字⺟⼤⼩写+数字+特殊符号")
@@ -147,7 +150,7 @@ func (a *Account) SaveAccount(rc *req.Ctx) {
}
// 更新操作不允许修改用户名、防止误传更新
account.Username = ""
a.AccountApp.Update(account)
biz.ErrIsNil(a.AccountApp.Update(account))
}
}
@@ -158,7 +161,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)
a.AccountApp.Update(account)
biz.ErrIsNil(a.AccountApp.Update(account))
}
func (a *Account) DeleteAccount(rc *req.Ctx) {
@@ -169,7 +172,7 @@ func (a *Account) DeleteAccount(rc *req.Ctx) {
for _, v := range ids {
value, err := strconv.Atoi(v)
biz.ErrIsNilAppendErr(err, "string类型转换为int异常: %s")
a.AccountApp.Delete(uint64(value))
biz.ErrIsNilAppendErr(a.AccountApp.Delete(uint64(value)), "删除失败:%s")
}
}
@@ -188,7 +191,7 @@ func (a *Account) AccountRoles(rc *req.Ctx) {
func (a *Account) AccountResources(rc *req.Ctx) {
var resources vo.ResourceManageVOList
// 获取账号菜单资源
a.ResourceApp.GetAccountResources(uint64(ginx.PathParamInt(rc.GinCtx, "id")), &resources)
biz.ErrIsNil(a.ResourceApp.GetAccountResources(uint64(ginx.PathParamInt(rc.GinCtx, "id")), &resources))
rc.ResData = resources.ToTrees(0)
}
@@ -213,5 +216,5 @@ func (a *Account) ResetOtpSecret(rc *req.Ctx) {
accountId := uint64(ginx.PathParamInt(rc.GinCtx, "id"))
account.Id = accountId
rc.ReqParam = collx.Kvs("accountId", accountId)
a.AccountApp.Update(account)
biz.ErrIsNil(a.AccountApp.Update(account))
}

View File

@@ -1,12 +1,14 @@
package api
import (
"mayfly-go/pkg/biz"
"mayfly-go/pkg/captcha"
"mayfly-go/pkg/req"
"mayfly-go/pkg/utils/collx"
)
func GenerateCaptcha(rc *req.Ctx) {
id, image := captcha.Generate()
id, image, err := captcha.Generate()
biz.ErrIsNilAppendErr(err, "获取验证码错误: %s")
rc.ResData = collx.M{"base64Captcha": image, "cid": id}
}

View File

@@ -17,7 +17,9 @@ func (c *Config) Configs(rc *req.Ctx) {
g := rc.GinCtx
condition := &entity.Config{Key: g.Query("key")}
condition.Permission = rc.LoginAccount.Username
rc.ResData = c.ConfigApp.GetPageList(condition, ginx.GetPageParam(g), new([]entity.Config))
res, err := c.ConfigApp.GetPageList(condition, ginx.GetPageParam(g), new([]entity.Config))
biz.ErrIsNil(err)
rc.ResData = res
}
func (c *Config) GetConfigValueByKey(rc *req.Ctx) {
@@ -39,5 +41,5 @@ func (c *Config) SaveConfig(rc *req.Ctx) {
config := ginx.BindJsonAndCopyTo(rc.GinCtx, form, new(entity.Config))
rc.ReqParam = form
config.SetBaseInfo(rc.LoginAccount)
c.ConfigApp.Save(config)
biz.ErrIsNil(c.ConfigApp.Save(config))
}

View File

@@ -6,6 +6,7 @@ import (
"mayfly-go/internal/sys/api/vo"
"mayfly-go/internal/sys/application"
"mayfly-go/internal/sys/domain/entity"
"mayfly-go/pkg/biz"
"mayfly-go/pkg/ginx"
"mayfly-go/pkg/req"
"mayfly-go/pkg/utils/collx"
@@ -17,12 +18,14 @@ type Resource struct {
func (r *Resource) GetAllResourceTree(rc *req.Ctx) {
var resources vo.ResourceManageVOList
r.ResourceApp.GetResourceList(new(entity.Resource), &resources, "weight asc")
r.ResourceApp.ListByCondOrder(new(entity.Resource), &resources, "weight asc")
rc.ResData = resources.ToTrees(0)
}
func (r *Resource) GetById(rc *req.Ctx) {
rc.ResData = r.ResourceApp.GetById(uint64(ginx.PathParamInt(rc.GinCtx, "id")))
res, err := r.ResourceApp.GetById(new(entity.Resource), uint64(ginx.PathParamInt(rc.GinCtx, "id")))
biz.ErrIsNil(err, "该资源不存在")
rc.ResData = res
}
func (r *Resource) SaveResource(rc *req.Ctx) {
@@ -37,18 +40,18 @@ func (r *Resource) SaveResource(rc *req.Ctx) {
entity.Meta = string(bytes)
entity.SetBaseInfo(rc.LoginAccount)
r.ResourceApp.Save(entity)
biz.ErrIsNil(r.ResourceApp.Save(entity))
}
func (r *Resource) DelResource(rc *req.Ctx) {
r.ResourceApp.Delete(uint64(ginx.PathParamInt(rc.GinCtx, "id")))
biz.ErrIsNil(r.ResourceApp.Delete(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)
r.ResourceApp.ChangeStatus(rid, status)
biz.ErrIsNil(r.ResourceApp.ChangeStatus(rid, status))
}
func (r *Resource) Sort(rc *req.Ctx) {

View File

@@ -22,7 +22,9 @@ type Role struct {
func (r *Role) Roles(rc *req.Ctx) {
g := rc.GinCtx
condition := &entity.Role{Name: g.Query("name")}
rc.ResData = r.RoleApp.GetPageList(condition, ginx.GetPageParam(g), new([]entity.Role))
res, err := r.RoleApp.GetPageList(condition, ginx.GetPageParam(g), new([]entity.Role))
biz.ErrIsNil(err)
rc.ResData = res
}
// 保存角色信息

View File

@@ -3,6 +3,7 @@ package api
import (
"mayfly-go/internal/sys/application"
"mayfly-go/internal/sys/domain/entity"
"mayfly-go/pkg/biz"
"mayfly-go/pkg/ginx"
"mayfly-go/pkg/req"
)
@@ -13,5 +14,7 @@ type Syslog struct {
func (r *Syslog) Syslogs(rc *req.Ctx) {
queryCond, page := ginx.BindQueryAndPage[*entity.SysLogQuery](rc.GinCtx, new(entity.SysLogQuery))
rc.ResData = r.SyslogApp.GetPageList(queryCond, page, new([]entity.SysLog), "create_time DESC")
res, err := r.SyslogApp.GetPageList(queryCond, page, new([]entity.SysLog), "create_time DESC")
biz.ErrIsNil(err)
rc.ResData = res
}

View File

@@ -20,7 +20,7 @@ func (s *System) ConnectWs(g *gin.Context) {
defer func() {
if err := recover(); err != nil {
errInfo := anyx.ToString(err)
logx.Error("websocket连接失败: ", errInfo)
logx.Errorf("websocket连接失败: %s", errInfo)
if wsConn != nil {
wsConn.WriteMessage(websocket.TextMessage, []byte(errInfo))
wsConn.Close()

View File

@@ -3,7 +3,8 @@ package application
import (
"mayfly-go/internal/sys/domain/entity"
"mayfly-go/internal/sys/domain/repository"
"mayfly-go/pkg/biz"
"mayfly-go/pkg/base"
"mayfly-go/pkg/errorx"
"mayfly-go/pkg/gormx"
"mayfly-go/pkg/model"
"mayfly-go/pkg/utils/cryptox"
@@ -12,71 +13,60 @@ import (
)
type Account interface {
GetAccount(condition *entity.Account, cols ...string) error
base.App[*entity.Account]
GetById(id uint64) *entity.Account
GetPageList(condition *entity.Account, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error)
GetPageList(condition *entity.Account, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any]
Create(account *entity.Account) error
Create(account *entity.Account)
Update(account *entity.Account) error
Update(account *entity.Account)
Delete(id uint64)
Delete(id uint64) error
}
func newAccountApp(accountRepo repository.Account) Account {
return &accountAppImpl{
accountRepo: accountRepo,
}
return &accountAppImpl{base.AppImpl[*entity.Account, repository.Account]{Repo: accountRepo}}
}
type accountAppImpl struct {
accountRepo repository.Account
base.AppImpl[*entity.Account, repository.Account]
}
// 根据条件获取账号信息
func (a *accountAppImpl) GetAccount(condition *entity.Account, cols ...string) error {
return a.accountRepo.GetAccount(condition, cols...)
func (a *accountAppImpl) GetPageList(condition *entity.Account, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error) {
return a.GetRepo().GetPageList(condition, pageParam, toEntity)
}
func (a *accountAppImpl) GetById(id uint64) *entity.Account {
return a.accountRepo.GetById(id)
}
func (a *accountAppImpl) GetPageList(condition *entity.Account, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any] {
return a.accountRepo.GetPageList(condition, pageParam, toEntity)
}
func (a *accountAppImpl) Create(account *entity.Account) {
biz.IsTrue(a.GetAccount(&entity.Account{Username: account.Username}) != nil, "该账号用户名已存在")
func (a *accountAppImpl) Create(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
a.accountRepo.Insert(account)
return a.Insert(account)
}
func (a *accountAppImpl) Update(account *entity.Account) {
func (a *accountAppImpl) Update(account *entity.Account) error {
if account.Username != "" {
unAcc := &entity.Account{Username: account.Username}
err := a.GetAccount(unAcc)
biz.IsTrue(err != nil || unAcc.Id == account.Id, "该用户名已存在")
err := a.GetBy(unAcc)
if err == nil && unAcc.Id != account.Id {
return errorx.NewBiz("该用户名已存在")
}
}
a.accountRepo.Update(account)
return a.UpdateById(account)
}
func (a *accountAppImpl) Delete(id uint64) {
err := gormx.Tx(
func (a *accountAppImpl) Delete(id uint64) error {
return gormx.Tx(
func(db *gorm.DB) error {
// 删除account信息
return db.Delete(new(entity.Account), "id = ?", id).Error
// 删除account信息
return a.DeleteByIdWithDb(db, id)
},
func(db *gorm.DB) error {
// 删除账号关联的角色信息
accountRole := &entity.AccountRole{AccountId: id}
return db.Where(accountRole).Delete(accountRole).Error
return gormx.DeleteByWithDb(db, &entity.AccountRole{AccountId: id})
},
)
biz.ErrIsNilAppendErr(err, "删除失败:%s")
}

View File

@@ -4,8 +4,9 @@ import (
"encoding/json"
"mayfly-go/internal/sys/domain/entity"
"mayfly-go/internal/sys/domain/repository"
"mayfly-go/pkg/biz"
"mayfly-go/pkg/base"
"mayfly-go/pkg/cache"
"mayfly-go/pkg/errorx"
"mayfly-go/pkg/logx"
"mayfly-go/pkg/model"
"mayfly-go/pkg/utils/jsonx"
@@ -15,40 +16,48 @@ import (
const SysConfigKeyPrefix = "mayfly:sys:config:"
type Config interface {
GetPageList(condition *entity.Config, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any]
base.App[*entity.Config]
Save(config *entity.Config)
GetPageList(condition *entity.Config, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error)
Save(config *entity.Config) error
// GetConfig 获取指定key的配置信息, 不会返回nil, 若不存在则值都默认值即空字符串
GetConfig(key string) *entity.Config
}
func newConfigApp(configRepo repository.Config) Config {
return &configAppImpl{
configRepo: configRepo,
}
configApp := new(configAppImpl)
configApp.Repo = configRepo
return configApp
// return &configAppImpl{base.AppImpl[*entity.Config, repository.Config]{Repo: configRepo}}
}
type configAppImpl struct {
configRepo repository.Config
base.AppImpl[*entity.Config, repository.Config]
}
func (a *configAppImpl) GetPageList(condition *entity.Config, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any] {
return a.configRepo.GetPageList(condition, pageParam, toEntity)
func (a *configAppImpl) GetPageList(condition *entity.Config, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error) {
return a.GetRepo().GetPageList(condition, pageParam, toEntity)
}
func (a *configAppImpl) Save(config *entity.Config) {
func (a *configAppImpl) Save(config *entity.Config) error {
if config.Id == 0 {
a.configRepo.Insert(config)
if err := a.Insert(config); err != nil {
return err
}
} else {
oldConfig := a.GetConfig(config.Key)
if oldConfig.Permission != "all" {
biz.IsTrue(strings.Contains(oldConfig.Permission, config.Modifier), "您无权修改该配置")
if oldConfig.Permission != "all" && !strings.Contains(oldConfig.Permission, config.Modifier) {
return errorx.NewBiz("您无权修改该配置")
}
a.configRepo.Update(config)
if err := a.UpdateById(config); err != nil {
return err
}
}
cache.Del(SysConfigKeyPrefix + config.Key)
return nil
}
func (a *configAppImpl) GetConfig(key string) *entity.Config {
@@ -60,7 +69,7 @@ func (a *configAppImpl) GetConfig(key string) *entity.Config {
return config
}
if err := a.configRepo.GetConfig(config, "Id", "Key", "Value", "Permission"); err != nil {
if err := a.GetBy(config, "Id", "Key", "Value", "Permission"); err != nil {
logx.Warnf("不存在key = [%s] 的系统配置", key)
} else {
cache.SetStr(SysConfigKeyPrefix+key, jsonx.ToStr(config), -1)

View File

@@ -4,7 +4,8 @@ import (
"mayfly-go/internal/common/consts"
"mayfly-go/internal/sys/domain/entity"
"mayfly-go/internal/sys/domain/repository"
"mayfly-go/pkg/biz"
"mayfly-go/pkg/base"
"mayfly-go/pkg/errorx"
"mayfly-go/pkg/gormx"
"mayfly-go/pkg/utils/stringx"
"strings"
@@ -12,58 +13,54 @@ import (
)
type Resource interface {
GetResourceList(condition *entity.Resource, toEntity any, orderBy ...string)
base.App[*entity.Resource]
GetById(id uint64, cols ...string) *entity.Resource
Save(entity *entity.Resource) error
Save(entity *entity.Resource)
Delete(id uint64) error
ChangeStatus(resourceId uint64, status int8)
ChangeStatus(resourceId uint64, status int8) error
Sort(re *entity.Resource)
Sort(re *entity.Resource) error
Delete(id uint64)
GetAccountResources(accountId uint64, toEntity any)
GetAccountResources(accountId uint64, toEntity any) error
}
func newResourceApp(resourceRepo repository.Resource) Resource {
return &resourceAppImpl{
resourceRepo: resourceRepo,
base.AppImpl[*entity.Resource, repository.Resource]{Repo: resourceRepo},
}
}
type resourceAppImpl struct {
resourceRepo repository.Resource
base.AppImpl[*entity.Resource, repository.Resource]
}
func (r *resourceAppImpl) GetResourceList(condition *entity.Resource, toEntity any, orderBy ...string) {
r.resourceRepo.GetResourceList(condition, toEntity, orderBy...)
}
func (r *resourceAppImpl) GetById(id uint64, cols ...string) *entity.Resource {
return r.resourceRepo.GetById(id, cols...)
}
func (r *resourceAppImpl) Save(resource *entity.Resource) {
func (r *resourceAppImpl) Save(resource *entity.Resource) error {
// 更新操作
if resource.Id != 0 {
if resource.Code != "" {
oldRes := r.GetById(resource.Id, "Code")
oldRes, err := r.GetById(new(entity.Resource), resource.Id, "Code")
if err != nil {
return errorx.NewBiz("更新失败, 该资源不存在")
}
// 如果修改了code则校验新code是否存在
if oldRes.Code != resource.Code {
r.checkCode(resource.Code)
if err := r.checkCode(resource.Code); err != nil {
return err
}
}
}
gormx.UpdateById(resource)
return
return gormx.UpdateById(resource)
}
// 生成随机八位唯一标识符
ui := stringx.Rand(8)
if pid := resource.Pid; pid != 0 {
pResource := r.GetById(uint64(pid))
biz.IsTrue(pResource != nil, "该父资源不存在")
pResource, err := r.GetById(new(entity.Resource), uint64(pid))
if err != nil {
return errorx.NewBiz("该父资源不存在")
}
resource.UiPath = pResource.UiPath + ui + entity.ResourceUiPathSp
} else {
resource.UiPath = ui + entity.ResourceUiPathSp
@@ -72,27 +69,33 @@ func (r *resourceAppImpl) Save(resource *entity.Resource) {
if resource.Status == 0 {
resource.Status = entity.ResourceStatusEnable
}
r.checkCode(resource.Code)
if err := r.checkCode(resource.Code); err != nil {
return err
}
resource.Weight = int(time.Now().Unix())
gormx.Insert(resource)
return gormx.Insert(resource)
}
func (r *resourceAppImpl) ChangeStatus(resourceId uint64, status int8) {
resource := r.resourceRepo.GetById(resourceId)
biz.NotNil(resource, "资源不存在")
func (r *resourceAppImpl) ChangeStatus(resourceId uint64, status int8) error {
resource, err := r.GetById(new(entity.Resource), resourceId)
if err != nil {
return errorx.NewBiz("资源不存在")
}
resource.Status = status
r.resourceRepo.UpdateByUiPathLike(resource)
return r.GetRepo().UpdateByUiPathLike(resource)
}
func (r *resourceAppImpl) Sort(sortResource *entity.Resource) {
resource := r.resourceRepo.GetById(sortResource.Id)
biz.NotNil(resource, "资源不存在")
func (r *resourceAppImpl) Sort(sortResource *entity.Resource) error {
resource, err := r.GetById(new(entity.Resource), sortResource.Id)
if err != nil {
return errorx.NewBiz("资源不存在")
}
// 未改变父节点,则更新排序值即可
if sortResource.Pid == resource.Pid {
saveE := &entity.Resource{Weight: sortResource.Weight}
saveE.Id = sortResource.Id
r.Save(saveE)
return
return r.Save(saveE)
}
// 若资源原本唯一标识路径为xxxx/yyyy/zzzz/,则获取其父节点路径标识 xxxx/yyyy/ 与自身节点标识 zzzz/
@@ -109,12 +112,14 @@ func (r *resourceAppImpl) Sort(sortResource *entity.Resource) {
newParentResourceUiPath := ""
if sortResource.Pid != 0 {
newParentResource := r.resourceRepo.GetById(uint64(sortResource.Pid))
biz.NotNil(newParentResource, "父资源不存在")
newParentResource, err := r.GetById(new(entity.Resource), uint64(sortResource.Pid))
if err != nil {
return errorx.NewBiz("父资源不存在")
}
newParentResourceUiPath = newParentResource.UiPath
}
children := r.resourceRepo.GetChildren(resource.UiPath)
children := r.GetRepo().GetChildren(resource.UiPath)
for _, v := range children {
if v.Id == sortResource.Id {
continue
@@ -137,36 +142,43 @@ func (r *resourceAppImpl) Sort(sortResource *entity.Resource) {
}
condition := new(entity.Resource)
condition.Id = sortResource.Id
gormx.Updates(condition, updateMap)
return gormx.Updates(condition, updateMap)
}
func (r *resourceAppImpl) checkCode(code string) {
biz.IsTrue(!strings.Contains(code, ","), "code不能包含','")
biz.IsEquals(gormx.CountBy(&entity.Resource{Code: code}), int64(0), "code已存在")
func (r *resourceAppImpl) checkCode(code string) error {
if strings.Contains(code, ",") {
return errorx.NewBiz("code不能包含','")
}
if gormx.CountBy(&entity.Resource{Code: code}) == 0 {
return errorx.NewBiz("该code已存在")
}
return nil
}
func (r *resourceAppImpl) Delete(id uint64) {
resource := r.resourceRepo.GetById(id)
biz.NotNil(resource, "资源不存在")
func (r *resourceAppImpl) Delete(id uint64) error {
resource, err := r.GetById(new(entity.Resource), id)
if err != nil {
return errorx.NewBiz("资源不存在")
}
// 删除当前节点及其所有子节点
children := r.resourceRepo.GetChildren(resource.UiPath)
children := r.GetRepo().GetChildren(resource.UiPath)
for _, v := range children {
r.resourceRepo.Delete(v.Id)
r.GetRepo().DeleteById(v.Id)
// 删除角色关联的资源信息
gormx.DeleteByCondition(&entity.RoleResource{ResourceId: v.Id})
gormx.DeleteBy(&entity.RoleResource{ResourceId: v.Id})
}
return nil
}
func (r *resourceAppImpl) GetAccountResources(accountId uint64, toEntity any) {
func (r *resourceAppImpl) GetAccountResources(accountId uint64, toEntity any) error {
// 超级管理员返回所有
if accountId == consts.AdminId {
cond := &entity.Resource{
Status: entity.ResourceStatusEnable,
}
r.resourceRepo.GetResourceList(cond, toEntity, "pid asc", "weight asc")
return
return r.ListByCondOrder(cond, toEntity, "pid asc", "weight asc")
}
r.resourceRepo.GetAccountResources(accountId, toEntity)
return r.GetRepo().GetAccountResources(accountId, toEntity)
}

View File

@@ -10,14 +10,16 @@ import (
"mayfly-go/pkg/utils/collx"
"strings"
"time"
"gorm.io/gorm"
)
type Role interface {
GetPageList(condition *entity.Role, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any]
GetPageList(condition *entity.Role, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error)
SaveRole(role *entity.Role)
SaveRole(role *entity.Role) error
DeleteRole(id uint64)
DeleteRole(id uint64) error
GetRoleResourceIds(roleId uint64) []uint64
@@ -50,26 +52,32 @@ type roleAppImpl struct {
roleRepo repository.Role
}
func (m *roleAppImpl) GetPageList(condition *entity.Role, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any] {
func (m *roleAppImpl) GetPageList(condition *entity.Role, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error) {
return m.roleRepo.GetPageList(condition, pageParam, toEntity, orderBy...)
}
func (m *roleAppImpl) SaveRole(role *entity.Role) {
func (m *roleAppImpl) SaveRole(role *entity.Role) error {
role.Code = strings.ToUpper(role.Code)
if role.Id != 0 {
// code不可更改防止误传
role.Code = ""
gormx.UpdateById(role)
} else {
role.Status = 1
gormx.Insert(role)
return gormx.UpdateById(role)
}
role.Status = 1
return gormx.Insert(role)
}
func (m *roleAppImpl) DeleteRole(id uint64) {
m.roleRepo.Delete(id)
func (m *roleAppImpl) DeleteRole(id uint64) error {
// 删除角色与资源的关联关系
gormx.DeleteByCondition(&entity.RoleResource{RoleId: id})
return gormx.Tx(
func(db *gorm.DB) error {
return m.roleRepo.DeleteByIdWithDb(db, id)
},
func(db *gorm.DB) error {
return gormx.DeleteByWithDb(db, &entity.RoleResource{RoleId: id})
},
)
}
func (m *roleAppImpl) GetRoleResourceIds(roleId uint64) []uint64 {

View File

@@ -5,7 +5,7 @@ import (
"fmt"
"mayfly-go/internal/sys/domain/entity"
"mayfly-go/internal/sys/domain/repository"
"mayfly-go/pkg/biz"
"mayfly-go/pkg/errorx"
"mayfly-go/pkg/model"
"mayfly-go/pkg/req"
"mayfly-go/pkg/utils/anyx"
@@ -13,7 +13,7 @@ import (
)
type Syslog interface {
GetPageList(condition *entity.SysLogQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any]
GetPageList(condition *entity.SysLogQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error)
// 从请求上下文的参数保存系统日志
SaveFromReq(req *req.Ctx)
@@ -29,7 +29,7 @@ type syslogAppImpl struct {
syslogRepo repository.Syslog
}
func (m *syslogAppImpl) GetPageList(condition *entity.SysLogQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any] {
func (m *syslogAppImpl) GetPageList(condition *entity.SysLogQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error) {
return m.syslogRepo.GetPageList(condition, pageParam, toEntity, orderBy...)
}
@@ -64,7 +64,7 @@ func (m *syslogAppImpl) SaveFromReq(req *req.Ctx) {
syslog.Type = entity.SyslogTypeError
var errMsg string
switch t := err.(type) {
case *biz.BizError:
case errorx.BizError:
errMsg = fmt.Sprintf("errCode: %d, errMsg: %s", t.Code(), t.Error())
case error:
errMsg = t.Error()

View File

@@ -2,18 +2,12 @@ package repository
import (
"mayfly-go/internal/sys/domain/entity"
"mayfly-go/pkg/base"
"mayfly-go/pkg/model"
)
type Account interface {
// 根据条件获取账号信息
GetAccount(condition *entity.Account, cols ...string) error
base.Repo[*entity.Account]
GetById(id uint64) *entity.Account
GetPageList(condition *entity.Account, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any]
Insert(account *entity.Account)
Update(account *entity.Account)
GetPageList(condition *entity.Account, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error)
}

View File

@@ -2,17 +2,12 @@ package repository
import (
"mayfly-go/internal/sys/domain/entity"
"mayfly-go/pkg/base"
"mayfly-go/pkg/model"
)
type Config interface {
GetPageList(condition *entity.Config, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any]
base.Repo[*entity.Config]
Insert(config *entity.Config)
Update(config *entity.Config)
GetConfig(config *entity.Config, cols ...string) error
GetByCondition(condition *entity.Config, cols ...string) error
GetPageList(condition *entity.Config, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error)
}

View File

@@ -2,24 +2,18 @@ package repository
import (
"mayfly-go/internal/sys/domain/entity"
"mayfly-go/pkg/base"
)
type Resource interface {
// 获取资源列表
GetResourceList(condition *entity.Resource, toEntity any, orderBy ...string)
GetById(id uint64, cols ...string) *entity.Resource
Delete(id uint64)
GetByCondition(condition *entity.Resource, cols ...string) error
base.Repo[*entity.Resource]
// 获取账号资源列表
GetAccountResources(accountId uint64, toEntity any)
GetAccountResources(accountId uint64, toEntity any) error
// 获取所有子节点id
GetChildren(uiPath string) []entity.Resource
// 根据uiPath右匹配更新所有相关类资源
UpdateByUiPathLike(resource *entity.Resource)
UpdateByUiPathLike(resource *entity.Resource) error
}

View File

@@ -2,13 +2,14 @@ package repository
import (
"mayfly-go/internal/sys/domain/entity"
"mayfly-go/pkg/base"
"mayfly-go/pkg/model"
)
type Role interface {
GetPageList(condition *entity.Role, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any]
base.Repo[*entity.Role]
Delete(id uint64)
GetPageList(condition *entity.Role, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error)
// 获取角色拥有的资源id数组从role_resource表获取
GetRoleResourceIds(roleId uint64) []uint64

View File

@@ -2,11 +2,12 @@ package repository
import (
"mayfly-go/internal/sys/domain/entity"
"mayfly-go/pkg/base"
"mayfly-go/pkg/model"
)
type Syslog interface {
GetPageList(condition *entity.SysLogQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any]
base.Repo[*entity.SysLog]
Insert(log *entity.SysLog)
GetPageList(condition *entity.SysLogQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error)
}

View File

@@ -3,40 +3,22 @@ package persistence
import (
"mayfly-go/internal/sys/domain/entity"
"mayfly-go/internal/sys/domain/repository"
"mayfly-go/pkg/biz"
"mayfly-go/pkg/base"
"mayfly-go/pkg/gormx"
"mayfly-go/pkg/model"
)
type accountRepoImpl struct{}
type accountRepoImpl struct {
base.RepoImpl[*entity.Account]
}
func newAccountRepo() repository.Account {
return new(accountRepoImpl)
return &accountRepoImpl{base.RepoImpl[*entity.Account]{M: new(entity.Account)}}
}
func (a *accountRepoImpl) GetAccount(condition *entity.Account, cols ...string) error {
return gormx.GetBy(condition, cols...)
}
func (a *accountRepoImpl) GetById(id uint64) *entity.Account {
ac := new(entity.Account)
if err := gormx.GetById(ac, id); err != nil {
return nil
}
return ac
}
func (m *accountRepoImpl) GetPageList(condition *entity.Account, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any] {
func (m *accountRepoImpl) GetPageList(condition *entity.Account, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error) {
qd := gormx.NewQuery(new(entity.Account)).
Like("name", condition.Name).
Like("username", condition.Username)
return gormx.PageQuery(qd, pageParam, toEntity)
}
func (m *accountRepoImpl) Insert(account *entity.Account) {
biz.ErrIsNil(gormx.Insert(account), "新增账号信息失败")
}
func (m *accountRepoImpl) Update(account *entity.Account) {
biz.ErrIsNil(gormx.UpdateById(account), "更新账号信息失败")
}

View File

@@ -3,37 +3,23 @@ package persistence
import (
"mayfly-go/internal/sys/domain/entity"
"mayfly-go/internal/sys/domain/repository"
"mayfly-go/pkg/biz"
"mayfly-go/pkg/base"
"mayfly-go/pkg/gormx"
"mayfly-go/pkg/model"
)
type configRepoImpl struct{}
func newConfigRepo() repository.Config {
return new(configRepoImpl)
type configRepoImpl struct {
base.RepoImpl[*entity.Config]
}
func (m *configRepoImpl) GetPageList(condition *entity.Config, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any] {
func newConfigRepo() repository.Config {
return &configRepoImpl{base.RepoImpl[*entity.Config]{M: new(entity.Config)}}
}
func (m *configRepoImpl) GetPageList(condition *entity.Config, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error) {
qd := gormx.NewQuery(condition).
Eq("key", condition.Key).
And("permission = 'all' OR permission LIKE ?", "%"+condition.Permission+",%").
WithOrderBy(orderBy...)
return gormx.PageQuery(qd, pageParam, toEntity)
}
func (m *configRepoImpl) Insert(config *entity.Config) {
biz.ErrIsNil(gormx.Insert(config), "新增系统配置失败")
}
func (m *configRepoImpl) Update(config *entity.Config) {
biz.ErrIsNil(gormx.UpdateById(config), "更新系统配置失败")
}
func (m *configRepoImpl) GetConfig(condition *entity.Config, cols ...string) error {
return gormx.GetBy(condition, cols...)
}
func (r *configRepoImpl) GetByCondition(condition *entity.Config, cols ...string) error {
return gormx.GetBy(condition, cols...)
}

View File

@@ -3,35 +3,18 @@ package persistence
import (
"mayfly-go/internal/sys/domain/entity"
"mayfly-go/internal/sys/domain/repository"
"mayfly-go/pkg/biz"
"mayfly-go/pkg/base"
"mayfly-go/pkg/gormx"
)
type resourceRepoImpl struct{}
type resourceRepoImpl struct {
base.RepoImpl[*entity.Resource]
}
func newResourceRepo() repository.Resource {
return new(resourceRepoImpl)
}
func (r *resourceRepoImpl) GetResourceList(condition *entity.Resource, toEntity any, orderBy ...string) {
gormx.ListByOrder(condition, toEntity, orderBy...)
}
func (r *resourceRepoImpl) GetById(id uint64, cols ...string) *entity.Resource {
res := new(entity.Resource)
if err := gormx.GetById(res, id, cols...); err != nil {
return nil
return &resourceRepoImpl{
base.RepoImpl[*entity.Resource]{M: new(entity.Resource)},
}
return res
}
func (r *resourceRepoImpl) Delete(id uint64) {
biz.ErrIsNil(gormx.DeleteById(new(entity.Resource), id), "删除失败")
}
func (r *resourceRepoImpl) GetByCondition(condition *entity.Resource, cols ...string) error {
return gormx.GetBy(condition, cols...)
}
func (r *resourceRepoImpl) GetChildren(uiPath string) []entity.Resource {
@@ -41,12 +24,12 @@ func (r *resourceRepoImpl) GetChildren(uiPath string) []entity.Resource {
return rs
}
func (r *resourceRepoImpl) UpdateByUiPathLike(resource *entity.Resource) {
func (r *resourceRepoImpl) UpdateByUiPathLike(resource *entity.Resource) error {
sql := "UPDATE t_sys_resource SET status=? WHERE (ui_path LIKE ?)"
gormx.ExecSql(sql, resource.Status, resource.UiPath+"%")
return gormx.ExecSql(sql, resource.Status, resource.UiPath+"%")
}
func (r *resourceRepoImpl) GetAccountResources(accountId uint64, toEntity any) {
func (r *resourceRepoImpl) GetAccountResources(accountId uint64, toEntity any) error {
sql := `SELECT
m.id,
m.pid,
@@ -80,5 +63,5 @@ func (r *resourceRepoImpl) GetAccountResources(accountId uint64, toEntity any) {
ORDER BY
m.pid ASC,
m.weight ASC`
biz.ErrIsNilAppendErr(gormx.GetListBySql2Model(sql, toEntity, accountId), "查询账号资源失败: %s")
return gormx.GetListBySql2Model(sql, toEntity, accountId)
}

View File

@@ -3,26 +3,24 @@ package persistence
import (
"mayfly-go/internal/sys/domain/entity"
"mayfly-go/internal/sys/domain/repository"
"mayfly-go/pkg/biz"
"mayfly-go/pkg/base"
"mayfly-go/pkg/gormx"
"mayfly-go/pkg/model"
)
type roleRepoImpl struct{}
type roleRepoImpl struct {
base.RepoImpl[*entity.Role]
}
func newRoleRepo() repository.Role {
return new(roleRepoImpl)
return &roleRepoImpl{base.RepoImpl[*entity.Role]{M: new(entity.Role)}}
}
func (m *roleRepoImpl) GetPageList(condition *entity.Role, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any] {
func (m *roleRepoImpl) GetPageList(condition *entity.Role, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error) {
qd := gormx.NewQuery(condition).WithCondModel(condition).WithOrderBy(orderBy...)
return gormx.PageQuery(qd, pageParam, toEntity)
}
func (m *roleRepoImpl) Delete(id uint64) {
biz.ErrIsNil(gormx.DeleteById(new(entity.Role), id), "删除角色失败")
}
// 获取角色拥有的资源id数组从role_resource表获取
func (m *roleRepoImpl) GetRoleResourceIds(roleId uint64) []uint64 {
var rrs []entity.RoleResource
@@ -51,7 +49,7 @@ func (m *roleRepoImpl) SaveRoleResource(rr []*entity.RoleResource) {
}
func (m *roleRepoImpl) DeleteRoleResource(roleId uint64, resourceId uint64) {
gormx.DeleteByCondition(&entity.RoleResource{RoleId: roleId, ResourceId: resourceId})
gormx.DeleteBy(&entity.RoleResource{RoleId: roleId, ResourceId: resourceId})
}
func (m *roleRepoImpl) GetAccountRoleIds(accountId uint64) []uint64 {
@@ -72,7 +70,7 @@ func (m *roleRepoImpl) SaveAccountRole(ar *entity.AccountRole) {
}
func (m *roleRepoImpl) DeleteAccountRole(accountId, roleId uint64) {
gormx.DeleteByCondition(&entity.AccountRole{RoleId: roleId, AccountId: accountId})
gormx.DeleteBy(&entity.AccountRole{RoleId: roleId, AccountId: accountId})
}
// 获取账号角色信息列表

View File

@@ -3,22 +3,21 @@ package persistence
import (
"mayfly-go/internal/sys/domain/entity"
"mayfly-go/internal/sys/domain/repository"
"mayfly-go/pkg/base"
"mayfly-go/pkg/gormx"
"mayfly-go/pkg/model"
)
type syslogRepoImpl struct{}
func newSyslogRepo() repository.Syslog {
return new(syslogRepoImpl)
type syslogRepoImpl struct {
base.RepoImpl[*entity.SysLog]
}
func (m *syslogRepoImpl) GetPageList(condition *entity.SysLogQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any] {
func newSyslogRepo() repository.Syslog {
return &syslogRepoImpl{base.RepoImpl[*entity.SysLog]{M: new(entity.SysLog)}}
}
func (m *syslogRepoImpl) GetPageList(condition *entity.SysLogQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error) {
qd := gormx.NewQuery(new(entity.SysLog)).Like("description", condition.Description).
Eq("creator_id", condition.CreatorId).Eq("type", condition.Type).WithOrderBy(orderBy...)
return gormx.PageQuery(qd, pageParam, toEntity)
}
func (m *syslogRepoImpl) Insert(syslog *entity.SysLog) {
gormx.Insert(syslog)
}

View File

@@ -5,6 +5,7 @@ import (
"mayfly-go/internal/tag/api/vo"
"mayfly-go/internal/tag/application"
"mayfly-go/internal/tag/domain/entity"
"mayfly-go/pkg/biz"
"mayfly-go/pkg/ginx"
"mayfly-go/pkg/req"
"strings"
@@ -47,11 +48,11 @@ func (p *TagTree) SaveTagTree(rc *req.Ctx) {
loginAccount := rc.LoginAccount
tagTree.SetBaseInfo(loginAccount)
p.TagTreeApp.Save(tagTree)
rc.ReqParam = fmt.Sprintf("tagTreeId: %d, tagName: %s, codePath: %s", tagTree.Id, tagTree.Name, tagTree.CodePath)
biz.ErrIsNil(p.TagTreeApp.Save(tagTree))
}
func (p *TagTree) DelTagTree(rc *req.Ctx) {
p.TagTreeApp.Delete(uint64(ginx.PathParamInt(rc.GinCtx, "id")))
biz.ErrIsNil(p.TagTreeApp.Delete(uint64(ginx.PathParamInt(rc.GinCtx, "id"))))
}

View File

@@ -24,7 +24,9 @@ type Team struct {
func (p *Team) GetTeams(rc *req.Ctx) {
teams := &[]entity.Team{}
rc.ResData = p.TeamApp.GetPageList(&entity.Team{}, ginx.GetPageParam(rc.GinCtx), teams)
res, err := p.TeamApp.GetPageList(&entity.Team{}, ginx.GetPageParam(rc.GinCtx), teams)
biz.ErrIsNil(err)
rc.ResData = res
}
func (p *Team) SaveTeam(rc *req.Ctx) {
@@ -66,7 +68,9 @@ func (p *Team) GetTeamMembers(rc *req.Ctx) {
condition := &entity.TeamMember{TeamId: uint64(ginx.PathParamInt(rc.GinCtx, "id"))}
condition.Username = rc.GinCtx.Query("username")
rc.ResData = p.TeamApp.GetMemberPage(condition, ginx.GetPageParam(rc.GinCtx), &[]vo.TeamMember{})
res, err := p.TeamApp.GetMemberPage(condition, ginx.GetPageParam(rc.GinCtx), &[]vo.TeamMember{})
biz.ErrIsNil(err)
rc.ResData = res
}
// 保存团队信息
@@ -84,7 +88,7 @@ func (p *Team) SaveTeamMember(rc *req.Ctx) {
// 校验账号并赋值username
account := &sys_entity.Account{}
account.Id = accountId
biz.ErrIsNil(p.AccountApp.GetAccount(account, "Id", "Username"), "账号不存在")
biz.ErrIsNil(p.AccountApp.GetBy(account, "Id", "Username"), "账号不存在")
teamMember := new(entity.TeamMember)
teamMember.TeamId = teamId
@@ -132,8 +136,8 @@ func (p *Team) SaveTags(rc *req.Ctx) {
loginAccount := rc.LoginAccount
for _, v := range addIds {
tagId := v
tag := p.TagApp.GetById(tagId)
biz.NotNil(tag, "存在非法标签id")
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)

View File

@@ -11,20 +11,21 @@ import (
redisentity "mayfly-go/internal/redis/domain/entity"
"mayfly-go/internal/tag/domain/entity"
"mayfly-go/internal/tag/domain/repository"
"mayfly-go/pkg/biz"
"mayfly-go/pkg/base"
"mayfly-go/pkg/errorx"
"mayfly-go/pkg/global"
"mayfly-go/pkg/gormx"
"strings"
)
type TagTree interface {
base.App[*entity.TagTree]
ListByQuery(condition *entity.TagTreeQuery, toEntity any)
GetById(id uint64) *entity.TagTree
Save(tt *entity.TagTree) error
Save(tt *entity.TagTree)
Delete(id uint64)
Delete(id uint64) error
// 获取账号id拥有的可访问的标签id
ListTagIdByAccountId(accountId uint64) []uint64
@@ -52,18 +53,20 @@ func newTagTreeApp(tagTreeRepo repository.TagTree,
redisApp redisapp.Redis,
dbApp dbapp.Db,
mongoApp mongoapp.Mongo) TagTree {
return &tagTreeAppImpl{
tagTreeRepo: tagTreeRepo,
tagTreeApp := &tagTreeAppImpl{
tagTreeTeamRepo: tagTreeTeamRepo,
machineApp: machineApp,
redisApp: redisApp,
dbApp: dbApp,
mongoApp: mongoApp,
}
tagTreeApp.Repo = tagTreeRepo
return tagTreeApp
}
type tagTreeAppImpl struct {
tagTreeRepo repository.TagTree
base.AppImpl[*entity.TagTree, repository.TagTree]
tagTreeTeamRepo repository.TagTreeTeam
machineApp machineapp.Machine
redisApp redisapp.Redis
@@ -71,38 +74,39 @@ type tagTreeAppImpl struct {
dbApp dbapp.Db
}
func (p *tagTreeAppImpl) Save(tag *entity.TagTree) {
func (p *tagTreeAppImpl) Save(tag *entity.TagTree) error {
// 新建项目树节点信息
if tag.Id == 0 {
biz.IsTrue(!strings.Contains(tag.Code, entity.CodePathSeparator), "标识符不能包含'/'")
if strings.Contains(tag.Code, entity.CodePathSeparator) {
return errorx.NewBiz("标识符不能包含'/'")
}
if tag.Pid != 0 {
parentTag := p.tagTreeRepo.SelectById(tag.Pid)
biz.NotNil(parentTag, "父节点不存在")
parentTag, err := p.GetById(new(entity.TagTree), tag.Pid)
if err != nil {
return errorx.NewBiz("父节点不存在")
}
tag.CodePath = parentTag.CodePath + tag.Code + entity.CodePathSeparator
} else {
tag.CodePath = tag.Code + entity.CodePathSeparator
}
// 判断该路径是否存在
var hasLikeTags []entity.TagTree
p.tagTreeRepo.SelectByCondition(&entity.TagTreeQuery{CodePathLike: tag.CodePath}, &hasLikeTags)
biz.IsTrue(len(hasLikeTags) == 0, "已存在该标签路径开头的标签, 请修改该标识code")
p.GetRepo().SelectByCondition(&entity.TagTreeQuery{CodePathLike: tag.CodePath}, &hasLikeTags)
if len(hasLikeTags) > 0 {
return errorx.NewBiz("已存在该标签路径开头的标签, 请修改该标识code")
}
p.tagTreeRepo.Insert(tag)
return
return p.GetRepo().Insert(tag)
}
// 防止误传导致被更新
tag.Code = ""
tag.CodePath = ""
p.tagTreeRepo.UpdateById(tag)
return p.GetRepo().UpdateById(tag)
}
func (p *tagTreeAppImpl) ListByQuery(condition *entity.TagTreeQuery, toEntity any) {
p.tagTreeRepo.SelectByCondition(condition, toEntity)
}
func (p *tagTreeAppImpl) GetById(tagId uint64) *entity.TagTree {
return p.tagTreeRepo.SelectById(tagId)
p.GetRepo().SelectByCondition(condition, toEntity)
}
func (p *tagTreeAppImpl) ListTagIdByAccountId(accountId uint64) []uint64 {
@@ -112,7 +116,7 @@ func (p *tagTreeAppImpl) ListTagIdByAccountId(accountId uint64) []uint64 {
func (p *tagTreeAppImpl) ListTagByPath(tagPaths ...string) []entity.TagTree {
var tags []entity.TagTree
p.tagTreeRepo.SelectByCondition(&entity.TagTreeQuery{CodePathLikes: tagPaths}, &tags)
p.GetRepo().SelectByCondition(&entity.TagTreeQuery{CodePathLikes: tagPaths}, &tags)
return tags
}
@@ -154,16 +158,25 @@ func (p *tagTreeAppImpl) CanAccess(accountId uint64, tagPath string) error {
}
}
return biz.NewBizErr("您无权操作该资源")
return errorx.NewBiz("您无权操作该资源")
}
func (p *tagTreeAppImpl) Delete(id uint64) {
func (p *tagTreeAppImpl) Delete(id uint64) error {
tagIds := [1]uint64{id}
biz.IsTrue(p.machineApp.Count(&machineentity.MachineQuery{TagIds: tagIds[:]}) == 0, "请先删除该项目关联的机器信息")
biz.IsTrue(p.redisApp.Count(&redisentity.RedisQuery{TagIds: tagIds[:]}) == 0, "请先删除该项目关联的redis信息")
biz.IsTrue(p.dbApp.Count(&dbentity.DbQuery{TagIds: tagIds[:]}) == 0, "请先删除该项目关联的数据库信息")
biz.IsTrue(p.mongoApp.Count(&mongoentity.MongoQuery{TagIds: tagIds[:]}) == 0, "请先删除该项目关联的Mongo信息")
p.tagTreeRepo.Delete(id)
if p.machineApp.Count(&machineentity.MachineQuery{TagIds: tagIds[:]}) > 0 {
return errorx.NewBiz("请先删除该标签关联的机器信息")
}
if p.redisApp.Count(&redisentity.RedisQuery{TagIds: tagIds[:]}) > 0 {
return errorx.NewBiz("请先删除该标签关联的redis信息")
}
if p.dbApp.Count(&dbentity.DbQuery{TagIds: tagIds[:]}) > 0 {
return errorx.NewBiz("请先删除该标签关联的数据库信息")
}
if p.mongoApp.Count(&mongoentity.MongoQuery{TagIds: tagIds[:]}) > 0 {
return errorx.NewBiz("请先删除该标签关联的Mongo信息")
}
p.DeleteById(id)
// 删除该标签关联的团队信息
p.tagTreeTeamRepo.DeleteBy(&entity.TagTreeTeam{TagId: id})
return p.tagTreeTeamRepo.DeleteByCond(&entity.TagTreeTeam{TagId: id})
}

View File

@@ -4,20 +4,23 @@ import (
"mayfly-go/internal/tag/domain/entity"
"mayfly-go/internal/tag/domain/repository"
"mayfly-go/pkg/biz"
"mayfly-go/pkg/gormx"
"mayfly-go/pkg/model"
"gorm.io/gorm"
)
type Team interface {
// 分页获取项目团队信息列表
GetPageList(condition *entity.Team, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any]
GetPageList(condition *entity.Team, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error)
Save(team *entity.Team)
Save(team *entity.Team) error
Delete(id uint64)
Delete(id uint64) error
//--------------- 团队成员相关接口 ---------------
GetMemberPage(condition *entity.TeamMember, pageParam *model.PageParam, toEntity any) *model.PageResult[any]
GetMemberPage(condition *entity.TeamMember, pageParam *model.PageParam, toEntity any) (*model.PageResult[any], error)
SaveMember(tagTeamMember *entity.TeamMember)
@@ -29,9 +32,9 @@ type Team interface {
ListTagIds(teamId uint64) []uint64
SaveTag(tagTeam *entity.TagTreeTeam)
SaveTag(tagTeam *entity.TagTreeTeam) error
DeleteTag(teamId, tagId uint64)
DeleteTag(teamId, tagId uint64) error
}
func newTeamApp(teamRepo repository.Team,
@@ -51,27 +54,34 @@ type teamAppImpl struct {
tagTreeTeamRepo repository.TagTreeTeam
}
func (p *teamAppImpl) GetPageList(condition *entity.Team, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any] {
func (p *teamAppImpl) GetPageList(condition *entity.Team, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error) {
return p.teamRepo.GetPageList(condition, pageParam, toEntity, orderBy...)
}
func (p *teamAppImpl) Save(team *entity.Team) {
func (p *teamAppImpl) Save(team *entity.Team) error {
if team.Id == 0 {
p.teamRepo.Insert(team)
} else {
p.teamRepo.UpdateById(team)
return p.teamRepo.Insert(team)
}
return p.teamRepo.UpdateById(team)
}
func (p *teamAppImpl) Delete(id uint64) {
p.teamRepo.Delete(id)
p.teamMemberRepo.DeleteBy(&entity.TeamMember{TeamId: id})
p.tagTreeTeamRepo.DeleteBy(&entity.TagTreeTeam{TeamId: id})
func (p *teamAppImpl) Delete(id uint64) error {
return gormx.Tx(
func(db *gorm.DB) error {
return p.teamRepo.DeleteByIdWithDb(db, id)
},
func(db *gorm.DB) error {
return p.teamMemberRepo.DeleteByCondWithDb(db, &entity.TeamMember{TeamId: id})
},
func(db *gorm.DB) error {
return p.tagTreeTeamRepo.DeleteByCondWithDb(db, &entity.TagTreeTeam{TeamId: id})
},
)
}
// --------------- 团队成员相关接口 ---------------
func (p *teamAppImpl) GetMemberPage(condition *entity.TeamMember, pageParam *model.PageParam, toEntity any) *model.PageResult[any] {
func (p *teamAppImpl) GetMemberPage(condition *entity.TeamMember, pageParam *model.PageParam, toEntity any) (*model.PageResult[any], error) {
return p.teamMemberRepo.GetPageList(condition, pageParam, toEntity)
}
@@ -79,12 +89,12 @@ func (p *teamAppImpl) GetMemberPage(condition *entity.TeamMember, pageParam *mod
func (p *teamAppImpl) SaveMember(teamMember *entity.TeamMember) {
teamMember.Id = 0
biz.IsTrue(!p.teamMemberRepo.IsExist(teamMember.TeamId, teamMember.AccountId), "该成员已存在")
p.teamMemberRepo.Save(teamMember)
p.teamMemberRepo.Insert(teamMember)
}
// 删除团队成员信息
func (p *teamAppImpl) DeleteMember(teamId, accountId uint64) {
p.teamMemberRepo.DeleteBy(&entity.TeamMember{TeamId: teamId, AccountId: accountId})
p.teamMemberRepo.DeleteByCond(&entity.TeamMember{TeamId: teamId, AccountId: accountId})
}
func (p *teamAppImpl) IsExistMember(teamId, accounId uint64) bool {
@@ -95,7 +105,7 @@ func (p *teamAppImpl) IsExistMember(teamId, accounId uint64) bool {
func (p *teamAppImpl) ListTagIds(teamId uint64) []uint64 {
tags := &[]entity.TagTreeTeam{}
p.tagTreeTeamRepo.ListTag(&entity.TagTreeTeam{TeamId: teamId}, tags)
p.tagTreeTeamRepo.ListByCondOrder(&entity.TagTreeTeam{TeamId: teamId}, tags)
ids := make([]uint64, 0)
for _, v := range *tags {
ids = append(ids, v.TagId)
@@ -104,12 +114,12 @@ func (p *teamAppImpl) ListTagIds(teamId uint64) []uint64 {
}
// 保存关联项目信息
func (p *teamAppImpl) SaveTag(tagTreeTeam *entity.TagTreeTeam) {
func (p *teamAppImpl) SaveTag(tagTreeTeam *entity.TagTreeTeam) error {
tagTreeTeam.Id = 0
p.tagTreeTeamRepo.Save(tagTreeTeam)
return p.tagTreeTeamRepo.Insert(tagTreeTeam)
}
// 删除关联项目信息
func (p *teamAppImpl) DeleteTag(teamId, tagId uint64) {
p.tagTreeTeamRepo.DeleteBy(&entity.TagTreeTeam{TeamId: teamId, TagId: tagId})
func (p *teamAppImpl) DeleteTag(teamId, tagId uint64) error {
return p.tagTreeTeamRepo.DeleteByCond(&entity.TagTreeTeam{TeamId: teamId, TagId: tagId})
}

View File

@@ -2,20 +2,12 @@ package repository
import (
"mayfly-go/internal/tag/domain/entity"
"mayfly-go/pkg/base"
)
type TagTree interface {
base.Repo[*entity.TagTree]
// 根据条件查询
SelectByCondition(condition *entity.TagTreeQuery, toEntity any, orderBy ...string)
GetBy(condition *entity.TagTree, cols ...string) error
// 根据主键查询若不存在返回nil
SelectById(id uint64) *entity.TagTree
Insert(p *entity.TagTree)
UpdateById(p *entity.TagTree)
Delete(id uint64)
}

View File

@@ -1,15 +1,15 @@
package repository
import "mayfly-go/internal/tag/domain/entity"
import (
"mayfly-go/internal/tag/domain/entity"
"mayfly-go/pkg/base"
)
type TagTreeTeam interface {
base.Repo[*entity.TagTreeTeam]
// 获取团队标签信息列表
ListTag(condition *entity.TagTreeTeam, toEntity any, orderBy ...string)
Save(mp *entity.TagTreeTeam)
DeleteBy(condition *entity.TagTreeTeam)
// ListTag(condition *entity.TagTreeTeam, toEntity any, orderBy ...string)
SelectTagPathsByAccountId(accountId uint64) []string
}

View File

@@ -2,17 +2,12 @@ package repository
import (
"mayfly-go/internal/tag/domain/entity"
"mayfly-go/pkg/base"
"mayfly-go/pkg/model"
)
type Team interface {
GetPageList(condition *entity.Team, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any]
base.Repo[*entity.Team]
Insert(p *entity.Team)
UpdateById(p *entity.Team)
Delete(id uint64)
DeleteBy(p *entity.Team)
GetPageList(condition *entity.Team, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error)
}

View File

@@ -2,19 +2,17 @@ package repository
import (
"mayfly-go/internal/tag/domain/entity"
"mayfly-go/pkg/base"
"mayfly-go/pkg/model"
)
type TeamMember interface {
base.Repo[*entity.TeamMember]
// 获取项目成员列表
ListMemeber(condition *entity.TeamMember, toEntity any, orderBy ...string)
Save(mp *entity.TeamMember)
GetPageList(condition *entity.TeamMember, pageParam *model.PageParam, toEntity any) *model.PageResult[any]
DeleteBy(condition *entity.TeamMember)
GetPageList(condition *entity.TeamMember, pageParam *model.PageParam, toEntity any) (*model.PageResult[any], error)
// 是否存在指定的团队成员关联信息
IsExist(teamId, accountId uint64) bool

View File

@@ -4,15 +4,17 @@ import (
"fmt"
"mayfly-go/internal/tag/domain/entity"
"mayfly-go/internal/tag/domain/repository"
"mayfly-go/pkg/biz"
"mayfly-go/pkg/base"
"mayfly-go/pkg/gormx"
"strings"
)
type tagTreeRepoImpl struct{}
type tagTreeRepoImpl struct {
base.RepoImpl[*entity.TagTree]
}
func newTagTreeRepo() repository.TagTree {
return new(tagTreeRepoImpl)
return &tagTreeRepoImpl{base.RepoImpl[*entity.TagTree]{M: new(entity.TagTree)}}
}
func (p *tagTreeRepoImpl) SelectByCondition(condition *entity.TagTreeQuery, toEntity any, orderBy ...string) {
@@ -51,27 +53,3 @@ func (p *tagTreeRepoImpl) SelectByCondition(condition *entity.TagTreeQuery, toEn
sql = sql + " ORDER BY p.code_path"
gormx.GetListBySql2Model(sql, toEntity)
}
func (p *tagTreeRepoImpl) SelectById(id uint64) *entity.TagTree {
pt := new(entity.TagTree)
if err := gormx.GetById(pt, id); err != nil {
return nil
}
return pt
}
func (a *tagTreeRepoImpl) GetBy(condition *entity.TagTree, cols ...string) error {
return gormx.GetBy(condition, cols...)
}
func (p *tagTreeRepoImpl) Insert(tagTree *entity.TagTree) {
biz.ErrIsNil(gormx.Insert(tagTree), "新增标签失败")
}
func (p *tagTreeRepoImpl) UpdateById(tagTree *entity.TagTree) {
biz.ErrIsNil(gormx.UpdateById(tagTree), "更新标签失败")
}
func (p *tagTreeRepoImpl) Delete(id uint64) {
gormx.DeleteById(new(entity.TagTree), id)
}

View File

@@ -3,26 +3,16 @@ package persistence
import (
"mayfly-go/internal/tag/domain/entity"
"mayfly-go/internal/tag/domain/repository"
"mayfly-go/pkg/biz"
"mayfly-go/pkg/base"
"mayfly-go/pkg/gormx"
)
type tagTreeTeamRepoImpl struct{}
type tagTreeTeamRepoImpl struct {
base.RepoImpl[*entity.TagTreeTeam]
}
func newTagTreeTeamRepo() repository.TagTreeTeam {
return new(tagTreeTeamRepoImpl)
}
func (p *tagTreeTeamRepoImpl) ListTag(condition *entity.TagTreeTeam, toEntity any, orderBy ...string) {
gormx.ListByOrder(condition, toEntity, orderBy...)
}
func (p *tagTreeTeamRepoImpl) Save(pm *entity.TagTreeTeam) {
biz.ErrIsNilAppendErr(gormx.Insert(pm), "保存团队项目信息失败:%s")
}
func (p *tagTreeTeamRepoImpl) DeleteBy(condition *entity.TagTreeTeam) {
gormx.DeleteByCondition(condition)
return &tagTreeTeamRepoImpl{base.RepoImpl[*entity.TagTreeTeam]{M: new(entity.TagTreeTeam)}}
}
func (p *tagTreeTeamRepoImpl) SelectTagPathsByAccountId(accountId uint64) []string {

View File

@@ -3,34 +3,20 @@ package persistence
import (
"mayfly-go/internal/tag/domain/entity"
"mayfly-go/internal/tag/domain/repository"
"mayfly-go/pkg/biz"
"mayfly-go/pkg/base"
"mayfly-go/pkg/gormx"
"mayfly-go/pkg/model"
)
type teamRepoImpl struct{}
func newTeamRepo() repository.Team {
return new(teamRepoImpl)
type teamRepoImpl struct {
base.RepoImpl[*entity.Team]
}
func (p *teamRepoImpl) GetPageList(condition *entity.Team, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any] {
func newTeamRepo() repository.Team {
return &teamRepoImpl{base.RepoImpl[*entity.Team]{M: new(entity.Team)}}
}
func (p *teamRepoImpl) GetPageList(condition *entity.Team, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error) {
qd := gormx.NewQuery(condition).WithCondModel(condition).WithOrderBy(orderBy...)
return gormx.PageQuery(qd, pageParam, toEntity)
}
func (p *teamRepoImpl) Insert(team *entity.Team) {
biz.ErrIsNil(gormx.Insert(team), "新增团队失败")
}
func (p *teamRepoImpl) UpdateById(team *entity.Team) {
biz.ErrIsNil(gormx.UpdateById(team), "更新团队失败")
}
func (p *teamRepoImpl) Delete(id uint64) {
gormx.DeleteById(new(entity.Team), id)
}
func (p *teamRepoImpl) DeleteBy(team *entity.Team) {
gormx.DeleteByCondition(team)
}

View File

@@ -3,26 +3,24 @@ package persistence
import (
"mayfly-go/internal/tag/domain/entity"
"mayfly-go/internal/tag/domain/repository"
"mayfly-go/pkg/biz"
"mayfly-go/pkg/base"
"mayfly-go/pkg/gormx"
"mayfly-go/pkg/model"
)
type teamMemberRepoImpl struct{}
type teamMemberRepoImpl struct {
base.RepoImpl[*entity.TeamMember]
}
func newTeamMemberRepo() repository.TeamMember {
return new(teamMemberRepoImpl)
return &teamMemberRepoImpl{base.RepoImpl[*entity.TeamMember]{M: new(entity.TeamMember)}}
}
func (p *teamMemberRepoImpl) ListMemeber(condition *entity.TeamMember, toEntity any, orderBy ...string) {
gormx.ListByOrder(condition, toEntity, orderBy...)
}
func (p *teamMemberRepoImpl) Save(pm *entity.TeamMember) {
biz.ErrIsNilAppendErr(gormx.Insert(pm), "保存团队成员失败:%s")
}
func (p *teamMemberRepoImpl) GetPageList(condition *entity.TeamMember, pageParam *model.PageParam, toEntity any) *model.PageResult[any] {
func (p *teamMemberRepoImpl) GetPageList(condition *entity.TeamMember, pageParam *model.PageParam, toEntity any) (*model.PageResult[any], error) {
qd := gormx.NewQueryWithTableName("t_team_member t").
Select("t.*, a.name").
Joins("JOIN t_sys_account a ON t.account_id = a.id AND a.status = 1").
@@ -35,10 +33,6 @@ func (p *teamMemberRepoImpl) GetPageList(condition *entity.TeamMember, pageParam
return gormx.PageQuery(qd, pageParam, toEntity)
}
func (p *teamMemberRepoImpl) DeleteBy(condition *entity.TeamMember) {
gormx.DeleteByCondition(condition)
}
func (p *teamMemberRepoImpl) IsExist(teamId, accountId uint64) bool {
return gormx.CountBy(&entity.TeamMember{TeamId: teamId, AccountId: accountId}) > 0
}

145
server/pkg/base/app.go Normal file
View File

@@ -0,0 +1,145 @@
package base
import (
"gorm.io/gorm"
)
// 基础application接口
type App[T any] interface {
// 新增一个实体
Insert(e T) error
// 批量新增实体
BatchInsert(models []T) error
// 根据实体id更新实体信息
UpdateById(e T) error
// 使用指定gorm db执行主要用于事务执行
UpdateByIdWithDb(db *gorm.DB, e T) error
// 根据实体主键删除实体
DeleteById(id uint64) error
// 使用指定gorm db执行主要用于事务执行
DeleteByIdWithDb(db *gorm.DB, id uint64) error
// 根据实体条件更新参数udpateFields指定字段
Updates(cond any, udpateFields map[string]any) error
// 根据实体条件删除实体
DeleteByCond(cond any) error
// 使用指定gorm db执行主要用于事务执行
DeleteByCondWithDb(db *gorm.DB, cond any) error
// 根据实体id查询
GetById(e T, id uint64, cols ...string) (T, error)
GetByIdIn(list any, ids []uint64, orderBy ...string) error
// 根据实体条件查询实体信息
GetBy(condModel T, cols ...string) error
// 根据条件查询数据映射至listModels
ListByCond(cond any, listModels any, cols ...string) error
// 获取满足model中不为空的字段值条件的所有数据.
//
// @param list为数组类型 如 var users *[]User可指定为非model结构体
// @param cond 条件
ListByCondOrder(cond any, list any, order ...string) error
// 根据指定条件统计model表的数量, cond为条件可以为map等
CountByCond(cond any) int64
}
// 基础application接口实现
type AppImpl[T any, R Repo[T]] struct {
Repo R // repo接口
}
// 获取repo
func (ai *AppImpl[T, R]) GetRepo() R {
return ai.Repo
}
// 新增一个实体 (单纯新增,不做其他业务逻辑处理)
func (ai *AppImpl[T, R]) Insert(e T) error {
return ai.GetRepo().Insert(e)
}
// 批量新增实体 (单纯新增,不做其他业务逻辑处理)
func (ai *AppImpl[T, R]) BatchInsert(es []T) error {
return ai.GetRepo().BatchInsert(es)
}
// 根据实体id更新实体信息 (单纯更新,不做其他业务逻辑处理)
func (ai *AppImpl[T, R]) UpdateById(e T) error {
return ai.GetRepo().UpdateById(e)
}
// 使用指定gorm db执行主要用于事务执行
func (ai *AppImpl[T, R]) UpdateByIdWithDb(db *gorm.DB, e T) error {
return ai.GetRepo().UpdateByIdWithDb(db, e)
}
// 根据实体条件更新参数udpateFields指定字段 (单纯更新,不做其他业务逻辑处理)
func (ai *AppImpl[T, R]) Updates(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]) DeleteByIdWithDb(db *gorm.DB, id uint64) error {
return ai.GetRepo().DeleteByCondWithDb(db, id)
}
// 根据指定条件删除实体 (单纯删除实体,不做其他业务逻辑处理)
func (ai *AppImpl[T, R]) DeleteByCond(cond any) error {
return ai.GetRepo().DeleteByCond(cond)
}
// 使用指定gorm db执行主要用于事务执行
func (ai *AppImpl[T, R]) DeleteByCondWithDb(db *gorm.DB, cond any) error {
return ai.GetRepo().DeleteByCondWithDb(db, cond)
}
// 根据实体id查询
func (ai *AppImpl[T, R]) GetById(e T, id uint64, cols ...string) (T, error) {
if err := ai.GetRepo().GetById(e, id, cols...); err != nil {
return e, err
}
return e, nil
}
func (ai *AppImpl[T, R]) GetByIdIn(list any, ids []uint64, orderBy ...string) error {
return ai.GetRepo().GetByIdIn(list, ids, orderBy...)
}
// 根据实体条件查询实体信息
func (ai *AppImpl[T, R]) GetBy(condModel T, cols ...string) error {
return ai.GetRepo().GetBy(condModel, cols...)
}
// 根据条件查询数据映射至listModels
func (ai *AppImpl[T, R]) ListByCond(cond any, listModels any, cols ...string) error {
return ai.GetRepo().ListByCond(cond, listModels, cols...)
}
// 获取满足model中不为空的字段值条件的所有数据.
//
// @param list为数组类型 如 var users *[]User可指定为非model结构体
// @param cond 条件
func (ai *AppImpl[T, R]) ListByCondOrder(cond any, list any, order ...string) error {
return ai.GetRepo().ListByCondOrder(cond, list, order...)
}
// 根据指定条件统计model表的数量, cond为条件可以为map等
func (ai *AppImpl[T, R]) CountByCond(cond any) int64 {
return ai.GetRepo().CountByCond(cond)
}

149
server/pkg/base/repo.go Normal file
View File

@@ -0,0 +1,149 @@
package base
import (
"mayfly-go/pkg/biz"
"mayfly-go/pkg/gormx"
"gorm.io/gorm"
)
// 基础repo接口
type Repo[T any] interface {
// 新增一个实体
Insert(e T) error
// 使用指定gorm db执行主要用于事务执行
InsertWithDb(db *gorm.DB, e T) error
// 批量新增实体
BatchInsert(models []T) error
// 使用指定gorm db执行主要用于事务执行
BatchInsertWithDb(db *gorm.DB, es []T) error
// 根据实体id更新实体信息
UpdateById(e T) error
// 使用指定gorm db执行主要用于事务执行
UpdateByIdWithDb(db *gorm.DB, e T) error
// 根据实体主键删除实体
DeleteById(id uint64) error
// 使用指定gorm db执行主要用于事务执行
DeleteByIdWithDb(db *gorm.DB, id uint64) error
// 根据实体条件更新参数udpateFields指定字段
Updates(cond any, udpateFields map[string]any) error
// 根据实体条件删除实体
DeleteByCond(cond any) error
// 使用指定gorm db执行主要用于事务执行
DeleteByCondWithDb(db *gorm.DB, cond any) error
// 根据实体id查询
GetById(e T, id uint64, cols ...string) error
// 根据实体id数组查询对应实体列表并将响应结果映射至list
GetByIdIn(list any, ids []uint64, orderBy ...string) error
// 根据实体条件查询实体信息
GetBy(cond T, cols ...string) error
// 根据实体条件查询数据映射至listModels
ListByCond(cond any, listModels any, cols ...string) error
// 获取满足model中不为空的字段值条件的所有数据.
//
// @param list为数组类型 如 var users *[]User可指定为非model结构体
// @param cond 条件
ListByCondOrder(cond any, list any, order ...string) error
// 根据指定条件统计model表的数量, cond为条件可以为map等
CountByCond(cond any) int64
}
// 基础repo接口
type RepoImpl[T any] struct {
M any // 模型实例
}
func (br *RepoImpl[T]) Insert(e T) error {
return gormx.Insert(e)
}
func (br *RepoImpl[T]) InsertWithDb(db *gorm.DB, e T) error {
return gormx.InsertWithDb(db, e)
}
func (br *RepoImpl[T]) BatchInsert(es []T) error {
return gormx.BatchInsert(es)
}
// 使用指定gorm db执行主要用于事务执行
func (br *RepoImpl[T]) BatchInsertWithDb(db *gorm.DB, es []T) error {
return gormx.BatchInsertWithDb(db, es)
}
func (br *RepoImpl[T]) UpdateById(e T) error {
return gormx.UpdateById(e)
}
func (br *RepoImpl[T]) UpdateByIdWithDb(db *gorm.DB, e T) error {
return gormx.UpdateByIdWithDb(db, 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 {
return gormx.DeleteById(br.getModel(), id)
}
func (br *RepoImpl[T]) DeleteByIdWithDb(db *gorm.DB, id uint64) error {
return gormx.DeleteByCondWithDb(db, br.getModel(), id)
}
func (br *RepoImpl[T]) DeleteByCond(cond any) error {
return gormx.DeleteByCond(br.getModel(), cond)
}
func (br *RepoImpl[T]) DeleteByCondWithDb(db *gorm.DB, cond any) error {
return gormx.DeleteByCondWithDb(db, br.getModel(), cond)
}
func (br *RepoImpl[T]) GetById(e T, id uint64, cols ...string) error {
if err := gormx.GetById(e, id, cols...); err != nil {
return err
}
return nil
}
func (br *RepoImpl[T]) GetByIdIn(list any, ids []uint64, orderBy ...string) error {
return gormx.GetByIdIn(br.getModel(), list, ids, orderBy...)
}
func (br *RepoImpl[T]) GetBy(cond T, cols ...string) error {
return gormx.GetBy(cond, cols...)
}
func (br *RepoImpl[T]) ListByCond(cond any, listModels any, cols ...string) error {
return gormx.ListByCond(br.getModel(), cond, listModels, cols...)
}
func (br *RepoImpl[T]) ListByCondOrder(cond any, list any, order ...string) error {
return gormx.ListByCondOrder(br.getModel(), cond, list, order...)
}
func (br *RepoImpl[T]) CountByCond(cond any) int64 {
return gormx.CountByCond(br.getModel(), cond)
}
// 获取表的模型实例
func (br *RepoImpl[T]) getModel() any {
biz.IsTrue(br.M != nil, "base.RepoImpl的M字段不能为空")
return br.M
}

View File

@@ -2,43 +2,41 @@ package biz
import (
"fmt"
"mayfly-go/pkg/logx"
"mayfly-go/pkg/errorx"
"mayfly-go/pkg/utils/anyx"
"reflect"
)
func ErrIsNil(err error, msg string, params ...any) {
// 断言错误为ni
// @param msgAndParams 消息与参数占位符,第一位为错误消息可包含%s等格式化标识。其余为Sprintf格式化值内容
//
// ErrIsNil(err)
// ErrIsNil(err, "xxxx")
// ErrIsNil(err, "xxxx: %s", "yyyy")
func ErrIsNil(err error, msgAndParams ...any) {
if err != nil {
// logx.ErrorTrace(msg, err)
panic(NewBizErr(fmt.Sprintf(msg, params...)))
if len(msgAndParams) == 0 {
panic(err)
}
panic(errorx.NewBiz(fmt.Sprintf(msgAndParams[0].(string), msgAndParams[1:]...)))
}
}
func ErrIsNilAppendErr(err error, msg string) {
if err != nil {
// logx.ErrorTrace(msg, err)
panic(NewBizErr(fmt.Sprintf(msg, err.Error())))
}
}
func IsNil(err error) {
switch t := err.(type) {
case *BizError:
panic(t)
case error:
logx.Error("非业务异常: " + err.Error())
panic(NewBizErr(fmt.Sprintf("非业务异常: %s", err.Error())))
panic(errorx.NewBiz(fmt.Sprintf(msg, err.Error())))
}
}
func IsTrue(exp bool, msg string, params ...any) {
if !exp {
panic(NewBizErr(fmt.Sprintf(msg, params...)))
panic(errorx.NewBiz(fmt.Sprintf(msg, params...)))
}
}
func IsTrueBy(exp bool, err BizError) {
func IsTrueBy(exp bool, err errorx.BizError) {
if !exp {
panic(err)
}
@@ -46,30 +44,30 @@ func IsTrueBy(exp bool, err BizError) {
func NotEmpty(str string, msg string, params ...any) {
if str == "" {
panic(NewBizErr(fmt.Sprintf(msg, params...)))
panic(errorx.NewBiz(fmt.Sprintf(msg, params...)))
}
}
func NotNil(data any, msg string, params ...any) {
if reflect.ValueOf(data).IsNil() {
panic(NewBizErr(fmt.Sprintf(msg, params...)))
panic(errorx.NewBiz(fmt.Sprintf(msg, params...)))
}
}
func NotBlank(data any, msg string, params ...any) {
if anyx.IsBlank(data) {
panic(NewBizErr(fmt.Sprintf(msg, params...)))
panic(errorx.NewBiz(fmt.Sprintf(msg, params...)))
}
}
func IsEquals(data any, data1 any, msg string) {
if data != data1 {
panic(NewBizErr(msg))
panic(errorx.NewBiz(msg))
}
}
func Nil(data any, msg string) {
if !reflect.ValueOf(data).IsNil() {
panic(NewBizErr(msg))
panic(errorx.NewBiz(msg))
}
}

View File

@@ -0,0 +1,11 @@
package biz
import (
"testing"
)
func TestErrIsNil(t *testing.T) {
// ErrIsNil(NewBizErr("xxx is error"))
// ErrIsNil(NewBizErr("xxx is error"), "格式错误")
// ErrIsNil(NewBizErr("xxx is error"), "格式错误: %s, %d", "xxx", 12)
}

Some files were not shown because too many files have changed in this diff Show More