mirror of
https://gitee.com/samwaf/SamWaf.git
synced 2026-10-31 02:01:44 +08:00
!45 feat: per-entry enable switches for IP/URL black and white lists
Merge pull request !45 from samwaf/feat_list_switches
This commit is contained in:
+38
-1
@@ -37,6 +37,10 @@ func (w *WafAllowIpApi) AddApi(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
req.IpType, req.Ip, req.GroupCode = ipType, ip, groupCode
|
||||
if req.IsEnable != nil && *req.IsEnable != 0 && *req.IsEnable != 1 {
|
||||
response.FailWithMessage("is_enable 取值只能是 0 或 1", c)
|
||||
return
|
||||
}
|
||||
|
||||
err = wafIpAllowService.CheckIsExistApi(req)
|
||||
if err != nil && errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
@@ -156,6 +160,10 @@ func (w *WafAllowIpApi) ModifyAllowIpApi(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
req.IpType, req.Ip, req.GroupCode = ipType, ip, groupCode
|
||||
if req.IsEnable != nil && *req.IsEnable != 0 && *req.IsEnable != 1 {
|
||||
response.FailWithMessage("is_enable 取值只能是 0 或 1", c)
|
||||
return
|
||||
}
|
||||
|
||||
//编辑前先取旧记录,拿到可能被本次编辑改掉的旧 host_code(issue #898)
|
||||
bean := wafIpAllowService.GetDetailByIdApi(req.Id)
|
||||
@@ -172,13 +180,42 @@ func (w *WafAllowIpApi) ModifyAllowIpApi(c *gin.Context) {
|
||||
}
|
||||
}
|
||||
|
||||
// ToggleApi 切换IP白名单条目启用状态
|
||||
// @Summary 切换IP白名单条目启用状态
|
||||
// @Description 启用或停用单条IP白名单记录,停用的条目不再对引擎生效
|
||||
// @Tags 网站防护-IP白名单
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param data body request.WafAllowIpToggleReq true "条目ID与目标状态"
|
||||
// @Success 200 {object} response.Response "操作成功"
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /wafhost/ipwhite/toggle [post]
|
||||
func (w *WafAllowIpApi) ToggleApi(c *gin.Context) {
|
||||
var req request.WafAllowIpToggleReq
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
response.FailWithMessage("解析失败", c)
|
||||
return
|
||||
}
|
||||
if *req.IsEnable != 0 && *req.IsEnable != 1 {
|
||||
response.FailWithMessage("is_enable 取值只能是 0 或 1", c)
|
||||
return
|
||||
}
|
||||
hostCode, err := wafIpAllowService.ToggleApi(req)
|
||||
if err != nil {
|
||||
response.FailWithMessage("操作失败", c)
|
||||
return
|
||||
}
|
||||
w.NotifyWaf(hostCode)
|
||||
response.OkWithMessage("操作成功", c)
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
通知到waf引擎实时生效
|
||||
*/
|
||||
func (w *WafAllowIpApi) NotifyWaf(host_code string) {
|
||||
var ipWhites []model.IPAllowList
|
||||
global.GWAF_LOCAL_DB.Where("host_code = ? ", host_code).Find(&ipWhites)
|
||||
global.GWAF_LOCAL_DB.Where("host_code = ? and is_enable = 1", host_code).Find(&ipWhites)
|
||||
var chanInfo = spec.ChanCommonHost{
|
||||
HostCode: host_code,
|
||||
Type: enums.ChanTypeAllowIP,
|
||||
|
||||
+38
-1
@@ -30,6 +30,10 @@ func (w *WafAllowUrlApi) AddApi(c *gin.Context) {
|
||||
var req request.WafAllowUrlAddReq
|
||||
err := c.ShouldBindJSON(&req)
|
||||
if err == nil {
|
||||
if req.IsEnable != nil && *req.IsEnable != 0 && *req.IsEnable != 1 {
|
||||
response.FailWithMessage("is_enable 取值只能是 0 或 1", c)
|
||||
return
|
||||
}
|
||||
err = wafUrlAllowService.CheckIsExistApi(req)
|
||||
if err != nil && errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
err = wafUrlAllowService.AddApi(req)
|
||||
@@ -142,6 +146,10 @@ func (w *WafAllowUrlApi) ModifyAllowUrlApi(c *gin.Context) {
|
||||
var req request.WafAllowUrlEditReq
|
||||
err := c.ShouldBindJSON(&req)
|
||||
if err == nil {
|
||||
if req.IsEnable != nil && *req.IsEnable != 0 && *req.IsEnable != 1 {
|
||||
response.FailWithMessage("is_enable 取值只能是 0 或 1", c)
|
||||
return
|
||||
}
|
||||
//编辑前先取旧记录,拿到可能被本次编辑改掉的旧 host_code(issue #898)
|
||||
bean := wafUrlAllowService.GetDetailByIdApi(req.Id)
|
||||
err = wafUrlAllowService.ModifyApi(req)
|
||||
@@ -157,13 +165,42 @@ func (w *WafAllowUrlApi) ModifyAllowUrlApi(c *gin.Context) {
|
||||
}
|
||||
}
|
||||
|
||||
// ToggleApi 切换URL白名单条目启用状态
|
||||
// @Summary 切换URL白名单条目启用状态
|
||||
// @Description 启用或停用单条URL白名单记录,停用的条目不再对引擎生效
|
||||
// @Tags 网站防护-URL白名单
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param data body request.WafAllowUrlToggleReq true "条目ID与目标状态"
|
||||
// @Success 200 {object} response.Response "操作成功"
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /wafhost/urlwhite/toggle [post]
|
||||
func (w *WafAllowUrlApi) ToggleApi(c *gin.Context) {
|
||||
var req request.WafAllowUrlToggleReq
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
response.FailWithMessage("解析失败", c)
|
||||
return
|
||||
}
|
||||
if *req.IsEnable != 0 && *req.IsEnable != 1 {
|
||||
response.FailWithMessage("is_enable 取值只能是 0 或 1", c)
|
||||
return
|
||||
}
|
||||
hostCode, err := wafUrlAllowService.ToggleApi(req)
|
||||
if err != nil {
|
||||
response.FailWithMessage("操作失败", c)
|
||||
return
|
||||
}
|
||||
w.NotifyWaf(hostCode)
|
||||
response.OkWithMessage("操作成功", c)
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
通知到waf引擎实时生效
|
||||
*/
|
||||
func (w *WafAllowUrlApi) NotifyWaf(host_code string) {
|
||||
var urlWhites []model.URLAllowList
|
||||
global.GWAF_LOCAL_DB.Where("host_code = ? ", host_code).Find(&urlWhites)
|
||||
global.GWAF_LOCAL_DB.Where("host_code = ? and is_enable = 1", host_code).Find(&urlWhites)
|
||||
var chanInfo = spec.ChanCommonHost{
|
||||
HostCode: host_code,
|
||||
Type: enums.ChanTypeAllowURL,
|
||||
|
||||
+38
-1
@@ -41,6 +41,10 @@ func (w *WafBlockIpApi) AddApi(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
req.IpType, req.Ip, req.GroupCode = ipType, ip, groupCode
|
||||
if req.IsEnable != nil && *req.IsEnable != 0 && *req.IsEnable != 1 {
|
||||
response.FailWithMessage("is_enable 取值只能是 0 或 1", c)
|
||||
return
|
||||
}
|
||||
|
||||
// 封禁层级:""/waf=WAF应用层(默认) | system=系统防火墙 | both=两者
|
||||
layer := req.TargetLayer
|
||||
@@ -196,6 +200,10 @@ func (w *WafBlockIpApi) ModifyBlockIpApi(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
req.IpType, req.Ip, req.GroupCode = ipType, ip, groupCode
|
||||
if req.IsEnable != nil && *req.IsEnable != 0 && *req.IsEnable != 1 {
|
||||
response.FailWithMessage("is_enable 取值只能是 0 或 1", c)
|
||||
return
|
||||
}
|
||||
|
||||
//编辑前先取旧记录,拿到可能被本次编辑改掉的旧 host_code(issue #898)
|
||||
bean := wafIpBlockService.GetDetailByIdApi(req.Id)
|
||||
@@ -271,13 +279,42 @@ func (w *WafBlockIpApi) DelAllBlockIpApi(c *gin.Context) {
|
||||
}
|
||||
}
|
||||
|
||||
// ToggleApi 切换IP黑名单条目启用状态
|
||||
// @Summary 切换IP黑名单条目启用状态
|
||||
// @Description 启用或停用单条IP黑名单记录,停用的条目不再对引擎生效
|
||||
// @Tags 网站防护-IP黑名单
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param data body request.WafBlockIpToggleReq true "条目ID与目标状态"
|
||||
// @Success 200 {object} response.Response "操作成功"
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /wafhost/ipblock/toggle [post]
|
||||
func (w *WafBlockIpApi) ToggleApi(c *gin.Context) {
|
||||
var req request.WafBlockIpToggleReq
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
response.FailWithMessage("解析失败", c)
|
||||
return
|
||||
}
|
||||
if *req.IsEnable != 0 && *req.IsEnable != 1 {
|
||||
response.FailWithMessage("is_enable 取值只能是 0 或 1", c)
|
||||
return
|
||||
}
|
||||
hostCode, err := wafIpBlockService.ToggleApi(req)
|
||||
if err != nil {
|
||||
response.FailWithMessage("操作失败", c)
|
||||
return
|
||||
}
|
||||
w.NotifyWaf(hostCode)
|
||||
response.OkWithMessage("操作成功", c)
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
通知到waf引擎实时生效
|
||||
*/
|
||||
func (w *WafBlockIpApi) NotifyWaf(host_code string) {
|
||||
var ipWhites []model.IPBlockList
|
||||
global.GWAF_LOCAL_DB.Where("host_code = ? ", host_code).Find(&ipWhites)
|
||||
global.GWAF_LOCAL_DB.Where("host_code = ? and is_enable = 1", host_code).Find(&ipWhites)
|
||||
var chanInfo = spec.ChanCommonHost{
|
||||
HostCode: host_code,
|
||||
Type: enums.ChanTypeBlockIP,
|
||||
|
||||
+38
-1
@@ -30,6 +30,10 @@ func (w *WafBlockUrlApi) AddApi(c *gin.Context) {
|
||||
var req request.WafBlockUrlAddReq
|
||||
err := c.ShouldBindJSON(&req)
|
||||
if err == nil {
|
||||
if req.IsEnable != nil && *req.IsEnable != 0 && *req.IsEnable != 1 {
|
||||
response.FailWithMessage("is_enable 取值只能是 0 或 1", c)
|
||||
return
|
||||
}
|
||||
err = wafUrlBlockService.CheckIsExistApi(req)
|
||||
if err != nil && errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
err = wafUrlBlockService.AddApi(req)
|
||||
@@ -142,6 +146,10 @@ func (w *WafBlockUrlApi) ModifyBlockUrlApi(c *gin.Context) {
|
||||
var req request.WafBlockUrlEditReq
|
||||
err := c.ShouldBindJSON(&req)
|
||||
if err == nil {
|
||||
if req.IsEnable != nil && *req.IsEnable != 0 && *req.IsEnable != 1 {
|
||||
response.FailWithMessage("is_enable 取值只能是 0 或 1", c)
|
||||
return
|
||||
}
|
||||
//编辑前先取旧记录,拿到可能被本次编辑改掉的旧 host_code(issue #898)
|
||||
bean := wafUrlBlockService.GetDetailByIdApi(req.Id)
|
||||
err = wafUrlBlockService.ModifyApi(req)
|
||||
@@ -157,13 +165,42 @@ func (w *WafBlockUrlApi) ModifyBlockUrlApi(c *gin.Context) {
|
||||
}
|
||||
}
|
||||
|
||||
// ToggleApi 切换URL黑名单条目启用状态
|
||||
// @Summary 切换URL黑名单条目启用状态
|
||||
// @Description 启用或停用单条URL黑名单记录,停用的条目不再对引擎生效
|
||||
// @Tags 网站防护-URL黑名单
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param data body request.WafBlockUrlToggleReq true "条目ID与目标状态"
|
||||
// @Success 200 {object} response.Response "操作成功"
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /wafhost/urlblock/toggle [post]
|
||||
func (w *WafBlockUrlApi) ToggleApi(c *gin.Context) {
|
||||
var req request.WafBlockUrlToggleReq
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
response.FailWithMessage("解析失败", c)
|
||||
return
|
||||
}
|
||||
if *req.IsEnable != 0 && *req.IsEnable != 1 {
|
||||
response.FailWithMessage("is_enable 取值只能是 0 或 1", c)
|
||||
return
|
||||
}
|
||||
hostCode, err := wafUrlBlockService.ToggleApi(req)
|
||||
if err != nil {
|
||||
response.FailWithMessage("操作失败", c)
|
||||
return
|
||||
}
|
||||
w.NotifyWaf(hostCode)
|
||||
response.OkWithMessage("操作成功", c)
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
通知到waf引擎实时生效
|
||||
*/
|
||||
func (w *WafBlockUrlApi) NotifyWaf(host_code string) {
|
||||
var urlWhites []model.URLBlockList
|
||||
global.GWAF_LOCAL_DB.Where("host_code = ? ", host_code).Find(&urlWhites)
|
||||
global.GWAF_LOCAL_DB.Where("host_code = ? and is_enable = 1", host_code).Find(&urlWhites)
|
||||
var chanInfo = spec.ChanCommonHost{
|
||||
HostCode: host_code,
|
||||
Type: enums.ChanTypeBlockURL,
|
||||
|
||||
@@ -13,6 +13,7 @@ type IPAllowList struct {
|
||||
// 存量行为空串,等同于 ip,判定处一律只判 == IPEntryTypeGroup。
|
||||
IpType string `gorm:"size:20" json:"ip_type"`
|
||||
GroupCode string `gorm:"size:64" json:"group_code"` //IpType=group 时指向 ip_group.group_code
|
||||
IsEnable int `gorm:"column:is_enable" json:"is_enable"` //1启用 0停用(停用条目不下发引擎)
|
||||
}
|
||||
type URLAllowList struct {
|
||||
baseorm.BaseOrm
|
||||
@@ -20,4 +21,5 @@ type URLAllowList struct {
|
||||
CompareType string `gorm:"size:50" json:"compare_type"` //判断类型,包含、开始、结束、完全匹配
|
||||
Url string `gorm:"type:text" json:"url"` //请求地址
|
||||
Remarks string `gorm:"size:500" json:"remarks"` //备注
|
||||
IsEnable int `gorm:"column:is_enable" json:"is_enable"` //1启用 0停用(停用条目不下发引擎)
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ type IPBlockList struct {
|
||||
// 存量行为空串,等同于 ip,判定处一律只判 == IPEntryTypeGroup。
|
||||
IpType string `gorm:"size:20" json:"ip_type"`
|
||||
GroupCode string `gorm:"size:64" json:"group_code"` //IpType=group 时指向 ip_group.group_code
|
||||
IsEnable int `gorm:"column:is_enable" json:"is_enable"` //1启用 0停用(停用条目不下发引擎)
|
||||
}
|
||||
|
||||
type URLBlockList struct {
|
||||
@@ -21,4 +22,5 @@ type URLBlockList struct {
|
||||
CompareType string `gorm:"size:50" json:"compare_type" form:"compare_type"` //对比方式
|
||||
Url string `gorm:"type:text" json:"url"` //限制请求地址
|
||||
Remarks string `gorm:"size:500" json:"remarks"` //备注
|
||||
IsEnable int `gorm:"column:is_enable" json:"is_enable"` //1启用 0停用(停用条目不下发引擎)
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ type WafAllowIpAddReq struct {
|
||||
Remarks string `json:"remarks"` //备注
|
||||
IpType string `json:"ip_type"` //条目类型: ""/ip(单条) | group(引用IP组)
|
||||
GroupCode string `json:"group_code"` //IpType=group 时的IP组短码
|
||||
IsEnable *int `json:"is_enable"` //启用状态:nil=新增默认启用/编辑不改动,0停用 1启用
|
||||
}
|
||||
type WafAllowIpDelReq struct {
|
||||
Id string `json:"id" form:"id"` //白名单IP唯一键
|
||||
@@ -25,6 +26,7 @@ type WafAllowIpEditReq struct {
|
||||
Remarks string `json:"remarks"` //备注
|
||||
IpType string `json:"ip_type"` //条目类型: ""/ip(单条) | group(引用IP组)
|
||||
GroupCode string `json:"group_code"` //IpType=group 时的IP组短码
|
||||
IsEnable *int `json:"is_enable"` //启用状态:nil=新增默认启用/编辑不改动,0停用 1启用
|
||||
}
|
||||
type WafAllowIpSearchReq struct {
|
||||
HostCode string `json:"host_code" ` //主机码
|
||||
@@ -39,3 +41,8 @@ type WafAllowIpBatchDelReq struct {
|
||||
type WafAllowIpDelAllReq struct {
|
||||
HostCode string `json:"host_code" form:"host_code"` //网站唯一码,为空则删除所有
|
||||
}
|
||||
|
||||
type WafAllowIpToggleReq struct {
|
||||
Id string `json:"id" form:"id" binding:"required"` //条目唯一键
|
||||
IsEnable *int `json:"is_enable" form:"is_enable" binding:"required"` //1启用 0停用(必填,防漏字段被当成停用)
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ type WafAllowUrlAddReq struct {
|
||||
CompareType string `json:"compare_type" form:"compare_type" binding:"required"` //对比方式
|
||||
Url string `json:"url" binding:"required"` //白名单url
|
||||
Remarks string `json:"remarks"` //备注
|
||||
IsEnable *int `json:"is_enable"` //启用状态:nil=新增默认启用/编辑不改动,0停用 1启用
|
||||
}
|
||||
type WafAllowUrlDelReq struct {
|
||||
Id string `json:"id" form:"id"` //白名单url唯一键
|
||||
@@ -21,6 +22,7 @@ type WafAllowUrlEditReq struct {
|
||||
CompareType string `json:"compare_type" form:"compare_type" binding:"required"` //对比方式
|
||||
Url string `json:"url" binding:"required"` //白名单url
|
||||
Remarks string `json:"remarks"` //备注
|
||||
IsEnable *int `json:"is_enable"` //启用状态:nil=新增默认启用/编辑不改动,0停用 1启用
|
||||
}
|
||||
|
||||
type WafAllowUrlSearchReq struct {
|
||||
@@ -36,3 +38,8 @@ type WafAllowUrlBatchDelReq struct {
|
||||
type WafAllowUrlDelAllReq struct {
|
||||
HostCode string `json:"host_code" form:"host_code"` //网站唯一码
|
||||
}
|
||||
|
||||
type WafAllowUrlToggleReq struct {
|
||||
Id string `json:"id" form:"id" binding:"required"` //条目唯一键
|
||||
IsEnable *int `json:"is_enable" form:"is_enable" binding:"required"` //1启用 0停用(必填,防漏字段被当成停用)
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ type WafBlockIpAddReq struct {
|
||||
TargetLayer string `json:"target_layer"` //封禁层级: ""/waf(WAF应用层) | system(系统防火墙) | both(两者)
|
||||
IpType string `json:"ip_type"` //条目类型: ""/ip(单条) | group(引用IP组)
|
||||
GroupCode string `json:"group_code"` //IpType=group 时的IP组短码
|
||||
IsEnable *int `json:"is_enable"` //启用状态:nil=新增默认启用/编辑不改动,0停用 1启用
|
||||
}
|
||||
|
||||
type WafBlockIpEditReq struct {
|
||||
@@ -21,6 +22,7 @@ type WafBlockIpEditReq struct {
|
||||
Remarks string `json:"remarks"` //备注
|
||||
IpType string `json:"ip_type"` //条目类型: ""/ip(单条) | group(引用IP组)
|
||||
GroupCode string `json:"group_code"` //IpType=group 时的IP组短码
|
||||
IsEnable *int `json:"is_enable"` //启用状态:nil=新增默认启用/编辑不改动,0停用 1启用
|
||||
}
|
||||
type WafBlockIpDelReq struct {
|
||||
Id string `json:"id" form:"id"` //Block IP唯一键
|
||||
@@ -44,3 +46,8 @@ type WafBlockIpBatchDelReq struct {
|
||||
type WafBlockIpDelAllReq struct {
|
||||
HostCode string `json:"host_code" form:"host_code"` //网站唯一码,为空则删除所有
|
||||
}
|
||||
|
||||
type WafBlockIpToggleReq struct {
|
||||
Id string `json:"id" form:"id" binding:"required"` //条目唯一键
|
||||
IsEnable *int `json:"is_enable" form:"is_enable" binding:"required"` //1启用 0停用(必填,防漏字段被当成停用)
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ type WafBlockUrlAddReq struct {
|
||||
CompareType string `json:"compare_type" form:"compare_type" binding:"required"` //对比方式
|
||||
Url string `json:"url" binding:"required"` //Block url
|
||||
Remarks string `json:"remarks"` //备注
|
||||
IsEnable *int `json:"is_enable"` //启用状态:nil=新增默认启用/编辑不改动,0停用 1启用
|
||||
}
|
||||
type WafBlockUrlSearchReq struct {
|
||||
HostCode string `json:"host_code" ` //主机码
|
||||
@@ -26,6 +27,7 @@ type WafBlockUrlEditReq struct {
|
||||
CompareType string `json:"compare_type" form:"compare_type" binding:"required"` //对比方式
|
||||
Url string `json:"url" binding:"required"` //Block url
|
||||
Remarks string `json:"remarks"` //备注
|
||||
IsEnable *int `json:"is_enable"` //启用状态:nil=新增默认启用/编辑不改动,0停用 1启用
|
||||
}
|
||||
|
||||
// 批量删除请求结构体
|
||||
@@ -37,3 +39,8 @@ type WafBlockUrlBatchDelReq struct {
|
||||
type WafBlockUrlDelAllReq struct {
|
||||
HostCode string `json:"host_code"` // 网站唯一码,为空则删除所有
|
||||
}
|
||||
|
||||
type WafBlockUrlToggleReq struct {
|
||||
Id string `json:"id" form:"id" binding:"required"` //条目唯一键
|
||||
IsEnable *int `json:"is_enable" form:"is_enable" binding:"required"` //1启用 0停用(必填,防漏字段被当成停用)
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ func (receiver *AllowIpRouter) InitAllowIpRouter(group *gin.RouterGroup) {
|
||||
allowIpRouter.POST("/api/v1/wafhost/ipwhite/add", AllowIpRouterApi.AddApi)
|
||||
allowIpRouter.GET("/api/v1/wafhost/ipwhite/del", AllowIpRouterApi.DelAllowIpApi)
|
||||
allowIpRouter.POST("/api/v1/wafhost/ipwhite/edit", AllowIpRouterApi.ModifyAllowIpApi)
|
||||
allowIpRouter.POST("/api/v1/wafhost/ipwhite/toggle", AllowIpRouterApi.ToggleApi)
|
||||
|
||||
allowIpRouter.POST("/api/v1/wafhost/ipwhite/batchdel", AllowIpRouterApi.BatchDelAllowIpApi)
|
||||
allowIpRouter.POST("/api/v1/wafhost/ipwhite/delall", AllowIpRouterApi.DelAllAllowIpApi)
|
||||
|
||||
@@ -16,6 +16,7 @@ func (receiver *AllowUrlRouter) InitAllowUrlRouter(group *gin.RouterGroup) {
|
||||
allowUrlRouter.POST("/api/v1/wafhost/urlwhite/add", AllowUrlRouterApi.AddApi)
|
||||
allowUrlRouter.GET("/api/v1/wafhost/urlwhite/del", AllowUrlRouterApi.DelAllowUrlApi)
|
||||
allowUrlRouter.POST("/api/v1/wafhost/urlwhite/edit", AllowUrlRouterApi.ModifyAllowUrlApi)
|
||||
allowUrlRouter.POST("/api/v1/wafhost/urlwhite/toggle", AllowUrlRouterApi.ToggleApi)
|
||||
// 新增批量删除路由
|
||||
allowUrlRouter.POST("/api/v1/wafhost/urlwhite/batchdel", AllowUrlRouterApi.BatchDelAllowUrlApi)
|
||||
// 新增全部删除路由
|
||||
|
||||
@@ -17,6 +17,7 @@ func (receiver *BlockIpRouter) InitBlockIpRouter(group *gin.RouterGroup) {
|
||||
router.GET("/api/v1/wafhost/ipblock/recommend-layer", api.GetRecommendLayerApi) // 推荐封禁层级(智能默认)
|
||||
router.GET("/api/v1/wafhost/ipblock/del", api.DelBlockIpApi)
|
||||
router.POST("/api/v1/wafhost/ipblock/edit", api.ModifyBlockIpApi)
|
||||
router.POST("/api/v1/wafhost/ipblock/toggle", api.ToggleApi)
|
||||
router.POST("/api/v1/wafhost/ipblock/batch/del", api.BatchDelBlockIpApi)
|
||||
router.POST("/api/v1/wafhost/ipblock/delall", api.DelAllBlockIpApi)
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ func (receiver *BlockUrlRouter) InitBlockUrlRouter(group *gin.RouterGroup) {
|
||||
router.POST("/api/v1/wafhost/urlblock/add", api.AddApi)
|
||||
router.GET("/api/v1/wafhost/urlblock/del", api.DelBlockUrlApi)
|
||||
router.POST("/api/v1/wafhost/urlblock/edit", api.ModifyBlockUrlApi)
|
||||
router.POST("/api/v1/wafhost/urlblock/toggle", api.ToggleApi)
|
||||
router.POST("/api/v1/wafhost/urlblock/batchdel", api.BatchDelBlockUrlApi)
|
||||
router.POST("/api/v1/wafhost/urlblock/delall", api.DelAllBlockUrlApi)
|
||||
}
|
||||
|
||||
@@ -32,6 +32,8 @@ func runCoreCases(t *testing.T, db *gorm.DB) {
|
||||
// ————— 新增:各 service 完整 CRUD 回路 —————
|
||||
runCoreCRUDCases(t, db)
|
||||
runCoreCRUDCasesB(t, db)
|
||||
// 名单条目启用开关(is_enable)三库回归
|
||||
runListEnableSwitchCases(t, db)
|
||||
// ————— 升级须知:生成幂等 / 状态流转 / 降级不生成 —————
|
||||
runUpgradeNoticeCases(t, db)
|
||||
}
|
||||
@@ -324,12 +326,12 @@ func runCoreCRUDCases(t *testing.T, db *gorm.DB) {
|
||||
t.Run("BatchTask", func(t *testing.T) {
|
||||
name := "bt_" + sfx()
|
||||
fatalIf(t, WafBatchServiceApp.AddApi(request.BatchTaskAddReq{
|
||||
BatchTaskName: name, BatchType: "ip_black", BatchSourceType: "local", BatchTriggerType: "manual", BatchSource: "/tmp/x", BatchExecuteMethod: "append",
|
||||
BatchTaskName: name, BatchType: "ipdeny", BatchSourceType: "local", BatchTriggerType: "manual", BatchSource: "/tmp/x", BatchExecuteMethod: "append",
|
||||
}))
|
||||
var bean model.BatchTask
|
||||
firstBy(t, db, &bean, "batch_task_name = ?", name)
|
||||
fatalIf(t, WafBatchServiceApp.ModifyApi(request.BatchTaskEditReq{
|
||||
Id: bean.Id, BatchTaskName: name, BatchType: "ip_black", BatchSourceType: "local", BatchTriggerType: "manual", BatchSource: "/tmp/y", BatchExecuteMethod: "append",
|
||||
Id: bean.Id, BatchTaskName: name, BatchType: "ipdeny", BatchSourceType: "local", BatchTriggerType: "manual", BatchSource: "/tmp/y", BatchExecuteMethod: "append",
|
||||
}))
|
||||
got := WafBatchServiceApp.GetDetailByIdApi(bean.Id)
|
||||
if got.BatchSource != "/tmp/y" {
|
||||
@@ -377,3 +379,187 @@ func runCoreCRUDCases(t *testing.T, db *gorm.DB) {
|
||||
assertGone(t, db, &model.DelayMsg{}, bean.Id)
|
||||
})
|
||||
}
|
||||
|
||||
// ========================= 名单条目启用开关(is_enable) =========================
|
||||
|
||||
// runListEnableSwitchCases 四类名单 is_enable 三库一致性:
|
||||
// - service 新增未传开关字段 → 启用(产品默认)
|
||||
// - service 新增显式 0 → 停用(弹窗关着开关新增;防 default 标签把 0 吞成 1 的回归)
|
||||
// - toggle 0→读回 0→toggle 1→读回 1
|
||||
// - 裸结构体 Create 不带该字段 → 0(字段无 default 标签的语义锚;
|
||||
// 若有人往模型上加回 default 标签,此用例会先红)
|
||||
func runListEnableSwitchCases(t *testing.T, db *gorm.DB) {
|
||||
type iostub struct {
|
||||
addNil func() error
|
||||
addZero func() error
|
||||
addOne func() error
|
||||
toggle func(id string, v int) error
|
||||
findByHC func(hostCode string) (int, error)
|
||||
}
|
||||
zero, one := 0, 1
|
||||
mk := []struct {
|
||||
name string
|
||||
kit func() iostub
|
||||
}{
|
||||
{"LSV_AllowIP", func() iostub {
|
||||
return iostub{
|
||||
addNil: func() error {
|
||||
return WafWhiteIpServiceApp.AddApi(request.WafAllowIpAddReq{HostCode: "hc_nil", Ip: "10.10.0.1", Remarks: "x"})
|
||||
},
|
||||
addZero: func() error {
|
||||
return WafWhiteIpServiceApp.AddApi(request.WafAllowIpAddReq{HostCode: "hc_zero", Ip: "10.10.0.2", Remarks: "x", IsEnable: &zero})
|
||||
},
|
||||
addOne: func() error {
|
||||
return WafWhiteIpServiceApp.AddApi(request.WafAllowIpAddReq{HostCode: "hc_one", Ip: "10.10.0.3", Remarks: "x", IsEnable: &one})
|
||||
},
|
||||
toggle: func(id string, v int) error {
|
||||
val := v
|
||||
_, err := WafWhiteIpServiceApp.ToggleApi(request.WafAllowIpToggleReq{Id: id, IsEnable: &val})
|
||||
return err
|
||||
},
|
||||
findByHC: func(hostCode string) (int, error) {
|
||||
var b model.IPAllowList
|
||||
if err := db.Where("host_code = ?", hostCode).First(&b).Error; err != nil {
|
||||
return -1, err
|
||||
}
|
||||
return b.IsEnable, nil
|
||||
},
|
||||
}
|
||||
}},
|
||||
{"LSV_BlockIP", func() iostub {
|
||||
return iostub{
|
||||
addNil: func() error {
|
||||
return WafBlockIpServiceApp.AddApi(request.WafBlockIpAddReq{HostCode: "hc_nil", Ip: "10.10.1.1", Remarks: "x"})
|
||||
},
|
||||
addZero: func() error {
|
||||
return WafBlockIpServiceApp.AddApi(request.WafBlockIpAddReq{HostCode: "hc_zero", Ip: "10.10.1.2", Remarks: "x", IsEnable: &zero})
|
||||
},
|
||||
addOne: func() error {
|
||||
return WafBlockIpServiceApp.AddApi(request.WafBlockIpAddReq{HostCode: "hc_one", Ip: "10.10.1.3", Remarks: "x", IsEnable: &one})
|
||||
},
|
||||
toggle: func(id string, v int) error {
|
||||
val := v
|
||||
_, err := WafBlockIpServiceApp.ToggleApi(request.WafBlockIpToggleReq{Id: id, IsEnable: &val})
|
||||
return err
|
||||
},
|
||||
findByHC: func(hostCode string) (int, error) {
|
||||
var b model.IPBlockList
|
||||
if err := db.Where("host_code = ?", hostCode).First(&b).Error; err != nil {
|
||||
return -1, err
|
||||
}
|
||||
return b.IsEnable, nil
|
||||
},
|
||||
}
|
||||
}},
|
||||
{"LSV_AllowURL", func() iostub {
|
||||
return iostub{
|
||||
addNil: func() error {
|
||||
return WafWhiteUrlServiceApp.AddApi(request.WafAllowUrlAddReq{HostCode: "hc_nil", CompareType: "等于", Url: "/lsv-nil", Remarks: "x"})
|
||||
},
|
||||
addZero: func() error {
|
||||
return WafWhiteUrlServiceApp.AddApi(request.WafAllowUrlAddReq{HostCode: "hc_zero", CompareType: "等于", Url: "/lsv-zero", Remarks: "x", IsEnable: &zero})
|
||||
},
|
||||
addOne: func() error {
|
||||
return WafWhiteUrlServiceApp.AddApi(request.WafAllowUrlAddReq{HostCode: "hc_one", CompareType: "等于", Url: "/lsv-one", Remarks: "x", IsEnable: &one})
|
||||
},
|
||||
toggle: func(id string, v int) error {
|
||||
val := v
|
||||
_, err := WafWhiteUrlServiceApp.ToggleApi(request.WafAllowUrlToggleReq{Id: id, IsEnable: &val})
|
||||
return err
|
||||
},
|
||||
findByHC: func(hostCode string) (int, error) {
|
||||
var b model.URLAllowList
|
||||
if err := db.Where("host_code = ?", hostCode).First(&b).Error; err != nil {
|
||||
return -1, err
|
||||
}
|
||||
return b.IsEnable, nil
|
||||
},
|
||||
}
|
||||
}},
|
||||
{"LSV_BlockURL", func() iostub {
|
||||
return iostub{
|
||||
addNil: func() error {
|
||||
return WafBlockUrlServiceApp.AddApi(request.WafBlockUrlAddReq{HostCode: "hc_nil", CompareType: "等于", Url: "/lsvb-nil", Remarks: "x"})
|
||||
},
|
||||
addZero: func() error {
|
||||
return WafBlockUrlServiceApp.AddApi(request.WafBlockUrlAddReq{HostCode: "hc_zero", CompareType: "等于", Url: "/lsvb-zero", Remarks: "x", IsEnable: &zero})
|
||||
},
|
||||
addOne: func() error {
|
||||
return WafBlockUrlServiceApp.AddApi(request.WafBlockUrlAddReq{HostCode: "hc_one", CompareType: "等于", Url: "/lsvb-one", Remarks: "x", IsEnable: &one})
|
||||
},
|
||||
toggle: func(id string, v int) error {
|
||||
val := v
|
||||
_, err := WafBlockUrlServiceApp.ToggleApi(request.WafBlockUrlToggleReq{Id: id, IsEnable: &val})
|
||||
return err
|
||||
},
|
||||
findByHC: func(hostCode string) (int, error) {
|
||||
var b model.URLBlockList
|
||||
if err := db.Where("host_code = ?", hostCode).First(&b).Error; err != nil {
|
||||
return -1, err
|
||||
}
|
||||
return b.IsEnable, nil
|
||||
},
|
||||
}
|
||||
}},
|
||||
}
|
||||
for _, it := range mk {
|
||||
it := it
|
||||
t.Run(it.name, func(t *testing.T) {
|
||||
k := it.kit()
|
||||
fatalIf(t, k.addNil())
|
||||
if v, err := k.findByHC("hc_nil"); err != nil || v != 1 {
|
||||
t.Fatalf("新增未传开关字段应为1(启用),实际 %d err=%v", v, err)
|
||||
}
|
||||
fatalIf(t, k.addZero())
|
||||
if v, err := k.findByHC("hc_zero"); err != nil || v != 0 {
|
||||
t.Fatalf("新增显式0应为0(停用),实际 %d err=%v(default 标签吞 0?)", v, err)
|
||||
}
|
||||
fatalIf(t, k.addOne())
|
||||
if v, err := k.findByHC("hc_one"); err != nil || v != 1 {
|
||||
t.Fatalf("新增显式1应为1,实际 %d err=%v", v, err)
|
||||
}
|
||||
// toggle 往返:0 落库、1 落库
|
||||
var b model.IPAllowList
|
||||
_ = b
|
||||
var id string
|
||||
switch it.name {
|
||||
case "LSV_AllowIP":
|
||||
var r model.IPAllowList
|
||||
firstBy(t, db, &r, "host_code = ?", "hc_zero")
|
||||
id = r.Id
|
||||
case "LSV_BlockIP":
|
||||
var r model.IPBlockList
|
||||
firstBy(t, db, &r, "host_code = ?", "hc_zero")
|
||||
id = r.Id
|
||||
case "LSV_AllowURL":
|
||||
var r model.URLAllowList
|
||||
firstBy(t, db, &r, "host_code = ?", "hc_zero")
|
||||
id = r.Id
|
||||
case "LSV_BlockURL":
|
||||
var r model.URLBlockList
|
||||
firstBy(t, db, &r, "host_code = ?", "hc_zero")
|
||||
id = r.Id
|
||||
}
|
||||
fatalIf(t, k.toggle(id, 0))
|
||||
if v, err := k.findByHC("hc_zero"); err != nil || v != 0 {
|
||||
t.Fatalf("toggle 0 应落库 0,实际 %d err=%v", v, err)
|
||||
}
|
||||
fatalIf(t, k.toggle(id, 1))
|
||||
if v, err := k.findByHC("hc_zero"); err != nil || v != 1 {
|
||||
t.Fatalf("toggle 1 应落库 1,实际 %d err=%v", v, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 语义锚:不带 default 标签的字段,裸结构体 Create 零值落库 0
|
||||
// (批量导入等绕过 service 的插入路径依赖显式写 1;此用例防止有人加回 default 标签)
|
||||
t.Run("BareCreateNoDefault", func(t *testing.T) {
|
||||
hc := "hc_bare_" + sfx()
|
||||
fatalIf(t, db.Create(&model.IPAllowList{BaseOrm: newBase(uuid.GenUUID()), HostCode: hc, Ip: "10.10.2.1"}).Error)
|
||||
var b model.IPAllowList
|
||||
firstBy(t, db, &b, "host_code = ?", hc)
|
||||
if b.IsEnable != 0 {
|
||||
t.Fatalf("裸 Create 零值应落库 0(无 default 标签语义),实际 %d", b.IsEnable)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -16,6 +16,10 @@ type WafWhiteIpService struct{}
|
||||
var WafWhiteIpServiceApp = new(WafWhiteIpService)
|
||||
|
||||
func (receiver *WafWhiteIpService) AddApi(wafWhiteIpAddReq request.WafAllowIpAddReq) error {
|
||||
isEnable := 1
|
||||
if wafWhiteIpAddReq.IsEnable != nil {
|
||||
isEnable = *wafWhiteIpAddReq.IsEnable
|
||||
}
|
||||
var wafHost = &model.IPAllowList{
|
||||
BaseOrm: baseorm.BaseOrm{
|
||||
Id: uuid.GenUUID(),
|
||||
@@ -29,14 +33,28 @@ func (receiver *WafWhiteIpService) AddApi(wafWhiteIpAddReq request.WafAllowIpAdd
|
||||
Remarks: wafWhiteIpAddReq.Remarks,
|
||||
IpType: wafWhiteIpAddReq.IpType,
|
||||
GroupCode: wafWhiteIpAddReq.GroupCode,
|
||||
IsEnable: isEnable,
|
||||
}
|
||||
global.GWAF_LOCAL_DB.Create(wafHost)
|
||||
return nil
|
||||
}
|
||||
|
||||
// ToggleApi 切换条目启用状态,返回所属网站编码供调用方通知引擎
|
||||
func (receiver *WafWhiteIpService) ToggleApi(req request.WafAllowIpToggleReq) (string, error) {
|
||||
var bean model.IPAllowList
|
||||
if err := global.GWAF_LOCAL_DB.Where("id = ?", req.Id).First(&bean).Error; err != nil {
|
||||
return "", err
|
||||
}
|
||||
err := global.GWAF_LOCAL_DB.Model(model.IPAllowList{}).Where("id = ?", req.Id).Updates(map[string]interface{}{
|
||||
"is_enable": *req.IsEnable,
|
||||
"UPDATE_TIME": customtype.JsonTime(time.Now()),
|
||||
}).Error
|
||||
return bean.HostCode, err
|
||||
}
|
||||
|
||||
// CheckIsExistApi 判重。唯一性由 (host_code, ip_type, ip, group_code) 共同决定:
|
||||
// 同一站点重复引用同一个 IP 组也算重复。
|
||||
// ip_type 用 IN ('', 'ip') 兼容存量行的空串。
|
||||
// ip_type 用 IN (”, 'ip') 兼容存量行的空串。
|
||||
func (receiver *WafWhiteIpService) CheckIsExistApi(wafWhiteIpAddReq request.WafAllowIpAddReq) error {
|
||||
if wafWhiteIpAddReq.IpType == model.IPEntryTypeGroup {
|
||||
return global.GWAF_LOCAL_DB.First(&model.IPAllowList{},
|
||||
@@ -68,6 +86,9 @@ func (receiver *WafWhiteIpService) ModifyApi(wafWhiteIpEditReq request.WafAllowI
|
||||
"group_code": wafWhiteIpEditReq.GroupCode,
|
||||
"UPDATE_TIME": customtype.JsonTime(time.Now()),
|
||||
}
|
||||
if wafWhiteIpEditReq.IsEnable != nil {
|
||||
ipWhiteMap["is_enable"] = *wafWhiteIpEditReq.IsEnable
|
||||
}
|
||||
err := global.GWAF_LOCAL_DB.Model(model.IPAllowList{}).Where("id = ?", wafWhiteIpEditReq.Id).Updates(ipWhiteMap).Error
|
||||
|
||||
return err
|
||||
|
||||
@@ -16,6 +16,10 @@ type WafWhiteUrlService struct{}
|
||||
var WafWhiteUrlServiceApp = new(WafWhiteUrlService)
|
||||
|
||||
func (receiver *WafWhiteUrlService) AddApi(req request.WafAllowUrlAddReq) error {
|
||||
isEnable := 1
|
||||
if req.IsEnable != nil {
|
||||
isEnable = *req.IsEnable
|
||||
}
|
||||
var bean = &model.URLAllowList{
|
||||
BaseOrm: baseorm.BaseOrm{
|
||||
Id: uuid.GenUUID(),
|
||||
@@ -28,11 +32,25 @@ func (receiver *WafWhiteUrlService) AddApi(req request.WafAllowUrlAddReq) error
|
||||
CompareType: req.CompareType,
|
||||
Url: req.Url,
|
||||
Remarks: req.Remarks,
|
||||
IsEnable: isEnable,
|
||||
}
|
||||
global.GWAF_LOCAL_DB.Create(bean)
|
||||
return nil
|
||||
}
|
||||
|
||||
// ToggleApi 切换条目启用状态,返回所属网站编码供调用方通知引擎
|
||||
func (receiver *WafWhiteUrlService) ToggleApi(req request.WafAllowUrlToggleReq) (string, error) {
|
||||
var bean model.URLAllowList
|
||||
if err := global.GWAF_LOCAL_DB.Where("id = ?", req.Id).First(&bean).Error; err != nil {
|
||||
return "", err
|
||||
}
|
||||
err := global.GWAF_LOCAL_DB.Model(model.URLAllowList{}).Where("id = ?", req.Id).Updates(map[string]interface{}{
|
||||
"is_enable": *req.IsEnable,
|
||||
"UPDATE_TIME": customtype.JsonTime(time.Now()),
|
||||
}).Error
|
||||
return bean.HostCode, err
|
||||
}
|
||||
|
||||
func (receiver *WafWhiteUrlService) CheckIsExistApi(req request.WafAllowUrlAddReq) error {
|
||||
return global.GWAF_LOCAL_DB.First(&model.URLAllowList{}, "host_code = ? and url= ?", req.HostCode,
|
||||
req.Url).Error
|
||||
@@ -51,6 +69,9 @@ func (receiver *WafWhiteUrlService) ModifyApi(req request.WafAllowUrlEditReq) er
|
||||
"Remarks": req.Remarks,
|
||||
"UPDATE_TIME": customtype.JsonTime(time.Now()),
|
||||
}
|
||||
if req.IsEnable != nil {
|
||||
ipWhiteMap["is_enable"] = *req.IsEnable
|
||||
}
|
||||
err := global.GWAF_LOCAL_DB.Model(model.URLAllowList{}).Where("id = ?", req.Id).Updates(ipWhiteMap).Error
|
||||
|
||||
return err
|
||||
|
||||
@@ -16,6 +16,10 @@ type WafBlockIpService struct{}
|
||||
var WafBlockIpServiceApp = new(WafBlockIpService)
|
||||
|
||||
func (receiver *WafBlockIpService) AddApi(req request.WafBlockIpAddReq) error {
|
||||
isEnable := 1
|
||||
if req.IsEnable != nil {
|
||||
isEnable = *req.IsEnable
|
||||
}
|
||||
var bean = &model.IPBlockList{
|
||||
BaseOrm: baseorm.BaseOrm{
|
||||
Id: uuid.GenUUID(),
|
||||
@@ -29,14 +33,28 @@ func (receiver *WafBlockIpService) AddApi(req request.WafBlockIpAddReq) error {
|
||||
Remarks: req.Remarks,
|
||||
IpType: req.IpType,
|
||||
GroupCode: req.GroupCode,
|
||||
IsEnable: isEnable,
|
||||
}
|
||||
global.GWAF_LOCAL_DB.Create(bean)
|
||||
return nil
|
||||
}
|
||||
|
||||
// ToggleApi 切换条目启用状态,返回所属网站编码供调用方通知引擎
|
||||
func (receiver *WafBlockIpService) ToggleApi(req request.WafBlockIpToggleReq) (string, error) {
|
||||
var bean model.IPBlockList
|
||||
if err := global.GWAF_LOCAL_DB.Where("id = ?", req.Id).First(&bean).Error; err != nil {
|
||||
return "", err
|
||||
}
|
||||
err := global.GWAF_LOCAL_DB.Model(model.IPBlockList{}).Where("id = ?", req.Id).Updates(map[string]interface{}{
|
||||
"is_enable": *req.IsEnable,
|
||||
"UPDATE_TIME": customtype.JsonTime(time.Now()),
|
||||
}).Error
|
||||
return bean.HostCode, err
|
||||
}
|
||||
|
||||
// CheckIsExistApi 判重。唯一性由 (host_code, ip_type, ip, group_code) 共同决定:
|
||||
// 同一站点重复引用同一个 IP 组也算重复。
|
||||
// ip_type 用 IN ('', 'ip') 兼容存量行的空串。
|
||||
// ip_type 用 IN (”, 'ip') 兼容存量行的空串。
|
||||
func (receiver *WafBlockIpService) CheckIsExistApi(req request.WafBlockIpAddReq) error {
|
||||
if req.IpType == model.IPEntryTypeGroup {
|
||||
return global.GWAF_LOCAL_DB.First(&model.IPBlockList{},
|
||||
@@ -67,6 +85,9 @@ func (receiver *WafBlockIpService) ModifyApi(req request.WafBlockIpEditReq) erro
|
||||
"group_code": req.GroupCode,
|
||||
"UPDATE_TIME": customtype.JsonTime(time.Now()),
|
||||
}
|
||||
if req.IsEnable != nil {
|
||||
ipWhiteMap["is_enable"] = *req.IsEnable
|
||||
}
|
||||
err := global.GWAF_LOCAL_DB.Model(model.IPBlockList{}).Where("id = ?", req.Id).Updates(ipWhiteMap).Error
|
||||
|
||||
return err
|
||||
|
||||
@@ -16,6 +16,10 @@ type WafBlockUrlService struct{}
|
||||
var WafBlockUrlServiceApp = new(WafBlockUrlService)
|
||||
|
||||
func (receiver *WafBlockUrlService) AddApi(req request.WafBlockUrlAddReq) error {
|
||||
isEnable := 1
|
||||
if req.IsEnable != nil {
|
||||
isEnable = *req.IsEnable
|
||||
}
|
||||
var bean = &model.URLBlockList{
|
||||
BaseOrm: baseorm.BaseOrm{
|
||||
Id: uuid.GenUUID(),
|
||||
@@ -28,11 +32,25 @@ func (receiver *WafBlockUrlService) AddApi(req request.WafBlockUrlAddReq) error
|
||||
Url: req.Url,
|
||||
CompareType: req.CompareType,
|
||||
Remarks: req.Remarks,
|
||||
IsEnable: isEnable,
|
||||
}
|
||||
global.GWAF_LOCAL_DB.Create(bean)
|
||||
return nil
|
||||
}
|
||||
|
||||
// ToggleApi 切换条目启用状态,返回所属网站编码供调用方通知引擎
|
||||
func (receiver *WafBlockUrlService) ToggleApi(req request.WafBlockUrlToggleReq) (string, error) {
|
||||
var bean model.URLBlockList
|
||||
if err := global.GWAF_LOCAL_DB.Where("id = ?", req.Id).First(&bean).Error; err != nil {
|
||||
return "", err
|
||||
}
|
||||
err := global.GWAF_LOCAL_DB.Model(model.URLBlockList{}).Where("id = ?", req.Id).Updates(map[string]interface{}{
|
||||
"is_enable": *req.IsEnable,
|
||||
"UPDATE_TIME": customtype.JsonTime(time.Now()),
|
||||
}).Error
|
||||
return bean.HostCode, err
|
||||
}
|
||||
|
||||
func (receiver *WafBlockUrlService) CheckIsExistApi(req request.WafBlockUrlAddReq) error {
|
||||
return global.GWAF_LOCAL_DB.First(&model.URLBlockList{}, "host_code = ? and url= ?", req.HostCode,
|
||||
req.Url).Error
|
||||
@@ -51,6 +69,9 @@ func (receiver *WafBlockUrlService) ModifyApi(req request.WafBlockUrlEditReq) er
|
||||
"CompareType": req.CompareType,
|
||||
"UPDATE_TIME": customtype.JsonTime(time.Now()),
|
||||
}
|
||||
if req.IsEnable != nil {
|
||||
modfiyMap["is_enable"] = *req.IsEnable
|
||||
}
|
||||
err := global.GWAF_LOCAL_DB.Model(model.URLBlockList{}).Where("id = ?", req.Id).Updates(modfiyMap).Error
|
||||
|
||||
return err
|
||||
|
||||
@@ -255,7 +255,8 @@ func (r *WafIPLookupService) hostLabel(code string, names map[string]string) str
|
||||
|
||||
func (r *WafIPLookupService) matchAllowList(ip string, names map[string]string, resp *response2.IPLookupResp) {
|
||||
var rows []model.IPAllowList
|
||||
if err := global.GWAF_LOCAL_DB.Find(&rows).Error; err != nil {
|
||||
//与引擎同口径:停用条目不参与判定,诊断结论才不会背离实际拦截行为
|
||||
if err := global.GWAF_LOCAL_DB.Where("is_enable = 1").Find(&rows).Error; err != nil {
|
||||
resp.Degraded = append(resp.Degraded, srcIPWhite)
|
||||
return
|
||||
}
|
||||
@@ -279,7 +280,7 @@ func (r *WafIPLookupService) matchAllowList(ip string, names map[string]string,
|
||||
|
||||
func (r *WafIPLookupService) matchBlockList(ip string, names map[string]string, resp *response2.IPLookupResp) {
|
||||
var rows []model.IPBlockList
|
||||
if err := global.GWAF_LOCAL_DB.Find(&rows).Error; err != nil {
|
||||
if err := global.GWAF_LOCAL_DB.Where("is_enable = 1").Find(&rows).Error; err != nil {
|
||||
resp.Degraded = append(resp.Degraded, srcIPBlack)
|
||||
return
|
||||
}
|
||||
@@ -366,7 +367,8 @@ func (r *WafIPLookupService) groupRefs() map[string]groupRef {
|
||||
refs := map[string]groupRef{}
|
||||
|
||||
var blockRows []model.IPBlockList
|
||||
global.GWAF_LOCAL_DB.Where("ip_type = ?", model.IPEntryTypeGroup).Find(&blockRows)
|
||||
//引用统计同样只算启用条目,与引擎侧组短码抽取同口径
|
||||
global.GWAF_LOCAL_DB.Where("ip_type = ? and is_enable = 1", model.IPEntryTypeGroup).Find(&blockRows)
|
||||
for _, row := range blockRows {
|
||||
if row.GroupCode == "" {
|
||||
continue
|
||||
@@ -375,7 +377,7 @@ func (r *WafIPLookupService) groupRefs() map[string]groupRef {
|
||||
}
|
||||
|
||||
var allowRows []model.IPAllowList
|
||||
global.GWAF_LOCAL_DB.Where("ip_type = ?", model.IPEntryTypeGroup).Find(&allowRows)
|
||||
global.GWAF_LOCAL_DB.Where("ip_type = ? and is_enable = 1", model.IPEntryTypeGroup).Find(&allowRows)
|
||||
for _, row := range allowRows {
|
||||
if row.GroupCode == "" {
|
||||
continue
|
||||
|
||||
@@ -2406,6 +2406,54 @@ func RunCoreDBMigrations(db *gorm.DB) error {
|
||||
return nil
|
||||
},
|
||||
},
|
||||
// 迁移: 四类名单表(IP/URL 黑白名单)新增条目级启用开关列。
|
||||
// 存量行回填 1(启用),升级前后生效行为不变
|
||||
{
|
||||
ID: "202610210001_add_list_entry_is_enable",
|
||||
Migrate: func(tx *gorm.DB) error {
|
||||
zlog.Info("迁移 202610210001: 四类名单表新增条目启用开关列")
|
||||
type listCol struct {
|
||||
model any
|
||||
field string
|
||||
col string
|
||||
}
|
||||
cols := []listCol{
|
||||
{&model.IPAllowList{}, "IsEnable", "is_enable"},
|
||||
{&model.URLAllowList{}, "IsEnable", "is_enable"},
|
||||
{&model.IPBlockList{}, "IsEnable", "is_enable"},
|
||||
{&model.URLBlockList{}, "IsEnable", "is_enable"},
|
||||
}
|
||||
for _, c := range cols {
|
||||
if tx.Migrator().HasColumn(c.model, c.col) {
|
||||
continue
|
||||
}
|
||||
if err := tx.Migrator().AddColumn(c.model, c.field); err != nil {
|
||||
return fmt.Errorf("新增名单条目启用列失败: %w", err)
|
||||
}
|
||||
}
|
||||
// 只回填 NULL:0 是「用户主动停用」的合法值,不能动
|
||||
for _, c := range cols {
|
||||
if err := tx.Model(c.model).Where("is_enable IS NULL").Update("is_enable", 1).Error; err != nil {
|
||||
return fmt.Errorf("回填名单条目启用默认值失败: %w", err)
|
||||
}
|
||||
}
|
||||
zlog.Info("迁移 202610210001: 完成")
|
||||
return nil
|
||||
},
|
||||
Rollback: func(tx *gorm.DB) error {
|
||||
zlog.Info("回滚 202610210001: 删除四类名单表的条目启用开关列")
|
||||
// 注意:删列即丢弃开关状态——用户停用过的条目回滚后回到「全部生效」,
|
||||
// 再升级也不会恢复停用标记
|
||||
for _, m := range []any{&model.IPAllowList{}, &model.URLAllowList{}, &model.IPBlockList{}, &model.URLBlockList{}} {
|
||||
if tx.Migrator().HasColumn(m, "is_enable") {
|
||||
if err := tx.Migrator().DropColumn(m, "is_enable"); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
// 执行迁移
|
||||
|
||||
@@ -120,21 +120,21 @@ func (waf *WafEngine) LoadHost(inHost model.Hosts) []innerbean.ServerRunTime {
|
||||
//加载并编译CC多规则(编译放在加载期,请求期只做取值与比较)
|
||||
ccRules := LoadCompiledCCRules(inHost.Code)
|
||||
|
||||
//查询ip白名单
|
||||
//查询ip白名单(停用条目不下发引擎,下同)
|
||||
var ipwhitelist []model.IPAllowList
|
||||
global.GWAF_LOCAL_DB.Where("host_code=? ", inHost.Code).Find(&ipwhitelist)
|
||||
global.GWAF_LOCAL_DB.Where("host_code=? and is_enable = 1", inHost.Code).Find(&ipwhitelist)
|
||||
|
||||
//查询url白名单
|
||||
var urlwhitelist []model.URLAllowList
|
||||
global.GWAF_LOCAL_DB.Where("host_code=? ", inHost.Code).Find(&urlwhitelist)
|
||||
global.GWAF_LOCAL_DB.Where("host_code=? and is_enable = 1", inHost.Code).Find(&urlwhitelist)
|
||||
|
||||
//查询ip黑名单
|
||||
var ipblocklist []model.IPBlockList
|
||||
global.GWAF_LOCAL_DB.Where("host_code=? ", inHost.Code).Find(&ipblocklist)
|
||||
global.GWAF_LOCAL_DB.Where("host_code=? and is_enable = 1", inHost.Code).Find(&ipblocklist)
|
||||
|
||||
//查询url白名单
|
||||
var urlblocklist []model.URLBlockList
|
||||
global.GWAF_LOCAL_DB.Where("host_code=? ", inHost.Code).Find(&urlblocklist)
|
||||
global.GWAF_LOCAL_DB.Where("host_code=? and is_enable = 1", inHost.Code).Find(&urlblocklist)
|
||||
|
||||
//查询url隐私保护
|
||||
var ldpurls []model.LDPUrl
|
||||
|
||||
@@ -57,7 +57,7 @@ func (p *IPAllowProcessor) GetExistingItems(items []string, task model.BatchTask
|
||||
// NotifyEngine 通知引擎更新
|
||||
func (p *IPAllowProcessor) NotifyEngine(task model.BatchTask) {
|
||||
var ipWhites []model.IPAllowList
|
||||
global.GWAF_LOCAL_DB.Where("host_code = ? ", task.BatchHostCode).Find(&ipWhites)
|
||||
global.GWAF_LOCAL_DB.Where("host_code = ? and is_enable = 1", task.BatchHostCode).Find(&ipWhites)
|
||||
var chanInfo = spec.ChanCommonHost{
|
||||
HostCode: task.BatchHostCode,
|
||||
Type: enums.ChanTypeAllowIP,
|
||||
@@ -86,6 +86,8 @@ func (p *IPAllowProcessor) processAppendBatch(items []string, existMap map[strin
|
||||
Remarks: time.Now().Format("20060102") + "批量导入 任务ID:" + task.Id,
|
||||
// 显式标记为「单条IP」:批量导入不产生 IP 组引用
|
||||
IpType: model.IPEntryTypeIP,
|
||||
// 显式启用:字段无 default 标签,零值会被如实落库为停用
|
||||
IsEnable: 1,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -137,6 +139,8 @@ func (p *IPAllowProcessor) processOverwriteBatch(items []string, existMap map[st
|
||||
Remarks: time.Now().Format("20060102") + "批量导入 任务ID:" + task.Id,
|
||||
// 显式标记为「单条IP」:批量导入不产生 IP 组引用
|
||||
IpType: model.IPEntryTypeIP,
|
||||
// 显式启用:字段无 default 标签,零值会被如实落库为停用
|
||||
IsEnable: 1,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ func (p *IPDenyProcessor) GetExistingItems(items []string, task model.BatchTask,
|
||||
// NotifyEngine 通知引擎更新
|
||||
func (p *IPDenyProcessor) NotifyEngine(task model.BatchTask) {
|
||||
var ipBlocks []model.IPBlockList
|
||||
global.GWAF_LOCAL_DB.Where("host_code = ? ", task.BatchHostCode).Find(&ipBlocks)
|
||||
global.GWAF_LOCAL_DB.Where("host_code = ? and is_enable = 1", task.BatchHostCode).Find(&ipBlocks)
|
||||
var chanInfo = spec.ChanCommonHost{
|
||||
HostCode: task.BatchHostCode,
|
||||
Type: enums.ChanTypeBlockIP,
|
||||
@@ -86,6 +86,8 @@ func (p *IPDenyProcessor) processAppendBatch(items []string, existMap map[string
|
||||
Remarks: time.Now().Format("20060102") + "批量导入 任务ID:" + task.Id,
|
||||
// 显式标记为「单条IP」:批量导入不产生 IP 组引用
|
||||
IpType: model.IPEntryTypeIP,
|
||||
// 显式启用:字段无 default 标签,零值会被如实落库为停用
|
||||
IsEnable: 1,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -137,6 +139,8 @@ func (p *IPDenyProcessor) processOverwriteBatch(items []string, existMap map[str
|
||||
Remarks: time.Now().Format("20060102") + "批量导入 任务ID:" + task.Id,
|
||||
// 显式标记为「单条IP」:批量导入不产生 IP 组引用
|
||||
IpType: model.IPEntryTypeIP,
|
||||
// 显式启用:字段无 default 标签,零值会被如实落库为停用
|
||||
IsEnable: 1,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,30 @@
|
||||
# 5. fresh_install: true 的条目只在"全新安装"时生成,不参与版本区间计算
|
||||
|
||||
notes:
|
||||
- id: v1_3_25_list_entry_switches
|
||||
version: v1.3.25
|
||||
kind: check
|
||||
level: low
|
||||
page: /waf/wafipwhitelist
|
||||
apply:
|
||||
type: navigate
|
||||
zh:
|
||||
title: IP/URL 黑白名单支持按条目启用停用
|
||||
detail: >-
|
||||
IP白名单、URL白名单、IP黑名单、URL黑名单的每条记录新增启用开关,在列表中直接切换,
|
||||
新增条目默认启用,存量条目升级后保持启用。停用的条目不再参与对应站点的防护判定
|
||||
(全局名单同理),配置仍保留在列表中,随时可重新启用;批量和编辑等原有操作不受影响。
|
||||
revert: 在对应名单页面把条目开关重新打开,即恢复该条目的防护效果。
|
||||
en:
|
||||
title: Per-entry enable switches for IP/URL black- and whitelists
|
||||
detail: >-
|
||||
Each entry in the IP whitelist, URL whitelist, IP blacklist and URL blacklist now has an
|
||||
enable switch toggled directly in the list. New entries default to enabled and existing
|
||||
entries stay enabled after the upgrade. Disabled entries stop taking effect for the
|
||||
corresponding website (global entries likewise) but remain in the list and can be
|
||||
re-enabled at any time; batch import and editing behave as before.
|
||||
revert: Turn the entry switch back on in the corresponding list page to restore its effect.
|
||||
|
||||
- id: v1_3_25_rule_ban
|
||||
version: v1.3.25
|
||||
kind: check
|
||||
|
||||
Reference in New Issue
Block a user