diff --git a/internal/web/actions/default/servers/components/waf/init.go b/internal/web/actions/default/servers/components/waf/init.go index 6848024d..0f8f7e36 100644 --- a/internal/web/actions/default/servers/components/waf/init.go +++ b/internal/web/actions/default/servers/components/waf/init.go @@ -45,11 +45,9 @@ func init() { GetPost("/ipadmin", new(ipadmin.IndexAction)). GetPost("/ipadmin/provinces", new(ipadmin.ProvincesAction)). Get("/ipadmin/lists", new(ipadmin.ListsAction)). - GetPost("/ipadmin/createIPPopup", new(ipadmin.CreateIPPopupAction)). GetPost("/ipadmin/updateIPPopup", new(ipadmin.UpdateIPPopupAction)). Post("/ipadmin/deleteIP", new(ipadmin.DeleteIPAction)). GetPost("/ipadmin/test", new(ipadmin.TestAction)). - EndAll() }) } diff --git a/internal/web/actions/default/servers/components/waf/ipadmin/createIPPopup.go b/internal/web/actions/default/servers/components/waf/ipadmin/createIPPopup.go deleted file mode 100644 index 82f7078d..00000000 --- a/internal/web/actions/default/servers/components/waf/ipadmin/createIPPopup.go +++ /dev/null @@ -1,105 +0,0 @@ -package ipadmin - -import ( - "github.com/TeaOSLab/EdgeAdmin/internal/oplogs" - "github.com/TeaOSLab/EdgeAdmin/internal/utils" - "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils" - "github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao" - "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb" - "github.com/iwind/TeaGo/actions" -) - -type CreateIPPopupAction struct { - actionutils.ParentAction -} - -func (this *CreateIPPopupAction) Init() { - this.Nav("", "", "") -} - -func (this *CreateIPPopupAction) RunGet(params struct { - FirewallPolicyId int64 - Type string -}) { - this.Data["listType"] = params.Type - - listId, err := dao.SharedHTTPFirewallPolicyDAO.FindEnabledPolicyIPListIdWithType(this.AdminContext(), params.FirewallPolicyId, params.Type) - if err != nil { - this.ErrorPage(err) - return - } - this.Data["listId"] = listId - - this.Show() -} - -func (this *CreateIPPopupAction) RunPost(params struct { - FirewallPolicyId int64 - ListId int64 - IpFrom string - IpTo string - ExpiredAt int64 - Reason string - Type string - EventLevel string - - Must *actions.Must - CSRF *actionutils.CSRF -}) { - // TODO 校验ListId所属用户 - - switch params.Type { - case "ipv4": - params.Must. - Field("ipFrom", params.IpFrom). - Require("请输入开始IP") - - // 校验IP格式(ipFrom/ipTo) - var ipFromLong uint64 - if !utils.IsIPv4(params.IpFrom) { - this.Fail("请输入正确的开始IP") - } - ipFromLong = utils.IP2Long(params.IpFrom) - - var ipToLong uint64 - if len(params.IpTo) > 0 && !utils.IsIPv4(params.IpTo) { - ipToLong = utils.IP2Long(params.IpTo) - this.Fail("请输入正确的结束IP") - } - - if ipFromLong > 0 && ipToLong > 0 && ipFromLong > ipToLong { - params.IpTo, params.IpFrom = params.IpFrom, params.IpTo - } - case "ipv6": - params.Must. - Field("ipFrom", params.IpFrom). - Require("请输入IP") - - // 校验IP格式(ipFrom) - if !utils.IsIPv6(params.IpFrom) { - this.Fail("请输入正确的IPv6地址") - } - case "all": - params.IpFrom = "0.0.0.0" - } - - createResp, err := this.RPC().IPItemRPC().CreateIPItem(this.AdminContext(), &pb.CreateIPItemRequest{ - IpListId: params.ListId, - IpFrom: params.IpFrom, - IpTo: params.IpTo, - ExpiredAt: params.ExpiredAt, - Reason: params.Reason, - Type: params.Type, - EventLevel: params.EventLevel, - }) - if err != nil { - this.ErrorPage(err) - return - } - itemId := createResp.IpItemId - - // 日志 - defer this.CreateLog(oplogs.LevelInfo, "在WAF策略 %d 名单中添加IP %d", params.FirewallPolicyId, itemId) - - this.Success() -} diff --git a/internal/web/actions/default/servers/iplists/createIPPopup.go b/internal/web/actions/default/servers/iplists/createIPPopup.go index 0f1e6479..33c4fca6 100644 --- a/internal/web/actions/default/servers/iplists/createIPPopup.go +++ b/internal/web/actions/default/servers/iplists/createIPPopup.go @@ -4,8 +4,13 @@ import ( "github.com/TeaOSLab/EdgeAdmin/internal/oplogs" "github.com/TeaOSLab/EdgeAdmin/internal/utils" "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils" + "github.com/TeaOSLab/EdgeCommon/pkg/configutils" "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb" "github.com/iwind/TeaGo/actions" + "github.com/iwind/TeaGo/maps" + "github.com/iwind/TeaGo/types" + "net" + "strings" ) type CreateIPPopupAction struct { @@ -21,13 +26,34 @@ func (this *CreateIPPopupAction) RunGet(params struct { }) { this.Data["listId"] = params.ListId + listResp, err := this.RPC().IPListRPC().FindEnabledIPList(this.AdminContext(), &pb.FindEnabledIPListRequest{ + IpListId: params.ListId, + }) + if err != nil { + this.ErrorPage(err) + return + } + var ipList = listResp.IpList + if ipList == nil { + this.NotFound("ipList", params.ListId) + return + } + this.Data["list"] = maps.Map{ + "type": ipList.Type, + } + this.Show() } func (this *CreateIPPopupAction) RunPost(params struct { - ListId int64 - IpFrom string - IpTo string + ListId int64 + Method string + + IpFrom string + IpTo string + + IpData string + ExpiredAt int64 Reason string Type string @@ -46,58 +72,207 @@ func (this *CreateIPPopupAction) RunPost(params struct { this.Fail("IP名单不存在") } + type ipData struct { + ipFrom string + ipTo string + } + + var batchIPs = []*ipData{} switch params.Type { case "ipv4": - params.Must. - Field("ipFrom", params.IpFrom). - Require("请输入开始IP") + if params.Method == "single" { + // 校验IP格式(ipFrom/ipTo) + params.Must. + Field("ipFrom", params.IpFrom). + Require("请输入开始IP") - // 校验IP格式(ipFrom/ipTo) - var ipFromLong uint64 - if !utils.IsIPv4(params.IpFrom) { - this.Fail("请输入正确的开始IP") - } - ipFromLong = utils.IP2Long(params.IpFrom) + var ipFromLong uint64 + if !utils.IsIPv4(params.IpFrom) { + this.Fail("请输入正确的开始IP") + } + ipFromLong = utils.IP2Long(params.IpFrom) - var ipToLong uint64 - if len(params.IpTo) > 0 && !utils.IsIPv4(params.IpTo) { - ipToLong = utils.IP2Long(params.IpTo) - this.Fail("请输入正确的结束IP") - } + var ipToLong uint64 + if len(params.IpTo) > 0 && !utils.IsIPv4(params.IpTo) { + ipToLong = utils.IP2Long(params.IpTo) + this.Fail("请输入正确的结束IP") + } - if ipFromLong > 0 && ipToLong > 0 && ipFromLong > ipToLong { - params.IpTo, params.IpFrom = params.IpFrom, params.IpTo + if ipFromLong > 0 && ipToLong > 0 && ipFromLong > ipToLong { + params.IpTo, params.IpFrom = params.IpFrom, params.IpTo + } + } else if params.Method == "batch" { + if len(params.IpData) == 0 { + this.FailField("ipData", "请输入IP") + } + var lines = strings.Split(params.IpData, "\n") + for index, line := range lines { + line = strings.TrimSpace(line) + if strings.Contains(line, "/") { // CIDR + if strings.Contains(line, ":") { + this.FailField("ipData", "第"+types.String(index+1)+"行IP格式错误:"+line) + } + ipFrom, ipTo, err := configutils.ParseCIDR(line) + if err != nil { + this.FailField("ipData", "第"+types.String(index+1)+"行IP格式错误:"+line) + } + batchIPs = append(batchIPs, &ipData{ + ipFrom: ipFrom, + ipTo: ipTo, + }) + } else if strings.Contains(line, "-") { // IP Range + var pieces = strings.Split(line, "-") + var ipFrom = strings.TrimSpace(pieces[0]) + var ipTo = strings.TrimSpace(pieces[1]) + + if net.ParseIP(ipFrom) == nil || net.ParseIP(ipTo) == nil || strings.Contains(ipFrom, ":") || strings.Contains(ipTo, ":") { + this.FailField("ipData", "第"+types.String(index+1)+"行IP格式错误:"+line) + } + if utils.IP2Long(ipFrom) > utils.IP2Long(ipTo) { + ipFrom, ipTo = ipTo, ipFrom + } + batchIPs = append(batchIPs, &ipData{ + ipFrom: ipFrom, + ipTo: ipTo, + }) + } else if strings.Contains(line, ",") { // IP Range + var pieces = strings.Split(line, ",") + var ipFrom = strings.TrimSpace(pieces[0]) + var ipTo = strings.TrimSpace(pieces[1]) + + if net.ParseIP(ipFrom) == nil || net.ParseIP(ipTo) == nil || strings.Contains(ipFrom, ":") || strings.Contains(ipTo, ":") { + this.FailField("ipData", "第"+types.String(index+1)+"行IP格式错误:"+line) + } + if utils.IP2Long(ipFrom) > utils.IP2Long(ipTo) { + ipFrom, ipTo = ipTo, ipFrom + } + batchIPs = append(batchIPs, &ipData{ + ipFrom: ipFrom, + ipTo: ipTo, + }) + } else if len(line) > 0 { + var ipFrom = line + if net.ParseIP(ipFrom) == nil || strings.Contains(ipFrom, ":") { + this.FailField("ipData", "第"+types.String(index+1)+"行IP格式错误:"+line) + } + batchIPs = append(batchIPs, &ipData{ + ipFrom: ipFrom, + }) + } + } } case "ipv6": - params.Must. - Field("ipFrom", params.IpFrom). - Require("请输入IP") + if params.Method == "single" { + params.Must. + Field("ipFrom", params.IpFrom). + Require("请输入IP") - // 校验IP格式(ipFrom) - if !utils.IsIPv6(params.IpFrom) { - this.Fail("请输入正确的IPv6地址") + // 校验IP格式(ipFrom) + if !utils.IsIPv6(params.IpFrom) { + this.Fail("请输入正确的IPv6地址") + } + } else if params.Method == "batch" { + if len(params.IpData) == 0 { + this.FailField("ipData", "请输入IP") + } + var lines = strings.Split(params.IpData, "\n") + for index, line := range lines { + line = strings.TrimSpace(line) + if strings.Contains(line, "/") { // CIDR + if !strings.Contains(line, ":") { + this.FailField("ipData", "第"+types.String(index+1)+"行IP格式错误:"+line) + } + ipFrom, ipTo, err := configutils.ParseCIDR(line) + if err != nil { + this.FailField("ipData", "第"+types.String(index+1)+"行IP格式错误:"+line) + } + batchIPs = append(batchIPs, &ipData{ + ipFrom: ipFrom, + ipTo: ipTo, + }) + } else if strings.Contains(line, "-") { // IP Range + var pieces = strings.Split(line, "-") + var ipFrom = strings.TrimSpace(pieces[0]) + var ipTo = strings.TrimSpace(pieces[1]) + + if net.ParseIP(ipFrom) == nil || net.ParseIP(ipTo) == nil || !strings.Contains(ipFrom, ":") || !strings.Contains(ipTo, ":") { + this.FailField("ipData", "第"+types.String(index+1)+"行IP格式错误:"+line) + } + if utils.IP2Long(ipFrom) > utils.IP2Long(ipTo) { + ipFrom, ipTo = ipTo, ipFrom + } + batchIPs = append(batchIPs, &ipData{ + ipFrom: ipFrom, + ipTo: ipTo, + }) + } else if strings.Contains(line, ",") { // IP Range + var pieces = strings.Split(line, ",") + var ipFrom = strings.TrimSpace(pieces[0]) + var ipTo = strings.TrimSpace(pieces[1]) + + if net.ParseIP(ipFrom) == nil || net.ParseIP(ipTo) == nil || !strings.Contains(ipFrom, ":") || !strings.Contains(ipTo, ":") { + this.FailField("ipData", "第"+types.String(index+1)+"行IP格式错误:"+line) + } + if utils.IP2Long(ipFrom) > utils.IP2Long(ipTo) { + ipFrom, ipTo = ipTo, ipFrom + } + batchIPs = append(batchIPs, &ipData{ + ipFrom: ipFrom, + ipTo: ipTo, + }) + } else if len(line) > 0 { + var ipFrom = line + if net.ParseIP(ipFrom) == nil || !strings.Contains(ipFrom, ":") { + this.FailField("ipData", "第"+types.String(index+1)+"行IP格式错误:"+line) + } + batchIPs = append(batchIPs, &ipData{ + ipFrom: ipFrom, + }) + } + } } case "all": params.IpFrom = "0.0.0.0" } - createResp, err := this.RPC().IPItemRPC().CreateIPItem(this.AdminContext(), &pb.CreateIPItemRequest{ - IpListId: params.ListId, - IpFrom: params.IpFrom, - IpTo: params.IpTo, - ExpiredAt: params.ExpiredAt, - Reason: params.Reason, - Type: params.Type, - EventLevel: params.EventLevel, - }) - if err != nil { - this.ErrorPage(err) - return - } - itemId := createResp.IpItemId + if len(batchIPs) > 0 { + for _, ip := range batchIPs { + _, err := this.RPC().IPItemRPC().CreateIPItem(this.AdminContext(), &pb.CreateIPItemRequest{ + IpListId: params.ListId, + IpFrom: ip.ipFrom, + IpTo: ip.ipTo, + ExpiredAt: params.ExpiredAt, + Reason: params.Reason, + Type: params.Type, + EventLevel: params.EventLevel, + }) + if err != nil { + this.ErrorPage(err) + return + } + } - // 日志 - defer this.CreateLog(oplogs.LevelInfo, "在IP名单中添加IP %d", itemId) + // 日志 + defer this.CreateLog(oplogs.LevelInfo, "在IP名单中批量添加IP %d", params.ListId) + } else { + createResp, err := this.RPC().IPItemRPC().CreateIPItem(this.AdminContext(), &pb.CreateIPItemRequest{ + IpListId: params.ListId, + IpFrom: params.IpFrom, + IpTo: params.IpTo, + ExpiredAt: params.ExpiredAt, + Reason: params.Reason, + Type: params.Type, + EventLevel: params.EventLevel, + }) + if err != nil { + this.ErrorPage(err) + return + } + itemId := createResp.IpItemId + + // 日志 + defer this.CreateLog(oplogs.LevelInfo, "在IP名单 %d 中添加IP %d", params.ListId, itemId) + } this.Success() } diff --git a/internal/web/actions/default/servers/server/settings/waf/init.go b/internal/web/actions/default/servers/server/settings/waf/init.go index 667073ce..e86a4c5e 100644 --- a/internal/web/actions/default/servers/server/settings/waf/init.go +++ b/internal/web/actions/default/servers/server/settings/waf/init.go @@ -19,7 +19,6 @@ func init() { Get("/ipadmin/denyList", new(ipadmin.DenyListAction)). GetPost("/ipadmin/countries", new(ipadmin.CountriesAction)). GetPost("/ipadmin/provinces", new(ipadmin.ProvincesAction)). - GetPost("/ipadmin/createIPPopup", new(ipadmin.CreateIPPopupAction)). GetPost("/ipadmin/updateIPPopup", new(ipadmin.UpdateIPPopupAction)). Post("/ipadmin/deleteIP", new(ipadmin.DeleteIPAction)). GetPost("/ipadmin/test", new(ipadmin.TestAction)). diff --git a/internal/web/actions/default/servers/server/settings/waf/ipadmin/createIPPopup.go b/internal/web/actions/default/servers/server/settings/waf/ipadmin/createIPPopup.go deleted file mode 100644 index 7fa25762..00000000 --- a/internal/web/actions/default/servers/server/settings/waf/ipadmin/createIPPopup.go +++ /dev/null @@ -1,95 +0,0 @@ -package ipadmin - -import ( - "github.com/TeaOSLab/EdgeAdmin/internal/oplogs" - "github.com/TeaOSLab/EdgeAdmin/internal/utils" - "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils" - "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb" - "github.com/iwind/TeaGo/actions" -) - -type CreateIPPopupAction struct { - actionutils.ParentAction -} - -func (this *CreateIPPopupAction) Init() { - this.Nav("", "", "") -} - -func (this *CreateIPPopupAction) RunGet(params struct { - ListId int64 - Type string -}) { - this.Data["listType"] = params.Type - this.Data["listId"] = params.ListId - - this.Show() -} - -func (this *CreateIPPopupAction) RunPost(params struct { - ListId int64 - IpFrom string - IpTo string - ExpiredAt int64 - Reason string - Type string - EventLevel string - - Must *actions.Must - CSRF *actionutils.CSRF -}) { - switch params.Type { - case "ipv4": - params.Must. - Field("ipFrom", params.IpFrom). - Require("请输入开始IP") - - // 校验IP格式(ipFrom/ipTo) - var ipFromLong uint64 - if !utils.IsIPv4(params.IpFrom) { - this.Fail("请输入正确的开始IP") - } - ipFromLong = utils.IP2Long(params.IpFrom) - - var ipToLong uint64 - if len(params.IpTo) > 0 && !utils.IsIPv4(params.IpTo) { - ipToLong = utils.IP2Long(params.IpTo) - this.Fail("请输入正确的结束IP") - } - - if ipFromLong > 0 && ipToLong > 0 && ipFromLong > ipToLong { - params.IpTo, params.IpFrom = params.IpFrom, params.IpTo - } - case "ipv6": - params.Must. - Field("ipFrom", params.IpFrom). - Require("请输入IP") - - // 校验IP格式(ipFrom) - if !utils.IsIPv6(params.IpFrom) { - this.Fail("请输入正确的IPv6地址") - } - case "all": - params.IpFrom = "0.0.0.0" - } - - createResp, err := this.RPC().IPItemRPC().CreateIPItem(this.AdminContext(), &pb.CreateIPItemRequest{ - IpListId: params.ListId, - IpFrom: params.IpFrom, - IpTo: params.IpTo, - ExpiredAt: params.ExpiredAt, - Reason: params.Reason, - Type: params.Type, - EventLevel: params.EventLevel, - }) - if err != nil { - this.ErrorPage(err) - return - } - itemId := createResp.IpItemId - - // 日志 - defer this.CreateLog(oplogs.LevelInfo, "在WAF策略 %d 名单中添加IP %d", params.ListId, itemId) - - this.Success() -} diff --git a/web/public/js/components/iplist/ip-list-bind-box.js b/web/public/js/components/iplist/ip-list-bind-box.js index 17f33a9f..45053adb 100644 --- a/web/public/js/components/iplist/ip-list-bind-box.js +++ b/web/public/js/components/iplist/ip-list-bind-box.js @@ -53,7 +53,7 @@ Vue.component("ip-list-bind-box", { } }, template: `
暂时还没有IP。
diff --git a/web/views/@default/servers/components/waf/ipadmin/lists.js b/web/views/@default/servers/components/waf/ipadmin/lists.js index 8713af3a..89ef4bf9 100644 --- a/web/views/@default/servers/components/waf/ipadmin/lists.js +++ b/web/views/@default/servers/components/waf/ipadmin/lists.js @@ -27,11 +27,11 @@ Tea.context(function () { */ this.createIP = function (type) { let that = this - teaweb.popup("/servers/components/waf/ipadmin/createIPPopup?firewallPolicyId=" + this.firewallPolicyId + '&type=' + type, { + teaweb.popup("/servers/iplists/createIPPopup?listId=" + this.listId + '&type=' + type, { height: "26em", callback: function () { teaweb.success("保存成功", function () { - window.location = "/servers/components/waf/ipadmin/lists?firewallPolicyId=" + that.firewallPolicyId + "&type=" + type + teaweb.reload() }) } }) diff --git a/web/views/@default/servers/components/waf/ipadmin/provinces.js b/web/views/@default/servers/components/waf/ipadmin/provinces.js index 7f3eb2fd..f2e83994 100644 --- a/web/views/@default/servers/components/waf/ipadmin/provinces.js +++ b/web/views/@default/servers/components/waf/ipadmin/provinces.js @@ -37,19 +37,4 @@ Tea.context(function () { return province.isChecked }) } - - /** - * 添加IP名单菜单 - */ - this.createIP = function (type) { - let that = this - teaweb.popup("/servers/components/waf/ipadmin/createIPPopup?firewallPolicyId=" + this.firewallPolicyId + '&type=' + type, { - height: "23em", - callback: function () { - teaweb.success("保存成功", function () { - window.location = "/servers/components/waf/ipadmin/lists?firewallPolicyId=" + that.firewallPolicyId + "&type=" + type - }) - } - }) - } }) \ No newline at end of file diff --git a/web/views/@default/servers/components/waf/ipadmin/test.js b/web/views/@default/servers/components/waf/ipadmin/test.js index 55d7900f..39932693 100644 --- a/web/views/@default/servers/components/waf/ipadmin/test.js +++ b/web/views/@default/servers/components/waf/ipadmin/test.js @@ -38,7 +38,7 @@ Tea.context(function () { */ this.createIP = function (type) { let that = this - teaweb.popup("/servers/components/waf/ipadmin/createIPPopup?firewallPolicyId=" + this.firewallPolicyId + '&type=' + type, { + teaweb.popup("/servers/iplists/createIPPopup?listId=" + this.listId + '&type=' + type, { height: "26em", callback: function () { teaweb.success("保存成功", function () { diff --git a/web/views/@default/servers/iplists/createIPPopup.html b/web/views/@default/servers/iplists/createIPPopup.html index bb9e6901..63f34f36 100644 --- a/web/views/@default/servers/iplists/createIPPopup.html +++ b/web/views/@default/servers/iplists/createIPPopup.html @@ -1,6 +1,7 @@ {$layout "layout_popup"} -