Files
mayfly-go/server/internal/mongo/api/mongo.go

279 lines
8.0 KiB
Go
Raw Normal View History

2022-05-17 20:23:08 +08:00
package api
import (
"context"
2022-09-09 18:26:08 +08:00
"mayfly-go/internal/mongo/api/form"
"mayfly-go/internal/mongo/api/vo"
2022-09-09 18:26:08 +08:00
"mayfly-go/internal/mongo/application"
"mayfly-go/internal/mongo/domain/entity"
"mayfly-go/internal/mongo/imsg"
"mayfly-go/internal/pkg/consts"
"mayfly-go/internal/pkg/event"
2022-10-26 20:49:29 +08:00
tagapp "mayfly-go/internal/tag/application"
tagentity "mayfly-go/internal/tag/domain/entity"
"mayfly-go/pkg/biz"
"mayfly-go/pkg/global"
2022-10-26 20:49:29 +08:00
"mayfly-go/pkg/model"
2023-01-14 16:29:52 +08:00
"mayfly-go/pkg/req"
2023-10-12 12:14:56 +08:00
"mayfly-go/pkg/utils/collx"
"regexp"
"strings"
2022-05-17 20:23:08 +08:00
2025-06-27 12:17:45 +08:00
"github.com/spf13/cast"
"go.mongodb.org/mongo-driver/v2/bson"
"go.mongodb.org/mongo-driver/v2/mongo/options"
2022-05-17 20:23:08 +08:00
)
type Mongo struct {
mongoApp application.Mongo `inject:"T"`
tagTreeApp tagapp.TagTree `inject:"T"`
}
func (ma *Mongo) ReqConfs() *req.Confs {
saveDataPerm := req.NewPermission("mongo:data:save")
reqs := [...]*req.Conf{
// 获取所有mongo列表
req.NewGet("", ma.Mongos),
req.NewPost("/test-conn", ma.TestConn),
req.NewPost("", ma.Save).Log(req.NewLogSaveI(imsg.LogMongoSave)),
req.NewDelete(":id", ma.DeleteMongo).Log(req.NewLogSaveI(imsg.LogMongoDelete)),
// 获取mongo下的所有数据库
req.NewGet(":id/databases", ma.Databases),
// 获取mongo指定库的所有集合
req.NewGet(":id/collections", ma.Collections),
// mongo runCommand
req.NewPost(":id/run-command", ma.RunCommand).Log(req.NewLogSaveI(imsg.LogMongoRunCmd)),
// 执行mongo find命令
req.NewPost(":id/command/find", ma.FindCommand),
req.NewPost(":id/command/update-by-id", ma.UpdateByIdCommand).RequiredPermission(saveDataPerm).Log(req.NewLogSaveI(imsg.LogUpdateDocs)),
// 执行mongo delete by id命令
req.NewPost(":id/command/delete-by-id", ma.DeleteByIdCommand).RequiredPermission(req.NewPermission("mongo:data:del")).Log(req.NewLogSaveI(imsg.LogDelDocs)),
// 执行mongo insert 命令
req.NewPost(":id/command/insert", ma.InsertOneCommand).RequiredPermission(saveDataPerm).Log(req.NewLogSaveI(imsg.LogInsertDocs)),
}
return req.NewConfs("/mongos", reqs[:]...)
2022-05-17 20:23:08 +08:00
}
2023-01-14 16:29:52 +08:00
func (m *Mongo) Mongos(rc *req.Ctx) {
queryCond := req.BindQuery[*entity.MongoQuery](rc)
2022-10-26 20:49:29 +08:00
// 不存在可访问标签id即没有可操作数据
tags := m.tagTreeApp.GetAccountTags(rc.GetLoginAccount().Id, &tagentity.TagTreeQuery{
2024-11-26 17:32:44 +08:00
TypePaths: collx.AsArray(tagentity.NewTypePaths(tagentity.TagTypeMongo)),
2024-11-23 17:23:18 +08:00
CodePathLikes: []string{queryCond.TagPath},
})
if len(tags) == 0 {
rc.ResData = model.NewEmptyPageResult[any]()
2022-10-26 20:49:29 +08:00
return
2022-05-17 20:23:08 +08:00
}
2024-11-23 17:23:18 +08:00
queryCond.Codes = tags.GetCodes()
res, err := m.mongoApp.GetPageList(queryCond)
biz.ErrIsNil(err)
resVo := model.PageResultConv[*entity.Mongo, *vo.Mongo](res)
mongovos := resVo.List
// 填充标签信息
m.tagTreeApp.FillTagInfo(tagentity.TagType(consts.ResourceTypeMongo), collx.ArrayMap(mongovos, func(mvo *vo.Mongo) tagentity.ITagResource {
return mvo
})...)
rc.ResData = resVo
2022-05-17 20:23:08 +08:00
}
func (m *Mongo) TestConn(rc *req.Ctx) {
_, mongo := req.BindJsonAndCopyTo[*form.Mongo, *entity.Mongo](rc)
biz.ErrIsNilAppendErr(m.mongoApp.TestConn(mongo), "connection error: %s")
}
2023-01-14 16:29:52 +08:00
func (m *Mongo) Save(rc *req.Ctx) {
form, mongo := req.BindJsonAndCopyTo[*form.Mongo, *entity.Mongo](rc)
// 密码脱敏记录日志
form.Uri = func(str string) string {
reg := regexp.MustCompile(`(^mongodb://.+?:)(.+)(@.+$)`)
return reg.ReplaceAllString(str, `${1}****${3}`)
}(form.Uri)
2022-05-17 20:23:08 +08:00
rc.ReqParam = form
biz.ErrIsNil(m.mongoApp.SaveMongo(rc.MetaCtx, mongo, form.TagCodePaths...))
2022-05-17 20:23:08 +08:00
}
2023-01-14 16:29:52 +08:00
func (m *Mongo) DeleteMongo(rc *req.Ctx) {
2024-02-25 12:46:18 +08:00
idsStr := rc.PathParam("id")
rc.ReqParam = idsStr
ids := strings.Split(idsStr, ",")
for _, v := range ids {
m.mongoApp.Delete(rc.MetaCtx, cast.ToUint64(v))
}
2022-05-17 20:23:08 +08:00
}
2023-01-14 16:29:52 +08:00
func (m *Mongo) Databases(rc *req.Ctx) {
2025-05-22 23:29:50 +08:00
conn, err := m.mongoApp.GetMongoConn(rc.MetaCtx, m.GetMongoId(rc))
biz.ErrIsNil(err)
res, err := conn.Cli.ListDatabases(context.TODO(), bson.D{})
2024-11-20 22:43:53 +08:00
biz.ErrIsNilAppendErr(err, "get mongo dbs error: %s")
2022-05-17 20:23:08 +08:00
rc.ResData = res
}
2023-01-14 16:29:52 +08:00
func (m *Mongo) Collections(rc *req.Ctx) {
2025-05-22 23:29:50 +08:00
conn, err := m.mongoApp.GetMongoConn(rc.MetaCtx, m.GetMongoId(rc))
biz.ErrIsNil(err)
global.EventBus.Publish(rc.MetaCtx, event.EventTopicResourceOp, conn.Info.CodePath[0])
2024-02-25 12:46:18 +08:00
db := rc.Query("database")
2024-11-20 22:43:53 +08:00
biz.NotEmpty(db, "database cannot be empty")
2022-05-17 20:23:08 +08:00
ctx := context.TODO()
res, err := conn.Cli.Database(db).ListCollectionNames(ctx, bson.D{})
2024-11-20 22:43:53 +08:00
biz.ErrIsNilAppendErr(err, "get db collections error: %s")
2022-05-17 20:23:08 +08:00
rc.ResData = res
}
2023-01-14 16:29:52 +08:00
func (m *Mongo) RunCommand(rc *req.Ctx) {
commandForm := req.BindJson[*form.MongoRunCommand](rc)
2023-08-25 19:41:52 +08:00
2025-05-22 23:29:50 +08:00
conn, err := m.mongoApp.GetMongoConn(rc.MetaCtx, m.GetMongoId(rc))
biz.ErrIsNil(err)
rc.ReqParam = collx.Kvs("mongo", conn.Info, "cmd", commandForm)
2023-08-25 10:20:32 +08:00
// 顺序执行
commands := bson.D{}
for _, cmd := range commandForm.Command {
e := bson.E{}
for k, v := range cmd {
e.Key = k
e.Value = v
}
commands = append(commands, e)
}
2022-05-17 20:23:08 +08:00
ctx := context.TODO()
var bm bson.M
err = conn.Cli.Database(commandForm.Database).RunCommand(
2022-05-17 20:23:08 +08:00
ctx,
2023-08-25 10:20:32 +08:00
commands,
2022-05-17 20:23:08 +08:00
).Decode(&bm)
2024-11-20 22:43:53 +08:00
biz.ErrIsNilAppendErr(err, "command execution failed: %s")
2022-05-17 20:23:08 +08:00
rc.ResData = bm
}
2023-01-14 16:29:52 +08:00
func (m *Mongo) FindCommand(rc *req.Ctx) {
commandForm := req.BindJson[*form.MongoFindCommand](rc)
2022-05-17 20:23:08 +08:00
2025-05-22 23:29:50 +08:00
conn, err := m.mongoApp.GetMongoConn(rc.MetaCtx, m.GetMongoId(rc))
biz.ErrIsNil(err)
cli := conn.Cli
2022-05-17 20:23:08 +08:00
limit := commandForm.Limit
if limit != 0 {
2024-11-20 22:43:53 +08:00
biz.IsTrue(limit <= 100, "the limit cannot exceed 100")
2022-05-17 20:23:08 +08:00
}
opts := options.Find().SetSort(commandForm.Sort).
SetSkip(commandForm.Skip).
SetLimit(limit)
ctx := context.TODO()
filter := commandForm.Filter
// 处理_id查询字段,使用ObjectId函数包装
id, ok := filter["_id"].(string)
if ok && id != "" {
objId, err := bson.ObjectIDFromHex(id)
if err == nil {
filter["_id"] = objId
}
}
2022-05-17 20:23:08 +08:00
cur, err := cli.Database(commandForm.Database).Collection(commandForm.Collection).Find(ctx, commandForm.Filter, opts)
2024-11-20 22:43:53 +08:00
biz.ErrIsNilAppendErr(err, "command execution failed: %s")
2022-05-17 20:23:08 +08:00
var res []bson.M
cur.All(ctx, &res)
rc.ResData = res
}
2023-01-14 16:29:52 +08:00
func (m *Mongo) UpdateByIdCommand(rc *req.Ctx) {
commandForm := req.BindJson[*form.MongoUpdateByIdCommand](rc)
2022-05-17 20:23:08 +08:00
2025-05-22 23:29:50 +08:00
conn, err := m.mongoApp.GetMongoConn(rc.MetaCtx, m.GetMongoId(rc))
biz.ErrIsNil(err)
rc.ReqParam = collx.Kvs("mongo", conn.Info, "cmd", commandForm)
2023-08-25 19:41:52 +08:00
2022-05-17 20:23:08 +08:00
// 解析docId文档id如果为string类型则使用ObjectId解析解析失败则为普通字符串
docId := commandForm.DocId
docIdVal, ok := docId.(string)
if ok {
objId, err := bson.ObjectIDFromHex(docIdVal)
2022-05-17 20:23:08 +08:00
if err == nil {
docId = objId
}
}
res, err := conn.Cli.Database(commandForm.Database).Collection(commandForm.Collection).UpdateByID(context.TODO(), docId, commandForm.Update)
2024-11-20 22:43:53 +08:00
biz.ErrIsNilAppendErr(err, "command execution failed: %s")
2022-05-17 20:23:08 +08:00
rc.ResData = res
}
2023-01-14 16:29:52 +08:00
func (m *Mongo) DeleteByIdCommand(rc *req.Ctx) {
commandForm := req.BindJson[*form.MongoUpdateByIdCommand](rc)
2022-05-17 20:23:08 +08:00
2025-05-22 23:29:50 +08:00
conn, err := m.mongoApp.GetMongoConn(rc.MetaCtx, m.GetMongoId(rc))
biz.ErrIsNil(err)
rc.ReqParam = collx.Kvs("mongo", conn.Info, "cmd", commandForm)
2023-08-25 19:41:52 +08:00
2022-05-17 20:23:08 +08:00
// 解析docId文档id如果为string类型则使用ObjectId解析解析失败则为普通字符串
docId := commandForm.DocId
docIdVal, ok := docId.(string)
if ok {
objId, err := bson.ObjectIDFromHex(docIdVal)
2022-05-17 20:23:08 +08:00
if err == nil {
docId = objId
}
}
res, err := conn.Cli.Database(commandForm.Database).Collection(commandForm.Collection).DeleteOne(context.TODO(), bson.D{{Key: "_id", Value: docId}})
2024-11-20 22:43:53 +08:00
biz.ErrIsNilAppendErr(err, "command execution failed: %s")
2022-05-17 20:23:08 +08:00
rc.ResData = res
}
2023-01-14 16:29:52 +08:00
func (m *Mongo) InsertOneCommand(rc *req.Ctx) {
commandForm := req.BindJson[*form.MongoInsertCommand](rc)
2022-05-17 20:23:08 +08:00
2025-05-22 23:29:50 +08:00
conn, err := m.mongoApp.GetMongoConn(rc.MetaCtx, m.GetMongoId(rc))
biz.ErrIsNil(err)
rc.ReqParam = collx.Kvs("mongo", conn.Info, "cmd", commandForm)
2022-05-17 20:23:08 +08:00
res, err := conn.Cli.Database(commandForm.Database).Collection(commandForm.Collection).InsertOne(context.TODO(), commandForm.Doc)
2024-11-20 22:43:53 +08:00
biz.ErrIsNilAppendErr(err, "command execution failed: %s")
2022-05-17 20:23:08 +08:00
rc.ResData = res
}
// 获取请求路径上的mongo id
func (m *Mongo) GetMongoId(rc *req.Ctx) uint64 {
2024-02-25 12:46:18 +08:00
dbId := rc.PathParamInt("id")
2024-11-20 22:43:53 +08:00
biz.IsTrue(dbId > 0, "mongoId error")
2022-05-17 20:23:08 +08:00
return uint64(dbId)
}