From cf404a97b9087f28d2837efa1d2a3d1975e43e38 Mon Sep 17 00:00:00 2001 From: junleea <354425203@qq.com> Date: Fri, 6 Jun 2025 14:16:44 +0800 Subject: [PATCH 1/8] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=A0=B9=E6=8D=AEshell?= =?UTF-8?q?=E7=9A=84id=E5=88=A0=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dao/shell.go | 16 +++++++++++++++ handler/shell.go | 44 +++++++++++++++++++++++++++++++++++++++++ service/shellService.go | 4 ++++ 3 files changed, 64 insertions(+) diff --git a/dao/shell.go b/dao/shell.go index 8d1c5bd..f83722a 100644 --- a/dao/shell.go +++ b/dao/shell.go @@ -98,3 +98,19 @@ func FindShellWillRunByServer(server string, uid uint) []Shell { } return shells } + +func DeleteShellByID(id, authId uint) bool { + var db2 *gorm.DB + if proto.Config.SERVER_SQL_LOG { + db2 = DB + } else { + db2 = DB.Debug() + } + result := db2.Where("id = ? and auth_id = ?", id, authId).Delete(&Shell{}) + + if result.Error != nil { + log.Printf("DeleteShellByID failed: %v", result.Error) + return false + } + return true +} diff --git a/handler/shell.go b/handler/shell.go index 3f39d77..af01042 100644 --- a/handler/shell.go +++ b/handler/shell.go @@ -2,6 +2,7 @@ package handler import ( "github.com/gin-gonic/gin" + "net/http" "videoplayer/proto" "videoplayer/service" ) @@ -32,12 +33,20 @@ type UpdateShellResp struct { Status int `json:"status" form:"status"` } +type DeleteShellRequestID struct { + ID uint `json:"id" form:"id" binding:"required"` +} +type DeleteShellRequest struct { + Shells []DeleteShellRequestID `json:"shells" form:"shells" binding:"required"` +} + func SetUpShellGroup(router *gin.Engine) { shellGroup := router.Group("/shell") //持续集成、部署 shellHandler := ShellHandler{} shellGroup.POST("/create", shellHandler.CreateShell) shellGroup.POST("/list", shellHandler.ListShell) shellGroup.POST("/update", shellHandler.UpdateShell) + shellGroup.POST("/delete", shellHandler.DeleteShell) shellGroup.POST("/server_will_run_list", shellHandler.ServerWillRun) } @@ -84,6 +93,41 @@ func (s *ShellHandler) UpdateShell(c *gin.Context) { } } +type DeleteShellResp struct { + Success []DeleteShellRequestID `json:"success" form:"success"` + Error []DeleteShellRequestID `json:"error" form:"error"` +} + +func (s *ShellHandler) DeleteShell(c *gin.Context) { + userId, _ := c.Get("id") + id := int(userId.(float64)) + var req DeleteShellRequest + var resp proto.GeneralResp + + if err := c.ShouldBind(&req); err != nil { + var delSuccessIDs []DeleteShellRequestID + var delErrorIDs []DeleteShellRequestID + for _, v := range req.Shells { + delSuccess := service.DeleteShellByID(v.ID, uint(id)) + if delSuccess { + delSuccessIDs = append(delSuccessIDs, v) + } else { + delErrorIDs = append(delErrorIDs, v) + } + } + var delResp DeleteShellResp + delResp.Success = delSuccessIDs + delResp.Error = delErrorIDs + resp.Code = proto.SuccessCode + resp.Data = delResp + resp.Message = "success" + } else { + resp.Code = proto.ParameterError + resp.Message = "参数解析错误:" + err.Error() + } + c.JSON(http.StatusOK, resp) +} + type ServerWillRunReq struct { Server string `json:"server"` } diff --git a/service/shellService.go b/service/shellService.go index 2a00982..ee38023 100644 --- a/service/shellService.go +++ b/service/shellService.go @@ -20,6 +20,10 @@ func FindShellByAuthID(id int) []dao.Shell { return dao.FindShellByAuthID(id) } +func DeleteShellByID(id, authId uint) bool { + return dao.DeleteShellByID(id, authId) +} + func UpdateShellByID(id, authId uint, shellName, shellContent, server string, status int, shellResult string) bool { return dao.UpdateShellByID(id, authId, shellName, shellContent, status, shellResult) } From ef1b2771cdf01916bc5ef02a388326e3ae454383 Mon Sep 17 00:00:00 2001 From: junleea <354425203@qq.com> Date: Fri, 6 Jun 2025 14:19:52 +0800 Subject: [PATCH 2/8] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=A0=B9=E6=8D=AEshell?= =?UTF-8?q?=E7=9A=84id=E5=88=A0=E9=99=A4,=E6=B7=BB=E5=8A=A0=E7=AE=A1?= =?UTF-8?q?=E7=90=86=E5=91=98=E4=BA=BA=E5=91=98=E5=88=A0=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dao/shell.go | 16 ++++++++++++++++ service/shellService.go | 4 ++++ 2 files changed, 20 insertions(+) diff --git a/dao/shell.go b/dao/shell.go index f83722a..b033a24 100644 --- a/dao/shell.go +++ b/dao/shell.go @@ -114,3 +114,19 @@ func DeleteShellByID(id, authId uint) bool { } return true } + +func DeleteShellByIDV2(id uint) bool { + var db2 *gorm.DB + if proto.Config.SERVER_SQL_LOG { + db2 = DB + } else { + db2 = DB.Debug() + } + result := db2.Where("id = ? ", id).Delete(&Shell{}) + + if result.Error != nil { + log.Printf("DeleteShellByID failed: %v", result.Error) + return false + } + return true +} diff --git a/service/shellService.go b/service/shellService.go index ee38023..430c7dd 100644 --- a/service/shellService.go +++ b/service/shellService.go @@ -21,6 +21,10 @@ func FindShellByAuthID(id int) []dao.Shell { } func DeleteShellByID(id, authId uint) bool { + user := GetUserByIDFromUserCenter(int(authId)) + if user.Role == "admin" { + return dao.DeleteShellByIDV2(id) + } return dao.DeleteShellByID(id, authId) } From 510b725adefc0ad698b5be61bad394a58c588d50 Mon Sep 17 00:00:00 2001 From: junleea <354425203@qq.com> Date: Fri, 6 Jun 2025 14:36:59 +0800 Subject: [PATCH 3/8] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=9F=A5=E7=9C=8Bmonitor?= =?UTF-8?q?=E8=AE=BE=E5=A4=87=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- handler/tool.go | 27 +++++++++++++++++++++++++++ proto/conf.go | 1 + proto/resp.go | 6 ++++++ service/toolService.go | 24 ++++++++++++++++++++++++ 4 files changed, 58 insertions(+) create mode 100644 proto/resp.go diff --git a/handler/tool.go b/handler/tool.go index 820854a..1654a21 100644 --- a/handler/tool.go +++ b/handler/tool.go @@ -52,10 +52,37 @@ func SetUpToolGroup(router *gin.Engine) { toolGroup.POST("/file_del", DelFile) //服务器、设备状态接口 toolGroup.POST("/monitor", SetDeviceStatusV2) + toolGroup.GET("/get_monitor_list", GetMonitorList) //获取设备监控列表 + toolGroup.POST("/update_monitor", UpdateMonitor) //设置设备状态 + toolGroup.POST("/del_monitor", DelMonitor) //删除设备监控 //发送邮件 toolGroup.POST("/send_mail", SendMailTool) } +func GetMonitorList(c *gin.Context) { + id, _ := c.Get("id") + userId := int(id.(float64)) + var resp proto.GeneralResp + monitorDeviceList, err := service.GetMonitorDeviceListWithStatus(userId) + if err != nil { + resp.Code = proto.OperationFailed + resp.Message = err.Error() + } else { + resp.Code = proto.SuccessCode + resp.Message = "success" + resp.Data = monitorDeviceList + } + c.JSON(http.StatusOK, resp) +} +func UpdateMonitor(c *gin.Context) { + id, _ := c.Get("id") + id1 := int(id.(float64)) +} +func DelMonitor(c *gin.Context) { + id, _ := c.Get("id") + id1 := int(id.(float64)) +} + func SetDeviceStatusV2(c *gin.Context) { // TODO var req SetDeviceStatusReq diff --git a/proto/conf.go b/proto/conf.go index 0c6bb27..c79fba0 100644 --- a/proto/conf.go +++ b/proto/conf.go @@ -82,6 +82,7 @@ type ConfigStruct struct { MASTER_SERVER_DOMAIN string `json:"master_server_domain"` // 主服务器域名 USER_SYNC_TIME int `json:"user_sync_time"` // 用户数据同步时间,单位秒 SERVER_NAME string `json:"server_name"` // 服务器名称,用于区分不同服务器 + MONITOR_SERVER_TOKEN string `json:"monitor_server_token"` // 监控服务器token,用于状态监控及邮件通知 } // 读取配置文件 diff --git a/proto/resp.go b/proto/resp.go new file mode 100644 index 0000000..afa2759 --- /dev/null +++ b/proto/resp.go @@ -0,0 +1,6 @@ +package proto + +type GetMonitorDeviceStatus struct { + ID string `json:"id" form:"id"` //设备编码 + Status string `json:"status" form:"status"` //设备状态 +} diff --git a/service/toolService.go b/service/toolService.go index 754daed..d4c0793 100644 --- a/service/toolService.go +++ b/service/toolService.go @@ -1,6 +1,7 @@ package service import ( + "errors" "fmt" "regexp" "time" @@ -113,3 +114,26 @@ func CheckEmail(email string) bool { reg := regexp.MustCompile(pattern) return reg.MatchString(email) } + +// 获取监控设备及状态 +func GetMonitorDeviceListWithStatus(userId int) ([]proto.GetMonitorDeviceStatus, error) { + var deviceStatus []proto.GetMonitorDeviceStatus + user := GetUserByIDFromUserCenter(userId) + if user.Role != "admin" { + return deviceStatus, errors.New("user is not admin, can not get monitor device list") + } else { + devices := worker.GetRedisSetMembers(proto.Config.MONITOR_SERVER_TOKEN) + for _, device := range devices { + status := worker.GetRedis("monitor_" + device) + var deviceInfo proto.GetMonitorDeviceStatus + deviceInfo.ID = device + if status == "" { + deviceInfo.Status = "offline" + } else { + deviceInfo.Status = status + } + deviceStatus = append(deviceStatus, deviceInfo) + } + } + return deviceStatus, nil +} From 3967d68ce0bbfac2c83b64fae80456e25a8bcba0 Mon Sep 17 00:00:00 2001 From: junleea <354425203@qq.com> Date: Fri, 6 Jun 2025 14:53:14 +0800 Subject: [PATCH 4/8] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E5=8F=8A=E4=BF=AE=E6=94=B9monitor=E8=AE=BE=E5=A4=87=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- handler/tool.go | 21 +++++++++++++++++++++ proto/resp.go | 1 + service/toolService.go | 29 ++++++++++++++++++++++++++++- worker/redis.go | 16 ++++++++++++++++ 4 files changed, 66 insertions(+), 1 deletion(-) diff --git a/handler/tool.go b/handler/tool.go index 1654a21..43d3b4e 100644 --- a/handler/tool.go +++ b/handler/tool.go @@ -74,9 +74,30 @@ func GetMonitorList(c *gin.Context) { } c.JSON(http.StatusOK, resp) } + +type UpdateMonitorDeviceStatusReq struct { + Devices []proto.GetMonitorDeviceStatus `json:"devices" form:"devices"` //设备状态列表 +} + func UpdateMonitor(c *gin.Context) { id, _ := c.Get("id") id1 := int(id.(float64)) + var req UpdateMonitorDeviceStatusReq + var resp proto.GeneralResp + if err := c.ShouldBind(&req); err != nil { + err2 := service.UpdateMonitorDeviceListWithStatus(id1, req.Devices) + if err2 != nil { + resp.Code = proto.OperationFailed + resp.Message = "更新设备状态失败:" + err2.Error() + } else { + resp.Code = proto.SuccessCode + resp.Message = "更新设备状态成功" + } + } else { + resp.Code = proto.ParameterError + resp.Message = "参数解析失败:" + err.Error() + } + c.JSON(http.StatusOK, resp) } func DelMonitor(c *gin.Context) { id, _ := c.Get("id") diff --git a/proto/resp.go b/proto/resp.go index afa2759..cb22ced 100644 --- a/proto/resp.go +++ b/proto/resp.go @@ -3,4 +3,5 @@ package proto type GetMonitorDeviceStatus struct { ID string `json:"id" form:"id"` //设备编码 Status string `json:"status" form:"status"` //设备状态 + Expire int `json:"expire" form:"expire"` //设备过期时间,及更新时间 } diff --git a/service/toolService.go b/service/toolService.go index d4c0793..b0b8340 100644 --- a/service/toolService.go +++ b/service/toolService.go @@ -124,9 +124,10 @@ func GetMonitorDeviceListWithStatus(userId int) ([]proto.GetMonitorDeviceStatus, } else { devices := worker.GetRedisSetMembers(proto.Config.MONITOR_SERVER_TOKEN) for _, device := range devices { - status := worker.GetRedis("monitor_" + device) + status, expireIn := worker.GetRedisWithExpire("monitor_" + device) var deviceInfo proto.GetMonitorDeviceStatus deviceInfo.ID = device + deviceInfo.Expire = expireIn if status == "" { deviceInfo.Status = "offline" } else { @@ -137,3 +138,29 @@ func GetMonitorDeviceListWithStatus(userId int) ([]proto.GetMonitorDeviceStatus, } return deviceStatus, nil } + +func UpdateMonitorDeviceListWithStatus(userId int, deviceReq []proto.GetMonitorDeviceStatus) error { + user := GetUserByIDFromUserCenter(userId) + var err error + if user.Role != "admin" { + err = errors.New("user is not admin, can not update monitor device list") + return err + } else { + // 更新监控设备状态.如果在集合中则添加,不在则添加到集合中 + devices := worker.GetRedisSetMembers(proto.Config.MONITOR_SERVER_TOKEN) + deviceMap := make(map[string]bool, len(devices)) + for _, device := range devices { + deviceMap[device] = true + } + for _, device := range deviceReq { + if _, ok := deviceMap[device.ID]; ok { + // 如果设备在集合中,则更新状态 + worker.SetRedisWithExpire("monitor_"+device.ID, device.Status, time.Duration(device.Expire)*time.Second) + } else { + worker.SetRedisSetAdd(proto.Config.MONITOR_SERVER_TOKEN, device.ID) + worker.SetRedisWithExpire("monitor_"+device.ID, device.Status, time.Duration(device.Expire)*time.Second) + } + } + } + return err +} diff --git a/worker/redis.go b/worker/redis.go index b31735f..ad21ff8 100644 --- a/worker/redis.go +++ b/worker/redis.go @@ -176,6 +176,22 @@ func GetRedis(key string) string { return val } +func GetRedisWithExpire(key string) (string, int) { + ctx := context.Background() + val, err := RedisClient.Get(ctx, key).Result() // 从 Redis 读取键值, 如果键不存在则返回空字符串, 如果出现错误则返回错误 + if err != nil { + //fmt.Println(key, " Error getting key: %v", err) + return "", 0 + } else { + // 获取键的过期时间 + ttl, err2 := RedisClient.TTL(ctx, key).Result() + if err2 != nil { + return val, -1 + } + return val, int(ttl.Seconds()) + } +} + // pop redis list from right,as stack func PopRedisList(key string) string { ctx := context.Background() From e94695329c635ec0def6fab444084ad0fcf45ec5 Mon Sep 17 00:00:00 2001 From: junleea <354425203@qq.com> Date: Fri, 6 Jun 2025 14:59:25 +0800 Subject: [PATCH 5/8] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=88=A0=E9=99=A4monitor?= =?UTF-8?q?=E8=AE=BE=E5=A4=87=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- handler/tool.go | 18 ++++++++++++++++++ service/toolService.go | 20 ++++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/handler/tool.go b/handler/tool.go index 43d3b4e..7e645cd 100644 --- a/handler/tool.go +++ b/handler/tool.go @@ -102,6 +102,24 @@ func UpdateMonitor(c *gin.Context) { func DelMonitor(c *gin.Context) { id, _ := c.Get("id") id1 := int(id.(float64)) + var req UpdateMonitorDeviceStatusReq + var resp proto.GeneralResp + if err := c.ShouldBind(&req); err != nil { + delSuccess, err2 := service.DelMonitorDeviceListWithStatus(id1, req.Devices) + if err2 != nil { + resp.Code = proto.OperationFailed + resp.Message = "更新设备状态失败:" + err2.Error() + resp.Data = delSuccess + } else { + resp.Code = proto.SuccessCode + resp.Message = "更新设备状态成功" + resp.Data = delSuccess + } + } else { + resp.Code = proto.ParameterError + resp.Message = "参数解析失败:" + err.Error() + } + c.JSON(http.StatusOK, resp) } func SetDeviceStatusV2(c *gin.Context) { diff --git a/service/toolService.go b/service/toolService.go index b0b8340..5c9e9b9 100644 --- a/service/toolService.go +++ b/service/toolService.go @@ -164,3 +164,23 @@ func UpdateMonitorDeviceListWithStatus(userId int, deviceReq []proto.GetMonitorD } return err } + +func DelMonitorDeviceListWithStatus(userId int, deviceReq []proto.GetMonitorDeviceStatus) ([]proto.GetMonitorDeviceStatus, error) { + user := GetUserByIDFromUserCenter(userId) + var err error + var delDevices []proto.GetMonitorDeviceStatus + if user.Role != "admin" { + err = errors.New("user is not admin, can not update monitor device list") + return delDevices, err + } else { + for _, device := range deviceReq { + if worker.IsContainSet(proto.Config.MONITOR_SERVER_TOKEN, device.ID) { + // 如果设备在集合中,则删除状态 + worker.DelRedis("monitor_" + device.ID) + worker.SetRedisSetRemove(proto.Config.MONITOR_SERVER_TOKEN, device.ID) + delDevices = append(delDevices, device) + } + } + } + return delDevices, err +} From aeacecea7079285d04e4cd1d94df8590ce3844f3 Mon Sep 17 00:00:00 2001 From: junleea <354425203@qq.com> Date: Fri, 6 Jun 2025 15:05:29 +0800 Subject: [PATCH 6/8] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=88=A0=E9=99=A4monitor?= =?UTF-8?q?=E8=AE=BE=E5=A4=87=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- handler/shell.go | 2 +- handler/tool.go | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/handler/shell.go b/handler/shell.go index af01042..397857f 100644 --- a/handler/shell.go +++ b/handler/shell.go @@ -104,7 +104,7 @@ func (s *ShellHandler) DeleteShell(c *gin.Context) { var req DeleteShellRequest var resp proto.GeneralResp - if err := c.ShouldBind(&req); err != nil { + if err := c.ShouldBind(&req); err == nil { var delSuccessIDs []DeleteShellRequestID var delErrorIDs []DeleteShellRequestID for _, v := range req.Shells { diff --git a/handler/tool.go b/handler/tool.go index 7e645cd..5743baa 100644 --- a/handler/tool.go +++ b/handler/tool.go @@ -84,7 +84,7 @@ func UpdateMonitor(c *gin.Context) { id1 := int(id.(float64)) var req UpdateMonitorDeviceStatusReq var resp proto.GeneralResp - if err := c.ShouldBind(&req); err != nil { + if err := c.ShouldBind(&req); err == nil { err2 := service.UpdateMonitorDeviceListWithStatus(id1, req.Devices) if err2 != nil { resp.Code = proto.OperationFailed @@ -104,7 +104,7 @@ func DelMonitor(c *gin.Context) { id1 := int(id.(float64)) var req UpdateMonitorDeviceStatusReq var resp proto.GeneralResp - if err := c.ShouldBind(&req); err != nil { + if err := c.ShouldBind(&req); err == nil { delSuccess, err2 := service.DelMonitorDeviceListWithStatus(id1, req.Devices) if err2 != nil { resp.Code = proto.OperationFailed From 7cc505daecd2cb715d6942181c557adc1220892f Mon Sep 17 00:00:00 2001 From: junleea <354425203@qq.com> Date: Wed, 11 Jun 2025 13:29:58 +0800 Subject: [PATCH 7/8] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=97=A0=E6=B3=95?= =?UTF-8?q?=E8=8E=B7=E5=8F=96=E8=B6=85=E7=BA=A7token=E6=97=B6=E7=9A=84?= =?UTF-8?q?=E9=94=99=E8=AF=AF=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- service/shellService.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/service/shellService.go b/service/shellService.go index 430c7dd..fd5cb70 100644 --- a/service/shellService.go +++ b/service/shellService.go @@ -92,7 +92,12 @@ func GetShellWillRunFromMaster(server string) ([]dao.Shell, error) { url := "https://" + master + "/shell/server_will_run_list?super_id=1" var req proto.SyncUserShellReq req.Server = server - req.Token = worker.GetRedisSetMembers("super_permission_tokens")[0] + superPermissions := worker.GetRedisSetMembers("super_permission_tokens") + if len(superPermissions) == 0 { + log.Println("no super permission tokens found, please check the configuration or redis") + return nil, errors.New("no super permission tokens found") + } + req.Token = superPermissions[0] shells, err := worker.SyncDataFromMasterShellReq2(url, req) if err != nil { return nil, err From a2441cdc20740797e4299733f519a7de2d2e231a Mon Sep 17 00:00:00 2001 From: junleea <354425203@qq.com> Date: Wed, 11 Jun 2025 13:32:29 +0800 Subject: [PATCH 8/8] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=97=A0=E6=B3=95?= =?UTF-8?q?=E8=8E=B7=E5=8F=96=E8=B6=85=E7=BA=A7token=E6=97=B6=E7=9A=84?= =?UTF-8?q?=E9=94=99=E8=AF=AF=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- service/shellService.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/service/shellService.go b/service/shellService.go index fd5cb70..9818bc6 100644 --- a/service/shellService.go +++ b/service/shellService.go @@ -94,7 +94,7 @@ func GetShellWillRunFromMaster(server string) ([]dao.Shell, error) { req.Server = server superPermissions := worker.GetRedisSetMembers("super_permission_tokens") if len(superPermissions) == 0 { - log.Println("no super permission tokens found, please check the configuration or redis") + log.Println("get shell will run from master error: no super permission tokens found, please check the configuration or redis!") return nil, errors.New("no super permission tokens found") } req.Token = superPermissions[0]