mirror of
				https://github.com/TeaOSLab/EdgeAdmin.git
				synced 2025-11-04 13:10:26 +08:00 
			
		
		
		
	实现公用的IP名单
This commit is contained in:
		
							
								
								
									
										1
									
								
								build/configs/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								build/configs/.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -2,3 +2,4 @@ api.yaml
 | 
			
		||||
server.yaml
 | 
			
		||||
api_db.yaml
 | 
			
		||||
*.pem
 | 
			
		||||
tip.json
 | 
			
		||||
							
								
								
									
										2
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								go.mod
									
									
									
									
									
								
							@@ -9,6 +9,7 @@ require (
 | 
			
		||||
	github.com/cespare/xxhash v1.1.0
 | 
			
		||||
	github.com/go-sql-driver/mysql v1.5.0
 | 
			
		||||
	github.com/go-yaml/yaml v2.1.0+incompatible
 | 
			
		||||
	github.com/golang/protobuf v1.5.2 // indirect
 | 
			
		||||
	github.com/google/go-cmp v0.5.6 // indirect
 | 
			
		||||
	github.com/iwind/TeaGo v0.0.0-20210411134150-ddf57e240c2f
 | 
			
		||||
	github.com/miekg/dns v1.1.35
 | 
			
		||||
@@ -20,5 +21,6 @@ require (
 | 
			
		||||
	golang.org/x/sys v0.0.0-20210616094352-59db8d763f22
 | 
			
		||||
	google.golang.org/genproto v0.0.0-20210617175327-b9e0b3197ced // indirect
 | 
			
		||||
	google.golang.org/grpc v1.38.0
 | 
			
		||||
	google.golang.org/protobuf v1.26.0 // indirect
 | 
			
		||||
	gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776
 | 
			
		||||
)
 | 
			
		||||
 
 | 
			
		||||
@@ -22,6 +22,7 @@ func (this *ListsAction) RunGet(params struct {
 | 
			
		||||
	Type             string
 | 
			
		||||
}) {
 | 
			
		||||
	this.Data["subMenuItem"] = params.Type
 | 
			
		||||
	this.Data["type"] = params.Type
 | 
			
		||||
 | 
			
		||||
	listId, err := dao.SharedHTTPFirewallPolicyDAO.FindEnabledPolicyIPListIdWithType(this.AdminContext(), params.FirewallPolicyId, params.Type)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,139 @@
 | 
			
		||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
 | 
			
		||||
 | 
			
		||||
package iplists
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
 | 
			
		||||
	"github.com/iwind/TeaGo/actions"
 | 
			
		||||
	"github.com/iwind/TeaGo/lists"
 | 
			
		||||
	"github.com/iwind/TeaGo/maps"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type BindHTTPFirewallPopupAction struct {
 | 
			
		||||
	actionutils.ParentAction
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (this *BindHTTPFirewallPopupAction) Init() {
 | 
			
		||||
	this.Nav("", "", "")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (this *BindHTTPFirewallPopupAction) RunGet(params struct {
 | 
			
		||||
	HttpFirewallPolicyId int64
 | 
			
		||||
	Type                 string
 | 
			
		||||
}) {
 | 
			
		||||
	this.Data["httpFirewallPolicyId"] = params.HttpFirewallPolicyId
 | 
			
		||||
 | 
			
		||||
	// 获取已经选中的名单IDs
 | 
			
		||||
	var selectedIds = []int64{}
 | 
			
		||||
	inboundConfig, err := dao.SharedHTTPFirewallPolicyDAO.FindEnabledHTTPFirewallPolicyInboundConfig(this.AdminContext(), params.HttpFirewallPolicyId)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		this.ErrorPage(err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	if inboundConfig != nil {
 | 
			
		||||
		for _, ref := range inboundConfig.PublicAllowListRefs {
 | 
			
		||||
			selectedIds = append(selectedIds, ref.ListId)
 | 
			
		||||
		}
 | 
			
		||||
		for _, ref := range inboundConfig.PublicDenyListRefs {
 | 
			
		||||
			selectedIds = append(selectedIds, ref.ListId)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// 公共的名单
 | 
			
		||||
	countResp, err := this.RPC().IPListRPC().CountAllEnabledIPLists(this.AdminContext(), &pb.CountAllEnabledIPListsRequest{
 | 
			
		||||
		Type:     params.Type,
 | 
			
		||||
		IsPublic: true,
 | 
			
		||||
		Keyword:  "",
 | 
			
		||||
	})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		this.ErrorPage(err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	count := countResp.Count
 | 
			
		||||
	page := this.NewPage(count)
 | 
			
		||||
	this.Data["page"] = page.AsHTML()
 | 
			
		||||
 | 
			
		||||
	listsResp, err := this.RPC().IPListRPC().ListEnabledIPLists(this.AdminContext(), &pb.ListEnabledIPListsRequest{
 | 
			
		||||
		Type:     params.Type,
 | 
			
		||||
		IsPublic: true,
 | 
			
		||||
		Keyword:  "",
 | 
			
		||||
		Offset:   page.Offset,
 | 
			
		||||
		Size:     page.Size,
 | 
			
		||||
	})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		this.ErrorPage(err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	var listMaps = []maps.Map{}
 | 
			
		||||
	for _, list := range listsResp.IpLists {
 | 
			
		||||
		// 包含的IP数量
 | 
			
		||||
		countItemsResp, err := this.RPC().IPItemRPC().CountIPItemsWithListId(this.AdminContext(), &pb.CountIPItemsWithListIdRequest{IpListId: list.Id})
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			this.ErrorPage(err)
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		var countItems = countItemsResp.Count
 | 
			
		||||
 | 
			
		||||
		listMaps = append(listMaps, maps.Map{
 | 
			
		||||
			"id":          list.Id,
 | 
			
		||||
			"isOn":        list.IsOn,
 | 
			
		||||
			"name":        list.Name,
 | 
			
		||||
			"description": list.Description,
 | 
			
		||||
			"countItems":  countItems,
 | 
			
		||||
			"type":        list.Type,
 | 
			
		||||
			"isSelected":  lists.ContainsInt64(selectedIds, list.Id),
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
	this.Data["lists"] = listMaps
 | 
			
		||||
 | 
			
		||||
	this.Show()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (this *BindHTTPFirewallPopupAction) RunPost(params struct {
 | 
			
		||||
	HttpFirewallPolicyId int64
 | 
			
		||||
	ListId               int64
 | 
			
		||||
 | 
			
		||||
	Must *actions.Must
 | 
			
		||||
}) {
 | 
			
		||||
	// List类型
 | 
			
		||||
	listResp, err := this.RPC().IPListRPC().FindEnabledIPList(this.AdminContext(), &pb.FindEnabledIPListRequest{IpListId: params.ListId})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		this.ErrorPage(err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	var list = listResp.IpList
 | 
			
		||||
	if list == nil {
 | 
			
		||||
		this.Fail("找不到要使用的IP名单")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// 已经绑定的
 | 
			
		||||
	inboundConfig, err := dao.SharedHTTPFirewallPolicyDAO.FindEnabledHTTPFirewallPolicyInboundConfig(this.AdminContext(), params.HttpFirewallPolicyId)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		this.ErrorPage(err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	if inboundConfig == nil {
 | 
			
		||||
		inboundConfig = &firewallconfigs.HTTPFirewallInboundConfig{IsOn: true}
 | 
			
		||||
	}
 | 
			
		||||
	inboundConfig.AddPublicList(list.Id, list.Type)
 | 
			
		||||
 | 
			
		||||
	inboundJSON, err := json.Marshal(inboundConfig)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		this.ErrorPage(err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	_, err = this.RPC().HTTPFirewallPolicyRPC().UpdateHTTPFirewallInboundConfig(this.AdminContext(), &pb.UpdateHTTPFirewallInboundConfigRequest{
 | 
			
		||||
		HttpFirewallPolicyId: params.HttpFirewallPolicyId,
 | 
			
		||||
		InboundJSON:          inboundJSON,
 | 
			
		||||
	})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		this.ErrorPage(err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	this.Success()
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										103
									
								
								internal/web/actions/default/servers/iplists/createIPPopup.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										103
									
								
								internal/web/actions/default/servers/iplists/createIPPopup.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,103 @@
 | 
			
		||||
package iplists
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
}) {
 | 
			
		||||
	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
 | 
			
		||||
}) {
 | 
			
		||||
	// 校验IPList
 | 
			
		||||
	existsResp, err := this.RPC().IPListRPC().ExistsEnabledIPList(this.AdminContext(), &pb.ExistsEnabledIPListRequest{IpListId: params.ListId})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		this.ErrorPage(err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	if !existsResp.Exists {
 | 
			
		||||
		this.Fail("IP名单不存在")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	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, "在IP名单中添加IP %d", itemId)
 | 
			
		||||
 | 
			
		||||
	this.Success()
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										64
									
								
								internal/web/actions/default/servers/iplists/createPopup.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								internal/web/actions/default/servers/iplists/createPopup.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,64 @@
 | 
			
		||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
 | 
			
		||||
 | 
			
		||||
package iplists
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
 | 
			
		||||
	"github.com/iwind/TeaGo/actions"
 | 
			
		||||
	"github.com/iwind/TeaGo/maps"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type CreatePopupAction struct {
 | 
			
		||||
	actionutils.ParentAction
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (this *CreatePopupAction) Init() {
 | 
			
		||||
	this.Nav("", "", "")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (this *CreatePopupAction) RunGet(params struct {
 | 
			
		||||
	Type string
 | 
			
		||||
}) {
 | 
			
		||||
	this.Data["type"] = params.Type
 | 
			
		||||
 | 
			
		||||
	this.Show()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (this *CreatePopupAction) RunPost(params struct {
 | 
			
		||||
	Name        string
 | 
			
		||||
	Type        string
 | 
			
		||||
	Description string
 | 
			
		||||
 | 
			
		||||
	Must *actions.Must
 | 
			
		||||
	CSRF *actionutils.CSRF
 | 
			
		||||
}) {
 | 
			
		||||
	var listId int64 = 0
 | 
			
		||||
	defer func() {
 | 
			
		||||
		defer this.CreateLogInfo("创建IP名单 %d", listId)
 | 
			
		||||
	}()
 | 
			
		||||
 | 
			
		||||
	params.Must.
 | 
			
		||||
		Field("name", params.Name).
 | 
			
		||||
		Require("请输入名称")
 | 
			
		||||
 | 
			
		||||
	createResp, err := this.RPC().IPListRPC().CreateIPList(this.AdminContext(), &pb.CreateIPListRequest{
 | 
			
		||||
		Type:        params.Type,
 | 
			
		||||
		Name:        params.Name,
 | 
			
		||||
		Code:        "",
 | 
			
		||||
		TimeoutJSON: nil,
 | 
			
		||||
		IsPublic:    true,
 | 
			
		||||
		Description: params.Description,
 | 
			
		||||
	})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		this.ErrorPage(err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	listId = createResp.IpListId
 | 
			
		||||
 | 
			
		||||
	this.Data["list"] = maps.Map{
 | 
			
		||||
		"type": params.Type,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	this.Success()
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										27
									
								
								internal/web/actions/default/servers/iplists/delete.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								internal/web/actions/default/servers/iplists/delete.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,27 @@
 | 
			
		||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
 | 
			
		||||
 | 
			
		||||
package iplists
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type DeleteAction struct {
 | 
			
		||||
	actionutils.ParentAction
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (this *DeleteAction) RunPost(params struct {
 | 
			
		||||
	ListId int64
 | 
			
		||||
}) {
 | 
			
		||||
	defer this.CreateLogInfo("删除IP名单 %d", params.ListId)
 | 
			
		||||
 | 
			
		||||
	// 删除
 | 
			
		||||
	_, err := this.RPC().IPListRPC().DeleteIPList(this.AdminContext(), &pb.DeleteIPListRequest{IpListId: params.ListId})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		this.ErrorPage(err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	this.Success()
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										26
									
								
								internal/web/actions/default/servers/iplists/deleteIP.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								internal/web/actions/default/servers/iplists/deleteIP.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,26 @@
 | 
			
		||||
package iplists
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/TeaOSLab/EdgeAdmin/internal/oplogs"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type DeleteIPAction struct {
 | 
			
		||||
	actionutils.ParentAction
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (this *DeleteIPAction) RunPost(params struct {
 | 
			
		||||
	ItemId int64
 | 
			
		||||
}) {
 | 
			
		||||
	// 日志
 | 
			
		||||
	defer this.CreateLog(oplogs.LevelInfo, "从IP名单中删除IP %d", params.ItemId)
 | 
			
		||||
 | 
			
		||||
	_, err := this.RPC().IPItemRPC().DeleteIPItem(this.AdminContext(), &pb.DeleteIPItemRequest{IpItemId: params.ItemId})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		this.ErrorPage(err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	this.Success()
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										25
									
								
								internal/web/actions/default/servers/iplists/export.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								internal/web/actions/default/servers/iplists/export.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,25 @@
 | 
			
		||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
 | 
			
		||||
 | 
			
		||||
package iplists
 | 
			
		||||
 | 
			
		||||
import "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
 | 
			
		||||
 | 
			
		||||
type ExportAction struct {
 | 
			
		||||
	actionutils.ParentAction
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (this *ExportAction) Init() {
 | 
			
		||||
	this.Nav("", "", "export")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (this *ExportAction) RunGet(params struct {
 | 
			
		||||
	ListId int64
 | 
			
		||||
}) {
 | 
			
		||||
	err := InitIPList(this.Parent(), params.ListId)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		this.ErrorPage(err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	this.Show()
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										57
									
								
								internal/web/actions/default/servers/iplists/exportData.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								internal/web/actions/default/servers/iplists/exportData.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,57 @@
 | 
			
		||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
 | 
			
		||||
 | 
			
		||||
package iplists
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/TeaOSLab/EdgeAdmin/internal/utils/numberutils"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
 | 
			
		||||
	"github.com/golang/protobuf/proto"
 | 
			
		||||
	"strconv"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type ExportDataAction struct {
 | 
			
		||||
	actionutils.ParentAction
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (this *ExportDataAction) Init() {
 | 
			
		||||
	this.Nav("", "", "")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (this *ExportDataAction) RunGet(params struct {
 | 
			
		||||
	ListId int64
 | 
			
		||||
}) {
 | 
			
		||||
	defer this.CreateLogInfo("导出IP名单 %d", params.ListId)
 | 
			
		||||
 | 
			
		||||
	resp := &pb.ListIPItemsWithListIdResponse{}
 | 
			
		||||
	var offset int64 = 0
 | 
			
		||||
	var size int64 = 1000
 | 
			
		||||
	for {
 | 
			
		||||
		itemsResp, err := this.RPC().IPItemRPC().ListIPItemsWithListId(this.AdminContext(), &pb.ListIPItemsWithListIdRequest{
 | 
			
		||||
			IpListId: params.ListId,
 | 
			
		||||
			Offset:   offset,
 | 
			
		||||
			Size:     size,
 | 
			
		||||
		})
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			this.ErrorPage(err)
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		if len(itemsResp.IpItems) == 0 {
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
		for _, item := range itemsResp.IpItems {
 | 
			
		||||
			resp.IpItems = append(resp.IpItems, item)
 | 
			
		||||
		}
 | 
			
		||||
		offset += size
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	data, err := proto.Marshal(resp)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		this.ErrorPage(err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	this.AddHeader("Content-Disposition", "attachment; filename=\"ip-list-"+numberutils.FormatInt64(params.ListId)+".data\";")
 | 
			
		||||
	this.AddHeader("Content-Length", strconv.Itoa(len(data)))
 | 
			
		||||
	this.Write(data)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										59
									
								
								internal/web/actions/default/servers/iplists/httpFirewall.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								internal/web/actions/default/servers/iplists/httpFirewall.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,59 @@
 | 
			
		||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
 | 
			
		||||
 | 
			
		||||
package iplists
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/ipconfigs"
 | 
			
		||||
	"github.com/iwind/TeaGo/maps"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// HttpFirewallAction 显示已经绑定的IP名单
 | 
			
		||||
type HttpFirewallAction struct {
 | 
			
		||||
	actionutils.ParentAction
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (this *HttpFirewallAction) RunPost(params struct {
 | 
			
		||||
	HttpFirewallPolicyId int64
 | 
			
		||||
	Type                 string
 | 
			
		||||
}) {
 | 
			
		||||
	inboundConfig, err := dao.SharedHTTPFirewallPolicyDAO.FindEnabledHTTPFirewallPolicyInboundConfig(this.AdminContext(), params.HttpFirewallPolicyId)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		this.ErrorPage(err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	if inboundConfig == nil {
 | 
			
		||||
		inboundConfig = &firewallconfigs.HTTPFirewallInboundConfig{IsOn: true}
 | 
			
		||||
	}
 | 
			
		||||
	var refs []*ipconfigs.IPListRef
 | 
			
		||||
	switch params.Type {
 | 
			
		||||
	case ipconfigs.IPListTypeBlack:
 | 
			
		||||
		refs = inboundConfig.PublicDenyListRefs
 | 
			
		||||
	case ipconfigs.IPListTypeWhite:
 | 
			
		||||
		refs = inboundConfig.PublicAllowListRefs
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	listMaps := []maps.Map{}
 | 
			
		||||
	for _, ref := range refs {
 | 
			
		||||
		listResp, err := this.RPC().IPListRPC().FindEnabledIPList(this.AdminContext(), &pb.FindEnabledIPListRequest{IpListId: ref.ListId})
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			this.ErrorPage(err)
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		var list = listResp.IpList
 | 
			
		||||
		if list == nil {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		listMaps = append(listMaps, maps.Map{
 | 
			
		||||
			"id":   list.Id,
 | 
			
		||||
			"name": list.Name,
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
	this.Data["lists"] = listMaps
 | 
			
		||||
 | 
			
		||||
	this.Success()
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										87
									
								
								internal/web/actions/default/servers/iplists/import.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										87
									
								
								internal/web/actions/default/servers/iplists/import.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,87 @@
 | 
			
		||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
 | 
			
		||||
 | 
			
		||||
package iplists
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
 | 
			
		||||
	"github.com/golang/protobuf/proto"
 | 
			
		||||
	"github.com/iwind/TeaGo/actions"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type ImportAction struct {
 | 
			
		||||
	actionutils.ParentAction
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (this *ImportAction) Init() {
 | 
			
		||||
	this.Nav("", "", "import")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (this *ImportAction) RunGet(params struct {
 | 
			
		||||
	ListId int64
 | 
			
		||||
}) {
 | 
			
		||||
	err := InitIPList(this.Parent(), params.ListId)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		this.ErrorPage(err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	this.Show()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (this *ImportAction) RunPost(params struct {
 | 
			
		||||
	ListId int64
 | 
			
		||||
	File   *actions.File
 | 
			
		||||
 | 
			
		||||
	Must *actions.Must
 | 
			
		||||
	CSRF *actionutils.CSRF
 | 
			
		||||
}) {
 | 
			
		||||
	defer this.CreateLogInfo("导入IP名单 %d", params.ListId)
 | 
			
		||||
 | 
			
		||||
	existsResp, err := this.RPC().IPListRPC().ExistsEnabledIPList(this.AdminContext(), &pb.ExistsEnabledIPListRequest{IpListId: params.ListId})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		this.ErrorPage(err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	if !existsResp.Exists {
 | 
			
		||||
		this.Fail("IP名单不存在")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if params.File == nil {
 | 
			
		||||
		this.Fail("请选择要导入的IP文件")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	data, err := params.File.Read()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		this.ErrorPage(err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	resp := &pb.ListIPItemsWithListIdResponse{}
 | 
			
		||||
	err = proto.Unmarshal(data, resp)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		this.Fail("导入失败,文件格式错误:" + err.Error())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var count = 0
 | 
			
		||||
	var countIgnore = 0
 | 
			
		||||
	for _, item := range resp.IpItems {
 | 
			
		||||
		_, err = this.RPC().IPItemRPC().CreateIPItem(this.AdminContext(), &pb.CreateIPItemRequest{
 | 
			
		||||
			IpListId:   params.ListId,
 | 
			
		||||
			IpFrom:     item.IpFrom,
 | 
			
		||||
			IpTo:       item.IpTo,
 | 
			
		||||
			ExpiredAt:  item.ExpiredAt,
 | 
			
		||||
			Reason:     item.Reason,
 | 
			
		||||
			Type:       item.Type,
 | 
			
		||||
			EventLevel: item.EventLevel,
 | 
			
		||||
		})
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			this.Fail("导入过程中出错:" + err.Error())
 | 
			
		||||
		}
 | 
			
		||||
		count++
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	this.Data["count"] = count
 | 
			
		||||
	this.Data["countIgnore"] = countIgnore
 | 
			
		||||
 | 
			
		||||
	this.Success()
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										76
									
								
								internal/web/actions/default/servers/iplists/index.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								internal/web/actions/default/servers/iplists/index.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,76 @@
 | 
			
		||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
 | 
			
		||||
 | 
			
		||||
package iplists
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/ipconfigs"
 | 
			
		||||
	"github.com/iwind/TeaGo/maps"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type IndexAction struct {
 | 
			
		||||
	actionutils.ParentAction
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (this *IndexAction) Init() {
 | 
			
		||||
	this.Nav("", "", "index")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (this *IndexAction) RunGet(params struct {
 | 
			
		||||
	Type    string
 | 
			
		||||
	Keyword string
 | 
			
		||||
}) {
 | 
			
		||||
	if len(params.Type) == 0 {
 | 
			
		||||
		params.Type = ipconfigs.IPListTypeBlack
 | 
			
		||||
	}
 | 
			
		||||
	this.Data["type"] = params.Type
 | 
			
		||||
	this.Data["keyword"] = params.Keyword
 | 
			
		||||
 | 
			
		||||
	countResp, err := this.RPC().IPListRPC().CountAllEnabledIPLists(this.AdminContext(), &pb.CountAllEnabledIPListsRequest{
 | 
			
		||||
		Type:     params.Type,
 | 
			
		||||
		IsPublic: true,
 | 
			
		||||
		Keyword:  params.Keyword,
 | 
			
		||||
	})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		this.ErrorPage(err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	count := countResp.Count
 | 
			
		||||
	page := this.NewPage(count)
 | 
			
		||||
	this.Data["page"] = page.AsHTML()
 | 
			
		||||
 | 
			
		||||
	listsResp, err := this.RPC().IPListRPC().ListEnabledIPLists(this.AdminContext(), &pb.ListEnabledIPListsRequest{
 | 
			
		||||
		Type:     params.Type,
 | 
			
		||||
		IsPublic: true,
 | 
			
		||||
		Keyword:  params.Keyword,
 | 
			
		||||
		Offset:   page.Offset,
 | 
			
		||||
		Size:     page.Size,
 | 
			
		||||
	})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		this.ErrorPage(err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	var listMaps = []maps.Map{}
 | 
			
		||||
	for _, list := range listsResp.IpLists {
 | 
			
		||||
		// 包含的IP数量
 | 
			
		||||
		countItemsResp, err := this.RPC().IPItemRPC().CountIPItemsWithListId(this.AdminContext(), &pb.CountIPItemsWithListIdRequest{IpListId: list.Id})
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			this.ErrorPage(err)
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		var countItems = countItemsResp.Count
 | 
			
		||||
 | 
			
		||||
		listMaps = append(listMaps, maps.Map{
 | 
			
		||||
			"id":          list.Id,
 | 
			
		||||
			"isOn":        list.IsOn,
 | 
			
		||||
			"name":        list.Name,
 | 
			
		||||
			"description": list.Description,
 | 
			
		||||
			"countItems":  countItems,
 | 
			
		||||
			"type":        list.Type,
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
	this.Data["lists"] = listMaps
 | 
			
		||||
 | 
			
		||||
	this.Show()
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										39
									
								
								internal/web/actions/default/servers/iplists/init.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								internal/web/actions/default/servers/iplists/init.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,39 @@
 | 
			
		||||
package iplists
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
 | 
			
		||||
	"github.com/iwind/TeaGo"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	TeaGo.BeforeStart(func(server *TeaGo.Server) {
 | 
			
		||||
		server.
 | 
			
		||||
			Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeServer)).
 | 
			
		||||
			Data("teaMenu", "servers").
 | 
			
		||||
			Data("teaSubMenu", "iplist").
 | 
			
		||||
			Prefix("/servers/iplists").
 | 
			
		||||
			Get("", new(IndexAction)).
 | 
			
		||||
			GetPost("/createPopup", new(CreatePopupAction)).
 | 
			
		||||
			Get("/list", new(ListAction)).
 | 
			
		||||
			GetPost("/import", new(ImportAction)).
 | 
			
		||||
			GetPost("/export", new(ExportAction)).
 | 
			
		||||
			Get("/exportData", new(ExportDataAction)).
 | 
			
		||||
			Post("/delete", new(DeleteAction)).
 | 
			
		||||
			GetPost("/test", new(TestAction)).
 | 
			
		||||
			GetPost("/update", new(UpdateAction)).
 | 
			
		||||
			Get("/items", new(ItemsAction)).
 | 
			
		||||
 | 
			
		||||
			// IP相关
 | 
			
		||||
			GetPost("/createIPPopup", new(CreateIPPopupAction)).
 | 
			
		||||
			GetPost("/updateIPPopup", new(UpdateIPPopupAction)).
 | 
			
		||||
			Post("/deleteIP", new(DeleteIPAction)).
 | 
			
		||||
 | 
			
		||||
			// 防火墙
 | 
			
		||||
			GetPost("/bindHTTPFirewallPopup", new(BindHTTPFirewallPopupAction)).
 | 
			
		||||
			Post("/unbindHTTPFirewall", new(UnbindHTTPFirewallAction)).
 | 
			
		||||
			Post("/httpFirewall", new(HttpFirewallAction)).
 | 
			
		||||
 | 
			
		||||
			EndAll()
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										71
									
								
								internal/web/actions/default/servers/iplists/items.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								internal/web/actions/default/servers/iplists/items.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,71 @@
 | 
			
		||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
 | 
			
		||||
 | 
			
		||||
package iplists
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
 | 
			
		||||
	"github.com/iwind/TeaGo/maps"
 | 
			
		||||
	timeutil "github.com/iwind/TeaGo/utils/time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type ItemsAction struct {
 | 
			
		||||
	actionutils.ParentAction
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (this *ItemsAction) Init() {
 | 
			
		||||
	this.Nav("", "", "item")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (this *ItemsAction) RunGet(params struct {
 | 
			
		||||
	ListId int64
 | 
			
		||||
}) {
 | 
			
		||||
	err := InitIPList(this.Parent(), params.ListId)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		this.ErrorPage(err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// 数量
 | 
			
		||||
	var listId = params.ListId
 | 
			
		||||
	countResp, err := this.RPC().IPItemRPC().CountIPItemsWithListId(this.AdminContext(), &pb.CountIPItemsWithListIdRequest{IpListId: listId})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		this.ErrorPage(err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	count := countResp.Count
 | 
			
		||||
	page := this.NewPage(count)
 | 
			
		||||
	this.Data["page"] = page.AsHTML()
 | 
			
		||||
 | 
			
		||||
	// 列表
 | 
			
		||||
	itemsResp, err := this.RPC().IPItemRPC().ListIPItemsWithListId(this.AdminContext(), &pb.ListIPItemsWithListIdRequest{
 | 
			
		||||
		IpListId: listId,
 | 
			
		||||
		Offset:   page.Offset,
 | 
			
		||||
		Size:     page.Size,
 | 
			
		||||
	})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		this.ErrorPage(err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	itemMaps := []maps.Map{}
 | 
			
		||||
	for _, item := range itemsResp.IpItems {
 | 
			
		||||
		expiredTime := ""
 | 
			
		||||
		if item.ExpiredAt > 0 {
 | 
			
		||||
			expiredTime = timeutil.FormatTime("Y-m-d H:i:s", item.ExpiredAt)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		itemMaps = append(itemMaps, maps.Map{
 | 
			
		||||
			"id":             item.Id,
 | 
			
		||||
			"ipFrom":         item.IpFrom,
 | 
			
		||||
			"ipTo":           item.IpTo,
 | 
			
		||||
			"expiredTime":    expiredTime,
 | 
			
		||||
			"reason":         item.Reason,
 | 
			
		||||
			"type":           item.Type,
 | 
			
		||||
			"eventLevelName": firewallconfigs.FindFirewallEventLevelName(item.EventLevel),
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
	this.Data["items"] = itemMaps
 | 
			
		||||
 | 
			
		||||
	this.Show()
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										25
									
								
								internal/web/actions/default/servers/iplists/list.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								internal/web/actions/default/servers/iplists/list.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,25 @@
 | 
			
		||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
 | 
			
		||||
 | 
			
		||||
package iplists
 | 
			
		||||
 | 
			
		||||
import "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
 | 
			
		||||
 | 
			
		||||
type ListAction struct {
 | 
			
		||||
	actionutils.ParentAction
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (this *ListAction) Init() {
 | 
			
		||||
	this.Nav("", "", "list")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (this *ListAction) RunGet(params struct{
 | 
			
		||||
	ListId int64
 | 
			
		||||
}) {
 | 
			
		||||
	err := InitIPList(this.Parent(), params.ListId)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		this.ErrorPage(err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	this.Show()
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										74
									
								
								internal/web/actions/default/servers/iplists/test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								internal/web/actions/default/servers/iplists/test.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,74 @@
 | 
			
		||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
 | 
			
		||||
 | 
			
		||||
package iplists
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
 | 
			
		||||
	"github.com/iwind/TeaGo/actions"
 | 
			
		||||
	"github.com/iwind/TeaGo/maps"
 | 
			
		||||
	timeutil "github.com/iwind/TeaGo/utils/time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type TestAction struct {
 | 
			
		||||
	actionutils.ParentAction
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (this *TestAction) Init() {
 | 
			
		||||
	this.Nav("", "", "test")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (this *TestAction) RunGet(params struct {
 | 
			
		||||
	ListId int64
 | 
			
		||||
}) {
 | 
			
		||||
	err := InitIPList(this.Parent(), params.ListId)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		this.ErrorPage(err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	this.Show()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (this *TestAction) RunPost(params struct {
 | 
			
		||||
	ListId int64
 | 
			
		||||
	Ip     string
 | 
			
		||||
 | 
			
		||||
	Must *actions.Must
 | 
			
		||||
	CSRF *actionutils.CSRF
 | 
			
		||||
}) {
 | 
			
		||||
	resp, err := this.RPC().IPItemRPC().CheckIPItemStatus(this.AdminContext(), &pb.CheckIPItemStatusRequest{
 | 
			
		||||
		IpListId: params.ListId,
 | 
			
		||||
		Ip:       params.Ip,
 | 
			
		||||
	})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		this.ErrorPage(err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	resultMap := maps.Map{
 | 
			
		||||
		"isDone":    true,
 | 
			
		||||
		"isFound":   resp.IsFound,
 | 
			
		||||
		"isOk":      resp.IsOk,
 | 
			
		||||
		"error":     resp.Error,
 | 
			
		||||
		"isAllowed": resp.IsAllowed,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if resp.IpItem != nil {
 | 
			
		||||
		resultMap["item"] = maps.Map{
 | 
			
		||||
			"id":             resp.IpItem.Id,
 | 
			
		||||
			"ipFrom":         resp.IpItem.IpFrom,
 | 
			
		||||
			"ipTo":           resp.IpItem.IpTo,
 | 
			
		||||
			"reason":         resp.IpItem.Reason,
 | 
			
		||||
			"expiredAt":      resp.IpItem.ExpiredAt,
 | 
			
		||||
			"expiredTime":    timeutil.FormatTime("Y-m-d H:i:s", resp.IpItem.ExpiredAt),
 | 
			
		||||
			"type":           resp.IpItem.Type,
 | 
			
		||||
			"eventLevelName": firewallconfigs.FindFirewallEventLevelName(resp.IpItem.EventLevel),
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	this.Data["result"] = resultMap
 | 
			
		||||
 | 
			
		||||
	this.Success()
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,58 @@
 | 
			
		||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
 | 
			
		||||
 | 
			
		||||
package iplists
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type UnbindHTTPFirewallAction struct {
 | 
			
		||||
	actionutils.ParentAction
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (this *UnbindHTTPFirewallAction) RunPost(params struct {
 | 
			
		||||
	HttpFirewallPolicyId int64
 | 
			
		||||
	ListId               int64
 | 
			
		||||
}) {
 | 
			
		||||
	// List类型
 | 
			
		||||
	listResp, err := this.RPC().IPListRPC().FindEnabledIPList(this.AdminContext(), &pb.FindEnabledIPListRequest{IpListId: params.ListId})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		this.ErrorPage(err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	var list = listResp.IpList
 | 
			
		||||
	if list == nil {
 | 
			
		||||
		this.Fail("找不到要使用的IP名单")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// 已经绑定的
 | 
			
		||||
	inboundConfig, err := dao.SharedHTTPFirewallPolicyDAO.FindEnabledHTTPFirewallPolicyInboundConfig(this.AdminContext(), params.HttpFirewallPolicyId)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		this.ErrorPage(err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	if inboundConfig == nil {
 | 
			
		||||
		inboundConfig = &firewallconfigs.HTTPFirewallInboundConfig{IsOn: true}
 | 
			
		||||
	}
 | 
			
		||||
	inboundConfig.RemovePublicList(list.Id, list.Type)
 | 
			
		||||
 | 
			
		||||
	inboundJSON, err := json.Marshal(inboundConfig)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		this.ErrorPage(err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	_, err = this.RPC().HTTPFirewallPolicyRPC().UpdateHTTPFirewallInboundConfig(this.AdminContext(), &pb.UpdateHTTPFirewallInboundConfigRequest{
 | 
			
		||||
		HttpFirewallPolicyId: params.HttpFirewallPolicyId,
 | 
			
		||||
		InboundJSON:          inboundJSON,
 | 
			
		||||
	})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		this.ErrorPage(err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	this.Success()
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										58
									
								
								internal/web/actions/default/servers/iplists/update.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								internal/web/actions/default/servers/iplists/update.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,58 @@
 | 
			
		||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
 | 
			
		||||
 | 
			
		||||
package iplists
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
 | 
			
		||||
	"github.com/iwind/TeaGo/actions"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type UpdateAction struct {
 | 
			
		||||
	actionutils.ParentAction
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (this *UpdateAction) Init() {
 | 
			
		||||
	this.Nav("", "", "update")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (this *UpdateAction) RunGet(params struct {
 | 
			
		||||
	ListId int64
 | 
			
		||||
}) {
 | 
			
		||||
	err := InitIPList(this.Parent(), params.ListId)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		this.ErrorPage(err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	this.Show()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (this *UpdateAction) RunPost(params struct {
 | 
			
		||||
	ListId      int64
 | 
			
		||||
	Name        string
 | 
			
		||||
	Type        string
 | 
			
		||||
	Description string
 | 
			
		||||
 | 
			
		||||
	Must *actions.Must
 | 
			
		||||
	CSRF *actionutils.CSRF
 | 
			
		||||
}) {
 | 
			
		||||
	defer this.CreateLogInfo("修改IP名单 %d", params.ListId)
 | 
			
		||||
 | 
			
		||||
	params.Must.
 | 
			
		||||
		Field("name", params.Name).
 | 
			
		||||
		Require("请输入名称")
 | 
			
		||||
 | 
			
		||||
	_, err := this.RPC().IPListRPC().UpdateIPList(this.AdminContext(), &pb.UpdateIPListRequest{
 | 
			
		||||
		IpListId:    params.ListId,
 | 
			
		||||
		Name:        params.Name,
 | 
			
		||||
		Code:        "",
 | 
			
		||||
		TimeoutJSON: nil,
 | 
			
		||||
		Description: params.Description,
 | 
			
		||||
	})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		this.ErrorPage(err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	this.Success()
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										117
									
								
								internal/web/actions/default/servers/iplists/updateIPPopup.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										117
									
								
								internal/web/actions/default/servers/iplists/updateIPPopup.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,117 @@
 | 
			
		||||
package iplists
 | 
			
		||||
 | 
			
		||||
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"
 | 
			
		||||
	"github.com/iwind/TeaGo/maps"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type UpdateIPPopupAction struct {
 | 
			
		||||
	actionutils.ParentAction
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (this *UpdateIPPopupAction) Init() {
 | 
			
		||||
	this.Nav("", "", "")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (this *UpdateIPPopupAction) RunGet(params struct {
 | 
			
		||||
	ItemId int64
 | 
			
		||||
}) {
 | 
			
		||||
	itemResp, err := this.RPC().IPItemRPC().FindEnabledIPItem(this.AdminContext(), &pb.FindEnabledIPItemRequest{IpItemId: params.ItemId})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		this.ErrorPage(err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	item := itemResp.IpItem
 | 
			
		||||
	if item == nil {
 | 
			
		||||
		this.NotFound("ipItem", params.ItemId)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	this.Data["item"] = maps.Map{
 | 
			
		||||
		"id":         item.Id,
 | 
			
		||||
		"ipFrom":     item.IpFrom,
 | 
			
		||||
		"ipTo":       item.IpTo,
 | 
			
		||||
		"expiredAt":  item.ExpiredAt,
 | 
			
		||||
		"reason":     item.Reason,
 | 
			
		||||
		"type":       item.Type,
 | 
			
		||||
		"eventLevel": item.EventLevel,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	this.Data["type"] = item.Type
 | 
			
		||||
 | 
			
		||||
	this.Show()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (this *UpdateIPPopupAction) RunPost(params struct {
 | 
			
		||||
	ItemId int64
 | 
			
		||||
 | 
			
		||||
	IpFrom     string
 | 
			
		||||
	IpTo       string
 | 
			
		||||
	ExpiredAt  int64
 | 
			
		||||
	Reason     string
 | 
			
		||||
	Type       string
 | 
			
		||||
	EventLevel string
 | 
			
		||||
 | 
			
		||||
	Must *actions.Must
 | 
			
		||||
	CSRF *actionutils.CSRF
 | 
			
		||||
}) {
 | 
			
		||||
	// 日志
 | 
			
		||||
	defer this.CreateLog(oplogs.LevelInfo, "修改IP名单中IP %d", params.ItemId)
 | 
			
		||||
 | 
			
		||||
	// TODO 校验ItemId所属用户
 | 
			
		||||
 | 
			
		||||
	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"
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	_, err := this.RPC().IPItemRPC().UpdateIPItem(this.AdminContext(), &pb.UpdateIPItemRequest{
 | 
			
		||||
		IpItemId:   params.ItemId,
 | 
			
		||||
		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
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	this.Success()
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										52
									
								
								internal/web/actions/default/servers/iplists/utils.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								internal/web/actions/default/servers/iplists/utils.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,52 @@
 | 
			
		||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
 | 
			
		||||
 | 
			
		||||
package iplists
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeAdmin/internal/rpc"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
 | 
			
		||||
	"github.com/iwind/TeaGo/maps"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func InitIPList(action *actionutils.ParentAction, listId int64) error {
 | 
			
		||||
	client, err := rpc.SharedRPC()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	listResp, err := client.IPListRPC().FindEnabledIPList(action.AdminContext(), &pb.FindEnabledIPListRequest{IpListId: listId})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	list := listResp.IpList
 | 
			
		||||
	if list == nil {
 | 
			
		||||
		return errors.New("not found")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var typeName = ""
 | 
			
		||||
	switch list.Type {
 | 
			
		||||
	case "black":
 | 
			
		||||
		typeName = "黑名单"
 | 
			
		||||
	case "white":
 | 
			
		||||
		typeName = "白名单"
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// IP数量
 | 
			
		||||
	countItemsResp, err := client.IPItemRPC().CountIPItemsWithListId(action.AdminContext(), &pb.CountIPItemsWithListIdRequest{IpListId: listId})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	countItems := countItemsResp.Count
 | 
			
		||||
 | 
			
		||||
	action.Data["list"] = maps.Map{
 | 
			
		||||
		"id":          list.Id,
 | 
			
		||||
		"name":        list.Name,
 | 
			
		||||
		"type":        list.Type,
 | 
			
		||||
		"typeName":    typeName,
 | 
			
		||||
		"description": list.Description,
 | 
			
		||||
		"isOn":        list.IsOn,
 | 
			
		||||
		"countItems":  countItems,
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										30
									
								
								internal/web/actions/default/ui/hideTip.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								internal/web/actions/default/ui/hideTip.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,30 @@
 | 
			
		||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
 | 
			
		||||
 | 
			
		||||
package ui
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
 | 
			
		||||
	"github.com/iwind/TeaGo/Tea"
 | 
			
		||||
	"io/ioutil"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type HideTipAction struct {
 | 
			
		||||
	actionutils.ParentAction
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (this *HideTipAction) RunPost(params struct {
 | 
			
		||||
	Code string
 | 
			
		||||
}) {
 | 
			
		||||
	tipKeyLocker.Lock()
 | 
			
		||||
	tipKeyMap[params.Code] = true
 | 
			
		||||
	tipKeyLocker.Unlock()
 | 
			
		||||
 | 
			
		||||
	// 保存到文件
 | 
			
		||||
	tipJSON, err := json.Marshal(tipKeyMap)
 | 
			
		||||
	if err == nil {
 | 
			
		||||
		_ = ioutil.WriteFile(Tea.ConfigFile(tipConfigFile), tipJSON, 0666)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	this.Success()
 | 
			
		||||
}
 | 
			
		||||
@@ -27,6 +27,8 @@ func init() {
 | 
			
		||||
			GetPost("/selectProvincesPopup", new(SelectProvincesPopupAction)).
 | 
			
		||||
			GetPost("/selectCountriesPopup", new(SelectCountriesPopupAction)).
 | 
			
		||||
			Post("/eventLevelOptions", new(EventLevelOptionsAction)).
 | 
			
		||||
			Post("/showTip", new(ShowTipAction)).
 | 
			
		||||
			Post("/hideTip", new(HideTipAction)).
 | 
			
		||||
 | 
			
		||||
			EndAll()
 | 
			
		||||
	})
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										48
									
								
								internal/web/actions/default/ui/showTip.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								internal/web/actions/default/ui/showTip.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,48 @@
 | 
			
		||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
 | 
			
		||||
 | 
			
		||||
package ui
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
 | 
			
		||||
	"github.com/iwind/TeaGo"
 | 
			
		||||
	"github.com/iwind/TeaGo/Tea"
 | 
			
		||||
	"io/ioutil"
 | 
			
		||||
	"sync"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var tipKeyMap = map[string]bool{}
 | 
			
		||||
var tipKeyLocker = sync.Mutex{}
 | 
			
		||||
var tipConfigFile = "tip.json"
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	TeaGo.BeforeStart(func(server *TeaGo.Server) {
 | 
			
		||||
		// 从配置文件中加载已关闭的tips
 | 
			
		||||
		data, err := ioutil.ReadFile(Tea.ConfigFile(tipConfigFile))
 | 
			
		||||
		if err == nil {
 | 
			
		||||
			var m = map[string]bool{}
 | 
			
		||||
			err = json.Unmarshal(data, &m)
 | 
			
		||||
			if err == nil {
 | 
			
		||||
				tipKeyLocker.Lock()
 | 
			
		||||
				tipKeyMap = m
 | 
			
		||||
				tipKeyLocker.Unlock()
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type ShowTipAction struct {
 | 
			
		||||
	actionutils.ParentAction
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (this *ShowTipAction) RunPost(params struct {
 | 
			
		||||
	Code string
 | 
			
		||||
}) {
 | 
			
		||||
	tipKeyLocker.Lock()
 | 
			
		||||
	_, ok := tipKeyMap[params.Code]
 | 
			
		||||
	tipKeyLocker.Unlock()
 | 
			
		||||
 | 
			
		||||
	this.Data["visible"] = !ok
 | 
			
		||||
 | 
			
		||||
	this.Success()
 | 
			
		||||
}
 | 
			
		||||
@@ -167,6 +167,11 @@ func (this *userMustAuth) modules(adminId int64) []maps.Map {
 | 
			
		||||
					"url":  "/servers/components/waf",
 | 
			
		||||
					"code": "waf",
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					"name": "IP名单",
 | 
			
		||||
					"url":  "/servers/iplists",
 | 
			
		||||
					"code": "iplist",
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					"name": "证书管理",
 | 
			
		||||
					"url":  "/servers/certs",
 | 
			
		||||
 
 | 
			
		||||
@@ -109,6 +109,8 @@ import (
 | 
			
		||||
	_ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/server/settings/websocket"
 | 
			
		||||
	_ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/server/stat"
 | 
			
		||||
 | 
			
		||||
	_ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/iplists"
 | 
			
		||||
 | 
			
		||||
	// 设置相关
 | 
			
		||||
	_ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/settings"
 | 
			
		||||
	_ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/settings/authority"
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										37
									
								
								web/public/js/components/common/tip-message-box.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								web/public/js/components/common/tip-message-box.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,37 @@
 | 
			
		||||
// 信息提示窗口
 | 
			
		||||
Vue.component("tip-message-box", {
 | 
			
		||||
	props: ["code"],
 | 
			
		||||
	mounted: function () {
 | 
			
		||||
		let that = this
 | 
			
		||||
		Tea.action("/ui/showTip")
 | 
			
		||||
			.params({
 | 
			
		||||
				code: this.code
 | 
			
		||||
			})
 | 
			
		||||
			.success(function (resp) {
 | 
			
		||||
				that.visible = resp.data.visible
 | 
			
		||||
			})
 | 
			
		||||
			.post()
 | 
			
		||||
	},
 | 
			
		||||
	data: function () {
 | 
			
		||||
		return {
 | 
			
		||||
			visible: false
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
	methods: {
 | 
			
		||||
		close: function () {
 | 
			
		||||
			this.visible = false
 | 
			
		||||
			Tea.action("/ui/hideTip")
 | 
			
		||||
				.params({
 | 
			
		||||
					code: this.code
 | 
			
		||||
				})
 | 
			
		||||
				.post()
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
	template: `<div class="ui icon message" v-if="visible">
 | 
			
		||||
	<i class="icon info circle"></i>
 | 
			
		||||
	<i class="close icon" title="取消" @click.prevent="close"></i>
 | 
			
		||||
	<div class="content">
 | 
			
		||||
		<slot></slot>
 | 
			
		||||
	</div>
 | 
			
		||||
</div>`
 | 
			
		||||
})
 | 
			
		||||
							
								
								
									
										62
									
								
								web/public/js/components/iplist/ip-list-bind-box.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								web/public/js/components/iplist/ip-list-bind-box.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,62 @@
 | 
			
		||||
// 绑定IP列表
 | 
			
		||||
Vue.component("ip-list-bind-box", {
 | 
			
		||||
	props: ["v-http-firewall-policy-id", "v-type"],
 | 
			
		||||
	mounted: function () {
 | 
			
		||||
		this.refresh()
 | 
			
		||||
	},
 | 
			
		||||
	data: function () {
 | 
			
		||||
		return {
 | 
			
		||||
			policyId: this.vHttpFirewallPolicyId,
 | 
			
		||||
			type: this.vType,
 | 
			
		||||
			lists: []
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
	methods: {
 | 
			
		||||
		bind: function () {
 | 
			
		||||
			let that = this
 | 
			
		||||
			teaweb.popup("/servers/iplists/bindHTTPFirewallPopup?httpFirewallPolicyId=" + this.policyId + "&type=" + this.type, {
 | 
			
		||||
				width: "50em",
 | 
			
		||||
				height: "34em",
 | 
			
		||||
				callback: function () {
 | 
			
		||||
 | 
			
		||||
				},
 | 
			
		||||
				onClose: function () {
 | 
			
		||||
					that.refresh()
 | 
			
		||||
				}
 | 
			
		||||
			})
 | 
			
		||||
		},
 | 
			
		||||
		remove: function (index, listId) {
 | 
			
		||||
			let that = this
 | 
			
		||||
			teaweb.confirm("确定要删除这个绑定的IP名单吗?", function () {
 | 
			
		||||
				Tea.action("/servers/iplists/unbindHTTPFirewall")
 | 
			
		||||
					.params({
 | 
			
		||||
						httpFirewallPolicyId: that.policyId,
 | 
			
		||||
						listId: listId
 | 
			
		||||
					})
 | 
			
		||||
					.post()
 | 
			
		||||
					.success(function (resp) {
 | 
			
		||||
						that.lists.$remove(index)
 | 
			
		||||
					})
 | 
			
		||||
			})
 | 
			
		||||
		},
 | 
			
		||||
		refresh: function () {
 | 
			
		||||
			let that = this
 | 
			
		||||
			Tea.action("/servers/iplists/httpFirewall")
 | 
			
		||||
				.params({
 | 
			
		||||
					httpFirewallPolicyId: this.policyId,
 | 
			
		||||
					type: this.vType
 | 
			
		||||
				})
 | 
			
		||||
				.post()
 | 
			
		||||
				.success(function (resp) {
 | 
			
		||||
					that.lists = resp.data.lists
 | 
			
		||||
				})
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
	template: `<div>
 | 
			
		||||
	<a href="" @click.prevent="bind()">绑定+</a>   <span v-if="lists.length > 0"><span class="disabled small">| </span> 已绑定:</span>
 | 
			
		||||
	<div class="ui label basic small" v-for="(list, index) in lists">
 | 
			
		||||
		{{list.name}}
 | 
			
		||||
		<a href="" title="删除" @click.prevent="remove(index, list.id)"><i class="icon remove small"></i></a>
 | 
			
		||||
	</div>
 | 
			
		||||
</div>`
 | 
			
		||||
})
 | 
			
		||||
@@ -34,7 +34,7 @@ Vue.component("http-access-log-box", {
 | 
			
		||||
			this.select()
 | 
			
		||||
			teaweb.popup("/servers/server/log/viewPopup?requestId=" + requestId, {
 | 
			
		||||
				width: "50em",
 | 
			
		||||
				height: "24em",
 | 
			
		||||
				height: "28em",
 | 
			
		||||
				onClose: function () {
 | 
			
		||||
					that.deselect()
 | 
			
		||||
				}
 | 
			
		||||
 
 | 
			
		||||
@@ -197,9 +197,6 @@ p.margin {
 | 
			
		||||
    padding-top: 2em;
 | 
			
		||||
    padding-bottom: 2.4em;
 | 
			
		||||
  }
 | 
			
		||||
  .main-menu .ui.menu .item span {
 | 
			
		||||
    display: none;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
.main-menu .ui.labeled.icon.menu .item {
 | 
			
		||||
  font-size: 0.9em;
 | 
			
		||||
@@ -214,9 +211,19 @@ p.margin {
 | 
			
		||||
  margin-top: 0.5em;
 | 
			
		||||
  color: grey;
 | 
			
		||||
}
 | 
			
		||||
@media screen and (max-width: 512px) {
 | 
			
		||||
  .main-menu .ui.menu .item.expend .subtitle {
 | 
			
		||||
    display: none;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
.main-menu .ui.menu .sub-items .item {
 | 
			
		||||
  padding-left: 2.8em !important;
 | 
			
		||||
}
 | 
			
		||||
@media screen and (max-width: 512px) {
 | 
			
		||||
  .main-menu .ui.menu .sub-items .item {
 | 
			
		||||
    padding-left: 1em!important;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
.main-menu .ui.menu .sub-items .item.active {
 | 
			
		||||
  background-color: #2185d0 !important;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							@@ -80,7 +80,7 @@
 | 
			
		||||
					<span v-if="module.code.length > 0">
 | 
			
		||||
						<i class="window restore outline icon" v-if="module.icon == null"></i>
 | 
			
		||||
						<i class="ui icon" v-if="module.icon != null" :class="module.icon"></i>
 | 
			
		||||
						<span>{{module.name}}</span>
 | 
			
		||||
						<span class="module-name">{{module.name}}</span>
 | 
			
		||||
					</span>
 | 
			
		||||
                    <div class="subtitle" v-if="module.subtitle != null && module.subtitle.length > 0">{{module.subtitle}}</div>
 | 
			
		||||
				</a>
 | 
			
		||||
 
 | 
			
		||||
@@ -139,7 +139,7 @@ div.margin, p.margin {
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	.main-menu .ui.menu .item span {
 | 
			
		||||
		display: none;
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -163,11 +163,23 @@ div.margin, p.margin {
 | 
			
		||||
			color: grey;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		@media screen and (max-width: 512px) {
 | 
			
		||||
			.item.expend .subtitle {
 | 
			
		||||
				display: none;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		.sub-items {
 | 
			
		||||
			.item {
 | 
			
		||||
				padding-left: 2.8em !important;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			@media screen and (max-width: 512px) {
 | 
			
		||||
				.item {
 | 
			
		||||
					padding-left: 1em!important;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			.item.active {
 | 
			
		||||
				background-color: #2185d0 !important;
 | 
			
		||||
			}
 | 
			
		||||
 
 | 
			
		||||
@@ -56,10 +56,13 @@ Tea.context(function () {
 | 
			
		||||
	 * 添加IP名单菜单
 | 
			
		||||
	 */
 | 
			
		||||
	this.createIP = function (type) {
 | 
			
		||||
		let that = this
 | 
			
		||||
		teaweb.popup("/servers/components/waf/ipadmin/createIPPopup?firewallPolicyId=" + this.firewallPolicyId + '&type=' + type, {
 | 
			
		||||
			height: "23em",
 | 
			
		||||
			callback: function () {
 | 
			
		||||
				window.location = "/servers/components/waf/ipadmin/lists?firewallPolicyId=" + this.firewallPolicyId + "&type=" + type
 | 
			
		||||
				teaweb.success("保存成功", function () {
 | 
			
		||||
					window.location = "/servers/components/waf/ipadmin/lists?firewallPolicyId=" + that.firewallPolicyId + "&type=" + type
 | 
			
		||||
				})
 | 
			
		||||
			}
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -4,6 +4,8 @@
 | 
			
		||||
 | 
			
		||||
<second-menu style="margin-top: -1em">
 | 
			
		||||
    <span class="item">ID: {{listId}}   <tip-icon content="ID可以用于使用API操作此IP名单"></tip-icon></span>
 | 
			
		||||
    <span class="item disabled">|</span>
 | 
			
		||||
    <div class="item"><ip-list-bind-box :v-http-firewall-policy-id="firewallPolicyId" :v-type="type"></ip-list-bind-box></div>
 | 
			
		||||
</second-menu>
 | 
			
		||||
 | 
			
		||||
<p class="comment" v-if="items.length == 0">暂时还没有IP。</p>
 | 
			
		||||
 
 | 
			
		||||
@@ -26,10 +26,13 @@ Tea.context(function () {
 | 
			
		||||
	 * 添加IP名单菜单
 | 
			
		||||
	 */
 | 
			
		||||
	this.createIP = function (type) {
 | 
			
		||||
		let that = this
 | 
			
		||||
		teaweb.popup("/servers/components/waf/ipadmin/createIPPopup?firewallPolicyId=" + this.firewallPolicyId + '&type=' + type, {
 | 
			
		||||
			height: "26em",
 | 
			
		||||
			callback: function () {
 | 
			
		||||
				window.location = "/servers/components/waf/ipadmin/lists?firewallPolicyId=" + this.firewallPolicyId + "&type=" + type
 | 
			
		||||
				teaweb.success("保存成功", function () {
 | 
			
		||||
					window.location = "/servers/components/waf/ipadmin/lists?firewallPolicyId=" + that.firewallPolicyId + "&type=" + type
 | 
			
		||||
				})
 | 
			
		||||
			}
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -42,10 +42,13 @@ Tea.context(function () {
 | 
			
		||||
	 * 添加IP名单菜单
 | 
			
		||||
	 */
 | 
			
		||||
	this.createIP = function (type) {
 | 
			
		||||
		let that = this
 | 
			
		||||
		teaweb.popup("/servers/components/waf/ipadmin/createIPPopup?firewallPolicyId=" + this.firewallPolicyId + '&type=' + type, {
 | 
			
		||||
			height: "23em",
 | 
			
		||||
			callback: function () {
 | 
			
		||||
				window.location = "/servers/components/waf/ipadmin/lists?firewallPolicyId=" + this.firewallPolicyId + "&type=" + type
 | 
			
		||||
				teaweb.success("保存成功", function () {
 | 
			
		||||
					window.location = "/servers/components/waf/ipadmin/lists?firewallPolicyId=" + that.firewallPolicyId + "&type=" + type
 | 
			
		||||
				})
 | 
			
		||||
			}
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -37,10 +37,13 @@ Tea.context(function () {
 | 
			
		||||
	 * 添加IP名单菜单
 | 
			
		||||
	 */
 | 
			
		||||
	this.createIP = function (type) {
 | 
			
		||||
		let that = this
 | 
			
		||||
		teaweb.popup("/servers/components/waf/ipadmin/createIPPopup?firewallPolicyId=" + this.firewallPolicyId + '&type=' + type, {
 | 
			
		||||
			height: "26em",
 | 
			
		||||
			callback: function () {
 | 
			
		||||
                window.location = "/servers/components/waf/ipadmin/lists?firewallPolicyId=" + this.firewallPolicyId + "&type=" + type
 | 
			
		||||
				teaweb.success("保存成功", function () {
 | 
			
		||||
					window.location = "/servers/components/waf/ipadmin/lists?firewallPolicyId=" + that.firewallPolicyId + "&type=" + type
 | 
			
		||||
				})
 | 
			
		||||
			}
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										10
									
								
								web/views/@default/servers/iplists/@list_menu.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								web/views/@default/servers/iplists/@list_menu.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,10 @@
 | 
			
		||||
<first-menu>
 | 
			
		||||
    <menu-item :href="'/servers/iplists?type=' + list.type">{{list.typeName}}</menu-item>
 | 
			
		||||
    <span class="disabled item">|</span>
 | 
			
		||||
    <menu-item :href="'/servers/iplists/list?listId=' + list.id" code="list">"{{list.name}}"详情</menu-item>
 | 
			
		||||
    <menu-item :href="'/servers/iplists/items?listId=' + list.id" code="item">IP({{list.countItems}})</menu-item>
 | 
			
		||||
    <menu-item :href="'/servers/iplists/update?listId=' + list.id" code="update">修改</menu-item>
 | 
			
		||||
    <menu-item :href="'/servers/iplists/test?listId=' + list.id" code="test">IP检查</menu-item>
 | 
			
		||||
    <menu-item :href="'/servers/iplists/export?listId=' + list.id" code="export">导出</menu-item>
 | 
			
		||||
    <menu-item :href="'/servers/iplists/import?listId=' + list.id" code="import">导入</menu-item>
 | 
			
		||||
</first-menu>
 | 
			
		||||
							
								
								
									
										8
									
								
								web/views/@default/servers/iplists/@menu.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								web/views/@default/servers/iplists/@menu.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,8 @@
 | 
			
		||||
<first-menu>
 | 
			
		||||
    <menu-item href="/servers/iplists" :active="type == 'black'">黑名单</menu-item>
 | 
			
		||||
    <menu-item href="/servers/iplists?type=white" :active="type == 'white'">白名单</menu-item>
 | 
			
		||||
    <span class="item disabled">|</span>
 | 
			
		||||
    <menu-item @click.prevent="createList">[创建]</menu-item>
 | 
			
		||||
    <span class="item disabled">|</span>
 | 
			
		||||
    <span class="item"><tip-icon content="可以在WAF策略里直接引用这些公用名单。"></tip-icon></span>
 | 
			
		||||
</first-menu>
 | 
			
		||||
@@ -0,0 +1,38 @@
 | 
			
		||||
{$layout "layout_popup"}
 | 
			
		||||
 | 
			
		||||
<h3>绑定公用IP名单</h3>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
<p class="comment" v-if="lists.length == 0">暂时还没有可用的公用IP名单。</p>
 | 
			
		||||
 | 
			
		||||
<table class="ui table selectable celled" v-if="lists.length > 0">
 | 
			
		||||
    <thead>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <th class="two wide">ID</th>
 | 
			
		||||
        <th>名称</th>
 | 
			
		||||
        <th class="two wide">类型</th>
 | 
			
		||||
        <th>备注</th>
 | 
			
		||||
        <th class="two wide">IP数量</th>
 | 
			
		||||
        <th class="two op">操作</th>
 | 
			
		||||
    </tr>
 | 
			
		||||
    </thead>
 | 
			
		||||
    <tr v-for="list in lists">
 | 
			
		||||
        <td>{{list.id}}</td>
 | 
			
		||||
        <td>{{list.name}}</td>
 | 
			
		||||
        <td>
 | 
			
		||||
            <span v-if="list.type == 'black'">黑名单</span>
 | 
			
		||||
            <span v-if="list.type == 'white'">白名单</span>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td>{{list.description}}</td>
 | 
			
		||||
        <td>
 | 
			
		||||
            <span v-if="list.countItems > 0">{{list.countItems}}</span>
 | 
			
		||||
            <span v-else class="disabled">0</span>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td>
 | 
			
		||||
            <a href="" @click.prevent="bind(list)" v-if="!list.isSelected">绑定</a>
 | 
			
		||||
            <a href="" style="color: grey" @click.prevent="unbind(list)" v-if="list.isSelected">已绑定</a>
 | 
			
		||||
        </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
</table>
 | 
			
		||||
 | 
			
		||||
<div class="page" v-html="page"></div>
 | 
			
		||||
							
								
								
									
										23
									
								
								web/views/@default/servers/iplists/bindHTTPFirewallPopup.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								web/views/@default/servers/iplists/bindHTTPFirewallPopup.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,23 @@
 | 
			
		||||
Tea.context(function () {
 | 
			
		||||
	this.bind = function (list) {
 | 
			
		||||
		this.$post("$")
 | 
			
		||||
			.params({
 | 
			
		||||
				httpFirewallPolicyId: this.httpFirewallPolicyId,
 | 
			
		||||
				listId: list.id
 | 
			
		||||
			})
 | 
			
		||||
			.success(function () {
 | 
			
		||||
				list.isSelected = true
 | 
			
		||||
			})
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	this.unbind = function (list) {
 | 
			
		||||
		this.$post(".unbindHTTPFirewall")
 | 
			
		||||
			.params({
 | 
			
		||||
				httpFirewallPolicyId: this.httpFirewallPolicyId,
 | 
			
		||||
				listId: list.id
 | 
			
		||||
			})
 | 
			
		||||
			.success(function () {
 | 
			
		||||
				list.isSelected = false
 | 
			
		||||
			})
 | 
			
		||||
	}
 | 
			
		||||
})
 | 
			
		||||
							
								
								
									
										76
									
								
								web/views/@default/servers/iplists/createIPPopup.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								web/views/@default/servers/iplists/createIPPopup.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,76 @@
 | 
			
		||||
{$layout "layout_popup"}
 | 
			
		||||
 | 
			
		||||
<h3>添加IP</h3>
 | 
			
		||||
 | 
			
		||||
<form method="post" class="ui form" data-tea-action="$" data-tea-success="success">
 | 
			
		||||
	<input type="hidden" name="listId" :value="listId"/>
 | 
			
		||||
	<csrf-token></csrf-token>
 | 
			
		||||
	<table class="ui table definition selectable">
 | 
			
		||||
        <tr>
 | 
			
		||||
            <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>
 | 
			
		||||
                    <input type="text" name="ipFrom" maxlength="64" placeholder="x.x.x.x" ref="focus"/>
 | 
			
		||||
                </td>
 | 
			
		||||
            </tr>
 | 
			
		||||
            <tr>
 | 
			
		||||
                <td>结束IP</td>
 | 
			
		||||
                <td>
 | 
			
		||||
                    <input type="text" name="ipTo" maxlength="64" placeholder="x.x.x.x"/>
 | 
			
		||||
                    <p class="comment">表示IP段的时候需要填写此项。</p>
 | 
			
		||||
                </td>
 | 
			
		||||
            </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>
 | 
			
		||||
            <td>级别</td>
 | 
			
		||||
            <td>
 | 
			
		||||
                <firewall-event-level-options :v-value="eventLevel"></firewall-event-level-options>
 | 
			
		||||
            </td>
 | 
			
		||||
        </tr>
 | 
			
		||||
 | 
			
		||||
		<tr>
 | 
			
		||||
			<td colspan="2"><more-options-indicator></more-options-indicator></td>
 | 
			
		||||
		</tr>
 | 
			
		||||
		<tbody v-show="moreOptionsVisible">
 | 
			
		||||
			<tr>
 | 
			
		||||
				<td>过期时间</td>
 | 
			
		||||
				<td>
 | 
			
		||||
					<datetime-input :v-name="'expiredAt'"></datetime-input>
 | 
			
		||||
					<p class="comment">在加入名单某一段时间后会失效,留空表示永久有效。</p>
 | 
			
		||||
				</td>
 | 
			
		||||
			</tr>
 | 
			
		||||
			<tr>
 | 
			
		||||
				<td>备注</td>
 | 
			
		||||
				<td><input type="text" name="reason" maxlength="100"/></td>
 | 
			
		||||
			</tr>
 | 
			
		||||
		</tbody>
 | 
			
		||||
	</table>
 | 
			
		||||
	<submit-btn></submit-btn>
 | 
			
		||||
</form>
 | 
			
		||||
							
								
								
									
										4
									
								
								web/views/@default/servers/iplists/createIPPopup.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								web/views/@default/servers/iplists/createIPPopup.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,4 @@
 | 
			
		||||
Tea.context(function () {
 | 
			
		||||
    this.type = "ipv4"
 | 
			
		||||
    this.eventLevel = (this.listType == "white") ? "debug" : "critical"
 | 
			
		||||
})
 | 
			
		||||
							
								
								
									
										4
									
								
								web/views/@default/servers/iplists/createPopup.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								web/views/@default/servers/iplists/createPopup.css
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,4 @@
 | 
			
		||||
h3 var {
 | 
			
		||||
  font-style: normal;
 | 
			
		||||
}
 | 
			
		||||
/*# sourceMappingURL=createPopup.css.map */
 | 
			
		||||
							
								
								
									
										1
									
								
								web/views/@default/servers/iplists/createPopup.css.map
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								web/views/@default/servers/iplists/createPopup.css.map
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
			
		||||
{"version":3,"sources":["createPopup.less"],"names":[],"mappings":"AAAA,EACC;EACC,kBAAA","file":"createPopup.css"}
 | 
			
		||||
							
								
								
									
										31
									
								
								web/views/@default/servers/iplists/createPopup.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								web/views/@default/servers/iplists/createPopup.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,31 @@
 | 
			
		||||
{$layout "layout_popup"}
 | 
			
		||||
 | 
			
		||||
<h3>创建<var v-if="type == 'black'">黑名单</var><var v-if="type == 'white'">白名单</var></h3>
 | 
			
		||||
 | 
			
		||||
<form class="ui form" data-tea-action="$" data-tea-success="success">
 | 
			
		||||
    <csrf-token></csrf-token>
 | 
			
		||||
    <table class="ui table definition selectable">
 | 
			
		||||
        <tr>
 | 
			
		||||
            <td class="title">名称 *</td>
 | 
			
		||||
            <td>
 | 
			
		||||
                <input type="text" name="name" maxlength="100" ref="focus"/>
 | 
			
		||||
            </td>
 | 
			
		||||
        </tr>
 | 
			
		||||
        <tr>
 | 
			
		||||
            <td>类型</td>
 | 
			
		||||
            <td>
 | 
			
		||||
                <select class="ui dropdown auto-width" name="type" v-model="type">
 | 
			
		||||
                    <option value="black">黑名单</option>
 | 
			
		||||
                    <option value="white">白名单</option>
 | 
			
		||||
                </select>
 | 
			
		||||
            </td>
 | 
			
		||||
        </tr>
 | 
			
		||||
        <tr>
 | 
			
		||||
            <td>备注</td>
 | 
			
		||||
            <td>
 | 
			
		||||
                <textarea name="description" rows="2" maxlength="200"></textarea>
 | 
			
		||||
            </td>
 | 
			
		||||
        </tr>
 | 
			
		||||
    </table>
 | 
			
		||||
    <submit-btn></submit-btn>
 | 
			
		||||
</form>
 | 
			
		||||
							
								
								
									
										5
									
								
								web/views/@default/servers/iplists/createPopup.less
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								web/views/@default/servers/iplists/createPopup.less
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
			
		||||
h3 {
 | 
			
		||||
	var {
 | 
			
		||||
		font-style: normal;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										13
									
								
								web/views/@default/servers/iplists/export.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								web/views/@default/servers/iplists/export.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
			
		||||
{$layout}
 | 
			
		||||
{$template "list_menu"}
 | 
			
		||||
 | 
			
		||||
<div class="margin"></div>
 | 
			
		||||
<form class="ui form">
 | 
			
		||||
    <table class="ui table definition selectable">
 | 
			
		||||
        <tr>
 | 
			
		||||
            <td class="title">说明</td>
 | 
			
		||||
            <td>导出所有的IP</td>
 | 
			
		||||
        </tr>
 | 
			
		||||
    </table>
 | 
			
		||||
    <a :href="'/servers/iplists/exportData?listId=' + list.id" class="ui button primary">导出</a>
 | 
			
		||||
</form>
 | 
			
		||||
							
								
								
									
										19
									
								
								web/views/@default/servers/iplists/import.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								web/views/@default/servers/iplists/import.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,19 @@
 | 
			
		||||
{$layout}
 | 
			
		||||
{$template "list_menu"}
 | 
			
		||||
 | 
			
		||||
<div class="margin"></div>
 | 
			
		||||
 | 
			
		||||
<form class="ui form" data-tea-action="$"  data-tea-success="success">
 | 
			
		||||
    <input type="hidden" name="listId" :value="list.id"/>
 | 
			
		||||
    <csrf-token></csrf-token>
 | 
			
		||||
    <table class="ui table definition selectable">
 | 
			
		||||
        <tr>
 | 
			
		||||
            <td class="title">选择IP文件 *</td>
 | 
			
		||||
            <td>
 | 
			
		||||
                <input type="file" name="file" accept=".data"/>
 | 
			
		||||
                <p class="comment">文件名类似于<code-label>ip-list-123.data</code-label>。</p>
 | 
			
		||||
            </td>
 | 
			
		||||
        </tr>
 | 
			
		||||
    </table>
 | 
			
		||||
    <submit-btn></submit-btn>
 | 
			
		||||
</form>
 | 
			
		||||
							
								
								
									
										7
									
								
								web/views/@default/servers/iplists/import.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								web/views/@default/servers/iplists/import.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,7 @@
 | 
			
		||||
Tea.context(function () {
 | 
			
		||||
	this.success = function (resp) {
 | 
			
		||||
		teaweb.success("成功导入" + resp.data.count + "个IP", function () {
 | 
			
		||||
			teaweb.reload()
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
})
 | 
			
		||||
							
								
								
									
										38
									
								
								web/views/@default/servers/iplists/index.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								web/views/@default/servers/iplists/index.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,38 @@
 | 
			
		||||
{$layout}
 | 
			
		||||
{$template "menu"}
 | 
			
		||||
 | 
			
		||||
<tip-message-box code="iplist-public-tip">这里是公用的IP名单,可以在WAF策略里直接引用。</tip-message-box>
 | 
			
		||||
 | 
			
		||||
<p class="comment" v-if="lists.length == 0">暂时还没有公用IP名单。</p>
 | 
			
		||||
 | 
			
		||||
<table class="ui table selectable celled" v-if="lists.length > 0">
 | 
			
		||||
    <thead>
 | 
			
		||||
        <tr>
 | 
			
		||||
            <th class="one wide">ID</th>
 | 
			
		||||
            <th>名称</th>
 | 
			
		||||
            <th class="one wide">类型</th>
 | 
			
		||||
            <th>备注</th>
 | 
			
		||||
            <th class="one wide">IP数量</th>
 | 
			
		||||
            <th class="two op">操作</th>
 | 
			
		||||
        </tr>
 | 
			
		||||
    </thead>
 | 
			
		||||
    <tr v-for="list in lists">
 | 
			
		||||
        <td>{{list.id}}</td>
 | 
			
		||||
        <td>{{list.name}}</td>
 | 
			
		||||
        <td>
 | 
			
		||||
            <span v-if="list.type == 'black'">黑名单</span>
 | 
			
		||||
            <span v-if="list.type == 'white'">白名单</span>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td>{{list.description}}</td>
 | 
			
		||||
        <td>
 | 
			
		||||
            <span v-if="list.countItems > 0">{{list.countItems}}</span>
 | 
			
		||||
            <span v-else class="disabled">0</span>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td>
 | 
			
		||||
            <a :href="'/servers/iplists/list?listId=' + list.id">详情</a>  
 | 
			
		||||
            <a href="" @click.prevent="deleteList(list.id)">删除</a>
 | 
			
		||||
        </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
</table>
 | 
			
		||||
 | 
			
		||||
<div class="page" v-html="page"></div>
 | 
			
		||||
							
								
								
									
										26
									
								
								web/views/@default/servers/iplists/index.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								web/views/@default/servers/iplists/index.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,26 @@
 | 
			
		||||
Tea.context(function () {
 | 
			
		||||
	this.createList = function () {
 | 
			
		||||
		teaweb.popup(Tea.url(".createPopup", {type: this.type}), {
 | 
			
		||||
			callback: function (resp) {
 | 
			
		||||
				teaweb.success("保存成功", function () {
 | 
			
		||||
					window.location = "/servers/iplists?type=" + resp.data.list.type
 | 
			
		||||
				})
 | 
			
		||||
			}
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	this.deleteList = function (listId) {
 | 
			
		||||
		let that = this
 | 
			
		||||
		teaweb.confirm("确定要删除此IP名单吗?", function () {
 | 
			
		||||
			that.$post(".delete")
 | 
			
		||||
				.params({
 | 
			
		||||
					listId: listId
 | 
			
		||||
				})
 | 
			
		||||
				.success(function () {
 | 
			
		||||
					teaweb.success("删除成功", function () {
 | 
			
		||||
						teaweb.reload()
 | 
			
		||||
					})
 | 
			
		||||
				})
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
})
 | 
			
		||||
							
								
								
									
										12
									
								
								web/views/@default/servers/iplists/items.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								web/views/@default/servers/iplists/items.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,12 @@
 | 
			
		||||
{$layout}
 | 
			
		||||
{$template "list_menu"}
 | 
			
		||||
 | 
			
		||||
<second-menu>
 | 
			
		||||
    <menu-item @click.prevent="createIP">[创建IP]</menu-item>
 | 
			
		||||
</second-menu>
 | 
			
		||||
 | 
			
		||||
<p class="comment" v-if="items.length == 0">暂时还没有IP。</p>
 | 
			
		||||
 | 
			
		||||
<ip-list-table v-if="items.length > 0" :v-items="items" @update-item="updateItem" @delete-item="deleteItem"></ip-list-table>
 | 
			
		||||
 | 
			
		||||
<div class="page" v-html="page"></div>
 | 
			
		||||
							
								
								
									
										37
									
								
								web/views/@default/servers/iplists/items.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								web/views/@default/servers/iplists/items.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,37 @@
 | 
			
		||||
Tea.context(function () {
 | 
			
		||||
	this.updateItem = function (itemId) {
 | 
			
		||||
		teaweb.popup(Tea.url(".updateIPPopup", {itemId: itemId}), {
 | 
			
		||||
			height: "26em",
 | 
			
		||||
			callback: function () {
 | 
			
		||||
				teaweb.success("保存成功", function () {
 | 
			
		||||
					teaweb.reload()
 | 
			
		||||
				})
 | 
			
		||||
			}
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	this.deleteItem = function (itemId) {
 | 
			
		||||
		let that = this
 | 
			
		||||
		teaweb.confirm("确定要删除这个IP吗?", function () {
 | 
			
		||||
			that.$post(".deleteIP")
 | 
			
		||||
				.params({
 | 
			
		||||
					"itemId": itemId
 | 
			
		||||
				})
 | 
			
		||||
				.refresh()
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 添加IP名单菜单
 | 
			
		||||
	 */
 | 
			
		||||
	this.createIP = function () {
 | 
			
		||||
		teaweb.popup(Tea.url(".createIPPopup", {listId: this.list.id}), {
 | 
			
		||||
			height: "23em",
 | 
			
		||||
			callback: function () {
 | 
			
		||||
				teaweb.success("保存成功", function () {
 | 
			
		||||
					teaweb.reload()
 | 
			
		||||
				})
 | 
			
		||||
			}
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
})
 | 
			
		||||
							
								
								
									
										24
									
								
								web/views/@default/servers/iplists/list.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								web/views/@default/servers/iplists/list.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,24 @@
 | 
			
		||||
{$layout}
 | 
			
		||||
{$template "list_menu"}
 | 
			
		||||
 | 
			
		||||
<table class="ui table definition selectable">
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td class="title">名称</td>
 | 
			
		||||
        <td>
 | 
			
		||||
            {{list.name}}
 | 
			
		||||
        </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td>类型</td>
 | 
			
		||||
        <td>
 | 
			
		||||
            {{list.typeName}}
 | 
			
		||||
        </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td>备注</td>
 | 
			
		||||
        <td>
 | 
			
		||||
            <span v-if="list.description.length > 0">{{list.description}}</span>
 | 
			
		||||
            <span v-else class="disabled">-</span>
 | 
			
		||||
        </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
</table>
 | 
			
		||||
							
								
								
									
										39
									
								
								web/views/@default/servers/iplists/test.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								web/views/@default/servers/iplists/test.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,39 @@
 | 
			
		||||
{$layout}
 | 
			
		||||
{$template "list_menu"}
 | 
			
		||||
<form method="post" class="ui form" data-tea-action="$" data-tea-success="success">
 | 
			
		||||
    <csrf-token></csrf-token>
 | 
			
		||||
    <input type="hidden" name="listId" :value="list.id"/>
 | 
			
		||||
    <table class="ui table selectable definition">
 | 
			
		||||
        <tr>
 | 
			
		||||
            <td class="title">IP *</td>
 | 
			
		||||
            <td>
 | 
			
		||||
                <input type="text" name="ip" class="text" maxlength="100" ref="focus" placeholder="x.x.x.x" v-model="ip"/>
 | 
			
		||||
                <p class="comment">要检查的IP</p>
 | 
			
		||||
            </td>
 | 
			
		||||
        </tr>
 | 
			
		||||
        <tr>
 | 
			
		||||
            <td>检查结果</td>
 | 
			
		||||
            <td>
 | 
			
		||||
                <div v-if="result.isDone">
 | 
			
		||||
                    <div v-if="!result.isOk">
 | 
			
		||||
                        <span class="red">{{result.error}}</span>
 | 
			
		||||
                    </div>
 | 
			
		||||
                    <div v-if="result.isFound">
 | 
			
		||||
                        <div v-if="result.item != null">
 | 
			
		||||
                            <div v-if="result.isAllowed">
 | 
			
		||||
                                <span class="green">在白名单中 <ip-item-text :v-item="result.item"></ip-item-text> <a href="" @click.prevent="updateItem(result.list.id, result.item.id)" title="查看和修改"><i class="icon pencil small"></i></a></span>
 | 
			
		||||
                            </div>
 | 
			
		||||
                            <div v-else>
 | 
			
		||||
                                <span class="red">在黑名单中 <ip-item-text :v-item="result.item"></ip-item-text> <a href="" @click.prevent="updateItem(result.item.id)" title="查看和修改"><i class="icon pencil small"></i></a></span>
 | 
			
		||||
                            </div>
 | 
			
		||||
                        </div>
 | 
			
		||||
                    </div>
 | 
			
		||||
                    <div v-if="!result.isFound">
 | 
			
		||||
                        没有找到和{{ip}}匹配的配置。
 | 
			
		||||
                    </div>
 | 
			
		||||
                </div>
 | 
			
		||||
            </td>
 | 
			
		||||
        </tr>
 | 
			
		||||
    </table>
 | 
			
		||||
    <submit-btn>检查IP状态</submit-btn>
 | 
			
		||||
</form>
 | 
			
		||||
							
								
								
									
										33
									
								
								web/views/@default/servers/iplists/test.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								web/views/@default/servers/iplists/test.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,33 @@
 | 
			
		||||
Tea.context(function () {
 | 
			
		||||
	this.ip = ""
 | 
			
		||||
	this.result = {
 | 
			
		||||
		isDone: false,
 | 
			
		||||
		isOk: false,
 | 
			
		||||
		isFound: false,
 | 
			
		||||
		isAllowed: false,
 | 
			
		||||
		error: "",
 | 
			
		||||
		ipItem: null,
 | 
			
		||||
		ipList: null
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	this.$delay(function () {
 | 
			
		||||
		this.$watch("ip", function () {
 | 
			
		||||
			this.result.isDone = false
 | 
			
		||||
		})
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	this.success = function (resp) {
 | 
			
		||||
		this.result = resp.data.result
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	this.updateItem = function (itemId) {
 | 
			
		||||
		teaweb.popup(Tea.url(".updateIPPopup", {itemId: itemId}), {
 | 
			
		||||
			height: "26em",
 | 
			
		||||
			callback: function () {
 | 
			
		||||
				teaweb.success("保存成功", function () {
 | 
			
		||||
					teaweb.reload()
 | 
			
		||||
				})
 | 
			
		||||
			}
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
})
 | 
			
		||||
							
								
								
									
										28
									
								
								web/views/@default/servers/iplists/update.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								web/views/@default/servers/iplists/update.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,28 @@
 | 
			
		||||
{$layout}
 | 
			
		||||
{$template "list_menu"}
 | 
			
		||||
 | 
			
		||||
<form class="ui form" data-tea-action="$" data-tea-success="success">
 | 
			
		||||
    <input type="hidden" name="listId" :value="list.id"/>
 | 
			
		||||
    <csrf-token></csrf-token>
 | 
			
		||||
    <table class="ui table definition selectable">
 | 
			
		||||
        <tr>
 | 
			
		||||
            <td class="title">名称 *</td>
 | 
			
		||||
            <td>
 | 
			
		||||
                <input type="text" name="name" maxlength="100" ref="focus" v-model="list.name"/>
 | 
			
		||||
            </td>
 | 
			
		||||
        </tr>
 | 
			
		||||
        <tr>
 | 
			
		||||
            <td>类型</td>
 | 
			
		||||
            <td>
 | 
			
		||||
                {{list.typeName}}
 | 
			
		||||
            </td>
 | 
			
		||||
        </tr>
 | 
			
		||||
        <tr>
 | 
			
		||||
            <td>备注</td>
 | 
			
		||||
            <td>
 | 
			
		||||
                <textarea name="description" rows="2" maxlength="200" v-model="list.description"></textarea>
 | 
			
		||||
            </td>
 | 
			
		||||
        </tr>
 | 
			
		||||
    </table>
 | 
			
		||||
    <submit-btn></submit-btn>
 | 
			
		||||
</form>
 | 
			
		||||
							
								
								
									
										3
									
								
								web/views/@default/servers/iplists/update.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								web/views/@default/servers/iplists/update.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
			
		||||
Tea.context(function () {
 | 
			
		||||
	this.success = NotifyReloadSuccess("保存成功")
 | 
			
		||||
})
 | 
			
		||||
							
								
								
									
										76
									
								
								web/views/@default/servers/iplists/updateIPPopup.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								web/views/@default/servers/iplists/updateIPPopup.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,76 @@
 | 
			
		||||
{$layout "layout_popup"}
 | 
			
		||||
 | 
			
		||||
<h3>修改IP</h3>
 | 
			
		||||
 | 
			
		||||
<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="type" :value="item.type"/>
 | 
			
		||||
	<csrf-token></csrf-token>
 | 
			
		||||
	<table class="ui table definition selectable">
 | 
			
		||||
        <tr>
 | 
			
		||||
            <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>
 | 
			
		||||
                <input type="text" name="ipFrom" maxlength="64" placeholder="x.x.x.x" ref="focus" v-model="item.ipFrom"/>
 | 
			
		||||
            </td>
 | 
			
		||||
        </tr>
 | 
			
		||||
        <tr>
 | 
			
		||||
            <td>结束IP</td>
 | 
			
		||||
            <td>
 | 
			
		||||
                <input type="text" name="ipTo" maxlength="64" placeholder="x.x.x.x" v-model="item.ipTo"/>
 | 
			
		||||
                <p class="comment">表示IP段的时候需要填写此项。</p>
 | 
			
		||||
            </td>
 | 
			
		||||
        </tr>
 | 
			
		||||
        </tbody>
 | 
			
		||||
 | 
			
		||||
        <tr>
 | 
			
		||||
            <td>级别</td>
 | 
			
		||||
            <td>
 | 
			
		||||
                <firewall-event-level-options :v-value="item.eventLevel"></firewall-event-level-options>
 | 
			
		||||
            </td>
 | 
			
		||||
        </tr>
 | 
			
		||||
 | 
			
		||||
        <!-- 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>
 | 
			
		||||
			<td colspan="2"><more-options-indicator></more-options-indicator></td>
 | 
			
		||||
		</tr>
 | 
			
		||||
		<tbody v-show="moreOptionsVisible">
 | 
			
		||||
			<tr>
 | 
			
		||||
				<td>过期时间</td>
 | 
			
		||||
				<td>
 | 
			
		||||
					<datetime-input :v-name="'expiredAt'" :v-timestamp="item.expiredAt"></datetime-input>
 | 
			
		||||
					<p class="comment">在加入名单某一段时间后会失效,留空表示永久有效。</p>
 | 
			
		||||
				</td>
 | 
			
		||||
			</tr>
 | 
			
		||||
			<tr>
 | 
			
		||||
				<td>备注</td>
 | 
			
		||||
				<td><input type="text" name="reason" maxlength="100" v-model="item.reason"/></td>
 | 
			
		||||
			</tr>
 | 
			
		||||
		</tbody>
 | 
			
		||||
	</table>
 | 
			
		||||
	<submit-btn></submit-btn>
 | 
			
		||||
</form>
 | 
			
		||||
@@ -11,6 +11,8 @@
 | 
			
		||||
        <menu-item @click.prevent="createIP('white')">添加IP</menu-item>
 | 
			
		||||
        <span class="item">|</span>
 | 
			
		||||
        <span class="item">ID: {{listId}}   <tip-icon content="ID可以用于使用API操作此IP名单"></tip-icon></span>
 | 
			
		||||
        <span class="item">|</span>
 | 
			
		||||
        <div class="item"><ip-list-bind-box :v-http-firewall-policy-id="firewallPolicyId" :v-type="'white'"></ip-list-bind-box></div>
 | 
			
		||||
    </second-menu>
 | 
			
		||||
 | 
			
		||||
    <p class="ui message warning" v-if="!wafIsOn">当前WAF未启用,设置将在<a :href="'/servers/server/settings/waf?serverId=' + serverId">[启用]</a>后生效。</p>
 | 
			
		||||
 
 | 
			
		||||
@@ -29,7 +29,9 @@ Tea.context(function () {
 | 
			
		||||
		teaweb.popup("/servers/server/settings/waf/ipadmin/createIPPopup?listId=" + this.listId + '&type=' + type, {
 | 
			
		||||
			height: "26em",
 | 
			
		||||
			callback: function () {
 | 
			
		||||
				window.location.reload()
 | 
			
		||||
				teaweb.success("保存成功", function () {
 | 
			
		||||
					teaweb.reload()
 | 
			
		||||
				})
 | 
			
		||||
			}
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -56,10 +56,13 @@ Tea.context(function () {
 | 
			
		||||
	 * 添加IP名单菜单
 | 
			
		||||
	 */
 | 
			
		||||
	this.createIP = function (type) {
 | 
			
		||||
		let that = this
 | 
			
		||||
		teaweb.popup("/servers/components/waf/ipadmin/createIPPopup?firewallPolicyId=" + this.firewallPolicyId + '&type=' + type, {
 | 
			
		||||
			height: "30em",
 | 
			
		||||
			callback: function () {
 | 
			
		||||
				window.location = "/servers/components/waf/ipadmin/lists?firewallPolicyId=" + this.firewallPolicyId + "&type=" + type
 | 
			
		||||
				teaweb.success("保存成功", function () {
 | 
			
		||||
					window.location = "/servers/components/waf/ipadmin/lists?firewallPolicyId=" + that.firewallPolicyId + "&type=" + type
 | 
			
		||||
				})
 | 
			
		||||
			}
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -11,6 +11,8 @@
 | 
			
		||||
        <menu-item @click.prevent="createIP('black')">添加IP</menu-item>
 | 
			
		||||
        <span class="item">|</span>
 | 
			
		||||
        <span class="item">ID: {{listId}}   <tip-icon content="ID可以用于使用API操作此IP名单"></tip-icon></span>
 | 
			
		||||
        <span class="item">|</span>
 | 
			
		||||
        <div class="item"><ip-list-bind-box :v-http-firewall-policy-id="firewallPolicyId" :v-type="'black'"></ip-list-bind-box></div>
 | 
			
		||||
    </second-menu>
 | 
			
		||||
 | 
			
		||||
    <p class="ui message warning" v-if="!wafIsOn">当前WAF未启用,设置将在<a :href="'/servers/server/settings/waf?serverId=' + serverId">[启用]</a>后生效。</p>
 | 
			
		||||
 
 | 
			
		||||
@@ -29,7 +29,9 @@ Tea.context(function () {
 | 
			
		||||
		teaweb.popup("/servers/server/settings/waf/ipadmin/createIPPopup?listId=" + this.listId + '&type=' + type, {
 | 
			
		||||
			height: "26em",
 | 
			
		||||
			callback: function () {
 | 
			
		||||
				window.location.reload()
 | 
			
		||||
				teaweb.success("保存成功", function () {
 | 
			
		||||
					teaweb.reload()
 | 
			
		||||
				})
 | 
			
		||||
			}
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -42,10 +42,13 @@ Tea.context(function () {
 | 
			
		||||
	 * 添加IP名单菜单
 | 
			
		||||
	 */
 | 
			
		||||
	this.createIP = function (type) {
 | 
			
		||||
		let that = this
 | 
			
		||||
		teaweb.popup("/servers/components/waf/ipadmin/createIPPopup?firewallPolicyId=" + this.firewallPolicyId + '&type=' + type, {
 | 
			
		||||
			height: "30em",
 | 
			
		||||
			callback: function () {
 | 
			
		||||
				window.location = "/servers/components/waf/ipadmin/lists?firewallPolicyId=" + this.firewallPolicyId + "&type=" + type
 | 
			
		||||
				teaweb.success("保存成功", function () {
 | 
			
		||||
					window.location = "/servers/components/waf/ipadmin/lists?firewallPolicyId=" + that.firewallPolicyId + "&type=" + type
 | 
			
		||||
				})
 | 
			
		||||
			}
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,7 @@
 | 
			
		||||
.chart-box {
 | 
			
		||||
  height: 20em;
 | 
			
		||||
}
 | 
			
		||||
h4 span.small {
 | 
			
		||||
  font-size: 0.8em;
 | 
			
		||||
}
 | 
			
		||||
/*# sourceMappingURL=clients.css.map */
 | 
			
		||||
@@ -1 +1 @@
 | 
			
		||||
{"version":3,"sources":["clients.less"],"names":[],"mappings":"AAAA;EACC,YAAA","file":"clients.css"}
 | 
			
		||||
{"version":3,"sources":["clients.less"],"names":[],"mappings":"AAAA;EACC,YAAA;;AAGD,EAAG,KAAI;EACN,gBAAA","file":"clients.css"}
 | 
			
		||||
@@ -12,10 +12,10 @@
 | 
			
		||||
        要想查看统计数据,需要先开启统计功能,<a :href="'/servers/server/settings/stat?serverId=' + serverId">[点击这里]</a>修改配置。
 | 
			
		||||
    </p>
 | 
			
		||||
    {$else}
 | 
			
		||||
    <h4>操作系统排行</h4>
 | 
			
		||||
    <h4>操作系统排行<span class="small grey">(按月)</span></h4>
 | 
			
		||||
    <div class="chart-box" id="system-chart"></div>
 | 
			
		||||
 | 
			
		||||
    <h4>浏览器排行</h4>
 | 
			
		||||
    <h4>浏览器排行<span class="small grey">(按月)</span></h4>
 | 
			
		||||
    <div class="chart-box" id="browser-chart"></div>
 | 
			
		||||
    {$end}
 | 
			
		||||
</div>
 | 
			
		||||
@@ -1,3 +1,7 @@
 | 
			
		||||
.chart-box {
 | 
			
		||||
	height: 20em;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
h4 span.small {
 | 
			
		||||
	font-size: 0.8em;
 | 
			
		||||
}
 | 
			
		||||
@@ -1,4 +1,7 @@
 | 
			
		||||
.chart-box {
 | 
			
		||||
  height: 21em;
 | 
			
		||||
}
 | 
			
		||||
h4 span.small {
 | 
			
		||||
  font-size: 0.8em;
 | 
			
		||||
}
 | 
			
		||||
/*# sourceMappingURL=dailyRequests.css.map */
 | 
			
		||||
@@ -1 +1 @@
 | 
			
		||||
{"version":3,"sources":["dailyRequests.less"],"names":[],"mappings":"AAAA;EACC,YAAA","file":"dailyRequests.css"}
 | 
			
		||||
{"version":3,"sources":["dailyRequests.less"],"names":[],"mappings":"AAAA;EACC,YAAA;;AAGD,EAAG,KAAI;EACN,gBAAA","file":"dailyRequests.css"}
 | 
			
		||||
@@ -1,3 +1,7 @@
 | 
			
		||||
.chart-box {
 | 
			
		||||
	height: 21em;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
h4 span.small {
 | 
			
		||||
	font-size: 0.8em;
 | 
			
		||||
}
 | 
			
		||||
@@ -1,4 +1,7 @@
 | 
			
		||||
.chart-box {
 | 
			
		||||
  height: 21em;
 | 
			
		||||
}
 | 
			
		||||
h4 span.small {
 | 
			
		||||
  font-size: 0.8em;
 | 
			
		||||
}
 | 
			
		||||
/*# sourceMappingURL=hourlyRequests.css.map */
 | 
			
		||||
@@ -1 +1 @@
 | 
			
		||||
{"version":3,"sources":["hourlyRequests.less"],"names":[],"mappings":"AAAA;EACC,YAAA","file":"hourlyRequests.css"}
 | 
			
		||||
{"version":3,"sources":["hourlyRequests.less"],"names":[],"mappings":"AAAA;EACC,YAAA;;AAGD,EAAG,KAAI;EACN,gBAAA","file":"hourlyRequests.css"}
 | 
			
		||||
@@ -1,3 +1,7 @@
 | 
			
		||||
.chart-box {
 | 
			
		||||
	height: 21em;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
h4 span.small {
 | 
			
		||||
	font-size: 0.8em;
 | 
			
		||||
}
 | 
			
		||||
@@ -1,4 +1,7 @@
 | 
			
		||||
.chart-box {
 | 
			
		||||
  height: 21em;
 | 
			
		||||
}
 | 
			
		||||
h4 span.small {
 | 
			
		||||
  font-size: 0.8em;
 | 
			
		||||
}
 | 
			
		||||
/*# sourceMappingURL=index.css.map */
 | 
			
		||||
@@ -1 +1 @@
 | 
			
		||||
{"version":3,"sources":["index.less"],"names":[],"mappings":"AAAA;EACC,YAAA","file":"index.css"}
 | 
			
		||||
{"version":3,"sources":["index.less"],"names":[],"mappings":"AAAA;EACC,YAAA;;AAGD,EAAG,KAAI;EACN,gBAAA","file":"index.css"}
 | 
			
		||||
@@ -1,3 +1,7 @@
 | 
			
		||||
.chart-box {
 | 
			
		||||
	height: 21em;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
h4 span.small {
 | 
			
		||||
	font-size: 0.8em;
 | 
			
		||||
}
 | 
			
		||||
@@ -1,4 +1,7 @@
 | 
			
		||||
.chart-box {
 | 
			
		||||
  height: 20em;
 | 
			
		||||
}
 | 
			
		||||
h4 span.small {
 | 
			
		||||
  font-size: 0.8em;
 | 
			
		||||
}
 | 
			
		||||
/*# sourceMappingURL=providers.css.map */
 | 
			
		||||
@@ -1 +1 @@
 | 
			
		||||
{"version":3,"sources":["providers.less"],"names":[],"mappings":"AAAA;EACC,YAAA","file":"providers.css"}
 | 
			
		||||
{"version":3,"sources":["providers.less"],"names":[],"mappings":"AAAA;EACC,YAAA;;AAGD,EAAG,KAAI;EACN,gBAAA","file":"providers.css"}
 | 
			
		||||
@@ -12,7 +12,7 @@
 | 
			
		||||
        要想查看统计数据,需要先开启统计功能,<a :href="'/servers/server/settings/stat?serverId=' + serverId">[点击这里]</a>修改配置。
 | 
			
		||||
    </p>
 | 
			
		||||
    {$else}
 | 
			
		||||
    <h4>运营商排行</h4>
 | 
			
		||||
    <h4>运营商排行<span class="small grey">(按月)</span></h4>
 | 
			
		||||
    <div class="chart-box" id="provider-chart"></div>
 | 
			
		||||
    {$end}
 | 
			
		||||
</div>
 | 
			
		||||
@@ -1,3 +1,7 @@
 | 
			
		||||
.chart-box {
 | 
			
		||||
	height: 20em;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
h4 span.small {
 | 
			
		||||
	font-size: 0.8em;
 | 
			
		||||
}
 | 
			
		||||
@@ -1,4 +1,7 @@
 | 
			
		||||
.chart-box {
 | 
			
		||||
  height: 20em;
 | 
			
		||||
}
 | 
			
		||||
/*# sourceMappingURL=index.css.map */
 | 
			
		||||
h4 span.small {
 | 
			
		||||
  font-size: 0.8em;
 | 
			
		||||
}
 | 
			
		||||
/*# sourceMappingURL=regions.css.map */
 | 
			
		||||
@@ -1 +1 @@
 | 
			
		||||
{"version":3,"sources":["index.less"],"names":[],"mappings":"AAAA;EACC,YAAA","file":"index.css"}
 | 
			
		||||
{"version":3,"sources":["regions.less"],"names":[],"mappings":"AAAA;EACC,YAAA;;AAGD,EAAG,KAAI;EACN,gBAAA","file":"regions.css"}
 | 
			
		||||
@@ -12,17 +12,17 @@
 | 
			
		||||
        要想查看统计数据,需要先开启统计功能,<a :href="'/servers/server/settings/stat?serverId=' + serverId">[点击这里]</a>修改配置。
 | 
			
		||||
    </p>
 | 
			
		||||
    {$else}
 | 
			
		||||
        <h4>地区排行</h4>
 | 
			
		||||
        <h4>地区排行<span class="small grey">(按月)</span></h4>
 | 
			
		||||
        <div class="chart-box" id="country-chart">
 | 
			
		||||
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
        <h4>省市排行</h4>
 | 
			
		||||
        <h4>省市排行<span class="small grey">(按月)</span></h4>
 | 
			
		||||
        <div class="chart-box" id="province-chart">
 | 
			
		||||
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
        <h4>城市排行</h4>
 | 
			
		||||
        <h4>城市排行<span class="small grey">(按月)</span></h4>
 | 
			
		||||
        <div class="chart-box" id="city-chart">
 | 
			
		||||
 | 
			
		||||
        </div>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,7 @@
 | 
			
		||||
.chart-box {
 | 
			
		||||
	height: 20em;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
h4 span.small {
 | 
			
		||||
	font-size: 0.8em;
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user