diff --git a/app/admin/apis/mm_group.go b/app/admin/apis/mm_group.go new file mode 100644 index 0000000..ef903cc --- /dev/null +++ b/app/admin/apis/mm_group.go @@ -0,0 +1,212 @@ +package apis + +import ( + "fmt" + + "github.com/gin-gonic/gin" + "github.com/go-admin-team/go-admin-core/sdk/api" + "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth/user" + _ "github.com/go-admin-team/go-admin-core/sdk/pkg/response" + + "go-admin/app/admin/models" + "go-admin/app/admin/service" + "go-admin/app/admin/service/dto" + "go-admin/common/actions" +) + +type MmGroup struct { + api.Api +} + +// GetPage 获取设备分组管理列表 +// @Summary 获取设备分组管理列表 +// @Description 获取设备分组管理列表 +// @Tags 设备分组管理 +// @Param groupName query string false "分组名称" +// @Param pageSize query int false "页条数" +// @Param pageIndex query int false "页码" +// @Success 200 {object} response.Response{data=response.Page{list=[]models.MmGroup}} "{"code": 200, "data": [...]}" +// @Router /api/v1/mm-group [get] +// @Security Bearer +func (e MmGroup) GetPage(c *gin.Context) { + req := dto.MmGroupGetPageReq{} + s := service.MmGroup{} + err := e.MakeContext(c). + MakeOrm(). + Bind(&req). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + + p := actions.GetPermissionFromContext(c) + list := make([]models.MmGroup, 0) + var count int64 + + err = s.GetPage(&req, p, &list, &count) + if err != nil { + e.Error(500, err, fmt.Sprintf("获取设备分组管理失败,\r\n失败信息 %s", err.Error())) + return + } + + e.PageOK(list, int(count), req.GetPageIndex(), req.GetPageSize(), "查询成功") +} + +// Get 获取设备分组管理 +// @Summary 获取设备分组管理 +// @Description 获取设备分组管理 +// @Tags 设备分组管理 +// @Param id path int false "id" +// @Success 200 {object} response.Response{data=models.MmGroup} "{"code": 200, "data": [...]}" +// @Router /api/v1/mm-group/{id} [get] +// @Security Bearer +func (e MmGroup) Get(c *gin.Context) { + req := dto.MmGroupGetReq{} + s := service.MmGroup{} + err := e.MakeContext(c). + MakeOrm(). + Bind(&req). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + var object models.MmGroup + + p := actions.GetPermissionFromContext(c) + err = s.Get(&req, p, &object) + if err != nil { + e.Error(500, err, fmt.Sprintf("获取设备分组管理失败,\r\n失败信息 %s", err.Error())) + return + } + + e.OK(object, "查询成功") +} + +// Insert 创建设备分组管理 +// @Summary 创建设备分组管理 +// @Description 创建设备分组管理 +// @Tags 设备分组管理 +// @Accept application/json +// @Product application/json +// @Param data body dto.MmGroupInsertReq true "data" +// @Success 200 {object} response.Response "{"code": 200, "message": "添加成功"}" +// @Router /api/v1/mm-group [post] +// @Security Bearer +func (e MmGroup) Insert(c *gin.Context) { + req := dto.MmGroupInsertReq{} + s := service.MmGroup{} + err := e.MakeContext(c). + MakeOrm(). + Bind(&req). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + // 设置创建人 + req.SetCreateBy(user.GetUserId(c)) + + err = s.Insert(&req) + if err != nil { + e.Error(500, err, fmt.Sprintf("创建设备分组管理失败,\r\n失败信息 %s", err.Error())) + return + } + + e.OK(req.GetId(), "创建成功") +} + +// Update 修改设备分组管理 +// @Summary 修改设备分组管理 +// @Description 修改设备分组管理 +// @Tags 设备分组管理 +// @Accept application/json +// @Product application/json +// @Param id path int true "id" +// @Param data body dto.MmGroupUpdateReq true "body" +// @Success 200 {object} response.Response "{"code": 200, "message": "修改成功"}" +// @Router /api/v1/mm-group/{id} [put] +// @Security Bearer +func (e MmGroup) Update(c *gin.Context) { + req := dto.MmGroupUpdateReq{} + s := service.MmGroup{} + err := e.MakeContext(c). + MakeOrm(). + Bind(&req). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + req.SetUpdateBy(user.GetUserId(c)) + p := actions.GetPermissionFromContext(c) + + err = s.Update(&req, p) + if err != nil { + e.Error(500, err, fmt.Sprintf("修改设备分组管理失败,\r\n失败信息 %s", err.Error())) + return + } + e.OK(req.GetId(), "修改成功") +} + +// Delete 删除设备分组管理 +// @Summary 删除设备分组管理 +// @Description 删除设备分组管理 +// @Tags 设备分组管理 +// @Param data body dto.MmGroupDeleteReq true "body" +// @Success 200 {object} response.Response "{"code": 200, "message": "删除成功"}" +// @Router /api/v1/mm-group [delete] +// @Security Bearer +func (e MmGroup) Delete(c *gin.Context) { + s := service.MmGroup{} + req := dto.MmGroupDeleteReq{} + err := e.MakeContext(c). + MakeOrm(). + Bind(&req). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + + // req.SetUpdateBy(user.GetUserId(c)) + p := actions.GetPermissionFromContext(c) + + err = s.Remove(&req, p) + if err != nil { + e.Error(500, err, fmt.Sprintf("删除设备分组管理失败,\r\n失败信息 %s", err.Error())) + return + } + e.OK(req.GetId(), "删除成功") +} + +func (e MmGroup) GetOptions(c *gin.Context) { + s := service.MmGroup{} + err := e.MakeContext(c). + MakeOrm(). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + list := make([]dto.MmGroupOption, 0) + err = s.GetOptions(&list) + if err != nil { + e.Error(500, err, fmt.Sprintf("获取设备分组管理失败,\r\n失败信息 %s", err.Error())) + return + } + e.OK(list, "查询成功") +} diff --git a/app/admin/apis/mm_keyword.go b/app/admin/apis/mm_keyword.go new file mode 100644 index 0000000..39a77ed --- /dev/null +++ b/app/admin/apis/mm_keyword.go @@ -0,0 +1,247 @@ +package apis + +import ( + "fmt" + "net/http" + + "github.com/gin-gonic/gin" + "github.com/gin-gonic/gin/binding" + "github.com/go-admin-team/go-admin-core/logger" + "github.com/go-admin-team/go-admin-core/sdk/api" + "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth/user" + _ "github.com/go-admin-team/go-admin-core/sdk/pkg/response" + + "go-admin/app/admin/models" + "go-admin/app/admin/service" + "go-admin/app/admin/service/dto" + "go-admin/common/actions" +) + +type MmKeyword struct { + api.Api +} + +// GetPage 获取关键字列表 +// @Summary 获取关键字列表 +// @Description 获取关键字列表 +// @Tags 关键字 +// @Param pageSize query int false "页条数" +// @Param pageIndex query int false "页码" +// @Success 200 {object} response.Response{data=response.Page{list=[]models.MmKeyword}} "{"code": 200, "data": [...]}" +// @Router /api/v1/mm-keyword [get] +// @Security Bearer +func (e MmKeyword) GetPage(c *gin.Context) { + req := dto.MmKeywordGetPageReq{} + s := service.MmKeyword{} + err := e.MakeContext(c). + MakeOrm(). + Bind(&req). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + + p := actions.GetPermissionFromContext(c) + list := make([]models.MmKeyword, 0) + var count int64 + + err = s.GetPage(&req, p, &list, &count) + if err != nil { + e.Error(500, err, fmt.Sprintf("获取关键字失败,\r\n失败信息 %s", err.Error())) + return + } + + e.PageOK(list, int(count), req.GetPageIndex(), req.GetPageSize(), "查询成功") +} + +// Get 获取关键字 +// @Summary 获取关键字 +// @Description 获取关键字 +// @Tags 关键字 +// @Param id path int false "id" +// @Success 200 {object} response.Response{data=models.MmKeyword} "{"code": 200, "data": [...]}" +// @Router /api/v1/mm-keyword/{id} [get] +// @Security Bearer +func (e MmKeyword) Get(c *gin.Context) { + req := dto.MmKeywordGetReq{} + s := service.MmKeyword{} + err := e.MakeContext(c). + MakeOrm(). + Bind(&req). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + var object models.MmKeyword + + p := actions.GetPermissionFromContext(c) + err = s.Get(&req, p, &object) + if err != nil { + e.Error(500, err, fmt.Sprintf("获取关键字失败,\r\n失败信息 %s", err.Error())) + return + } + + e.OK(object, "查询成功") +} + +// Insert 创建关键字 +// @Summary 创建关键字 +// @Description 创建关键字 +// @Tags 关键字 +// @Accept application/json +// @Product application/json +// @Param data body dto.MmKeywordInsertReq true "data" +// @Success 200 {object} response.Response "{"code": 200, "message": "添加成功"}" +// @Router /api/v1/mm-keyword [post] +// @Security Bearer +func (e MmKeyword) Insert(c *gin.Context) { + req := dto.MmKeywordInsertReq{} + s := service.MmKeyword{} + err := e.MakeContext(c). + MakeOrm(). + Bind(&req). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + // 设置创建人 + req.SetCreateBy(user.GetUserId(c)) + + err = s.Insert(&req) + if err != nil { + e.Error(500, err, fmt.Sprintf("创建关键字失败,\r\n失败信息 %s", err.Error())) + return + } + + e.OK(req.GetId(), "创建成功") +} + +// 批量添加添加长度关键字 +func (e MmKeyword) InsertBatch(c *gin.Context) { + req := dto.MmKeywordInsertBatchReq{} + s := service.MmKeyword{} + err := e.MakeContext(c). + MakeOrm(). + Bind(&req). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + + if err := req.Valid(); err != nil { + e.Error(500, err, "") + return + } + + err = s.InsertBatch(&req) + if err != nil { + e.Error(500, err, fmt.Sprintf("创建关键字失败,\r\n失败信息 %s", err.Error())) + return + } + + e.OK(nil, "创建成功") +} + +// Update 修改关键字 +// @Summary 修改关键字 +// @Description 修改关键字 +// @Tags 关键字 +// @Accept application/json +// @Product application/json +// @Param id path int true "id" +// @Param data body dto.MmKeywordUpdateReq true "body" +// @Success 200 {object} response.Response "{"code": 200, "message": "修改成功"}" +// @Router /api/v1/mm-keyword/{id} [put] +// @Security Bearer +func (e MmKeyword) Update(c *gin.Context) { + req := dto.MmKeywordUpdateReq{} + s := service.MmKeyword{} + err := e.MakeContext(c). + MakeOrm(). + Bind(&req). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + req.SetUpdateBy(user.GetUserId(c)) + p := actions.GetPermissionFromContext(c) + + err = s.Update(&req, p) + if err != nil { + e.Error(500, err, fmt.Sprintf("修改关键字失败,\r\n失败信息 %s", err.Error())) + return + } + e.OK(req.GetId(), "修改成功") +} + +// Delete 删除关键字 +// @Summary 删除关键字 +// @Description 删除关键字 +// @Tags 关键字 +// @Param data body dto.MmKeywordDeleteReq true "body" +// @Success 200 {object} response.Response "{"code": 200, "message": "删除成功"}" +// @Router /api/v1/mm-keyword [delete] +// @Security Bearer +func (e MmKeyword) Delete(c *gin.Context) { + s := service.MmKeyword{} + req := dto.MmKeywordDeleteReq{} + err := e.MakeContext(c). + MakeOrm(). + Bind(&req). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + + // req.SetUpdateBy(user.GetUserId(c)) + p := actions.GetPermissionFromContext(c) + + err = s.Remove(&req, p) + if err != nil { + e.Error(500, err, fmt.Sprintf("删除关键字失败,\r\n失败信息 %s", err.Error())) + return + } + e.OK(req.GetId(), "删除成功") +} + +// 获取关键字 +func (e MmKeyword) GetKeywords(c *gin.Context) { + s := service.MmKeyword{} + req := dto.MmKeywordReq{} + err := e.MakeContext(c). + MakeOrm(). + Bind(&req, binding.Form, binding.Query). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + logger.Debugf("获取关键字:%s", req.MachineId) + resp, err := s.GetKeywords(req.MachineId) + if err != nil { + c.String(500, err.Error()) + return + } + + c.String(http.StatusOK, resp) +} diff --git a/app/admin/apis/mm_machine.go b/app/admin/apis/mm_machine.go index b95e527..473947a 100644 --- a/app/admin/apis/mm_machine.go +++ b/app/admin/apis/mm_machine.go @@ -1,12 +1,13 @@ package apis import ( + "encoding/json" "fmt" "net/http" - "strings" "github.com/gin-gonic/gin" "github.com/gin-gonic/gin/binding" + "github.com/go-admin-team/go-admin-core/logger" "github.com/go-admin-team/go-admin-core/sdk/api" "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth/user" _ "github.com/go-admin-team/go-admin-core/sdk/pkg/response" @@ -161,6 +162,37 @@ func (e MmMachine) Update(c *gin.Context) { e.OK(req.GetId(), "修改成功") } +// UpdateLimitBatch 批量修改设备白名单配置 +func (e MmMachine) UpdateLimitBatch(c *gin.Context) { + req := dto.MmMachineUpdateLimitBatchReq{} + s := service.MmMachine{} + err := e.MakeContext(c). + MakeOrm(). + Bind(&req, binding.JSON). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + + if err := req.Validate(); err != nil { + e.Error(500, err, fmt.Sprintf("批量修改设备白名单配置失败,\r\n失败信息 %s", err.Error())) + return + } + + p := actions.GetPermissionFromContext(c) + + err = s.UpdateLimitBatch(&req, p) + if err != nil { + e.Error(500, err, fmt.Sprintf("批量修改设备白名单配置失败,\r\n失败信息 %s", err.Error())) + return + } + + e.OK(nil, "批量修改成功") +} + // 批量修改 func (e MmMachine) UpdateBatch(c *gin.Context) { req := dto.MmMachineUpdateBatchReq{} @@ -249,6 +281,7 @@ func (e MmMachine) GetPassword(c *gin.Context) { // 获取设备白名单数据 func (e MmMachine) GetWhiteProcess(c *gin.Context) { + logger.Info("获取设备白名单数据") s := service.MmMachine{} req := dto.MmMachineQueryWhiteListReq{} err := e.MakeContext(c). @@ -261,14 +294,16 @@ func (e MmMachine) GetWhiteProcess(c *gin.Context) { e.Logger.Error(err) } - whiteProcess, err := s.GetWhiteProcess(&req) + whiteProcess, err := s.GetWhiteProcess(&req, false) if err != nil { c.String(500, err.Error()) return } - c.String(http.StatusOK, whiteProcess) + resp, _ := json.Marshal(whiteProcess) + + c.String(http.StatusOK, string(resp)) } // 修改设备白名单数据 @@ -310,21 +345,24 @@ func (e MmMachine) CheckMachine(c *gin.Context) { c.Set("status", 500) } - err = s.CheckMachine(&req) - if err != nil { - e.Logger.Errorf("CheckMachine error:%s", err.Error()) - if strings.Contains(err.Error(), "设备编号已被占用") { - c.String(http.StatusOK, err.Error()) - } else { - c.String(500, "0") - } - return - } + resp := s.CheckMachine(&req) + // if err != nil { + // e.Logger.Errorf("CheckMachine error:%s", err.Error()) + // if strings.Contains(err.Error(), "设备编号已被占用") { + // c.String(http.StatusOK, err.Error()) + // } else { + // c.String(500, "0") + // } + // return + // } - c.String(http.StatusOK, "1") + byts, _ := json.Marshal(resp) + + c.String(http.StatusOK, string(byts)) } func (e MmMachine) GetMachineList(c *gin.Context) { + logger.Info("获取设备列表") s := service.MmMachine{} // req := dto.MmMachineQueryWhiteListReq{} err := e.MakeContext(c). @@ -344,3 +382,137 @@ func (e MmMachine) GetMachineList(c *gin.Context) { } e.OK(machineList, "查询成功") } + +// 批量修改设备分组 +func (e MmMachine) UpdateGroupBatch(c *gin.Context) { + req := dto.MmMachineUpdateGroupBatchReq{} + s := service.MmMachine{} + + err := e.MakeContext(c). + MakeOrm(). + Bind(&req, binding.JSON). + MakeService(&s.Service). + Errors + + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + + if err := req.Validate(); err != nil { + e.Error(500, err, fmt.Sprintf("批量修改设备白名单配置失败,\r\n失败信息 %s", err.Error())) + return + } + + p := actions.GetPermissionFromContext(c) + + err = s.UpdateGroupBatch(&req, p) + if err != nil { + e.Error(500, err, fmt.Sprintf("批量修改设备白名单配置失败,\r\n失败信息 %s", err.Error())) + return + } + + e.OK(nil, "批量修改成功") +} + +// 清除所有设备 +func (e MmMachine) ClearAll(c *gin.Context) { + s := service.MmMachine{} + err := e.MakeContext(c). + MakeOrm(). + MakeService(&s.Service). + Errors + + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + + err = s.ClearAll() + if err != nil { + e.Error(500, err, fmt.Sprintf("清除所有设备失败,\r\n失败信息 %s", err.Error())) + return + } + + e.OK(nil, "清除成功") +} + +// 解绑所有设备 +func (e MmMachine) Uninstall(c *gin.Context) { + s := service.MmMachine{} + err := e.MakeContext(c). + MakeOrm(). + MakeService(&s.Service). + Errors + + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + + err = s.Uninstall() + if err != nil { + e.Error(500, err, fmt.Sprintf("解绑所有设备失败,\r\n失败信息 %s", err.Error())) + return + } + + e.OK(nil, "解绑成功") +} + +// 批量修改设备描述 +func (e MmMachine) UpdateDescriptionBatch(c *gin.Context) { + req := dto.MmMachineUpdateDescriptionBatchReq{} + s := service.MmMachine{} + + err := e.MakeContext(c). + MakeOrm(). + Bind(&req, binding.JSON). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + + if err := req.Validate(); err != nil { + e.Error(500, err, fmt.Sprintf("批量修改设备白名单配置失败,\r\n失败信息 %s", err.Error())) + return + } + + p := actions.GetPermissionFromContext(c) + + err = s.UpdateDescriptionBatch(&req, p) + if err != nil { + e.Error(500, err, fmt.Sprintf("批量修改设备白名单配置失败,\r\n失败信息 %s", err.Error())) + return + } + + e.OK(nil, "批量修改成功") +} + +// 查询设备间隔账号 +func (e MmMachine) QueryIntervalAccount(c *gin.Context) { + s := service.MmMachine{} + err := e.MakeContext(c). + MakeOrm(). + MakeService(&s.Service). + Errors + + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + + intervalAccount, err := s.QueryIntervalAccount() + if err != nil { + e.Error(500, err, fmt.Sprintf("查询设备间隔账号失败,\r\n失败信息 %s", err.Error())) + return + } + + e.OK(intervalAccount, "查询成功") +} diff --git a/app/admin/apis/mm_machine_log.go b/app/admin/apis/mm_machine_log.go index 17332b5..30f95e2 100644 --- a/app/admin/apis/mm_machine_log.go +++ b/app/admin/apis/mm_machine_log.go @@ -1,11 +1,13 @@ package apis import ( + "encoding/json" "fmt" "net/http" "github.com/gin-gonic/gin" "github.com/gin-gonic/gin/binding" + "github.com/go-admin-team/go-admin-core/logger" "github.com/go-admin-team/go-admin-core/sdk/api" "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth/user" _ "github.com/go-admin-team/go-admin-core/sdk/pkg/response" @@ -197,6 +199,7 @@ func (e MmMachineLog) Delete(c *gin.Context) { // CreateLog 创建设备管理-操作记录 func (e MmMachineLog) CreateLog(c *gin.Context) { + logger.Debug("创建设备管理-操作记录") req := dto.MmMachineLogInsertReq{} s := service.MmMachineLog{} err := e.MakeContext(c). @@ -210,14 +213,16 @@ func (e MmMachineLog) CreateLog(c *gin.Context) { return } - content, err := s.InsertLog(&req) + respData, err := s.InsertLog(&req) if err != nil { e.Logger.Errorf(fmt.Sprintf("创建设备管理-操作记录失败,\r\n失败信息 %s", err.Error())) c.String(500, "") return } - c.String(http.StatusOK, content) + content, _ := json.Marshal(respData) + + c.String(http.StatusOK, string(content)) } // ClearAll 清空设备管理-操作记录 diff --git a/app/admin/apis/mm_risk_log.go b/app/admin/apis/mm_risk_log.go new file mode 100644 index 0000000..1c09a84 --- /dev/null +++ b/app/admin/apis/mm_risk_log.go @@ -0,0 +1,239 @@ +package apis + +import ( + "fmt" + + "github.com/gin-gonic/gin" + "github.com/go-admin-team/go-admin-core/logger" + "github.com/go-admin-team/go-admin-core/sdk/api" + "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth/user" + _ "github.com/go-admin-team/go-admin-core/sdk/pkg/response" + + "go-admin/app/admin/models" + "go-admin/app/admin/service" + "go-admin/app/admin/service/dto" + "go-admin/common/actions" +) + +type MmRiskLog struct { + api.Api +} + +// GetPage 获取设备风险记录列表 +// @Summary 获取设备风险记录列表 +// @Description 获取设备风险记录列表 +// @Tags 设备风险记录 +// @Param pageSize query int false "页条数" +// @Param pageIndex query int false "页码" +// @Success 200 {object} response.Response{data=response.Page{list=[]models.MmRiskLog}} "{"code": 200, "data": [...]}" +// @Router /api/v1/mm-risk-log [get] +// @Security Bearer +func (e MmRiskLog) GetPage(c *gin.Context) { + req := dto.MmRiskLogGetPageReq{} + s := service.MmRiskLog{} + err := e.MakeContext(c). + MakeOrm(). + Bind(&req). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + + p := actions.GetPermissionFromContext(c) + list := make([]models.MmRiskLog, 0) + var count int64 + + err = s.GetPage(&req, p, &list, &count) + if err != nil { + e.Error(500, err, fmt.Sprintf("获取设备风险记录失败,\r\n失败信息 %s", err.Error())) + return + } + + e.PageOK(list, int(count), req.GetPageIndex(), req.GetPageSize(), "查询成功") +} + +// Get 获取设备风险记录 +// @Summary 获取设备风险记录 +// @Description 获取设备风险记录 +// @Tags 设备风险记录 +// @Param id path int false "id" +// @Success 200 {object} response.Response{data=models.MmRiskLog} "{"code": 200, "data": [...]}" +// @Router /api/v1/mm-risk-log/{id} [get] +// @Security Bearer +func (e MmRiskLog) Get(c *gin.Context) { + req := dto.MmRiskLogGetReq{} + s := service.MmRiskLog{} + err := e.MakeContext(c). + MakeOrm(). + Bind(&req). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + var object models.MmRiskLog + + p := actions.GetPermissionFromContext(c) + err = s.Get(&req, p, &object) + if err != nil { + e.Error(500, err, fmt.Sprintf("获取设备风险记录失败,\r\n失败信息 %s", err.Error())) + return + } + + e.OK(object, "查询成功") +} + +// Insert 创建设备风险记录 +// @Summary 创建设备风险记录 +// @Description 创建设备风险记录 +// @Tags 设备风险记录 +// @Accept application/json +// @Product application/json +// @Param data body dto.MmRiskLogInsertReq true "data" +// @Success 200 {object} response.Response "{"code": 200, "message": "添加成功"}" +// @Router /api/v1/mm-risk-log [post] +// @Security Bearer +func (e MmRiskLog) Insert(c *gin.Context) { + req := dto.MmRiskLogInsertReq{} + s := service.MmRiskLog{} + err := e.MakeContext(c). + MakeOrm(). + Bind(&req). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + // 设置创建人 + req.SetCreateBy(user.GetUserId(c)) + + err = s.Insert(&req) + if err != nil { + e.Error(500, err, fmt.Sprintf("创建设备风险记录失败,\r\n失败信息 %s", err.Error())) + return + } + + e.OK(req.GetId(), "创建成功") +} + +// Update 修改设备风险记录 +// @Summary 修改设备风险记录 +// @Description 修改设备风险记录 +// @Tags 设备风险记录 +// @Accept application/json +// @Product application/json +// @Param id path int true "id" +// @Param data body dto.MmRiskLogUpdateReq true "body" +// @Success 200 {object} response.Response "{"code": 200, "message": "修改成功"}" +// @Router /api/v1/mm-risk-log/{id} [put] +// @Security Bearer +func (e MmRiskLog) Update(c *gin.Context) { + req := dto.MmRiskLogUpdateReq{} + s := service.MmRiskLog{} + err := e.MakeContext(c). + MakeOrm(). + Bind(&req). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + req.SetUpdateBy(user.GetUserId(c)) + p := actions.GetPermissionFromContext(c) + + err = s.Update(&req, p) + if err != nil { + e.Error(500, err, fmt.Sprintf("修改设备风险记录失败,\r\n失败信息 %s", err.Error())) + return + } + e.OK(req.GetId(), "修改成功") +} + +// Delete 删除设备风险记录 +// @Summary 删除设备风险记录 +// @Description 删除设备风险记录 +// @Tags 设备风险记录 +// @Param data body dto.MmRiskLogDeleteReq true "body" +// @Success 200 {object} response.Response "{"code": 200, "message": "删除成功"}" +// @Router /api/v1/mm-risk-log [delete] +// @Security Bearer +func (e MmRiskLog) Delete(c *gin.Context) { + s := service.MmRiskLog{} + req := dto.MmRiskLogDeleteReq{} + err := e.MakeContext(c). + MakeOrm(). + Bind(&req). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + + // req.SetUpdateBy(user.GetUserId(c)) + p := actions.GetPermissionFromContext(c) + + err = s.Remove(&req, p) + if err != nil { + e.Error(500, err, fmt.Sprintf("删除设备风险记录失败,\r\n失败信息 %s", err.Error())) + return + } + e.OK(req.GetId(), "删除成功") +} + +// Save 创建或修改设备风险记录 +func (e MmRiskLog) Save(c *gin.Context) { + logger.Info("Save") + s := service.MmRiskLog{} + req := dto.MmRiskLogBatchReq{} + err := e.MakeContext(c). + MakeOrm(). + Bind(&req). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + + err = s.Save(&req) + if err != nil { + e.Error(500, err, fmt.Sprintf("创建设备风险记录失败,\r\n失败信息 %s", err.Error())) + return + } + e.OK(nil, "创建成功") +} + +// ClearAll 清空设备管理-操作记录 +func (e MmRiskLog) ClearAll(c *gin.Context) { + s := service.MmRiskLog{} + err := e.MakeContext(c). + MakeOrm(). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + + err = s.ClearAll() + if err != nil { + e.Logger.Errorf(fmt.Sprintf("清空-操作记录失败,\r\n失败信息 %s", err.Error())) + e.Error(500, err, err.Error()) + return + } + + e.OK(nil, "修改成功") +} diff --git a/app/admin/models/mm_group.go b/app/admin/models/mm_group.go new file mode 100644 index 0000000..7127abf --- /dev/null +++ b/app/admin/models/mm_group.go @@ -0,0 +1,28 @@ +package models + +import ( + + "go-admin/common/models" + +) + +type MmGroup struct { + models.Model + + GroupName string `json:"groupName" gorm:"type:varchar(30);comment:分组名称"` + models.ModelTime + models.ControlBy +} + +func (MmGroup) TableName() string { + return "mm_group" +} + +func (e *MmGroup) Generate() models.ActiveRecord { + o := *e + return &o +} + +func (e *MmGroup) GetId() interface{} { + return e.Id +} \ No newline at end of file diff --git a/app/admin/models/mm_keyword.go b/app/admin/models/mm_keyword.go new file mode 100644 index 0000000..346cba8 --- /dev/null +++ b/app/admin/models/mm_keyword.go @@ -0,0 +1,27 @@ +package models + +import ( + "go-admin/common/models" +) + +type MmKeyword struct { + models.Model + + Type int `json:"type" gorm:"type:tinyint;comment:类型 0-关键字限制 1-长度限制"` + Keyword string `json:"keyword" gorm:"type:varchar(255);comment:关键字"` + models.ModelTime + models.ControlBy +} + +func (MmKeyword) TableName() string { + return "mm_keyword" +} + +func (e *MmKeyword) Generate() models.ActiveRecord { + o := *e + return &o +} + +func (e *MmKeyword) GetId() interface{} { + return e.Id +} diff --git a/app/admin/models/mm_machine.go b/app/admin/models/mm_machine.go index 8a60ec1..6ca5d1c 100644 --- a/app/admin/models/mm_machine.go +++ b/app/admin/models/mm_machine.go @@ -9,11 +9,16 @@ import ( type MmMachine struct { models.Model - MachineId string `json:"machineId" gorm:"type:varchar(30);comment:设备id"` - BiosId string `json:"biosId" gorm:"type:varchar(30);comment:设备biosid(绑定之后的id)"` - LastTime *time.Time `json:"lastTime" gorm:"type:datetime;comment:最后通讯时间"` - Content string `json:"content" gorm:"type:text;comment:白名单内容"` - Status int `json:"status" gorm:"type:tinyint;comment:状态 0-掉线 1-在线"` + MachineId string `json:"machineId" gorm:"type:varchar(30);comment:设备id"` + BiosId string `json:"biosId" gorm:"type:varchar(30);comment:设备biosid(绑定之后的id)"` + GroupId int `json:"groupId" gorm:"type:bigint;comment:分组id"` + Description string `json:"description" gorm:"type:varchar(255);comment:描述"` + LastTime *time.Time `json:"lastTime" gorm:"type:datetime;comment:最后通讯时间"` + Content string `json:"content" gorm:"type:text;comment:白名单内容"` + GroupItems string `json:"groupItems" gorm:"type:text;comment:分组信息"` + Status int `json:"status" gorm:"type:tinyint;comment:状态 0-掉线 1-在线"` + TaskLimit int `json:"taskLimit" gorm:"type:int;comment:任务限制 1-限制 2-不限制"` + AppLimit int `json:"appLimit" gorm:"type:int;comment:应用限制 1-限制 2-不限制"` models.ModelTime models.ControlBy } diff --git a/app/admin/models/mm_risk_log.go b/app/admin/models/mm_risk_log.go new file mode 100644 index 0000000..f6ca92d --- /dev/null +++ b/app/admin/models/mm_risk_log.go @@ -0,0 +1,29 @@ +package models + +import ( + "go-admin/common/models" +) + +type MmRiskLog struct { + models.Model + + MachineId string `json:"machine_id" gorm:"type:varchar(30);comment:机器ID"` + BiosId string `json:"bios_id" gorm:"type:varchar(50);comment:BIOS ID"` + Type int `json:"type" gorm:"type:tinyint;comment:类型 0-关键字 1-长度限制"` + Content string `json:"content" gorm:"type:text;comment:内容"` + models.ModelTime + models.ControlBy +} + +func (MmRiskLog) TableName() string { + return "mm_risk_log" +} + +func (e *MmRiskLog) Generate() models.ActiveRecord { + o := *e + return &o +} + +func (e *MmRiskLog) GetId() interface{} { + return e.Id +} diff --git a/app/admin/models/mm_white_template.go b/app/admin/models/mm_white_template.go index 6d677b4..62766ff 100644 --- a/app/admin/models/mm_white_template.go +++ b/app/admin/models/mm_white_template.go @@ -1,21 +1,20 @@ package models import ( - "go-admin/common/models" - ) type MmWhiteTemplate struct { - models.Model - - Content string `json:"content" gorm:"type:text;comment:进程白名单内容"` - models.ModelTime - models.ControlBy + models.Model + + Type int `json:"type" gorm:"type:int;comment:白名单类型"` + Content string `json:"content" gorm:"type:text;comment:进程白名单内容"` + models.ModelTime + models.ControlBy } func (MmWhiteTemplate) TableName() string { - return "mm_white_template" + return "mm_white_template" } func (e *MmWhiteTemplate) Generate() models.ActiveRecord { @@ -25,4 +24,4 @@ func (e *MmWhiteTemplate) Generate() models.ActiveRecord { func (e *MmWhiteTemplate) GetId() interface{} { return e.Id -} \ No newline at end of file +} diff --git a/app/admin/router/mm_group.go b/app/admin/router/mm_group.go new file mode 100644 index 0000000..816ee64 --- /dev/null +++ b/app/admin/router/mm_group.go @@ -0,0 +1,29 @@ +package router + +import ( + "github.com/gin-gonic/gin" + jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" + + "go-admin/app/admin/apis" + "go-admin/common/actions" + "go-admin/common/middleware" +) + +func init() { + routerCheckRole = append(routerCheckRole, registerMmGroupRouter) +} + +// registerMmGroupRouter +func registerMmGroupRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) { + api := apis.MmGroup{} + r := v1.Group("/mm-group").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole()) + { + r.GET("", actions.PermissionAction(), api.GetPage) + r.GET("/:id", actions.PermissionAction(), api.Get) + r.POST("", api.Insert) + r.PUT("/:id", actions.PermissionAction(), api.Update) + r.DELETE("", api.Delete) + } + + v1.Group("/mm-group").GET("options", api.GetOptions) +} diff --git a/app/admin/router/mm_keyword.go b/app/admin/router/mm_keyword.go new file mode 100644 index 0000000..eb7e02f --- /dev/null +++ b/app/admin/router/mm_keyword.go @@ -0,0 +1,28 @@ +package router + +import ( + "github.com/gin-gonic/gin" + jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" + + "go-admin/app/admin/apis" + "go-admin/common/actions" + "go-admin/common/middleware" +) + +func init() { + routerCheckRole = append(routerCheckRole, registerMmKeywordRouter) +} + +// registerMmKeywordRouter +func registerMmKeywordRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) { + api := apis.MmKeyword{} + r := v1.Group("/mm-keyword").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole()) + { + r.GET("", actions.PermissionAction(), api.GetPage) + r.GET("/:id", actions.PermissionAction(), api.Get) + r.POST("", api.Insert) + r.POST("intervalBatch", api.InsertBatch) + r.PUT("/:id", actions.PermissionAction(), api.Update) + r.DELETE("", api.Delete) + } +} diff --git a/app/admin/router/mm_machine.go b/app/admin/router/mm_machine.go index 61a049e..c345dd7 100644 --- a/app/admin/router/mm_machine.go +++ b/app/admin/router/mm_machine.go @@ -24,7 +24,13 @@ func registerMmMachineRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMidd r.POST("", api.Insert) r.PUT("/:id", actions.PermissionAction(), api.Update) r.DELETE("", api.Delete) + r.DELETE("clearAll", api.ClearAll) r.PUT("batch", actions.PermissionAction(), api.UpdateBatch) + r.PUT("limitBatch", actions.PermissionAction(), api.UpdateLimitBatch) + r.PUT("groupBatch", actions.PermissionAction(), api.UpdateGroupBatch) + r.PUT("descriptionBatch", actions.PermissionAction(), api.UpdateDescriptionBatch) + r.DELETE("uninstall", actions.PermissionAction(), api.Uninstall) + r.GET("intervalAccount", actions.PermissionAction(), api.QueryIntervalAccount) } } @@ -32,6 +38,7 @@ func registerMmMachineRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMidd func registerMmMachineRouterNoRole(v1 *gin.RouterGroup) { api := apis.MmMachine{} api2 := apis.MmMachineLog{} + api3 := apis.MmKeyword{} r := v1.Group("/mm-machine") { @@ -41,5 +48,6 @@ func registerMmMachineRouterNoRole(v1 *gin.RouterGroup) { r.POST("machineWhite", api.UpdateMachineWhite) //修改机器白名单 r.POST("machineLog", api2.CreateLog) //新增机器日志 r.GET("checkMachine", api.CheckMachine) //占用设备编号 + r.GET("keywords", api3.GetKeywords) //获取关键字列表 } } diff --git a/app/admin/router/mm_risk_log.go b/app/admin/router/mm_risk_log.go new file mode 100644 index 0000000..5d4f68c --- /dev/null +++ b/app/admin/router/mm_risk_log.go @@ -0,0 +1,37 @@ +package router + +import ( + "github.com/gin-gonic/gin" + jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" + + "go-admin/app/admin/apis" + "go-admin/common/actions" + "go-admin/common/middleware" +) + +func init() { + routerCheckRole = append(routerCheckRole, registerMmRiskLogRouter) + routerNoCheckRole = append(routerNoCheckRole, registerMmRiskLogRouterNoCheck) +} + +// registerMmRiskLogRouter +func registerMmRiskLogRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) { + api := apis.MmRiskLog{} + r := v1.Group("/mm-risk-log").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole()) + { + r.GET("", actions.PermissionAction(), api.GetPage) + r.GET("/:id", actions.PermissionAction(), api.Get) + r.POST("", api.Insert) + r.PUT("/:id", actions.PermissionAction(), api.Update) + r.DELETE("", api.Delete) + r.DELETE("clear", api.ClearAll) + } +} + +func registerMmRiskLogRouterNoCheck(v1 *gin.RouterGroup) { + api := apis.MmRiskLog{} + r := v1.Group("/mm-risk-log") + { + r.POST("/save", api.Save) + } +} diff --git a/app/admin/service/dto/mm_group.go b/app/admin/service/dto/mm_group.go new file mode 100644 index 0000000..ab5befa --- /dev/null +++ b/app/admin/service/dto/mm_group.go @@ -0,0 +1,86 @@ +package dto + +import ( + "go-admin/app/admin/models" + "go-admin/common/dto" + common "go-admin/common/models" +) + +type MmGroupGetPageReq struct { + dto.Pagination `search:"-"` + GroupName string `form:"groupName" search:"type:contains;column:group_name;table:mm_group" comment:"分组名称"` + MmGroupOrder +} + +type MmGroupOrder struct { + Id string `form:"idOrder" search:"type:order;column:id;table:mm_group"` + GroupName string `form:"groupNameOrder" search:"type:order;column:group_name;table:mm_group"` + CreatedAt string `form:"createdAtOrder" search:"type:order;column:created_at;table:mm_group"` + UpdatedAt string `form:"updatedAtOrder" search:"type:order;column:updated_at;table:mm_group"` + DeletedAt string `form:"deletedAtOrder" search:"type:order;column:deleted_at;table:mm_group"` + CreateBy string `form:"createByOrder" search:"type:order;column:create_by;table:mm_group"` + UpdateBy string `form:"updateByOrder" search:"type:order;column:update_by;table:mm_group"` +} + +func (m *MmGroupGetPageReq) GetNeedSearch() interface{} { + return *m +} + +type MmGroupOption struct { + Value int `json:"value"` + Label string `json:"label"` +} + +type MmGroupInsertReq struct { + Id int `json:"-" comment:"主键id"` // 主键id + GroupName string `json:"groupName" comment:"分组名称"` + common.ControlBy +} + +func (s *MmGroupInsertReq) Generate(model *models.MmGroup) { + if s.Id == 0 { + model.Model = common.Model{Id: s.Id} + } + model.GroupName = s.GroupName + model.CreateBy = s.CreateBy // 添加这而,需要记录是被谁创建的 +} + +func (s *MmGroupInsertReq) GetId() interface{} { + return s.Id +} + +type MmGroupUpdateReq struct { + Id int `uri:"id" comment:"主键id"` // 主键id + GroupName string `json:"groupName" comment:"分组名称"` + common.ControlBy +} + +func (s *MmGroupUpdateReq) Generate(model *models.MmGroup) { + if s.Id == 0 { + model.Model = common.Model{Id: s.Id} + } + model.GroupName = s.GroupName + model.UpdateBy = s.UpdateBy // 添加这而,需要记录是被谁更新的 +} + +func (s *MmGroupUpdateReq) GetId() interface{} { + return s.Id +} + +// MmGroupGetReq 功能获取请求参数 +type MmGroupGetReq struct { + Id int `uri:"id"` +} + +func (s *MmGroupGetReq) GetId() interface{} { + return s.Id +} + +// MmGroupDeleteReq 功能删除请求参数 +type MmGroupDeleteReq struct { + Ids []int `json:"ids"` +} + +func (s *MmGroupDeleteReq) GetId() interface{} { + return s.Ids +} diff --git a/app/admin/service/dto/mm_keyword.go b/app/admin/service/dto/mm_keyword.go new file mode 100644 index 0000000..29bbdb9 --- /dev/null +++ b/app/admin/service/dto/mm_keyword.go @@ -0,0 +1,115 @@ +package dto + +import ( + "errors" + "go-admin/app/admin/models" + "go-admin/common/dto" + common "go-admin/common/models" +) + +type MmKeywordGetPageReq struct { + dto.Pagination `search:"-"` + Content string `form:"content" search:"type:contains;column:keyword;table:mm_keyword" comment:"关键字"` + MmKeywordOrder +} + +type MmKeywordOrder struct { + Id string `form:"idOrder" search:"type:order;column:id;table:mm_keyword"` + Type string `form:"typeOrder" search:"type:order;column:type;table:mm_keyword"` + Keyword string `form:"keywordOrder" search:"type:order;column:keyword;table:mm_keyword"` + CreatedAt string `form:"createdAtOrder" search:"type:order;column:created_at;table:mm_keyword"` + UpdatedAt string `form:"updatedAtOrder" search:"type:order;column:updated_at;table:mm_keyword"` + DeletedAt string `form:"deletedAtOrder" search:"type:order;column:deleted_at;table:mm_keyword"` + CreateBy string `form:"createByOrder" search:"type:order;column:create_by;table:mm_keyword"` + UpdateBy string `form:"updateByOrder" search:"type:order;column:update_by;table:mm_keyword"` +} + +func (m *MmKeywordGetPageReq) GetNeedSearch() interface{} { + return *m +} + +type MmKeywordInsertBatchReq struct { + Type int `json:"type" comment:"类型 1-长度限制 2-长度限制(忽略符号)"` + Start int `json:"start" comment:"开始位置"` + End int `json:"end" comment:"结束位置"` +} + +// 校验请求参数 +func (m *MmKeywordInsertBatchReq) Valid() error { + if m.Start <= 0 || m.End <= 0 { + return errors.New("不能小于0") + } + if m.Start > m.End { + return errors.New("起始数据不能大于结束数据") + } + + return nil +} + +type MmKeywordInsertReq struct { + Id int `json:"-" comment:"主键id"` // 主键id + Type int `json:"type" comment:"类型 0-关键字限制 1-长度限制"` + Keyword string `json:"keyword" comment:"关键字"` + common.ControlBy +} + +func (s *MmKeywordInsertReq) Generate(model *models.MmKeyword) { + if s.Id == 0 { + model.Model = common.Model{Id: s.Id} + } + model.Type = s.Type + model.Keyword = s.Keyword + model.CreateBy = s.CreateBy // 添加这而,需要记录是被谁创建的 +} + +func (s *MmKeywordInsertReq) GetId() interface{} { + return s.Id +} + +type MmKeywordCacheResp struct { + Keywords []string `json:"k"` + Length []string `json:"l"` + LengthIgnore []string `json:"li"` +} + +type MmKeywordUpdateReq struct { + Id int `uri:"id" comment:"主键id"` // 主键id + Type int `json:"type" comment:"类型 0-关键字限制 1-长度限制"` + Keyword string `json:"keyword" comment:"关键字"` + common.ControlBy +} + +func (s *MmKeywordUpdateReq) Generate(model *models.MmKeyword) { + if s.Id == 0 { + model.Model = common.Model{Id: s.Id} + } + model.Type = s.Type + model.Keyword = s.Keyword + model.UpdateBy = s.UpdateBy // 添加这而,需要记录是被谁更新的 +} + +func (s *MmKeywordUpdateReq) GetId() interface{} { + return s.Id +} + +// MmKeywordGetReq 功能获取请求参数 +type MmKeywordGetReq struct { + Id int `uri:"id"` +} + +func (s *MmKeywordGetReq) GetId() interface{} { + return s.Id +} + +// MmKeywordDeleteReq 功能删除请求参数 +type MmKeywordDeleteReq struct { + Ids []int `json:"ids"` +} + +func (s *MmKeywordDeleteReq) GetId() interface{} { + return s.Ids +} + +type MmKeywordReq struct { + MachineId string `json:"machineId" form:"machineId" query:"machineId" comment:"机器id"` +} diff --git a/app/admin/service/dto/mm_machine.go b/app/admin/service/dto/mm_machine.go index b310508..346557a 100644 --- a/app/admin/service/dto/mm_machine.go +++ b/app/admin/service/dto/mm_machine.go @@ -12,7 +12,8 @@ import ( type MmMachineGetPageReq struct { dto.Pagination `search:"-"` Status string `form:"status" search:"type:exact;column:status;table:mm_machine" comment:"状态 0-掉线 1-在线"` - MmMachineOrder + GroupId int `form:"groupId" search:"-" comment:"分组id"` + ShowBind int `form:"showBind" search:"-" comment:"是否显示绑定 1-已绑定 2-未绑定"` } type MmMachineOrder struct { @@ -34,12 +35,17 @@ func (m *MmMachineGetPageReq) GetNeedSearch() interface{} { } type MmMachineInsertReq struct { - Id int `json:"-" comment:"主键id"` // 主键id - MachineId string `json:"machineId" comment:"设备id"` - BiosId string `json:"biosId" comment:"设备biosid(绑定之后的id)"` - LastTime *time.Time `json:"lastTime" comment:"最后通讯时间"` - Content string `json:"content" comment:"白名单内容"` - Status int `json:"status" comment:"状态 0-掉线 1-在线"` + Id int `json:"-" comment:"主键id"` // 主键id + MachineId string `json:"machineId" comment:"设备id"` + BiosId string `json:"biosId" comment:"设备biosid(绑定之后的id)"` + GroupId int `json:"groupId" comment:"组id"` + Description string `json:"description" comment:"描述"` + LastTime *time.Time `json:"lastTime" comment:"最后通讯时间"` + Content string `json:"content" comment:"白名单内容"` + GroupItems string `json:"groupItems" comment:"组策略内容"` + Status int `json:"status" comment:"状态 0-掉线 1-在线"` + TaskLimit int `json:"taskLimit" comment:"任务限制 1-限制 2-不限制"` + AppLimit int `json:"appLimit" comment:"应用限制 1-限制 2-不限制"` common.ControlBy } @@ -49,10 +55,14 @@ func (s *MmMachineInsertReq) Generate(model *models.MmMachine) { } model.MachineId = s.MachineId model.BiosId = s.BiosId + model.GroupId = s.GroupId + model.Description = s.Description model.Content = s.Content model.Status = 0 - + model.GroupItems = s.GroupItems model.CreateBy = s.CreateBy // 添加这而,需要记录是被谁创建的 + model.TaskLimit = s.TaskLimit + model.AppLimit = s.AppLimit } func (s *MmMachineInsertReq) GetId() interface{} { @@ -60,28 +70,74 @@ func (s *MmMachineInsertReq) GetId() interface{} { } type MmMachineUpdateReq struct { - Id int `uri:"id" comment:"主键id"` // 主键id - MachineId string `json:"machineId" comment:"设备id"` - BiosId string `json:"biosId" comment:"设备biosid(绑定之后的id)"` - LastTime *time.Time `json:"lastTime" comment:"最后通讯时间"` - Content string `json:"content" comment:"白名单内容"` - Status int `json:"status" comment:"状态 0-掉线 1-在线"` + Id int `uri:"id" comment:"主键id"` // 主键id + MachineId string `json:"machineId" comment:"设备id"` + BiosId string `json:"biosId" comment:"设备biosid(绑定之后的id)"` + GroupId int `json:"groupId" comment:"组id"` + Description string `json:"description" comment:"描述"` + LastTime *time.Time `json:"lastTime" comment:"最后通讯时间"` + Content string `json:"content" comment:"白名单内容"` + GroupItems string `json:"groupItems" comment:"组策略内容"` + Status int `json:"status" comment:"状态 0-掉线 1-在线"` + TaskLimit int `json:"taskLimit" comment:"任务限制 1-限制 2-不限制"` + AppLimit int `json:"appLimit" comment:"应用限制 1-限制 2-不限制"` common.ControlBy } type MmMachineUpdateBatchReq struct { + Type int `json:"type" comment:"操作类型 0-进程白名单 1-应用白名单"` Ids []int `json:"ids"` Content string `json:"content" comment:"白名单内容"` common.ControlBy } +type MmMachineUpdateGroupBatchReq struct { + Ids []int `json:"ids"` + GroupId int `json:"groupId" comment:"组id"` +} + +type MmMachineUpdateDescriptionBatchReq struct { + Ids []int `json:"ids"` + Description string `json:"description" comment:"描述"` +} + +func (s *MmMachineUpdateDescriptionBatchReq) Validate() error { + if len(s.Ids) == 0 { + return errors.New("请选择需要修改的数据") + } + + return nil +} + +func (s *MmMachineUpdateGroupBatchReq) Validate() error { + if len(s.Ids) == 0 { + return errors.New("请选择要修改的数据") + } + + return nil +} + func (s *MmMachineUpdateBatchReq) Validate() error { if len(s.Ids) == 0 { return errors.New("请选择要修改的数据") } - if s.Content == "" { - return errors.New("请输入白名单内容") + if s.Type > 1 || s.Type < 0 { + return errors.New("操作类型错误") + } + return nil +} + +type MmMachineUpdateLimitBatchReq struct { + Type int `json:"type" comment:"操作类型 0-进程白名单 1-应用白名单"` + // All int `json:"all" comment:"是否全量更新 0-否 1-是"` + Ids []int `json:"ids" comment:"主键id"` + Limit int `json:"limit" comment:"任务限制 1-限制 2-不限制 3-只记录(只有进程限制有)"` +} + +func (s *MmMachineUpdateLimitBatchReq) Validate() error { + if len(s.Ids) == 0 { + return errors.New("请选择要修改的数据") } return nil @@ -98,7 +154,7 @@ type MmMachineCheckMachineReq struct { type Option struct { Label string `json:"label"` - Value int `json:"value"` + Value string `json:"value"` } type MmMachineUpdateWhiteReq struct { @@ -113,7 +169,12 @@ func (s *MmMachineUpdateReq) Generate(model *models.MmMachine) { } model.MachineId = s.MachineId model.BiosId = s.BiosId + model.GroupId = s.GroupId + model.Description = s.Description model.Content = s.Content + model.GroupItems = s.GroupItems + model.TaskLimit = s.TaskLimit + model.AppLimit = s.AppLimit model.UpdateBy = s.UpdateBy // 添加这而,需要记录是被谁更新的 } diff --git a/app/admin/service/dto/mm_machine_log.go b/app/admin/service/dto/mm_machine_log.go index b474e72..fa9fc76 100644 --- a/app/admin/service/dto/mm_machine_log.go +++ b/app/admin/service/dto/mm_machine_log.go @@ -11,6 +11,7 @@ type MmMachineLogGetPageReq struct { MachineId string `form:"machineId" search:"type:exact;column:machine_id;table:mm_machine_log" comment:"机器编号"` BiosId string `form:"biosId" search:"type:exact;column:bios_id;table:mm_machine_log" comment:"客户端唯一码"` Type string `form:"type" search:"type:exact;column:type;table:mm_machine_log" comment:"日志类型(1-软件运行,2-软件安装,3-软件卸载,4-退出软件,5-修改机器号,6-进程拦截,7-心跳请求"` + Remark string `form:"remark" search:"type:contains;column:remark;table:mm_machine_log" comment:"备注"` MmMachineLogOrder } @@ -31,6 +32,19 @@ func (m *MmMachineLogGetPageReq) GetNeedSearch() interface{} { return *m } +type MmMachineHeartResp struct { + Code int `json:"code" comment:"状态码 0-成功 1-失败"` + Msg string `json:"msg" comment:"消息"` + Content string `json:"c" comment:"内容"` + GroupItems string `json:"g" comment:"状态"` + TaskLimit int `json:"tl" comment:"进程限制 1-限制 2-不限制"` + AppLimit int `json:"al" comment:"应用限制 1-限制 2-不限制"` + KeywordLimit int `json:"kl" comment:"关键字限制 1-限制 2-不限制"` + HeartInterval int `json:"hi" comment:"心跳间隔(秒)"` + KeywordsInterval int `json:"ki" comment:"关键字间隔(秒)"` + InterceptInterval float64 `json:"ii" comment:"拦截间隔(小时)"` +} + type MmMachineLogInsertReq struct { Id int `json:"-" comment:"主键id"` // 主键id MachineId string `json:"machineId" form:"machineId" comment:"机器编号"` diff --git a/app/admin/service/dto/mm_risk_log.go b/app/admin/service/dto/mm_risk_log.go new file mode 100644 index 0000000..49c99b5 --- /dev/null +++ b/app/admin/service/dto/mm_risk_log.go @@ -0,0 +1,121 @@ +package dto + +import ( + "errors" + "go-admin/app/admin/models" + "go-admin/common/dto" + common "go-admin/common/models" +) + +type MmRiskLogGetPageReq struct { + dto.Pagination `search:"-"` + Content string `form:"content" search:"type:contains;column:content;table:mm_risk_log" comment:"关键字"` + MmRiskLogOrder +} + +type MmRiskLogOrder struct { + Id string `form:"idOrder" search:"type:order;column:id;table:mm_risk_log"` + Type string `form:"typeOrder" search:"type:order;column:type;table:mm_risk_log"` + Content string `form:"contentOrder" search:"type:order;column:content;table:mm_risk_log"` + CreatedAt string `form:"createdAtOrder" search:"type:order;column:created_at;table:mm_risk_log"` + UpdatedAt string `form:"updatedAtOrder" search:"type:order;column:updated_at;table:mm_risk_log"` + DeletedAt string `form:"deletedAtOrder" search:"type:order;column:deleted_at;table:mm_risk_log"` + CreateBy string `form:"createByOrder" search:"type:order;column:create_by;table:mm_risk_log"` + UpdateBy string `form:"updateByOrder" search:"type:order;column:update_by;table:mm_risk_log"` +} + +func (m *MmRiskLogGetPageReq) GetNeedSearch() interface{} { + return *m +} + +type MmRiskLogBatchReq struct { + MachineId string `json:"machineId" comment:"机器id"` + BiosId string `json:"biosId" comment:"bios id"` + Contents []MmRiskLogContentReq `json:"content" comment:"内容"` +} + +type MmRiskLogContentReq struct { + Type int `json:"type" comment:"类型 0-关键字 1-长度限制"` + Content string `json:"content" comment:"内容"` +} + +type MmRiskLogInsertReq struct { + Id int `json:"-" comment:"主键id"` // 主键id + MachineId string `json:"machineId" comment:"机器id"` + BiosId string `json:"biosId" comment:"bios id"` + Type int `json:"type" comment:"类型 0-关键字 1-长度限制"` + Content string `json:"content" comment:"内容"` + common.ControlBy +} + +func (s *MmRiskLogInsertReq) Valid() error { + if s.MachineId == "" { + return errors.New("机器id不能为空") + } + if s.BiosId == "" { + return errors.New("唯一码不能为空") + } + + if s.Type < 0 || s.Type > 1 { + return errors.New("类型错误") + } + + if s.Content == "" { + return errors.New("内容不能为空") + } + + return nil +} + +func (s *MmRiskLogInsertReq) Generate(model *models.MmRiskLog) { + if s.Id == 0 { + model.Model = common.Model{Id: s.Id} + } + model.Type = s.Type + model.Content = s.Content + model.CreateBy = s.CreateBy // 添加这而,需要记录是被谁创建的 +} + +func (s *MmRiskLogInsertReq) GetId() interface{} { + return s.Id +} + +type MmRiskLogUpdateReq struct { + Id int `uri:"id" comment:"主键id"` // 主键id + MachineId string `json:"machineId" comment:"机器id"` + BiosId string `json:"biosId" comment:"bios id"` + Type int `json:"type" comment:"类型 0-关键字 1-长度限制"` + Content string `json:"content" comment:"内容"` + common.ControlBy +} + +func (s *MmRiskLogUpdateReq) Generate(model *models.MmRiskLog) { + if s.Id == 0 { + model.Model = common.Model{Id: s.Id} + } + model.Type = s.Type + model.Content = s.Content + model.UpdateBy = s.UpdateBy // 添加这而,需要记录是被谁更新的 +} + +func (s *MmRiskLogUpdateReq) GetId() interface{} { + return s.Id +} + +// MmRiskLogGetReq 功能获取请求参数 +type MmRiskLogGetReq struct { + Id int `uri:"id"` +} + +func (s *MmRiskLogGetReq) GetId() interface{} { + return s.Id +} + +// MmRiskLogDeleteReq 功能删除请求参数 +type MmRiskLogDeleteReq struct { + Ids []int `json:"ids"` +} + +func (s *MmRiskLogDeleteReq) GetId() interface{} { + return s.Ids +} diff --git a/app/admin/service/dto/mm_white_template.go b/app/admin/service/dto/mm_white_template.go index 972af79..96f218e 100644 --- a/app/admin/service/dto/mm_white_template.go +++ b/app/admin/service/dto/mm_white_template.go @@ -1,27 +1,25 @@ package dto import ( - "go-admin/app/admin/models" "go-admin/common/dto" common "go-admin/common/models" ) type MmWhiteTemplateGetPageReq struct { - dto.Pagination `search:"-"` - Content string `form:"content" search:"type:contains;column:content;table:mm_white_template" comment:"进程白名单内容"` - MmWhiteTemplateOrder + dto.Pagination `search:"-"` + Content string `form:"content" search:"type:contains;column:content;table:mm_white_template" comment:"进程白名单内容"` + MmWhiteTemplateOrder } type MmWhiteTemplateOrder struct { - Id string `form:"idOrder" search:"type:order;column:id;table:mm_white_template"` - Content string `form:"contentOrder" search:"type:order;column:content;table:mm_white_template"` - CreatedAt string `form:"createdAtOrder" search:"type:order;column:created_at;table:mm_white_template"` - UpdatedAt string `form:"updatedAtOrder" search:"type:order;column:updated_at;table:mm_white_template"` - DeletedAt string `form:"deletedAtOrder" search:"type:order;column:deleted_at;table:mm_white_template"` - CreateBy string `form:"createByOrder" search:"type:order;column:create_by;table:mm_white_template"` - UpdateBy string `form:"updateByOrder" search:"type:order;column:update_by;table:mm_white_template"` - + Id string `form:"idOrder" search:"type:order;column:id;table:mm_white_template"` + Content string `form:"contentOrder" search:"type:order;column:content;table:mm_white_template"` + CreatedAt string `form:"createdAtOrder" search:"type:order;column:created_at;table:mm_white_template"` + UpdatedAt string `form:"updatedAtOrder" search:"type:order;column:updated_at;table:mm_white_template"` + DeletedAt string `form:"deletedAtOrder" search:"type:order;column:deleted_at;table:mm_white_template"` + CreateBy string `form:"createByOrder" search:"type:order;column:create_by;table:mm_white_template"` + UpdateBy string `form:"updateByOrder" search:"type:order;column:update_by;table:mm_white_template"` } func (m *MmWhiteTemplateGetPageReq) GetNeedSearch() interface{} { @@ -29,17 +27,17 @@ func (m *MmWhiteTemplateGetPageReq) GetNeedSearch() interface{} { } type MmWhiteTemplateInsertReq struct { - Id int `json:"-" comment:"主键id"` // 主键id - Content string `json:"content" comment:"进程白名单内容"` - common.ControlBy + Id int `json:"-" comment:"主键id"` // 主键id + Content string `json:"content" comment:"进程白名单内容"` + common.ControlBy } -func (s *MmWhiteTemplateInsertReq) Generate(model *models.MmWhiteTemplate) { - if s.Id == 0 { - model.Model = common.Model{ Id: s.Id } - } - model.Content = s.Content - model.CreateBy = s.CreateBy // 添加这而,需要记录是被谁创建的 +func (s *MmWhiteTemplateInsertReq) Generate(model *models.MmWhiteTemplate) { + if s.Id == 0 { + model.Model = common.Model{Id: s.Id} + } + model.Content = s.Content + model.CreateBy = s.CreateBy // 添加这而,需要记录是被谁创建的 } func (s *MmWhiteTemplateInsertReq) GetId() interface{} { @@ -47,17 +45,18 @@ func (s *MmWhiteTemplateInsertReq) GetId() interface{} { } type MmWhiteTemplateUpdateReq struct { - Id int `uri:"id" comment:"主键id"` // 主键id - Content string `json:"content" comment:"进程白名单内容"` - common.ControlBy + Id int `uri:"id" comment:"主键id"` // 主键id + Type int `json:"type" comment:"类型 0-进程白名单 1-应用白名单"` + Content string `json:"content" comment:"进程白名单内容"` + common.ControlBy } -func (s *MmWhiteTemplateUpdateReq) Generate(model *models.MmWhiteTemplate) { - if s.Id == 0 { - model.Model = common.Model{ Id: s.Id } - } - model.Content = s.Content - model.UpdateBy = s.UpdateBy // 添加这而,需要记录是被谁更新的 +func (s *MmWhiteTemplateUpdateReq) Generate(model *models.MmWhiteTemplate) { + if s.Id == 0 { + model.Model = common.Model{Id: s.Id} + } + model.Content = s.Content + model.UpdateBy = s.UpdateBy // 添加这而,需要记录是被谁更新的 } func (s *MmWhiteTemplateUpdateReq) GetId() interface{} { @@ -66,8 +65,9 @@ func (s *MmWhiteTemplateUpdateReq) GetId() interface{} { // MmWhiteTemplateGetReq 功能获取请求参数 type MmWhiteTemplateGetReq struct { - Id int `uri:"id"` + Id int `uri:"id"` } + func (s *MmWhiteTemplateGetReq) GetId() interface{} { return s.Id } diff --git a/app/admin/service/mm_group.go b/app/admin/service/mm_group.go new file mode 100644 index 0000000..107a60c --- /dev/null +++ b/app/admin/service/mm_group.go @@ -0,0 +1,144 @@ +package service + +import ( + "errors" + + "github.com/go-admin-team/go-admin-core/sdk/service" + "gorm.io/gorm" + + "go-admin/app/admin/models" + "go-admin/app/admin/service/dto" + "go-admin/common/actions" + cDto "go-admin/common/dto" +) + +type MmGroup struct { + service.Service +} + +// GetPage 获取MmGroup列表 +func (e *MmGroup) GetPage(c *dto.MmGroupGetPageReq, p *actions.DataPermission, list *[]models.MmGroup, count *int64) error { + var err error + var data models.MmGroup + + err = e.Orm.Model(&data). + Scopes( + cDto.MakeCondition(c.GetNeedSearch()), + cDto.Paginate(c.GetPageSize(), c.GetPageIndex()), + actions.Permission(data.TableName(), p), + ). + Find(list).Limit(-1).Offset(-1). + Count(count).Error + if err != nil { + e.Log.Errorf("MmGroupService GetPage error:%s \r\n", err) + return err + } + return nil +} + +// Get 获取MmGroup对象 +func (e *MmGroup) Get(d *dto.MmGroupGetReq, p *actions.DataPermission, model *models.MmGroup) error { + var data models.MmGroup + + err := e.Orm.Model(&data). + Scopes( + actions.Permission(data.TableName(), p), + ). + First(model, d.GetId()).Error + if err != nil && errors.Is(err, gorm.ErrRecordNotFound) { + err = errors.New("查看对象不存在或无权查看") + e.Log.Errorf("Service GetMmGroup error:%s \r\n", err) + return err + } + if err != nil { + e.Log.Errorf("db error:%s", err) + return err + } + return nil +} + +// Insert 创建MmGroup对象 +func (e *MmGroup) Insert(c *dto.MmGroupInsertReq) error { + var err error + var data models.MmGroup + var count int64 + c.Generate(&data) + + e.Orm.Model(data).Where("group_name = ?", data.GroupName).Count(&count) + + if count > 0 { + return errors.New("分组名称已存在") + } + + err = e.Orm.Create(&data).Error + if err != nil { + e.Log.Errorf("MmGroupService Insert error:%s \r\n", err) + return err + } + return nil +} + +// Update 修改MmGroup对象 +func (e *MmGroup) Update(c *dto.MmGroupUpdateReq, p *actions.DataPermission) error { + var err error + var data = models.MmGroup{} + var count int64 + e.Orm.Scopes( + actions.Permission(data.TableName(), p), + ).First(&data, c.GetId()) + c.Generate(&data) + + e.Orm.Model(data).Where("group_name = ? and id <> ?", data.GroupName, c.Id).Count(&count) + + if count > 0 { + return errors.New("分组名称已存在") + } + + db := e.Orm.Save(&data) + if err = db.Error; err != nil { + e.Log.Errorf("MmGroupService Save error:%s \r\n", err) + return err + } + if db.RowsAffected == 0 { + return errors.New("无权更新该数据") + } + return nil +} + +// Remove 删除MmGroup +func (e *MmGroup) Remove(d *dto.MmGroupDeleteReq, p *actions.DataPermission) error { + var data models.MmGroup + + db := e.Orm.Model(&data). + Scopes( + actions.Permission(data.TableName(), p), + ).Delete(&data, d.GetId()) + if err := db.Error; err != nil { + e.Log.Errorf("Service RemoveMmGroup error:%s \r\n", err) + return err + } + if db.RowsAffected == 0 { + return errors.New("无权删除该数据") + } + + e.Orm.Model(models.MmMachine{}).Where("group_id in ?", d.Ids).Update("group_id", 0) + return nil +} + +// GetOptions 获取MmGroup选项 +func (e *MmGroup) GetOptions(list *[]dto.MmGroupOption) error { + var datas []models.MmGroup + if err := e.Orm.Model(models.MmGroup{}).Find(&datas).Error; err != nil { + e.Log.Errorf("Service GetMmGroupOptions error:%s \r\n", err) + return err + } + + for _, data := range datas { + var option dto.MmGroupOption + option.Value = data.Id + option.Label = data.GroupName + *list = append(*list, option) + } + + return nil +} diff --git a/app/admin/service/mm_keyword.go b/app/admin/service/mm_keyword.go new file mode 100644 index 0000000..9ce5749 --- /dev/null +++ b/app/admin/service/mm_keyword.go @@ -0,0 +1,196 @@ +package service + +import ( + "encoding/json" + "errors" + "fmt" + "strconv" + "time" + + "github.com/go-admin-team/go-admin-core/logger" + "github.com/go-admin-team/go-admin-core/sdk/service" + "gorm.io/gorm" + + "go-admin/app/admin/models" + "go-admin/app/admin/service/dto" + "go-admin/common/actions" + cDto "go-admin/common/dto" + "go-admin/common/enums" + "go-admin/common/helper" +) + +type MmKeyword struct { + service.Service +} + +// GetPage 获取MmKeyword列表 +func (e *MmKeyword) GetPage(c *dto.MmKeywordGetPageReq, p *actions.DataPermission, list *[]models.MmKeyword, count *int64) error { + var err error + var data models.MmKeyword + + err = e.Orm.Model(&data). + Scopes( + cDto.MakeCondition(c.GetNeedSearch()), + cDto.Paginate(c.GetPageSize(), c.GetPageIndex()), + actions.Permission(data.TableName(), p), + ). + Find(list).Limit(-1).Offset(-1). + Count(count).Error + if err != nil { + e.Log.Errorf("MmKeywordService GetPage error:%s \r\n", err) + return err + } + return nil +} + +// Get 获取MmKeyword对象 +func (e *MmKeyword) Get(d *dto.MmKeywordGetReq, p *actions.DataPermission, model *models.MmKeyword) error { + var data models.MmKeyword + + err := e.Orm.Model(&data). + Scopes( + actions.Permission(data.TableName(), p), + ). + First(model, d.GetId()).Error + if err != nil && errors.Is(err, gorm.ErrRecordNotFound) { + err = errors.New("查看对象不存在或无权查看") + e.Log.Errorf("Service GetMmKeyword error:%s \r\n", err) + return err + } + if err != nil { + e.Log.Errorf("db error:%s", err) + return err + } + return nil +} + +// Insert 创建MmKeyword对象 +func (e *MmKeyword) Insert(c *dto.MmKeywordInsertReq) error { + var err error + var data models.MmKeyword + c.Generate(&data) + err = e.Orm.Create(&data).Error + if err != nil { + e.Log.Errorf("MmKeywordService Insert error:%s \r\n", err) + return err + } + + e.ReloadMachineCache(true) + return nil +} + +// 根据区间生成 +func (e *MmKeyword) InsertBatch(req *dto.MmKeywordInsertBatchReq) error { + datas := make([]models.MmKeyword, 0) + + for i := req.Start; i <= req.End; i++ { + data := models.MmKeyword{ + Type: req.Type, + Keyword: strconv.Itoa(i), + } + + datas = append(datas, data) + } + err := e.Orm.Create(&datas).Error + if err != nil { + e.Log.Errorf("MmKeywordService InsertBatch error:%s \r\n", err) + return err + } + + e.ReloadMachineCache(true) + + return nil +} + +// 重新加载变更缓存 +// isAll 是否全部重新加载 +func (e *MmKeyword) ReloadMachineCache(isAll bool) { + var datas []models.MmKeyword + cache := dto.MmKeywordCacheResp{} + e.Orm.Model(models.MmKeyword{}).Select("type", "keyword").Find(&datas) + machineIds := make([]string, 0) + e.Orm.Model(models.MmMachine{}).Select("machine_id").Find(&machineIds) + for _, item := range datas { + switch item.Type { + case 0: + cache.Keywords = append(cache.Keywords, item.Keyword) + case 1: + cache.Length = append(cache.Length, item.Keyword) + case 2: + cache.LengthIgnore = append(cache.LengthIgnore, item.Keyword) + } + } + bytes, _ := json.Marshal(cache) + helper.DefaultRedis.SetString(enums.Keywords, string(bytes)) + + if isAll && (len(cache.Keywords) > 0 || len(cache.Length) > 0 || len(cache.LengthIgnore) > 0) { + + for _, machineId := range machineIds { + key := fmt.Sprintf(enums.MachineKeywords, machineId) + + helper.DefaultRedis.SetStringExpire(key, string(bytes), time.Hour*3) + } + } +} + +// Update 修改MmKeyword对象 +func (e *MmKeyword) Update(c *dto.MmKeywordUpdateReq, p *actions.DataPermission) error { + var err error + var data = models.MmKeyword{} + e.Orm.Scopes( + actions.Permission(data.TableName(), p), + ).First(&data, c.GetId()) + c.Generate(&data) + + db := e.Orm.Save(&data) + if err = db.Error; err != nil { + e.Log.Errorf("MmKeywordService Save error:%s \r\n", err) + return err + } + if db.RowsAffected == 0 { + return errors.New("无权更新该数据") + } + + e.ReloadMachineCache(true) + return nil +} + +// Remove 删除MmKeyword +func (e *MmKeyword) Remove(d *dto.MmKeywordDeleteReq, p *actions.DataPermission) error { + var data models.MmKeyword + + db := e.Orm.Model(&data). + Scopes( + actions.Permission(data.TableName(), p), + ).Delete(&data, d.GetId()) + if err := db.Error; err != nil { + e.Log.Errorf("Service RemoveMmKeyword error:%s \r\n", err) + return err + } + if db.RowsAffected == 0 { + return errors.New("无权删除该数据") + } + + e.ReloadMachineCache(true) + return nil +} + +func (e *MmKeyword) GetKeywords(machineId string) (string, error) { + result := "" + + if machineId == "" { + key := fmt.Sprintf(enums.Keywords) + result, _ = helper.DefaultRedis.GetString(key) + + logger.Infof("没有获取keywords缓存%s", key) + } else { + key := fmt.Sprintf(enums.MachineKeywords, machineId) + result, _ = helper.DefaultRedis.GetString(key) + + if err := helper.DefaultRedis.DeleteString(key); err != nil { + logger.Infof("删除keywords缓存失败%v", err) + } + } + + return result, nil +} diff --git a/app/admin/service/mm_machine.go b/app/admin/service/mm_machine.go index 1b9fb42..3e26fa7 100644 --- a/app/admin/service/mm_machine.go +++ b/app/admin/service/mm_machine.go @@ -4,6 +4,7 @@ import ( "errors" "fmt" "strconv" + "strings" "time" "github.com/go-admin-team/go-admin-core/sdk/service" @@ -13,6 +14,8 @@ import ( "go-admin/app/admin/service/dto" "go-admin/common/actions" cDto "go-admin/common/dto" + "go-admin/common/enums" + "go-admin/common/helper" ) type MmMachine struct { @@ -24,12 +27,28 @@ func (e *MmMachine) GetPage(c *dto.MmMachineGetPageReq, p *actions.DataPermissio var err error var data models.MmMachine - err = e.Orm.Model(&data). + query := e.Orm.Model(&data). + Order(" LENGTH(machine_id) asc, machine_id asc"). Scopes( cDto.MakeCondition(c.GetNeedSearch()), cDto.Paginate(c.GetPageSize(), c.GetPageIndex()), actions.Permission(data.TableName(), p), - ). + ) + + if c.GroupId > 0 { + query = query.Where("group_id =?", c.GroupId) + } else if c.GroupId == -1 { + query = query.Where("group_id = 0") + } + + switch c.ShowBind { + case 1: + query = query.Where("bios_id <> ''") + case 2: + query = query.Where("bios_id = '' or bios_id is null") + } + + err = query. Find(list).Limit(-1).Offset(-1). Count(count).Error if err != nil { @@ -64,6 +83,11 @@ func (e *MmMachine) Get(d *dto.MmMachineGetReq, p *actions.DataPermission, model func (e *MmMachine) Insert(c *dto.MmMachineInsertReq) error { var err error var data models.MmMachine + result := getDistictApp(c.Content) + c.Content = strings.Join(result, "\n") + groupItems := getDistictApp(c.GroupItems) + c.GroupItems = strings.Join(groupItems, "\n") + c.Generate(&data) err = e.Orm.Transaction(func(tx *gorm.DB) error { @@ -87,6 +111,28 @@ func (e *MmMachine) Insert(c *dto.MmMachineInsertReq) error { e.Log.Errorf("MmMachineService Insert error:%s \r\n", err) return err } + + //保存更新缓存 + if data.MachineId != "" { + content := c.Content + groupItems := c.GroupItems + key := fmt.Sprintf(enums.MachineContentKey, data.MachineId) + key2 := fmt.Sprintf(enums.MachineGroupKey, data.MachineId) + var templates []models.MmWhiteTemplate + + e.Orm.Model(models.MmWhiteTemplate{}).Find(&templates) + + for _, item := range templates { + if item.Type == 0 { + content = item.Content + } else if item.Type == 1 { + groupItems = item.Content + } + } + + helper.DefaultRedis.SetStringExpire(key, content, time.Hour*3) + helper.DefaultRedis.SetStringExpire(key2, groupItems, time.Hour*3) + } return nil } @@ -94,6 +140,12 @@ func (e *MmMachine) Insert(c *dto.MmMachineInsertReq) error { func (e *MmMachine) Update(c *dto.MmMachineUpdateReq, p *actions.DataPermission) error { var err error var data = models.MmMachine{} + + result := getDistictApp(c.Content) + c.Content = strings.Join(result, "\n") + groupItems := getDistictApp(c.GroupItems) + c.GroupItems = strings.Join(groupItems, "\n") + e.Orm.Scopes( actions.Permission(data.TableName(), p), ).First(&data, c.GetId()) @@ -122,16 +174,120 @@ func (e *MmMachine) Update(c *dto.MmMachineUpdateReq, p *actions.DataPermission) return nil }) + //保存更新缓存 + if data.MachineId != "" { + content := c.Content + groupItems := c.GroupItems + key := fmt.Sprintf(enums.MachineContentKey, data.MachineId) + key2 := fmt.Sprintf(enums.MachineGroupKey, data.MachineId) + + if data.Content == "" || data.GroupItems == "" { + var templates []models.MmWhiteTemplate + + e.Orm.Model(models.MmWhiteTemplate{}).Find(&templates) + + for _, item := range templates { + if item.Type == 0 && content == "" { + content = item.Content + } else if item.Type == 1 && groupItems == "" { + groupItems = item.Content + } + } + } + + helper.DefaultRedis.SetStringExpire(key, content, time.Hour*3) + helper.DefaultRedis.SetStringExpire(key2, groupItems, time.Hour*3) + } + return err } +func (e *MmMachine) UpdateLimitBatch(req *dto.MmMachineUpdateLimitBatchReq, p *actions.DataPermission) error { + mapData := map[string]interface{}{} + + if req.Type == 0 && req.Limit > 0 { + mapData["task_limit"] = req.Limit + } + + if req.Type == 1 && req.Limit > 0 { + mapData["app_limit"] = req.Limit + } + + if len(mapData) == 0 { + return errors.New("无更新内容") + } + + if len(req.Ids) > 0 { + if err := e.Orm.Model(&models.MmMachine{}).Where("id in (?)", req.Ids).Updates(mapData).Error; err != nil { + e.Log.Errorf("Service UpdateLimitBatch error:%s \r\n", err) + return err + } + } + + return nil +} + // 批量修改白名单 func (e *MmMachine) UpdateBatch(req *dto.MmMachineUpdateBatchReq, p *actions.DataPermission) error { - if err := e.Orm.Model(&models.MmMachine{}).Where("id in (?)", req.Ids).Updates(map[string]interface{}{"content": req.Content, "update_by": req.UpdateBy, "updated_at": time.Now()}).Error; err != nil { + machineIds := make([]string, 0) + result := getDistictApp(req.Content) + req.Content = strings.Join(result, "\n") + mapData := map[string]interface{}{ + "update_by": req.UpdateBy, + "updated_at": time.Now(), + } + + switch req.Type { + case 0: + mapData["content"] = req.Content + case 1: + mapData["group_items"] = req.Content + default: + return errors.New("类型不存在") + } + + if err := e.Orm.Model(&models.MmMachine{}).Where("id in (?)", req.Ids).Updates(mapData).Error; err != nil { e.Log.Errorf("Service UpdateBatch error:%s \r\n", err) return err } + e.Orm.Model(&models.MmWhiteTemplate{}).Where("id in ?", req.Ids).Select("machine_id").Find(&machineIds) + + switch { + case req.Type == 0: + var content string + if req.Content == "" { + var template models.MmWhiteTemplate + e.Orm.Model(template).Where("type = 0").First(&template) + content = template.Content + } + for _, item := range machineIds { + key := fmt.Sprintf(enums.MachineContentKey, item) + if content != "" { + helper.DefaultRedis.SetStringExpire(key, content, time.Hour*3) + } else { + helper.DefaultRedis.SetStringExpire(key, req.Content, time.Hour*3) + } + } + case req.Type == 1: + var content string + if req.Content == "" { + var template models.MmWhiteTemplate + e.Orm.Model(template).Where("type = 1").First(&template) + content = template.Content + } + + for _, item := range machineIds { + key := fmt.Sprintf(enums.MachineContentKey, item) + + if content != "" { + helper.DefaultRedis.SetStringExpire(key, content, time.Hour*3) + } else { + helper.DefaultRedis.SetStringExpire(key, req.Content, time.Hour*3) + } + } + } + return nil } @@ -166,26 +322,116 @@ func (e *MmMachine) GetPassword() (string, error) { } // GetWhiteProcess 获取白名单进程列表 -func (e *MmMachine) GetWhiteProcess(req *dto.MmMachineQueryWhiteListReq) (string, error) { +func (e *MmMachine) GetWhiteProcess(req *dto.MmMachineQueryWhiteListReq, useCache bool) (dto.MmMachineHeartResp, error) { + result := e.GetHeartResp(req.MachineId, useCache) + + return result, nil +} + +// GetWhiteApp 获取白名单应用列表 +// machineId 机器id +// cache 是否获取变更缓存 +func (e *MmMachine) GetHeartResp(machineId string, cache bool) dto.MmMachineHeartResp { var machine models.MmMachine + var config models.SysConfig + var keywordIntevalConfig models.SysConfig + var keywordLimitConfig models.SysConfig + var taskLimitConfig models.SysConfig + var appLimitConfig models.SysConfig + var interceptConfig models.SysConfig + configService := SysConfig{Service: e.Service} + result := dto.MmMachineHeartResp{} + heartInterval := 0 + keywordHeartInterval := 0 - e.Orm.Model(machine).Where("machine_id = ?", req.MachineId).First(&machine) + e.Orm.Model(machine).Where("machine_id = ?", machineId).First(&machine) + config, _ = configService.GetByKey("machine_heart_interval") + keywordIntevalConfig, _ = configService.GetByKey("mm_keyword_interval") + keywordLimitConfig, _ = configService.GetByKey("mm_keyword_enable") + taskLimitConfig, _ = configService.GetByKey("mm_task_limit") + appLimitConfig, _ = configService.GetByKey("mm_app_limit") + interceptConfig, _ = configService.GetByKey("mm_intecept_inteval") - //没有就返回模板配置 - if machine.Content == "" { - var whiteTemplate models.MmWhiteTemplate - e.Orm.Model(whiteTemplate).First(&whiteTemplate) - - return whiteTemplate.Content, nil - } else { - return machine.Content, nil + if config.ConfigValue != "" { + heartInterval, _ = strconv.Atoi(config.ConfigValue) } + + if keywordIntevalConfig.ConfigValue != "" { + keywordHeartInterval, _ = strconv.Atoi(keywordIntevalConfig.ConfigValue) + } + + intercept, _ := strconv.ParseFloat(interceptConfig.ConfigValue, 64) + //默认一小时 + if intercept > 0 { + result.InterceptInterval = intercept + } else { + result.InterceptInterval = 1 + } + + //从缓存获取变更 + if cache { + contentKey := fmt.Sprintf(enums.MachineContentKey, machineId) + contentVal, _ := helper.DefaultRedis.GetString(contentKey) + groupKey := fmt.Sprintf(enums.MachineGroupKey, machineId) + groupItemVal, _ := helper.DefaultRedis.GetString(groupKey) + + result.Content = contentVal + result.GroupItems = groupItemVal + if contentVal != "" { + helper.DefaultRedis.DeleteString(contentKey) + } + if groupItemVal != "" { + helper.DefaultRedis.DeleteString(groupKey) + } + } else { + //没有就返回模板配置 + if machine.Content == "" { + var whiteTemplate models.MmWhiteTemplate + e.Orm.Model(whiteTemplate).Where("type = 0").First(&whiteTemplate) + + result.Content = whiteTemplate.Content + } else { + result.Content = machine.Content + } + + if machine.GroupItems == "" { + var temp models.MmWhiteTemplate + e.Orm.Model(temp).Where("type = 1").First(&temp) + result.GroupItems = temp.Content + } else { + result.GroupItems = machine.GroupItems + } + } + + result.TaskLimit, _ = strconv.Atoi(taskLimitConfig.ConfigValue) + + if result.TaskLimit < 1 || result.TaskLimit > 3 { + result.TaskLimit = 1 + } + + if appLimitConfig.ConfigValue != "2" { + result.AppLimit = 1 + } else { + result.AppLimit = 2 + } + + result.HeartInterval = heartInterval + result.KeywordsInterval = keywordHeartInterval + + if keywordLimitConfig.ConfigValue != "" { + result.KeywordLimit, _ = strconv.Atoi(keywordLimitConfig.ConfigValue) + } else { + result.KeywordLimit = 2 + } + + return result } // UpdateMachineWhite 更新机器白名单 func (e *MmMachine) UpdateMachineWhite(req *dto.MmMachineUpdateWhiteReq) error { var machine models.MmMachine - + result := getDistictApp(req.Content) + req.Content = strings.Join(result, "\n") e.Orm.Model(machine).Where("machine_id = ?", req.MachineId).Find(&machine) if machine.Id > 0 && machine.BiosId == req.BiosId { @@ -214,14 +460,36 @@ func (e *MmMachine) UpdateMachineWhite(req *dto.MmMachineUpdateWhiteReq) error { return nil } -func (e *MmMachine) CheckMachine(req *dto.MmMachineCheckMachineReq) error { +func getDistictApp(content string) []string { + apps := strings.Split(content, "\n") + seen := make(map[string]bool) + result := []string{} + + for _, app := range apps { + app = strings.TrimSpace(app) // 去除首尾空格 + if app == "" { + continue // 跳过空行 + } + if !seen[app] { + seen[app] = true + result = append(result, app) + } + } + return result +} + +func (e *MmMachine) CheckMachine(req *dto.MmMachineCheckMachineReq) dto.MmMachineHeartResp { var machine models.MmMachine now := time.Now() + resp := dto.MmMachineHeartResp{} + resp.Code = 1 if req.MachineId == "" { err := errors.New("设备编号不能为空") + resp.Msg = "设备编号不能为空" e.Log.Errorf("Service CheckMachine error:%s \r\n", err) - return err + + return resp } e.Orm.Model(machine).Where("machine_id = ?", req.MachineId).First(&machine) @@ -233,26 +501,37 @@ func (e *MmMachine) CheckMachine(req *dto.MmMachineCheckMachineReq) error { if err := e.Orm.Save(&machine).Error; err != nil { e.Log.Errorf("Service CheckMachine error:%s \r\n", err) - return err + resp.Msg = "保存失败" + return resp } } else if machine.Id > 0 && machine.BiosId != req.BiosId { - return errors.New("设备编号已被占用") + resp.Msg = "设备编号已被占用" + return resp } else if machine.Id == 0 && req.MachineId != "" { machine.MachineId = req.MachineId machine.BiosId = req.BiosId machine.Content = "" machine.Status = 0 + machine.TaskLimit = 1 + machine.AppLimit = 1 if err := e.Orm.Create(&machine).Error; err != nil { e.Log.Errorf("Service CheckMachine error:%s \r\n", err) - return err + resp.Msg = "保存失败" + return resp } } // e.Orm.Model(&models.MmMachine{}).Where("machine_id != ? and bios_id = ?", req.MachineId, req.BiosId).Updates(map[string]interface{}{"status": 0, "bios_id": ""}) e.Orm.Exec("update mm_machine set status = 0, bios_id = '' where machine_id != ? and bios_id = ?", req.MachineId, req.BiosId) - return nil + resp = e.GetHeartResp(req.MachineId, false) + + if resp.Content != "" { + resp.Code = 0 + } + + return resp } // ChangeStatus 改变机器状态 @@ -261,8 +540,10 @@ func (e *MmMachine) ChangeStatus() error { var data models.MmMachine var config models.SysConfig timeInterval := 5 * time.Minute + configService := SysConfig{Service: e.Service} + config, _ = configService.GetByKey("machine_status_change_time") - e.Orm.Model(config).Where("config_key = ?", "machine_status_change_time").First(&config) + // e.Orm.Model(config).Where("config_key = ?", "machine_status_change_time").First(&config) if config.ConfigValue != "" { interval, _ := strconv.Atoi(config.ConfigValue) @@ -301,7 +582,7 @@ func (e *MmMachine) GetMachineList() ([]dto.Option, error) { var machines []models.MmMachine result := make([]dto.Option, 0) - if err := e.Orm.Model(models.MmMachine{}).Find(&machines).Error; err != nil { + if err := e.Orm.Model(models.MmMachine{}).Order("LENGTH(machine_id) asc, machine_id asc").Find(&machines).Error; err != nil { e.Log.Errorf("Service GetMachineList error:%s \r\n", err) return result, err } @@ -312,7 +593,87 @@ func (e *MmMachine) GetMachineList() ([]dto.Option, error) { statusName = "在线" } label := fmt.Sprintf("%s(%s)", machine.MachineId, statusName) - result = append(result, dto.Option{Label: label, Value: machine.Id}) + result = append(result, dto.Option{Label: label, Value: machine.MachineId}) + } + + return result, nil +} + +// 更新机器分组 +func (e *MmMachine) UpdateGroupBatch(req *dto.MmMachineUpdateGroupBatchReq, p *actions.DataPermission) error { + if err := e.Orm.Model(&models.MmMachine{}).Where("id in (?)", req.Ids).Update("group_id", req.GroupId).Error; err != nil { + e.Log.Errorf("Service UpdateGroupBatch error:%s \r\n", err) + return err + } + + return nil +} + +// 清空所有机器数据 +func (e *MmMachine) ClearAll() error { + if err := e.Orm.Exec("truncate table mm_machine").Error; err != nil { + e.Log.Errorf("Service ClearAll error:%s \r\n", err) + return err + } + + return nil +} + +// 清空所有绑定 +func (e *MmMachine) Uninstall() error { + if err := e.Orm.Exec("update mm_machine set bios_id = '' where bios_id != ''").Error; err != nil { + e.Log.Errorf("Service Uninstall error:%s \r\n", err) + return err + } + return nil +} + +// 批量修改备注 +func (e *MmMachine) UpdateDescriptionBatch(req *dto.MmMachineUpdateDescriptionBatchReq, p *actions.DataPermission) error { + if err := e.Orm.Model(&models.MmMachine{}).Where("id in (?)", req.Ids).Update("description", req.Description).Error; err != nil { + e.Log.Errorf("Service UpdateDescriptionBatch error:%s \r\n", err) + return err + } + return nil +} + +// 查询设备间隔账号 +func (e *MmMachine) QueryIntervalAccount() (string, error) { + machineIds := make([]string, 0) + result := "" + lastMachineId := 0 + errMachineIds := make([]string, 0) + + if err := e.Orm.Model(models.MmMachine{}). + Order(" LENGTH(machine_id) asc, machine_id asc"). + Pluck("machine_id", &machineIds).Error; err != nil { + e.Log.Errorf("Service QueryIntervalAccount error:%s \r\n", err) + return result, err + } + + for _, machineId := range machineIds { + newId, _ := strconv.Atoi(machineId) + + if newId == 0 { + continue + } + + if lastMachineId == 0 { + lastMachineId = newId + continue + } + + //间隔超过1就不正常 + if newId-lastMachineId > 1 { + errMachineIds = append(errMachineIds, fmt.Sprintf("%v-%v", lastMachineId, newId)) + } + lastMachineId = newId + } + + if len(errMachineIds) > 0 { + result = fmt.Sprintf("设备编号%s中有设备编号未记录,请检查", strings.Join(errMachineIds, ",")) + } else { + result = "设备编号正常" } return result, nil diff --git a/app/admin/service/mm_machine_log.go b/app/admin/service/mm_machine_log.go index 0a0d7ce..58dda3e 100644 --- a/app/admin/service/mm_machine_log.go +++ b/app/admin/service/mm_machine_log.go @@ -110,10 +110,10 @@ func (e *MmMachineLog) Remove(d *dto.MmMachineLogDeleteReq, p *actions.DataPermi } // InsertLog 记录日志 -func (e *MmMachineLog) InsertLog(req *dto.MmMachineLogInsertReq) (string, error) { +func (e *MmMachineLog) InsertLog(req *dto.MmMachineLogInsertReq) (dto.MmMachineHeartResp, error) { var machine models.MmMachine var data models.MmMachineLog - result := "" + result := dto.MmMachineHeartResp{} req.Generate(&data) e.Orm.Model(machine).Where("machine_id = ?", req.MachineId).First(&machine) @@ -122,18 +122,34 @@ func (e *MmMachineLog) InsertLog(req *dto.MmMachineLogInsertReq) (string, error) if err := e.Orm.Model(&machine).Updates(map[string]interface{}{"status": 1, "last_time": time.Now()}).Error; err != nil { e.Log.Errorf("更新机器状态失败:%s", err) } + } else if machine.Id == 0 && req.Type == "7" { + now := time.Now() + machine.MachineId = req.MachineId + machine.BiosId = req.BiosId + machine.GroupId = 0 + machine.Description = "" + machine.LastTime = &now + machine.Content = "" + machine.GroupItems = "" + machine.Status = 1 + + if err := e.Orm.Create(&machine).Error; err != nil { + e.Log.Errorf("创建机器失败:%s", err) + } } - if err := e.Orm.Create(&data).Error; err != nil { - e.Log.Errorf("记录日志失败:%s", err) - return result, err + if req.Type != "7" { + if err := e.Orm.Create(&data).Error; err != nil { + e.Log.Errorf("记录日志失败:%s", err) + return result, err + } } //心跳 返回白名单信息 if req.Type == "7" { machineService := MmMachine{Service: e.Service} whiteReq := dto.MmMachineQueryWhiteListReq{MachineId: req.MachineId} - result, _ = machineService.GetWhiteProcess(&whiteReq) + result, _ = machineService.GetWhiteProcess(&whiteReq, true) } return result, nil diff --git a/app/admin/service/mm_risk_log.go b/app/admin/service/mm_risk_log.go new file mode 100644 index 0000000..298914e --- /dev/null +++ b/app/admin/service/mm_risk_log.go @@ -0,0 +1,141 @@ +package service + +import ( + "errors" + + "github.com/go-admin-team/go-admin-core/logger" + "github.com/go-admin-team/go-admin-core/sdk/service" + "gorm.io/gorm" + + "go-admin/app/admin/models" + "go-admin/app/admin/service/dto" + "go-admin/common/actions" + cDto "go-admin/common/dto" +) + +type MmRiskLog struct { + service.Service +} + +// GetPage 获取MmRiskLog列表 +func (e *MmRiskLog) GetPage(c *dto.MmRiskLogGetPageReq, p *actions.DataPermission, list *[]models.MmRiskLog, count *int64) error { + var err error + var data models.MmRiskLog + + err = e.Orm.Model(&data). + Scopes( + cDto.MakeCondition(c.GetNeedSearch()), + cDto.Paginate(c.GetPageSize(), c.GetPageIndex()), + actions.Permission(data.TableName(), p), + ). + Find(list).Limit(-1).Offset(-1). + Count(count).Error + if err != nil { + e.Log.Errorf("MmRiskLogService GetPage error:%s \r\n", err) + return err + } + return nil +} + +// Get 获取MmRiskLog对象 +func (e *MmRiskLog) Get(d *dto.MmRiskLogGetReq, p *actions.DataPermission, model *models.MmRiskLog) error { + var data models.MmRiskLog + + err := e.Orm.Model(&data). + Scopes( + actions.Permission(data.TableName(), p), + ). + First(model, d.GetId()).Error + if err != nil && errors.Is(err, gorm.ErrRecordNotFound) { + err = errors.New("查看对象不存在或无权查看") + e.Log.Errorf("Service GetMmRiskLog error:%s \r\n", err) + return err + } + if err != nil { + e.Log.Errorf("db error:%s", err) + return err + } + return nil +} + +// Insert 创建MmRiskLog对象 +func (e *MmRiskLog) Insert(c *dto.MmRiskLogInsertReq) error { + var err error + var data models.MmRiskLog + c.Generate(&data) + err = e.Orm.Create(&data).Error + if err != nil { + e.Log.Errorf("MmRiskLogService Insert error:%s \r\n", err) + return err + } + return nil +} + +// Update 修改MmRiskLog对象 +func (e *MmRiskLog) Update(c *dto.MmRiskLogUpdateReq, p *actions.DataPermission) error { + var err error + var data = models.MmRiskLog{} + e.Orm.Scopes( + actions.Permission(data.TableName(), p), + ).First(&data, c.GetId()) + c.Generate(&data) + + db := e.Orm.Save(&data) + if err = db.Error; err != nil { + e.Log.Errorf("MmRiskLogService Save error:%s \r\n", err) + return err + } + if db.RowsAffected == 0 { + return errors.New("无权更新该数据") + } + return nil +} + +// Remove 删除MmRiskLog +func (e *MmRiskLog) Remove(d *dto.MmRiskLogDeleteReq, p *actions.DataPermission) error { + var data models.MmRiskLog + + db := e.Orm.Model(&data). + Scopes( + actions.Permission(data.TableName(), p), + ).Delete(&data, d.GetId()) + if err := db.Error; err != nil { + e.Log.Errorf("Service RemoveMmRiskLog error:%s \r\n", err) + return err + } + if db.RowsAffected == 0 { + return errors.New("无权删除该数据") + } + return nil +} + +// Save 保存MmRiskLog对象 +func (e *MmRiskLog) Save(req *dto.MmRiskLogBatchReq) error { + datas := make([]models.MmRiskLog, 0) + + logger.Debug("req:%v", req) + + for _, item := range req.Contents { + data := models.MmRiskLog{} + data.MachineId = req.MachineId + data.BiosId = req.BiosId + data.Type = item.Type + data.Content = item.Content + datas = append(datas, data) + } + + if err := e.Orm.Save(&datas).Error; err != nil { + e.Log.Errorf("MmRiskLogService Save error:%s \r\n", err) + return err + } + return nil +} + +// ClearAll 清空日志 +func (e *MmRiskLog) ClearAll() error { + if err := e.Orm.Exec("TRUNCATE TABLE mm_risk_log").Error; err != nil { + e.Log.Errorf("清空日志失败:%s", err) + return err + } + return nil +} diff --git a/app/admin/service/mm_white_template.go b/app/admin/service/mm_white_template.go index 88dcb68..4a41386 100644 --- a/app/admin/service/mm_white_template.go +++ b/app/admin/service/mm_white_template.go @@ -2,14 +2,19 @@ package service import ( "errors" + "fmt" + "strings" + "time" - "github.com/go-admin-team/go-admin-core/sdk/service" + "github.com/go-admin-team/go-admin-core/sdk/service" "gorm.io/gorm" "go-admin/app/admin/models" "go-admin/app/admin/service/dto" "go-admin/common/actions" cDto "go-admin/common/dto" + "go-admin/common/enums" + "go-admin/common/helper" ) type MmWhiteTemplate struct { @@ -59,9 +64,9 @@ func (e *MmWhiteTemplate) Get(d *dto.MmWhiteTemplateGetReq, p *actions.DataPermi // Insert 创建MmWhiteTemplate对象 func (e *MmWhiteTemplate) Insert(c *dto.MmWhiteTemplateInsertReq) error { - var err error - var data models.MmWhiteTemplate - c.Generate(&data) + var err error + var data models.MmWhiteTemplate + c.Generate(&data) err = e.Orm.Create(&data).Error if err != nil { e.Log.Errorf("MmWhiteTemplateService Insert error:%s \r\n", err) @@ -72,22 +77,42 @@ func (e *MmWhiteTemplate) Insert(c *dto.MmWhiteTemplateInsertReq) error { // Update 修改MmWhiteTemplate对象 func (e *MmWhiteTemplate) Update(c *dto.MmWhiteTemplateUpdateReq, p *actions.DataPermission) error { - var err error - var data = models.MmWhiteTemplate{} - e.Orm.Scopes( - actions.Permission(data.TableName(), p), - ).First(&data, c.GetId()) - c.Generate(&data) + var err error + var data = models.MmWhiteTemplate{} + content := getDistictApp(c.Content) + c.Content = strings.Join(content, "\n") + e.Orm.Scopes( + actions.Permission(data.TableName(), p), + ).First(&data, c.GetId()) + c.Generate(&data) - db := e.Orm.Save(&data) - if err = db.Error; err != nil { - e.Log.Errorf("MmWhiteTemplateService Save error:%s \r\n", err) - return err - } - if db.RowsAffected == 0 { - return errors.New("无权更新该数据") - } - return nil + db := e.Orm.Save(&data) + if err = db.Error; err != nil { + e.Log.Errorf("MmWhiteTemplateService Save error:%s \r\n", err) + return err + } + if db.RowsAffected == 0 { + return errors.New("无权更新该数据") + } + + machineIds := make([]string, 0) + if c.Type == 0 { + e.Orm.Model(models.MmMachine{}).Where("content='' and bios_id!=''").Select("machine_id").Find(&machineIds) + + for _, machineId := range machineIds { + key := fmt.Sprintf(enums.MachineContentKey, machineId) + helper.DefaultRedis.SetStringExpire(key, c.Content, time.Hour*3) + } + } else { + e.Orm.Model(models.MmMachine{}).Where(" group_items='' and bios_id!=''").Select("machine_id").Find(&machineIds) + + for _, machineId := range machineIds { + key := fmt.Sprintf(enums.MachineGroupKey, machineId) + helper.DefaultRedis.SetStringExpire(key, c.Content, time.Hour*3) + } + } + + return nil } // Remove 删除MmWhiteTemplate @@ -99,11 +124,11 @@ func (e *MmWhiteTemplate) Remove(d *dto.MmWhiteTemplateDeleteReq, p *actions.Dat actions.Permission(data.TableName(), p), ).Delete(&data, d.GetId()) if err := db.Error; err != nil { - e.Log.Errorf("Service RemoveMmWhiteTemplate error:%s \r\n", err) - return err - } - if db.RowsAffected == 0 { - return errors.New("无权删除该数据") - } + e.Log.Errorf("Service RemoveMmWhiteTemplate error:%s \r\n", err) + return err + } + if db.RowsAffected == 0 { + return errors.New("无权删除该数据") + } return nil } diff --git a/app/admin/service/sys_config.go b/app/admin/service/sys_config.go index 016177f..6fa411b 100644 --- a/app/admin/service/sys_config.go +++ b/app/admin/service/sys_config.go @@ -1,11 +1,15 @@ package service import ( + "encoding/json" "errors" + "fmt" "go-admin/app/admin/models" "go-admin/app/admin/service/dto" cDto "go-admin/common/dto" + "go-admin/common/enums" + "go-admin/common/helper" "github.com/go-admin-team/go-admin-core/sdk/service" ) @@ -59,6 +63,11 @@ func (e *SysConfig) Insert(c *dto.SysConfigControl) error { e.Log.Errorf("Service InsertSysConfig error:%s", err) return err } + + key := fmt.Sprintf(enums.Config, data.ConfigKey) + val, _ := json.Marshal(data) + helper.DefaultRedis.SetString(key, string(val)) + return nil } @@ -78,9 +87,36 @@ func (e *SysConfig) Update(c *dto.SysConfigControl) error { return errors.New("无权更新该数据") } + + key := fmt.Sprintf(enums.Config, model.ConfigKey) + val, _ := json.Marshal(model) + helper.DefaultRedis.SetString(key, string(val)) return nil } +// GetByCache 获取缓存SysConfig对象 +func (e *SysConfig) GetByKey(key string) (models.SysConfig, error) { + redisKey := fmt.Sprintf(enums.Config, key) + val, _ := helper.DefaultRedis.GetString(redisKey) + result := models.SysConfig{} + if val != "" { + _ = json.Unmarshal([]byte(val), &result) + } + + if result.Id == 0 { + err := e.Orm.Model(result).Where("config_key = ?", key).First(&result).Error + if err != nil { + e.Log.Errorf("Service GetSysConfigByKey error:%s", err) + return result, err + } + + bytes, _ := json.Marshal(result) + helper.DefaultRedis.SetString(redisKey, string(bytes)) + } + + return result, nil +} + // SetSysConfig 修改SysConfig对象 func (e *SysConfig) SetSysConfig(c *[]dto.GetSetSysConfigReq) error { var err error @@ -153,6 +189,10 @@ func (e *SysConfig) Remove(d *dto.SysConfigDeleteReq) error { err = errors.New("无权删除该数据") return err } + + key := fmt.Sprintf(enums.Config, data.ConfigKey) + helper.DefaultRedis.DeleteString(key) + return nil } diff --git a/app/jobs/clear_job.go b/app/jobs/clear_job.go new file mode 100644 index 0000000..982aab7 --- /dev/null +++ b/app/jobs/clear_job.go @@ -0,0 +1,81 @@ +package jobs + +import ( + "fmt" + "os" + "path/filepath" + "time" + + "github.com/go-admin-team/go-admin-core/logger" + "github.com/go-admin-team/go-admin-core/sdk" + "github.com/go-admin-team/go-admin-core/sdk/config" + "gorm.io/gorm" +) + +type ClearLogJob struct { +} + +// 删除过期日志 +func (t ClearLogJob) Exec(arg interface{}) error { + str := time.Now().Format(timeFormat) + " [INFO] JobCore ClearLogJob exec success" + defer logger.Info(str) + var db *gorm.DB + + for _, item := range sdk.Runtime.GetDb() { + db = item + break + } + + ClearLogs(db) + + return nil +} + +func ClearLogs(orm *gorm.DB) { + dir := config.LoggerConfig.Path + + if dir == "" { + dir = "temp/logs" + } + + // 检查文件夹是否存在 + if _, err := os.Stat(dir); os.IsNotExist(err) { + fmt.Printf("Directory %s does not exist, skipping cleanup.\n", dir) + return + } + + // 获取当前时间 + now := time.Now() + expirateDay := 2 + + // 遍历指定文件夹中的所有文件 + err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error { + if err != nil { + return err + } + + // 只处理普通文件 + if !info.IsDir() { + // 获取文件的修改时间 + modTime := info.ModTime() + + // 计算文件修改时间与当前时间的差值 + duration := now.Sub(modTime) + + // 如果文件超过7天,则删除 + if duration > time.Duration(expirateDay)*24*time.Hour { + fmt.Printf("Deleting file: %s (Last modified: %s)\n", path, modTime) + err := os.Remove(path) + if err != nil { + return err + } + } + } + + return nil + }) + + if err != nil { + fmt.Printf("Error walking the path %v: %v\n", dir, err) + } +} diff --git a/cmd/api/server.go b/cmd/api/server.go index 3f922e8..961242c 100644 --- a/cmd/api/server.go +++ b/cmd/api/server.go @@ -2,6 +2,7 @@ package api import ( "context" + "encoding/json" "fmt" "net/http" "os" @@ -17,12 +18,16 @@ import ( "github.com/go-admin-team/go-admin-core/sdk/pkg" "github.com/pkg/errors" "github.com/spf13/cobra" + "gorm.io/gorm" "go-admin/app/admin/models" "go-admin/app/admin/router" + "go-admin/app/admin/service" "go-admin/app/jobs" "go-admin/common/database" + "go-admin/common/enums" "go-admin/common/global" + "go-admin/common/helper" common "go-admin/common/middleware" "go-admin/common/middleware/handler" "go-admin/common/storage" @@ -91,6 +96,9 @@ func run() error { Handler: sdk.Runtime.GetEngine(), } + //初始化redis连接 + helper.InitDefaultRedis(ext.ExtConfig.Redis.Addr, ext.ExtConfig.Redis.Password, ext.ExtConfig.Redis.Db) + go func() { jobs.InitJob() jobs.Setup(sdk.Runtime.GetDb()) @@ -114,6 +122,8 @@ func run() error { } } + initConfig() + go func() { // 服务连接 if config.SslConfig.Enable { @@ -176,11 +186,37 @@ func initRouter() { if config.SslConfig.Enable { r.Use(handler.TlsHandler()) } - //r.Use(middleware.Metrics()) - r.Use(common.Sentinel()). - Use(common.RequestId(pkg.TrafficKey)). + //r.Use(middleware.Metrics() + //Use(common.Sentinel()). + r.Use(common.RequestId(pkg.TrafficKey)). Use(api.SetRequestLogger) common.InitMiddleware(r) } + +func initConfig() { + var db *gorm.DB + dbs := sdk.Runtime.GetDb() + + for _, item := range dbs { + db = item + break + } + + configs := make([]models.SysConfig, 0) + db.Model(models.SysConfig{}).Find(&configs) + for _, config := range configs { + key := fmt.Sprintf(enums.Config, config.ConfigKey) + cacheContent, _ := json.Marshal(config) + + if err := helper.DefaultRedis.SetString(key, string(cacheContent)); err != nil { + log.Errorf("set redis key %s error, %s", key, err.Error()) + } + } + + keywordService := service.MmKeyword{} + keywordService.Orm = db + + keywordService.ReloadMachineCache(false) +} diff --git a/common/enums/redis_key.go b/common/enums/redis_key.go new file mode 100644 index 0000000..5db0e53 --- /dev/null +++ b/common/enums/redis_key.go @@ -0,0 +1,24 @@ +package enums + +const ( + //设备进程白名单更新缓存 {machineId} t代表模板 + MachineContentKey = "m_content:%s" + //设备进程白名单 {{machineId}} t代表模板 + MachineContentUsedIdKey = "m_content_used_id:%s" + //设备应用程序白名单更新缓存 {machineId} t代表模板 + MachineGroupKey = "m_group:%s" + //设备应用程序白名单 {{machineId}} t代表模板 + MachineGroupUsedIdKey = "m_group_used_id:%s" +) + +const ( + //关键字缓存 + Keywords = "keywords" + //设备更新关键字缓存 {machineId} + MachineKeywords = "m_keywords:%s" +) + +const ( + //系统配置缓存 + Config = "config:%s" +) diff --git a/common/helper/redis_helper.go b/common/helper/redis_helper.go new file mode 100644 index 0000000..c3cc6c1 --- /dev/null +++ b/common/helper/redis_helper.go @@ -0,0 +1,779 @@ +package helper + +import ( + "context" + "errors" + "fmt" + "log" + "math" + "reflect" + "strconv" + "time" + + "github.com/bytedance/sonic" + "github.com/go-redis/redis/v8" +) + +// RedisHelper 结构体封装了 Redis 客户端及上下文 +type RedisHelper struct { + client *redis.Client // Redis 客户端 + ctx context.Context // 上下文 + emptyCacheValue string // 缓存空值的标志 +} + +var DefaultRedis *RedisHelper + +// 初始化默认链接 +func InitDefaultRedis(addr, password string, db int) { + if DefaultRedis == nil { + DefaultRedis = NewRedisHelper(addr, password, db) + } + + log.Printf("初始化redis链接") +} + +// NewRedisHelper 创建一个新的 RedisHelper 实例 +func NewRedisHelper(addr, password string, db int) *RedisHelper { + rdb := redis.NewClient(&redis.Options{ + Addr: addr, // Redis 服务器地址 + Password: password, // Redis 密码 + DB: db, // 使用的数据库编号 + PoolSize: 50, + MinIdleConns: 10, + DialTimeout: 10 * time.Second, // 调整连接超时时间 + ReadTimeout: 10 * time.Second, // 调整读超时时间 + WriteTimeout: 10 * time.Second, // 调整写超时时间 + }) + + return &RedisHelper{ + client: rdb, + ctx: context.Background(), // 创建背景上下文 + } +} + +// 测试连接 +func (r *RedisHelper) Ping() error { + return r.client.Ping(r.ctx).Err() +} + +// SetString 设置字符串值 +func (r *RedisHelper) SetString(key, value string) error { + return r.client.Set(r.ctx, key, value, 0).Err() // 将值存储到指定的键 +} + +// 批量设置 +func (r *RedisHelper) BatchSet(maps *map[string]string) error { + pipe := r.client.Pipeline() + + for key, val := range *maps { + pipe.Set(r.ctx, key, val, 0) + } + + _, err := pipe.Exec(r.ctx) + + return err +} + +// SetString 设置字符串值 +func (r *RedisHelper) SetStringExpire(key, value string, expireTime time.Duration) error { + return r.client.Set(r.ctx, key, value, expireTime).Err() // 将值存储到指定的键 +} + +// SetString 设置字符串值 +func (r *RedisHelper) SetAdd(key, value string, expireTime time.Duration) error { + // 存储到 SET 中 + result, err := r.client.SAdd(r.ctx, key, value).Result() + if err != nil { + return err + } + + if result == 1 { + // 设置 SET 的过期时间 + err = r.client.Expire(r.ctx, key, expireTime).Err() + if err != nil { + return errors.New("设置过期时间失败:" + err.Error()) + } + + return nil + } else { + return errors.New("key已存在") + } +} + +// 设置对象 +func SetObjString[T any](r *RedisHelper, key string, value T) error { + keyValue, err := sonic.Marshal(value) + + if err != nil { + return err + } + + return r.SetString(key, string(keyValue)) +} + +// 获取对象 +func GetObjString[T any](r *RedisHelper, key string) (T, error) { + var result T + value, err := r.GetString(key) + + if err != nil { + return result, err + } + + err = sonic.Unmarshal([]byte(value), &result) + + if err != nil { + return result, err + } + + return result, nil +} + +func (r *RedisHelper) Get(key string) *redis.StringCmd { + return r.client.Get(r.ctx, key) +} + +/* +获取剩余时间 + - @key redis key +*/ +func (r *RedisHelper) TTL(key string) *redis.DurationCmd { + return r.client.TTL(r.ctx, key) +} + +// GetString 获取字符串值 +func (r *RedisHelper) GetString(key string) (string, error) { + return r.client.Get(r.ctx, key).Result() // 从指定的键获取值 +} + +// DeleteString 删除字符串键 +func (r *RedisHelper) DeleteString(key string) error { + return r.client.Del(r.ctx, key).Err() // 删除指定的键 +} + +// DeleteString 删除目录下所有key +func (r *RedisHelper) DeleteAll(key string) error { + keys, err := r.ScanKeys(key) + + if err != nil { + return err + } + + _, err = r.BatchDeleteKeys(keys) + return err +} + +/* +递增 + - @key rediskey +*/ +func (r *RedisHelper) Incr(key string) *redis.IntCmd { + return r.client.Incr(r.ctx, key) +} + +/* +设置过期时间 + - @key redis key + - @expiration 过期时间 +*/ +func (r *RedisHelper) Expire(key string, expiration time.Duration) *redis.BoolCmd { + return r.client.Expire(r.ctx, key, expiration) +} + +/* +批量删除 + + - @keys 键数组 +*/ +func (r *RedisHelper) BatchDeleteKeys(keys []string) (int, error) { + if r.client == nil { + return 0, errors.New("Redis client is nil") + } + if len(keys) == 0 { + return 0, nil + } + + deletedCount := 0 + batchSize := 1000 // 每批次删除的键数量 + for i := 0; i < len(keys); i += batchSize { + end := i + batchSize + if end > len(keys) { + end = len(keys) + } + batch := keys[i:end] + + _, err := r.client.Pipelined(r.ctx, func(pipe redis.Pipeliner) error { + for _, key := range batch { + pipe.Del(r.ctx, key) + deletedCount++ + } + return nil + }) + if err != nil { + return deletedCount, fmt.Errorf("failed to delete keys in batch: %v", err) + } + } + + return deletedCount, nil +} + +// DeleteKeysByPrefix 删除指定前缀的键 +func (r *RedisHelper) DeleteKeysByPrefix(prefixes ...string) error { + ctx := context.Background() + // 遍历每个前缀 + for _, prefix := range prefixes { + var cursor uint64 + var keys []string + + // 使用 SCAN 命令查找匹配的键 + for { + var err error + keys, cursor, err = r.client.Scan(ctx, cursor, prefix+"*", 1000).Result() + if err != nil { + return err + } + + // 删除匹配的键 + if len(keys) > 0 { + _, err := r.client.Del(ctx, keys...).Result() + if err != nil { + return err + } + fmt.Printf("Deleted keys with prefix '%s': %v\n", prefix, keys) + } + + // 如果游标为 0,表示迭代结束 + if cursor == 0 { + break + } + } + } + return nil +} + +// 查找所有value +func (r *RedisHelper) GetAllKeysAndValues(pattern string) ([]string, error) { + var cursor uint64 + var result = []string{} + + for { + // 使用 SCAN 命令获取匹配的键 + keys, nextCursor, err := r.client.Scan(r.ctx, cursor, pattern+"*", 1000).Result() + if err != nil { + log.Printf("Error scanning keys: %v", err) + return nil, err + } + + // 处理匹配到的键 + for _, key := range keys { + value, err := r.client.Get(r.ctx, key).Result() + if err != nil { + if err == redis.Nil { + fmt.Printf("Key %s does not exist\n", key) + } else { + fmt.Printf("Error getting value for key %s: %v", key, err) + } + } else { + result = append(result, value) + } + } + + // 如果 cursor 为 0,表示扫描完成 + if nextCursor == 0 { + break + } + cursor = nextCursor + } + + return result, nil +} + +// LPushList 将一个或多个值插入到列表的头部 +func (r *RedisHelper) LPushList(key string, values ...string) error { + return r.client.LPush(r.ctx, key, values).Err() // 将值插入到列表的头部 +} + +// RPushList 将一个或多个值插入到列表的尾部 +func (r *RedisHelper) RPushList(key string, values ...string) error { + return r.client.RPush(r.ctx, key, values).Err() // 将值插入到列表的尾部 +} + +// LPopList 从列表的头部弹出一个元素 +func (r *RedisHelper) LPopList(key string) (string, error) { + return r.client.LPop(r.ctx, key).Result() // 从列表的头部移除并返回第一个元素 +} + +// RPopList 从列表的尾部弹出一个元素 +func (r *RedisHelper) RPopList(key string) (string, error) { + return r.client.RPop(r.ctx, key).Result() // 从列表的尾部移除并返回最后一个元素 +} + +// LRangeList 获取列表中指定范围的元素 +func (r *RedisHelper) LRangeList(key string, start, stop int64) ([]string, error) { + return r.client.LRange(r.ctx, key, start, stop).Result() // 获取列表中指定范围的元素 +} + +// GetAllList 获取列表中的所有元素 +func (r *RedisHelper) GetAllList(key string) ([]string, error) { + values, err := r.client.LRange(r.ctx, key, 0, -1).Result() + if err == redis.Nil { + return nil, nil + } else if err != nil { + return nil, err + } + + // 检查是否包含空值标志 + if len(values) == 1 && values[0] == r.emptyCacheValue { + return nil, nil + } + + return values, nil +} + +func (r *RedisHelper) LRem(key, val string) (int64, error) { + count := 0 // 删除所有与 valueToRemove 相等的元素 + result, err := r.client.LRem(r.ctx, key, int64(count), val).Result() + if err != nil { + fmt.Printf("删除元素失败: %v\n", err) + } + + return result, nil +} + +func (r *RedisHelper) IsElementInList(key string, element string) (bool, error) { + var cursor int64 = 0 + const batchSize int64 = 1000 // 每批次获取的元素数量 + + for { + // 分批次获取列表元素 + elements, err := r.client.LRange(r.ctx, key, cursor, cursor+batchSize-1).Result() + if err != nil { + return false, err + } + if len(elements) == 0 { + break // 没有更多数据 + } + + // 遍历当前批次的元素 + for _, e := range elements { + if e == element { + return true, nil + } + } + + cursor += batchSize // 移动到下一批次 + } + + return false, nil +} + +/* +SetListCache 重新设置列表缓存 + - @expiration 0-过期 1-过期时间 +*/ +func (r *RedisHelper) SetListCache(key string, expiration time.Duration, values ...string) error { + tempKey := key + ":temp" + + // 使用事务来确保操作的原子性 + pipe := r.client.TxPipeline() + + // 将新数据插入到临时列表中 + pipe.RPush(r.ctx, tempKey, values) + + // 重命名临时列表为目标列表 + pipe.Rename(r.ctx, tempKey, key) + + if expiration > 0 { + // 设置目标列表的过期时间 + pipe.Expire(r.ctx, key, expiration) + } + + // 执行事务 + _, err := pipe.Exec(r.ctx) + return err +} + +// SetEmptyListCache 设置空值缓存 +func (r *RedisHelper) SetEmptyListCache(key string, expiration time.Duration) error { + // 使用一个特殊标志值表示列表为空 + _, err := r.client.RPush(r.ctx, key, r.emptyCacheValue).Result() + if err != nil { + return err + } + + // 设置列表的过期时间 + return r.client.Expire(r.ctx, key, expiration).Err() +} + +// scanKeys 使用 SCAN 命令获取所有匹配的键 +func (r *RedisHelper) ScanKeys(pattern string) ([]string, error) { + + var cursor uint64 + var keys []string + for { + var newKeys []string + var err error + + // SCAN 命令每次返回部分匹配的键 + newKeys, cursor, err = r.client.Scan(r.ctx, cursor, pattern, 1000).Result() + if err != nil { + return nil, err + } + keys = append(keys, newKeys...) + if cursor == 0 { + break + } + } + return keys, nil +} + +// 泛型函数,用于获取所有键的列表数据并合并为一个数组 +func GetAndMergeLists[T any](r *RedisHelper, keys []string) ([]T, error) { + var combinedList []T + for _, key := range keys { + // 获取每个键的列表数据 + listData, err := r.client.LRange(r.ctx, key, 0, -1).Result() + if err != nil { + return nil, err + } + + // 解码每个数据项为类型 T,并添加到结果列表中 + for _, data := range listData { + var item T + if err := sonic.Unmarshal([]byte(data), &item); err != nil { + return nil, err + } + combinedList = append(combinedList, item) + } + } + return combinedList, nil +} + +// SetNX 实现类似于 Redis 的 SETNX 命令 +func (r *RedisHelper) SetNX(key string, value interface{}, expiration time.Duration) (bool, error) { + result, err := r.client.Set(r.ctx, key, value, expiration).Result() + if err != nil { + return false, err + } + + // 如果键不存在则 result 会等于 "OK" + return result == "OK", nil +} + +func getFieldsFromStruct(obj interface{}) map[string]interface{} { + fields := make(map[string]interface{}) + val := reflect.ValueOf(obj) + typ := reflect.TypeOf(obj) + + for i := 0; i < val.NumField(); i++ { + field := typ.Field(i) + tag := field.Tag.Get("redis") + if tag != "" { + fieldVal := val.Field(i) + if fieldVal.Kind() == reflect.Slice || fieldVal.Kind() == reflect.Map { + // 处理切片或映射类型 + // 对于切片,使用索引作为字段名 + if fieldVal.Kind() == reflect.Slice { + for j := 0; j < fieldVal.Len(); j++ { + elem := fieldVal.Index(j).Interface() + fields[fmt.Sprintf("%s_%d", tag, j)] = elem + } + } else if fieldVal.Kind() == reflect.Map { + // 对于映射,使用键作为字段名 + for _, key := range fieldVal.MapKeys() { + elem := fieldVal.MapIndex(key).Interface() + fields[fmt.Sprintf("%s_%v", tag, key.Interface())] = elem + } + } + } else { + fields[tag] = fieldVal.Interface() + } + } + } + + return fields +} + +func (r *RedisHelper) SetHashWithTags(key string, obj interface{}) error { + fields := getFieldsFromStruct(obj) + _, err := r.client.HSet(r.ctx, key, fields).Result() + return err +} + +// HSetField 设置哈希中的一个字段 +func (r *RedisHelper) HSetField(key, field string, value interface{}) error { + _, err := r.client.HSet(r.ctx, key, field, value).Result() + if err != nil { + log.Printf("Error setting field %s in hash %s: %v", field, key, err) + return err + } + return nil +} + +// HSetMultipleFields 设置哈希中的多个字段 +func (r *RedisHelper) HSetMultipleFields(key string, fields map[string]interface{}) error { + _, err := r.client.HSet(r.ctx, key, fields).Result() + if err != nil { + log.Printf("Error setting multiple fields in hash %s: %v", key, err) + return err + } + return nil +} + +// HGetField 获取哈希中某个字段的值 +func (r *RedisHelper) HGetField(key, field string) (string, error) { + val, err := r.client.HGet(r.ctx, key, field).Result() + if err != nil { + if err == redis.Nil { + return "", nil // Field does not exist + } + log.Printf("Error getting field %s from hash %s: %v", field, key, err) + return "", err + } + return val, nil +} + +// HGetAllFields 获取哈希中所有字段的值 +func (r *RedisHelper) HGetAllFields(key string) (map[string]string, error) { + fields, err := r.client.HGetAll(r.ctx, key).Result() + if err != nil { + log.Printf("Error getting all fields from hash %s: %v", key, err) + return nil, err + } + return fields, nil +} + +// HDelField 删除哈希中的某个字段 +func (r *RedisHelper) HDelField(key, field string) error { + _, err := r.client.HDel(r.ctx, key, field).Result() + if err != nil { + log.Printf("Error deleting field %s from hash %s: %v", field, key, err) + return err + } + return nil +} + +// 删除哈希 +func (r *RedisHelper) HDelAll(key string) error { + _, err := r.client.Del(r.ctx, key).Result() + if err != nil { + log.Printf("Error deleting from hash %s: %v", key, err) + return err + } + return nil +} + +// HKeys 获取哈希中所有字段的名字 +func (r *RedisHelper) HKeys(key string) ([]string, error) { + fields, err := r.client.HKeys(r.ctx, key).Result() + if err != nil { + log.Printf("Error getting keys from hash %s: %v", key, err) + return nil, err + } + return fields, nil +} + +func (r *RedisHelper) HExists(key, field, value string) (bool, error) { + exists, err := r.client.HExists(r.ctx, key, field).Result() + if err != nil { + return false, fmt.Errorf("check existence failed: %v", err) + } + if !exists { + return false, nil + } + + storedValue, err := r.client.HGet(r.ctx, key, field).Result() + if err != nil { + return false, fmt.Errorf("get value failed: %v", err) + } + + // 如果值是 JSON,比较前反序列化 + var storedObj, inputObj interface{} + if err := sonic.UnmarshalString(storedValue, &storedObj); err != nil { + return false, fmt.Errorf("unmarshal stored value failed: %v", err) + } + if err := sonic.UnmarshalString(value, &inputObj); err != nil { + return false, fmt.Errorf("unmarshal input value failed: %v", err) + } + + // 比较两个对象(需要根据实际类型调整) + return fmt.Sprintf("%v", storedObj) == fmt.Sprintf("%v", inputObj), nil +} + +// DelSet 从集合中删除元素 +func (r *RedisHelper) DelSet(key string, value string) error { + _, err := r.client.SRem(r.ctx, key, value).Result() + if err != nil { + log.Printf("Error del value from set %s: %v", key, err) + return err + } + return nil +} + +func (r *RedisHelper) Sismember(key string, value string) (bool, error) { + result, err := r.client.SIsMember(r.ctx, key, value).Result() + if err != nil { + log.Printf("Error Sismember value from set %s: %v", key, err) + } + return result, err +} + +// sort set start +// 批量添加 +func (r *RedisHelper) BatchSortSet(key string, array []*redis.Z) error { + pipe := r.client.Pipeline() + for _, val := range array { + pipe.ZAdd(r.ctx, key, val) + } + + _, err := pipe.Exec(r.ctx) + return err +} + +// 单一写入 sort set +func (e *RedisHelper) SignelAdd(key string, score float64, member string) error { + // 先删除具有相同 score 的所有成员 + scoreStr := strconv.FormatFloat(score, 'g', -1, 64) + _, err := e.client.ZRemRangeByScore(e.ctx, key, scoreStr, scoreStr).Result() + + if err != nil { + fmt.Printf("删除score失败,err:%s", err.Error()) + } + _, err = e.client.ZAdd(e.ctx, key, &redis.Z{ + Score: score, + Member: member, + }).Result() + + if err != nil { + return err + } + + return nil +} + +// 写入数据 +func (e *RedisHelper) AddSortSet(key string, score float64, member string) error { + _, err := e.client.ZAdd(e.ctx, key, &redis.Z{ + Score: score, + Member: member, + }).Result() + + if err != nil { + return err + } + + return nil +} + +// 删除指定元素 +func (e *RedisHelper) DelSortSet(key, member string) error { + return e.client.ZRem(e.ctx, key, member).Err() +} + +// RemoveBeforeScore 移除 Sorted Set 中分数小于等于指定值的数据 +// key: Sorted Set 的键 +// score: 分数上限,所有小于等于此分数的元素将被移除 +// 返回值: 移除的元素数量和可能的错误 +func (e *RedisHelper) RemoveBeforeScore(key string, score float64) (int64, error) { + if key == "" { + return 0, errors.New("key 不能为空") + } + if math.IsNaN(score) || math.IsInf(score, 0) { + return 0, errors.New("score 必须是有效数字") + } + + // 使用 ZRemRangeByScore 移除数据 + count, err := e.client.ZRemRangeByScore(e.ctx, key, "-inf", strconv.FormatFloat(score, 'f', -1, 64)).Result() + if err != nil { + return 0, fmt.Errorf("移除 Sorted Set 数据失败, key: %s, score: %f, err: %v", key, score, err) + } + + return count, nil +} + +// GetNextAfterScore 获取指定分数及之后的第一条数据(包含指定分数) +func (e *RedisHelper) GetNextAfterScore(key string, score float64) (string, error) { + // 使用 ZRangeByScore 获取大于等于 score 的第一条数据 + zs, err := e.client.ZRangeByScoreWithScores(e.ctx, key, &redis.ZRangeBy{ + Min: fmt.Sprintf("%f", score), // 包含指定分数 + Max: "+inf", // 上限为正无穷 + Offset: 0, // 从第 0 条开始 + Count: 1, // 只取 1 条 + }).Result() + + if err != nil { + return "", fmt.Errorf("获取数据失败: %v", err) + } + if len(zs) == 0 { + return "", nil // 没有符合条件的元素 + } + return zs[0].Member.(string), nil +} + +/* +获取sort set 所有数据 +*/ +func (e *RedisHelper) GetAllSortSet(key string) ([]string, error) { + return e.client.ZRange(e.ctx, key, 0, -1).Result() +} + +/* +获取sort set 所有数据和score +*/ +func (e *RedisHelper) GetRevRangeScoresSortSet(key string) ([]redis.Z, error) { + return e.client.ZRevRangeWithScores(e.ctx, key, 0, -1).Result() +} + +// 获取最后一条数据 +func (e *RedisHelper) GetLastSortSet(key string) ([]redis.Z, error) { + // 获取最后一个元素及其分数 + results, err := e.client.ZRevRangeWithScores(e.ctx, key, 0, 0).Result() + if err != nil { + return nil, fmt.Errorf("failed to get last member: %w", err) + } + + // 如果没有数据,返回空 + if len(results) == 0 { + return []redis.Z{}, nil + } + + return results, nil +} + +// 获取指定区间数据 +func (e *RedisHelper) GetSortSetMembers(key string, start, stop int64) ([]string, error) { + return e.client.ZRange(e.ctx, key, start, stop).Result() +} + +// 获取最后N条数据 +func (e *RedisHelper) GetLastSortSetMembers(key string, num int64) ([]string, error) { + return e.client.ZRevRange(e.ctx, key, 0, num).Result() +} + +// func (e *RedisHelper) DelSortSet(key,) + +// 根据索引范围删除 +func (e *RedisHelper) DelByRank(key string, start, stop int64) error { + return e.client.ZRemRangeByRank(e.ctx, key, start, stop).Err() +} + +// sort set end + +// GetUserLoginPwdErrFre 获取用户登录密码错误频次 +func (e *RedisHelper) GetUserLoginPwdErrFre(key string) (total int, wait time.Duration, err error) { + total, _ = e.client.Get(e.ctx, key).Int() + wait = e.client.TTL(e.ctx, key).Val() + return +} + +// SetUserLoginPwdErrFre 设置用户登录密码错误频次 +func (e *RedisHelper) SetUserLoginPwdErrFre(key string, expire time.Duration) (val int64, err error) { + val, err = e.client.Incr(e.ctx, key).Result() + if err != nil { + return + } + if err = e.client.Expire(e.ctx, key, expire).Err(); err != nil { + return + } + return +} diff --git a/config/extend.go b/config/extend.go index bd06e03..bae4500 100644 --- a/config/extend.go +++ b/config/extend.go @@ -3,14 +3,24 @@ package config var ExtConfig Extend // Extend 扩展配置 -// extend: -// demo: -// name: demo-name +// +// extend: +// demo: +// name: demo-name +// // 使用方法: config.ExtConfig......即可!! type Extend struct { - AMap AMap // 这里配置对应配置文件的结构即可 + AMap AMap // 这里配置对应配置文件的结构即可 + Redis RedisConfig `mapstructure:"redis"` } type AMap struct { Key string } + +// redis配置 +type RedisConfig struct { + Addr string + Password string + Db int +} diff --git a/config/settings.yml b/config/settings.yml index 74f061b..4345c74 100644 --- a/config/settings.yml +++ b/config/settings.yml @@ -48,6 +48,11 @@ settings: extend: # 扩展项使用说明 demo: name: data + # redis 配置 + redis: + addr: "127.0.0.1:6379" + password: "" + db: 3 cache: # redis: # addr: 127.0.0.1:6379 diff --git a/go.mod b/go.mod index a1faa9f..1675e01 100644 --- a/go.mod +++ b/go.mod @@ -56,6 +56,7 @@ require ( github.com/chanxuehong/rand v0.0.0-20211009035549-2f07823e8e99 // indirect github.com/chanxuehong/wechat v0.0.0-20230222024006-36f0325263cd // indirect github.com/cloudwego/base64x v0.1.5 // indirect + github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect github.com/dustin/go-humanize v1.0.1 // indirect github.com/fsnotify/fsnotify v1.9.0 // indirect github.com/gabriel-vasile/mimetype v1.4.8 // indirect @@ -73,6 +74,7 @@ require ( github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect github.com/go-playground/validator/v10 v10.26.0 // indirect + github.com/go-redis/redis/v8 v8.11.5 // indirect github.com/go-sql-driver/mysql v1.9.2 // indirect github.com/goccy/go-json v0.10.5 // indirect github.com/gofrs/flock v0.8.1 // indirect