feat: add message push function call
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
@@ -54,6 +55,10 @@ func (ac *AuthController) Login(c *gin.Context) {
|
||||
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,
|
||||
})
|
||||
utils.TooManyRequests(c, "尝试次数过多,请一分钟后再试")
|
||||
return
|
||||
}
|
||||
@@ -102,6 +107,11 @@ func (ac *AuthController) Login(c *gin.Context) {
|
||||
// 记录登录成功日志
|
||||
ac.loginLogService.Create(req.Username, ip, userAgent, "success", "登录成功")
|
||||
|
||||
go services.NewNotificationService().TriggerEvent(constant.BindingTypeSystem, constant.EventUserLogin, "", map[string]interface{}{
|
||||
"ip": ip,
|
||||
"username": req.Username,
|
||||
})
|
||||
|
||||
utils.Success(c, gin.H{
|
||||
"user": user.Username,
|
||||
})
|
||||
|
||||
@@ -0,0 +1,168 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"github.com/engigu/baihu-panel/internal/models"
|
||||
"github.com/engigu/baihu-panel/internal/services"
|
||||
"github.com/engigu/baihu-panel/internal/utils"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type NotificationController struct {
|
||||
notifyService *services.NotificationService
|
||||
}
|
||||
|
||||
func NewNotificationController() *NotificationController {
|
||||
return &NotificationController{
|
||||
notifyService: services.NewNotificationService(),
|
||||
}
|
||||
}
|
||||
|
||||
// GetChannelTypes 获取支持的渠道类型
|
||||
func (nc *NotificationController) GetChannelTypes(c *gin.Context) {
|
||||
utils.Success(c, gin.H{
|
||||
"channel_types": services.SupportedChannelTypes,
|
||||
"event_types": services.SupportedEvents,
|
||||
})
|
||||
}
|
||||
|
||||
// GetChannels 获取所有渠道
|
||||
func (nc *NotificationController) GetChannels(c *gin.Context) {
|
||||
channels := nc.notifyService.GetChannels()
|
||||
utils.Success(c, channels)
|
||||
}
|
||||
|
||||
// SaveChannel 保存/更新渠道
|
||||
func (nc *NotificationController) SaveChannel(c *gin.Context) {
|
||||
var req services.NotifyChannel
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
utils.BadRequest(c, "参数错误")
|
||||
return
|
||||
}
|
||||
|
||||
if req.Name == "" || req.Type == "" {
|
||||
utils.BadRequest(c, "渠道名称和类型不能为空")
|
||||
return
|
||||
}
|
||||
|
||||
if err := nc.notifyService.SaveChannel(req); err != nil {
|
||||
utils.ServerError(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
utils.SuccessMsg(c, "保存成功")
|
||||
}
|
||||
|
||||
// DeleteChannel 删除渠道
|
||||
func (nc *NotificationController) DeleteChannel(c *gin.Context) {
|
||||
id := c.Param("id")
|
||||
if id == "" {
|
||||
utils.BadRequest(c, "缺少渠道ID")
|
||||
return
|
||||
}
|
||||
|
||||
if err := nc.notifyService.DeleteChannel(id); err != nil {
|
||||
utils.ServerError(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
utils.SuccessMsg(c, "删除成功")
|
||||
}
|
||||
|
||||
// TestChannel 测试渠道
|
||||
func (nc *NotificationController) TestChannel(c *gin.Context) {
|
||||
var req services.NotifyChannel
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
utils.BadRequest(c, "参数错误")
|
||||
return
|
||||
}
|
||||
|
||||
result := nc.notifyService.SendToChannel(req, &services.NotifyMessage{
|
||||
Title: "🔔 白虎面板测试通知",
|
||||
Text: "如果你看到这条消息,说明通知渠道配置正确!",
|
||||
})
|
||||
|
||||
utils.Success(c, result)
|
||||
}
|
||||
|
||||
|
||||
// GetBindings 获取事件绑定列表
|
||||
func (nc *NotificationController) GetBindings(c *gin.Context) {
|
||||
bindings := nc.notifyService.GetBindings()
|
||||
utils.Success(c, bindings)
|
||||
}
|
||||
|
||||
// SaveBinding 保存事件绑定
|
||||
func (nc *NotificationController) SaveBinding(c *gin.Context) {
|
||||
var req struct {
|
||||
ID string `json:"id"`
|
||||
Type string `json:"type"`
|
||||
Event string `json:"event"`
|
||||
WayID string `json:"way_id"`
|
||||
DataID string `json:"data_id"`
|
||||
}
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
utils.BadRequest(c, "参数错误")
|
||||
return
|
||||
}
|
||||
|
||||
if req.Type == "" || req.Event == "" || req.WayID == "" {
|
||||
utils.BadRequest(c, "类型、事件和渠道ID不能为空")
|
||||
return
|
||||
}
|
||||
|
||||
binding := &models.NotifyBinding{
|
||||
ID: req.ID,
|
||||
Type: req.Type,
|
||||
Event: req.Event,
|
||||
WayID: req.WayID,
|
||||
DataID: req.DataID,
|
||||
}
|
||||
|
||||
if err := nc.notifyService.SaveBinding(binding); err != nil {
|
||||
utils.ServerError(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
utils.Success(c, binding)
|
||||
}
|
||||
|
||||
// DeleteBinding 删除事件绑定
|
||||
func (nc *NotificationController) DeleteBinding(c *gin.Context) {
|
||||
id := c.Param("id")
|
||||
if id == "" {
|
||||
utils.BadRequest(c, "缺少绑定ID")
|
||||
return
|
||||
}
|
||||
|
||||
if err := nc.notifyService.DeleteBinding(id); err != nil {
|
||||
utils.ServerError(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
utils.SuccessMsg(c, "删除成功")
|
||||
}
|
||||
|
||||
// SendNotification API 发送通知(供脚本调用)
|
||||
func (nc *NotificationController) SendNotification(c *gin.Context) {
|
||||
var req struct {
|
||||
ChannelID string `json:"channel_id"`
|
||||
Title string `json:"title"`
|
||||
Text string `json:"text"`
|
||||
}
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
utils.BadRequest(c, "参数错误")
|
||||
return
|
||||
}
|
||||
|
||||
if req.ChannelID == "" || req.Title == "" {
|
||||
utils.BadRequest(c, "channel_id 和 title 不能为空")
|
||||
return
|
||||
}
|
||||
|
||||
result := nc.notifyService.SendByChannelID(req.ChannelID, &services.NotifyMessage{
|
||||
Title: req.Title,
|
||||
Text: req.Text,
|
||||
})
|
||||
|
||||
utils.Success(c, result)
|
||||
}
|
||||
@@ -76,6 +76,10 @@ func (sc *SettingsController) ChangePassword(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
go services.NewNotificationService().TriggerEvent(constant.BindingTypeSystem, constant.EventPasswordChanged, "", map[string]interface{}{
|
||||
"username": user.Username,
|
||||
})
|
||||
|
||||
utils.SuccessMsg(c, "密码修改成功")
|
||||
}
|
||||
|
||||
@@ -373,3 +377,39 @@ func (sc *SettingsController) RestoreBackup(c *gin.Context) {
|
||||
|
||||
utils.SuccessMsg(c, "恢复成功")
|
||||
}
|
||||
|
||||
// GetSetting 获取单个设置值
|
||||
func (sc *SettingsController) GetSetting(c *gin.Context) {
|
||||
section := c.Param("section")
|
||||
key := c.Param("key")
|
||||
|
||||
if section == "" || key == "" {
|
||||
utils.BadRequest(c, "参数错误")
|
||||
return
|
||||
}
|
||||
|
||||
value := sc.settingsService.Get(section, key)
|
||||
utils.Success(c, value)
|
||||
}
|
||||
|
||||
// GenerateSettingToken 为指定设置生成随机token
|
||||
func (sc *SettingsController) GenerateSettingToken(c *gin.Context) {
|
||||
section := c.Param("section")
|
||||
key := c.Param("key")
|
||||
|
||||
if section == "" || key == "" {
|
||||
utils.BadRequest(c, "参数错误")
|
||||
return
|
||||
}
|
||||
|
||||
// 生成32位随机token
|
||||
token := strings.ToLower(utils.RandomString(32))
|
||||
|
||||
// 保存到数据库
|
||||
if err := sc.settingsService.Set(section, key, token); err != nil {
|
||||
utils.ServerError(c, "保存失败")
|
||||
return
|
||||
}
|
||||
|
||||
utils.Success(c, token)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user