Compare commits
65 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d045f0526f | ||
|
|
0766ec9d5a | ||
|
|
4511b48382 | ||
|
|
151e58fbb9 | ||
|
|
c833ac2e96 | ||
|
|
99983330a3 | ||
|
|
a14e81a28f | ||
|
|
fc714a15a3 | ||
|
|
8a8f9d2912 | ||
|
|
58a0521605 | ||
|
|
e129b52f1c | ||
|
|
5cefd900a4 | ||
|
|
857dc70b4d | ||
|
|
e3036025bc | ||
|
|
76035dc3c2 | ||
|
|
22c55d0b83 | ||
|
|
9780937a1f | ||
|
|
b4eb6e92e0 | ||
|
|
245c4374b4 | ||
|
|
ed302370e9 | ||
|
|
b2feb452e0 | ||
|
|
8b7661d82d | ||
|
|
33c9cd0819 | ||
|
|
a0635a97d5 | ||
|
|
e22a9d061c | ||
|
|
1b9d62c7bd | ||
|
|
2ca31ffcb4 | ||
|
|
14636ed82f | ||
|
|
cc5a34c20e | ||
|
|
3ebb47d915 | ||
|
|
3eea58c1fc | ||
|
|
255bf58abf | ||
|
|
b5b324bca0 | ||
|
|
74e654446e | ||
|
|
be01536a09 | ||
|
|
4c6bcc7c19 | ||
|
|
98dceb20db | ||
|
|
25833bc81a | ||
|
|
0d5fc7ad85 | ||
|
|
b9af3d4757 | ||
|
|
f179b0a60e | ||
|
|
875162cfb6 | ||
|
|
2f21effdbf | ||
|
|
f7336235a1 | ||
|
|
6ed0791991 | ||
|
|
045a18fb22 | ||
|
|
dbe598a934 | ||
|
|
2812b30b01 | ||
|
|
386d4957e7 | ||
|
|
ea36e60899 | ||
|
|
bbf7e2898f | ||
|
|
beab50de4c | ||
|
|
a3ac7678d9 | ||
|
|
fc68167f77 | ||
|
|
0bb379e4cc | ||
|
|
7b350bcc37 | ||
|
|
561b4ba591 | ||
|
|
74896babb5 | ||
|
|
7f66c65770 | ||
|
|
724622f678 | ||
|
|
b52313434b | ||
|
|
c6a14708df | ||
|
|
6468605325 | ||
|
|
6c3a130afe | ||
|
|
b235b57392 |
27
README.md
27
README.md
@@ -1 +1,26 @@
|
|||||||

