mirror of
https://github.com/TeaOSLab/EdgeAdmin.git
synced 2025-11-13 11:53:34 +08:00
IP名单新增IPv6和所有IP两种类型
This commit is contained in:
@@ -2,18 +2,42 @@ package utils
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
|
"math/big"
|
||||||
"net"
|
"net"
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// 将IP转换为整型
|
// 将IP转换为整型
|
||||||
func IP2Long(ip string) uint32 {
|
func IP2Long(ip string) uint64 {
|
||||||
s := net.ParseIP(ip)
|
s := net.ParseIP(ip)
|
||||||
if s == nil {
|
if len(s) != 16 {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(s) == 16 {
|
if strings.Contains(ip, ":") { // IPv6
|
||||||
return binary.BigEndian.Uint32(s[12:16])
|
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
|
||||||
}
|
}
|
||||||
|
|||||||
85
internal/utils/ip_utils_test.go
Normal file
85
internal/utils/ip_utils_test.go
Normal file
@@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -21,7 +21,7 @@ func (this *CreateIPPopupAction) RunGet(params struct {
|
|||||||
FirewallPolicyId int64
|
FirewallPolicyId int64
|
||||||
Type string
|
Type string
|
||||||
}) {
|
}) {
|
||||||
this.Data["type"] = params.Type
|
this.Data["listType"] = params.Type
|
||||||
|
|
||||||
listId, err := dao.SharedHTTPFirewallPolicyDAO.FindEnabledPolicyIPListIdWithType(this.AdminContext(), params.FirewallPolicyId, params.Type)
|
listId, err := dao.SharedHTTPFirewallPolicyDAO.FindEnabledPolicyIPListIdWithType(this.AdminContext(), params.FirewallPolicyId, params.Type)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -40,34 +40,47 @@ func (this *CreateIPPopupAction) RunPost(params struct {
|
|||||||
IpTo string
|
IpTo string
|
||||||
ExpiredAt int64
|
ExpiredAt int64
|
||||||
Reason string
|
Reason string
|
||||||
|
Type string
|
||||||
|
|
||||||
Must *actions.Must
|
Must *actions.Must
|
||||||
CSRF *actionutils.CSRF
|
CSRF *actionutils.CSRF
|
||||||
}) {
|
}) {
|
||||||
// TODO 校验ListId所属用户
|
// TODO 校验ListId所属用户
|
||||||
|
|
||||||
|
switch params.Type {
|
||||||
|
case "ipv4":
|
||||||
params.Must.
|
params.Must.
|
||||||
Field("ipFrom", params.IpFrom).
|
Field("ipFrom", params.IpFrom).
|
||||||
Require("请输入开始IP")
|
Require("请输入开始IP")
|
||||||
|
|
||||||
// 校验IP格式(ipFrom/ipTo)
|
// 校验IP格式(ipFrom/ipTo)
|
||||||
ipFromLong := utils.IP2Long(params.IpFrom)
|
var ipFromLong uint64
|
||||||
if len(params.IpFrom) > 0 {
|
if !utils.IsIPv4(params.IpFrom) {
|
||||||
if ipFromLong == 0 {
|
|
||||||
this.Fail("请输入正确的开始IP")
|
this.Fail("请输入正确的开始IP")
|
||||||
}
|
}
|
||||||
}
|
ipFromLong = utils.IP2Long(params.IpFrom)
|
||||||
|
|
||||||
ipToLong := utils.IP2Long(params.IpTo)
|
var ipToLong uint64
|
||||||
if len(params.IpTo) > 0 {
|
if len(params.IpTo) > 0 && !utils.IsIPv4(params.IpTo) {
|
||||||
if ipToLong == 0 {
|
ipToLong = utils.IP2Long(params.IpTo)
|
||||||
this.Fail("请输入正确的结束IP")
|
this.Fail("请输入正确的结束IP")
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if ipFromLong > 0 && ipToLong > 0 && ipFromLong > ipToLong {
|
if ipFromLong > 0 && ipToLong > 0 && ipFromLong > ipToLong {
|
||||||
params.IpTo, params.IpFrom = params.IpFrom, params.IpTo
|
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{
|
createResp, err := this.RPC().IPItemRPC().CreateIPItem(this.AdminContext(), &pb.CreateIPItemRequest{
|
||||||
IpListId: params.ListId,
|
IpListId: params.ListId,
|
||||||
@@ -75,6 +88,7 @@ func (this *CreateIPPopupAction) RunPost(params struct {
|
|||||||
IpTo: params.IpTo,
|
IpTo: params.IpTo,
|
||||||
ExpiredAt: params.ExpiredAt,
|
ExpiredAt: params.ExpiredAt,
|
||||||
Reason: params.Reason,
|
Reason: params.Reason,
|
||||||
|
Type: params.Type,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
this.ErrorPage(err)
|
this.ErrorPage(err)
|
||||||
|
|||||||
@@ -63,6 +63,7 @@ func (this *ListsAction) RunGet(params struct {
|
|||||||
"ipTo": item.IpTo,
|
"ipTo": item.IpTo,
|
||||||
"expiredTime": expiredTime,
|
"expiredTime": expiredTime,
|
||||||
"reason": item.Reason,
|
"reason": item.Reason,
|
||||||
|
"type": item.Type,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
this.Data["items"] = itemMaps
|
this.Data["items"] = itemMaps
|
||||||
|
|||||||
@@ -37,8 +37,11 @@ func (this *UpdateIPPopupAction) RunGet(params struct {
|
|||||||
"ipTo": item.IpTo,
|
"ipTo": item.IpTo,
|
||||||
"expiredAt": item.ExpiredAt,
|
"expiredAt": item.ExpiredAt,
|
||||||
"reason": item.Reason,
|
"reason": item.Reason,
|
||||||
|
"type": item.Type,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.Data["type"] = item.Type
|
||||||
|
|
||||||
this.Show()
|
this.Show()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -50,6 +53,7 @@ func (this *UpdateIPPopupAction) RunPost(params struct {
|
|||||||
IpTo string
|
IpTo string
|
||||||
ExpiredAt int64
|
ExpiredAt int64
|
||||||
Reason string
|
Reason string
|
||||||
|
Type string
|
||||||
|
|
||||||
Must *actions.Must
|
Must *actions.Must
|
||||||
CSRF *actionutils.CSRF
|
CSRF *actionutils.CSRF
|
||||||
@@ -59,28 +63,40 @@ func (this *UpdateIPPopupAction) RunPost(params struct {
|
|||||||
|
|
||||||
// TODO 校验ItemId所属用户
|
// TODO 校验ItemId所属用户
|
||||||
|
|
||||||
|
switch params.Type {
|
||||||
|
case "ipv4":
|
||||||
params.Must.
|
params.Must.
|
||||||
Field("ipFrom", params.IpFrom).
|
Field("ipFrom", params.IpFrom).
|
||||||
Require("请输入开始IP")
|
Require("请输入开始IP")
|
||||||
|
|
||||||
// 校验IP格式(ipFrom/ipTo)
|
// 校验IP格式(ipFrom/ipTo)
|
||||||
ipFromLong := utils.IP2Long(params.IpFrom)
|
var ipFromLong uint64
|
||||||
if len(params.IpFrom) > 0 {
|
if !utils.IsIPv4(params.IpFrom) {
|
||||||
if ipFromLong == 0 {
|
|
||||||
this.Fail("请输入正确的开始IP")
|
this.Fail("请输入正确的开始IP")
|
||||||
}
|
}
|
||||||
}
|
ipFromLong = utils.IP2Long(params.IpFrom)
|
||||||
|
|
||||||
ipToLong := utils.IP2Long(params.IpTo)
|
var ipToLong uint64
|
||||||
if len(params.IpTo) > 0 {
|
if len(params.IpTo) > 0 && !utils.IsIPv4(params.IpTo) {
|
||||||
if ipToLong == 0 {
|
ipToLong = utils.IP2Long(params.IpTo)
|
||||||
this.Fail("请输入正确的结束IP")
|
this.Fail("请输入正确的结束IP")
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if ipFromLong > 0 && ipToLong > 0 && ipFromLong > ipToLong {
|
if ipFromLong > 0 && ipToLong > 0 && ipFromLong > ipToLong {
|
||||||
params.IpTo, params.IpFrom = params.IpFrom, params.IpTo
|
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{
|
_, err := this.RPC().IPItemRPC().UpdateIPItem(this.AdminContext(), &pb.UpdateIPItemRequest{
|
||||||
IpItemId: params.ItemId,
|
IpItemId: params.ItemId,
|
||||||
@@ -88,6 +104,7 @@ func (this *UpdateIPPopupAction) RunPost(params struct {
|
|||||||
IpTo: params.IpTo,
|
IpTo: params.IpTo,
|
||||||
ExpiredAt: params.ExpiredAt,
|
ExpiredAt: params.ExpiredAt,
|
||||||
Reason: params.Reason,
|
Reason: params.Reason,
|
||||||
|
Type: params.Type,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
this.ErrorPage(err)
|
this.ErrorPage(err)
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ func (this *GroupsAction) Init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (this *GroupsAction) RunGet(params struct {
|
func (this *GroupsAction) RunGet(params struct {
|
||||||
|
ServerId int64
|
||||||
FirewallPolicyId int64
|
FirewallPolicyId int64
|
||||||
Type string
|
Type string
|
||||||
}) {
|
}) {
|
||||||
@@ -70,5 +71,13 @@ func (this *GroupsAction) RunGet(params struct {
|
|||||||
|
|
||||||
this.Data["groups"] = groupMaps
|
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()
|
this.Show()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
"github.com/iwind/TeaGo/maps"
|
"github.com/iwind/TeaGo/maps"
|
||||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
type AllowListAction struct {
|
type AllowListAction struct {
|
||||||
@@ -74,9 +75,19 @@ func (this *AllowListAction) RunGet(params struct {
|
|||||||
"ipTo": item.IpTo,
|
"ipTo": item.IpTo,
|
||||||
"expiredTime": expiredTime,
|
"expiredTime": expiredTime,
|
||||||
"reason": item.Reason,
|
"reason": item.Reason,
|
||||||
|
"type": item.Type,
|
||||||
|
"isExpired": item.ExpiredAt > 0 && item.ExpiredAt < time.Now().Unix(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
this.Data["items"] = itemMaps
|
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()
|
this.Show()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ func (this *CreateIPPopupAction) RunGet(params struct {
|
|||||||
ListId int64
|
ListId int64
|
||||||
Type string
|
Type string
|
||||||
}) {
|
}) {
|
||||||
this.Data["type"] = params.Type
|
this.Data["listType"] = params.Type
|
||||||
this.Data["listId"] = params.ListId
|
this.Data["listId"] = params.ListId
|
||||||
|
|
||||||
this.Show()
|
this.Show()
|
||||||
@@ -32,34 +32,47 @@ func (this *CreateIPPopupAction) RunPost(params struct {
|
|||||||
IpTo string
|
IpTo string
|
||||||
ExpiredAt int64
|
ExpiredAt int64
|
||||||
Reason string
|
Reason string
|
||||||
|
Type string
|
||||||
|
|
||||||
Must *actions.Must
|
Must *actions.Must
|
||||||
CSRF *actionutils.CSRF
|
CSRF *actionutils.CSRF
|
||||||
}) {
|
}) {
|
||||||
// TODO 校验ListId所属用户
|
// TODO 校验ListId所属用户
|
||||||
|
|
||||||
|
switch params.Type {
|
||||||
|
case "ipv4":
|
||||||
params.Must.
|
params.Must.
|
||||||
Field("ipFrom", params.IpFrom).
|
Field("ipFrom", params.IpFrom).
|
||||||
Require("请输入开始IP")
|
Require("请输入开始IP")
|
||||||
|
|
||||||
// 校验IP格式(ipFrom/ipTo)
|
// 校验IP格式(ipFrom/ipTo)
|
||||||
ipFromLong := utils.IP2Long(params.IpFrom)
|
var ipFromLong uint64
|
||||||
if len(params.IpFrom) > 0 {
|
if !utils.IsIPv4(params.IpFrom) {
|
||||||
if ipFromLong == 0 {
|
|
||||||
this.Fail("请输入正确的开始IP")
|
this.Fail("请输入正确的开始IP")
|
||||||
}
|
}
|
||||||
}
|
ipFromLong = utils.IP2Long(params.IpFrom)
|
||||||
|
|
||||||
ipToLong := utils.IP2Long(params.IpTo)
|
var ipToLong uint64
|
||||||
if len(params.IpTo) > 0 {
|
if len(params.IpTo) > 0 && !utils.IsIPv4(params.IpTo) {
|
||||||
if ipToLong == 0 {
|
ipToLong = utils.IP2Long(params.IpTo)
|
||||||
this.Fail("请输入正确的结束IP")
|
this.Fail("请输入正确的结束IP")
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if ipFromLong > 0 && ipToLong > 0 && ipFromLong > ipToLong {
|
if ipFromLong > 0 && ipToLong > 0 && ipFromLong > ipToLong {
|
||||||
params.IpTo, params.IpFrom = params.IpFrom, params.IpTo
|
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{
|
createResp, err := this.RPC().IPItemRPC().CreateIPItem(this.AdminContext(), &pb.CreateIPItemRequest{
|
||||||
IpListId: params.ListId,
|
IpListId: params.ListId,
|
||||||
@@ -67,6 +80,7 @@ func (this *CreateIPPopupAction) RunPost(params struct {
|
|||||||
IpTo: params.IpTo,
|
IpTo: params.IpTo,
|
||||||
ExpiredAt: params.ExpiredAt,
|
ExpiredAt: params.ExpiredAt,
|
||||||
Reason: params.Reason,
|
Reason: params.Reason,
|
||||||
|
Type: params.Type,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
this.ErrorPage(err)
|
this.ErrorPage(err)
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
"github.com/iwind/TeaGo/maps"
|
"github.com/iwind/TeaGo/maps"
|
||||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
type DenyListAction struct {
|
type DenyListAction struct {
|
||||||
@@ -74,9 +75,19 @@ func (this *DenyListAction) RunGet(params struct {
|
|||||||
"ipTo": item.IpTo,
|
"ipTo": item.IpTo,
|
||||||
"expiredTime": expiredTime,
|
"expiredTime": expiredTime,
|
||||||
"reason": item.Reason,
|
"reason": item.Reason,
|
||||||
|
"type": item.Type,
|
||||||
|
"isExpired": item.ExpiredAt > 0 && item.ExpiredAt < time.Now().Unix(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
this.Data["items"] = itemMaps
|
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()
|
this.Show()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,8 +37,11 @@ func (this *UpdateIPPopupAction) RunGet(params struct {
|
|||||||
"ipTo": item.IpTo,
|
"ipTo": item.IpTo,
|
||||||
"expiredAt": item.ExpiredAt,
|
"expiredAt": item.ExpiredAt,
|
||||||
"reason": item.Reason,
|
"reason": item.Reason,
|
||||||
|
"type": item.Type,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.Data["type"] = item.Type
|
||||||
|
|
||||||
this.Show()
|
this.Show()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,6 +52,7 @@ func (this *UpdateIPPopupAction) RunPost(params struct {
|
|||||||
IpTo string
|
IpTo string
|
||||||
ExpiredAt int64
|
ExpiredAt int64
|
||||||
Reason string
|
Reason string
|
||||||
|
Type string
|
||||||
|
|
||||||
Must *actions.Must
|
Must *actions.Must
|
||||||
CSRF *actionutils.CSRF
|
CSRF *actionutils.CSRF
|
||||||
@@ -58,28 +62,40 @@ func (this *UpdateIPPopupAction) RunPost(params struct {
|
|||||||
|
|
||||||
// TODO 校验ItemId所属用户
|
// TODO 校验ItemId所属用户
|
||||||
|
|
||||||
|
switch params.Type {
|
||||||
|
case "ipv4":
|
||||||
params.Must.
|
params.Must.
|
||||||
Field("ipFrom", params.IpFrom).
|
Field("ipFrom", params.IpFrom).
|
||||||
Require("请输入开始IP")
|
Require("请输入开始IP")
|
||||||
|
|
||||||
// 校验IP格式(ipFrom/ipTo)
|
// 校验IP格式(ipFrom/ipTo)
|
||||||
ipFromLong := utils.IP2Long(params.IpFrom)
|
var ipFromLong uint64
|
||||||
if len(params.IpFrom) > 0 {
|
if !utils.IsIPv4(params.IpFrom) {
|
||||||
if ipFromLong == 0 {
|
|
||||||
this.Fail("请输入正确的开始IP")
|
this.Fail("请输入正确的开始IP")
|
||||||
}
|
}
|
||||||
}
|
ipFromLong = utils.IP2Long(params.IpFrom)
|
||||||
|
|
||||||
ipToLong := utils.IP2Long(params.IpTo)
|
var ipToLong uint64
|
||||||
if len(params.IpTo) > 0 {
|
if len(params.IpTo) > 0 && !utils.IsIPv4(params.IpTo) {
|
||||||
if ipToLong == 0 {
|
ipToLong = utils.IP2Long(params.IpTo)
|
||||||
this.Fail("请输入正确的结束IP")
|
this.Fail("请输入正确的结束IP")
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if ipFromLong > 0 && ipToLong > 0 && ipFromLong > ipToLong {
|
if ipFromLong > 0 && ipToLong > 0 && ipFromLong > ipToLong {
|
||||||
params.IpTo, params.IpFrom = params.IpFrom, params.IpTo
|
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{
|
_, err := this.RPC().IPItemRPC().UpdateIPItem(this.AdminContext(), &pb.UpdateIPItemRequest{
|
||||||
IpItemId: params.ItemId,
|
IpItemId: params.ItemId,
|
||||||
@@ -87,6 +103,7 @@ func (this *UpdateIPPopupAction) RunPost(params struct {
|
|||||||
IpTo: params.IpTo,
|
IpTo: params.IpTo,
|
||||||
ExpiredAt: params.ExpiredAt,
|
ExpiredAt: params.ExpiredAt,
|
||||||
Reason: params.Reason,
|
Reason: params.Reason,
|
||||||
|
Type: params.Type,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
this.ErrorPage(err)
|
this.ErrorPage(err)
|
||||||
|
|||||||
@@ -1,5 +1,15 @@
|
|||||||
Vue.component("datetime-input", {
|
Vue.component("datetime-input", {
|
||||||
props: ["v-name", "v-timestamp"],
|
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 () {
|
data: function () {
|
||||||
let timestamp = this.vTimestamp
|
let timestamp = this.vTimestamp
|
||||||
if (timestamp != null) {
|
if (timestamp != null) {
|
||||||
@@ -122,7 +132,7 @@ Vue.component("datetime-input", {
|
|||||||
this.hasSecondError = false
|
this.hasSecondError = false
|
||||||
date.setSeconds(second)
|
date.setSeconds(second)
|
||||||
|
|
||||||
this.timestamp = Math.ceil(date.getTime() / 1000)
|
this.timestamp = parseInt(date.getTime() / 1000)
|
||||||
},
|
},
|
||||||
leadingZero: function (s, l) {
|
leadingZero: function (s, l) {
|
||||||
if (l <= s.length) {
|
if (l <= s.length) {
|
||||||
@@ -138,7 +148,7 @@ Vue.component("datetime-input", {
|
|||||||
<input type="hidden" :name="vName" :value="timestamp"/>
|
<input type="hidden" :name="vName" :value="timestamp"/>
|
||||||
<div class="ui fields inline" style="padding: 0; margin:0">
|
<div class="ui fields inline" style="padding: 0; margin:0">
|
||||||
<div class="ui field" :class="{error: hasDayError}">
|
<div class="ui field" :class="{error: hasDayError}">
|
||||||
<input type="text" v-model="day" placeholder="YYYY-MM-DD" style="width:8em" maxlength="10" @input="change"/>
|
<input type="text" v-model="day" placeholder="YYYY-MM-DD" style="width:8.6em" maxlength="10" @input="change" ref="dayInput"/>
|
||||||
</div>
|
</div>
|
||||||
<div class="ui field" :class="{error: hasHourError}"><input type="text" v-model="hour" maxlength="2" style="width:4em" placeholder="时" @input="change"/></div>
|
<div class="ui field" :class="{error: hasHourError}"><input type="text" v-model="hour" maxlength="2" style="width:4em" placeholder="时" @input="change"/></div>
|
||||||
<div class="ui field">:</div>
|
<div class="ui field">:</div>
|
||||||
|
|||||||
58
web/public/js/components/iplist/ip-list-table.js
Normal file
58
web/public/js/components/iplist/ip-list-table.js
Normal file
@@ -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: `<div>
|
||||||
|
<table class="ui table selectable celled" v-if="items.length > 0">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th style="width:18em">IP</th>
|
||||||
|
<th>类型</th>
|
||||||
|
<th>过期时间</th>
|
||||||
|
<th>备注</th>
|
||||||
|
<th class="two op">操作</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tr v-for="item in items">
|
||||||
|
<td>
|
||||||
|
<span v-if="item.type != 'all'">{{item.ipFrom}}<span v-if="item.ipTo.length > 0"> - {{item.ipTo}}</span></span>
|
||||||
|
<span v-else class="disabled">*</span>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<span v-if="item.type.length == 0">IPv4</span>
|
||||||
|
<span v-else-if="item.type == 'ipv4'">IPv4</span>
|
||||||
|
<span v-else-if="item.type == 'ipv6'">IPv6</span>
|
||||||
|
<span v-else-if="item.type == 'all'"><strong>所有IP</strong></span>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div v-if="item.expiredTime.length > 0">
|
||||||
|
{{item.expiredTime}}
|
||||||
|
<div v-if="item.isExpired" style="margin-top: 0.5em">
|
||||||
|
<span class="ui label tiny basic red">已过期</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<span v-else class="disabled">不过期</span>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<span v-if="item.reason.length > 0">{{item.reason}}</span>
|
||||||
|
<span v-else class="disabled">-</span>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<a href="" @click.prevent="updateItem(item.id)">修改</a>
|
||||||
|
<a href="" @click.prevent="deleteItem(item.id)">删除</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>`
|
||||||
|
})
|
||||||
@@ -50,7 +50,41 @@ window.teaweb = {
|
|||||||
return true;
|
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) {
|
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") {
|
if (typeof (element) == "string") {
|
||||||
element = document.getElementById(element);
|
element = document.getElementById(element);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,23 @@
|
|||||||
<csrf-token></csrf-token>
|
<csrf-token></csrf-token>
|
||||||
<table class="ui table definition selectable">
|
<table class="ui table definition selectable">
|
||||||
<tr>
|
<tr>
|
||||||
<td class="title">开始IP *</td>
|
<td class="title">类型 *</td>
|
||||||
|
<td>
|
||||||
|
<select class="ui dropdown auto-width" name="type" v-model="type">
|
||||||
|
<option value="ipv4">IPv4</option>
|
||||||
|
<option value="ipv6">IPv6</option>
|
||||||
|
<option value="all">所有IP</option>
|
||||||
|
</select>
|
||||||
|
<p class="comment" v-if="type == 'ipv4'">单个IPv4或一个IPv4范围。</p>
|
||||||
|
<p class="comment" v-if="type == 'ipv6'">单个IPv6。</p>
|
||||||
|
<p class="comment" v-if="type == 'all'">允许或禁用所有的IP。</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<!-- IPv4 -->
|
||||||
|
<tbody v-if="type == 'ipv4'">
|
||||||
|
<tr>
|
||||||
|
<td>开始IP *</td>
|
||||||
<td>
|
<td>
|
||||||
<input type="text" name="ipFrom" maxlength="64" placeholder="x.x.x.x" ref="focus"/>
|
<input type="text" name="ipFrom" maxlength="64" placeholder="x.x.x.x" ref="focus"/>
|
||||||
</td>
|
</td>
|
||||||
@@ -21,6 +37,18 @@
|
|||||||
<p class="comment">表示IP段的时候需要填写此项。</p>
|
<p class="comment">表示IP段的时候需要填写此项。</p>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
|
||||||
|
<!-- IPv6 -->
|
||||||
|
<tbody v-if="type == 'ipv6'">
|
||||||
|
<tr>
|
||||||
|
<td>IP *</td>
|
||||||
|
<td>
|
||||||
|
<input type="text" name="ipFrom" maxlength="64" placeholder="x:x:x:x:x:x:x:x" ref="focus"/>
|
||||||
|
<p class="comment">IPv6地址,比如 1406:3c00:0:2409:13:58:103:15</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="2"><more-options-indicator></more-options-indicator></td>
|
<td colspan="2"><more-options-indicator></more-options-indicator></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
Tea.context(function () {
|
||||||
|
this.type = "ipv4"
|
||||||
|
})
|
||||||
@@ -5,30 +5,6 @@
|
|||||||
|
|
||||||
<p class="comment" v-if="items.length == 0">暂时还没有IP。</p>
|
<p class="comment" v-if="items.length == 0">暂时还没有IP。</p>
|
||||||
|
|
||||||
<table class="ui table selectable celled" v-if="items.length > 0">
|
<ip-list-table v-if="items.length > 0" :v-items="items" @update-item="updateItem" @delete-item="deleteItem"></ip-list-table>
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>IP</th>
|
|
||||||
<th>过期时间</th>
|
|
||||||
<th>备注</th>
|
|
||||||
<th class="two op">操作</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tr v-for="item in items">
|
|
||||||
<td>{{item.ipFrom}}<span v-if="item.ipTo.length > 0"> - {{item.ipTo}}</span></td>
|
|
||||||
<td>
|
|
||||||
<span v-if="item.expiredTime.length > 0">{{item.expiredTime}}</span>
|
|
||||||
<span v-else class="disabled">不过期</span>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<span v-if="item.reason.length > 0">{{item.reason}}</span>
|
|
||||||
<span v-else class="disabled">-</span>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<a href="" @click.prevent="updateItem(item.id)">修改</a>
|
|
||||||
<a href="" @click.prevent="deleteItem(item.id)">删除</a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<div class="page" v-html="page"></div>
|
<div class="page" v-html="page"></div>
|
||||||
@@ -5,10 +5,27 @@
|
|||||||
<form method="post" class="ui form" data-tea-action="$" data-tea-success="success">
|
<form method="post" class="ui form" data-tea-action="$" data-tea-success="success">
|
||||||
<input type="hidden" name="firewallPolicyId" :value="firewallPolicyId"/>
|
<input type="hidden" name="firewallPolicyId" :value="firewallPolicyId"/>
|
||||||
<input type="hidden" name="itemId" :value="item.id"/>
|
<input type="hidden" name="itemId" :value="item.id"/>
|
||||||
|
<input type="hidden" name="type" :value="item.type"/>
|
||||||
<csrf-token></csrf-token>
|
<csrf-token></csrf-token>
|
||||||
<table class="ui table definition selectable">
|
<table class="ui table definition selectable">
|
||||||
<tr>
|
<tr>
|
||||||
<td class="title">开始IP *</td>
|
<td class="title">类型 *</td>
|
||||||
|
<td>
|
||||||
|
<!-- 类型不允许修改 -->
|
||||||
|
<span v-if="item.type == 'ipv4'">IPv4</span>
|
||||||
|
<span v-if="item.type == 'ipv6'">IPv6</span>
|
||||||
|
<span v-if="item.type == 'all'">所有IP</span>
|
||||||
|
|
||||||
|
<p class="comment" v-if="type == 'ipv4'">单个IPv4或一个IPv4范围。</p>
|
||||||
|
<p class="comment" v-if="type == 'ipv6'">单个IPv6。</p>
|
||||||
|
<p class="comment" v-if="type == 'all'">允许或禁用所有的IP。</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<!-- IPv4 -->
|
||||||
|
<tbody v-if="type == 'ipv4'">
|
||||||
|
<tr>
|
||||||
|
<td>开始IP *</td>
|
||||||
<td>
|
<td>
|
||||||
<input type="text" name="ipFrom" maxlength="64" placeholder="x.x.x.x" ref="focus" v-model="item.ipFrom"/>
|
<input type="text" name="ipFrom" maxlength="64" placeholder="x.x.x.x" ref="focus" v-model="item.ipFrom"/>
|
||||||
</td>
|
</td>
|
||||||
@@ -20,6 +37,18 @@
|
|||||||
<p class="comment">表示IP段的时候需要填写此项。</p>
|
<p class="comment">表示IP段的时候需要填写此项。</p>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
|
||||||
|
<!-- IPv6 -->
|
||||||
|
<tbody v-if="type == 'ipv6'">
|
||||||
|
<tr>
|
||||||
|
<td>IP *</td>
|
||||||
|
<td>
|
||||||
|
<input type="text" name="ipFrom" maxlength="64" placeholder="x:x:x:x:x:x:x:x" ref="focus" v-model="item.ipFrom"/>
|
||||||
|
<p class="comment">IPv6地址,比如 1406:3c00:0:2409:13:58:103:15</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="2"><more-options-indicator></more-options-indicator></td>
|
<td colspan="2"><more-options-indicator></more-options-indicator></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|||||||
@@ -8,6 +8,8 @@
|
|||||||
<a href="" class="item" @click.prevent="createGroup(type)">[添加分组]</a>
|
<a href="" class="item" @click.prevent="createGroup(type)">[添加分组]</a>
|
||||||
</second-menu>
|
</second-menu>
|
||||||
|
|
||||||
|
<p class="ui message warning" v-if="!wafIsOn">当前WAF未启用,设置将在<a :href="'/servers/server/settings/waf?serverId=' + serverId">[启用]</a>后生效。</p>
|
||||||
|
|
||||||
<p class="comment" v-if="groups.length == 0">暂时还没有规则分组。</p>
|
<p class="comment" v-if="groups.length == 0">暂时还没有规则分组。</p>
|
||||||
|
|
||||||
<table class="ui table selectable celled" v-if="groups.length > 0" id="sortable-table">
|
<table class="ui table selectable celled" v-if="groups.length > 0" id="sortable-table">
|
||||||
|
|||||||
@@ -13,33 +13,10 @@
|
|||||||
<span class="item">ID: {{listId}} <tip-icon content="ID可以用于使用API操作此IP名单"></tip-icon></span>
|
<span class="item">ID: {{listId}} <tip-icon content="ID可以用于使用API操作此IP名单"></tip-icon></span>
|
||||||
</second-menu>
|
</second-menu>
|
||||||
|
|
||||||
<p class="comment" v-if="items.length == 0">暂时还没有IP。</p>
|
<p class="ui message warning" v-if="!wafIsOn">当前WAF未启用,设置将在<a :href="'/servers/server/settings/waf?serverId=' + serverId">[启用]</a>后生效。</p>
|
||||||
|
|
||||||
<table class="ui table selectable celled" v-if="items.length > 0">
|
<p class="comment" v-if="items.length == 0">暂时还没有IP。</p>
|
||||||
<thead>
|
<ip-list-table v-if="items.length > 0" :v-items="items" @update-item="updateItem" @delete-item="deleteItem"></ip-list-table>
|
||||||
<tr>
|
|
||||||
<th>IP</th>
|
|
||||||
<th>过期时间</th>
|
|
||||||
<th>备注</th>
|
|
||||||
<th class="two op">操作</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tr v-for="item in items">
|
|
||||||
<td>{{item.ipFrom}}<span v-if="item.ipTo.length > 0"> - {{item.ipTo}}</span></td>
|
|
||||||
<td>
|
|
||||||
<span v-if="item.expiredTime.length > 0">{{item.expiredTime}}</span>
|
|
||||||
<span v-else class="disabled">不过期</span>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<span v-if="item.reason.length > 0">{{item.reason}}</span>
|
|
||||||
<span v-else class="disabled">-</span>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<a href="" @click.prevent="updateItem(item.id)">修改</a>
|
|
||||||
<a href="" @click.prevent="deleteItem(item.id)">删除</a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<div class="page" v-html="page"></div>
|
<div class="page" v-html="page"></div>
|
||||||
{$end}
|
{$end}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
Tea.context(function () {
|
Tea.context(function () {
|
||||||
this.updateItem = function (itemId) {
|
this.updateItem = function (itemId) {
|
||||||
teaweb.popup(Tea.url(".updateIPPopup?listId=" + this.listId, {itemId: itemId}), {
|
teaweb.popup(Tea.url(".updateIPPopup?listId=" + this.listId, {itemId: itemId}), {
|
||||||
height: "23em",
|
height: "24em",
|
||||||
callback: function () {
|
callback: function () {
|
||||||
teaweb.success("保存成功", function () {
|
teaweb.success("保存成功", function () {
|
||||||
teaweb.reload()
|
teaweb.reload()
|
||||||
@@ -27,7 +27,7 @@ Tea.context(function () {
|
|||||||
*/
|
*/
|
||||||
this.createIP = function (type) {
|
this.createIP = function (type) {
|
||||||
teaweb.popup("/servers/server/settings/waf/ipadmin/createIPPopup?listId=" + this.listId + '&type=' + type, {
|
teaweb.popup("/servers/server/settings/waf/ipadmin/createIPPopup?listId=" + this.listId + '&type=' + type, {
|
||||||
height: "23em",
|
height: "24em",
|
||||||
callback: function () {
|
callback: function () {
|
||||||
window.location.reload()
|
window.location.reload()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,30 @@
|
|||||||
{$layout "layout_popup"}
|
{$layout "layout_popup"}
|
||||||
|
|
||||||
<h3 v-if="type == 'white'">添加IP到白名单</h3>
|
<h3 v-if="listType == 'white'">添加IP到白名单</h3>
|
||||||
<h3 v-if="type == 'black'">添加IP到黑名单</h3>
|
<h3 v-if="listType == 'black'">添加IP到黑名单</h3>
|
||||||
|
|
||||||
<form method="post" class="ui form" data-tea-action="$" data-tea-success="success">
|
<form method="post" class="ui form" data-tea-action="$" data-tea-success="success">
|
||||||
<input type="hidden" name="listId" :value="listId"/>
|
<input type="hidden" name="listId" :value="listId"/>
|
||||||
<csrf-token></csrf-token>
|
<csrf-token></csrf-token>
|
||||||
<table class="ui table definition selectable">
|
<table class="ui table definition selectable">
|
||||||
<tr>
|
<tr>
|
||||||
<td class="title">开始IP *</td>
|
<td class="title">类型 *</td>
|
||||||
|
<td>
|
||||||
|
<select class="ui dropdown auto-width" name="type" v-model="type">
|
||||||
|
<option value="ipv4">IPv4</option>
|
||||||
|
<option value="ipv6">IPv6</option>
|
||||||
|
<option value="all">所有IP</option>
|
||||||
|
</select>
|
||||||
|
<p class="comment" v-if="type == 'ipv4'">单个IPv4或一个IPv4范围。</p>
|
||||||
|
<p class="comment" v-if="type == 'ipv6'">单个IPv6。</p>
|
||||||
|
<p class="comment" v-if="type == 'all'">允许或禁用所有的IP。</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<!-- IPv4 -->
|
||||||
|
<tbody v-if="type == 'ipv4'">
|
||||||
|
<tr>
|
||||||
|
<td>开始IP *</td>
|
||||||
<td>
|
<td>
|
||||||
<input type="text" name="ipFrom" maxlength="64" placeholder="x.x.x.x" ref="focus"/>
|
<input type="text" name="ipFrom" maxlength="64" placeholder="x.x.x.x" ref="focus"/>
|
||||||
</td>
|
</td>
|
||||||
@@ -20,6 +36,19 @@
|
|||||||
<p class="comment">表示IP段的时候需要填写此项。</p>
|
<p class="comment">表示IP段的时候需要填写此项。</p>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
|
||||||
|
<!-- IPv6 -->
|
||||||
|
<tbody v-if="type == 'ipv6'">
|
||||||
|
<tr>
|
||||||
|
<td>IP *</td>
|
||||||
|
<td>
|
||||||
|
<input type="text" name="ipFrom" maxlength="64" placeholder="x:x:x:x:x:x:x:x" ref="focus"/>
|
||||||
|
<p class="comment">IPv6地址,比如 1406:3c00:0:2409:13:58:103:15</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="2"><more-options-indicator></more-options-indicator></td>
|
<td colspan="2"><more-options-indicator></more-options-indicator></td>
|
||||||
</tr>
|
</tr>
|
||||||
@@ -37,6 +66,6 @@
|
|||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
<p class="comment">添加后将会在5分钟后生效。</p>
|
<p class="comment">添加后将会在5分钟内生效。</p>
|
||||||
<submit-btn></submit-btn>
|
<submit-btn></submit-btn>
|
||||||
</form>
|
</form>
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
Tea.context(function () {
|
||||||
|
this.type = "ipv4"
|
||||||
|
})
|
||||||
@@ -13,33 +13,10 @@
|
|||||||
<span class="item">ID: {{listId}} <tip-icon content="ID可以用于使用API操作此IP名单"></tip-icon></span>
|
<span class="item">ID: {{listId}} <tip-icon content="ID可以用于使用API操作此IP名单"></tip-icon></span>
|
||||||
</second-menu>
|
</second-menu>
|
||||||
|
|
||||||
<p class="comment" v-if="items.length == 0">暂时还没有IP。</p>
|
<p class="ui message warning" v-if="!wafIsOn">当前WAF未启用,设置将在<a :href="'/servers/server/settings/waf?serverId=' + serverId">[启用]</a>后生效。</p>
|
||||||
|
|
||||||
<table class="ui table selectable celled" v-if="items.length > 0">
|
<p class="comment" v-if="items.length == 0">暂时还没有IP。</p>
|
||||||
<thead>
|
<ip-list-table v-if="items.length > 0" :v-items="items" @update-item="updateItem" @delete-item="deleteItem"></ip-list-table>
|
||||||
<tr>
|
|
||||||
<th>IP</th>
|
|
||||||
<th>过期时间</th>
|
|
||||||
<th>备注</th>
|
|
||||||
<th class="two op">操作</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tr v-for="item in items">
|
|
||||||
<td>{{item.ipFrom}}<span v-if="item.ipTo.length > 0"> - {{item.ipTo}}</span></td>
|
|
||||||
<td>
|
|
||||||
<span v-if="item.expiredTime.length > 0">{{item.expiredTime}}</span>
|
|
||||||
<span v-else class="disabled">不过期</span>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<span v-if="item.reason.length > 0">{{item.reason}}</span>
|
|
||||||
<span v-else class="disabled">-</span>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<a href="" @click.prevent="updateItem(item.id)">修改</a>
|
|
||||||
<a href="" @click.prevent="deleteItem(item.id)">删除</a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<div class="page" v-html="page"></div>
|
<div class="page" v-html="page"></div>
|
||||||
{$end}
|
{$end}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
Tea.context(function () {
|
Tea.context(function () {
|
||||||
this.updateItem = function (itemId) {
|
this.updateItem = function (itemId) {
|
||||||
teaweb.popup(Tea.url(".updateIPPopup?listId=" + this.listId, {itemId: itemId}), {
|
teaweb.popup(Tea.url(".updateIPPopup?listId=" + this.listId, {itemId: itemId}), {
|
||||||
height: "23em",
|
height: "24em",
|
||||||
callback: function () {
|
callback: function () {
|
||||||
teaweb.success("保存成功", function () {
|
teaweb.success("保存成功", function () {
|
||||||
teaweb.reload()
|
teaweb.reload()
|
||||||
@@ -27,7 +27,7 @@ Tea.context(function () {
|
|||||||
*/
|
*/
|
||||||
this.createIP = function (type) {
|
this.createIP = function (type) {
|
||||||
teaweb.popup("/servers/server/settings/waf/ipadmin/createIPPopup?listId=" + this.listId + '&type=' + type, {
|
teaweb.popup("/servers/server/settings/waf/ipadmin/createIPPopup?listId=" + this.listId + '&type=' + type, {
|
||||||
height: "23em",
|
height: "24em",
|
||||||
callback: function () {
|
callback: function () {
|
||||||
window.location.reload()
|
window.location.reload()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,10 +4,27 @@
|
|||||||
|
|
||||||
<form method="post" class="ui form" data-tea-action="$" data-tea-success="success">
|
<form method="post" class="ui form" data-tea-action="$" data-tea-success="success">
|
||||||
<input type="hidden" name="itemId" :value="item.id"/>
|
<input type="hidden" name="itemId" :value="item.id"/>
|
||||||
|
<input type="hidden" name="type" :value="item.type"/>
|
||||||
<csrf-token></csrf-token>
|
<csrf-token></csrf-token>
|
||||||
<table class="ui table definition selectable">
|
<table class="ui table definition selectable">
|
||||||
<tr>
|
<tr>
|
||||||
<td class="title">开始IP *</td>
|
<td class="title">类型 *</td>
|
||||||
|
<td>
|
||||||
|
<!-- 类型不允许修改 -->
|
||||||
|
<span v-if="item.type == 'ipv4'">IPv4</span>
|
||||||
|
<span v-if="item.type == 'ipv6'">IPv6</span>
|
||||||
|
<span v-if="item.type == 'all'">所有IP</span>
|
||||||
|
|
||||||
|
<p class="comment" v-if="type == 'ipv4'">单个IPv4或一个IPv4范围。</p>
|
||||||
|
<p class="comment" v-if="type == 'ipv6'">单个IPv6。</p>
|
||||||
|
<p class="comment" v-if="type == 'all'">允许或禁用所有的IP。</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<!-- IPv4 -->
|
||||||
|
<tbody v-if="type == 'ipv4'">
|
||||||
|
<tr>
|
||||||
|
<td>开始IP *</td>
|
||||||
<td>
|
<td>
|
||||||
<input type="text" name="ipFrom" maxlength="64" placeholder="x.x.x.x" ref="focus" v-model="item.ipFrom"/>
|
<input type="text" name="ipFrom" maxlength="64" placeholder="x.x.x.x" ref="focus" v-model="item.ipFrom"/>
|
||||||
</td>
|
</td>
|
||||||
@@ -19,6 +36,19 @@
|
|||||||
<p class="comment">表示IP段的时候需要填写此项。</p>
|
<p class="comment">表示IP段的时候需要填写此项。</p>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
|
||||||
|
<!-- IPv6 -->
|
||||||
|
<tbody v-if="type == 'ipv6'">
|
||||||
|
<tr>
|
||||||
|
<td>IP *</td>
|
||||||
|
<td>
|
||||||
|
<input type="text" name="ipFrom" maxlength="64" placeholder="x:x:x:x:x:x:x:x" ref="focus" v-model="item.ipFrom"/>
|
||||||
|
<p class="comment">IPv6地址,比如 1406:3c00:0:2409:13:58:103:15</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="2"><more-options-indicator></more-options-indicator></td>
|
<td colspan="2"><more-options-indicator></more-options-indicator></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|||||||
Reference in New Issue
Block a user