From a0635a97d53af0702589aa73fe35af1e504f83bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E7=A5=A5=E8=B6=85?= Date: Tue, 2 Feb 2021 15:25:11 +0800 Subject: [PATCH] =?UTF-8?q?IP=E5=90=8D=E5=8D=95=E6=96=B0=E5=A2=9EIPv6?= =?UTF-8?q?=E5=92=8C=E6=89=80=E6=9C=89IP=E4=B8=A4=E7=A7=8D=E7=B1=BB?= =?UTF-8?q?=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/utils/ip_utils.go | 34 ++- internal/utils/ip_utils_test.go | 85 ++++++ .../components/waf/ipadmin/createIPPopup.go | 44 ++- .../servers/components/waf/ipadmin/lists.go | 1 + .../components/waf/ipadmin/updateIPPopup.go | 45 ++- .../servers/server/settings/waf/groups.go | 9 + .../server/settings/waf/ipadmin/allowList.go | 11 + .../settings/waf/ipadmin/createIPPopup.go | 44 ++- .../server/settings/waf/ipadmin/denyList.go | 11 + .../settings/waf/ipadmin/updateIPPopup.go | 45 ++- .../js/components/common/datetime-input.js | 256 +++++++++--------- .../js/components/iplist/ip-list-table.js | 58 ++++ web/public/js/utils.js | 34 +++ .../components/waf/ipadmin/createIPPopup.html | 54 +++- .../components/waf/ipadmin/createIPPopup.js | 3 + .../servers/components/waf/ipadmin/lists.html | 26 +- .../components/waf/ipadmin/updateIPPopup.html | 55 +++- .../servers/server/settings/waf/groups.html | 2 + .../settings/waf/ipadmin/allowList.html | 29 +- .../server/settings/waf/ipadmin/allowList.js | 4 +- .../settings/waf/ipadmin/createIPPopup.html | 61 +++-- .../settings/waf/ipadmin/createIPPopup.js | 3 + .../server/settings/waf/ipadmin/denyList.html | 29 +- .../server/settings/waf/ipadmin/denyList.js | 4 +- .../settings/waf/ipadmin/updateIPPopup.html | 56 +++- 25 files changed, 681 insertions(+), 322 deletions(-) create mode 100644 internal/utils/ip_utils_test.go create mode 100644 web/public/js/components/iplist/ip-list-table.js create mode 100644 web/views/@default/servers/components/waf/ipadmin/createIPPopup.js create mode 100644 web/views/@default/servers/server/settings/waf/ipadmin/createIPPopup.js diff --git a/internal/utils/ip_utils.go b/internal/utils/ip_utils.go index 58105208..ebb7fcb4 100644 --- a/internal/utils/ip_utils.go +++ b/internal/utils/ip_utils.go @@ -2,18 +2,42 @@ package utils import ( "encoding/binary" + "math/big" "net" + "regexp" + "strings" ) // 将IP转换为整型 -func IP2Long(ip string) uint32 { +func IP2Long(ip string) uint64 { s := net.ParseIP(ip) - if s == nil { + if len(s) != 16 { return 0 } - if len(s) == 16 { - return binary.BigEndian.Uint32(s[12:16]) + if strings.Contains(ip, ":") { // IPv6 + bigInt := big.NewInt(0) + bigInt.SetBytes(s.To16()) + return bigInt.Uint64() } - return binary.BigEndian.Uint32(s) + return uint64(binary.BigEndian.Uint32(s.To4())) +} + +// 判断是否为IPv4 +func IsIPv4(ip string) bool { + if !regexp.MustCompile(`^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$`).MatchString(ip) { + return false + } + if IP2Long(ip) == 0 { + return false + } + return true +} + +// 判断是否为IPv6 +func IsIPv6(ip string) bool { + if !strings.Contains(ip, ":") { + return false + } + return len(net.ParseIP(ip)) == net.IPv6len } diff --git a/internal/utils/ip_utils_test.go b/internal/utils/ip_utils_test.go new file mode 100644 index 00000000..8c891ce9 --- /dev/null +++ b/internal/utils/ip_utils_test.go @@ -0,0 +1,85 @@ +package utils + +import ( + "testing" +) + +func TestIP2Long(t *testing.T) { + for _, ip := range []string{ + "0.0.0.1", + "0.0.0.2", + "127.0.0.1", + "192.0.0.2", + "255.255.255.255", + "2001:db8:0:1::101", + "2001:db8:0:1::102", + "2406:8c00:0:3409:133:18:203:0", + "2406:8c00:0:3409:133:18:203:158", + "2406:8c00:0:3409:133:18:203:159", + "2406:8c00:0:3409:133:18:203:160", + } { + t.Log(ip, " -> ", IP2Long(ip)) + } +} + +func TestIsIPv4(t *testing.T) { + type testIP struct { + ip string + ok bool + } + for _, item := range []testIP{ + { + ip: "1", + ok: false, + }, + { + ip: "192.168.0.1", + ok: true, + }, + { + ip: "1.1.0.1", + ok: true, + }, + { + ip: "255.255.255.255", + ok: true, + }, + { + ip: "192.168.0.1233", + ok: false, + }, + } { + if IsIPv4(item.ip) != item.ok { + t.Fatal(item.ip, "should be", item.ok) + } + } +} + +func TestIsIPv6(t *testing.T) { + type testIP struct { + ip string + ok bool + } + for _, item := range []testIP{ + { + ip: "1", + ok: false, + }, + { + ip: "2406:8c00:0:3409:133:18:203:158", + ok: true, + }, + { + ip: "2406::8c00:0:3409:133:18:203:158", + ok: false, + }, + { + ip: "2001:db8:0:1::101", + ok: true, + }, + } { + if IsIPv6(item.ip) != item.ok { + t.Fatal(item.ip, "should be", item.ok) + } + } +} diff --git a/internal/web/actions/default/servers/components/waf/ipadmin/createIPPopup.go b/internal/web/actions/default/servers/components/waf/ipadmin/createIPPopup.go index fcef1be7..cd7b69de 100644 --- a/internal/web/actions/default/servers/components/waf/ipadmin/createIPPopup.go +++ b/internal/web/actions/default/servers/components/waf/ipadmin/createIPPopup.go @@ -21,7 +21,7 @@ func (this *CreateIPPopupAction) RunGet(params struct { FirewallPolicyId int64 Type string }) { - this.Data["type"] = params.Type + this.Data["listType"] = params.Type listId, err := dao.SharedHTTPFirewallPolicyDAO.FindEnabledPolicyIPListIdWithType(this.AdminContext(), params.FirewallPolicyId, params.Type) if err != nil { @@ -40,33 +40,46 @@ func (this *CreateIPPopupAction) RunPost(params struct { IpTo string ExpiredAt int64 Reason string + Type string Must *actions.Must CSRF *actionutils.CSRF }) { // TODO 校验ListId所属用户 - params.Must. - Field("ipFrom", params.IpFrom). - Require("请输入开始IP") + switch params.Type { + case "ipv4": + params.Must. + Field("ipFrom", params.IpFrom). + Require("请输入开始IP") - // 校验IP格式(ipFrom/ipTo) - ipFromLong := utils.IP2Long(params.IpFrom) - if len(params.IpFrom) > 0 { - if ipFromLong == 0 { + // 校验IP格式(ipFrom/ipTo) + var ipFromLong uint64 + if !utils.IsIPv4(params.IpFrom) { this.Fail("请输入正确的开始IP") } - } + ipFromLong = utils.IP2Long(params.IpFrom) - ipToLong := utils.IP2Long(params.IpTo) - if len(params.IpTo) > 0 { - if ipToLong == 0 { + 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 + } + 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{ @@ -75,6 +88,7 @@ func (this *CreateIPPopupAction) RunPost(params struct { IpTo: params.IpTo, ExpiredAt: params.ExpiredAt, Reason: params.Reason, + Type: params.Type, }) if err != nil { this.ErrorPage(err) diff --git a/internal/web/actions/default/servers/components/waf/ipadmin/lists.go b/internal/web/actions/default/servers/components/waf/ipadmin/lists.go index 3d7d5bd6..65121840 100644 --- a/internal/web/actions/default/servers/components/waf/ipadmin/lists.go +++ b/internal/web/actions/default/servers/components/waf/ipadmin/lists.go @@ -63,6 +63,7 @@ func (this *ListsAction) RunGet(params struct { "ipTo": item.IpTo, "expiredTime": expiredTime, "reason": item.Reason, + "type": item.Type, }) } this.Data["items"] = itemMaps diff --git a/internal/web/actions/default/servers/components/waf/ipadmin/updateIPPopup.go b/internal/web/actions/default/servers/components/waf/ipadmin/updateIPPopup.go index 525d4b62..243eaf6c 100644 --- a/internal/web/actions/default/servers/components/waf/ipadmin/updateIPPopup.go +++ b/internal/web/actions/default/servers/components/waf/ipadmin/updateIPPopup.go @@ -37,8 +37,11 @@ func (this *UpdateIPPopupAction) RunGet(params struct { "ipTo": item.IpTo, "expiredAt": item.ExpiredAt, "reason": item.Reason, + "type": item.Type, } + this.Data["type"] = item.Type + this.Show() } @@ -50,6 +53,7 @@ func (this *UpdateIPPopupAction) RunPost(params struct { IpTo string ExpiredAt int64 Reason string + Type string Must *actions.Must CSRF *actionutils.CSRF @@ -59,27 +63,39 @@ func (this *UpdateIPPopupAction) RunPost(params struct { // TODO 校验ItemId所属用户 - params.Must. - Field("ipFrom", params.IpFrom). - Require("请输入开始IP") + switch params.Type { + case "ipv4": + params.Must. + Field("ipFrom", params.IpFrom). + Require("请输入开始IP") - // 校验IP格式(ipFrom/ipTo) - ipFromLong := utils.IP2Long(params.IpFrom) - if len(params.IpFrom) > 0 { - if ipFromLong == 0 { + // 校验IP格式(ipFrom/ipTo) + var ipFromLong uint64 + if !utils.IsIPv4(params.IpFrom) { this.Fail("请输入正确的开始IP") } - } + ipFromLong = utils.IP2Long(params.IpFrom) - ipToLong := utils.IP2Long(params.IpTo) - if len(params.IpTo) > 0 { - if ipToLong == 0 { + 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 + } + 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" } _, err := this.RPC().IPItemRPC().UpdateIPItem(this.AdminContext(), &pb.UpdateIPItemRequest{ @@ -88,6 +104,7 @@ func (this *UpdateIPPopupAction) RunPost(params struct { IpTo: params.IpTo, ExpiredAt: params.ExpiredAt, Reason: params.Reason, + Type: params.Type, }) if err != nil { this.ErrorPage(err) diff --git a/internal/web/actions/default/servers/server/settings/waf/groups.go b/internal/web/actions/default/servers/server/settings/waf/groups.go index f6c21d92..565ad5cf 100644 --- a/internal/web/actions/default/servers/server/settings/waf/groups.go +++ b/internal/web/actions/default/servers/server/settings/waf/groups.go @@ -16,6 +16,7 @@ func (this *GroupsAction) Init() { } func (this *GroupsAction) RunGet(params struct { + ServerId int64 FirewallPolicyId int64 Type string }) { @@ -70,5 +71,13 @@ func (this *GroupsAction) RunGet(params struct { this.Data["groups"] = groupMaps + // WAF是否启用 + webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithServerId(this.AdminContext(), params.ServerId) + if err != nil { + this.ErrorPage(err) + return + } + this.Data["wafIsOn"] = webConfig.FirewallRef != nil && webConfig.FirewallRef.IsOn + this.Show() } diff --git a/internal/web/actions/default/servers/server/settings/waf/ipadmin/allowList.go b/internal/web/actions/default/servers/server/settings/waf/ipadmin/allowList.go index f52c227d..215b24b3 100644 --- a/internal/web/actions/default/servers/server/settings/waf/ipadmin/allowList.go +++ b/internal/web/actions/default/servers/server/settings/waf/ipadmin/allowList.go @@ -6,6 +6,7 @@ import ( "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb" "github.com/iwind/TeaGo/maps" timeutil "github.com/iwind/TeaGo/utils/time" + "time" ) type AllowListAction struct { @@ -74,9 +75,19 @@ func (this *AllowListAction) RunGet(params struct { "ipTo": item.IpTo, "expiredTime": expiredTime, "reason": item.Reason, + "type": item.Type, + "isExpired": item.ExpiredAt > 0 && item.ExpiredAt < time.Now().Unix(), }) } this.Data["items"] = itemMaps + // WAF是否启用 + webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithServerId(this.AdminContext(), params.ServerId) + if err != nil { + this.ErrorPage(err) + return + } + this.Data["wafIsOn"] = webConfig.FirewallRef != nil && webConfig.FirewallRef.IsOn + this.Show() } 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 index 985bb4cc..9b8f1206 100644 --- a/internal/web/actions/default/servers/server/settings/waf/ipadmin/createIPPopup.go +++ b/internal/web/actions/default/servers/server/settings/waf/ipadmin/createIPPopup.go @@ -20,7 +20,7 @@ func (this *CreateIPPopupAction) RunGet(params struct { ListId int64 Type string }) { - this.Data["type"] = params.Type + this.Data["listType"] = params.Type this.Data["listId"] = params.ListId this.Show() @@ -32,33 +32,46 @@ func (this *CreateIPPopupAction) RunPost(params struct { IpTo string ExpiredAt int64 Reason string + Type string Must *actions.Must CSRF *actionutils.CSRF }) { // TODO 校验ListId所属用户 - params.Must. - Field("ipFrom", params.IpFrom). - Require("请输入开始IP") + switch params.Type { + case "ipv4": + params.Must. + Field("ipFrom", params.IpFrom). + Require("请输入开始IP") - // 校验IP格式(ipFrom/ipTo) - ipFromLong := utils.IP2Long(params.IpFrom) - if len(params.IpFrom) > 0 { - if ipFromLong == 0 { + // 校验IP格式(ipFrom/ipTo) + var ipFromLong uint64 + if !utils.IsIPv4(params.IpFrom) { this.Fail("请输入正确的开始IP") } - } + ipFromLong = utils.IP2Long(params.IpFrom) - ipToLong := utils.IP2Long(params.IpTo) - if len(params.IpTo) > 0 { - if ipToLong == 0 { + 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 + } + 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{ @@ -67,6 +80,7 @@ func (this *CreateIPPopupAction) RunPost(params struct { IpTo: params.IpTo, ExpiredAt: params.ExpiredAt, Reason: params.Reason, + Type: params.Type, }) if err != nil { this.ErrorPage(err) diff --git a/internal/web/actions/default/servers/server/settings/waf/ipadmin/denyList.go b/internal/web/actions/default/servers/server/settings/waf/ipadmin/denyList.go index e22f9a07..f4701f63 100644 --- a/internal/web/actions/default/servers/server/settings/waf/ipadmin/denyList.go +++ b/internal/web/actions/default/servers/server/settings/waf/ipadmin/denyList.go @@ -6,6 +6,7 @@ import ( "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb" "github.com/iwind/TeaGo/maps" timeutil "github.com/iwind/TeaGo/utils/time" + "time" ) type DenyListAction struct { @@ -74,9 +75,19 @@ func (this *DenyListAction) RunGet(params struct { "ipTo": item.IpTo, "expiredTime": expiredTime, "reason": item.Reason, + "type": item.Type, + "isExpired": item.ExpiredAt > 0 && item.ExpiredAt < time.Now().Unix(), }) } this.Data["items"] = itemMaps + // WAF是否启用 + webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithServerId(this.AdminContext(), params.ServerId) + if err != nil { + this.ErrorPage(err) + return + } + this.Data["wafIsOn"] = webConfig.FirewallRef != nil && webConfig.FirewallRef.IsOn + this.Show() } diff --git a/internal/web/actions/default/servers/server/settings/waf/ipadmin/updateIPPopup.go b/internal/web/actions/default/servers/server/settings/waf/ipadmin/updateIPPopup.go index f25d3d9c..7b85cd6e 100644 --- a/internal/web/actions/default/servers/server/settings/waf/ipadmin/updateIPPopup.go +++ b/internal/web/actions/default/servers/server/settings/waf/ipadmin/updateIPPopup.go @@ -37,8 +37,11 @@ func (this *UpdateIPPopupAction) RunGet(params struct { "ipTo": item.IpTo, "expiredAt": item.ExpiredAt, "reason": item.Reason, + "type": item.Type, } + this.Data["type"] = item.Type + this.Show() } @@ -49,6 +52,7 @@ func (this *UpdateIPPopupAction) RunPost(params struct { IpTo string ExpiredAt int64 Reason string + Type string Must *actions.Must CSRF *actionutils.CSRF @@ -58,27 +62,39 @@ func (this *UpdateIPPopupAction) RunPost(params struct { // TODO 校验ItemId所属用户 - params.Must. - Field("ipFrom", params.IpFrom). - Require("请输入开始IP") + switch params.Type { + case "ipv4": + params.Must. + Field("ipFrom", params.IpFrom). + Require("请输入开始IP") - // 校验IP格式(ipFrom/ipTo) - ipFromLong := utils.IP2Long(params.IpFrom) - if len(params.IpFrom) > 0 { - if ipFromLong == 0 { + // 校验IP格式(ipFrom/ipTo) + var ipFromLong uint64 + if !utils.IsIPv4(params.IpFrom) { this.Fail("请输入正确的开始IP") } - } + ipFromLong = utils.IP2Long(params.IpFrom) - ipToLong := utils.IP2Long(params.IpTo) - if len(params.IpTo) > 0 { - if ipToLong == 0 { + 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 + } + 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" } _, err := this.RPC().IPItemRPC().UpdateIPItem(this.AdminContext(), &pb.UpdateIPItemRequest{ @@ -87,6 +103,7 @@ func (this *UpdateIPPopupAction) RunPost(params struct { IpTo: params.IpTo, ExpiredAt: params.ExpiredAt, Reason: params.Reason, + Type: params.Type, }) if err != nil { this.ErrorPage(err) diff --git a/web/public/js/components/common/datetime-input.js b/web/public/js/components/common/datetime-input.js index 6cfb63fb..cf565236 100644 --- a/web/public/js/components/common/datetime-input.js +++ b/web/public/js/components/common/datetime-input.js @@ -1,144 +1,154 @@ Vue.component("datetime-input", { - props: ["v-name", "v-timestamp"], - data: function () { - let timestamp = this.vTimestamp - if (timestamp != null) { - timestamp = parseInt(timestamp) - if (isNaN(timestamp)) { - timestamp = 0 - } - } else { - timestamp = 0 - } + props: ["v-name", "v-timestamp"], + mounted: function () { + let that = this + teaweb.datepicker(this.$refs.dayInput, function (v) { + that.day = v + that.hour = "23" + that.minute = "59" + that.second = "59" + that.change() + }) + }, + data: function () { + let timestamp = this.vTimestamp + if (timestamp != null) { + timestamp = parseInt(timestamp) + if (isNaN(timestamp)) { + timestamp = 0 + } + } else { + timestamp = 0 + } - let day = "" - let hour = "" - let minute = "" - let second = "" + let day = "" + let hour = "" + let minute = "" + let second = "" - if (timestamp > 0) { - let date = new Date() - date.setTime(timestamp * 1000) + if (timestamp > 0) { + let date = new Date() + date.setTime(timestamp * 1000) - let year = date.getFullYear().toString() - let month = this.leadingZero((date.getMonth() + 1).toString(), 2) - day = year + "-" + month + "-" + this.leadingZero(date.getDate().toString(), 2) + let year = date.getFullYear().toString() + let month = this.leadingZero((date.getMonth() + 1).toString(), 2) + day = year + "-" + month + "-" + this.leadingZero(date.getDate().toString(), 2) - hour = this.leadingZero(date.getHours().toString(), 2) - minute = this.leadingZero(date.getMinutes().toString(), 2) - second = this.leadingZero(date.getSeconds().toString(), 2) - } + hour = this.leadingZero(date.getHours().toString(), 2) + minute = this.leadingZero(date.getMinutes().toString(), 2) + second = this.leadingZero(date.getSeconds().toString(), 2) + } - return { - timestamp: timestamp, - day: day, - hour: hour, - minute: minute, - second: second, + return { + timestamp: timestamp, + day: day, + hour: hour, + minute: minute, + second: second, - hasDayError: false, - hasHourError: false, - hasMinuteError: false, - hasSecondError: false - } - }, - methods: { - change: function () { - let date = new Date() + hasDayError: false, + hasHourError: false, + hasMinuteError: false, + hasSecondError: false + } + }, + methods: { + change: function () { + let date = new Date() - // day - if (!/^\d{4}-\d{1,2}-\d{1,2}$/.test(this.day)) { - this.hasDayError = true - return - } - let pieces = this.day.split("-") - let year = parseInt(pieces[0]) - date.setFullYear(year) + // day + if (!/^\d{4}-\d{1,2}-\d{1,2}$/.test(this.day)) { + this.hasDayError = true + return + } + let pieces = this.day.split("-") + let year = parseInt(pieces[0]) + date.setFullYear(year) - let month = parseInt(pieces[1]) - if (month < 1 || month > 12) { - this.hasDayError = true - return - } - date.setMonth(month - 1) + let month = parseInt(pieces[1]) + if (month < 1 || month > 12) { + this.hasDayError = true + return + } + date.setMonth(month - 1) - let day = parseInt(pieces[2]) - if (day < 1 || day > 32) { - this.hasDayError = true - return - } - date.setDate(day) + let day = parseInt(pieces[2]) + if (day < 1 || day > 32) { + this.hasDayError = true + return + } + date.setDate(day) - this.hasDayError = false + this.hasDayError = false - // hour - if (!/^\d+$/.test(this.hour)) { - this.hasHourError = true - return - } - let hour = parseInt(this.hour) - if (isNaN(hour)) { - this.hasHourError = true - return - } - if (hour < 0 || hour >= 24) { - this.hasHourError = true - return - } - this.hasHourError = false - date.setHours(hour) + // hour + if (!/^\d+$/.test(this.hour)) { + this.hasHourError = true + return + } + let hour = parseInt(this.hour) + if (isNaN(hour)) { + this.hasHourError = true + return + } + if (hour < 0 || hour >= 24) { + this.hasHourError = true + return + } + this.hasHourError = false + date.setHours(hour) - // minute - if (!/^\d+$/.test(this.minute)) { - this.hasMinuteError = true - return - } - let minute = parseInt(this.minute) - if (isNaN(minute)) { - this.hasMinuteError = true - return - } - if (minute < 0 || minute >= 60) { - this.hasMinuteError = true - return - } - this.hasMinuteError = false - date.setMinutes(minute) + // minute + if (!/^\d+$/.test(this.minute)) { + this.hasMinuteError = true + return + } + let minute = parseInt(this.minute) + if (isNaN(minute)) { + this.hasMinuteError = true + return + } + if (minute < 0 || minute >= 60) { + this.hasMinuteError = true + return + } + this.hasMinuteError = false + date.setMinutes(minute) - // second - if (!/^\d+$/.test(this.second)) { - this.hasSecondError = true - return - } - let second = parseInt(this.second) - if (isNaN(second)) { - this.hasSecondError = true - return - } - if (second < 0 || second >= 60) { - this.hasSecondError = true - return - } - this.hasSecondError = false - date.setSeconds(second) + // second + if (!/^\d+$/.test(this.second)) { + this.hasSecondError = true + return + } + let second = parseInt(this.second) + if (isNaN(second)) { + this.hasSecondError = true + return + } + if (second < 0 || second >= 60) { + this.hasSecondError = true + return + } + this.hasSecondError = false + date.setSeconds(second) - this.timestamp = Math.ceil(date.getTime() / 1000) - }, - leadingZero: function (s, l) { - if (l <= s.length) { - return s - } - for (let i = 0; i < l - s.length; i++) { - s = "0" + s - } - return s - } - }, - template: `
+ this.timestamp = parseInt(date.getTime() / 1000) + }, + leadingZero: function (s, l) { + if (l <= s.length) { + return s + } + for (let i = 0; i < l - s.length; i++) { + s = "0" + s + } + return s + } + }, + template: `
- +
:
diff --git a/web/public/js/components/iplist/ip-list-table.js b/web/public/js/components/iplist/ip-list-table.js new file mode 100644 index 00000000..9de6e538 --- /dev/null +++ b/web/public/js/components/iplist/ip-list-table.js @@ -0,0 +1,58 @@ +Vue.component("ip-list-table", { + props: ["v-items"], + data: function () { + return { + items: this.vItems + } + }, + methods: { + updateItem: function (itemId) { + this.$emit("update-item", itemId) + }, + deleteItem: function (itemId) { + this.$emit("delete-item", itemId) + } + }, + template: `
+ + + + + + + + + + + + + + + + + +
IP类型过期时间备注操作
+ {{item.ipFrom}} - {{item.ipTo}} + * + + IPv4 + IPv4 + IPv6 + 所有IP + +
+ {{item.expiredTime}} +
+ 已过期 +
+
+ 不过期 +
+ {{item.reason}} + - + + 修改   + 删除 +
+
` +}) \ No newline at end of file diff --git a/web/public/js/utils.js b/web/public/js/utils.js index b9497e64..53b37910 100644 --- a/web/public/js/utils.js +++ b/web/public/js/utils.js @@ -50,7 +50,41 @@ window.teaweb = { return true; }, + loadJS: function (file, callback) { + let element = document.createElement("script") + element.setAttribute("type", "text/javascript") + element.setAttribute("src", file) + if (typeof callback == "function") { + element.addEventListener("load", callback) + } + document.head.append(element) + }, + loadCSS: function (file, callback) { + let element = document.createElement("link") + element.setAttribute("rel", "stylesheet") + element.setAttribute("type", "text/css") + element.setAttribute("href", file) + if (typeof callback == "function") { + element.addEventListener("load", callback) + } + document.head.append(element) + }, datepicker: function (element, callback) { + // 加载 + if (typeof Pikaday == "undefined") { + let that = this + this.loadJS("/js/moment.min.js") + this.loadJS("/js/pikaday.js", function () { + that.datepicker(element, callback) + }) + this.loadCSS("/js/pikaday.css") + this.loadCSS("/js/pikaday.theme.css") + this.loadCSS("/js/pikaday.triangle.css") + + return + } + + if (typeof (element) == "string") { element = document.getElementById(element); } diff --git a/web/views/@default/servers/components/waf/ipadmin/createIPPopup.html b/web/views/@default/servers/components/waf/ipadmin/createIPPopup.html index 821699bb..cc058a3a 100644 --- a/web/views/@default/servers/components/waf/ipadmin/createIPPopup.html +++ b/web/views/@default/servers/components/waf/ipadmin/createIPPopup.html @@ -8,19 +8,47 @@ - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/web/views/@default/servers/components/waf/ipadmin/createIPPopup.js b/web/views/@default/servers/components/waf/ipadmin/createIPPopup.js new file mode 100644 index 00000000..82ad185a --- /dev/null +++ b/web/views/@default/servers/components/waf/ipadmin/createIPPopup.js @@ -0,0 +1,3 @@ +Tea.context(function () { + this.type = "ipv4" +}) \ No newline at end of file diff --git a/web/views/@default/servers/components/waf/ipadmin/lists.html b/web/views/@default/servers/components/waf/ipadmin/lists.html index 5ffbcfbb..9feb9f11 100644 --- a/web/views/@default/servers/components/waf/ipadmin/lists.html +++ b/web/views/@default/servers/components/waf/ipadmin/lists.html @@ -5,30 +5,6 @@

暂时还没有IP。

-
开始IP * - -
结束IP - -

表示IP段的时候需要填写此项。

-
类型 * + +

单个IPv4或一个IPv4范围。

+

单个IPv6。

+

允许或禁用所有的IP。

+
开始IP * + +
结束IP + +

表示IP段的时候需要填写此项。

+
IP * + +

IPv6地址,比如 1406:3c00:0:2409:13:58:103:15

+
- - - - - - - - - - - - - - -
IP过期时间备注操作
{{item.ipFrom}} - {{item.ipTo}} - {{item.expiredTime}} - 不过期 - - {{item.reason}} - - - - 修改   - 删除 -
+
\ No newline at end of file diff --git a/web/views/@default/servers/components/waf/ipadmin/updateIPPopup.html b/web/views/@default/servers/components/waf/ipadmin/updateIPPopup.html index df4f4635..5c6365c1 100644 --- a/web/views/@default/servers/components/waf/ipadmin/updateIPPopup.html +++ b/web/views/@default/servers/components/waf/ipadmin/updateIPPopup.html @@ -5,21 +5,50 @@
+ - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/web/views/@default/servers/server/settings/waf/groups.html b/web/views/@default/servers/server/settings/waf/groups.html index dbb99e3f..bc2a4d33 100644 --- a/web/views/@default/servers/server/settings/waf/groups.html +++ b/web/views/@default/servers/server/settings/waf/groups.html @@ -8,6 +8,8 @@ [添加分组] +

当前WAF未启用,设置将在[启用]后生效。

+

暂时还没有规则分组。

开始IP * - -
结束IP - -

表示IP段的时候需要填写此项。

-
类型 * + + IPv4 + IPv6 + 所有IP + +

单个IPv4或一个IPv4范围。

+

单个IPv6。

+

允许或禁用所有的IP。

+
开始IP * + +
结束IP + +

表示IP段的时候需要填写此项。

+
IP * + +

IPv6地址,比如 1406:3c00:0:2409:13:58:103:15

+
diff --git a/web/views/@default/servers/server/settings/waf/ipadmin/allowList.html b/web/views/@default/servers/server/settings/waf/ipadmin/allowList.html index a20eb855..227567bf 100644 --- a/web/views/@default/servers/server/settings/waf/ipadmin/allowList.html +++ b/web/views/@default/servers/server/settings/waf/ipadmin/allowList.html @@ -13,33 +13,10 @@ ID: {{listId}}   -

暂时还没有IP。

+

当前WAF未启用,设置将在[启用]后生效。

-
- - - - - - - - - - - - - - -
IP过期时间备注操作
{{item.ipFrom}} - {{item.ipTo}} - {{item.expiredTime}} - 不过期 - - {{item.reason}} - - - - 修改   - 删除 -
+

暂时还没有IP。

+
{$end} diff --git a/web/views/@default/servers/server/settings/waf/ipadmin/allowList.js b/web/views/@default/servers/server/settings/waf/ipadmin/allowList.js index c7079229..b62759c4 100644 --- a/web/views/@default/servers/server/settings/waf/ipadmin/allowList.js +++ b/web/views/@default/servers/server/settings/waf/ipadmin/allowList.js @@ -1,7 +1,7 @@ Tea.context(function () { this.updateItem = function (itemId) { teaweb.popup(Tea.url(".updateIPPopup?listId=" + this.listId, {itemId: itemId}), { - height: "23em", + height: "24em", callback: function () { teaweb.success("保存成功", function () { teaweb.reload() @@ -27,7 +27,7 @@ Tea.context(function () { */ this.createIP = function (type) { teaweb.popup("/servers/server/settings/waf/ipadmin/createIPPopup?listId=" + this.listId + '&type=' + type, { - height: "23em", + height: "24em", callback: function () { window.location.reload() } diff --git a/web/views/@default/servers/server/settings/waf/ipadmin/createIPPopup.html b/web/views/@default/servers/server/settings/waf/ipadmin/createIPPopup.html index 7d990d77..dec646b4 100644 --- a/web/views/@default/servers/server/settings/waf/ipadmin/createIPPopup.html +++ b/web/views/@default/servers/server/settings/waf/ipadmin/createIPPopup.html @@ -1,25 +1,54 @@ {$layout "layout_popup"} -

添加IP到白名单

-

添加IP到黑名单

+

添加IP到白名单

+

添加IP到黑名单

- - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + @@ -37,6 +66,6 @@
开始IP * - -
结束IP - -

表示IP段的时候需要填写此项。

-
类型 * + +

单个IPv4或一个IPv4范围。

+

单个IPv6。

+

允许或禁用所有的IP。

+
开始IP * + +
结束IP + +

表示IP段的时候需要填写此项。

+
IP * + +

IPv6地址,比如 1406:3c00:0:2409:13:58:103:15

+
-

添加后将会在5分钟后生效。

+

添加后将会在5分钟内生效。

\ No newline at end of file diff --git a/web/views/@default/servers/server/settings/waf/ipadmin/createIPPopup.js b/web/views/@default/servers/server/settings/waf/ipadmin/createIPPopup.js new file mode 100644 index 00000000..82ad185a --- /dev/null +++ b/web/views/@default/servers/server/settings/waf/ipadmin/createIPPopup.js @@ -0,0 +1,3 @@ +Tea.context(function () { + this.type = "ipv4" +}) \ No newline at end of file diff --git a/web/views/@default/servers/server/settings/waf/ipadmin/denyList.html b/web/views/@default/servers/server/settings/waf/ipadmin/denyList.html index 173acc31..64748c35 100644 --- a/web/views/@default/servers/server/settings/waf/ipadmin/denyList.html +++ b/web/views/@default/servers/server/settings/waf/ipadmin/denyList.html @@ -13,33 +13,10 @@ ID: {{listId}}   -

暂时还没有IP。

+

当前WAF未启用,设置将在[启用]后生效。

- - - - - - - - - - - - - - - -
IP过期时间备注操作
{{item.ipFrom}} - {{item.ipTo}} - {{item.expiredTime}} - 不过期 - - {{item.reason}} - - - - 修改   - 删除 -
+

暂时还没有IP。

+
{$end} diff --git a/web/views/@default/servers/server/settings/waf/ipadmin/denyList.js b/web/views/@default/servers/server/settings/waf/ipadmin/denyList.js index c7079229..b62759c4 100644 --- a/web/views/@default/servers/server/settings/waf/ipadmin/denyList.js +++ b/web/views/@default/servers/server/settings/waf/ipadmin/denyList.js @@ -1,7 +1,7 @@ Tea.context(function () { this.updateItem = function (itemId) { teaweb.popup(Tea.url(".updateIPPopup?listId=" + this.listId, {itemId: itemId}), { - height: "23em", + height: "24em", callback: function () { teaweb.success("保存成功", function () { teaweb.reload() @@ -27,7 +27,7 @@ Tea.context(function () { */ this.createIP = function (type) { teaweb.popup("/servers/server/settings/waf/ipadmin/createIPPopup?listId=" + this.listId + '&type=' + type, { - height: "23em", + height: "24em", callback: function () { window.location.reload() } diff --git a/web/views/@default/servers/server/settings/waf/ipadmin/updateIPPopup.html b/web/views/@default/servers/server/settings/waf/ipadmin/updateIPPopup.html index aff914f0..740d9ef0 100644 --- a/web/views/@default/servers/server/settings/waf/ipadmin/updateIPPopup.html +++ b/web/views/@default/servers/server/settings/waf/ipadmin/updateIPPopup.html @@ -4,21 +4,51 @@
+ - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + +
开始IP * - -
结束IP - -

表示IP段的时候需要填写此项。

-
类型 * + + IPv4 + IPv6 + 所有IP + +

单个IPv4或一个IPv4范围。

+

单个IPv6。

+

允许或禁用所有的IP。

+
开始IP * + +
结束IP + +

表示IP段的时候需要填写此项。

+
IP * + +

IPv6地址,比如 1406:3c00:0:2409:13:58:103:15

+