|
# GoEdge目标
|
||||||
|
做一款人人用得起的CDN & WAF系统。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## 特性
|
||||||
|
* `免费` - 开源、免费、自由、开放
|
||||||
|
* `简单` - 架构简单清晰,安装简单,使用简单,运维简单
|
||||||
|
* `高扩展性` - 可以自由扩展新的节点,支持亿级数据
|
||||||
|
|
||||||
|
## 文档
|
||||||
|
[点这里查看文档](https://github.com/TeaOSLab/EdgeDocs)
|
||||||
|
|
||||||
|
## 架构
|
||||||
|

|
||||||
|
|
||||||
|
其中的组件源码地址如下:
|
||||||
|
* [边缘节点](https://github.com/TeaOSLab/EdgeNode)
|
||||||
|
* [API节点](https://github.com/TeaOSLab/EdgeAPI)
|
||||||
|
* [管理平台](https://github.com/TeaOSLab/EdgeAdmin)
|
||||||
|
|
||||||
|
## 联系我们
|
||||||
|
有什么问题和建议都可以加入QQ群 `659832182`。
|
||||||
|
|
||||||
|
## 感谢
|
||||||
|
* 感谢[JetBrains公司](https://www.jetbrains.com/)提供免费的IDE开发Licence。
|
||||||
2
build/configs/.gitignore
vendored
2
build/configs/.gitignore
vendored
@@ -1,4 +1,4 @@
|
|||||||
|
api.yaml
|
||||||
server.yaml
|
server.yaml
|
||||||
api_db.yaml
|
api_db.yaml
|
||||||
api-123.yaml
|
|
||||||
*.pem
|
*.pem
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
rpc:
|
|
||||||
endpoints:
|
|
||||||
- http://192.168.2.40:8003
|
|
||||||
nodeId: H6sjDf779jimnVPnBFSgZxvr6Ca0wQ0z
|
|
||||||
secret: hMHjmEng0SIcT3yiA3HIoUjogwAC9cur
|
|
||||||
|
|
||||||
@@ -22,6 +22,7 @@ func main() {
|
|||||||
err := nodes.NewAdminNode().InstallSystemService()
|
err := nodes.NewAdminNode().InstallSystemService()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("[ERROR]install failed: " + err.Error())
|
fmt.Println("[ERROR]install failed: " + err.Error())
|
||||||
|
return
|
||||||
}
|
}
|
||||||
fmt.Println("done")
|
fmt.Println("done")
|
||||||
})
|
})
|
||||||
|
|||||||
BIN
doc/screenshot.png
Normal file
BIN
doc/screenshot.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 203 KiB |
@@ -10,15 +10,16 @@ import (
|
|||||||
type AdminModuleCode = string
|
type AdminModuleCode = string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
AdminModuleCodeServer AdminModuleCode = "server" // 网站
|
AdminModuleCodeDashboard AdminModuleCode = "dashboard" // 看板
|
||||||
AdminModuleCodeNode AdminModuleCode = "node" // 节点
|
AdminModuleCodeServer AdminModuleCode = "server" // 网站
|
||||||
AdminModuleCodeDNS AdminModuleCode = "dns" // DNS
|
AdminModuleCodeNode AdminModuleCode = "node" // 节点
|
||||||
AdminModuleCodeAdmin AdminModuleCode = "admin" // 系统用户
|
AdminModuleCodeDNS AdminModuleCode = "dns" // DNS
|
||||||
AdminModuleCodeUser AdminModuleCode = "user" // 平台用户
|
AdminModuleCodeAdmin AdminModuleCode = "admin" // 系统用户
|
||||||
AdminModuleCodeFinance AdminModuleCode = "finance" // 财务
|
AdminModuleCodeUser AdminModuleCode = "user" // 平台用户
|
||||||
AdminModuleCodeLog AdminModuleCode = "log" // 日志
|
AdminModuleCodeFinance AdminModuleCode = "finance" // 财务
|
||||||
AdminModuleCodeSetting AdminModuleCode = "setting" // 设置
|
AdminModuleCodeLog AdminModuleCode = "log" // 日志
|
||||||
AdminModuleCodeCommon AdminModuleCode = "common" // 只要登录就可以访问的模块
|
AdminModuleCodeSetting AdminModuleCode = "setting" // 设置
|
||||||
|
AdminModuleCodeCommon AdminModuleCode = "common" // 只要登录就可以访问的模块
|
||||||
)
|
)
|
||||||
|
|
||||||
var sharedAdminModuleMapping = map[int64]*AdminModuleList{} // adminId => AdminModuleList
|
var sharedAdminModuleMapping = map[int64]*AdminModuleList{} // adminId => AdminModuleList
|
||||||
@@ -109,7 +110,7 @@ func FindFirstAdminModule(adminId int64) (module AdminModuleCode, ok bool) {
|
|||||||
list, ok2 := sharedAdminModuleMapping[adminId]
|
list, ok2 := sharedAdminModuleMapping[adminId]
|
||||||
if ok2 {
|
if ok2 {
|
||||||
if list.IsSuper {
|
if list.IsSuper {
|
||||||
return AdminModuleCodeServer, true
|
return AdminModuleCodeDashboard, true
|
||||||
} else if len(list.Modules) > 0 {
|
} else if len(list.Modules) > 0 {
|
||||||
return list.Modules[0].Code, true
|
return list.Modules[0].Code, true
|
||||||
}
|
}
|
||||||
@@ -132,6 +133,11 @@ func FindAdminFullname(adminId int64) string {
|
|||||||
// 所有权限列表
|
// 所有权限列表
|
||||||
func AllModuleMaps() []maps.Map {
|
func AllModuleMaps() []maps.Map {
|
||||||
return []maps.Map{
|
return []maps.Map{
|
||||||
|
{
|
||||||
|
"name": "看板",
|
||||||
|
"code": AdminModuleCodeDashboard,
|
||||||
|
"url": "/dashboard",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "网站服务",
|
"name": "网站服务",
|
||||||
"code": AdminModuleCodeServer,
|
"code": AdminModuleCodeServer,
|
||||||
|
|||||||
@@ -24,13 +24,14 @@ func LoadAPIConfig() (*APIConfig, error) {
|
|||||||
localFile := Tea.ConfigFile("api.yaml")
|
localFile := Tea.ConfigFile("api.yaml")
|
||||||
isFromLocal := false
|
isFromLocal := false
|
||||||
paths := []string{localFile}
|
paths := []string{localFile}
|
||||||
homeDir, err := os.UserHomeDir()
|
homeDir, homeErr := os.UserHomeDir()
|
||||||
if err == nil {
|
if homeErr == nil {
|
||||||
paths = append(paths, homeDir+"/."+teaconst.ProcessName+"/api.yaml")
|
paths = append(paths, homeDir+"/."+teaconst.ProcessName+"/api.yaml")
|
||||||
}
|
}
|
||||||
paths = append(paths, "/etc/"+teaconst.ProcessName+"/api.yaml")
|
paths = append(paths, "/etc/"+teaconst.ProcessName+"/api.yaml")
|
||||||
|
|
||||||
var data []byte
|
var data []byte
|
||||||
|
var err error
|
||||||
for _, path := range paths {
|
for _, path := range paths {
|
||||||
data, err = ioutil.ReadFile(path)
|
data, err = ioutil.ReadFile(path)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
@@ -69,8 +70,8 @@ func (this *APIConfig) WriteFile(path string) error {
|
|||||||
// 写入 ~/ 和 /etc/ 目录,因为是备份需要,所以不需要提示错误信息
|
// 写入 ~/ 和 /etc/ 目录,因为是备份需要,所以不需要提示错误信息
|
||||||
// 写入 ~/.edge-admin/
|
// 写入 ~/.edge-admin/
|
||||||
filename := filepath.Base(path)
|
filename := filepath.Base(path)
|
||||||
homeDir, err := os.UserHomeDir()
|
homeDir, homeErr := os.UserHomeDir()
|
||||||
if err == nil {
|
if homeErr == nil {
|
||||||
dir := homeDir + "/." + teaconst.ProcessName
|
dir := homeDir + "/." + teaconst.ProcessName
|
||||||
stat, err := os.Stat(dir)
|
stat, err := os.Stat(dir)
|
||||||
if err == nil && stat.IsDir() {
|
if err == nil && stat.IsDir() {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package teaconst
|
package teaconst
|
||||||
|
|
||||||
const (
|
const (
|
||||||
Version = "0.0.8"
|
Version = "0.0.12"
|
||||||
|
|
||||||
ProductName = "Edge Admin"
|
ProductName = "Edge Admin"
|
||||||
ProcessName = "edge-admin"
|
ProcessName = "edge-admin"
|
||||||
|
|||||||
@@ -71,6 +71,10 @@ func (this *RPCClient) NodeClusterRPC() pb.NodeClusterServiceClient {
|
|||||||
return pb.NewNodeClusterServiceClient(this.pickConn())
|
return pb.NewNodeClusterServiceClient(this.pickConn())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (this *RPCClient) NodeClusterFirewallActionRPC() pb.NodeClusterFirewallActionServiceClient {
|
||||||
|
return pb.NewNodeClusterFirewallActionServiceClient(this.pickConn())
|
||||||
|
}
|
||||||
|
|
||||||
func (this *RPCClient) NodeGroupRPC() pb.NodeGroupServiceClient {
|
func (this *RPCClient) NodeGroupRPC() pb.NodeGroupServiceClient {
|
||||||
return pb.NewNodeGroupServiceClient(this.pickConn())
|
return pb.NewNodeGroupServiceClient(this.pickConn())
|
||||||
}
|
}
|
||||||
@@ -91,6 +95,34 @@ func (this *RPCClient) ServerRPC() pb.ServerServiceClient {
|
|||||||
return pb.NewServerServiceClient(this.pickConn())
|
return pb.NewServerServiceClient(this.pickConn())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (this *RPCClient) ServerClientSystemMonthlyStatRPC() pb.ServerClientSystemMonthlyStatServiceClient {
|
||||||
|
return pb.NewServerClientSystemMonthlyStatServiceClient(this.pickConn())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *RPCClient) ServerClientBrowserMonthlyStatRPC() pb.ServerClientBrowserMonthlyStatServiceClient {
|
||||||
|
return pb.NewServerClientBrowserMonthlyStatServiceClient(this.pickConn())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *RPCClient) ServerRegionCountryMonthlyStatRPC() pb.ServerRegionCountryMonthlyStatServiceClient {
|
||||||
|
return pb.NewServerRegionCountryMonthlyStatServiceClient(this.pickConn())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *RPCClient) ServerRegionProvinceMonthlyStatRPC() pb.ServerRegionProvinceMonthlyStatServiceClient {
|
||||||
|
return pb.NewServerRegionProvinceMonthlyStatServiceClient(this.pickConn())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *RPCClient) ServerRegionCityMonthlyStatRPC() pb.ServerRegionCityMonthlyStatServiceClient {
|
||||||
|
return pb.NewServerRegionCityMonthlyStatServiceClient(this.pickConn())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *RPCClient) ServerRegionProviderMonthlyStatRPC() pb.ServerRegionProviderMonthlyStatServiceClient {
|
||||||
|
return pb.NewServerRegionProviderMonthlyStatServiceClient(this.pickConn())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *RPCClient) ServerHTTPFirewallDailyStatRPC() pb.ServerHTTPFirewallDailyStatServiceClient {
|
||||||
|
return pb.NewServerHTTPFirewallDailyStatServiceClient(this.pickConn())
|
||||||
|
}
|
||||||
|
|
||||||
func (this *RPCClient) ServerGroupRPC() pb.ServerGroupServiceClient {
|
func (this *RPCClient) ServerGroupRPC() pb.ServerGroupServiceClient {
|
||||||
return pb.NewServerGroupServiceClient(this.pickConn())
|
return pb.NewServerGroupServiceClient(this.pickConn())
|
||||||
}
|
}
|
||||||
@@ -107,6 +139,10 @@ func (this *RPCClient) DBNodeRPC() pb.DBNodeServiceClient {
|
|||||||
return pb.NewDBNodeServiceClient(this.pickConn())
|
return pb.NewDBNodeServiceClient(this.pickConn())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (this *RPCClient) DBRPC() pb.DBServiceClient {
|
||||||
|
return pb.NewDBServiceClient(this.pickConn())
|
||||||
|
}
|
||||||
|
|
||||||
func (this *RPCClient) OriginRPC() pb.OriginServiceClient {
|
func (this *RPCClient) OriginRPC() pb.OriginServiceClient {
|
||||||
return pb.NewOriginServiceClient(this.pickConn())
|
return pb.NewOriginServiceClient(this.pickConn())
|
||||||
}
|
}
|
||||||
@@ -232,6 +268,10 @@ func (this *RPCClient) DNSRPC() pb.DNSServiceClient {
|
|||||||
return pb.NewDNSServiceClient(this.pickConn())
|
return pb.NewDNSServiceClient(this.pickConn())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (this *RPCClient) DNSTaskRPC() pb.DNSTaskServiceClient {
|
||||||
|
return pb.NewDNSTaskServiceClient(this.pickConn())
|
||||||
|
}
|
||||||
|
|
||||||
func (this *RPCClient) ACMEUserRPC() pb.ACMEUserServiceClient {
|
func (this *RPCClient) ACMEUserRPC() pb.ACMEUserServiceClient {
|
||||||
return pb.NewACMEUserServiceClient(this.pickConn())
|
return pb.NewACMEUserServiceClient(this.pickConn())
|
||||||
}
|
}
|
||||||
@@ -302,6 +342,12 @@ func (this *RPCClient) APIContext(apiNodeId int64) context.Context {
|
|||||||
return ctx
|
return ctx
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 修改配置
|
||||||
|
func (this *RPCClient) UpdateConfig(config *configs.APIConfig) error {
|
||||||
|
this.apiConfig = config
|
||||||
|
return this.init()
|
||||||
|
}
|
||||||
|
|
||||||
// 初始化
|
// 初始化
|
||||||
func (this *RPCClient) init() error {
|
func (this *RPCClient) init() error {
|
||||||
// 重新连接
|
// 重新连接
|
||||||
@@ -329,6 +375,8 @@ func (this *RPCClient) init() error {
|
|||||||
if len(conns) == 0 {
|
if len(conns) == 0 {
|
||||||
return errors.New("[RPC]no available endpoints")
|
return errors.New("[RPC]no available endpoints")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 这里不需要加锁,因为会和pickConn冲突
|
||||||
this.conns = conns
|
this.conns = conns
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
92
internal/tasks/task_sync_api_nodes.go
Normal file
92
internal/tasks/task_sync_api_nodes.go
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
package tasks
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/configs"
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/events"
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/rpc"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
|
"github.com/iwind/TeaGo/Tea"
|
||||||
|
"github.com/iwind/TeaGo/logs"
|
||||||
|
"sort"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
events.On(events.EventStart, func() {
|
||||||
|
task := NewSyncAPINodesTask()
|
||||||
|
go task.Start()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// API节点同步任务
|
||||||
|
type SyncAPINodesTask struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewSyncAPINodesTask() *SyncAPINodesTask {
|
||||||
|
return &SyncAPINodesTask{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *SyncAPINodesTask) Start() {
|
||||||
|
ticker := time.NewTicker(5 * time.Minute)
|
||||||
|
if Tea.IsTesting() {
|
||||||
|
// 快速测试
|
||||||
|
ticker = time.NewTicker(1 * time.Minute)
|
||||||
|
}
|
||||||
|
for range ticker.C {
|
||||||
|
err := this.Loop()
|
||||||
|
if err != nil {
|
||||||
|
logs.Println("[TASK][SYNC_API_NODES]" + err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *SyncAPINodesTask) Loop() error {
|
||||||
|
// 获取所有可用的节点
|
||||||
|
rpcClient, err := rpc.SharedRPC()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
resp, err := rpcClient.APINodeRPC().FindAllEnabledAPINodes(rpcClient.Context(0), &pb.FindAllEnabledAPINodesRequest{})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
newEndpoints := []string{}
|
||||||
|
for _, node := range resp.Nodes {
|
||||||
|
if !node.IsOn {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
newEndpoints = append(newEndpoints, node.AccessAddrs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 和现有的对比
|
||||||
|
config, err := configs.LoadAPIConfig()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if this.isSame(newEndpoints, config.RPC.Endpoints) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 修改RPC对象配置
|
||||||
|
config.RPC.Endpoints = newEndpoints
|
||||||
|
err = rpcClient.UpdateConfig(config)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 保存到文件
|
||||||
|
err = config.WriteFile(Tea.ConfigFile("api.yaml"))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *SyncAPINodesTask) isSame(endpoints1 []string, endpoints2 []string) bool {
|
||||||
|
sort.Strings(endpoints1)
|
||||||
|
sort.Strings(endpoints2)
|
||||||
|
return strings.Join(endpoints1, "&") == strings.Join(endpoints2, "&")
|
||||||
|
}
|
||||||
15
internal/tasks/task_sync_api_nodes_test.go
Normal file
15
internal/tasks/task_sync_api_nodes_test.go
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
package tasks
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "github.com/iwind/TeaGo/bootstrap"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestSyncAPINodesTask_Loop(t *testing.T) {
|
||||||
|
task := NewSyncAPINodesTask()
|
||||||
|
err := task.Loop()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
t.Log("ok")
|
||||||
|
}
|
||||||
@@ -2,18 +2,42 @@ package utils
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
|
"math/big"
|
||||||
"net"
|
"net"
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// 将IP转换为整型
|
// 将IP转换为整型
|
||||||
func IP2Long(ip string) uint32 {
|
func IP2Long(ip string) uint64 {
|
||||||
s := net.ParseIP(ip)
|
s := net.ParseIP(ip)
|
||||||
if s == nil {
|
if len(s) != 16 {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(s) == 16 {
|
if strings.Contains(ip, ":") { // IPv6
|
||||||
return binary.BigEndian.Uint32(s[12:16])
|
bigInt := big.NewInt(0)
|
||||||
|
bigInt.SetBytes(s.To16())
|
||||||
|
return bigInt.Uint64()
|
||||||
}
|
}
|
||||||
return binary.BigEndian.Uint32(s)
|
return uint64(binary.BigEndian.Uint32(s.To4()))
|
||||||
|
}
|
||||||
|
|
||||||
|
// 判断是否为IPv4
|
||||||
|
func IsIPv4(ip string) bool {
|
||||||
|
if !regexp.MustCompile(`^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$`).MatchString(ip) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if IP2Long(ip) == 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// 判断是否为IPv6
|
||||||
|
func IsIPv6(ip string) bool {
|
||||||
|
if !strings.Contains(ip, ":") {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return len(net.ParseIP(ip)) == net.IPv6len
|
||||||
}
|
}
|
||||||
|
|||||||
85
internal/utils/ip_utils_test.go
Normal file
85
internal/utils/ip_utils_test.go
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestIP2Long(t *testing.T) {
|
||||||
|
for _, ip := range []string{
|
||||||
|
"0.0.0.1",
|
||||||
|
"0.0.0.2",
|
||||||
|
"127.0.0.1",
|
||||||
|
"192.0.0.2",
|
||||||
|
"255.255.255.255",
|
||||||
|
"2001:db8:0:1::101",
|
||||||
|
"2001:db8:0:1::102",
|
||||||
|
"2406:8c00:0:3409:133:18:203:0",
|
||||||
|
"2406:8c00:0:3409:133:18:203:158",
|
||||||
|
"2406:8c00:0:3409:133:18:203:159",
|
||||||
|
"2406:8c00:0:3409:133:18:203:160",
|
||||||
|
} {
|
||||||
|
t.Log(ip, " -> ", IP2Long(ip))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIsIPv4(t *testing.T) {
|
||||||
|
type testIP struct {
|
||||||
|
ip string
|
||||||
|
ok bool
|
||||||
|
}
|
||||||
|
for _, item := range []testIP{
|
||||||
|
{
|
||||||
|
ip: "1",
|
||||||
|
ok: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ip: "192.168.0.1",
|
||||||
|
ok: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ip: "1.1.0.1",
|
||||||
|
ok: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ip: "255.255.255.255",
|
||||||
|
ok: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ip: "192.168.0.1233",
|
||||||
|
ok: false,
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
if IsIPv4(item.ip) != item.ok {
|
||||||
|
t.Fatal(item.ip, "should be", item.ok)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIsIPv6(t *testing.T) {
|
||||||
|
type testIP struct {
|
||||||
|
ip string
|
||||||
|
ok bool
|
||||||
|
}
|
||||||
|
for _, item := range []testIP{
|
||||||
|
{
|
||||||
|
ip: "1",
|
||||||
|
ok: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ip: "2406:8c00:0:3409:133:18:203:158",
|
||||||
|
ok: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ip: "2406::8c00:0:3409:133:18:203:158",
|
||||||
|
ok: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ip: "2001:db8:0:1::101",
|
||||||
|
ok: true,
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
if IsIPv6(item.ip) != item.ok {
|
||||||
|
t.Fatal(item.ip, "should be", item.ok)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,9 @@
|
|||||||
package numberutils
|
package numberutils
|
||||||
|
|
||||||
import "strconv"
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
func FormatInt64(value int64) string {
|
func FormatInt64(value int64) string {
|
||||||
return strconv.FormatInt(value, 10)
|
return strconv.FormatInt(value, 10)
|
||||||
@@ -9,3 +12,31 @@ func FormatInt64(value int64) string {
|
|||||||
func FormatInt(value int) string {
|
func FormatInt(value int) string {
|
||||||
return strconv.Itoa(value)
|
return strconv.Itoa(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func FormatBytes(bytes int64) string {
|
||||||
|
if bytes < 1024 {
|
||||||
|
return FormatInt64(bytes) + "B"
|
||||||
|
} else if bytes < 1024*1024 {
|
||||||
|
return fmt.Sprintf("%.2fKB", float64(bytes)/1024)
|
||||||
|
} else if bytes < 1024*1024*1024 {
|
||||||
|
return fmt.Sprintf("%.2fMB", float64(bytes)/1024/1024)
|
||||||
|
} else if bytes < 1024*1024*1024*1024 {
|
||||||
|
return fmt.Sprintf("%.2fGB", float64(bytes)/1024/1024/1024)
|
||||||
|
} else {
|
||||||
|
return fmt.Sprintf("%.2fPB", float64(bytes)/1024/1024/1024/1024)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func FormatBits(bits int64) string {
|
||||||
|
if bits < 1000 {
|
||||||
|
return FormatInt64(bits) + "B"
|
||||||
|
} else if bits < 1000*1000 {
|
||||||
|
return fmt.Sprintf("%.2fKB", float64(bits)/1000)
|
||||||
|
} else if bits < 1000*1000*1000 {
|
||||||
|
return fmt.Sprintf("%.2fMB", float64(bits)/1000/1000)
|
||||||
|
} else if bits < 1000*1000*1000*1000 {
|
||||||
|
return fmt.Sprintf("%.2fGB", float64(bits)/1000/1000/1000)
|
||||||
|
} else {
|
||||||
|
return fmt.Sprintf("%.2fPB", float64(bits)/1000/1000/1000/1000)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ func init() {
|
|||||||
Get("/node/logs", new(node.LogsAction)).
|
Get("/node/logs", new(node.LogsAction)).
|
||||||
Post("/node/start", new(node.StartAction)).
|
Post("/node/start", new(node.StartAction)).
|
||||||
Post("/node/stop", new(node.StopAction)).
|
Post("/node/stop", new(node.StopAction)).
|
||||||
|
Post("/node/up", new(node.UpAction)).
|
||||||
|
|
||||||
// 分组相关
|
// 分组相关
|
||||||
Get("/groups", new(groups.IndexAction)).
|
Get("/groups", new(groups.IndexAction)).
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ func (this *InstallManualAction) Init() {
|
|||||||
func (this *InstallManualAction) RunGet(params struct {
|
func (this *InstallManualAction) RunGet(params struct {
|
||||||
ClusterId int64
|
ClusterId int64
|
||||||
}) {
|
}) {
|
||||||
this.Data["leftMenuItems"] = LeftMenuItemsForInstall(params.ClusterId, "manual")
|
this.Data["leftMenuItems"] = LeftMenuItemsForInstall(this.AdminContext(), params.ClusterId, "manual")
|
||||||
|
|
||||||
nodesResp, err := this.RPC().NodeRPC().FindAllNotInstalledNodesWithClusterId(this.AdminContext(), &pb.FindAllNotInstalledNodesWithClusterIdRequest{NodeClusterId: params.ClusterId})
|
nodesResp, err := this.RPC().NodeRPC().FindAllNotInstalledNodesWithClusterId(this.AdminContext(), &pb.FindAllNotInstalledNodesWithClusterIdRequest{NodeClusterId: params.ClusterId})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ func (this *InstallNodesAction) Init() {
|
|||||||
func (this *InstallNodesAction) RunGet(params struct {
|
func (this *InstallNodesAction) RunGet(params struct {
|
||||||
ClusterId int64
|
ClusterId int64
|
||||||
}) {
|
}) {
|
||||||
this.Data["leftMenuItems"] = LeftMenuItemsForInstall(params.ClusterId, "register")
|
this.Data["leftMenuItems"] = LeftMenuItemsForInstall(this.AdminContext(), params.ClusterId, "register")
|
||||||
|
|
||||||
clusterResp, err := this.RPC().NodeClusterRPC().FindEnabledNodeCluster(this.AdminContext(), &pb.FindEnabledNodeClusterRequest{NodeClusterId: params.ClusterId})
|
clusterResp, err := this.RPC().NodeClusterRPC().FindEnabledNodeCluster(this.AdminContext(), &pb.FindEnabledNodeClusterRequest{NodeClusterId: params.ClusterId})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ func (this *InstallRemoteAction) Init() {
|
|||||||
func (this *InstallRemoteAction) RunGet(params struct {
|
func (this *InstallRemoteAction) RunGet(params struct {
|
||||||
ClusterId int64
|
ClusterId int64
|
||||||
}) {
|
}) {
|
||||||
this.Data["leftMenuItems"] = LeftMenuItemsForInstall(params.ClusterId, "install")
|
this.Data["leftMenuItems"] = LeftMenuItemsForInstall(this.AdminContext(), params.ClusterId, "install")
|
||||||
|
|
||||||
nodesResp, err := this.RPC().NodeRPC().FindAllNotInstalledNodesWithClusterId(this.AdminContext(), &pb.FindAllNotInstalledNodesWithClusterIdRequest{NodeClusterId: params.ClusterId})
|
nodesResp, err := this.RPC().NodeRPC().FindAllNotInstalledNodesWithClusterId(this.AdminContext(), &pb.FindAllNotInstalledNodesWithClusterIdRequest{NodeClusterId: params.ClusterId})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -89,6 +89,12 @@ func (this *NodeAction) RunGet(params struct {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if len(dnsRouteMaps) == 0 {
|
||||||
|
dnsRouteMaps = append(dnsRouteMaps, maps.Map{
|
||||||
|
"name": "",
|
||||||
|
"code": "",
|
||||||
|
})
|
||||||
|
}
|
||||||
this.Data["dnsRoutes"] = dnsRouteMaps
|
this.Data["dnsRoutes"] = dnsRouteMaps
|
||||||
this.Data["dnsRecordName"] = recordName
|
this.Data["dnsRecordName"] = recordName
|
||||||
this.Data["dnsRecordValue"] = recordValue
|
this.Data["dnsRecordValue"] = recordValue
|
||||||
@@ -143,6 +149,24 @@ func (this *NodeAction) RunGet(params struct {
|
|||||||
status.IsActive = status.IsActive && time.Now().Unix()-status.UpdatedAt <= 60 // N秒之内认为活跃
|
status.IsActive = status.IsActive && time.Now().Unix()-status.UpdatedAt <= 60 // N秒之内认为活跃
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 检查是否有新版本
|
||||||
|
if len(status.OS) > 0 {
|
||||||
|
checkVersionResp, err := this.RPC().NodeRPC().CheckNodeLatestVersion(this.AdminContext(), &pb.CheckNodeLatestVersionRequest{
|
||||||
|
Os: status.OS,
|
||||||
|
Arch: status.Arch,
|
||||||
|
CurrentVersion: status.BuildVersion,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.Data["shouldUpgrade"] = checkVersionResp.HasNewVersion
|
||||||
|
this.Data["newVersion"] = checkVersionResp.NewVersion
|
||||||
|
} else {
|
||||||
|
this.Data["shouldUpgrade"] = false
|
||||||
|
this.Data["newVersion"] = ""
|
||||||
|
}
|
||||||
|
|
||||||
// 分组
|
// 分组
|
||||||
var groupMap maps.Map = nil
|
var groupMap maps.Map = nil
|
||||||
if node.Group != nil {
|
if node.Group != nil {
|
||||||
@@ -175,14 +199,20 @@ func (this *NodeAction) RunGet(params struct {
|
|||||||
"isOn": node.IsOn,
|
"isOn": node.IsOn,
|
||||||
|
|
||||||
"status": maps.Map{
|
"status": maps.Map{
|
||||||
"isActive": status.IsActive,
|
"isActive": status.IsActive,
|
||||||
"updatedAt": status.UpdatedAt,
|
"updatedAt": status.UpdatedAt,
|
||||||
"hostname": status.Hostname,
|
"hostname": status.Hostname,
|
||||||
"cpuUsage": status.CPUUsage,
|
"cpuUsage": status.CPUUsage,
|
||||||
"cpuUsageText": fmt.Sprintf("%.2f%%", status.CPUUsage*100),
|
"cpuUsageText": fmt.Sprintf("%.2f%%", status.CPUUsage*100),
|
||||||
"memUsage": status.MemoryUsage,
|
"memUsage": status.MemoryUsage,
|
||||||
"memUsageText": fmt.Sprintf("%.2f%%", status.MemoryUsage*100),
|
"memUsageText": fmt.Sprintf("%.2f%%", status.MemoryUsage*100),
|
||||||
"connectionCount": status.ConnectionCount,
|
"connectionCount": status.ConnectionCount,
|
||||||
|
"buildVersion": status.BuildVersion,
|
||||||
|
"cpuPhysicalCount": status.CPUPhysicalCount,
|
||||||
|
"cpuLogicalCount": status.CPULogicalCount,
|
||||||
|
"load1m": fmt.Sprintf("%.2f", status.Load1m),
|
||||||
|
"load5m": fmt.Sprintf("%.2f", status.Load5m),
|
||||||
|
"load15m": fmt.Sprintf("%.2f", status.Load15m),
|
||||||
},
|
},
|
||||||
|
|
||||||
"group": groupMap,
|
"group": groupMap,
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
package node
|
package node
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
"github.com/iwind/TeaGo/maps"
|
"github.com/iwind/TeaGo/maps"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -34,6 +34,7 @@ func (this *StatusAction) RunPost(params struct {
|
|||||||
"isOk": node.InstallStatus.IsOk,
|
"isOk": node.InstallStatus.IsOk,
|
||||||
"updatedAt": node.InstallStatus.UpdatedAt,
|
"updatedAt": node.InstallStatus.UpdatedAt,
|
||||||
"error": node.InstallStatus.Error,
|
"error": node.InstallStatus.Error,
|
||||||
|
"errorCode": node.InstallStatus.ErrorCode,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this.Data["installStatus"] = nil
|
this.Data["installStatus"] = nil
|
||||||
|
|||||||
28
internal/web/actions/default/clusters/cluster/node/up.go
Normal file
28
internal/web/actions/default/clusters/cluster/node/up.go
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
package node
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
|
)
|
||||||
|
|
||||||
|
// 手动上线
|
||||||
|
type UpAction struct {
|
||||||
|
actionutils.ParentAction
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *UpAction) RunPost(params struct {
|
||||||
|
NodeId int64
|
||||||
|
}) {
|
||||||
|
defer this.CreateLogInfo("手动上线节点 %d", params.NodeId)
|
||||||
|
|
||||||
|
_, err := this.RPC().NodeRPC().UpdateNodeUp(this.AdminContext(), &pb.UpdateNodeUpRequest{
|
||||||
|
NodeId: params.NodeId,
|
||||||
|
IsUp: true,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Success()
|
||||||
|
}
|
||||||
@@ -0,0 +1,125 @@
|
|||||||
|
package firewallActions
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"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"
|
||||||
|
)
|
||||||
|
|
||||||
|
type CreatePopupAction struct {
|
||||||
|
actionutils.ParentAction
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *CreatePopupAction) Init() {
|
||||||
|
this.Nav("", "", "")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *CreatePopupAction) RunGet(params struct {
|
||||||
|
ClusterId int64
|
||||||
|
}) {
|
||||||
|
this.Data["clusterId"] = params.ClusterId
|
||||||
|
this.Data["actionTypes"] = firewallconfigs.FindAllFirewallActionTypes()
|
||||||
|
|
||||||
|
this.Show()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *CreatePopupAction) RunPost(params struct {
|
||||||
|
ClusterId int64
|
||||||
|
Name string
|
||||||
|
EventLevel string
|
||||||
|
Type string
|
||||||
|
|
||||||
|
// ipset
|
||||||
|
IpsetWhiteName string
|
||||||
|
IpsetBlackName string
|
||||||
|
IpsetAutoAddToIPTables bool
|
||||||
|
IpsetAutoAddToFirewalld bool
|
||||||
|
|
||||||
|
// script
|
||||||
|
ScriptPath string
|
||||||
|
|
||||||
|
// http api
|
||||||
|
HttpAPIURL string
|
||||||
|
|
||||||
|
// html
|
||||||
|
HtmlContent string
|
||||||
|
|
||||||
|
Must *actions.Must
|
||||||
|
CSRF *actionutils.CSRF
|
||||||
|
}) {
|
||||||
|
defer this.CreateLogInfo("创建WAF动作")
|
||||||
|
|
||||||
|
params.Must.
|
||||||
|
Field("name", params.Name).
|
||||||
|
Require("请输入动作名称").
|
||||||
|
Field("type", params.Type).
|
||||||
|
Require("请选择动作类型")
|
||||||
|
|
||||||
|
var actionParams interface{} = nil
|
||||||
|
switch params.Type {
|
||||||
|
case firewallconfigs.FirewallActionTypeIPSet:
|
||||||
|
params.Must.
|
||||||
|
Field("ipsetWhiteName", params.IpsetWhiteName).
|
||||||
|
Require("请输入IPSet白名单名称").
|
||||||
|
Match(`^\w+$`, "请输入正确的IPSet白名单名称").
|
||||||
|
Field("ipsetBlackName", params.IpsetBlackName).
|
||||||
|
Require("请输入IPSet黑名单名称").
|
||||||
|
Match(`^\w+$`, "请输入正确的IPSet黑名单名称")
|
||||||
|
|
||||||
|
actionParams = &firewallconfigs.FirewallActionIPSetConfig{
|
||||||
|
WhiteName: params.IpsetWhiteName,
|
||||||
|
BlackName: params.IpsetBlackName,
|
||||||
|
AutoAddToIPTables: params.IpsetAutoAddToIPTables,
|
||||||
|
AutoAddToFirewalld: params.IpsetAutoAddToFirewalld,
|
||||||
|
}
|
||||||
|
case firewallconfigs.FirewallActionTypeIPTables:
|
||||||
|
actionParams = &firewallconfigs.FirewallActionIPTablesConfig{}
|
||||||
|
case firewallconfigs.FirewallActionTypeFirewalld:
|
||||||
|
actionParams = &firewallconfigs.FirewallActionFirewalldConfig{}
|
||||||
|
case firewallconfigs.FirewallActionTypeScript:
|
||||||
|
params.Must.
|
||||||
|
Field("scriptPath", params.ScriptPath).
|
||||||
|
Require("请输入脚本路径")
|
||||||
|
actionParams = &firewallconfigs.FirewallActionScriptConfig{
|
||||||
|
Path: params.ScriptPath,
|
||||||
|
}
|
||||||
|
case firewallconfigs.FirewallActionTypeHTTPAPI:
|
||||||
|
params.Must.
|
||||||
|
Field("httpAPIURL", params.HttpAPIURL).
|
||||||
|
Require("请输入API URL").
|
||||||
|
Match(`^(http|https):`, "API地址必须以http://或https://开头")
|
||||||
|
actionParams = &firewallconfigs.FirewallActionHTTPAPIConfig{
|
||||||
|
URL: params.HttpAPIURL,
|
||||||
|
}
|
||||||
|
case firewallconfigs.FirewallActionTypeHTML:
|
||||||
|
params.Must.
|
||||||
|
Field("htmlContent", params.HtmlContent).
|
||||||
|
Require("请输入HTML内容")
|
||||||
|
actionParams = &firewallconfigs.FirewallActionHTMLConfig{
|
||||||
|
Content: params.HtmlContent,
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
this.Fail("选择的类型'" + params.Type + "'暂时不支持")
|
||||||
|
}
|
||||||
|
|
||||||
|
actionParamsJSON, err := json.Marshal(actionParams)
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = this.RPC().NodeClusterFirewallActionRPC().CreateNodeClusterFirewallAction(this.AdminContext(), &pb.CreateNodeClusterFirewallActionRequest{
|
||||||
|
NodeClusterId: params.ClusterId,
|
||||||
|
Name: params.Name,
|
||||||
|
EventLevel: params.EventLevel,
|
||||||
|
Type: params.Type,
|
||||||
|
ParamsJSON: actionParamsJSON,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.Success()
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package firewallActions
|
||||||
|
|
||||||
|
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 {
|
||||||
|
ActionId int64
|
||||||
|
}) {
|
||||||
|
defer this.CreateLogInfo("删除WAF动作 %d", params.ActionId)
|
||||||
|
|
||||||
|
_, err := this.RPC().NodeClusterFirewallActionRPC().DeleteNodeClusterFirewallAction(this.AdminContext(), &pb.DeleteNodeClusterFirewallActionRequest{NodeClusterFirewallActionId: params.ActionId})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Success()
|
||||||
|
}
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
package firewallActions
|
||||||
|
|
||||||
|
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"
|
||||||
|
)
|
||||||
|
|
||||||
|
type IndexAction struct {
|
||||||
|
actionutils.ParentAction
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *IndexAction) Init() {
|
||||||
|
this.Nav("", "setting", "")
|
||||||
|
this.SecondMenu("firewallAction")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *IndexAction) RunGet(params struct {
|
||||||
|
ClusterId int64
|
||||||
|
}) {
|
||||||
|
actionsResp, err := this.RPC().NodeClusterFirewallActionRPC().FindAllEnabledNodeClusterFirewallActions(this.AdminContext(), &pb.FindAllEnabledNodeClusterFirewallActionsRequest{NodeClusterId: params.ClusterId})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
levelMaps := map[string][]maps.Map{} // level => actionMaps
|
||||||
|
for _, action := range actionsResp.NodeClusterFirewallActions {
|
||||||
|
actionMaps, ok := levelMaps[action.EventLevel]
|
||||||
|
if !ok {
|
||||||
|
actionMaps = []maps.Map{}
|
||||||
|
}
|
||||||
|
|
||||||
|
actionMaps = append(actionMaps, maps.Map{
|
||||||
|
"id": action.Id,
|
||||||
|
"name": action.Name,
|
||||||
|
"type": action.Type,
|
||||||
|
"typeName": firewallconfigs.FindFirewallActionTypeName(action.Type),
|
||||||
|
})
|
||||||
|
levelMaps[action.EventLevel] = actionMaps
|
||||||
|
}
|
||||||
|
|
||||||
|
levelMaps2 := []maps.Map{} // []levelMap
|
||||||
|
hasActions := false
|
||||||
|
for _, level := range firewallconfigs.FindAllFirewallEventLevels() {
|
||||||
|
actionMaps, ok := levelMaps[level.Code]
|
||||||
|
if !ok {
|
||||||
|
actionMaps = []maps.Map{}
|
||||||
|
} else {
|
||||||
|
hasActions = true
|
||||||
|
}
|
||||||
|
|
||||||
|
levelMaps2 = append(levelMaps2, maps.Map{
|
||||||
|
"name": level.Name,
|
||||||
|
"code": level.Code,
|
||||||
|
"actions": actionMaps,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Data["levels"] = levelMaps2
|
||||||
|
this.Data["hasActions"] = hasActions
|
||||||
|
|
||||||
|
this.Show()
|
||||||
|
}
|
||||||
@@ -0,0 +1,154 @@
|
|||||||
|
package firewallActions
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"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"
|
||||||
|
)
|
||||||
|
|
||||||
|
type UpdatePopupAction struct {
|
||||||
|
actionutils.ParentAction
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *UpdatePopupAction) Init() {
|
||||||
|
this.Nav("", "", "")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *UpdatePopupAction) RunGet(params struct {
|
||||||
|
ActionId int64
|
||||||
|
}) {
|
||||||
|
actionResp, err := this.RPC().NodeClusterFirewallActionRPC().FindEnabledNodeClusterFirewallAction(this.AdminContext(), &pb.FindEnabledNodeClusterFirewallActionRequest{NodeClusterFirewallActionId: params.ActionId})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
action := actionResp.NodeClusterFirewallAction
|
||||||
|
if action == nil {
|
||||||
|
this.NotFound("nodeClusterFirewallAction", params.ActionId)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
actionParams := maps.Map{}
|
||||||
|
if len(action.ParamsJSON) > 0 {
|
||||||
|
err = json.Unmarshal(action.ParamsJSON, &actionParams)
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Data["action"] = maps.Map{
|
||||||
|
"id": action.Id,
|
||||||
|
"name": action.Name,
|
||||||
|
"eventLevel": action.EventLevel,
|
||||||
|
"params": actionParams,
|
||||||
|
"type": action.Type,
|
||||||
|
}
|
||||||
|
|
||||||
|
// 通用参数
|
||||||
|
this.Data["actionTypes"] = firewallconfigs.FindAllFirewallActionTypes()
|
||||||
|
|
||||||
|
this.Show()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *UpdatePopupAction) RunPost(params struct {
|
||||||
|
ActionId int64
|
||||||
|
Name string
|
||||||
|
EventLevel string
|
||||||
|
Type string
|
||||||
|
|
||||||
|
// ipset
|
||||||
|
IpsetWhiteName string
|
||||||
|
IpsetBlackName string
|
||||||
|
IpsetAutoAddToIPTables bool
|
||||||
|
IpsetAutoAddToFirewalld bool
|
||||||
|
|
||||||
|
// script
|
||||||
|
ScriptPath string
|
||||||
|
|
||||||
|
// http api
|
||||||
|
HttpAPIURL string
|
||||||
|
|
||||||
|
// HTML内容
|
||||||
|
HtmlContent string
|
||||||
|
|
||||||
|
Must *actions.Must
|
||||||
|
CSRF *actionutils.CSRF
|
||||||
|
}) {
|
||||||
|
defer this.CreateLogInfo("修改WAF动作 %d", params.ActionId)
|
||||||
|
|
||||||
|
params.Must.
|
||||||
|
Field("name", params.Name).
|
||||||
|
Require("请输入动作名称").
|
||||||
|
Field("type", params.Type).
|
||||||
|
Require("请选择动作类型")
|
||||||
|
|
||||||
|
var actionParams interface{} = nil
|
||||||
|
switch params.Type {
|
||||||
|
case firewallconfigs.FirewallActionTypeIPSet:
|
||||||
|
params.Must.
|
||||||
|
Field("ipsetWhiteName", params.IpsetWhiteName).
|
||||||
|
Require("请输入IPSet白名单名称").
|
||||||
|
Match(`^\w+$`, "请输入正确的IPSet白名单名称").
|
||||||
|
Field("ipsetBlackName", params.IpsetBlackName).
|
||||||
|
Require("请输入IPSet黑名单名称").
|
||||||
|
Match(`^\w+$`, "请输入正确的IPSet黑名单名称")
|
||||||
|
|
||||||
|
actionParams = &firewallconfigs.FirewallActionIPSetConfig{
|
||||||
|
WhiteName: params.IpsetWhiteName,
|
||||||
|
BlackName: params.IpsetBlackName,
|
||||||
|
AutoAddToIPTables: params.IpsetAutoAddToIPTables,
|
||||||
|
AutoAddToFirewalld: params.IpsetAutoAddToFirewalld,
|
||||||
|
}
|
||||||
|
case firewallconfigs.FirewallActionTypeIPTables:
|
||||||
|
actionParams = &firewallconfigs.FirewallActionIPTablesConfig{}
|
||||||
|
case firewallconfigs.FirewallActionTypeFirewalld:
|
||||||
|
actionParams = &firewallconfigs.FirewallActionFirewalldConfig{}
|
||||||
|
case firewallconfigs.FirewallActionTypeScript:
|
||||||
|
params.Must.
|
||||||
|
Field("scriptPath", params.ScriptPath).
|
||||||
|
Require("请输入脚本路径")
|
||||||
|
actionParams = &firewallconfigs.FirewallActionScriptConfig{
|
||||||
|
Path: params.ScriptPath,
|
||||||
|
}
|
||||||
|
case firewallconfigs.FirewallActionTypeHTTPAPI:
|
||||||
|
params.Must.
|
||||||
|
Field("httpAPIURL", params.HttpAPIURL).
|
||||||
|
Require("请输入API URL").
|
||||||
|
Match(`^(http|https):`, "API地址必须以http://或https://开头")
|
||||||
|
actionParams = &firewallconfigs.FirewallActionHTTPAPIConfig{
|
||||||
|
URL: params.HttpAPIURL,
|
||||||
|
}
|
||||||
|
case firewallconfigs.FirewallActionTypeHTML:
|
||||||
|
params.Must.
|
||||||
|
Field("htmlContent", params.HtmlContent).
|
||||||
|
Require("请输入HTML内容")
|
||||||
|
actionParams = &firewallconfigs.FirewallActionHTMLConfig{
|
||||||
|
Content: params.HtmlContent,
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
this.Fail("选择的类型'" + params.Type + "'暂时不支持")
|
||||||
|
}
|
||||||
|
|
||||||
|
actionParamsJSON, err := json.Marshal(actionParams)
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = this.RPC().NodeClusterFirewallActionRPC().UpdateNodeClusterFirewallAction(this.AdminContext(), &pb.UpdateNodeClusterFirewallActionRequest{
|
||||||
|
NodeClusterFirewallActionId: params.ActionId,
|
||||||
|
Name: params.Name,
|
||||||
|
EventLevel: params.EventLevel,
|
||||||
|
Type: params.Type,
|
||||||
|
ParamsJSON: actionParamsJSON,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.Success()
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package settings
|
package health
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
@@ -9,16 +9,16 @@ import (
|
|||||||
"github.com/iwind/TeaGo/actions"
|
"github.com/iwind/TeaGo/actions"
|
||||||
)
|
)
|
||||||
|
|
||||||
type HealthAction struct {
|
type IndexAction struct {
|
||||||
actionutils.ParentAction
|
actionutils.ParentAction
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *HealthAction) Init() {
|
func (this *IndexAction) Init() {
|
||||||
this.Nav("", "setting", "")
|
this.Nav("", "setting", "")
|
||||||
this.SecondMenu("health")
|
this.SecondMenu("health")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *HealthAction) RunGet(params struct {
|
func (this *IndexAction) RunGet(params struct {
|
||||||
ClusterId int64
|
ClusterId int64
|
||||||
}) {
|
}) {
|
||||||
configResp, err := this.RPC().NodeClusterRPC().FindNodeClusterHealthCheckConfig(this.AdminContext(), &pb.FindNodeClusterHealthCheckConfigRequest{NodeClusterId: params.ClusterId})
|
configResp, err := this.RPC().NodeClusterRPC().FindNodeClusterHealthCheckConfig(this.AdminContext(), &pb.FindNodeClusterHealthCheckConfigRequest{NodeClusterId: params.ClusterId})
|
||||||
@@ -40,7 +40,7 @@ func (this *HealthAction) RunGet(params struct {
|
|||||||
this.Show()
|
this.Show()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *HealthAction) RunPost(params struct {
|
func (this *IndexAction) RunPost(params struct {
|
||||||
ClusterId int64
|
ClusterId int64
|
||||||
HealthCheckJSON []byte
|
HealthCheckJSON []byte
|
||||||
Must *actions.Must
|
Must *actions.Must
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package settings
|
package health
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/oplogs"
|
"github.com/TeaOSLab/EdgeAdmin/internal/oplogs"
|
||||||
@@ -7,20 +7,19 @@ import (
|
|||||||
"github.com/iwind/TeaGo/actions"
|
"github.com/iwind/TeaGo/actions"
|
||||||
)
|
)
|
||||||
|
|
||||||
type HealthRunPopupAction struct {
|
type RunPopupAction struct {
|
||||||
actionutils.ParentAction
|
actionutils.ParentAction
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *HealthRunPopupAction) Init() {
|
func (this *RunPopupAction) Init() {
|
||||||
this.Nav("", "", "")
|
this.Nav("", "", "")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *HealthRunPopupAction) RunGet(params struct{}) {
|
func (this *RunPopupAction) RunGet(params struct{}) {
|
||||||
|
|
||||||
this.Show()
|
this.Show()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *HealthRunPopupAction) RunPost(params struct {
|
func (this *RunPopupAction) RunPost(params struct {
|
||||||
ClusterId int64
|
ClusterId int64
|
||||||
|
|
||||||
Must *actions.Must
|
Must *actions.Must
|
||||||
@@ -4,6 +4,8 @@ import (
|
|||||||
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
|
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/cluster/settings/cache"
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/cluster/settings/cache"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/cluster/settings/dns"
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/cluster/settings/dns"
|
||||||
|
firewallActions "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/cluster/settings/firewall-actions"
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/cluster/settings/health"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/cluster/settings/services"
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/cluster/settings/services"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/cluster/settings/toa"
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/cluster/settings/toa"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/cluster/settings/waf"
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/cluster/settings/waf"
|
||||||
@@ -21,8 +23,8 @@ func init() {
|
|||||||
GetPost("", new(IndexAction)).
|
GetPost("", new(IndexAction)).
|
||||||
|
|
||||||
// 健康检查
|
// 健康检查
|
||||||
GetPost("/health", new(HealthAction)).
|
GetPost("/health", new(health.IndexAction)).
|
||||||
GetPost("/healthRunPopup", new(HealthRunPopupAction)).
|
GetPost("/health/runPopup", new(health.RunPopupAction)).
|
||||||
|
|
||||||
// 缓存
|
// 缓存
|
||||||
GetPost("/cache", new(cache.IndexAction)).
|
GetPost("/cache", new(cache.IndexAction)).
|
||||||
@@ -43,6 +45,13 @@ func init() {
|
|||||||
GetPost("", new(services.IndexAction)).
|
GetPost("", new(services.IndexAction)).
|
||||||
GetPost("/status", new(services.StatusAction)).
|
GetPost("/status", new(services.StatusAction)).
|
||||||
|
|
||||||
|
// 防火墙动作
|
||||||
|
Prefix("/clusters/cluster/settings/firewall-actions").
|
||||||
|
Get("", new(firewallActions.IndexAction)).
|
||||||
|
GetPost("/createPopup", new(firewallActions.CreatePopupAction)).
|
||||||
|
GetPost("/updatePopup", new(firewallActions.UpdatePopupAction)).
|
||||||
|
Post("/delete", new(firewallActions.DeleteAction)).
|
||||||
|
|
||||||
EndAll()
|
EndAll()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ func (this *UpgradeRemoteAction) Init() {
|
|||||||
func (this *UpgradeRemoteAction) RunGet(params struct {
|
func (this *UpgradeRemoteAction) RunGet(params struct {
|
||||||
ClusterId int64
|
ClusterId int64
|
||||||
}) {
|
}) {
|
||||||
this.Data["leftMenuItems"] = LeftMenuItemsForInstall(params.ClusterId, "upgrade")
|
this.Data["leftMenuItems"] = LeftMenuItemsForInstall(this.AdminContext(), params.ClusterId, "upgrade")
|
||||||
|
|
||||||
nodes := []maps.Map{}
|
nodes := []maps.Map{}
|
||||||
resp, err := this.RPC().NodeRPC().FindAllUpgradeNodesWithClusterId(this.AdminContext(), &pb.FindAllUpgradeNodesWithClusterIdRequest{NodeClusterId: params.ClusterId})
|
resp, err := this.RPC().NodeRPC().FindAllUpgradeNodesWithClusterId(this.AdminContext(), &pb.FindAllUpgradeNodesWithClusterIdRequest{NodeClusterId: params.ClusterId})
|
||||||
|
|||||||
@@ -1,12 +1,34 @@
|
|||||||
package cluster
|
package cluster
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/rpc"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/utils/numberutils"
|
"github.com/TeaOSLab/EdgeAdmin/internal/utils/numberutils"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
"github.com/iwind/TeaGo/maps"
|
"github.com/iwind/TeaGo/maps"
|
||||||
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
// 安装升级相关的左侧菜单
|
// 安装升级相关的左侧菜单
|
||||||
func LeftMenuItemsForInstall(clusterId int64, selectedItem string) []maps.Map {
|
func LeftMenuItemsForInstall(ctx context.Context, clusterId int64, selectedItem string) []maps.Map {
|
||||||
|
rpcClient, _ := rpc.SharedRPC()
|
||||||
|
countNotInstalled := int64(0)
|
||||||
|
countUpgrade := int64(0)
|
||||||
|
if rpcClient != nil {
|
||||||
|
{
|
||||||
|
resp, err := rpcClient.NodeRPC().CountAllNotInstalledNodesWithClusterId(ctx, &pb.CountAllNotInstalledNodesWithClusterIdRequest{NodeClusterId: clusterId})
|
||||||
|
if err == nil {
|
||||||
|
countNotInstalled = resp.Count
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
resp, err := rpcClient.NodeRPC().CountAllUpgradeNodesWithClusterId(ctx, &pb.CountAllUpgradeNodesWithClusterIdRequest{NodeClusterId: clusterId})
|
||||||
|
if err == nil {
|
||||||
|
countUpgrade = resp.Count
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return []maps.Map{
|
return []maps.Map{
|
||||||
{
|
{
|
||||||
"name": "手动安装",
|
"name": "手动安装",
|
||||||
@@ -19,12 +41,12 @@ func LeftMenuItemsForInstall(clusterId int64, selectedItem string) []maps.Map {
|
|||||||
"isActive": selectedItem == "register",
|
"isActive": selectedItem == "register",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "远程安装",
|
"name": "远程安装(" + strconv.FormatInt(countNotInstalled, 10) + ")",
|
||||||
"url": "/clusters/cluster/installRemote?clusterId=" + numberutils.FormatInt64(clusterId),
|
"url": "/clusters/cluster/installRemote?clusterId=" + numberutils.FormatInt64(clusterId),
|
||||||
"isActive": selectedItem == "install",
|
"isActive": selectedItem == "install",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "远程升级",
|
"name": "远程升级(" + strconv.FormatInt(countUpgrade, 10) + ")",
|
||||||
"url": "/clusters/cluster/upgradeRemote?clusterId=" + numberutils.FormatInt64(clusterId),
|
"url": "/clusters/cluster/upgradeRemote?clusterId=" + numberutils.FormatInt64(clusterId),
|
||||||
"isActive": selectedItem == "upgrade",
|
"isActive": selectedItem == "upgrade",
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
package clusterutils
|
package clusterutils
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/rpc"
|
"github.com/TeaOSLab/EdgeAdmin/internal/rpc"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/utils/numberutils"
|
"github.com/TeaOSLab/EdgeAdmin/internal/utils/numberutils"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||||
"github.com/iwind/TeaGo/actions"
|
"github.com/iwind/TeaGo/actions"
|
||||||
"github.com/iwind/TeaGo/logs"
|
"github.com/iwind/TeaGo/logs"
|
||||||
"github.com/iwind/TeaGo/maps"
|
"github.com/iwind/TeaGo/maps"
|
||||||
@@ -86,15 +88,32 @@ func (this *ClusterHelper) createSettingMenu(cluster *pb.NodeCluster, selectedIt
|
|||||||
"isActive": selectedItem == "waf",
|
"isActive": selectedItem == "waf",
|
||||||
"isOn": cluster.HttpFirewallPolicyId > 0,
|
"isOn": cluster.HttpFirewallPolicyId > 0,
|
||||||
})
|
})
|
||||||
items = append(items, maps.Map{
|
|
||||||
"name": "健康检查",
|
{
|
||||||
"url": "/clusters/cluster/settings/health?clusterId=" + clusterId,
|
hasActions, _ := this.checkFirewallActions(cluster.Id)
|
||||||
"isActive": selectedItem == "health",
|
items = append(items, maps.Map{
|
||||||
})
|
"name": "WAF动作",
|
||||||
|
"url": "/clusters/cluster/settings/firewall-actions?clusterId=" + clusterId,
|
||||||
|
"isActive": selectedItem == "firewallAction",
|
||||||
|
"isOn": hasActions,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
healthCheckIsOn, _ := this.checkHealthCheckIsOn(cluster.Id)
|
||||||
|
items = append(items, maps.Map{
|
||||||
|
"name": "健康检查",
|
||||||
|
"url": "/clusters/cluster/settings/health?clusterId=" + clusterId,
|
||||||
|
"isActive": selectedItem == "health",
|
||||||
|
"isOn": healthCheckIsOn,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
items = append(items, maps.Map{
|
items = append(items, maps.Map{
|
||||||
"name": "DNS设置",
|
"name": "DNS设置",
|
||||||
"url": "/clusters/cluster/settings/dns?clusterId=" + clusterId,
|
"url": "/clusters/cluster/settings/dns?clusterId=" + clusterId,
|
||||||
"isActive": selectedItem == "dns",
|
"isActive": selectedItem == "dns",
|
||||||
|
"isOn": cluster.DnsDomainId > 0 || len(cluster.DnsName) > 0,
|
||||||
})
|
})
|
||||||
items = append(items, maps.Map{
|
items = append(items, maps.Map{
|
||||||
"name": "系统服务",
|
"name": "系统服务",
|
||||||
@@ -108,3 +127,37 @@ func (this *ClusterHelper) createSettingMenu(cluster *pb.NodeCluster, selectedIt
|
|||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 检查健康检查是否开启
|
||||||
|
func (this *ClusterHelper) checkHealthCheckIsOn(clusterId int64) (bool, error) {
|
||||||
|
rpcClient, err := rpc.SharedRPC()
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
resp, err := rpcClient.NodeClusterRPC().FindNodeClusterHealthCheckConfig(rpcClient.Context(0), &pb.FindNodeClusterHealthCheckConfigRequest{NodeClusterId: clusterId})
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
if len(resp.HealthCheckJSON) > 0 {
|
||||||
|
healthCheckConfig := &serverconfigs.HealthCheckConfig{}
|
||||||
|
err = json.Unmarshal(resp.HealthCheckJSON, healthCheckConfig)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
return healthCheckConfig.IsOn, nil
|
||||||
|
}
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查是否有WAF动作
|
||||||
|
func (this *ClusterHelper) checkFirewallActions(clusterId int64) (bool, error) {
|
||||||
|
rpcClient, err := rpc.SharedRPC()
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
resp, err := rpcClient.NodeClusterFirewallActionRPC().CountAllEnabledNodeClusterFirewallActions(rpcClient.Context(0), &pb.CountAllEnabledNodeClusterFirewallActionsRequest{NodeClusterId: clusterId})
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
return resp.Count > 0, nil
|
||||||
|
}
|
||||||
|
|||||||
24
internal/web/actions/default/clusters/tasks/deleteBatch.go
Normal file
24
internal/web/actions/default/clusters/tasks/deleteBatch.go
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
package tasks
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
|
)
|
||||||
|
|
||||||
|
type DeleteBatchAction struct {
|
||||||
|
actionutils.ParentAction
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *DeleteBatchAction) RunPost(params struct {
|
||||||
|
TaskIds []int64
|
||||||
|
}) {
|
||||||
|
defer this.CreateLogInfo("批量删除节点同步任务")
|
||||||
|
|
||||||
|
_, err := this.RPC().NodeTaskRPC().DeleteNodeTasks(this.AdminContext(), &pb.DeleteNodeTasksRequest{NodeTaskIds: params.TaskIds})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Success()
|
||||||
|
}
|
||||||
@@ -16,6 +16,7 @@ func init() {
|
|||||||
GetPost("/listPopup", new(ListPopupAction)).
|
GetPost("/listPopup", new(ListPopupAction)).
|
||||||
Post("/check", new(CheckAction)).
|
Post("/check", new(CheckAction)).
|
||||||
Post("/delete", new(DeleteAction)).
|
Post("/delete", new(DeleteAction)).
|
||||||
|
Post("/deleteBatch", new(DeleteBatchAction)).
|
||||||
|
|
||||||
EndAll()
|
EndAll()
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -2,7 +2,12 @@ package dashboard
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
|
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/utils/numberutils"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
|
"github.com/iwind/TeaGo/maps"
|
||||||
|
"math"
|
||||||
|
"regexp"
|
||||||
)
|
)
|
||||||
|
|
||||||
type IndexAction struct {
|
type IndexAction struct {
|
||||||
@@ -17,13 +22,75 @@ func (this *IndexAction) RunGet(params struct{}) {
|
|||||||
// 取得用户的权限
|
// 取得用户的权限
|
||||||
module, ok := configloaders.FindFirstAdminModule(this.AdminId())
|
module, ok := configloaders.FindFirstAdminModule(this.AdminId())
|
||||||
if ok {
|
if ok {
|
||||||
for _, m := range configloaders.AllModuleMaps() {
|
if module != "dashboard" {
|
||||||
if m.GetString("code") == module {
|
for _, m := range configloaders.AllModuleMaps() {
|
||||||
this.RedirectURL(m.GetString("url"))
|
if m.GetString("code") == module {
|
||||||
return
|
this.RedirectURL(m.GetString("url"))
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 读取看板数据
|
||||||
|
resp, err := this.RPC().AdminRPC().ComposeAdminDashboard(this.AdminContext(), &pb.ComposeAdminDashboardRequest{})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.Data["dashboard"] = maps.Map{
|
||||||
|
"countServers": resp.CountServers,
|
||||||
|
"countNodeClusters": resp.CountNodeClusters,
|
||||||
|
"countNodes": resp.CountNodes,
|
||||||
|
"countUsers": resp.CountUsers,
|
||||||
|
"countAPINodes": resp.CountAPINodes,
|
||||||
|
"countDBNodes": resp.CountDBNodes,
|
||||||
|
"countUserNodes": resp.CountUserNodes,
|
||||||
|
|
||||||
|
"canGoServers": configloaders.AllowModule(this.AdminId(), configloaders.AdminModuleCodeServer),
|
||||||
|
"canGoNodes": configloaders.AllowModule(this.AdminId(), configloaders.AdminModuleCodeNode),
|
||||||
|
"canGoSettings": configloaders.AllowModule(this.AdminId(), configloaders.AdminModuleCodeSetting),
|
||||||
|
"canGoUsers": configloaders.AllowModule(this.AdminId(), configloaders.AdminModuleCodeUser),
|
||||||
|
}
|
||||||
|
|
||||||
|
// 今日流量
|
||||||
|
todayTrafficBytes := int64(0)
|
||||||
|
if len(resp.DailyTrafficStats) > 0 {
|
||||||
|
todayTrafficBytes = resp.DailyTrafficStats[len(resp.DailyTrafficStats)-1].Bytes
|
||||||
|
}
|
||||||
|
todayTrafficString := numberutils.FormatBits(todayTrafficBytes * 8)
|
||||||
|
result := regexp.MustCompile(`^(?U)(.+)([a-zA-Z]+)$`).FindStringSubmatch(todayTrafficString)
|
||||||
|
if len(result) > 2 {
|
||||||
|
this.Data["todayTraffic"] = result[1]
|
||||||
|
this.Data["todayTrafficUnit"] = result[2]
|
||||||
|
} else {
|
||||||
|
this.Data["todayTraffic"] = todayTrafficString
|
||||||
|
this.Data["todayTrafficUnit"] = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// 24小时流量趋势
|
||||||
|
{
|
||||||
|
statMaps := []maps.Map{}
|
||||||
|
for _, stat := range resp.HourlyTrafficStats {
|
||||||
|
statMaps = append(statMaps, maps.Map{
|
||||||
|
"count": math.Ceil((float64(stat.Bytes)*8/1000/1000/1000)*1000) / 1000,
|
||||||
|
"hour": stat.Hour[8:],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
this.Data["hourlyTrafficStats"] = statMaps
|
||||||
|
}
|
||||||
|
|
||||||
|
// 15天流量趋势
|
||||||
|
{
|
||||||
|
statMaps := []maps.Map{}
|
||||||
|
for _, stat := range resp.DailyTrafficStats {
|
||||||
|
statMaps = append(statMaps, maps.Map{
|
||||||
|
"count": math.Ceil((float64(stat.Bytes)*8/1000/1000/1000)*1000) / 1000,
|
||||||
|
"day": stat.Day[4:6] + "月" + stat.Day[6:] + "日",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
this.Data["dailyTrafficStats"] = statMaps
|
||||||
|
}
|
||||||
|
|
||||||
this.Show()
|
this.Show()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import (
|
|||||||
func init() {
|
func init() {
|
||||||
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
||||||
server.Prefix("/dashboard").
|
server.Prefix("/dashboard").
|
||||||
|
Data("teaMenu", "dashboard").
|
||||||
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeCommon)).
|
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeCommon)).
|
||||||
GetPost("", new(IndexAction)).
|
GetPost("", new(IndexAction)).
|
||||||
EndAll()
|
EndAll()
|
||||||
|
|||||||
56
internal/web/actions/default/db/cleanPopup.go
Normal file
56
internal/web/actions/default/db/cleanPopup.go
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
package db
|
||||||
|
|
||||||
|
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/iwind/TeaGo/actions"
|
||||||
|
"github.com/iwind/TeaGo/maps"
|
||||||
|
)
|
||||||
|
|
||||||
|
type CleanPopupAction struct {
|
||||||
|
actionutils.ParentAction
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *CleanPopupAction) Init() {
|
||||||
|
this.Nav("", "", "")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *CleanPopupAction) RunGet(params struct {
|
||||||
|
NodeId int64
|
||||||
|
}) {
|
||||||
|
this.Data["nodeId"] = params.NodeId
|
||||||
|
|
||||||
|
this.Show()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *CleanPopupAction) RunPost(params struct {
|
||||||
|
NodeId int64
|
||||||
|
|
||||||
|
Must *actions.Must
|
||||||
|
}) {
|
||||||
|
tablesResp, err := this.RPC().DBNodeRPC().FindAllDBNodeTables(this.AdminContext(), &pb.FindAllDBNodeTablesRequest{
|
||||||
|
DbNodeId: params.NodeId,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
tableMaps := []maps.Map{}
|
||||||
|
for _, table := range tablesResp.DbNodeTables {
|
||||||
|
if !table.IsBaseTable || (!table.CanClean && !table.CanDelete) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
tableMaps = append(tableMaps, maps.Map{
|
||||||
|
"name": table.Name,
|
||||||
|
"rows": table.Rows,
|
||||||
|
"size": numberutils.FormatBytes(table.DataLength + table.IndexLength),
|
||||||
|
"canDelete": table.CanDelete,
|
||||||
|
"canClean": table.CanClean,
|
||||||
|
"comment": table.Comment,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
this.Data["tables"] = tableMaps
|
||||||
|
this.Success()
|
||||||
|
}
|
||||||
@@ -62,7 +62,7 @@ func (this *CreatePopupAction) RunPost(params struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 创建日志
|
// 创建日志
|
||||||
defer this.CreateLog(oplogs.LevelInfo, "创建数据库节点 %d", createResp.NodeId)
|
defer this.CreateLog(oplogs.LevelInfo, "创建数据库节点 %d", createResp.DbNodeId)
|
||||||
|
|
||||||
this.Success()
|
this.Success()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ func (this *DeleteAction) RunPost(params struct {
|
|||||||
// 创建日志
|
// 创建日志
|
||||||
defer this.CreateLog(oplogs.LevelInfo, "删除数据库节点 %d", params.NodeId)
|
defer this.CreateLog(oplogs.LevelInfo, "删除数据库节点 %d", params.NodeId)
|
||||||
|
|
||||||
_, err := this.RPC().DBNodeRPC().DeleteDBNode(this.AdminContext(), &pb.DeleteDBNodeRequest{NodeId: params.NodeId})
|
_, err := this.RPC().DBNodeRPC().DeleteDBNode(this.AdminContext(), &pb.DeleteDBNodeRequest{DbNodeId: params.NodeId})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
this.ErrorPage(err)
|
this.ErrorPage(err)
|
||||||
return
|
return
|
||||||
|
|||||||
27
internal/web/actions/default/db/deleteTable.go
Normal file
27
internal/web/actions/default/db/deleteTable.go
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
package db
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
|
)
|
||||||
|
|
||||||
|
type DeleteTableAction struct {
|
||||||
|
actionutils.ParentAction
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *DeleteTableAction) RunPost(params struct {
|
||||||
|
NodeId int64
|
||||||
|
Table string
|
||||||
|
}) {
|
||||||
|
defer this.CreateLogInfo("删除数据库节点 %d 数据表 %s", params.NodeId, params.Table)
|
||||||
|
|
||||||
|
_, err := this.RPC().DBNodeRPC().DeleteDBNodeTable(this.AdminContext(), &pb.DeleteDBNodeTableRequest{
|
||||||
|
DbNodeId: params.NodeId,
|
||||||
|
DbNodeTable: params.Table,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.Success()
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
package db
|
package db
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/utils/numberutils"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
"github.com/iwind/TeaGo/maps"
|
"github.com/iwind/TeaGo/maps"
|
||||||
@@ -32,7 +33,7 @@ func (this *IndexAction) RunGet(params struct{}) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
nodeMaps := []maps.Map{}
|
nodeMaps := []maps.Map{}
|
||||||
for _, node := range listResp.Nodes {
|
for _, node := range listResp.DbNodes {
|
||||||
nodeMaps = append(nodeMaps, maps.Map{
|
nodeMaps = append(nodeMaps, maps.Map{
|
||||||
"id": node.Id,
|
"id": node.Id,
|
||||||
"isOn": node.IsOn,
|
"isOn": node.IsOn,
|
||||||
@@ -40,6 +41,11 @@ func (this *IndexAction) RunGet(params struct{}) {
|
|||||||
"host": node.Host,
|
"host": node.Host,
|
||||||
"port": node.Port,
|
"port": node.Port,
|
||||||
"database": node.Database,
|
"database": node.Database,
|
||||||
|
"status": maps.Map{
|
||||||
|
"isOk": node.Status.IsOk,
|
||||||
|
"error": node.Status.Error,
|
||||||
|
"size": numberutils.FormatBytes(node.Status.Size),
|
||||||
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,9 @@ func init() {
|
|||||||
GetPost("/createPopup", new(CreatePopupAction)).
|
GetPost("/createPopup", new(CreatePopupAction)).
|
||||||
GetPost("/updatePopup", new(UpdatePopupAction)).
|
GetPost("/updatePopup", new(UpdatePopupAction)).
|
||||||
Post("/delete", new(DeleteAction)).
|
Post("/delete", new(DeleteAction)).
|
||||||
|
GetPost("/cleanPopup", new(CleanPopupAction)).
|
||||||
|
Post("/deleteTable", new(DeleteTableAction)).
|
||||||
|
Post("/truncateTable", new(TruncateTableAction)).
|
||||||
|
|
||||||
EndAll()
|
EndAll()
|
||||||
})
|
})
|
||||||
|
|||||||
27
internal/web/actions/default/db/truncateTable.go
Normal file
27
internal/web/actions/default/db/truncateTable.go
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
package db
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
|
)
|
||||||
|
|
||||||
|
type TruncateTableAction struct {
|
||||||
|
actionutils.ParentAction
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *TruncateTableAction) RunPost(params struct {
|
||||||
|
NodeId int64
|
||||||
|
Table string
|
||||||
|
}) {
|
||||||
|
defer this.CreateLogInfo("清空数据库节点 %d 数据表 %s 数据", params.NodeId, params.Table)
|
||||||
|
|
||||||
|
_, err := this.RPC().DBNodeRPC().TruncateDBNodeTable(this.AdminContext(), &pb.TruncateDBNodeTableRequest{
|
||||||
|
DbNodeId: params.NodeId,
|
||||||
|
DbNodeTable: params.Table,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.Success()
|
||||||
|
}
|
||||||
@@ -19,13 +19,13 @@ func (this *UpdatePopupAction) Init() {
|
|||||||
func (this *UpdatePopupAction) RunGet(params struct {
|
func (this *UpdatePopupAction) RunGet(params struct {
|
||||||
NodeId int64
|
NodeId int64
|
||||||
}) {
|
}) {
|
||||||
nodeResp, err := this.RPC().DBNodeRPC().FindEnabledDBNode(this.AdminContext(), &pb.FindEnabledDBNodeRequest{NodeId: params.NodeId})
|
nodeResp, err := this.RPC().DBNodeRPC().FindEnabledDBNode(this.AdminContext(), &pb.FindEnabledDBNodeRequest{DbNodeId: params.NodeId})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
this.ErrorPage(err)
|
this.ErrorPage(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
node := nodeResp.Node
|
node := nodeResp.DbNode
|
||||||
if node == nil {
|
if node == nil {
|
||||||
this.NotFound("dbNode", params.NodeId)
|
this.NotFound("dbNode", params.NodeId)
|
||||||
return
|
return
|
||||||
@@ -78,7 +78,7 @@ func (this *UpdatePopupAction) RunPost(params struct {
|
|||||||
Require("请输入连接数据库的用户名")
|
Require("请输入连接数据库的用户名")
|
||||||
|
|
||||||
_, err := this.RPC().DBNodeRPC().UpdateDBNode(this.AdminContext(), &pb.UpdateDBNodeRequest{
|
_, err := this.RPC().DBNodeRPC().UpdateDBNode(this.AdminContext(), &pb.UpdateDBNodeRequest{
|
||||||
NodeId: params.NodeId,
|
DbNodeId: params.NodeId,
|
||||||
IsOn: params.IsOn,
|
IsOn: params.IsOn,
|
||||||
Name: params.Name,
|
Name: params.Name,
|
||||||
Description: params.Description,
|
Description: params.Description,
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
"github.com/iwind/TeaGo/actions"
|
"github.com/iwind/TeaGo/actions"
|
||||||
"github.com/iwind/TeaGo/maps"
|
"github.com/iwind/TeaGo/maps"
|
||||||
|
"github.com/iwind/TeaGo/rands"
|
||||||
)
|
)
|
||||||
|
|
||||||
type CreatePopupAction struct {
|
type CreatePopupAction struct {
|
||||||
@@ -32,6 +33,9 @@ func (this *CreatePopupAction) RunGet(params struct{}) {
|
|||||||
}
|
}
|
||||||
this.Data["types"] = typeMaps
|
this.Data["types"] = typeMaps
|
||||||
|
|
||||||
|
// 自动生成CustomHTTP私钥
|
||||||
|
this.Data["paramCustomHTTPSecret"] = rands.HexString(32)
|
||||||
|
|
||||||
this.Show()
|
this.Show()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,6 +55,10 @@ func (this *CreatePopupAction) RunPost(params struct {
|
|||||||
ParamApiKey string
|
ParamApiKey string
|
||||||
ParamApiSecret string
|
ParamApiSecret string
|
||||||
|
|
||||||
|
// CustomHTTP
|
||||||
|
ParamCustomHTTPURL string
|
||||||
|
ParamCustomHTTPSecret string
|
||||||
|
|
||||||
Must *actions.Must
|
Must *actions.Must
|
||||||
CSRF *actionutils.CSRF
|
CSRF *actionutils.CSRF
|
||||||
}) {
|
}) {
|
||||||
@@ -89,6 +97,15 @@ func (this *CreatePopupAction) RunPost(params struct {
|
|||||||
|
|
||||||
apiParams["apiKey"] = params.ParamApiKey
|
apiParams["apiKey"] = params.ParamApiKey
|
||||||
apiParams["apiSecret"] = params.ParamApiSecret
|
apiParams["apiSecret"] = params.ParamApiSecret
|
||||||
|
case "customHTTP":
|
||||||
|
params.Must.
|
||||||
|
Field("paramCustomHTTPURL", params.ParamCustomHTTPURL).
|
||||||
|
Require("请输入HTTP URL").
|
||||||
|
Match("^(?i)(http|https):", "URL必须以http://或者https://开头").
|
||||||
|
Field("paramCustomHTTPSecret", params.ParamCustomHTTPSecret).
|
||||||
|
Require("请输入私钥")
|
||||||
|
apiParams["url"] = params.ParamCustomHTTPURL
|
||||||
|
apiParams["secret"] = params.ParamCustomHTTPSecret
|
||||||
default:
|
default:
|
||||||
this.Fail("暂时不支持此服务商'" + params.Type + "'")
|
this.Fail("暂时不支持此服务商'" + params.Type + "'")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -84,6 +84,10 @@ func (this *UpdatePopupAction) RunPost(params struct {
|
|||||||
ParamApiKey string
|
ParamApiKey string
|
||||||
ParamApiSecret string
|
ParamApiSecret string
|
||||||
|
|
||||||
|
// CustomHTTP
|
||||||
|
ParamCustomHTTPURL string
|
||||||
|
ParamCustomHTTPSecret string
|
||||||
|
|
||||||
Must *actions.Must
|
Must *actions.Must
|
||||||
CSRF *actionutils.CSRF
|
CSRF *actionutils.CSRF
|
||||||
}) {
|
}) {
|
||||||
@@ -124,6 +128,15 @@ func (this *UpdatePopupAction) RunPost(params struct {
|
|||||||
|
|
||||||
apiParams["apiKey"] = params.ParamApiKey
|
apiParams["apiKey"] = params.ParamApiKey
|
||||||
apiParams["apiSecret"] = params.ParamApiSecret
|
apiParams["apiSecret"] = params.ParamApiSecret
|
||||||
|
case "customHTTP":
|
||||||
|
params.Must.
|
||||||
|
Field("paramCustomHTTPURL", params.ParamCustomHTTPURL).
|
||||||
|
Require("请输入HTTP URL").
|
||||||
|
Match("^(?i)(http|https):", "URL必须以http://或者https://开头").
|
||||||
|
Field("paramCustomHTTPSecret", params.ParamCustomHTTPSecret).
|
||||||
|
Require("请输入私钥")
|
||||||
|
apiParams["url"] = params.ParamCustomHTTPURL
|
||||||
|
apiParams["secret"] = params.ParamCustomHTTPSecret
|
||||||
default:
|
default:
|
||||||
this.Fail("暂时不支持此服务商'" + params.Type + "'")
|
this.Fail("暂时不支持此服务商'" + params.Type + "'")
|
||||||
}
|
}
|
||||||
|
|||||||
23
internal/web/actions/default/dns/tasks/check.go
Normal file
23
internal/web/actions/default/dns/tasks/check.go
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
package tasks
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
|
)
|
||||||
|
|
||||||
|
type CheckAction struct {
|
||||||
|
actionutils.ParentAction
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *CheckAction) RunPost(params struct{}) {
|
||||||
|
resp, err := this.RPC().DNSTaskRPC().ExistsDNSTasks(this.AdminContext(), &pb.ExistsDNSTasksRequest{})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Data["isDoing"] = resp.ExistTasks
|
||||||
|
this.Data["hasError"] = resp.ExistError
|
||||||
|
|
||||||
|
this.Success()
|
||||||
|
}
|
||||||
24
internal/web/actions/default/dns/tasks/delete.go
Normal file
24
internal/web/actions/default/dns/tasks/delete.go
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
package tasks
|
||||||
|
|
||||||
|
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 {
|
||||||
|
TaskId int64
|
||||||
|
}) {
|
||||||
|
defer this.CreateLogInfo("删除DNS同步任务 %d", params.TaskId)
|
||||||
|
|
||||||
|
_, err := this.RPC().DNSTaskRPC().DeleteDNSTask(this.AdminContext(), &pb.DeleteDNSTaskRequest{DnsTaskId: params.TaskId})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Success()
|
||||||
|
}
|
||||||
22
internal/web/actions/default/dns/tasks/init.go
Normal file
22
internal/web/actions/default/dns/tasks/init.go
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
package tasks
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/clusterutils"
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
|
||||||
|
"github.com/iwind/TeaGo"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
||||||
|
server.
|
||||||
|
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeDNS)).
|
||||||
|
Helper(clusterutils.NewClustersHelper()).
|
||||||
|
Prefix("/dns/tasks").
|
||||||
|
GetPost("/listPopup", new(ListPopupAction)).
|
||||||
|
Post("/check", new(CheckAction)).
|
||||||
|
Post("/delete", new(DeleteAction)).
|
||||||
|
|
||||||
|
EndAll()
|
||||||
|
})
|
||||||
|
}
|
||||||
84
internal/web/actions/default/dns/tasks/listPopup.go
Normal file
84
internal/web/actions/default/dns/tasks/listPopup.go
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
package tasks
|
||||||
|
|
||||||
|
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"
|
||||||
|
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ListPopupAction struct {
|
||||||
|
actionutils.ParentAction
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *ListPopupAction) Init() {
|
||||||
|
this.Nav("", "", "")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *ListPopupAction) RunGet(params struct{}) {
|
||||||
|
this.retrieveTasks()
|
||||||
|
|
||||||
|
this.Show()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *ListPopupAction) RunPost(params struct {
|
||||||
|
Must *actions.Must
|
||||||
|
}) {
|
||||||
|
this.retrieveTasks()
|
||||||
|
this.Success()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *ListPopupAction) retrieveTasks() {
|
||||||
|
resp, err := this.RPC().DNSTaskRPC().FindAllDoingDNSTasks(this.AdminContext(), &pb.FindAllDoingDNSTasksRequest{})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
taskMaps := []maps.Map{}
|
||||||
|
for _, task := range resp.DnsTasks {
|
||||||
|
var clusterMap maps.Map = nil
|
||||||
|
var nodeMap maps.Map = nil
|
||||||
|
var serverMap maps.Map = nil
|
||||||
|
var domainMap maps.Map = nil
|
||||||
|
|
||||||
|
if task.NodeCluster != nil {
|
||||||
|
clusterMap = maps.Map{
|
||||||
|
"id": task.NodeCluster.Id,
|
||||||
|
"name": task.NodeCluster.Name,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if task.Node != nil {
|
||||||
|
nodeMap = maps.Map{
|
||||||
|
"id": task.Node.Id,
|
||||||
|
"name": task.Node.Name,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if task.Server != nil {
|
||||||
|
serverMap = maps.Map{
|
||||||
|
"id": task.Server.Id,
|
||||||
|
"name": task.Server.Name,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if task.DnsDomain != nil {
|
||||||
|
domainMap = maps.Map{
|
||||||
|
"id": task.DnsDomain.Id,
|
||||||
|
"name": task.DnsDomain.Name,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
taskMaps = append(taskMaps, maps.Map{
|
||||||
|
"id": task.Id,
|
||||||
|
"type": task.Type,
|
||||||
|
"isDone": task.IsDone,
|
||||||
|
"isOk": task.IsOk,
|
||||||
|
"error": task.Error,
|
||||||
|
"updatedTime": timeutil.FormatTime("Y-m-d H:i:s", task.UpdatedAt),
|
||||||
|
"cluster": clusterMap,
|
||||||
|
"node": nodeMap,
|
||||||
|
"server": serverMap,
|
||||||
|
"domain": domainMap,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
this.Data["tasks"] = taskMaps
|
||||||
|
}
|
||||||
@@ -65,6 +65,7 @@ func (this *IndexAction) RunGet(params struct {
|
|||||||
} else {
|
} else {
|
||||||
this.Data["version"] = teaconst.Version
|
this.Data["version"] = teaconst.Version
|
||||||
}
|
}
|
||||||
|
this.Data["faviconFileId"] = config.FaviconFileId
|
||||||
|
|
||||||
this.Show()
|
this.Show()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
|
||||||
"github.com/iwind/TeaGo/actions"
|
"github.com/iwind/TeaGo/actions"
|
||||||
"github.com/iwind/TeaGo/maps"
|
"github.com/iwind/TeaGo/maps"
|
||||||
)
|
)
|
||||||
@@ -28,7 +29,8 @@ func (this *CreatePopupAction) RunPost(params struct {
|
|||||||
Type string
|
Type string
|
||||||
|
|
||||||
// file
|
// file
|
||||||
FileDir string
|
FileDir string
|
||||||
|
FileMemoryCapacityJSON []byte
|
||||||
|
|
||||||
CapacityJSON []byte
|
CapacityJSON []byte
|
||||||
MaxSizeJSON []byte
|
MaxSizeJSON []byte
|
||||||
@@ -50,8 +52,21 @@ func (this *CreatePopupAction) RunPost(params struct {
|
|||||||
params.Must.
|
params.Must.
|
||||||
Field("fileDir", params.FileDir).
|
Field("fileDir", params.FileDir).
|
||||||
Require("请输入缓存目录")
|
Require("请输入缓存目录")
|
||||||
|
|
||||||
|
memoryCapacity := &shared.SizeCapacity{}
|
||||||
|
if len(params.FileMemoryCapacityJSON) > 0 {
|
||||||
|
err := json.Unmarshal(params.FileMemoryCapacityJSON, memoryCapacity)
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
options = &serverconfigs.HTTPFileCacheStorage{
|
options = &serverconfigs.HTTPFileCacheStorage{
|
||||||
Dir: params.FileDir,
|
Dir: params.FileDir,
|
||||||
|
MemoryPolicy: &serverconfigs.HTTPCachePolicy{
|
||||||
|
Capacity: memoryCapacity,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
case serverconfigs.CachePolicyStorageMemory:
|
case serverconfigs.CachePolicyStorageMemory:
|
||||||
options = &serverconfigs.HTTPMemoryCacheStorage{
|
options = &serverconfigs.HTTPMemoryCacheStorage{
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
|
||||||
"github.com/iwind/TeaGo/actions"
|
"github.com/iwind/TeaGo/actions"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -52,7 +53,8 @@ func (this *UpdateAction) RunPost(params struct {
|
|||||||
Type string
|
Type string
|
||||||
|
|
||||||
// file
|
// file
|
||||||
FileDir string
|
FileDir string
|
||||||
|
FileMemoryCapacityJSON []byte
|
||||||
|
|
||||||
CapacityJSON []byte
|
CapacityJSON []byte
|
||||||
MaxSizeJSON []byte
|
MaxSizeJSON []byte
|
||||||
@@ -74,8 +76,21 @@ func (this *UpdateAction) RunPost(params struct {
|
|||||||
params.Must.
|
params.Must.
|
||||||
Field("fileDir", params.FileDir).
|
Field("fileDir", params.FileDir).
|
||||||
Require("请输入缓存目录")
|
Require("请输入缓存目录")
|
||||||
|
|
||||||
|
memoryCapacity := &shared.SizeCapacity{}
|
||||||
|
if len(params.FileMemoryCapacityJSON) > 0 {
|
||||||
|
err := json.Unmarshal(params.FileMemoryCapacityJSON, memoryCapacity)
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
options = &serverconfigs.HTTPFileCacheStorage{
|
options = &serverconfigs.HTTPFileCacheStorage{
|
||||||
Dir: params.FileDir,
|
Dir: params.FileDir,
|
||||||
|
MemoryPolicy: &serverconfigs.HTTPCachePolicy{
|
||||||
|
Capacity: memoryCapacity,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
case serverconfigs.CachePolicyStorageMemory:
|
case serverconfigs.CachePolicyStorageMemory:
|
||||||
options = &serverconfigs.HTTPMemoryCacheStorage{
|
options = &serverconfigs.HTTPMemoryCacheStorage{
|
||||||
@@ -91,14 +106,14 @@ func (this *UpdateAction) RunPost(params struct {
|
|||||||
}
|
}
|
||||||
_, err = this.RPC().HTTPCachePolicyRPC().UpdateHTTPCachePolicy(this.AdminContext(), &pb.UpdateHTTPCachePolicyRequest{
|
_, err = this.RPC().HTTPCachePolicyRPC().UpdateHTTPCachePolicy(this.AdminContext(), &pb.UpdateHTTPCachePolicyRequest{
|
||||||
HttpCachePolicyId: params.CachePolicyId,
|
HttpCachePolicyId: params.CachePolicyId,
|
||||||
IsOn: params.IsOn,
|
IsOn: params.IsOn,
|
||||||
Name: params.Name,
|
Name: params.Name,
|
||||||
Description: params.Description,
|
Description: params.Description,
|
||||||
CapacityJSON: params.CapacityJSON,
|
CapacityJSON: params.CapacityJSON,
|
||||||
MaxKeys: params.MaxKeys,
|
MaxKeys: params.MaxKeys,
|
||||||
MaxSizeJSON: params.MaxSizeJSON,
|
MaxSizeJSON: params.MaxSizeJSON,
|
||||||
Type: params.Type,
|
Type: params.Type,
|
||||||
OptionsJSON: optionsJSON,
|
OptionsJSON: optionsJSON,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
this.ErrorPage(err)
|
this.ErrorPage(err)
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ func init() {
|
|||||||
GetPost("/ipadmin/createIPPopup", new(ipadmin.CreateIPPopupAction)).
|
GetPost("/ipadmin/createIPPopup", new(ipadmin.CreateIPPopupAction)).
|
||||||
GetPost("/ipadmin/updateIPPopup", new(ipadmin.UpdateIPPopupAction)).
|
GetPost("/ipadmin/updateIPPopup", new(ipadmin.UpdateIPPopupAction)).
|
||||||
Post("/ipadmin/deleteIP", new(ipadmin.DeleteIPAction)).
|
Post("/ipadmin/deleteIP", new(ipadmin.DeleteIPAction)).
|
||||||
|
GetPost("/ipadmin/test", new(ipadmin.TestAction)).
|
||||||
|
|
||||||
EndAll()
|
EndAll()
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ func (this *CreateIPPopupAction) RunGet(params struct {
|
|||||||
FirewallPolicyId int64
|
FirewallPolicyId int64
|
||||||
Type string
|
Type string
|
||||||
}) {
|
}) {
|
||||||
this.Data["type"] = params.Type
|
this.Data["listType"] = params.Type
|
||||||
|
|
||||||
listId, err := dao.SharedHTTPFirewallPolicyDAO.FindEnabledPolicyIPListIdWithType(this.AdminContext(), params.FirewallPolicyId, params.Type)
|
listId, err := dao.SharedHTTPFirewallPolicyDAO.FindEnabledPolicyIPListIdWithType(this.AdminContext(), params.FirewallPolicyId, params.Type)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -40,41 +40,57 @@ func (this *CreateIPPopupAction) RunPost(params struct {
|
|||||||
IpTo string
|
IpTo string
|
||||||
ExpiredAt int64
|
ExpiredAt int64
|
||||||
Reason string
|
Reason string
|
||||||
|
Type string
|
||||||
|
EventLevel string
|
||||||
|
|
||||||
Must *actions.Must
|
Must *actions.Must
|
||||||
CSRF *actionutils.CSRF
|
CSRF *actionutils.CSRF
|
||||||
}) {
|
}) {
|
||||||
// TODO 校验ListId所属用户
|
// TODO 校验ListId所属用户
|
||||||
|
|
||||||
params.Must.
|
switch params.Type {
|
||||||
Field("ipFrom", params.IpFrom).
|
case "ipv4":
|
||||||
Require("请输入开始IP")
|
params.Must.
|
||||||
|
Field("ipFrom", params.IpFrom).
|
||||||
|
Require("请输入开始IP")
|
||||||
|
|
||||||
// 校验IP格式(ipFrom/ipTo)
|
// 校验IP格式(ipFrom/ipTo)
|
||||||
ipFromLong := utils.IP2Long(params.IpFrom)
|
var ipFromLong uint64
|
||||||
if len(params.IpFrom) > 0 {
|
if !utils.IsIPv4(params.IpFrom) {
|
||||||
if ipFromLong == 0 {
|
|
||||||
this.Fail("请输入正确的开始IP")
|
this.Fail("请输入正确的开始IP")
|
||||||
}
|
}
|
||||||
}
|
ipFromLong = utils.IP2Long(params.IpFrom)
|
||||||
|
|
||||||
ipToLong := utils.IP2Long(params.IpTo)
|
var ipToLong uint64
|
||||||
if len(params.IpTo) > 0 {
|
if len(params.IpTo) > 0 && !utils.IsIPv4(params.IpTo) {
|
||||||
if ipToLong == 0 {
|
ipToLong = utils.IP2Long(params.IpTo)
|
||||||
this.Fail("请输入正确的结束IP")
|
this.Fail("请输入正确的结束IP")
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if ipFromLong > 0 && ipToLong > 0 && ipFromLong > ipToLong {
|
if ipFromLong > 0 && ipToLong > 0 && ipFromLong > ipToLong {
|
||||||
params.IpTo, params.IpFrom = params.IpFrom, params.IpTo
|
params.IpTo, params.IpFrom = params.IpFrom, params.IpTo
|
||||||
|
}
|
||||||
|
case "ipv6":
|
||||||
|
params.Must.
|
||||||
|
Field("ipFrom", params.IpFrom).
|
||||||
|
Require("请输入IP")
|
||||||
|
|
||||||
|
// 校验IP格式(ipFrom)
|
||||||
|
if !utils.IsIPv6(params.IpFrom) {
|
||||||
|
this.Fail("请输入正确的IPv6地址")
|
||||||
|
}
|
||||||
|
case "all":
|
||||||
|
params.IpFrom = "0.0.0.0"
|
||||||
}
|
}
|
||||||
|
|
||||||
createResp, err := this.RPC().IPItemRPC().CreateIPItem(this.AdminContext(), &pb.CreateIPItemRequest{
|
createResp, err := this.RPC().IPItemRPC().CreateIPItem(this.AdminContext(), &pb.CreateIPItemRequest{
|
||||||
IpListId: params.ListId,
|
IpListId: params.ListId,
|
||||||
IpFrom: params.IpFrom,
|
IpFrom: params.IpFrom,
|
||||||
IpTo: params.IpTo,
|
IpTo: params.IpTo,
|
||||||
ExpiredAt: params.ExpiredAt,
|
ExpiredAt: params.ExpiredAt,
|
||||||
Reason: params.Reason,
|
Reason: params.Reason,
|
||||||
|
Type: params.Type,
|
||||||
|
EventLevel: params.EventLevel,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
this.ErrorPage(err)
|
this.ErrorPage(err)
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
|
||||||
"github.com/iwind/TeaGo/maps"
|
"github.com/iwind/TeaGo/maps"
|
||||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||||
)
|
)
|
||||||
@@ -58,11 +59,13 @@ func (this *ListsAction) RunGet(params struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
itemMaps = append(itemMaps, maps.Map{
|
itemMaps = append(itemMaps, maps.Map{
|
||||||
"id": item.Id,
|
"id": item.Id,
|
||||||
"ipFrom": item.IpFrom,
|
"ipFrom": item.IpFrom,
|
||||||
"ipTo": item.IpTo,
|
"ipTo": item.IpTo,
|
||||||
"expiredTime": expiredTime,
|
"expiredTime": expiredTime,
|
||||||
"reason": item.Reason,
|
"reason": item.Reason,
|
||||||
|
"type": item.Type,
|
||||||
|
"eventLevelName": firewallconfigs.FindFirewallEventLevelName(item.EventLevel),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
this.Data["items"] = itemMaps
|
this.Data["items"] = itemMaps
|
||||||
|
|||||||
@@ -0,0 +1,87 @@
|
|||||||
|
package ipadmin
|
||||||
|
|
||||||
|
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("", "", "ipadmin")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *TestAction) RunGet(params struct {
|
||||||
|
FirewallPolicyId int64
|
||||||
|
}) {
|
||||||
|
this.Data["subMenuItem"] = "test"
|
||||||
|
|
||||||
|
this.Show()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *TestAction) RunPost(params struct {
|
||||||
|
FirewallPolicyId int64
|
||||||
|
Ip string
|
||||||
|
|
||||||
|
Must *actions.Must
|
||||||
|
}) {
|
||||||
|
resp, err := this.RPC().HTTPFirewallPolicyRPC().CheckHTTPFirewallPolicyIPStatus(this.AdminContext(), &pb.CheckHTTPFirewallPolicyIPStatusRequest{
|
||||||
|
HttpFirewallPolicyId: params.FirewallPolicyId,
|
||||||
|
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.IpList != nil {
|
||||||
|
resultMap["list"] = maps.Map{
|
||||||
|
"id": resp.IpList.Id,
|
||||||
|
"name": resp.IpList.Name,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if resp.RegionCountry != nil {
|
||||||
|
resultMap["country"] = maps.Map{
|
||||||
|
"id": resp.RegionCountry.Id,
|
||||||
|
"name": resp.RegionCountry.Name,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if resp.RegionProvince != nil {
|
||||||
|
resultMap["province"] = maps.Map{
|
||||||
|
"id": resp.RegionProvince.Id,
|
||||||
|
"name": resp.RegionProvince.Name,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Data["result"] = resultMap
|
||||||
|
|
||||||
|
this.Success()
|
||||||
|
}
|
||||||
@@ -32,13 +32,17 @@ func (this *UpdateIPPopupAction) RunGet(params struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.Data["item"] = maps.Map{
|
this.Data["item"] = maps.Map{
|
||||||
"id": item.Id,
|
"id": item.Id,
|
||||||
"ipFrom": item.IpFrom,
|
"ipFrom": item.IpFrom,
|
||||||
"ipTo": item.IpTo,
|
"ipTo": item.IpTo,
|
||||||
"expiredAt": item.ExpiredAt,
|
"expiredAt": item.ExpiredAt,
|
||||||
"reason": item.Reason,
|
"reason": item.Reason,
|
||||||
|
"type": item.Type,
|
||||||
|
"eventLevel": item.EventLevel,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.Data["type"] = item.Type
|
||||||
|
|
||||||
this.Show()
|
this.Show()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -46,10 +50,12 @@ func (this *UpdateIPPopupAction) RunPost(params struct {
|
|||||||
FirewallPolicyId int64
|
FirewallPolicyId int64
|
||||||
ItemId int64
|
ItemId int64
|
||||||
|
|
||||||
IpFrom string
|
IpFrom string
|
||||||
IpTo string
|
IpTo string
|
||||||
ExpiredAt int64
|
ExpiredAt int64
|
||||||
Reason string
|
Reason string
|
||||||
|
Type string
|
||||||
|
EventLevel string
|
||||||
|
|
||||||
Must *actions.Must
|
Must *actions.Must
|
||||||
CSRF *actionutils.CSRF
|
CSRF *actionutils.CSRF
|
||||||
@@ -59,35 +65,49 @@ func (this *UpdateIPPopupAction) RunPost(params struct {
|
|||||||
|
|
||||||
// TODO 校验ItemId所属用户
|
// TODO 校验ItemId所属用户
|
||||||
|
|
||||||
params.Must.
|
switch params.Type {
|
||||||
Field("ipFrom", params.IpFrom).
|
case "ipv4":
|
||||||
Require("请输入开始IP")
|
params.Must.
|
||||||
|
Field("ipFrom", params.IpFrom).
|
||||||
|
Require("请输入开始IP")
|
||||||
|
|
||||||
// 校验IP格式(ipFrom/ipTo)
|
// 校验IP格式(ipFrom/ipTo)
|
||||||
ipFromLong := utils.IP2Long(params.IpFrom)
|
var ipFromLong uint64
|
||||||
if len(params.IpFrom) > 0 {
|
if !utils.IsIPv4(params.IpFrom) {
|
||||||
if ipFromLong == 0 {
|
|
||||||
this.Fail("请输入正确的开始IP")
|
this.Fail("请输入正确的开始IP")
|
||||||
}
|
}
|
||||||
}
|
ipFromLong = utils.IP2Long(params.IpFrom)
|
||||||
|
|
||||||
ipToLong := utils.IP2Long(params.IpTo)
|
var ipToLong uint64
|
||||||
if len(params.IpTo) > 0 {
|
if len(params.IpTo) > 0 && !utils.IsIPv4(params.IpTo) {
|
||||||
if ipToLong == 0 {
|
ipToLong = utils.IP2Long(params.IpTo)
|
||||||
this.Fail("请输入正确的结束IP")
|
this.Fail("请输入正确的结束IP")
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if ipFromLong > 0 && ipToLong > 0 && ipFromLong > ipToLong {
|
if ipFromLong > 0 && ipToLong > 0 && ipFromLong > ipToLong {
|
||||||
params.IpTo, params.IpFrom = params.IpFrom, params.IpTo
|
params.IpTo, params.IpFrom = params.IpFrom, params.IpTo
|
||||||
|
}
|
||||||
|
case "ipv6":
|
||||||
|
params.Must.
|
||||||
|
Field("ipFrom", params.IpFrom).
|
||||||
|
Require("请输入IP")
|
||||||
|
|
||||||
|
// 校验IP格式(ipFrom)
|
||||||
|
if !utils.IsIPv6(params.IpFrom) {
|
||||||
|
this.Fail("请输入正确的IPv6地址")
|
||||||
|
}
|
||||||
|
case "all":
|
||||||
|
params.IpFrom = "0.0.0.0"
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := this.RPC().IPItemRPC().UpdateIPItem(this.AdminContext(), &pb.UpdateIPItemRequest{
|
_, err := this.RPC().IPItemRPC().UpdateIPItem(this.AdminContext(), &pb.UpdateIPItemRequest{
|
||||||
IpItemId: params.ItemId,
|
IpItemId: params.ItemId,
|
||||||
IpFrom: params.IpFrom,
|
IpFrom: params.IpFrom,
|
||||||
IpTo: params.IpTo,
|
IpTo: params.IpTo,
|
||||||
ExpiredAt: params.ExpiredAt,
|
ExpiredAt: params.ExpiredAt,
|
||||||
Reason: params.Reason,
|
Reason: params.Reason,
|
||||||
|
Type: params.Type,
|
||||||
|
EventLevel: params.EventLevel,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
this.ErrorPage(err)
|
this.ErrorPage(err)
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
|
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
|
||||||
|
"github.com/iwind/TeaGo/lists"
|
||||||
"github.com/iwind/TeaGo/maps"
|
"github.com/iwind/TeaGo/maps"
|
||||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||||
"regexp"
|
"regexp"
|
||||||
@@ -35,6 +36,7 @@ func (this *LogAction) RunGet(params struct {
|
|||||||
this.Data["accessLogs"] = []interface{}{}
|
this.Data["accessLogs"] = []interface{}{}
|
||||||
|
|
||||||
day := params.Day
|
day := params.Day
|
||||||
|
ipList := []string{}
|
||||||
if len(day) > 0 && regexp.MustCompile(`\d{4}-\d{2}-\d{2}`).MatchString(day) {
|
if len(day) > 0 && regexp.MustCompile(`\d{4}-\d{2}-\d{2}`).MatchString(day) {
|
||||||
day = strings.ReplaceAll(day, "-", "")
|
day = strings.ReplaceAll(day, "-", "")
|
||||||
size := int64(10)
|
size := int64(10)
|
||||||
@@ -55,6 +57,13 @@ func (this *LogAction) RunGet(params struct {
|
|||||||
this.Data["accessLogs"] = []interface{}{}
|
this.Data["accessLogs"] = []interface{}{}
|
||||||
} else {
|
} else {
|
||||||
this.Data["accessLogs"] = resp.AccessLogs
|
this.Data["accessLogs"] = resp.AccessLogs
|
||||||
|
for _, accessLog := range resp.AccessLogs {
|
||||||
|
if len(accessLog.RemoteAddr) > 0 {
|
||||||
|
if !lists.ContainsString(ipList, accessLog.RemoteAddr) {
|
||||||
|
ipList = append(ipList, accessLog.RemoteAddr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
this.Data["hasMore"] = resp.HasMore
|
this.Data["hasMore"] = resp.HasMore
|
||||||
this.Data["nextRequestId"] = resp.RequestId
|
this.Data["nextRequestId"] = resp.RequestId
|
||||||
@@ -106,5 +115,21 @@ func (this *LogAction) RunGet(params struct {
|
|||||||
}
|
}
|
||||||
this.Data["groups"] = groupMaps
|
this.Data["groups"] = groupMaps
|
||||||
|
|
||||||
|
// 根据IP查询区域
|
||||||
|
regionMap := map[string]string{} // ip => region
|
||||||
|
if len(ipList) > 0 {
|
||||||
|
resp, err := this.RPC().IPLibraryRPC().LookupIPRegions(this.AdminContext(), &pb.LookupIPRegionsRequest{IpList: ipList})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if resp.IpRegionMap != nil {
|
||||||
|
for ip, region := range resp.IpRegionMap {
|
||||||
|
regionMap[ip] = region.Summary
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.Data["regions"] = regionMap
|
||||||
|
|
||||||
this.Show()
|
this.Show()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import (
|
|||||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/sslconfigs"
|
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/sslconfigs"
|
||||||
"github.com/iwind/TeaGo/actions"
|
"github.com/iwind/TeaGo/actions"
|
||||||
"github.com/iwind/TeaGo/maps"
|
"github.com/iwind/TeaGo/maps"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
type CreateAction struct {
|
type CreateAction struct {
|
||||||
@@ -215,6 +216,22 @@ func (this *CreateAction) RunPost(params struct {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
this.Fail("域名解析失败:" + err.Error())
|
this.Fail("域名解析失败:" + err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 检查域名是否已经存在
|
||||||
|
allServerNames := serverconfigs.PlainServerNames(serverNames)
|
||||||
|
if len(allServerNames) > 0 {
|
||||||
|
dupResp, err := this.RPC().ServerRPC().CheckServerNameDuplicationInNodeCluster(this.AdminContext(), &pb.CheckServerNameDuplicationInNodeClusterRequest{
|
||||||
|
ServerNames: allServerNames,
|
||||||
|
NodeClusterId: params.ClusterId,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if len(dupResp.DuplicatedServerNames) > 0 {
|
||||||
|
this.Fail("域名 " + strings.Join(dupResp.DuplicatedServerNames, ", ") + " 已经被其他服务所占用,不能重复使用")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 源站地址
|
// 源站地址
|
||||||
|
|||||||
@@ -86,6 +86,7 @@ func (this *SettingAction) RunPost(params struct {
|
|||||||
RequestURI: reverseProxyConfig.RequestURI,
|
RequestURI: reverseProxyConfig.RequestURI,
|
||||||
StripPrefix: reverseProxyConfig.StripPrefix,
|
StripPrefix: reverseProxyConfig.StripPrefix,
|
||||||
AutoFlush: reverseProxyConfig.AutoFlush,
|
AutoFlush: reverseProxyConfig.AutoFlush,
|
||||||
|
AddHeaders: reverseProxyConfig.AddHeaders,
|
||||||
})
|
})
|
||||||
|
|
||||||
this.Success()
|
this.Success()
|
||||||
|
|||||||
@@ -86,6 +86,7 @@ func (this *SettingAction) RunPost(params struct {
|
|||||||
RequestURI: reverseProxyConfig.RequestURI,
|
RequestURI: reverseProxyConfig.RequestURI,
|
||||||
StripPrefix: reverseProxyConfig.StripPrefix,
|
StripPrefix: reverseProxyConfig.StripPrefix,
|
||||||
AutoFlush: reverseProxyConfig.AutoFlush,
|
AutoFlush: reverseProxyConfig.AutoFlush,
|
||||||
|
AddHeaders: reverseProxyConfig.AddHeaders,
|
||||||
})
|
})
|
||||||
|
|
||||||
this.Success()
|
this.Success()
|
||||||
|
|||||||
@@ -70,10 +70,10 @@ func (this *UpdateSchedulingPopupAction) RunGet(params struct {
|
|||||||
if !types.IsSlice(networks) {
|
if !types.IsSlice(networks) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if (serverConfig.IsHTTP() && lists.Contains(networks, "http")) ||
|
if (serverConfig.IsHTTPFamily() && lists.Contains(networks, "http")) ||
|
||||||
(serverConfig.IsTCP() && lists.Contains(networks, "tcp")) ||
|
(serverConfig.IsTCPFamily() && lists.Contains(networks, "tcp")) ||
|
||||||
(serverConfig.IsUDP() && lists.Contains(networks, "udp")) ||
|
(serverConfig.IsUDPFamily() && lists.Contains(networks, "udp")) ||
|
||||||
(serverConfig.IsUnix() && lists.Contains(networks, "unix")) {
|
(serverConfig.IsUnixFamily() && lists.Contains(networks, "unix")) {
|
||||||
schedulingTypes = append(schedulingTypes, m)
|
schedulingTypes = append(schedulingTypes, m)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import (
|
|||||||
"github.com/iwind/TeaGo/actions"
|
"github.com/iwind/TeaGo/actions"
|
||||||
"github.com/iwind/TeaGo/maps"
|
"github.com/iwind/TeaGo/maps"
|
||||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// 域名管理
|
// 域名管理
|
||||||
@@ -74,6 +75,34 @@ func (this *IndexAction) RunPost(params struct {
|
|||||||
this.Fail("域名解析失败:" + err.Error())
|
this.Fail("域名解析失败:" + err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
serverResp, err := this.RPC().ServerRPC().FindEnabledUserServerBasic(this.AdminContext(), &pb.FindEnabledUserServerBasicRequest{ServerId: params.ServerId})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if serverResp.Server == nil || serverResp.Server.NodeCluster == nil {
|
||||||
|
this.NotFound("server", params.ServerId)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
clusterId := serverResp.Server.NodeCluster.Id
|
||||||
|
|
||||||
|
// 检查域名是否已经存在
|
||||||
|
allServerNames := serverconfigs.PlainServerNames(serverNames)
|
||||||
|
if len(allServerNames) > 0 {
|
||||||
|
dupResp, err := this.RPC().ServerRPC().CheckServerNameDuplicationInNodeCluster(this.AdminContext(), &pb.CheckServerNameDuplicationInNodeClusterRequest{
|
||||||
|
ServerNames: allServerNames,
|
||||||
|
NodeClusterId: clusterId,
|
||||||
|
ExcludeServerId: params.ServerId,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if len(dupResp.DuplicatedServerNames) > 0 {
|
||||||
|
this.Fail("域名 " + strings.Join(dupResp.DuplicatedServerNames, ", ") + " 已经被其他服务所占用,不能重复使用")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_, err = this.RPC().ServerRPC().UpdateServerNames(this.AdminContext(), &pb.UpdateServerNamesRequest{
|
_, err = this.RPC().ServerRPC().UpdateServerNames(this.AdminContext(), &pb.UpdateServerNamesRequest{
|
||||||
ServerId: params.ServerId,
|
ServerId: params.ServerId,
|
||||||
ServerNamesJSON: []byte(params.ServerNames),
|
ServerNamesJSON: []byte(params.ServerNames),
|
||||||
|
|||||||
@@ -0,0 +1,110 @@
|
|||||||
|
package waf
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
|
||||||
|
"github.com/iwind/TeaGo/lists"
|
||||||
|
"github.com/iwind/TeaGo/maps"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type GroupAction struct {
|
||||||
|
actionutils.ParentAction
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *GroupAction) Init() {
|
||||||
|
this.Nav("", "setting", this.ParamString("type"))
|
||||||
|
this.SecondMenu("waf")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *GroupAction) RunGet(params struct {
|
||||||
|
FirewallPolicyId int64
|
||||||
|
GroupId int64
|
||||||
|
Type string
|
||||||
|
}) {
|
||||||
|
this.Data["type"] = params.Type
|
||||||
|
this.Data["firewallPolicyId"] = params.FirewallPolicyId
|
||||||
|
|
||||||
|
// policy
|
||||||
|
firewallPolicy, err := dao.SharedHTTPFirewallPolicyDAO.FindEnabledHTTPFirewallPolicyConfig(this.AdminContext(), params.FirewallPolicyId)
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if firewallPolicy == nil {
|
||||||
|
this.NotFound("firewallPolicy", params.FirewallPolicyId)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// group config
|
||||||
|
groupConfig, err := dao.SharedHTTPFirewallRuleGroupDAO.FindRuleGroupConfig(this.AdminContext(), params.GroupId)
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if groupConfig == nil {
|
||||||
|
this.NotFound("firewallRuleGroup", params.GroupId)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Data["group"] = groupConfig
|
||||||
|
|
||||||
|
// rule sets
|
||||||
|
this.Data["sets"] = lists.Map(groupConfig.Sets, func(k int, v interface{}) interface{} {
|
||||||
|
set := v.(*firewallconfigs.HTTPFirewallRuleSet)
|
||||||
|
|
||||||
|
// 动作说明
|
||||||
|
actionLinks := []maps.Map{}
|
||||||
|
if set.Action == firewallconfigs.HTTPFirewallActionGoGroup {
|
||||||
|
nextGroup := firewallPolicy.FindRuleGroup(set.ActionOptions.GetInt64("groupId"))
|
||||||
|
if nextGroup != nil {
|
||||||
|
actionLinks = append(actionLinks, maps.Map{
|
||||||
|
"name": nextGroup.Name,
|
||||||
|
"url": "/servers/components/waf/group?firewallPolicyId=" + strconv.FormatInt(params.FirewallPolicyId, 10) + "&type=" + params.Type + "&groupId=" + strconv.FormatInt(nextGroup.Id, 10),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} else if set.Action == firewallconfigs.HTTPFirewallActionGoSet {
|
||||||
|
nextGroup := firewallPolicy.FindRuleGroup(set.ActionOptions.GetInt64("groupId"))
|
||||||
|
if nextGroup != nil {
|
||||||
|
actionLinks = append(actionLinks, maps.Map{
|
||||||
|
"name": nextGroup.Name,
|
||||||
|
"url": "/servers/components/waf/group?firewallPolicyId=" + strconv.FormatInt(params.FirewallPolicyId, 10) + "&type=" + params.Type + "&groupId=" + strconv.FormatInt(nextGroup.Id, 10),
|
||||||
|
})
|
||||||
|
|
||||||
|
nextSet := nextGroup.FindRuleSet(set.ActionOptions.GetInt64("setId"))
|
||||||
|
if nextSet != nil {
|
||||||
|
actionLinks = append(actionLinks, maps.Map{
|
||||||
|
"name": nextSet.Name,
|
||||||
|
"url": "/servers/components/waf/group?firewallPolicyId=" + strconv.FormatInt(params.FirewallPolicyId, 10) + "&type=" + params.Type + "&groupId=" + strconv.FormatInt(nextGroup.Id, 10),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return maps.Map{
|
||||||
|
"id": set.Id,
|
||||||
|
"name": set.Name,
|
||||||
|
"rules": lists.Map(set.Rules, func(k int, v interface{}) interface{} {
|
||||||
|
rule := v.(*firewallconfigs.HTTPFirewallRule)
|
||||||
|
return maps.Map{
|
||||||
|
"param": rule.Param,
|
||||||
|
"paramFilters": rule.ParamFilters,
|
||||||
|
"operator": rule.Operator,
|
||||||
|
"value": rule.Value,
|
||||||
|
"isCaseInsensitive": rule.IsCaseInsensitive,
|
||||||
|
"isComposed": firewallconfigs.CheckCheckpointIsComposed(rule.Prefix()),
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
"isOn": set.IsOn,
|
||||||
|
"action": strings.ToUpper(set.Action),
|
||||||
|
"actionOptions": set.ActionOptions,
|
||||||
|
"actionName": firewallconfigs.FindActionName(set.Action),
|
||||||
|
"actionLinks": actionLinks,
|
||||||
|
"connector": strings.ToUpper(set.Connector),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
this.Show()
|
||||||
|
}
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
package waf
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
|
||||||
|
"github.com/iwind/TeaGo/maps"
|
||||||
|
)
|
||||||
|
|
||||||
|
type GroupsAction struct {
|
||||||
|
actionutils.ParentAction
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *GroupsAction) Init() {
|
||||||
|
this.Nav("", "setting", this.ParamString("type"))
|
||||||
|
this.SecondMenu("waf")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *GroupsAction) RunGet(params struct {
|
||||||
|
ServerId int64
|
||||||
|
FirewallPolicyId int64
|
||||||
|
Type string
|
||||||
|
}) {
|
||||||
|
this.Data["firewallPolicyId"] = params.FirewallPolicyId
|
||||||
|
this.Data["type"] = params.Type
|
||||||
|
|
||||||
|
firewallPolicy, err := dao.SharedHTTPFirewallPolicyDAO.FindEnabledHTTPFirewallPolicyConfig(this.AdminContext(), params.FirewallPolicyId)
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if firewallPolicy == nil {
|
||||||
|
this.NotFound("firewallPolicy", params.FirewallPolicyId)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
groupMaps := []maps.Map{}
|
||||||
|
|
||||||
|
// inbound
|
||||||
|
if params.Type == "inbound" {
|
||||||
|
if firewallPolicy.Inbound != nil {
|
||||||
|
for _, g := range firewallPolicy.Inbound.Groups {
|
||||||
|
groupMaps = append(groupMaps, maps.Map{
|
||||||
|
"id": g.Id,
|
||||||
|
"name": g.Name,
|
||||||
|
"code": g.Code,
|
||||||
|
"isOn": g.IsOn,
|
||||||
|
"description": g.Description,
|
||||||
|
"countSets": len(g.Sets),
|
||||||
|
"canDelete": len(g.Code) == 0,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// outbound
|
||||||
|
if params.Type == "outbound" {
|
||||||
|
if firewallPolicy.Outbound != nil {
|
||||||
|
for _, g := range firewallPolicy.Outbound.Groups {
|
||||||
|
groupMaps = append(groupMaps, maps.Map{
|
||||||
|
"id": g.Id,
|
||||||
|
"name": g.Name,
|
||||||
|
"code": g.Code,
|
||||||
|
"isOn": g.IsOn,
|
||||||
|
"description": g.Description,
|
||||||
|
"countSets": len(g.Sets),
|
||||||
|
"canDelete": len(g.Code) == 0,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Data["groups"] = groupMaps
|
||||||
|
|
||||||
|
// WAF是否启用
|
||||||
|
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithServerId(this.AdminContext(), params.ServerId)
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.Data["wafIsOn"] = webConfig.FirewallRef != nil && webConfig.FirewallRef.IsOn
|
||||||
|
|
||||||
|
this.Show()
|
||||||
|
}
|
||||||
@@ -45,6 +45,18 @@ func (this *IndexAction) RunGet(params struct {
|
|||||||
this.Data["firewallPolicy"] = nil
|
this.Data["firewallPolicy"] = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 当前的Server独立设置
|
||||||
|
if webConfig.FirewallRef == nil || webConfig.FirewallRef.FirewallPolicyId == 0 {
|
||||||
|
firewallPolicyId, err := dao.SharedHTTPWebDAO.InitEmptyHTTPFirewallPolicy(this.AdminContext(), params.ServerId, webConfig.Id, webConfig.FirewallRef != nil && webConfig.FirewallRef.IsOn)
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.Data["firewallPolicyId"] = firewallPolicyId
|
||||||
|
} else {
|
||||||
|
this.Data["firewallPolicyId"] = webConfig.FirewallRef.FirewallPolicyId
|
||||||
|
}
|
||||||
|
|
||||||
this.Show()
|
this.Show()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package waf
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
|
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/server/settings/waf/ipadmin"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/serverutils"
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/serverutils"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
|
||||||
"github.com/iwind/TeaGo"
|
"github.com/iwind/TeaGo"
|
||||||
@@ -14,6 +15,18 @@ func init() {
|
|||||||
Helper(serverutils.NewServerHelper()).
|
Helper(serverutils.NewServerHelper()).
|
||||||
Prefix("/servers/server/settings/waf").
|
Prefix("/servers/server/settings/waf").
|
||||||
GetPost("", new(IndexAction)).
|
GetPost("", new(IndexAction)).
|
||||||
|
Get("/ipadmin/allowList", new(ipadmin.AllowListAction)).
|
||||||
|
Get("/ipadmin/denyList", new(ipadmin.DenyListAction)).
|
||||||
|
GetPost("/ipadmin/countries", new(ipadmin.CountriesAction)).
|
||||||
|
GetPost("/ipadmin/provinces", new(ipadmin.ProvincesAction)).
|
||||||
|
GetPost("/ipadmin/createIPPopup", new(ipadmin.CreateIPPopupAction)).
|
||||||
|
GetPost("/ipadmin/updateIPPopup", new(ipadmin.UpdateIPPopupAction)).
|
||||||
|
Post("/ipadmin/deleteIP", new(ipadmin.DeleteIPAction)).
|
||||||
|
GetPost("/ipadmin/test", new(ipadmin.TestAction)).
|
||||||
|
|
||||||
|
// 规则相关
|
||||||
|
Get("/groups", new(GroupsAction)).
|
||||||
|
Get("/group", new(GroupAction)).
|
||||||
EndAll()
|
EndAll()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,95 @@
|
|||||||
|
package ipadmin
|
||||||
|
|
||||||
|
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/iwind/TeaGo/maps"
|
||||||
|
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type AllowListAction struct {
|
||||||
|
actionutils.ParentAction
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *AllowListAction) Init() {
|
||||||
|
this.Nav("", "setting", "allowList")
|
||||||
|
this.SecondMenu("waf")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *AllowListAction) RunGet(params struct {
|
||||||
|
ServerId int64
|
||||||
|
FirewallPolicyId int64
|
||||||
|
}) {
|
||||||
|
this.Data["featureIsOn"] = true
|
||||||
|
this.Data["firewallPolicyId"] = params.FirewallPolicyId
|
||||||
|
|
||||||
|
listId, err := dao.SharedIPListDAO.FindAllowIPListIdWithServerId(this.AdminContext(), params.ServerId)
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建
|
||||||
|
if listId == 0 {
|
||||||
|
listId, err = dao.SharedIPListDAO.CreateIPListForServerId(this.AdminContext(), params.ServerId, "white")
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Data["listId"] = 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,
|
||||||
|
"isExpired": item.ExpiredAt > 0 && item.ExpiredAt < time.Now().Unix(),
|
||||||
|
"eventLevelName": firewallconfigs.FindFirewallEventLevelName(item.EventLevel),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
this.Data["items"] = itemMaps
|
||||||
|
|
||||||
|
// WAF是否启用
|
||||||
|
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithServerId(this.AdminContext(), params.ServerId)
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.Data["wafIsOn"] = webConfig.FirewallRef != nil && webConfig.FirewallRef.IsOn
|
||||||
|
|
||||||
|
this.Show()
|
||||||
|
}
|
||||||
@@ -0,0 +1,121 @@
|
|||||||
|
package ipadmin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/oplogs"
|
||||||
|
"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"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type CountriesAction struct {
|
||||||
|
actionutils.ParentAction
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *CountriesAction) Init() {
|
||||||
|
this.Nav("", "setting", "country")
|
||||||
|
this.SecondMenu("waf")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *CountriesAction) RunGet(params struct {
|
||||||
|
FirewallPolicyId int64
|
||||||
|
ServerId int64
|
||||||
|
}) {
|
||||||
|
this.Data["featureIsOn"] = true
|
||||||
|
this.Data["firewallPolicyId"] = params.FirewallPolicyId
|
||||||
|
|
||||||
|
this.Data["subMenuItem"] = "region"
|
||||||
|
|
||||||
|
// 当前选中的地区
|
||||||
|
policyConfig, err := dao.SharedHTTPFirewallPolicyDAO.FindEnabledHTTPFirewallPolicyConfig(this.AdminContext(), params.FirewallPolicyId)
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if policyConfig == nil {
|
||||||
|
this.NotFound("firewallPolicy", params.FirewallPolicyId)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
selectedCountryIds := []int64{}
|
||||||
|
if policyConfig.Inbound != nil && policyConfig.Inbound.Region != nil {
|
||||||
|
selectedCountryIds = policyConfig.Inbound.Region.DenyCountryIds
|
||||||
|
}
|
||||||
|
|
||||||
|
countriesResp, err := this.RPC().RegionCountryRPC().FindAllEnabledRegionCountries(this.AdminContext(), &pb.FindAllEnabledRegionCountriesRequest{})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
countryMaps := []maps.Map{}
|
||||||
|
for _, country := range countriesResp.Countries {
|
||||||
|
countryMaps = append(countryMaps, maps.Map{
|
||||||
|
"id": country.Id,
|
||||||
|
"name": country.Name,
|
||||||
|
"letter": strings.ToUpper(string(country.Pinyin[0][0])),
|
||||||
|
"isChecked": lists.ContainsInt64(selectedCountryIds, country.Id),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
this.Data["countries"] = countryMaps
|
||||||
|
|
||||||
|
// WAF是否启用
|
||||||
|
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithServerId(this.AdminContext(), params.ServerId)
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.Data["wafIsOn"] = webConfig.FirewallRef != nil && webConfig.FirewallRef.IsOn
|
||||||
|
|
||||||
|
this.Show()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *CountriesAction) RunPost(params struct {
|
||||||
|
FirewallPolicyId int64
|
||||||
|
CountryIds []int64
|
||||||
|
|
||||||
|
Must *actions.Must
|
||||||
|
}) {
|
||||||
|
// 日志
|
||||||
|
defer this.CreateLog(oplogs.LevelInfo, "WAF策略 %d 设置禁止访问的国家和地区", params.FirewallPolicyId)
|
||||||
|
|
||||||
|
policyConfig, err := dao.SharedHTTPFirewallPolicyDAO.FindEnabledHTTPFirewallPolicyConfig(this.AdminContext(), params.FirewallPolicyId)
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if policyConfig == nil {
|
||||||
|
this.NotFound("firewallPolicy", params.FirewallPolicyId)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if policyConfig.Inbound == nil {
|
||||||
|
policyConfig.Inbound = &firewallconfigs.HTTPFirewallInboundConfig{IsOn: true}
|
||||||
|
}
|
||||||
|
if policyConfig.Inbound.Region == nil {
|
||||||
|
policyConfig.Inbound.Region = &firewallconfigs.HTTPFirewallRegionConfig{
|
||||||
|
IsOn: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
policyConfig.Inbound.Region.DenyCountryIds = params.CountryIds
|
||||||
|
|
||||||
|
inboundJSON, err := json.Marshal(policyConfig.Inbound)
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = this.RPC().HTTPFirewallPolicyRPC().UpdateHTTPFirewallInboundConfig(this.AdminContext(), &pb.UpdateHTTPFirewallInboundConfigRequest{
|
||||||
|
HttpFirewallPolicyId: params.FirewallPolicyId,
|
||||||
|
InboundJSON: inboundJSON,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Success()
|
||||||
|
}
|
||||||
@@ -0,0 +1,95 @@
|
|||||||
|
package ipadmin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/oplogs"
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/utils"
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
|
"github.com/iwind/TeaGo/actions"
|
||||||
|
)
|
||||||
|
|
||||||
|
type CreateIPPopupAction struct {
|
||||||
|
actionutils.ParentAction
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *CreateIPPopupAction) Init() {
|
||||||
|
this.Nav("", "", "")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *CreateIPPopupAction) RunGet(params struct {
|
||||||
|
ListId int64
|
||||||
|
Type string
|
||||||
|
}) {
|
||||||
|
this.Data["listType"] = params.Type
|
||||||
|
this.Data["listId"] = params.ListId
|
||||||
|
|
||||||
|
this.Show()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *CreateIPPopupAction) RunPost(params struct {
|
||||||
|
ListId int64
|
||||||
|
IpFrom string
|
||||||
|
IpTo string
|
||||||
|
ExpiredAt int64
|
||||||
|
Reason string
|
||||||
|
Type string
|
||||||
|
EventLevel string
|
||||||
|
|
||||||
|
Must *actions.Must
|
||||||
|
CSRF *actionutils.CSRF
|
||||||
|
}) {
|
||||||
|
switch params.Type {
|
||||||
|
case "ipv4":
|
||||||
|
params.Must.
|
||||||
|
Field("ipFrom", params.IpFrom).
|
||||||
|
Require("请输入开始IP")
|
||||||
|
|
||||||
|
// 校验IP格式(ipFrom/ipTo)
|
||||||
|
var ipFromLong uint64
|
||||||
|
if !utils.IsIPv4(params.IpFrom) {
|
||||||
|
this.Fail("请输入正确的开始IP")
|
||||||
|
}
|
||||||
|
ipFromLong = utils.IP2Long(params.IpFrom)
|
||||||
|
|
||||||
|
var ipToLong uint64
|
||||||
|
if len(params.IpTo) > 0 && !utils.IsIPv4(params.IpTo) {
|
||||||
|
ipToLong = utils.IP2Long(params.IpTo)
|
||||||
|
this.Fail("请输入正确的结束IP")
|
||||||
|
}
|
||||||
|
|
||||||
|
if ipFromLong > 0 && ipToLong > 0 && ipFromLong > ipToLong {
|
||||||
|
params.IpTo, params.IpFrom = params.IpFrom, params.IpTo
|
||||||
|
}
|
||||||
|
case "ipv6":
|
||||||
|
params.Must.
|
||||||
|
Field("ipFrom", params.IpFrom).
|
||||||
|
Require("请输入IP")
|
||||||
|
|
||||||
|
// 校验IP格式(ipFrom)
|
||||||
|
if !utils.IsIPv6(params.IpFrom) {
|
||||||
|
this.Fail("请输入正确的IPv6地址")
|
||||||
|
}
|
||||||
|
case "all":
|
||||||
|
params.IpFrom = "0.0.0.0"
|
||||||
|
}
|
||||||
|
|
||||||
|
createResp, err := this.RPC().IPItemRPC().CreateIPItem(this.AdminContext(), &pb.CreateIPItemRequest{
|
||||||
|
IpListId: params.ListId,
|
||||||
|
IpFrom: params.IpFrom,
|
||||||
|
IpTo: params.IpTo,
|
||||||
|
ExpiredAt: params.ExpiredAt,
|
||||||
|
Reason: params.Reason,
|
||||||
|
Type: params.Type,
|
||||||
|
EventLevel: params.EventLevel,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
itemId := createResp.IpItemId
|
||||||
|
|
||||||
|
// 日志
|
||||||
|
defer this.CreateLog(oplogs.LevelInfo, "在WAF策略 %d 名单中添加IP %d", params.ListId, itemId)
|
||||||
|
|
||||||
|
this.Success()
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package ipadmin
|
||||||
|
|
||||||
|
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 {
|
||||||
|
FirewallPolicyId int64
|
||||||
|
ItemId int64
|
||||||
|
}) {
|
||||||
|
// 日志
|
||||||
|
defer this.CreateLog(oplogs.LevelInfo, "从WAF策略 %d 名单中删除IP %d", params.FirewallPolicyId, params.ItemId)
|
||||||
|
|
||||||
|
// TODO 判断权限
|
||||||
|
|
||||||
|
_, err := this.RPC().IPItemRPC().DeleteIPItem(this.AdminContext(), &pb.DeleteIPItemRequest{IpItemId: params.ItemId})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Success()
|
||||||
|
}
|
||||||
@@ -0,0 +1,95 @@
|
|||||||
|
package ipadmin
|
||||||
|
|
||||||
|
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/iwind/TeaGo/maps"
|
||||||
|
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type DenyListAction struct {
|
||||||
|
actionutils.ParentAction
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *DenyListAction) Init() {
|
||||||
|
this.Nav("", "setting", "denyList")
|
||||||
|
this.SecondMenu("waf")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *DenyListAction) RunGet(params struct {
|
||||||
|
FirewallPolicyId int64
|
||||||
|
ServerId int64
|
||||||
|
}) {
|
||||||
|
this.Data["featureIsOn"] = true
|
||||||
|
this.Data["firewallPolicyId"] = params.FirewallPolicyId
|
||||||
|
|
||||||
|
listId, err := dao.SharedIPListDAO.FindDenyIPListIdWithServerId(this.AdminContext(), params.ServerId)
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建
|
||||||
|
if listId == 0 {
|
||||||
|
listId, err = dao.SharedIPListDAO.CreateIPListForServerId(this.AdminContext(), params.ServerId, "black")
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Data["listId"] = 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,
|
||||||
|
"isExpired": item.ExpiredAt > 0 && item.ExpiredAt < time.Now().Unix(),
|
||||||
|
"eventLevelName": firewallconfigs.FindFirewallEventLevelName(item.EventLevel),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
this.Data["items"] = itemMaps
|
||||||
|
|
||||||
|
// WAF是否启用
|
||||||
|
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithServerId(this.AdminContext(), params.ServerId)
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.Data["wafIsOn"] = webConfig.FirewallRef != nil && webConfig.FirewallRef.IsOn
|
||||||
|
|
||||||
|
this.Show()
|
||||||
|
}
|
||||||
@@ -0,0 +1,122 @@
|
|||||||
|
package ipadmin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/oplogs"
|
||||||
|
"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"
|
||||||
|
)
|
||||||
|
|
||||||
|
const ChinaCountryId = 1
|
||||||
|
|
||||||
|
type ProvincesAction struct {
|
||||||
|
actionutils.ParentAction
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *ProvincesAction) Init() {
|
||||||
|
this.Nav("", "setting", "province")
|
||||||
|
this.SecondMenu("waf")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *ProvincesAction) RunGet(params struct {
|
||||||
|
FirewallPolicyId int64
|
||||||
|
ServerId int64
|
||||||
|
}) {
|
||||||
|
this.Data["featureIsOn"] = true
|
||||||
|
this.Data["firewallPolicyId"] = params.FirewallPolicyId
|
||||||
|
this.Data["subMenuItem"] = "province"
|
||||||
|
|
||||||
|
// 当前选中的省份
|
||||||
|
policyConfig, err := dao.SharedHTTPFirewallPolicyDAO.FindEnabledHTTPFirewallPolicyConfig(this.AdminContext(), params.FirewallPolicyId)
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if policyConfig == nil {
|
||||||
|
this.NotFound("firewallPolicy", params.FirewallPolicyId)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
selectedProvinceIds := []int64{}
|
||||||
|
if policyConfig.Inbound != nil && policyConfig.Inbound.Region != nil {
|
||||||
|
selectedProvinceIds = policyConfig.Inbound.Region.DenyProvinceIds
|
||||||
|
}
|
||||||
|
|
||||||
|
provincesResp, err := this.RPC().RegionProvinceRPC().FindAllEnabledRegionProvincesWithCountryId(this.AdminContext(), &pb.FindAllEnabledRegionProvincesWithCountryIdRequest{
|
||||||
|
CountryId: int64(ChinaCountryId),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
provinceMaps := []maps.Map{}
|
||||||
|
for _, province := range provincesResp.Provinces {
|
||||||
|
provinceMaps = append(provinceMaps, maps.Map{
|
||||||
|
"id": province.Id,
|
||||||
|
"name": province.Name,
|
||||||
|
"isChecked": lists.ContainsInt64(selectedProvinceIds, province.Id),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
this.Data["provinces"] = provinceMaps
|
||||||
|
|
||||||
|
// WAF是否启用
|
||||||
|
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithServerId(this.AdminContext(), params.ServerId)
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.Data["wafIsOn"] = webConfig.FirewallRef != nil && webConfig.FirewallRef.IsOn
|
||||||
|
|
||||||
|
this.Show()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *ProvincesAction) RunPost(params struct {
|
||||||
|
FirewallPolicyId int64
|
||||||
|
ProvinceIds []int64
|
||||||
|
|
||||||
|
Must *actions.Must
|
||||||
|
}) {
|
||||||
|
// 日志
|
||||||
|
defer this.CreateLog(oplogs.LevelInfo, "WAF策略 %d 设置禁止访问的省份", params.FirewallPolicyId)
|
||||||
|
|
||||||
|
policyConfig, err := dao.SharedHTTPFirewallPolicyDAO.FindEnabledHTTPFirewallPolicyConfig(this.AdminContext(), params.FirewallPolicyId)
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if policyConfig == nil {
|
||||||
|
this.NotFound("firewallPolicy", params.FirewallPolicyId)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if policyConfig.Inbound == nil {
|
||||||
|
policyConfig.Inbound = &firewallconfigs.HTTPFirewallInboundConfig{IsOn: true}
|
||||||
|
}
|
||||||
|
if policyConfig.Inbound.Region == nil {
|
||||||
|
policyConfig.Inbound.Region = &firewallconfigs.HTTPFirewallRegionConfig{
|
||||||
|
IsOn: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
policyConfig.Inbound.Region.DenyProvinceIds = params.ProvinceIds
|
||||||
|
|
||||||
|
inboundJSON, err := json.Marshal(policyConfig.Inbound)
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = this.RPC().HTTPFirewallPolicyRPC().UpdateHTTPFirewallInboundConfig(this.AdminContext(), &pb.UpdateHTTPFirewallInboundConfigRequest{
|
||||||
|
HttpFirewallPolicyId: params.FirewallPolicyId,
|
||||||
|
InboundJSON: inboundJSON,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Success()
|
||||||
|
}
|
||||||
@@ -0,0 +1,100 @@
|
|||||||
|
package ipadmin
|
||||||
|
|
||||||
|
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/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("", "setting", "test")
|
||||||
|
this.SecondMenu("waf")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *TestAction) RunGet(params struct {
|
||||||
|
ServerId int64
|
||||||
|
FirewallPolicyId int64
|
||||||
|
}) {
|
||||||
|
this.Data["featureIsOn"] = true
|
||||||
|
this.Data["firewallPolicyId"] = params.FirewallPolicyId
|
||||||
|
this.Data["subMenuItem"] = "province"
|
||||||
|
|
||||||
|
// WAF是否启用
|
||||||
|
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithServerId(this.AdminContext(), params.ServerId)
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.Data["wafIsOn"] = webConfig.FirewallRef != nil && webConfig.FirewallRef.IsOn
|
||||||
|
|
||||||
|
this.Show()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *TestAction) RunPost(params struct {
|
||||||
|
FirewallPolicyId int64
|
||||||
|
Ip string
|
||||||
|
|
||||||
|
Must *actions.Must
|
||||||
|
}) {
|
||||||
|
resp, err := this.RPC().HTTPFirewallPolicyRPC().CheckHTTPFirewallPolicyIPStatus(this.AdminContext(), &pb.CheckHTTPFirewallPolicyIPStatusRequest{
|
||||||
|
HttpFirewallPolicyId: params.FirewallPolicyId,
|
||||||
|
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.IpList != nil {
|
||||||
|
resultMap["list"] = maps.Map{
|
||||||
|
"id": resp.IpList.Id,
|
||||||
|
"name": resp.IpList.Name,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if resp.RegionCountry != nil {
|
||||||
|
resultMap["country"] = maps.Map{
|
||||||
|
"id": resp.RegionCountry.Id,
|
||||||
|
"name": resp.RegionCountry.Name,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if resp.RegionProvince != nil {
|
||||||
|
resultMap["province"] = maps.Map{
|
||||||
|
"id": resp.RegionProvince.Id,
|
||||||
|
"name": resp.RegionProvince.Name,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Data["result"] = resultMap
|
||||||
|
|
||||||
|
this.Success()
|
||||||
|
}
|
||||||
@@ -0,0 +1,117 @@
|
|||||||
|
package ipadmin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/oplogs"
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/utils"
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
|
"github.com/iwind/TeaGo/actions"
|
||||||
|
"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, "修改WAF策略名单中的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()
|
||||||
|
}
|
||||||
110
internal/web/actions/default/servers/server/stat/clients.go
Normal file
110
internal/web/actions/default/servers/server/stat/clients.go
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
package stat
|
||||||
|
|
||||||
|
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"
|
||||||
|
"github.com/iwind/TeaGo/maps"
|
||||||
|
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ClientsAction struct {
|
||||||
|
actionutils.ParentAction
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *ClientsAction) Init() {
|
||||||
|
this.Nav("", "stat", "")
|
||||||
|
this.SecondMenu("client")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *ClientsAction) RunGet(params struct {
|
||||||
|
ServerId int64
|
||||||
|
Month string
|
||||||
|
}) {
|
||||||
|
month := params.Month
|
||||||
|
if len(month) != 6 {
|
||||||
|
month = timeutil.Format("Ym")
|
||||||
|
}
|
||||||
|
this.Data["month"] = month
|
||||||
|
|
||||||
|
serverTypeResp, err := this.RPC().ServerRPC().FindEnabledServerType(this.AdminContext(), &pb.FindEnabledServerTypeRequest{ServerId: params.ServerId})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
serverType := serverTypeResp.Type
|
||||||
|
|
||||||
|
statIsOn := false
|
||||||
|
|
||||||
|
// 是否已开启
|
||||||
|
if serverconfigs.IsHTTPServerType(serverType) {
|
||||||
|
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithServerId(this.AdminContext(), params.ServerId)
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if webConfig != nil && webConfig.StatRef != nil {
|
||||||
|
statIsOn = webConfig.StatRef.IsOn
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.WriteString("此类型服务暂不支持统计")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Data["statIsOn"] = statIsOn
|
||||||
|
|
||||||
|
// 统计数据
|
||||||
|
systemMaps := []maps.Map{}
|
||||||
|
browserMaps := []maps.Map{}
|
||||||
|
|
||||||
|
if statIsOn {
|
||||||
|
{
|
||||||
|
resp, err := this.RPC().ServerClientSystemMonthlyStatRPC().FindTopServerClientSystemMonthlyStats(this.AdminContext(), &pb.FindTopServerClientSystemMonthlyStatsRequest{
|
||||||
|
ServerId: params.ServerId,
|
||||||
|
Month: month,
|
||||||
|
Offset: 0,
|
||||||
|
Size: 10,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for _, stat := range resp.Stats {
|
||||||
|
systemMaps = append(systemMaps, maps.Map{
|
||||||
|
"count": stat.Count,
|
||||||
|
"system": maps.Map{
|
||||||
|
"id": stat.ClientSystem.Id,
|
||||||
|
"name": stat.ClientSystem.Name + " " + stat.Version,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
resp, err := this.RPC().ServerClientBrowserMonthlyStatRPC().FindTopServerClientBrowserMonthlyStats(this.AdminContext(), &pb.FindTopServerClientBrowserMonthlyStatsRequest{
|
||||||
|
ServerId: params.ServerId,
|
||||||
|
Month: month,
|
||||||
|
Offset: 0,
|
||||||
|
Size: 10,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for _, stat := range resp.Stats {
|
||||||
|
browserMaps = append(browserMaps, maps.Map{
|
||||||
|
"count": stat.Count,
|
||||||
|
"browser": maps.Map{
|
||||||
|
"id": stat.ClientBrowser.Id,
|
||||||
|
"name": stat.ClientBrowser.Name + " " + stat.Version,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.Data["systemStats"] = systemMaps
|
||||||
|
this.Data["browserStats"] = browserMaps
|
||||||
|
|
||||||
|
this.Show()
|
||||||
|
}
|
||||||
@@ -1,6 +1,13 @@
|
|||||||
package stat
|
package stat
|
||||||
|
|
||||||
import "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
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"
|
||||||
|
"github.com/iwind/TeaGo/maps"
|
||||||
|
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||||
|
)
|
||||||
|
|
||||||
type IndexAction struct {
|
type IndexAction struct {
|
||||||
actionutils.ParentAction
|
actionutils.ParentAction
|
||||||
@@ -11,6 +18,133 @@ func (this *IndexAction) Init() {
|
|||||||
this.SecondMenu("index")
|
this.SecondMenu("index")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *IndexAction) RunGet(params struct{}) {
|
func (this *IndexAction) RunGet(params struct {
|
||||||
|
ServerId int64
|
||||||
|
Month string
|
||||||
|
}) {
|
||||||
|
month := params.Month
|
||||||
|
if len(month) != 6 {
|
||||||
|
month = timeutil.Format("Ym")
|
||||||
|
}
|
||||||
|
this.Data["month"] = month
|
||||||
|
|
||||||
|
serverTypeResp, err := this.RPC().ServerRPC().FindEnabledServerType(this.AdminContext(), &pb.FindEnabledServerTypeRequest{ServerId: params.ServerId})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
serverType := serverTypeResp.Type
|
||||||
|
|
||||||
|
statIsOn := false
|
||||||
|
|
||||||
|
// 是否已开启
|
||||||
|
if serverconfigs.IsHTTPServerType(serverType) {
|
||||||
|
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithServerId(this.AdminContext(), params.ServerId)
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if webConfig != nil && webConfig.StatRef != nil {
|
||||||
|
statIsOn = webConfig.StatRef.IsOn
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.WriteString("此类型服务暂不支持统计")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Data["statIsOn"] = statIsOn
|
||||||
|
|
||||||
|
// 统计数据
|
||||||
|
countryStatMaps := []maps.Map{}
|
||||||
|
provinceStatMaps := []maps.Map{}
|
||||||
|
cityStatMaps := []maps.Map{}
|
||||||
|
|
||||||
|
if statIsOn {
|
||||||
|
// 地区
|
||||||
|
{
|
||||||
|
resp, err := this.RPC().ServerRegionCountryMonthlyStatRPC().FindTopServerRegionCountryMonthlyStats(this.AdminContext(), &pb.FindTopServerRegionCountryMonthlyStatsRequest{
|
||||||
|
Month: month,
|
||||||
|
ServerId: params.ServerId,
|
||||||
|
Offset: 0,
|
||||||
|
Size: 10,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for _, stat := range resp.Stats {
|
||||||
|
countryStatMaps = append(countryStatMaps, maps.Map{
|
||||||
|
"count": stat.Count,
|
||||||
|
"country": maps.Map{
|
||||||
|
"id": stat.RegionCountry.Id,
|
||||||
|
"name": stat.RegionCountry.Name,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 省份
|
||||||
|
{
|
||||||
|
resp, err := this.RPC().ServerRegionProvinceMonthlyStatRPC().FindTopServerRegionProvinceMonthlyStats(this.AdminContext(), &pb.FindTopServerRegionProvinceMonthlyStatsRequest{
|
||||||
|
Month: month,
|
||||||
|
ServerId: params.ServerId,
|
||||||
|
Offset: 0,
|
||||||
|
Size: 10,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for _, stat := range resp.Stats {
|
||||||
|
provinceStatMaps = append(provinceStatMaps, maps.Map{
|
||||||
|
"count": stat.Count,
|
||||||
|
"country": maps.Map{
|
||||||
|
"id": stat.RegionCountry.Id,
|
||||||
|
"name": stat.RegionCountry.Name,
|
||||||
|
},
|
||||||
|
"province": maps.Map{
|
||||||
|
"id": stat.RegionProvince.Id,
|
||||||
|
"name": stat.RegionProvince.Name,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 城市
|
||||||
|
{
|
||||||
|
resp, err := this.RPC().ServerRegionCityMonthlyStatRPC().FindTopServerRegionCityMonthlyStats(this.AdminContext(), &pb.FindTopServerRegionCityMonthlyStatsRequest{
|
||||||
|
Month: month,
|
||||||
|
ServerId: params.ServerId,
|
||||||
|
Offset: 0,
|
||||||
|
Size: 10,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for _, stat := range resp.Stats {
|
||||||
|
cityStatMaps = append(cityStatMaps, maps.Map{
|
||||||
|
"count": stat.Count,
|
||||||
|
"country": maps.Map{
|
||||||
|
"id": stat.RegionCountry.Id,
|
||||||
|
"name": stat.RegionCountry.Name,
|
||||||
|
},
|
||||||
|
"province": maps.Map{
|
||||||
|
"id": stat.RegionProvince.Id,
|
||||||
|
"name": stat.RegionProvince.Name,
|
||||||
|
},
|
||||||
|
"city": maps.Map{
|
||||||
|
"id": stat.RegionCity.Id,
|
||||||
|
"name": stat.RegionCity.Name,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Data["countryStats"] = countryStatMaps
|
||||||
|
this.Data["provinceStats"] = provinceStatMaps
|
||||||
|
this.Data["cityStats"] = cityStatMaps
|
||||||
|
|
||||||
this.Show()
|
this.Show()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,9 @@ func init() {
|
|||||||
Helper(serverutils.NewServerHelper()).
|
Helper(serverutils.NewServerHelper()).
|
||||||
Prefix("/servers/server/stat").
|
Prefix("/servers/server/stat").
|
||||||
Get("", new(IndexAction)).
|
Get("", new(IndexAction)).
|
||||||
|
Get("/providers", new(ProvidersAction)).
|
||||||
|
Get("/clients", new(ClientsAction)).
|
||||||
|
Get("/waf", new(WafAction)).
|
||||||
EndAll()
|
EndAll()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,86 @@
|
|||||||
|
package stat
|
||||||
|
|
||||||
|
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"
|
||||||
|
"github.com/iwind/TeaGo/maps"
|
||||||
|
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ProvidersAction struct {
|
||||||
|
actionutils.ParentAction
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *ProvidersAction) Init() {
|
||||||
|
this.Nav("", "stat", "")
|
||||||
|
this.SecondMenu("provider")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *ProvidersAction) RunGet(params struct {
|
||||||
|
ServerId int64
|
||||||
|
Month string
|
||||||
|
}) {
|
||||||
|
month := params.Month
|
||||||
|
if len(month) != 6 {
|
||||||
|
month = timeutil.Format("Ym")
|
||||||
|
}
|
||||||
|
this.Data["month"] = month
|
||||||
|
|
||||||
|
serverTypeResp, err := this.RPC().ServerRPC().FindEnabledServerType(this.AdminContext(), &pb.FindEnabledServerTypeRequest{ServerId: params.ServerId})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
serverType := serverTypeResp.Type
|
||||||
|
|
||||||
|
statIsOn := false
|
||||||
|
|
||||||
|
// 是否已开启
|
||||||
|
if serverconfigs.IsHTTPServerType(serverType) {
|
||||||
|
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithServerId(this.AdminContext(), params.ServerId)
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if webConfig != nil && webConfig.StatRef != nil {
|
||||||
|
statIsOn = webConfig.StatRef.IsOn
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.WriteString("此类型服务暂不支持统计")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Data["statIsOn"] = statIsOn
|
||||||
|
|
||||||
|
// 统计数据
|
||||||
|
providerMaps := []maps.Map{}
|
||||||
|
|
||||||
|
if statIsOn {
|
||||||
|
{
|
||||||
|
resp, err := this.RPC().ServerRegionProviderMonthlyStatRPC().FindTopServerRegionProviderMonthlyStats(this.AdminContext(), &pb.FindTopServerRegionProviderMonthlyStatsRequest{
|
||||||
|
Month: month,
|
||||||
|
ServerId: params.ServerId,
|
||||||
|
Offset: 0,
|
||||||
|
Size: 10,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for _, stat := range resp.Stats {
|
||||||
|
providerMaps = append(providerMaps, maps.Map{
|
||||||
|
"count": stat.Count,
|
||||||
|
"provider": maps.Map{
|
||||||
|
"id": stat.RegionProvider.Id,
|
||||||
|
"name": stat.RegionProvider.Name,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.Data["providerStats"] = providerMaps
|
||||||
|
|
||||||
|
this.Show()
|
||||||
|
}
|
||||||
78
internal/web/actions/default/servers/server/stat/waf.go
Normal file
78
internal/web/actions/default/servers/server/stat/waf.go
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
package stat
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
|
"github.com/iwind/TeaGo/maps"
|
||||||
|
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type WafAction struct {
|
||||||
|
actionutils.ParentAction
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *WafAction) Init() {
|
||||||
|
this.Nav("", "stat", "")
|
||||||
|
this.SecondMenu("waf")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *WafAction) RunGet(params struct {
|
||||||
|
ServerId int64
|
||||||
|
}) {
|
||||||
|
// 统计数据
|
||||||
|
resp, err := this.RPC().ServerHTTPFirewallDailyStatRPC().ComposeServerHTTPFirewallDashboard(this.AdminContext(), &pb.ComposeServerHTTPFirewallDashboardRequest{
|
||||||
|
Day: timeutil.Format("Ymd"),
|
||||||
|
ServerId: params.ServerId,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Data["countDailyLog"] = resp.CountDailyLog
|
||||||
|
this.Data["countDailyBlock"] = resp.CountDailyBlock
|
||||||
|
this.Data["countDailyCaptcha"] = resp.CountDailyCaptcha
|
||||||
|
this.Data["countWeeklyBlock"] = resp.CountWeeklyBlock
|
||||||
|
this.Data["countMonthlyBlock"] = resp.CountMonthlyBlock
|
||||||
|
|
||||||
|
// 分组
|
||||||
|
groupStatMaps := []maps.Map{}
|
||||||
|
for _, group := range resp.HttpFirewallRuleGroups {
|
||||||
|
groupStatMaps = append(groupStatMaps, maps.Map{
|
||||||
|
"group": maps.Map{
|
||||||
|
"id": group.HttpFirewallRuleGroup.Id,
|
||||||
|
"name": group.HttpFirewallRuleGroup.Name,
|
||||||
|
},
|
||||||
|
"count": group.Count,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
this.Data["groupStats"] = groupStatMaps
|
||||||
|
|
||||||
|
// 每日趋势
|
||||||
|
logStatMaps := []maps.Map{}
|
||||||
|
blockStatMaps := []maps.Map{}
|
||||||
|
captchaStatMaps := []maps.Map{}
|
||||||
|
for _, stat := range resp.LogDailyStats {
|
||||||
|
logStatMaps = append(logStatMaps, maps.Map{
|
||||||
|
"day": stat.Day,
|
||||||
|
"count": stat.Count,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
for _, stat := range resp.BlockDailyStats {
|
||||||
|
blockStatMaps = append(blockStatMaps, maps.Map{
|
||||||
|
"day": stat.Day,
|
||||||
|
"count": stat.Count,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
for _, stat := range resp.CaptchaDailyStats {
|
||||||
|
captchaStatMaps = append(captchaStatMaps, maps.Map{
|
||||||
|
"day": stat.Day,
|
||||||
|
"count": stat.Count,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
this.Data["logDailyStats"] = logStatMaps
|
||||||
|
this.Data["blockDailyStats"] = blockStatMaps
|
||||||
|
this.Data["captchaDailyStats"] = captchaStatMaps
|
||||||
|
|
||||||
|
this.Show()
|
||||||
|
}
|
||||||
@@ -77,13 +77,13 @@ func (this *ServerHelper) createLeftMenu(action *actions.ActionObject) {
|
|||||||
|
|
||||||
// 协议簇
|
// 协议簇
|
||||||
family := ""
|
family := ""
|
||||||
if serverConfig.IsHTTP() {
|
if serverConfig.IsHTTPFamily() {
|
||||||
family = "http"
|
family = "http"
|
||||||
} else if serverConfig.IsTCP() {
|
} else if serverConfig.IsTCPFamily() {
|
||||||
family = "tcp"
|
family = "tcp"
|
||||||
} else if serverConfig.IsUnix() {
|
} else if serverConfig.IsUnixFamily() {
|
||||||
family = "unix"
|
family = "unix"
|
||||||
} else if serverConfig.IsUDP() {
|
} else if serverConfig.IsUDPFamily() {
|
||||||
family = "udp"
|
family = "udp"
|
||||||
}
|
}
|
||||||
action.Data["serverFamily"] = family
|
action.Data["serverFamily"] = family
|
||||||
@@ -94,7 +94,9 @@ func (this *ServerHelper) createLeftMenu(action *actions.ActionObject) {
|
|||||||
tabbar.Add("服务列表", "", "/servers", "", false)
|
tabbar.Add("服务列表", "", "/servers", "", false)
|
||||||
//tabbar.Add("看板", "", "/servers/server/board?serverId="+serverIdString, "dashboard", selectedTabbar == "board")
|
//tabbar.Add("看板", "", "/servers/server/board?serverId="+serverIdString, "dashboard", selectedTabbar == "board")
|
||||||
tabbar.Add("日志", "", "/servers/server/log?serverId="+serverIdString, "history", selectedTabbar == "log")
|
tabbar.Add("日志", "", "/servers/server/log?serverId="+serverIdString, "history", selectedTabbar == "log")
|
||||||
//tabbar.Add("统计", "", "/servers/server/stat?serverId="+serverIdString, "chart area", selectedTabbar == "stat")
|
if family == "http" {
|
||||||
|
tabbar.Add("统计", "", "/servers/server/stat?serverId="+serverIdString, "chart area", selectedTabbar == "stat")
|
||||||
|
}
|
||||||
tabbar.Add("设置", "", "/servers/server/settings?serverId="+serverIdString, "setting", selectedTabbar == "setting")
|
tabbar.Add("设置", "", "/servers/server/settings?serverId="+serverIdString, "setting", selectedTabbar == "setting")
|
||||||
tabbar.Add("删除", "", "/servers/server/delete?serverId="+serverIdString, "trash", selectedTabbar == "delete")
|
tabbar.Add("删除", "", "/servers/server/delete?serverId="+serverIdString, "trash", selectedTabbar == "delete")
|
||||||
{
|
{
|
||||||
@@ -155,10 +157,25 @@ func (this *ServerHelper) createLogMenu(secondMenuItem string, serverIdString st
|
|||||||
func (this *ServerHelper) createStatMenu(secondMenuItem string, serverIdString string, serverConfig *serverconfigs.ServerConfig) []maps.Map {
|
func (this *ServerHelper) createStatMenu(secondMenuItem string, serverIdString string, serverConfig *serverconfigs.ServerConfig) []maps.Map {
|
||||||
menuItems := []maps.Map{}
|
menuItems := []maps.Map{}
|
||||||
menuItems = append(menuItems, maps.Map{
|
menuItems = append(menuItems, maps.Map{
|
||||||
"name": "统计",
|
"name": "地域分布",
|
||||||
"url": "/servers/server/stat?serverId=" + serverIdString,
|
"url": "/servers/server/stat?serverId=" + serverIdString,
|
||||||
"isActive": secondMenuItem == "index",
|
"isActive": secondMenuItem == "index",
|
||||||
})
|
})
|
||||||
|
menuItems = append(menuItems, maps.Map{
|
||||||
|
"name": "运营商",
|
||||||
|
"url": "/servers/server/stat/providers?serverId=" + serverIdString,
|
||||||
|
"isActive": secondMenuItem == "provider",
|
||||||
|
})
|
||||||
|
menuItems = append(menuItems, maps.Map{
|
||||||
|
"name": "终端",
|
||||||
|
"url": "/servers/server/stat/clients?serverId=" + serverIdString,
|
||||||
|
"isActive": secondMenuItem == "client",
|
||||||
|
})
|
||||||
|
menuItems = append(menuItems, maps.Map{
|
||||||
|
"name": "WAF",
|
||||||
|
"url": "/servers/server/stat/waf?serverId=" + serverIdString,
|
||||||
|
"isActive": secondMenuItem == "waf",
|
||||||
|
})
|
||||||
return menuItems
|
return menuItems
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -179,7 +196,7 @@ func (this *ServerHelper) createSettingsMenu(secondMenuItem string, serverIdStri
|
|||||||
}
|
}
|
||||||
|
|
||||||
// HTTP
|
// HTTP
|
||||||
if serverConfig.IsHTTP() {
|
if serverConfig.IsHTTPFamily() {
|
||||||
menuItems = append(menuItems, maps.Map{
|
menuItems = append(menuItems, maps.Map{
|
||||||
"name": "域名",
|
"name": "域名",
|
||||||
"url": "/servers/server/settings/serverNames?serverId=" + serverIdString,
|
"url": "/servers/server/settings/serverNames?serverId=" + serverIdString,
|
||||||
@@ -294,7 +311,7 @@ func (this *ServerHelper) createSettingsMenu(secondMenuItem string, serverIdStri
|
|||||||
"isActive": secondMenuItem == "websocket",
|
"isActive": secondMenuItem == "websocket",
|
||||||
"isOn": serverConfig.Web != nil && serverConfig.Web.WebsocketRef != nil && serverConfig.Web.WebsocketRef.IsOn,
|
"isOn": serverConfig.Web != nil && serverConfig.Web.WebsocketRef != nil && serverConfig.Web.WebsocketRef.IsOn,
|
||||||
})
|
})
|
||||||
} else if serverConfig.IsTCP() {
|
} else if serverConfig.IsTCPFamily() {
|
||||||
menuItems = append(menuItems, maps.Map{
|
menuItems = append(menuItems, maps.Map{
|
||||||
"name": "TCP",
|
"name": "TCP",
|
||||||
"url": "/servers/server/settings/tcp?serverId=" + serverIdString,
|
"url": "/servers/server/settings/tcp?serverId=" + serverIdString,
|
||||||
@@ -313,14 +330,14 @@ func (this *ServerHelper) createSettingsMenu(secondMenuItem string, serverIdStri
|
|||||||
"isActive": secondMenuItem == "reverseProxy",
|
"isActive": secondMenuItem == "reverseProxy",
|
||||||
"isOn": serverConfig.ReverseProxyRef != nil && serverConfig.ReverseProxyRef.IsOn,
|
"isOn": serverConfig.ReverseProxyRef != nil && serverConfig.ReverseProxyRef.IsOn,
|
||||||
})
|
})
|
||||||
} else if serverConfig.IsUnix() {
|
} else if serverConfig.IsUnixFamily() {
|
||||||
menuItems = append(menuItems, maps.Map{
|
menuItems = append(menuItems, maps.Map{
|
||||||
"name": "Unix",
|
"name": "Unix",
|
||||||
"url": "/servers/server/settings/unix?serverId=" + serverIdString,
|
"url": "/servers/server/settings/unix?serverId=" + serverIdString,
|
||||||
"isActive": secondMenuItem == "unix",
|
"isActive": secondMenuItem == "unix",
|
||||||
"isOn": serverConfig.Unix != nil && serverConfig.Unix.IsOn && len(serverConfig.Unix.Listen) > 0,
|
"isOn": serverConfig.Unix != nil && serverConfig.Unix.IsOn && len(serverConfig.Unix.Listen) > 0,
|
||||||
})
|
})
|
||||||
} else if serverConfig.IsUDP() {
|
} else if serverConfig.IsUDPFamily() {
|
||||||
menuItems = append(menuItems, maps.Map{
|
menuItems = append(menuItems, maps.Map{
|
||||||
"name": "UDP",
|
"name": "UDP",
|
||||||
"url": "/servers/server/settings/udp?serverId=" + serverIdString,
|
"url": "/servers/server/settings/udp?serverId=" + serverIdString,
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ func init() {
|
|||||||
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
||||||
server.
|
server.
|
||||||
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeSetting)).
|
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeSetting)).
|
||||||
Helper(settingutils.NewHelper("backup")).
|
Helper(settingutils.NewAdvancedHelper("backup")).
|
||||||
Prefix("/settings/backup").
|
Prefix("/settings/backup").
|
||||||
Get("", new(IndexAction)).
|
Get("", new(IndexAction)).
|
||||||
EndAll()
|
EndAll()
|
||||||
|
|||||||
48
internal/web/actions/default/settings/database/clean.go
Normal file
48
internal/web/actions/default/settings/database/clean.go
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
package database
|
||||||
|
|
||||||
|
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/iwind/TeaGo/actions"
|
||||||
|
"github.com/iwind/TeaGo/maps"
|
||||||
|
)
|
||||||
|
|
||||||
|
type CleanAction struct {
|
||||||
|
actionutils.ParentAction
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *CleanAction) Init() {
|
||||||
|
this.Nav("", "", "clean")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *CleanAction) RunGet(params struct{}) {
|
||||||
|
this.Show()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *CleanAction) RunPost(params struct {
|
||||||
|
Must *actions.Must
|
||||||
|
}) {
|
||||||
|
tablesResp, err := this.RPC().DBRPC().FindAllDBTables(this.AdminContext(), &pb.FindAllDBTablesRequest{})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
tableMaps := []maps.Map{}
|
||||||
|
for _, table := range tablesResp.DbTables {
|
||||||
|
if !table.IsBaseTable || (!table.CanClean && !table.CanDelete) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
tableMaps = append(tableMaps, maps.Map{
|
||||||
|
"name": table.Name,
|
||||||
|
"rows": table.Rows,
|
||||||
|
"size": numberutils.FormatBytes(table.DataLength + table.IndexLength),
|
||||||
|
"canDelete": table.CanDelete,
|
||||||
|
"canClean": table.CanClean,
|
||||||
|
"comment": table.Comment,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
this.Data["tables"] = tableMaps
|
||||||
|
this.Success()
|
||||||
|
}
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
package database
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/systemconfigs"
|
||||||
|
"github.com/iwind/TeaGo/actions"
|
||||||
|
)
|
||||||
|
|
||||||
|
type CleanSettingAction struct {
|
||||||
|
actionutils.ParentAction
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *CleanSettingAction) Init() {
|
||||||
|
this.Nav("", "", "cleanSetting")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *CleanSettingAction) RunGet(params struct{}) {
|
||||||
|
// 读取设置
|
||||||
|
configResp, err := this.RPC().SysSettingRPC().ReadSysSetting(this.AdminContext(), &pb.ReadSysSettingRequest{Code: systemconfigs.SettingCodeDatabaseConfigSetting})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var config = &systemconfigs.DatabaseConfig{}
|
||||||
|
if len(configResp.ValueJSON) > 0 {
|
||||||
|
err = json.Unmarshal(configResp.ValueJSON, config)
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.Data["config"] = config.ServerAccessLog.Clean
|
||||||
|
|
||||||
|
this.Show()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *CleanSettingAction) RunPost(params struct {
|
||||||
|
Days int
|
||||||
|
|
||||||
|
Must *actions.Must
|
||||||
|
CSRF *actionutils.CSRF
|
||||||
|
}) {
|
||||||
|
defer this.CreateLogInfo("修改数据库自动清理设置")
|
||||||
|
|
||||||
|
days := params.Days
|
||||||
|
if days < 0 {
|
||||||
|
days = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// 读取设置
|
||||||
|
configResp, err := this.RPC().SysSettingRPC().ReadSysSetting(this.AdminContext(), &pb.ReadSysSettingRequest{Code: systemconfigs.SettingCodeDatabaseConfigSetting})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var config = &systemconfigs.DatabaseConfig{}
|
||||||
|
if len(configResp.ValueJSON) > 0 {
|
||||||
|
err = json.Unmarshal(configResp.ValueJSON, config)
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
config.ServerAccessLog.Clean.Days = days
|
||||||
|
configJSON, err := json.Marshal(config)
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
_, err = this.RPC().SysSettingRPC().UpdateSysSetting(this.AdminContext(), &pb.UpdateSysSettingRequest{
|
||||||
|
Code: systemconfigs.SettingCodeDatabaseConfigSetting,
|
||||||
|
ValueJSON: configJSON,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Success()
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
package database
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
|
)
|
||||||
|
|
||||||
|
type DeleteTableAction struct {
|
||||||
|
actionutils.ParentAction
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *DeleteTableAction) RunPost(params struct {
|
||||||
|
Table string
|
||||||
|
}) {
|
||||||
|
defer this.CreateLogInfo("删除数据表 %s", params.Table)
|
||||||
|
|
||||||
|
_, err := this.RPC().DBRPC().DeleteDBTable(this.AdminContext(), &pb.DeleteDBTableRequest{DbTable: params.Table})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.Success()
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package profile
|
package database
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
package profile
|
package database
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
|
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
|
||||||
@@ -15,6 +15,10 @@ func init() {
|
|||||||
Prefix("/settings/database").
|
Prefix("/settings/database").
|
||||||
Get("", new(IndexAction)).
|
Get("", new(IndexAction)).
|
||||||
GetPost("/update", new(UpdateAction)).
|
GetPost("/update", new(UpdateAction)).
|
||||||
|
GetPost("/clean", new(CleanAction)).
|
||||||
|
GetPost("/cleanSetting", new(CleanSettingAction)).
|
||||||
|
GetPost("/truncateTable", new(TruncateTableAction)).
|
||||||
|
GetPost("/deleteTable", new(DeleteTableAction)).
|
||||||
EndAll()
|
EndAll()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
package database
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
|
)
|
||||||
|
|
||||||
|
type TruncateTableAction struct {
|
||||||
|
actionutils.ParentAction
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *TruncateTableAction) RunPost(params struct {
|
||||||
|
Table string
|
||||||
|
}) {
|
||||||
|
defer this.CreateLogInfo("清空数据表 %s 数据", params.Table)
|
||||||
|
|
||||||
|
_, err := this.RPC().DBRPC().TruncateDBTable(this.AdminContext(), &pb.TruncateDBTableRequest{DbTable: params.Table})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.Success()
|
||||||
|
}
|
||||||
@@ -1,17 +1,15 @@
|
|||||||
package profile
|
package database
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
|
"github.com/go-sql-driver/mysql"
|
||||||
"github.com/iwind/TeaGo/Tea"
|
"github.com/iwind/TeaGo/Tea"
|
||||||
"github.com/iwind/TeaGo/actions"
|
"github.com/iwind/TeaGo/actions"
|
||||||
"github.com/iwind/TeaGo/dbs"
|
"github.com/iwind/TeaGo/dbs"
|
||||||
"github.com/iwind/TeaGo/maps"
|
"github.com/iwind/TeaGo/maps"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/url"
|
|
||||||
"path/filepath"
|
|
||||||
"regexp"
|
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -57,28 +55,33 @@ func (this *UpdateAction) RunGet(params struct{}) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dsn := dbConfig.Dsn
|
dsn := dbConfig.Dsn
|
||||||
dsn = regexp.MustCompile(`tcp\((.+)\)`).ReplaceAllString(dsn, "$1")
|
cfg, err := mysql.ParseDSN(dsn)
|
||||||
dsnURL, err := url.Parse("mysql://" + dsn)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
this.Data["dbConfig"] = maps.Map{
|
||||||
|
"host": "",
|
||||||
|
"port": "",
|
||||||
|
"username": "",
|
||||||
|
"password": "",
|
||||||
|
"database": "",
|
||||||
|
}
|
||||||
this.Show()
|
this.Show()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
host := dsnURL.Host
|
host := cfg.Addr
|
||||||
port := "3306"
|
port := "3306"
|
||||||
index := strings.LastIndex(dsnURL.Host, ":")
|
index := strings.LastIndex(cfg.Addr, ":")
|
||||||
if index > 0 {
|
if index > 0 {
|
||||||
host = dsnURL.Host[:index]
|
host = cfg.Addr[:index]
|
||||||
port = dsnURL.Host[index+1:]
|
port = cfg.Addr[index+1:]
|
||||||
}
|
}
|
||||||
|
|
||||||
password, _ := dsnURL.User.Password()
|
|
||||||
this.Data["dbConfig"] = maps.Map{
|
this.Data["dbConfig"] = maps.Map{
|
||||||
"host": host,
|
"host": host,
|
||||||
"port": port,
|
"port": port,
|
||||||
"username": dsnURL.User.Username(),
|
"username": cfg.User,
|
||||||
"password": password,
|
"password": cfg.Passwd,
|
||||||
"database": filepath.Base(dsnURL.Path),
|
"database": cfg.DBName,
|
||||||
}
|
}
|
||||||
|
|
||||||
this.Show()
|
this.Show()
|
||||||
|
|||||||
@@ -91,6 +91,7 @@ func (this *UploadPopupAction) RunPost(params struct {
|
|||||||
_, err = this.RPC().FileRPC().UpdateFileFinished(this.AdminContext(), &pb.UpdateFileFinishedRequest{FileId: fileId})
|
_, err = this.RPC().FileRPC().UpdateFileFinished(this.AdminContext(), &pb.UpdateFileFinishedRequest{FileId: fileId})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
this.ErrorPage(err)
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// 保存
|
// 保存
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
package profile
|
package database
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
|
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
package profile
|
package database
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
|
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ func (this *AdvancedHelper) BeforeAction(actionPtr actions.ActionWrapper) (goNex
|
|||||||
tabbar.Add("API节点", "", "/api", "", this.tab == "apiNodes")
|
tabbar.Add("API节点", "", "/api", "", this.tab == "apiNodes")
|
||||||
tabbar.Add("用户节点", "", "/settings/userNodes", "", this.tab == "userNodes")
|
tabbar.Add("用户节点", "", "/settings/userNodes", "", this.tab == "userNodes")
|
||||||
tabbar.Add("日志数据库", "", "/db", "", this.tab == "dbNodes")
|
tabbar.Add("日志数据库", "", "/db", "", this.tab == "dbNodes")
|
||||||
|
//tabbar.Add("备份", "", "/settings/backup", "", this.tab == "backup")
|
||||||
}
|
}
|
||||||
actionutils.SetTabbar(actionPtr, tabbar)
|
actionutils.SetTabbar(actionPtr, tabbar)
|
||||||
|
|
||||||
|
|||||||
@@ -34,7 +34,6 @@ func (this *Helper) BeforeAction(actionPtr actions.ActionWrapper) (goNext bool)
|
|||||||
tabbar.Add("用户界面设置", "", "/settings/user-ui", "", this.tab == "userUI")
|
tabbar.Add("用户界面设置", "", "/settings/user-ui", "", this.tab == "userUI")
|
||||||
tabbar.Add("安全设置", "", "/settings/security", "", this.tab == "security")
|
tabbar.Add("安全设置", "", "/settings/security", "", this.tab == "security")
|
||||||
tabbar.Add("IP库", "", "/settings/ip-library", "", this.tab == "ipLibrary")
|
tabbar.Add("IP库", "", "/settings/ip-library", "", this.tab == "ipLibrary")
|
||||||
tabbar.Add("备份", "", "/settings/backup", "", this.tab == "backup")
|
|
||||||
}
|
}
|
||||||
tabbar.Add("个人资料", "", "/settings/profile", "", this.tab == "profile")
|
tabbar.Add("个人资料", "", "/settings/profile", "", this.tab == "profile")
|
||||||
tabbar.Add("登录设置", "", "/settings/login", "", this.tab == "login")
|
tabbar.Add("登录设置", "", "/settings/login", "", this.tab == "login")
|
||||||
|
|||||||
@@ -3,7 +3,9 @@ package ui
|
|||||||
import (
|
import (
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
|
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
"github.com/iwind/TeaGo/actions"
|
"github.com/iwind/TeaGo/actions"
|
||||||
|
"io"
|
||||||
)
|
)
|
||||||
|
|
||||||
type IndexAction struct {
|
type IndexAction struct {
|
||||||
@@ -32,10 +34,14 @@ func (this *IndexAction) RunPost(params struct {
|
|||||||
ShowFinance bool
|
ShowFinance bool
|
||||||
ShowVersion bool
|
ShowVersion bool
|
||||||
Version string
|
Version string
|
||||||
|
FaviconFile *actions.File
|
||||||
|
LogoFile *actions.File
|
||||||
|
|
||||||
Must *actions.Must
|
Must *actions.Must
|
||||||
CSRF *actionutils.CSRF
|
CSRF *actionutils.CSRF
|
||||||
}) {
|
}) {
|
||||||
|
defer this.CreateLogInfo("修改管理界面设置")
|
||||||
|
|
||||||
params.Must.
|
params.Must.
|
||||||
Field("productName", params.ProductName).
|
Field("productName", params.ProductName).
|
||||||
Require("请输入产品名称").
|
Require("请输入产品名称").
|
||||||
@@ -53,6 +59,101 @@ func (this *IndexAction) RunPost(params struct {
|
|||||||
config.ShowFinance = params.ShowFinance
|
config.ShowFinance = params.ShowFinance
|
||||||
config.ShowVersion = params.ShowVersion
|
config.ShowVersion = params.ShowVersion
|
||||||
config.Version = params.Version
|
config.Version = params.Version
|
||||||
|
|
||||||
|
// 上传Favicon文件
|
||||||
|
if params.FaviconFile != nil {
|
||||||
|
createResp, err := this.RPC().FileRPC().CreateFile(this.AdminContext(), &pb.CreateFileRequest{
|
||||||
|
Filename: params.FaviconFile.Filename,
|
||||||
|
Size: params.FaviconFile.Size,
|
||||||
|
IsPublic: true,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fileId := createResp.FileId
|
||||||
|
|
||||||
|
// 上传内容
|
||||||
|
buf := make([]byte, 512*1024)
|
||||||
|
reader, err := params.FaviconFile.OriginFile.Open()
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for {
|
||||||
|
n, err := reader.Read(buf)
|
||||||
|
if n > 0 {
|
||||||
|
_, err = this.RPC().FileChunkRPC().CreateFileChunk(this.AdminContext(), &pb.CreateFileChunkRequest{
|
||||||
|
FileId: fileId,
|
||||||
|
Data: buf[:n],
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
this.Fail("上传失败:" + err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
if err == io.EOF {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
this.Fail("上传失败:" + err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 置为已完成
|
||||||
|
_, err = this.RPC().FileRPC().UpdateFileFinished(this.AdminContext(), &pb.UpdateFileFinishedRequest{FileId: fileId})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
}
|
||||||
|
config.FaviconFileId = fileId
|
||||||
|
}
|
||||||
|
|
||||||
|
// 上传Logo文件
|
||||||
|
if params.LogoFile != nil {
|
||||||
|
createResp, err := this.RPC().FileRPC().CreateFile(this.AdminContext(), &pb.CreateFileRequest{
|
||||||
|
Filename: params.LogoFile.Filename,
|
||||||
|
Size: params.LogoFile.Size,
|
||||||
|
IsPublic: true,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fileId := createResp.FileId
|
||||||
|
|
||||||
|
// 上传内容
|
||||||
|
buf := make([]byte, 512*1024)
|
||||||
|
reader, err := params.LogoFile.OriginFile.Open()
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for {
|
||||||
|
n, err := reader.Read(buf)
|
||||||
|
if n > 0 {
|
||||||
|
_, err = this.RPC().FileChunkRPC().CreateFileChunk(this.AdminContext(), &pb.CreateFileChunkRequest{
|
||||||
|
FileId: fileId,
|
||||||
|
Data: buf[:n],
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
this.Fail("上传失败:" + err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
if err == io.EOF {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
this.Fail("上传失败:" + err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 置为已完成
|
||||||
|
_, err = this.RPC().FileRPC().UpdateFileFinished(this.AdminContext(), &pb.UpdateFileFinishedRequest{FileId: fileId})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
}
|
||||||
|
config.LogoFileId = fileId
|
||||||
|
}
|
||||||
|
|
||||||
err = configloaders.UpdateAdminUIConfig(config)
|
err = configloaders.UpdateAdminUIConfig(config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
this.ErrorPage(err)
|
this.ErrorPage(err)
|
||||||
|
|||||||
@@ -1,9 +1,14 @@
|
|||||||
package usernodes
|
package usernodes
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
|
"github.com/iwind/TeaGo/logs"
|
||||||
"github.com/iwind/TeaGo/maps"
|
"github.com/iwind/TeaGo/maps"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
type IndexAction struct {
|
type IndexAction struct {
|
||||||
@@ -36,11 +41,32 @@ func (this *IndexAction) RunGet(params struct{}) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, node := range nodesResp.Nodes {
|
for _, node := range nodesResp.Nodes {
|
||||||
|
// 状态
|
||||||
|
status := &nodeconfigs.NodeStatus{}
|
||||||
|
if len(node.StatusJSON) > 0 {
|
||||||
|
err = json.Unmarshal(node.StatusJSON, &status)
|
||||||
|
if err != nil {
|
||||||
|
logs.Error(err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
status.IsActive = status.IsActive && time.Now().Unix()-status.UpdatedAt <= 60 // N秒之内认为活跃
|
||||||
|
}
|
||||||
|
|
||||||
nodeMaps = append(nodeMaps, maps.Map{
|
nodeMaps = append(nodeMaps, maps.Map{
|
||||||
"id": node.Id,
|
"id": node.Id,
|
||||||
"isOn": node.IsOn,
|
"isOn": node.IsOn,
|
||||||
"name": node.Name,
|
"name": node.Name,
|
||||||
"accessAddrs": node.AccessAddrs,
|
"accessAddrs": node.AccessAddrs,
|
||||||
|
"status": maps.Map{
|
||||||
|
"isActive": status.IsActive,
|
||||||
|
"updatedAt": status.UpdatedAt,
|
||||||
|
"hostname": status.Hostname,
|
||||||
|
"cpuUsage": status.CPUUsage,
|
||||||
|
"cpuUsageText": fmt.Sprintf("%.2f%%", status.CPUUsage*100),
|
||||||
|
"memUsage": status.MemoryUsage,
|
||||||
|
"memUsageText": fmt.Sprintf("%.2f%%", status.MemoryUsage*100),
|
||||||
|
"buildVersion": status.BuildVersion,
|
||||||
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,9 @@ package userui
|
|||||||
import (
|
import (
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
|
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
"github.com/iwind/TeaGo/actions"
|
"github.com/iwind/TeaGo/actions"
|
||||||
|
"io"
|
||||||
)
|
)
|
||||||
|
|
||||||
type IndexAction struct {
|
type IndexAction struct {
|
||||||
@@ -32,6 +34,8 @@ func (this *IndexAction) RunPost(params struct {
|
|||||||
ShowVersion bool
|
ShowVersion bool
|
||||||
Version string
|
Version string
|
||||||
ShowFinance bool
|
ShowFinance bool
|
||||||
|
FaviconFile *actions.File
|
||||||
|
LogoFile *actions.File
|
||||||
|
|
||||||
Must *actions.Must
|
Must *actions.Must
|
||||||
CSRF *actionutils.CSRF
|
CSRF *actionutils.CSRF
|
||||||
@@ -53,6 +57,101 @@ func (this *IndexAction) RunPost(params struct {
|
|||||||
config.ShowVersion = params.ShowVersion
|
config.ShowVersion = params.ShowVersion
|
||||||
config.Version = params.Version
|
config.Version = params.Version
|
||||||
config.ShowFinance = params.ShowFinance
|
config.ShowFinance = params.ShowFinance
|
||||||
|
|
||||||
|
// 上传Favicon文件
|
||||||
|
if params.FaviconFile != nil {
|
||||||
|
createResp, err := this.RPC().FileRPC().CreateFile(this.AdminContext(), &pb.CreateFileRequest{
|
||||||
|
Filename: params.FaviconFile.Filename,
|
||||||
|
Size: params.FaviconFile.Size,
|
||||||
|
IsPublic: true,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fileId := createResp.FileId
|
||||||
|
|
||||||
|
// 上传内容
|
||||||
|
buf := make([]byte, 512*1024)
|
||||||
|
reader, err := params.FaviconFile.OriginFile.Open()
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for {
|
||||||
|
n, err := reader.Read(buf)
|
||||||
|
if n > 0 {
|
||||||
|
_, err = this.RPC().FileChunkRPC().CreateFileChunk(this.AdminContext(), &pb.CreateFileChunkRequest{
|
||||||
|
FileId: fileId,
|
||||||
|
Data: buf[:n],
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
this.Fail("上传失败:" + err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
if err == io.EOF {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
this.Fail("上传失败:" + err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 置为已完成
|
||||||
|
_, err = this.RPC().FileRPC().UpdateFileFinished(this.AdminContext(), &pb.UpdateFileFinishedRequest{FileId: fileId})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
}
|
||||||
|
config.FaviconFileId = fileId
|
||||||
|
}
|
||||||
|
|
||||||
|
// 上传Logo文件
|
||||||
|
if params.LogoFile != nil {
|
||||||
|
createResp, err := this.RPC().FileRPC().CreateFile(this.AdminContext(), &pb.CreateFileRequest{
|
||||||
|
Filename: params.LogoFile.Filename,
|
||||||
|
Size: params.LogoFile.Size,
|
||||||
|
IsPublic: true,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fileId := createResp.FileId
|
||||||
|
|
||||||
|
// 上传内容
|
||||||
|
buf := make([]byte, 512*1024)
|
||||||
|
reader, err := params.LogoFile.OriginFile.Open()
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for {
|
||||||
|
n, err := reader.Read(buf)
|
||||||
|
if n > 0 {
|
||||||
|
_, err = this.RPC().FileChunkRPC().CreateFileChunk(this.AdminContext(), &pb.CreateFileChunkRequest{
|
||||||
|
FileId: fileId,
|
||||||
|
Data: buf[:n],
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
this.Fail("上传失败:" + err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
if err == io.EOF {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
this.Fail("上传失败:" + err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 置为已完成
|
||||||
|
_, err = this.RPC().FileRPC().UpdateFileFinished(this.AdminContext(), &pb.UpdateFileFinishedRequest{FileId: fileId})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
}
|
||||||
|
config.LogoFileId = fileId
|
||||||
|
}
|
||||||
|
|
||||||
err = configloaders.UpdateUserUIConfig(config)
|
err = configloaders.UpdateUserUIConfig(config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
this.ErrorPage(err)
|
this.ErrorPage(err)
|
||||||
|
|||||||
@@ -83,6 +83,7 @@ func (this *InstallAction) RunPost(params struct {
|
|||||||
Prefix: "edge",
|
Prefix: "edge",
|
||||||
}},
|
}},
|
||||||
}
|
}
|
||||||
|
dbConfig.Default.DB = "prod"
|
||||||
dbConfigData, err := yaml.Marshal(dbConfig)
|
dbConfigData, err := yaml.Marshal(dbConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
this.Fail("生成数据库配置失败:" + err.Error())
|
this.Fail("生成数据库配置失败:" + err.Error())
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package ui
|
package ui
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/server/settings/conds/condutils"
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/server/settings/conds/condutils"
|
||||||
"github.com/iwind/TeaGo/Tea"
|
"github.com/iwind/TeaGo/Tea"
|
||||||
@@ -11,9 +12,19 @@ import (
|
|||||||
|
|
||||||
type ComponentsAction actions.Action
|
type ComponentsAction actions.Action
|
||||||
|
|
||||||
|
var componentsData = []byte{}
|
||||||
|
|
||||||
func (this *ComponentsAction) RunGet(params struct{}) {
|
func (this *ComponentsAction) RunGet(params struct{}) {
|
||||||
this.AddHeader("Content-Type", "text/javascript; charset=utf-8")
|
this.AddHeader("Content-Type", "text/javascript; charset=utf-8")
|
||||||
|
|
||||||
|
if !Tea.IsTesting() && len(componentsData) > 0 {
|
||||||
|
this.AddHeader("Last-Modified", "Fri, 06 Sep 2019 08:29:50 GMT")
|
||||||
|
this.Write(componentsData)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var buffer = bytes.NewBuffer([]byte{})
|
||||||
|
|
||||||
var webRoot string
|
var webRoot string
|
||||||
if Tea.IsTesting() {
|
if Tea.IsTesting() {
|
||||||
webRoot = Tea.Root + "/../web/public/js/components/"
|
webRoot = Tea.Root + "/../web/public/js/components/"
|
||||||
@@ -34,8 +45,8 @@ func (this *ComponentsAction) RunGet(params struct{}) {
|
|||||||
logs.Error(err)
|
logs.Error(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
this.Write(data)
|
buffer.Write(data)
|
||||||
this.Write([]byte{'\n', '\n'})
|
buffer.Write([]byte{'\n', '\n'})
|
||||||
})
|
})
|
||||||
|
|
||||||
// 条件组件
|
// 条件组件
|
||||||
@@ -43,8 +54,11 @@ func (this *ComponentsAction) RunGet(params struct{}) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
logs.Println("ComponentsAction: " + err.Error())
|
logs.Println("ComponentsAction: " + err.Error())
|
||||||
} else {
|
} else {
|
||||||
this.WriteString("window.REQUEST_COND_COMPONENTS = ")
|
buffer.WriteString("window.REQUEST_COND_COMPONENTS = ")
|
||||||
this.Write(typesJSON)
|
buffer.Write(typesJSON)
|
||||||
this.Write([]byte{'\n', '\n'})
|
buffer.Write([]byte{'\n', '\n'})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
componentsData = buffer.Bytes()
|
||||||
|
this.Write(componentsData)
|
||||||
}
|
}
|
||||||
|
|||||||
16
internal/web/actions/default/ui/eventLevelOptions.go
Normal file
16
internal/web/actions/default/ui/eventLevelOptions.go
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
package ui
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
|
||||||
|
)
|
||||||
|
|
||||||
|
type EventLevelOptionsAction struct {
|
||||||
|
actionutils.ParentAction
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *EventLevelOptionsAction) RunPost(params struct{}) {
|
||||||
|
this.Data["eventLevels"] = firewallconfigs.FindAllFirewallEventLevels()
|
||||||
|
|
||||||
|
this.Success()
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user