feat: add notify icon read
This commit is contained in:
@@ -0,0 +1,108 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"github.com/engigu/baihu-panel/internal/services"
|
||||
"github.com/engigu/baihu-panel/internal/utils"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type AppLogController struct {
|
||||
appLogService *services.AppLogService
|
||||
}
|
||||
|
||||
func NewAppLogController() *AppLogController {
|
||||
return &AppLogController{
|
||||
appLogService: services.NewAppLogService(),
|
||||
}
|
||||
}
|
||||
|
||||
// GetLogs 获取应用日志列表
|
||||
// @Summary 获取应用日志列表
|
||||
// @Tags 应用日志
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security BearerAuth
|
||||
// @Param category query string false "日志分类"
|
||||
// @Param status query string false "状态"
|
||||
// @Param level query string false "级别"
|
||||
// @Param keyword query string false "搜索关键词"
|
||||
// @Param page query int false "页码"
|
||||
// @Param page_size query int false "每页数量"
|
||||
// @Success 200 {object} utils.Response
|
||||
// @Router /app-logs [get]
|
||||
func (ac *AppLogController) GetLogs(c *gin.Context) {
|
||||
p := utils.ParsePagination(c)
|
||||
category := c.Query("category")
|
||||
status := c.Query("status")
|
||||
level := c.Query("level")
|
||||
keyword := c.Query("keyword")
|
||||
|
||||
logs, total, err := ac.appLogService.List(category, status, level, p.Page, p.PageSize, keyword)
|
||||
if err != nil {
|
||||
utils.BadRequest(c, err.Error())
|
||||
return
|
||||
}
|
||||
utils.PaginatedResponse(c, logs, total, p)
|
||||
}
|
||||
|
||||
// MarkAsRead 标记已读
|
||||
// @Summary 标记已读
|
||||
// @Tags 应用日志
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security BearerAuth
|
||||
// @Param body body object true "请求体"
|
||||
// @Success 200 {object} utils.Response
|
||||
// @Router /app-logs/read [post]
|
||||
func (ac *AppLogController) MarkAsRead(c *gin.Context) {
|
||||
var req struct {
|
||||
ID string `json:"id"`
|
||||
Category string `json:"category"`
|
||||
}
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
utils.BadRequest(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
if req.ID != "" {
|
||||
if err := ac.appLogService.MarkAsRead(req.ID); err != nil {
|
||||
utils.BadRequest(c, err.Error())
|
||||
return
|
||||
}
|
||||
} else if req.Category != "" {
|
||||
if err := ac.appLogService.MarkAllAsRead(req.Category); err != nil {
|
||||
utils.BadRequest(c, err.Error())
|
||||
return
|
||||
}
|
||||
} else {
|
||||
utils.BadRequest(c, "id 或 category 必须提供")
|
||||
return
|
||||
}
|
||||
utils.SuccessMsg(c, "标记成功")
|
||||
}
|
||||
|
||||
// ClearLogs 清理日志
|
||||
// @Summary 清理日志
|
||||
// @Tags 应用日志
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security BearerAuth
|
||||
// @Param body body object true "请求体"
|
||||
// @Success 200 {object} utils.Response
|
||||
// @Router /app-logs/clear [post]
|
||||
func (ac *AppLogController) ClearLogs(c *gin.Context) {
|
||||
var req struct {
|
||||
Category string `json:"category"`
|
||||
}
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
utils.BadRequest(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
if err := ac.appLogService.Clear(req.Category); err != nil {
|
||||
utils.BadRequest(c, err.Error())
|
||||
return
|
||||
}
|
||||
utils.SuccessMsg(c, "清理成功")
|
||||
}
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/engigu/baihu-panel/internal/constant"
|
||||
"github.com/engigu/baihu-panel/internal/eventbus"
|
||||
"github.com/engigu/baihu-panel/internal/middleware"
|
||||
"github.com/engigu/baihu-panel/internal/models/vo"
|
||||
"github.com/engigu/baihu-panel/internal/services"
|
||||
@@ -54,10 +55,13 @@ func (ac *AuthController) Login(c *gin.Context) {
|
||||
if val, ok := loginAttempts.Load(ip); ok {
|
||||
attempt := val.(*loginAttempt)
|
||||
if attempt.Count >= 5 && time.Since(attempt.LastAttempt) < time.Minute {
|
||||
ac.loginLogService.Create(req.Username, ip, userAgent, "failed", "尝试次数过多,请一分钟后再试")
|
||||
go services.NewNotificationService().TriggerEvent(constant.BindingTypeSystem, constant.EventBruteForceLogin, "", map[string]interface{}{
|
||||
"ip": ip,
|
||||
"username": req.Username,
|
||||
eventbus.DefaultBus.Publish(eventbus.Event{
|
||||
Type: constant.EventBruteForceLogin,
|
||||
Payload: map[string]interface{}{
|
||||
"ip": ip,
|
||||
"username": req.Username,
|
||||
"userAgent": userAgent,
|
||||
},
|
||||
})
|
||||
utils.TooManyRequests(c, "尝试次数过多,请一分钟后再试")
|
||||
return
|
||||
@@ -77,7 +81,16 @@ func (ac *AuthController) Login(c *gin.Context) {
|
||||
attempt.LastAttempt = time.Now()
|
||||
|
||||
// 记录登录失败日志
|
||||
ac.loginLogService.Create(req.Username, ip, userAgent, "failed", "用户名或密码错误")
|
||||
eventbus.DefaultBus.Publish(eventbus.Event{
|
||||
Type: constant.EventUserLogin,
|
||||
Payload: map[string]interface{}{
|
||||
"ip": ip,
|
||||
"username": req.Username,
|
||||
"userAgent": userAgent,
|
||||
"status": "failed",
|
||||
"message": "用户名或密码错误",
|
||||
},
|
||||
})
|
||||
utils.Unauthorized(c, "用户名或密码错误")
|
||||
return
|
||||
}
|
||||
@@ -96,7 +109,16 @@ func (ac *AuthController) Login(c *gin.Context) {
|
||||
// 生成 token
|
||||
token, err := utils.GenerateToken(user.ID, user.Username, expireDays, constant.Secret)
|
||||
if err != nil {
|
||||
ac.loginLogService.Create(req.Username, ip, userAgent, "failed", "Token生成失败")
|
||||
eventbus.DefaultBus.Publish(eventbus.Event{
|
||||
Type: constant.EventUserLogin,
|
||||
Payload: map[string]interface{}{
|
||||
"ip": ip,
|
||||
"username": req.Username,
|
||||
"userAgent": userAgent,
|
||||
"status": "failed",
|
||||
"message": "Token生成失败",
|
||||
},
|
||||
})
|
||||
utils.ServerError(c, "登录失败")
|
||||
return
|
||||
}
|
||||
@@ -105,11 +127,15 @@ func (ac *AuthController) Login(c *gin.Context) {
|
||||
middleware.SetAuthCookie(c, token, expireDays)
|
||||
|
||||
// 记录登录成功日志
|
||||
ac.loginLogService.Create(req.Username, ip, userAgent, "success", "登录成功")
|
||||
|
||||
go services.NewNotificationService().TriggerEvent(constant.BindingTypeSystem, constant.EventUserLogin, "", map[string]interface{}{
|
||||
"ip": ip,
|
||||
"username": req.Username,
|
||||
eventbus.DefaultBus.Publish(eventbus.Event{
|
||||
Type: constant.EventUserLogin,
|
||||
Payload: map[string]interface{}{
|
||||
"ip": ip,
|
||||
"username": req.Username,
|
||||
"userAgent": userAgent,
|
||||
"status": "success",
|
||||
"message": "登录成功",
|
||||
},
|
||||
})
|
||||
|
||||
utils.Success(c, gin.H{
|
||||
|
||||
@@ -87,7 +87,7 @@ func (lc *LogController) GetLogs(c *gin.Context) {
|
||||
TaskName: task.Name,
|
||||
TaskType: taskType,
|
||||
AgentID: log.AgentID,
|
||||
Command: log.Command,
|
||||
Command: string(log.Command),
|
||||
Status: log.Status,
|
||||
Duration: log.Duration,
|
||||
StartTime: log.StartTime,
|
||||
|
||||
@@ -37,7 +37,7 @@ func (lc *LogWSController) StreamLog(c *gin.Context) {
|
||||
if err := database.DB.Where("id = ?", logID).First(&taskLog).Error; err == nil {
|
||||
if taskLog.Status != "running" {
|
||||
// 已结束,读取库内日志
|
||||
content, err := utils.DecompressFromBase64(taskLog.Output)
|
||||
content, err := utils.DecompressFromBase64(string(taskLog.Output))
|
||||
if err != nil {
|
||||
conn.WriteMessage(websocket.TextMessage, []byte("解压日志失败: "+err.Error()))
|
||||
return
|
||||
@@ -75,7 +75,7 @@ func (lc *LogWSController) StreamLog(c *gin.Context) {
|
||||
// 任务结束,尝试刷新最后一次库内完整内容
|
||||
var finalLog models.TaskLog
|
||||
if err := database.DB.Where("id = ?", logID).First(&finalLog).Error; err == nil {
|
||||
content, _ := utils.DecompressFromBase64(finalLog.Output)
|
||||
content, _ := utils.DecompressFromBase64(string(finalLog.Output))
|
||||
if content != "" {
|
||||
conn.WriteMessage(websocket.TextMessage, []byte("\n--- 任务已结束 ---\n"))
|
||||
// 这里可以选择性再推一次完整版,或直接退出
|
||||
|
||||
@@ -10,9 +10,9 @@ import (
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/engigu/baihu-panel/internal/constant"
|
||||
"github.com/engigu/baihu-panel/internal/database"
|
||||
"github.com/engigu/baihu-panel/internal/eventbus"
|
||||
"github.com/engigu/baihu-panel/internal/models"
|
||||
"github.com/engigu/baihu-panel/internal/models/vo"
|
||||
"github.com/engigu/baihu-panel/internal/services"
|
||||
@@ -76,8 +76,11 @@ func (sc *SettingsController) ChangePassword(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
go services.NewNotificationService().TriggerEvent(constant.BindingTypeSystem, constant.EventPasswordChanged, "", map[string]interface{}{
|
||||
"username": user.Username,
|
||||
eventbus.DefaultBus.Publish(eventbus.Event{
|
||||
Type: constant.EventPasswordChanged,
|
||||
Payload: map[string]interface{}{
|
||||
"username": user.Username,
|
||||
},
|
||||
})
|
||||
|
||||
utils.SuccessMsg(c, "密码修改成功")
|
||||
|
||||
Reference in New Issue
Block a user