Compare commits

..

60 Commits

Author SHA1 Message Date
刘祥超
9af2c4a18a 修改版本为v0.4.3 2022-02-21 18:32:03 +08:00
刘祥超
8f4c56b24a 更改版本为v0.4.2 2022-02-21 17:52:36 +08:00
刘祥超
5eb0f65934 更新截图 2022-02-21 11:53:51 +08:00
刘祥超
4ed4f165ac URL跳转可以设置是否保留参数 2022-02-20 09:17:30 +08:00
刘祥超
eb8419fda0 Update components.js 2022-02-17 17:24:23 +08:00
刘祥超
b4a7ee0e89 域名支持--(连续的连字符) 2022-02-17 17:24:14 +08:00
刘祥超
83ad1bc529 优化界面 2022-02-15 14:54:45 +08:00
刘祥超
56948d3035 优化菜单中badge显示 2022-02-14 08:58:31 +08:00
刘祥超
e71e5ad57e 支持默认价格设置 2022-01-23 20:16:02 +08:00
刘祥超
e06d1fa5b0 实现带宽计费套餐 2022-01-23 19:16:22 +08:00
刘祥超
460439f6bd 修复服务访问日志不能使用集群、节点筛选的Bug 2022-01-20 16:28:43 +08:00
刘祥超
4b4072a47e 优化界面 2022-01-20 15:53:46 +08:00
刘祥超
65d19d92e9 增加API方法调用耗时统计 2022-01-19 16:53:38 +08:00
刘祥超
79e52d1c6e 优化demo模式进入命令 2022-01-19 15:58:54 +08:00
刘祥超
59963ee7b9 修复检查更新配置不起作用的Bug 2022-01-18 19:29:42 +08:00
刘祥超
88273b1c9b 修改版本为v0.4.1 2022-01-17 10:53:28 +08:00
刘祥超
bc1eb994f9 Update components.js 2022-01-16 20:04:11 +08:00
刘祥超
136f0fd4bd 源站支持客户端证书 2022-01-16 19:51:26 +08:00
刘祥超
021dc13ce9 CAPTCHA增加多个选项 2022-01-16 16:54:20 +08:00
刘祥超
925b71489d Update components.js 2022-01-14 10:46:02 +08:00
刘祥超
580ce9f8f5 可以在IP名单、访问日志中跳到对应的WAF规则集 2022-01-14 10:45:58 +08:00
刘祥超
2b3d8c062d 优化界面 2022-01-13 15:05:57 +08:00
刘祥超
41858e091a Update components.js 2022-01-13 10:03:54 +08:00
刘祥超
5b7eaf08ae 实现open file cache 2022-01-12 21:09:11 +08:00
刘祥超
7362722adb 优化代码 2022-01-11 16:02:27 +08:00
刘祥超
8198ea8819 可以使用集群搜索WAF策略、缓存策略 2022-01-11 15:46:47 +08:00
刘祥超
cb615f4cbc Update components.js 2022-01-11 15:28:50 +08:00
刘祥超
6623fd8362 优化交互 2022-01-11 15:26:43 +08:00
刘祥超
7f8be85116 运行日志可以使用集群、节点筛选 2022-01-11 14:59:19 +08:00
刘祥超
c61381441c 访问日志可以使用集群和节点搜索 2022-01-11 12:04:03 +08:00
刘祥超
b3cecdfea2 实现自动SYN Flood防护 2022-01-10 19:54:29 +08:00
刘祥超
66f582df58 WAF规则增加备注信息/其他界面优化 2022-01-10 10:28:23 +08:00
刘祥超
7f6f7e11ce 生成components.js 2022-01-09 20:13:18 +08:00
刘祥超
0bdda313da WAF策略增加是否使用本地防火墙设置 2022-01-09 17:05:51 +08:00
刘祥超
d5e851cff7 优化界面 2022-01-09 10:47:03 +08:00
刘祥超
92f1ec13f9 优化界面 2022-01-09 10:43:37 +08:00
刘祥超
5376006754 优化文字提示 2022-01-08 16:49:46 +08:00
刘祥超
361979411e IP名单增加未读数、按未读筛选等操作 2022-01-08 16:48:45 +08:00
刘祥超
3981308083 优化代码 2022-01-06 11:13:36 +08:00
刘祥超
facd5e14cc 改进文字 2022-01-05 20:13:22 +08:00
刘祥超
ecce92c528 Update components.js 2022-01-05 15:54:22 +08:00
刘祥超
7696940989 用户列表可以使用待审核、关键词搜索 2022-01-05 11:12:28 +08:00
刘祥超
941ff46c2c 实现用户注册/审核功能 2022-01-05 10:45:28 +08:00
刘祥超
94036073de 优化请求脚本配置交互 2022-01-03 21:48:48 +08:00
刘祥超
13216f481c 尝试自动在firewalld中开放端口 2022-01-03 16:28:27 +08:00
刘祥超
eb35df8720 改进服务访问日志、设置页在手机下的显示 2022-01-03 14:50:11 +08:00
刘祥超
bf500fe1a4 增加格式化数字函数 2022-01-03 12:04:09 +08:00
刘祥超
c173e86e62 创建服务时默认选中统计 2022-01-03 11:27:01 +08:00
刘祥超
d4cb148272 WAF动作中各个超时/有效秒数最大值从10位改成9位 2022-01-03 11:17:33 +08:00
刘祥超
ffc3f8544e 节点运行日志增加标签筛选 2022-01-03 11:08:59 +08:00
刘祥超
b326bfe63a 优化文字 2021-12-31 19:45:14 +08:00
刘祥超
12f3f47ef9 实现初版边缘脚本 2021-12-31 15:20:59 +08:00
刘祥超
45734747c1 修改版本为0.4.0 2021-12-31 15:19:44 +08:00
刘祥超
37933d814c 修改版本号0.3.8 2021-12-31 11:38:55 +08:00
刘祥超
5b26287264 修复路由规则中不能设置响应Header的Bug 2021-12-28 20:12:29 +08:00
刘祥超
bac20b1d1f 自动检查更新被取消时,同时重置已发现的最新版本信息 2021-12-22 10:02:06 +08:00
刘祥超
904c641992 删除不必要的文件 2021-12-22 10:01:35 +08:00
刘祥超
36004bfd94 优化代码 2021-12-21 15:41:43 +08:00
刘祥超
0fcba7e90c 增加自动检查系统更新设置 2021-12-21 15:18:11 +08:00
刘祥超
2e9182933e 修改版本号为0.4.0 2021-12-20 20:01:55 +08:00
211 changed files with 3171 additions and 3097 deletions

View File

@@ -9,6 +9,7 @@ import (
"github.com/TeaOSLab/EdgeAdmin/internal/nodes"
_ "github.com/TeaOSLab/EdgeAdmin/internal/web"
_ "github.com/iwind/TeaGo/bootstrap"
"github.com/iwind/TeaGo/maps"
"github.com/iwind/gosock/pkg/gosock"
)
@@ -64,12 +65,17 @@ func main() {
fmt.Println("[ERROR]the service not started yet, you should start the service first")
return
}
_, err := sock.Send(&gosock.Command{Code: "demo"})
reply, err := sock.Send(&gosock.Command{Code: "demo"})
if err != nil {
fmt.Println("[ERROR]change demo mode failed: " + err.Error())
return
}
fmt.Println("change demo mode successfully")
var isDemo = maps.NewMap(reply.Params).GetBool("isDemo")
if isDemo {
fmt.Println("change demo mode to: on")
} else {
fmt.Println("change demo mode to: off")
}
})
app.On("generate", func() {
err := gen.Generate()

Binary file not shown.

Before

Width:  |  Height:  |  Size: 203 KiB

After

Width:  |  Height:  |  Size: 225 KiB

View File

@@ -11,10 +11,6 @@ import (
var sharedAdminUIConfig *systemconfigs.AdminUIConfig = nil
const (
AdminUISettingName = "adminUIConfig"
)
func LoadAdminUIConfig() (*systemconfigs.AdminUIConfig, error) {
locker.Lock()
defer locker.Unlock()
@@ -41,7 +37,7 @@ func UpdateAdminUIConfig(uiConfig *systemconfigs.AdminUIConfig) error {
return err
}
_, err = rpcClient.SysSettingRPC().UpdateSysSetting(rpcClient.Context(0), &pb.UpdateSysSettingRequest{
Code: AdminUISettingName,
Code: systemconfigs.SettingCodeAdminUIConfig,
ValueJSON: valueJSON,
})
if err != nil {
@@ -52,7 +48,7 @@ func UpdateAdminUIConfig(uiConfig *systemconfigs.AdminUIConfig) error {
return nil
}
// 是否显示财务信息
// ShowFinance 是否显示财务信息
func ShowFinance() bool {
config, _ := LoadAdminUIConfig()
if config != nil && !config.ShowFinance {
@@ -70,7 +66,7 @@ func loadAdminUIConfig() (*systemconfigs.AdminUIConfig, error) {
return nil, err
}
resp, err := rpcClient.SysSettingRPC().ReadSysSetting(rpcClient.Context(0), &pb.ReadSysSettingRequest{
Code: AdminUISettingName,
Code: systemconfigs.SettingCodeAdminUIConfig,
})
if err != nil {
return nil, err

View File

@@ -1,9 +1,9 @@
package teaconst
const (
Version = "0.3.7"
Version = "0.4.3"
APINodeVersion = "0.3.7"
APINodeVersion = "0.4.3"
ProductName = "Edge Admin"
ProcessName = "edge-admin"

View File

@@ -4,9 +4,10 @@ package teaconst
var (
IsRecoverMode = false
)
var (
IsDemoMode = false
ErrorDemoOperation = "DEMO模式下无法进行创建、修改、删除等操作"
NewVersionCode = "" // 有新的版本
NewVersionDownloadURL = "" // 新版本下载地址
)

View File

@@ -0,0 +1,12 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package goman
import "time"
type Instance struct {
Id uint64
CreatedTime time.Time
File string
Line int
}

81
internal/goman/lib.go Normal file
View File

@@ -0,0 +1,81 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package goman
import (
"runtime"
"sync"
"time"
)
var locker = &sync.Mutex{}
var instanceMap = map[uint64]*Instance{} // id => *Instance
var instanceId = uint64(0)
// New 新创建goroutine
func New(f func()) {
_, file, line, _ := runtime.Caller(1)
go func() {
locker.Lock()
instanceId++
var instance = &Instance{
Id: instanceId,
CreatedTime: time.Now(),
}
instance.File = file
instance.Line = line
instanceMap[instanceId] = instance
locker.Unlock()
// run function
f()
locker.Lock()
delete(instanceMap, instanceId)
locker.Unlock()
}()
}
// NewWithArgs 创建带有参数的goroutine
func NewWithArgs(f func(args ...interface{}), args ...interface{}) {
_, file, line, _ := runtime.Caller(1)
go func() {
locker.Lock()
instanceId++
var instance = &Instance{
Id: instanceId,
CreatedTime: time.Now(),
}
instance.File = file
instance.Line = line
instanceMap[instanceId] = instance
locker.Unlock()
// run function
f(args...)
locker.Lock()
delete(instanceMap, instanceId)
locker.Unlock()
}()
}
// List 列出所有正在运行goroutine
func List() []*Instance {
locker.Lock()
defer locker.Unlock()
var result = []*Instance{}
for _, instance := range instanceMap {
result = append(result, instance)
}
return result
}

View File

@@ -0,0 +1,28 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package goman
import (
"testing"
"time"
)
func TestNew(t *testing.T) {
New(func() {
t.Log("Hello")
t.Log(List())
})
time.Sleep(1 * time.Second)
t.Log(List())
time.Sleep(1 * time.Second)
}
func TestNewWithArgs(t *testing.T) {
NewWithArgs(func(args ...interface{}) {
t.Log(args[0], args[1])
}, 1, 2)
time.Sleep(1 * time.Second)
}

View File

@@ -325,7 +325,9 @@ func (this *AdminNode) listenSock() error {
_ = cmd.ReplyOk()
case "demo":
teaconst.IsDemoMode = !teaconst.IsDemoMode
_ = cmd.ReplyOk()
_ = cmd.Reply(&gosock.Command{
Params: map[string]interface{}{"isDemo": teaconst.IsDemoMode},
})
case "info":
exePath, _ := os.Executable()
_ = cmd.Reply(&gosock.Command{

View File

@@ -161,6 +161,10 @@ func (this *RPCClient) APINodeRPC() pb.APINodeServiceClient {
return pb.NewAPINodeServiceClient(this.pickConn())
}
func (this *RPCClient) APIMethodStatRPC() pb.APIMethodStatServiceClient {
return pb.NewAPIMethodStatServiceClient(this.pickConn())
}
func (this *RPCClient) UserNodeRPC() pb.UserNodeServiceClient {
return pb.NewUserNodeServiceClient(this.pickConn())
}
@@ -382,6 +386,10 @@ func (this *RPCClient) UserBillRPC() pb.UserBillServiceClient {
return pb.NewUserBillServiceClient(this.pickConn())
}
func (this *RPCClient) ServerBillRPC() pb.ServerBillServiceClient {
return pb.NewServerBillServiceClient(this.pickConn())
}
func (this *RPCClient) UserAccountRPC() pb.UserAccountServiceClient {
return pb.NewUserAccountServiceClient(this.pickConn())
}

View File

@@ -0,0 +1,131 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package tasks
import (
"encoding/json"
"errors"
teaconst "github.com/TeaOSLab/EdgeAdmin/internal/const"
"github.com/TeaOSLab/EdgeAdmin/internal/events"
"github.com/TeaOSLab/EdgeAdmin/internal/goman"
"github.com/TeaOSLab/EdgeAdmin/internal/rpc"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/TeaOSLab/EdgeCommon/pkg/systemconfigs"
"github.com/iwind/TeaGo/logs"
"github.com/iwind/TeaGo/maps"
stringutil "github.com/iwind/TeaGo/utils/string"
"io/ioutil"
"net/http"
"runtime"
"strings"
"time"
)
func init() {
events.On(events.EventStart, func() {
var task = NewCheckUpdatesTask()
goman.New(func() {
task.Start()
})
})
}
type CheckUpdatesTask struct {
ticker *time.Ticker
}
func NewCheckUpdatesTask() *CheckUpdatesTask {
return &CheckUpdatesTask{}
}
func (this *CheckUpdatesTask) Start() {
this.ticker = time.NewTicker(12 * time.Hour)
for range this.ticker.C {
err := this.Loop()
if err != nil {
logs.Println("[TASK][CHECK_UPDATES_TASK]" + err.Error())
}
}
}
func (this *CheckUpdatesTask) Loop() error {
// 检查是否开启
rpcClient, err := rpc.SharedRPC()
if err != nil {
return err
}
valueResp, err := rpcClient.SysSettingRPC().ReadSysSetting(rpcClient.Context(0), &pb.ReadSysSettingRequest{Code: systemconfigs.SettingCodeCheckUpdates})
if err != nil {
return err
}
var valueJSON = valueResp.ValueJSON
var config = &systemconfigs.CheckUpdatesConfig{AutoCheck: false}
if len(valueJSON) > 0 {
err = json.Unmarshal(valueJSON, config)
if err != nil {
return errors.New("decode config failed: " + err.Error())
}
if !config.AutoCheck {
return nil
}
} else {
return nil
}
// 开始检查
type Response struct {
Code int `json:"code"`
Message string `json:"message"`
Data interface{} `json:"data"`
}
// 目前支持Linux
if runtime.GOOS != "linux" {
return nil
}
var apiURL = teaconst.UpdatesURL
apiURL = strings.ReplaceAll(apiURL, "${os}", runtime.GOOS)
apiURL = strings.ReplaceAll(apiURL, "${arch}", runtime.GOARCH)
resp, err := http.Get(apiURL)
if err != nil {
return errors.New("read api failed: " + err.Error())
}
defer func() {
_ = resp.Body.Close()
}()
data, err := ioutil.ReadAll(resp.Body)
if err != nil {
return errors.New("read api failed: " + err.Error())
}
var apiResponse = &Response{}
err = json.Unmarshal(data, apiResponse)
if err != nil {
return errors.New("decode version data failed: " + err.Error())
}
if apiResponse.Code != 200 {
return errors.New("invalid response: " + apiResponse.Message)
}
var m = maps.NewMap(apiResponse.Data)
var dlHost = m.GetString("host")
var versions = m.GetSlice("versions")
if len(versions) > 0 {
for _, version := range versions {
var vMap = maps.NewMap(version)
if vMap.GetString("code") == "admin" {
var latestVersion = vMap.GetString("version")
if stringutil.VersionCompare(teaconst.Version, latestVersion) < 0 {
teaconst.NewVersionCode = latestVersion
teaconst.NewVersionDownloadURL = dlHost + vMap.GetString("url")
return nil
}
}
}
}
return nil
}

View File

@@ -6,6 +6,7 @@ import (
"github.com/TeaOSLab/EdgeAdmin/internal/configs"
teaconst "github.com/TeaOSLab/EdgeAdmin/internal/const"
"github.com/TeaOSLab/EdgeAdmin/internal/events"
"github.com/TeaOSLab/EdgeAdmin/internal/goman"
"github.com/TeaOSLab/EdgeAdmin/internal/rpc"
"github.com/TeaOSLab/EdgeAdmin/internal/setup"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
@@ -23,7 +24,9 @@ import (
func init() {
events.On(events.EventStart, func() {
task := NewSyncAPINodesTask()
go task.Start()
goman.New(func() {
task.Start()
})
})
}

View File

@@ -3,6 +3,7 @@ package tasks
import (
teaconst "github.com/TeaOSLab/EdgeAdmin/internal/const"
"github.com/TeaOSLab/EdgeAdmin/internal/events"
"github.com/TeaOSLab/EdgeAdmin/internal/goman"
"github.com/TeaOSLab/EdgeAdmin/internal/rpc"
"github.com/TeaOSLab/EdgeAdmin/internal/setup"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/nodes/nodeutils"
@@ -17,7 +18,9 @@ import (
func init() {
events.On(events.EventStart, func() {
task := NewSyncClusterTask()
go task.Start()
goman.New(func() {
task.Start()
})
})
}

View File

@@ -0,0 +1,27 @@
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
//go:build community
// +build community
package nodelogutils
import (
"github.com/iwind/TeaGo/maps"
)
// FindCommonTags 查找常用的标签
func FindNodeCommonTags() []maps.Map {
return []maps.Map{
{
"name": "端口监听",
"code": "LISTENER",
},
{
"name": "WAF",
"code": "WAF",
},
{
"name": "访问日志",
"code": "ACCESS_LOG",
},
}
}

View File

@@ -2,6 +2,7 @@ package numberutils
import (
"fmt"
"github.com/iwind/TeaGo/types"
"strconv"
)
@@ -40,3 +41,16 @@ func FormatBytes(bytes int64) string {
return fmt.Sprintf("%.2fEB", float64(bytes)/float64(Pow1024(6)))
}
}
func FormatCount(count int64) string {
if count < 1000 {
return types.String(count)
}
if count < 1000 * 1000 {
return fmt.Sprintf("%.1fK", float32(count)/1000)
}
if count < 1000 * 1000 * 1000{
return fmt.Sprintf("%.1fM", float32(count)/1000/1000)
}
return fmt.Sprintf("%.1fB", float32(count)/1000/1000/1000)
}

View File

@@ -14,3 +14,13 @@ func TestFormatBytes(t *testing.T) {
t.Log(FormatBytes(1_000_000_000_000_000_000))
t.Log(FormatBytes(9_000_000_000_000_000_000))
}
func TestFormatCount(t *testing.T) {
t.Log(FormatCount(1))
t.Log(FormatCount(1000))
t.Log(FormatCount(1500))
t.Log(FormatCount(1_000_000))
t.Log(FormatCount(1_500_000))
t.Log(FormatCount(1_000_000_000))
t.Log(FormatCount(1_500_000_000))
}

View File

@@ -9,6 +9,7 @@ import (
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
"github.com/iwind/TeaGo/logs"
"github.com/iwind/TeaGo/maps"
timeutil "github.com/iwind/TeaGo/utils/time"
"time"
)
@@ -26,11 +27,11 @@ func (this *IndexAction) RunGet(params struct{}) {
this.ErrorPage(err)
return
}
count := countResp.Count
page := this.NewPage(count)
var count = countResp.Count
var page = this.NewPage(count)
this.Data["page"] = page.AsHTML()
nodeMaps := []maps.Map{}
var nodeMaps = []maps.Map{}
if count > 0 {
nodesResp, err := this.RPC().APINodeRPC().ListEnabledAPINodes(this.AdminContext(), &pb.ListEnabledAPINodesRequest{
Offset: page.Offset,
@@ -106,5 +107,13 @@ func (this *IndexAction) RunGet(params struct{}) {
}
this.Data["nodes"] = nodeMaps
// 检查是否有调试数据
countMethodStatsResp, err := this.RPC().APIMethodStatRPC().CountAPIMethodStatsWithDay(this.AdminContext(), &pb.CountAPIMethodStatsWithDayRequest{Day: timeutil.Format("Ymd")})
if err != nil {
this.ErrorPage(err)
return
}
this.Data["hasMethodStats"] = countMethodStatsResp.Count > 0
this.Show()
}

View File

@@ -16,6 +16,7 @@ func init() {
Helper(settingutils.NewAdvancedHelper("apiNodes")).
Prefix("/api").
Get("", new(IndexAction)).
Get("/methodStats", new(MethodStatsAction)).
GetPost("/node/createPopup", new(node.CreatePopupAction)).
Post("/delete", new(DeleteAction)).
EndAll()

View File

@@ -0,0 +1,78 @@
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package api
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"
"sort"
"strings"
)
type MethodStatsAction struct {
actionutils.ParentAction
}
func (this *MethodStatsAction) Init() {
this.Nav("", "", "")
}
func (this *MethodStatsAction) RunGet(params struct {
Order string
Method string
Tag string
}) {
this.Data["order"] = params.Order
this.Data["method"] = params.Method
this.Data["tag"] = params.Tag
statsResp, err := this.RPC().APIMethodStatRPC().FindAPIMethodStatsWithDay(this.AdminContext(), &pb.FindAPIMethodStatsWithDayRequest{Day: timeutil.Format("Ymd")})
if err != nil {
this.ErrorPage(err)
return
}
var pbStats = statsResp.ApiMethodStats
switch params.Order {
case "method":
sort.Slice(pbStats, func(i, j int) bool {
return pbStats[i].Method < pbStats[j].Method
})
case "costMs.desc":
sort.Slice(pbStats, func(i, j int) bool {
return pbStats[i].CostMs > pbStats[j].CostMs
})
case "peekMs.desc":
sort.Slice(pbStats, func(i, j int) bool {
return pbStats[i].PeekMs > pbStats[j].PeekMs
})
case "calls.desc":
sort.Slice(pbStats, func(i, j int) bool {
return pbStats[i].CountCalls > pbStats[j].CountCalls
})
}
var statMaps = []maps.Map{}
for _, stat := range pbStats {
if len(params.Method) > 0 && !strings.Contains(strings.ToLower(stat.Method), strings.ToLower(params.Method)) {
continue
}
if len(params.Tag) > 0 && !strings.Contains(strings.ToLower(stat.Tag), strings.ToLower(params.Tag)) {
continue
}
statMaps = append(statMaps, maps.Map{
"id": stat.Id,
"method": stat.Method,
"tag": stat.Tag,
"costMs": stat.CostMs,
"peekMs": stat.PeekMs,
"countCalls": stat.CountCalls,
})
}
this.Data["stats"] = statMaps
this.Show()
}

View File

@@ -1,6 +1,7 @@
package node
import (
"github.com/TeaOSLab/EdgeAdmin/internal/utils/nodelogutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/cluster/node/nodeutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
@@ -23,6 +24,7 @@ func (this *LogsAction) RunGet(params struct {
DayTo string
Keyword string
Level string
Tag string
}) {
// 初始化节点信息(用于菜单)
_, err := nodeutils.InitNodeInfo(this.Parent(), params.NodeId)
@@ -31,11 +33,14 @@ func (this *LogsAction) RunGet(params struct {
return
}
this.Data["tags"] = nodelogutils.FindNodeCommonTags()
this.Data["nodeId"] = params.NodeId
this.Data["dayFrom"] = params.DayFrom
this.Data["dayTo"] = params.DayTo
this.Data["keyword"] = params.Keyword
this.Data["level"] = params.Level
this.Data["tag"] = params.Tag
countResp, err := this.RPC().NodeLogRPC().CountNodeLogs(this.AdminContext(), &pb.CountNodeLogsRequest{
Role: "node",
@@ -44,6 +49,7 @@ func (this *LogsAction) RunGet(params struct {
DayTo: params.DayTo,
Keyword: params.Keyword,
Level: params.Level,
Tag: params.Tag,
})
if err != nil {
this.ErrorPage(err)
@@ -59,6 +65,7 @@ func (this *LogsAction) RunGet(params struct {
DayTo: params.DayTo,
Keyword: params.Keyword,
Level: params.Level,
Tag: params.Tag,
Offset: page.Offset,
Size: page.Size,
})

View File

@@ -17,7 +17,7 @@ type IndexAction struct {
}
func (this *IndexAction) Init() {
this.Nav("", "", "update")
this.Nav("", "node", "update")
this.SecondMenu("cache")
}

View File

@@ -16,7 +16,7 @@ type IndexAction struct {
}
func (this *IndexAction) Init() {
this.Nav("", "", "update")
this.Nav("", "node", "update")
this.SecondMenu("dns")
}

View File

@@ -17,7 +17,7 @@ type IndexAction struct {
}
func (this *IndexAction) Init() {
this.Nav("", "", "update")
this.Nav("", "node", "update")
this.SecondMenu("ssh")
}

View File

@@ -15,7 +15,7 @@ type IndexAction struct {
}
func (this *IndexAction) Init() {
this.Nav("", "", "update")
this.Nav("", "node", "update")
this.SecondMenu("system")
}

View File

@@ -15,7 +15,7 @@ type IndexAction struct {
}
func (this *IndexAction) Init() {
this.Nav("", "", "update")
this.Nav("", "node", "update")
this.SecondMenu("threshold")
}

View File

@@ -72,6 +72,7 @@ func (this *IndexAction) RunGet(params struct {
"timeZone": cluster.TimeZone,
"nodeMaxThreads": cluster.NodeMaxThreads,
"nodeTCPMaxConnections": cluster.NodeTCPMaxConnections,
"autoOpenPorts": cluster.AutoOpenPorts,
}
// 默认值
@@ -92,6 +93,7 @@ func (this *IndexAction) RunPost(params struct {
TimeZone string
NodeMaxThreads int32
NodeTCPMaxConnections int32
AutoOpenPorts bool
Must *actions.Must
}) {
@@ -117,6 +119,7 @@ func (this *IndexAction) RunPost(params struct {
TimeZone: params.TimeZone,
NodeMaxThreads: params.NodeMaxThreads,
NodeTCPMaxConnections: params.NodeTCPMaxConnections,
AutoOpenPorts: params.AutoOpenPorts,
})
if err != nil {
this.ErrorPage(err)

View File

@@ -21,8 +21,8 @@ func init() {
EndHelpers().
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeCommon)).
Post("/options", new(OptionsAction)).
Post("/nodeOptions", new(NodeOptionsAction)).
GetPost("/selectPopup", new(SelectPopupAction)).
EndAll()
})
}

View File

@@ -1,6 +1,7 @@
package logs
import (
"github.com/TeaOSLab/EdgeAdmin/internal/utils/nodelogutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
@@ -21,17 +22,26 @@ func (this *IndexAction) Init() {
}
func (this *IndexAction) RunGet(params struct {
DayFrom string
DayTo string
Keyword string
Level string
Type string
DayFrom string
DayTo string
Keyword string
Level string
Type string
Tag string
ClusterId int64
NodeId int64
}) {
this.Data["dayFrom"] = params.DayFrom
this.Data["dayTo"] = params.DayTo
this.Data["keyword"] = params.Keyword
this.Data["level"] = params.Level
this.Data["type"] = params.Type
this.Data["tag"] = params.Tag
this.Data["clusterId"] = params.ClusterId
this.Data["nodeId"] = params.NodeId
// 常见标签
this.Data["tags"] = nodelogutils.FindNodeCommonTags()
// 未读数量
countUnreadResp, err := this.RPC().NodeLogRPC().CountNodeLogs(this.AdminContext(), &pb.CountNodeLogsRequest{
@@ -46,13 +56,15 @@ func (this *IndexAction) RunGet(params struct {
// 日志数量
countResp, err := this.RPC().NodeLogRPC().CountNodeLogs(this.AdminContext(), &pb.CountNodeLogsRequest{
NodeId: 0,
Role: nodeconfigs.NodeRoleNode,
DayFrom: params.DayFrom,
DayTo: params.DayTo,
Keyword: params.Keyword,
Level: params.Level,
IsUnread: params.Type == "unread",
NodeClusterId: params.ClusterId,
NodeId: params.NodeId,
Role: nodeconfigs.NodeRoleNode,
DayFrom: params.DayFrom,
DayTo: params.DayTo,
Keyword: params.Keyword,
Level: params.Level,
IsUnread: params.Type == "unread",
Tag: params.Tag,
})
if err != nil {
this.ErrorPage(err)
@@ -63,15 +75,17 @@ func (this *IndexAction) RunGet(params struct {
this.Data["page"] = page.AsHTML()
logsResp, err := this.RPC().NodeLogRPC().ListNodeLogs(this.AdminContext(), &pb.ListNodeLogsRequest{
NodeId: 0,
Role: nodeconfigs.NodeRoleNode,
DayFrom: params.DayFrom,
DayTo: params.DayTo,
Keyword: params.Keyword,
Level: params.Level,
IsUnread: params.Type == "unread",
Offset: page.Offset,
Size: page.Size,
NodeClusterId: params.ClusterId,
NodeId: params.NodeId,
Role: nodeconfigs.NodeRoleNode,
DayFrom: params.DayFrom,
DayTo: params.DayTo,
Keyword: params.Keyword,
Level: params.Level,
IsUnread: params.Type == "unread",
Tag: params.Tag,
Offset: page.Offset,
Size: page.Size,
})
if err != nil {
this.ErrorPage(err)

View File

@@ -0,0 +1,34 @@
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package clusters
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/maps"
)
type NodeOptionsAction struct {
actionutils.ParentAction
}
func (this *NodeOptionsAction) RunPost(params struct {
ClusterId int64
}) {
resp, err := this.RPC().NodeRPC().FindAllEnabledNodesWithNodeClusterId(this.AdminContext(), &pb.FindAllEnabledNodesWithNodeClusterIdRequest{NodeClusterId: params.ClusterId})
if err != nil {
this.ErrorPage(err)
return
}
var nodeMaps = []maps.Map{}
for _, node := range resp.Nodes {
nodeMaps = append(nodeMaps, maps.Map{
"id": node.Id,
"name": node.Name,
})
}
this.Data["nodes"] = nodeMaps
this.Success()
}

View File

@@ -40,6 +40,11 @@ func (this *IndexAction) RunGet(params struct{}) {
}
}
// 版本更新
this.Data["currentVersionCode"] = teaconst.Version
this.Data["newVersionCode"] = teaconst.NewVersionCode
this.Data["newVersionDownloadURL"] = teaconst.NewVersionDownloadURL
this.Show()
}

View File

@@ -17,7 +17,7 @@ func ValidateDomainFormat(domain string) bool {
if piece == "-" ||
strings.HasPrefix(piece, "-") ||
strings.HasSuffix(piece, "-") ||
strings.Contains(piece, "--") ||
//strings.Contains(piece, "--") ||
len(piece) > 63 ||
!regexp.MustCompile(`^[a-z0-9-]+$`).MatchString(piece) {
return false
@@ -75,7 +75,7 @@ func ValidateRecordName(name string) bool {
if piece == "-" ||
strings.HasPrefix(piece, "-") ||
strings.HasSuffix(piece, "-") ||
strings.Contains(piece, "--") ||
//strings.Contains(piece, "--") ||
len(piece) > 63 ||
!regexp.MustCompile(`^[_a-z0-9-]+$`).MatchString(piece) {
return false

View File

@@ -1,173 +0,0 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package logs
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/lists"
"github.com/iwind/TeaGo/maps"
timeutil "github.com/iwind/TeaGo/utils/time"
"net"
"regexp"
"strings"
)
type IndexAction struct {
actionutils.ParentAction
}
func (this *IndexAction) Init() {
this.Nav("", "", "")
}
func (this *IndexAction) RunGet(params struct {
RequestId string
Keyword string
Day string
}) {
day := strings.ReplaceAll(params.Day, "-", "")
if !regexp.MustCompile(`^\d{8}$`).MatchString(day) {
day = timeutil.Format("Ymd")
}
this.Data["keyword"] = params.Keyword
this.Data["day"] = day[:4] + "-" + day[4:6] + "-" + day[6:]
this.Data["path"] = this.Request.URL.Path
var size = int64(10)
resp, err := this.RPC().NSAccessLogRPC().ListNSAccessLogs(this.AdminContext(), &pb.ListNSAccessLogsRequest{
RequestId: params.RequestId,
NsNodeId: 0,
NsDomainId: 0,
NsRecordId: 0,
Size: size,
Day: day,
Keyword: params.Keyword,
Reverse: false,
})
if err != nil {
this.ErrorPage(err)
return
}
ipList := []string{}
nodeIds := []int64{}
domainIds := []int64{}
if len(resp.NsAccessLogs) == 0 {
this.Data["accessLogs"] = []interface{}{}
} else {
this.Data["accessLogs"] = resp.NsAccessLogs
for _, accessLog := range resp.NsAccessLogs {
// IP
if len(accessLog.RemoteAddr) > 0 {
// 去掉端口
ip, _, err := net.SplitHostPort(accessLog.RemoteAddr)
if err == nil {
accessLog.RemoteAddr = ip
if !lists.ContainsString(ipList, ip) {
ipList = append(ipList, ip)
}
}
}
// 节点
if !lists.ContainsInt64(nodeIds, accessLog.NsNodeId) {
nodeIds = append(nodeIds, accessLog.NsNodeId)
}
// 域名
if !lists.ContainsInt64(domainIds, accessLog.NsDomainId) {
domainIds = append(domainIds, accessLog.NsDomainId)
}
}
}
this.Data["hasMore"] = resp.HasMore
this.Data["nextRequestId"] = resp.RequestId
// 上一个requestId
this.Data["hasPrev"] = false
this.Data["lastRequestId"] = ""
if len(params.RequestId) > 0 {
this.Data["hasPrev"] = true
prevResp, err := this.RPC().NSAccessLogRPC().ListNSAccessLogs(this.AdminContext(), &pb.ListNSAccessLogsRequest{
RequestId: params.RequestId,
NsNodeId: 0,
NsDomainId: 0,
NsRecordId: 0,
Day: day,
Keyword: params.Keyword,
Size: size,
Reverse: true,
})
if err != nil {
this.ErrorPage(err)
return
}
if int64(len(prevResp.NsAccessLogs)) == size {
this.Data["lastRequestId"] = prevResp.RequestId
}
}
// 根据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 {
if len(region.Isp) > 0 {
region.Summary += " | " + region.Isp
}
regionMap[ip] = region.Summary
}
}
}
this.Data["regions"] = regionMap
// 节点信息
nodeMap := map[int64]interface{}{} // node id => { ... }
for _, nodeId := range nodeIds {
nodeResp, err := this.RPC().NSNodeRPC().FindEnabledNSNode(this.AdminContext(), &pb.FindEnabledNSNodeRequest{NsNodeId: nodeId})
if err != nil {
this.ErrorPage(err)
return
}
node := nodeResp.NsNode
if node != nil {
nodeMap[node.Id] = maps.Map{
"id": node.Id,
"name": node.Name,
"cluster": maps.Map{
"id": node.NsCluster.Id,
"name": node.NsCluster.Name,
},
}
}
}
this.Data["nodes"] = nodeMap
// 域名信息
domainMap := map[int64]interface{}{} // domain id => { ... }
for _, domainId := range domainIds {
domainResp, err := this.RPC().NSDomainRPC().FindEnabledNSDomain(this.AdminContext(), &pb.FindEnabledNSDomainRequest{NsDomainId: domainId})
if err != nil {
this.ErrorPage(err)
return
}
domain := domainResp.NsDomain
if domain != nil {
domainMap[domain.Id] = maps.Map{
"id": domain.Id,
"name": domain.Name,
}
}
}
this.Data["domains"] = domainMap
this.Show()
}

View File

@@ -1,127 +0,0 @@
package cluster
import (
"encoding/json"
"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/nodeconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/actions"
"github.com/iwind/TeaGo/maps"
)
// CreateNodeAction 创建节点
type CreateNodeAction struct {
actionutils.ParentAction
}
func (this *CreateNodeAction) Init() {
this.Nav("", "node", "create")
this.SecondMenu("nodes")
}
func (this *CreateNodeAction) RunGet(params struct {
ClusterId int64
}) {
this.Show()
}
func (this *CreateNodeAction) RunPost(params struct {
Name string
IpAddressesJSON []byte
ClusterId int64
Must *actions.Must
}) {
params.Must.
Field("name", params.Name).
Require("请输入节点名称")
if len(params.IpAddressesJSON) == 0 {
this.Fail("请至少添加一个IP地址")
}
// 检查cluster
if params.ClusterId <= 0 {
this.Fail("请选择所在集群")
}
clusterResp, err := this.RPC().NSClusterRPC().FindEnabledNSCluster(this.AdminContext(), &pb.FindEnabledNSClusterRequest{NsClusterId: params.ClusterId})
if err != nil {
this.ErrorPage(err)
return
}
if clusterResp.NsCluster == nil {
this.Fail("选择的集群不存在")
}
// IP地址
ipAddresses := []maps.Map{}
if len(params.IpAddressesJSON) > 0 {
err := json.Unmarshal(params.IpAddressesJSON, &ipAddresses)
if err != nil {
this.ErrorPage(err)
return
}
}
if len(ipAddresses) == 0 {
this.Fail("请至少输入一个IP地址")
}
// 保存
createResp, err := this.RPC().NSNodeRPC().CreateNSNode(this.AdminContext(), &pb.CreateNSNodeRequest{
Name: params.Name,
NodeClusterId: params.ClusterId,
})
if err != nil {
this.ErrorPage(err)
return
}
nodeId := createResp.NsNodeId
// IP地址
for _, addrMap := range ipAddresses {
addressId := addrMap.GetInt64("id")
if addressId > 0 {
_, err = this.RPC().NodeIPAddressRPC().UpdateNodeIPAddressNodeId(this.AdminContext(), &pb.UpdateNodeIPAddressNodeIdRequest{
NodeIPAddressId: addressId,
NodeId: nodeId,
})
} else {
var ipStrings = addrMap.GetString("ip")
result, _ := utils.ExtractIP(ipStrings)
if len(result) == 1 {
// 单个创建
_, err = this.RPC().NodeIPAddressRPC().CreateNodeIPAddress(this.AdminContext(), &pb.CreateNodeIPAddressRequest{
NodeId: nodeId,
Role: nodeconfigs.NodeRoleDNS,
Name: addrMap.GetString("name"),
Ip: result[0],
CanAccess: addrMap.GetBool("canAccess"),
IsUp: addrMap.GetBool("isUp"),
})
} else if len(result) > 1 {
// 批量创建
_, err = this.RPC().NodeIPAddressRPC().CreateNodeIPAddresses(this.AdminContext(), &pb.CreateNodeIPAddressesRequest{
NodeId: nodeId,
Role: nodeconfigs.NodeRoleDNS,
Name: addrMap.GetString("name"),
IpList: result,
CanAccess: addrMap.GetBool("canAccess"),
IsUp: addrMap.GetBool("isUp"),
GroupValue: ipStrings,
})
}
}
if err != nil {
this.ErrorPage(err)
return
}
}
// 创建日志
defer this.CreateLog(oplogs.LevelInfo, "创建域名服务节点 %d", nodeId)
this.Success()
}

View File

@@ -1,38 +0,0 @@
package cluster
import (
"github.com/TeaOSLab/EdgeAdmin/internal/oplogs"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
)
type DeleteAction struct {
actionutils.ParentAction
}
func (this *DeleteAction) Init() {
this.Nav("", "delete", "index")
this.SecondMenu("nodes")
}
func (this *DeleteAction) RunGet(params struct{}) {
this.Show()
}
func (this *DeleteAction) RunPost(params struct {
ClusterId int64
}) {
// 创建日志
defer this.CreateLog(oplogs.LevelInfo, "删除域名服务集群 %d", params.ClusterId)
// TODO 如果有用户在使用此集群,就不能删除
// 删除
_, err := this.RPC().NSClusterRPC().DeleteNSCluster(this.AdminContext(), &pb.DeleteNSCluster{NsClusterId: params.ClusterId})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -1,26 +0,0 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package cluster
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
)
type DeleteNodeAction struct {
actionutils.ParentAction
}
func (this *DeleteNodeAction) RunPost(params struct {
NodeId int64
}) {
defer this.CreateLogInfo("删除域名服务节点 %d", params.NodeId)
_, err := this.RPC().NSNodeRPC().DeleteNSNode(this.AdminContext(), &pb.DeleteNSNodeRequest{NsNodeId: params.NodeId})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -1,141 +0,0 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package cluster
import (
"encoding/json"
"fmt"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/logs"
"github.com/iwind/TeaGo/maps"
"github.com/iwind/TeaGo/types"
"time"
)
type IndexAction struct {
actionutils.ParentAction
}
func (this *IndexAction) Init() {
this.Nav("", "node", "index")
}
func (this *IndexAction) RunGet(params struct {
ClusterId int64
InstalledState int
ActiveState int
Keyword string
}) {
this.Data["installState"] = params.InstalledState
this.Data["activeState"] = params.ActiveState
this.Data["keyword"] = params.Keyword
countAllResp, err := this.RPC().NSNodeRPC().CountAllEnabledNSNodesMatch(this.AdminContext(), &pb.CountAllEnabledNSNodesMatchRequest{
NsClusterId: params.ClusterId,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Data["countAll"] = countAllResp.Count
countResp, err := this.RPC().NSNodeRPC().CountAllEnabledNSNodesMatch(this.AdminContext(), &pb.CountAllEnabledNSNodesMatchRequest{
NsClusterId: params.ClusterId,
InstallState: types.Int32(params.InstalledState),
ActiveState: types.Int32(params.ActiveState),
Keyword: params.Keyword,
})
if err != nil {
this.ErrorPage(err)
return
}
page := this.NewPage(countResp.Count)
this.Data["page"] = page.AsHTML()
nodesResp, err := this.RPC().NSNodeRPC().ListEnabledNSNodesMatch(this.AdminContext(), &pb.ListEnabledNSNodesMatchRequest{
Offset: page.Offset,
Size: page.Size,
NsClusterId: params.ClusterId,
InstallState: types.Int32(params.InstalledState),
ActiveState: types.Int32(params.ActiveState),
Keyword: params.Keyword,
})
if err != nil {
this.ErrorPage(err)
return
}
nodeMaps := []maps.Map{}
for _, node := range nodesResp.NsNodes {
// 状态
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秒之内认为活跃
}
// IP
ipAddressesResp, err := this.RPC().NodeIPAddressRPC().FindAllEnabledNodeIPAddressesWithNodeId(this.AdminContext(), &pb.FindAllEnabledNodeIPAddressesWithNodeIdRequest{
NodeId: node.Id,
Role: nodeconfigs.NodeRoleDNS,
})
if err != nil {
this.ErrorPage(err)
return
}
ipAddresses := []maps.Map{}
for _, addr := range ipAddressesResp.NodeIPAddresses {
ipAddresses = append(ipAddresses, maps.Map{
"id": addr.Id,
"name": addr.Name,
"ip": addr.Ip,
"canAccess": addr.CanAccess,
"isOn": addr.IsOn,
"isUp": addr.IsUp,
})
}
nodeMaps = append(nodeMaps, maps.Map{
"id": node.Id,
"name": node.Name,
"isInstalled": node.IsInstalled,
"isOn": node.IsOn,
"isUp": node.IsUp,
"installStatus": maps.Map{
"isRunning": node.InstallStatus.IsRunning,
"isFinished": node.InstallStatus.IsFinished,
"isOk": node.InstallStatus.IsOk,
"error": node.InstallStatus.Error,
},
"status": maps.Map{
"isActive": node.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),
},
"ipAddresses": ipAddresses,
})
}
this.Data["nodes"] = nodeMaps
// 记录最近访问
_, err = this.RPC().LatestItemRPC().IncreaseLatestItem(this.AdminContext(), &pb.IncreaseLatestItemRequest{
ItemType: "nsCluster",
ItemId: params.ClusterId,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Show()
}

View File

@@ -1,129 +0,0 @@
package cluster
import (
"encoding/json"
"github.com/TeaOSLab/EdgeAdmin/internal/oplogs"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/grants/grantutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/actions"
"github.com/iwind/TeaGo/maps"
)
type UpdateNodeSSHAction struct {
actionutils.ParentAction
}
func (this *UpdateNodeSSHAction) Init() {
this.Nav("", "", "")
}
func (this *UpdateNodeSSHAction) RunGet(params struct {
NodeId int64
}) {
nodeResp, err := this.RPC().NSNodeRPC().FindEnabledNSNode(this.AdminContext(), &pb.FindEnabledNSNodeRequest{NsNodeId: params.NodeId})
if err != nil {
this.ErrorPage(err)
return
}
if nodeResp.NsNode == nil {
this.NotFound("node", params.NodeId)
return
}
node := nodeResp.NsNode
this.Data["node"] = maps.Map{
"id": node.Id,
"name": node.Name,
}
if nodeResp.NsNode.NsCluster != nil {
this.Data["clusterId"] = nodeResp.NsNode.NsCluster.Id
} else {
this.Data["clusterId"] = 0
}
// SSH
loginParams := maps.Map{
"host": "",
"port": "",
"grantId": 0,
}
this.Data["loginId"] = 0
if node.NodeLogin != nil {
this.Data["loginId"] = node.NodeLogin.Id
if len(node.NodeLogin.Params) > 0 {
err = json.Unmarshal(node.NodeLogin.Params, &loginParams)
if err != nil {
this.ErrorPage(err)
return
}
}
}
this.Data["params"] = loginParams
// 认证信息
grantId := loginParams.GetInt64("grantId")
grantResp, err := this.RPC().NodeGrantRPC().FindEnabledNodeGrant(this.AdminContext(), &pb.FindEnabledNodeGrantRequest{NodeGrantId: grantId})
if err != nil {
this.ErrorPage(err)
}
var grantMap maps.Map = nil
if grantResp.NodeGrant != nil {
grantMap = maps.Map{
"id": grantResp.NodeGrant.Id,
"name": grantResp.NodeGrant.Name,
"method": grantResp.NodeGrant.Method,
"methodName": grantutils.FindGrantMethodName(grantResp.NodeGrant.Method),
}
}
this.Data["grant"] = grantMap
this.Show()
}
func (this *UpdateNodeSSHAction) RunPost(params struct {
NodeId int64
LoginId int64
SshHost string
SshPort int
GrantId int64
Must *actions.Must
}) {
params.Must.
Field("sshHost", params.SshHost).
Require("请输入SSH主机地址").
Field("sshPort", params.SshPort).
Gt(0, "SSH主机端口需要大于0").
Lt(65535, "SSH主机端口需要小于65535")
if params.GrantId <= 0 {
this.Fail("需要选择或填写至少一个认证信息")
}
login := &pb.NodeLogin{
Id: params.LoginId,
Name: "SSH",
Type: "ssh",
Params: maps.Map{
"grantId": params.GrantId,
"host": params.SshHost,
"port": params.SshPort,
}.AsJSON(),
}
_, err := this.RPC().NSNodeRPC().UpdateNSNodeLogin(this.AdminContext(), &pb.UpdateNSNodeLoginRequest{
NsNodeId: params.NodeId,
NodeLogin: login,
})
if err != nil {
this.ErrorPage(err)
return
}
// 创建日志
defer this.CreateLog(oplogs.LevelInfo, "修改节点 %d 配置", params.NodeId)
this.Success()
}

View File

@@ -1,17 +0,0 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package cluster
import "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
type UpgradeRemoteAction struct {
actionutils.ParentAction
}
func (this *UpgradeRemoteAction) Init() {
this.Nav("", "", "")
}
func (this *UpgradeRemoteAction) RunGet(params struct{}) {
this.Show()
}

View File

@@ -1,98 +0,0 @@
package clusterutils
import (
"github.com/TeaOSLab/EdgeAdmin/internal/rpc"
"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/logs"
"github.com/iwind/TeaGo/maps"
"net/http"
"strconv"
)
// ClusterHelper 单个集群的帮助
type ClusterHelper struct {
}
func NewClusterHelper() *ClusterHelper {
return &ClusterHelper{}
}
func (this *ClusterHelper) BeforeAction(actionPtr actions.ActionWrapper) (goNext bool) {
action := actionPtr.Object()
if action.Request.Method != http.MethodGet {
return true
}
action.Data["teaMenu"] = "ns"
selectedTabbar := action.Data.GetString("mainTab")
clusterId := action.ParamInt64("clusterId")
clusterIdString := strconv.FormatInt(clusterId, 10)
action.Data["clusterId"] = clusterId
if clusterId > 0 {
rpcClient, err := rpc.SharedRPC()
if err != nil {
logs.Error(err)
return
}
clusterResp, err := rpcClient.NSClusterRPC().FindEnabledNSCluster(actionPtr.(actionutils.ActionInterface).AdminContext(), &pb.FindEnabledNSClusterRequest{
NsClusterId: clusterId,
})
if err != nil {
logs.Error(err)
return
}
cluster := clusterResp.NsCluster
if cluster == nil {
action.WriteString("can not find ns cluster")
return
}
tabbar := actionutils.NewTabbar()
tabbar.Add("集群列表", "", "/ns/clusters", "", false)
tabbar.Add("集群节点", "", "/ns/clusters/cluster?clusterId="+clusterIdString, "server", selectedTabbar == "node")
tabbar.Add("集群设置", "", "/ns/clusters/cluster/settings?clusterId="+clusterIdString, "setting", selectedTabbar == "setting")
tabbar.Add("删除集群", "", "/ns/clusters/cluster/delete?clusterId="+clusterIdString, "trash", selectedTabbar == "delete")
{
m := tabbar.Add("当前集群:"+cluster.Name, "", "/ns/clusters/cluster?clusterId="+clusterIdString, "", false)
m["right"] = true
}
actionutils.SetTabbar(action, tabbar)
// 左侧菜单
secondMenuItem := action.Data.GetString("secondMenuItem")
switch selectedTabbar {
case "setting":
action.Data["leftMenuItems"] = this.createSettingMenu(cluster, secondMenuItem)
}
}
return true
}
// 设置菜单
func (this *ClusterHelper) createSettingMenu(cluster *pb.NSCluster, selectedItem string) (items []maps.Map) {
clusterId := numberutils.FormatInt64(cluster.Id)
return []maps.Map{
{
"name": "基础设置",
"url": "/ns/clusters/cluster/settings?clusterId=" + clusterId,
"isActive": selectedItem == "basic",
},
{
"name": "访问日志",
"url": "/ns/clusters/cluster/settings/accessLog?clusterId=" + clusterId,
"isActive": selectedItem == "accessLog",
},
{
"name": "递归DNS",
"url": "/ns/clusters/cluster/settings/recursion?clusterId=" + clusterId,
"isActive": selectedItem == "recursion",
},
}
}

View File

@@ -1,68 +0,0 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package clusters
import (
"encoding/json"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/actions"
)
type CreateAction struct {
actionutils.ParentAction
}
func (this *CreateAction) Init() {
this.Nav("", "", "create")
}
func (this *CreateAction) RunGet(params struct{}) {
// 默认的访问日志设置
this.Data["accessLogRef"] = &dnsconfigs.NSAccessLogRef{
IsOn: true,
}
this.Show()
}
func (this *CreateAction) RunPost(params struct {
Name string
AccessLogJSON []byte
Must *actions.Must
CSRF *actionutils.CSRF
}) {
var clusterId int64
defer func() {
this.CreateLogInfo("创建域名服务集群 %d", clusterId)
}()
params.Must.
Field("name", params.Name).
Require("请输入集群名称")
// 校验访问日志设置
ref := &dnsconfigs.NSAccessLogRef{}
err := json.Unmarshal(params.AccessLogJSON, ref)
if err != nil {
this.Fail("数据格式错误:" + err.Error())
}
err = ref.Init()
if err != nil {
this.Fail("数据格式错误:" + err.Error())
}
resp, err := this.RPC().NSClusterRPC().CreateNSCluster(this.AdminContext(), &pb.CreateNSClusterRequest{
Name: params.Name,
AccessLogJSON: params.AccessLogJSON,
})
if err != nil {
this.ErrorPage(err)
return
}
clusterId = resp.NsClusterId
this.Success()
}

View File

@@ -1,77 +0,0 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package clusters
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/configutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/maps"
"github.com/iwind/TeaGo/types"
)
type IndexAction struct {
actionutils.ParentAction
}
func (this *IndexAction) Init() {
this.Nav("", "", "index")
}
func (this *IndexAction) RunGet(params struct{}) {
countResp, err := this.RPC().NSClusterRPC().CountAllEnabledNSClusters(this.AdminContext(), &pb.CountAllEnabledNSClustersRequest{})
if err != nil {
this.ErrorPage(err)
return
}
count := countResp.Count
page := this.NewPage(count)
this.Data["page"] = page.AsHTML()
clustersResp, err := this.RPC().NSClusterRPC().ListEnabledNSClusters(this.AdminContext(), &pb.ListEnabledNSClustersRequest{
Offset: page.Offset,
Size: page.Size,
})
if err != nil {
this.ErrorPage(err)
return
}
clusterMaps := []maps.Map{}
for _, cluster := range clustersResp.NsClusters {
// 全部节点数量
countNodesResp, err := this.RPC().NSNodeRPC().CountAllEnabledNSNodesMatch(this.AdminContext(), &pb.CountAllEnabledNSNodesMatchRequest{NsClusterId: cluster.Id})
if err != nil {
this.ErrorPage(err)
return
}
// 在线节点
countActiveNodesResp, err := this.RPC().NSNodeRPC().CountAllEnabledNSNodesMatch(this.AdminContext(), &pb.CountAllEnabledNSNodesMatchRequest{
NsClusterId: cluster.Id,
ActiveState: types.Int32(configutils.BoolStateYes),
})
if err != nil {
this.ErrorPage(err)
return
}
// 需要升级的节点
countUpgradeNodesResp, err := this.RPC().NSNodeRPC().CountAllUpgradeNSNodesWithNSClusterId(this.AdminContext(), &pb.CountAllUpgradeNSNodesWithNSClusterIdRequest{NsClusterId: cluster.Id})
if err != nil {
this.ErrorPage(err)
return
}
clusterMaps = append(clusterMaps, maps.Map{
"id": cluster.Id,
"name": cluster.Name,
"isOn": cluster.IsOn,
"countAllNodes": countNodesResp.Count,
"countActiveNodes": countActiveNodesResp.Count,
"countUpgradeNodes": countUpgradeNodesResp.Count,
})
}
this.Data["clusters"] = clusterMaps
this.Show()
}

View File

@@ -1,88 +0,0 @@
package logs
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/maps"
timeutil "github.com/iwind/TeaGo/utils/time"
)
type IndexAction struct {
actionutils.ParentAction
}
func (this *IndexAction) Init() {
}
func (this *IndexAction) RunGet(params struct {
DayFrom string
DayTo string
Keyword string
Level string
}) {
this.Data["dayFrom"] = params.DayFrom
this.Data["dayTo"] = params.DayTo
this.Data["keyword"] = params.Keyword
this.Data["level"] = params.Level
countResp, err := this.RPC().NodeLogRPC().CountNodeLogs(this.AdminContext(), &pb.CountNodeLogsRequest{
NodeId: 0,
Role: nodeconfigs.NodeRoleDNS,
DayFrom: params.DayFrom,
DayTo: params.DayTo,
Keyword: params.Keyword,
Level: params.Level,
})
if err != nil {
this.ErrorPage(err)
return
}
count := countResp.Count
page := this.NewPage(count)
this.Data["page"] = page.AsHTML()
logsResp, err := this.RPC().NodeLogRPC().ListNodeLogs(this.AdminContext(), &pb.ListNodeLogsRequest{
NodeId: 0,
Role: nodeconfigs.NodeRoleDNS,
DayFrom: params.DayFrom,
DayTo: params.DayTo,
Keyword: params.Keyword,
Level: params.Level,
Offset: page.Offset,
Size: page.Size,
})
logs := []maps.Map{}
for _, log := range logsResp.NodeLogs {
// 节点信息
nodeResp, err := this.RPC().NSNodeRPC().FindEnabledNSNode(this.AdminContext(), &pb.FindEnabledNSNodeRequest{NsNodeId: log.NodeId})
if err != nil {
continue
}
node := nodeResp.NsNode
if node == nil || node.NsCluster == nil {
continue
}
logs = append(logs, maps.Map{
"tag": log.Tag,
"description": log.Description,
"createdTime": timeutil.FormatTime("Y-m-d H:i:s", log.CreatedAt),
"level": log.Level,
"isToday": timeutil.FormatTime("Y-m-d", log.CreatedAt) == timeutil.Format("Y-m-d"),
"count": log.Count,
"node": maps.Map{
"id": node.Id,
"cluster": maps.Map{
"id": node.NsCluster.Id,
"name": node.NsCluster.Name,
},
"name": node.Name,
},
})
}
this.Data["logs"] = logs
this.Show()
}

View File

@@ -1,30 +0,0 @@
package clusters
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/maps"
)
type OptionsAction struct {
actionutils.ParentAction
}
func (this *OptionsAction) RunPost(params struct{}) {
clustersResp, err := this.RPC().NSClusterRPC().FindAllEnabledNSClusters(this.AdminContext(), &pb.FindAllEnabledNSClustersRequest{})
if err != nil {
this.ErrorPage(err)
return
}
clusterMaps := []maps.Map{}
for _, cluster := range clustersResp.NsClusters {
clusterMaps = append(clusterMaps, maps.Map{
"id": cluster.Id,
"name": cluster.Name,
})
}
this.Data["clusters"] = clusterMaps
this.Success()
}

View File

@@ -1,156 +0,0 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package test
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/dns/domains/domainutils"
"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/actions"
"github.com/iwind/TeaGo/maps"
"github.com/iwind/TeaGo/types"
"github.com/miekg/dns"
"net"
"regexp"
)
type IndexAction struct {
actionutils.ParentAction
}
func (this *IndexAction) Init() {
this.Nav("", "", "")
}
func (this *IndexAction) RunGet(params struct{}) {
// 集群列表
clustersResp, err := this.RPC().NSClusterRPC().FindAllEnabledNSClusters(this.AdminContext(), &pb.FindAllEnabledNSClustersRequest{})
if err != nil {
this.ErrorPage(err)
return
}
var clusterMaps = []maps.Map{}
for _, cluster := range clustersResp.NsClusters {
if !cluster.IsOn {
continue
}
countNodesResp, err := this.RPC().NSNodeRPC().CountAllEnabledNSNodesMatch(this.AdminContext(), &pb.CountAllEnabledNSNodesMatchRequest{
NsClusterId: cluster.Id,
InstallState: 0,
ActiveState: 0,
Keyword: "",
})
if err != nil {
this.ErrorPage(err)
return
}
var countNodes = countNodesResp.Count
if countNodes <= 0 {
continue
}
clusterMaps = append(clusterMaps, maps.Map{
"id": cluster.Id,
"name": cluster.Name,
"countNodes": countNodes,
})
}
this.Data["clusters"] = clusterMaps
// 记录类型
this.Data["recordTypes"] = dnsconfigs.FindAllRecordTypeDefinitions()
this.Show()
}
func (this *IndexAction) RunPost(params struct {
NodeId int64
Domain string
Type string
Ip string
ClientIP string
Must *actions.Must
}) {
nodeResp, err := this.RPC().NSNodeRPC().FindEnabledNSNode(this.AdminContext(), &pb.FindEnabledNSNodeRequest{NsNodeId: params.NodeId})
if err != nil {
this.ErrorPage(err)
return
}
var node = nodeResp.NsNode
if node == nil {
this.Fail("找不到要测试的节点")
}
var isOk = false
var errMsg string
var isNetError = false
var result string
defer func() {
this.Data["isOk"] = isOk
this.Data["err"] = errMsg
this.Data["isNetErr"] = isNetError
this.Data["result"] = result
this.Success()
}()
if !domainutils.ValidateDomainFormat(params.Domain) {
errMsg = "域名格式错误"
return
}
recordType, ok := dns.StringToType[params.Type]
if !ok {
errMsg = "不支持此记录类型"
return
}
if len(params.ClientIP) > 0 && net.ParseIP(params.ClientIP) == nil {
errMsg = "客户端IP格式不正确"
return
}
var optionId int64
if len(params.ClientIP) > 0 {
optionResp, err := this.RPC().NSQuestionOptionRPC().CreateNSQuestionOption(this.AdminContext(), &pb.CreateNSQuestionOptionRequest{
Name: "setRemoteAddr",
ValuesJSON: maps.Map{"ip": params.ClientIP}.AsJSON(),
})
if err != nil {
this.ErrorPage(err)
return
}
optionId = optionResp.NsQuestionOptionId
defer func() {
_, err = this.RPC().NSQuestionOptionRPC().DeleteNSQuestionOption(this.AdminContext(), &pb.DeleteNSQuestionOptionRequest{NsQuestionOptionId: optionId})
if err != nil {
this.ErrorPage(err)
}
}()
}
c := new(dns.Client)
m := new(dns.Msg)
var domain = params.Domain + "."
if optionId > 0 {
domain = "$" + types.String(optionId) + "-" + domain
}
m.SetQuestion(domain, recordType)
r, _, err := c.Exchange(m, params.Ip+":53")
if err != nil {
errMsg = "解析过程中出错:" + err.Error()
// 是否为网络错误
if regexp.MustCompile(`timeout|connect`).MatchString(err.Error()) {
isNetError = true
}
return
}
result = r.String()
result = regexp.MustCompile(`\$\d+-`).ReplaceAllString(result, "")
isOk = true
}

View File

@@ -1,59 +0,0 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package test
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/maps"
)
type NodeOptionsAction struct {
actionutils.ParentAction
}
func (this *NodeOptionsAction) RunPost(params struct {
ClusterId int64
}) {
nodesResp, err := this.RPC().NSNodeRPC().FindAllEnabledNSNodesWithNSClusterId(this.AdminContext(), &pb.FindAllEnabledNSNodesWithNSClusterIdRequest{NsClusterId: params.ClusterId})
if err != nil {
this.ErrorPage(err)
return
}
var nodeMaps = []maps.Map{}
for _, node := range nodesResp.NsNodes {
if !node.IsOn {
continue
}
addressesResp, err := this.RPC().NodeIPAddressRPC().FindAllEnabledNodeIPAddressesWithNodeId(this.AdminContext(), &pb.FindAllEnabledNodeIPAddressesWithNodeIdRequest{
NodeId: node.Id,
Role: nodeconfigs.NodeRoleDNS,
})
if err != nil {
this.ErrorPage(err)
return
}
var addresses = addressesResp.NodeIPAddresses
if len(addresses) == 0 {
continue
}
var addrs = []string{}
for _, addr := range addresses {
if addr.CanAccess {
addrs = append(addrs, addr.Ip)
}
}
nodeMaps = append(nodeMaps, maps.Map{
"id": node.Id,
"name": node.Name,
"addrs": addrs,
})
}
this.Data["nodes"] = nodeMaps
this.Success()
}

View File

@@ -1,34 +0,0 @@
package users
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/maps"
)
type OptionsAction struct {
actionutils.ParentAction
}
func (this *OptionsAction) RunPost(params struct{}) {
usersResp, err := this.RPC().UserRPC().ListEnabledUsers(this.AdminContext(), &pb.ListEnabledUsersRequest{
Offset: 0,
Size: 10000, // TODO 改进 <ns-user-selector> 组件
})
if err != nil {
this.ErrorPage(err)
return
}
userMaps := []maps.Map{}
for _, user := range usersResp.Users {
userMaps = append(userMaps, maps.Map{
"id": user.Id,
"fullname": user.Fullname,
"username": user.Username,
})
}
this.Data["users"] = userMaps
this.Success()
}

View File

@@ -31,6 +31,7 @@ func (this *CreatePopupAction) RunPost(params struct {
// file
FileDir string
FileMemoryCapacityJSON []byte
FileOpenFileCacheMax int
CapacityJSON []byte
MaxSizeJSON []byte
@@ -62,15 +63,23 @@ func (this *CreatePopupAction) RunPost(params struct {
}
}
var openFileCacheConfig *serverconfigs.OpenFileCacheConfig
if params.FileOpenFileCacheMax > 0 {
openFileCacheConfig = &serverconfigs.OpenFileCacheConfig{
IsOn: true,
Max: params.FileOpenFileCacheMax,
}
}
options = &serverconfigs.HTTPFileCacheStorage{
Dir: params.FileDir,
MemoryPolicy: &serverconfigs.HTTPCachePolicy{
Capacity: memoryCapacity,
},
OpenFileCache: openFileCacheConfig,
}
case serverconfigs.CachePolicyStorageMemory:
options = &serverconfigs.HTTPMemoryCacheStorage{
}
options = &serverconfigs.HTTPMemoryCacheStorage{}
default:
this.Fail("请选择正确的缓存类型")
}

View File

@@ -17,12 +17,15 @@ func (this *IndexAction) Init() {
}
func (this *IndexAction) RunGet(params struct {
Keyword string
ClusterId int64
Keyword string
}) {
this.Data["keyword"] = params.Keyword
this.Data["clusterId"] = params.ClusterId
countResp, err := this.RPC().HTTPCachePolicyRPC().CountAllEnabledHTTPCachePolicies(this.AdminContext(), &pb.CountAllEnabledHTTPCachePoliciesRequest{
Keyword: params.Keyword,
NodeClusterId: params.ClusterId,
Keyword: params.Keyword,
})
if err != nil {
this.ErrorPage(err)
@@ -33,9 +36,10 @@ func (this *IndexAction) RunGet(params struct {
this.Data["page"] = page.AsHTML()
listResp, err := this.RPC().HTTPCachePolicyRPC().ListEnabledHTTPCachePolicies(this.AdminContext(), &pb.ListEnabledHTTPCachePoliciesRequest{
Keyword: params.Keyword,
Offset: page.Offset,
Size: page.Size,
Keyword: params.Keyword,
NodeClusterId: params.ClusterId,
Offset: page.Offset,
Size: page.Size,
})
if err != nil {
this.ErrorPage(err)

View File

@@ -55,6 +55,7 @@ func (this *UpdateAction) RunPost(params struct {
// file
FileDir string
FileMemoryCapacityJSON []byte
FileOpenFileCacheMax int
CapacityJSON []byte
MaxSizeJSON []byte
@@ -91,15 +92,23 @@ func (this *UpdateAction) RunPost(params struct {
}
}
var openFileCacheConfig *serverconfigs.OpenFileCacheConfig
if params.FileOpenFileCacheMax > 0 {
openFileCacheConfig = &serverconfigs.OpenFileCacheConfig{
IsOn: true,
Max: params.FileOpenFileCacheMax,
}
}
options = &serverconfigs.HTTPFileCacheStorage{
Dir: params.FileDir,
MemoryPolicy: &serverconfigs.HTTPCachePolicy{
Capacity: memoryCapacity,
},
OpenFileCache: openFileCacheConfig,
}
case serverconfigs.CachePolicyStorageMemory:
options = &serverconfigs.HTTPMemoryCacheStorage{
}
options = &serverconfigs.HTTPMemoryCacheStorage{}
default:
this.Fail("请选择正确的缓存类型")
}

View File

@@ -61,6 +61,7 @@ func (this *CreateRulePopupAction) RunPost(params struct {
OptionsJSON []byte
Value string
Case bool
Description string
Must *actions.Must
}) {
@@ -91,6 +92,7 @@ func (this *CreateRulePopupAction) RunPost(params struct {
rule.Operator = params.Operator
rule.Value = params.Value
rule.IsCaseInsensitive = params.Case
rule.Description = params.Description
if len(params.OptionsJSON) > 0 {
options := []maps.Map{}

View File

@@ -87,6 +87,7 @@ func (this *GroupAction) RunGet(params struct {
"operator": rule.Operator,
"value": rule.Value,
"isCaseInsensitive": rule.IsCaseInsensitive,
"description": rule.Description,
"isComposed": firewallconfigs.CheckCheckpointIsComposed(rule.Prefix()),
"checkpointOptions": rule.CheckpointOptions,
"err": errString,

View File

@@ -17,12 +17,15 @@ func (this *IndexAction) Init() {
}
func (this *IndexAction) RunGet(params struct {
Keyword string
Keyword string
ClusterId int64
}) {
this.Data["keyword"] = params.Keyword
this.Data["clusterId"] = params.ClusterId
countResp, err := this.RPC().HTTPFirewallPolicyRPC().CountAllEnabledHTTPFirewallPolicies(this.AdminContext(), &pb.CountAllEnabledHTTPFirewallPoliciesRequest{
Keyword: params.Keyword,
NodeClusterId: params.ClusterId,
Keyword: params.Keyword,
})
if err != nil {
this.ErrorPage(err)
@@ -32,9 +35,10 @@ func (this *IndexAction) RunGet(params struct {
page := this.NewPage(count)
listResp, err := this.RPC().HTTPFirewallPolicyRPC().ListEnabledHTTPFirewallPolicies(this.AdminContext(), &pb.ListEnabledHTTPFirewallPoliciesRequest{
Keyword: params.Keyword,
Offset: page.Offset,
Size: page.Size,
NodeClusterId: params.ClusterId,
Keyword: params.Keyword,
Offset: page.Offset,
Size: page.Size,
})
if err != nil {
this.ErrorPage(err)

View File

@@ -47,7 +47,7 @@ func (this *IndexAction) RunGet(params struct {
return
}
countryMaps := []maps.Map{}
for _, country := range countriesResp.Countries {
for _, country := range countriesResp.RegionCountries {
countryMaps = append(countryMaps, maps.Map{
"id": country.Id,
"name": country.Name,

View File

@@ -7,6 +7,7 @@ import (
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
"github.com/iwind/TeaGo/maps"
timeutil "github.com/iwind/TeaGo/utils/time"
"time"
)
type ListsAction struct {
@@ -109,6 +110,7 @@ func (this *ListsAction) RunGet(params struct {
"sourceGroup": sourceGroupMap,
"sourceSet": sourceSetMap,
"sourceServer": sourceServerMap,
"lifeSeconds": item.ExpiredAt - time.Now().Unix(),
})
}
this.Data["items"] = itemMaps

View File

@@ -43,14 +43,14 @@ func (this *ProvincesAction) RunGet(params struct {
}
provincesResp, err := this.RPC().RegionProvinceRPC().FindAllEnabledRegionProvincesWithCountryId(this.AdminContext(), &pb.FindAllEnabledRegionProvincesWithCountryIdRequest{
CountryId: int64(ChinaCountryId),
RegionCountryId: int64(ChinaCountryId),
})
if err != nil {
this.ErrorPage(err)
return
}
provinceMaps := []maps.Map{}
for _, province := range provincesResp.Provinces {
for _, province := range provincesResp.RegionProvinces {
provinceMaps = append(provinceMaps, maps.Map{
"id": province.Id,
"name": province.Name,

View File

@@ -49,7 +49,7 @@ func (this *PolicyAction) RunGet(params struct {
// 检查是否有升级
var templatePolicy = firewallconfigs.HTTPFirewallTemplate()
var upgradeItems = []string{}
var upgradeItems = []maps.Map{}
if templatePolicy.Inbound != nil {
for _, group := range templatePolicy.Inbound.Groups {
if len(group.Code) == 0 {
@@ -57,7 +57,10 @@ func (this *PolicyAction) RunGet(params struct {
}
var oldGroup = firewallPolicy.FindRuleGroupWithCode(group.Code)
if oldGroup == nil {
upgradeItems = append(upgradeItems, group.Name)
upgradeItems = append(upgradeItems, maps.Map{
"name": group.Name,
"isOn": group.IsOn,
})
continue
}
for _, set := range group.Sets {
@@ -66,7 +69,10 @@ func (this *PolicyAction) RunGet(params struct {
}
var oldSet = oldGroup.FindRuleSetWithCode(set.Code)
if oldSet == nil {
upgradeItems = append(upgradeItems, group.Name+" -- "+set.Name)
upgradeItems = append(upgradeItems, maps.Map{
"name": group.Name + " -- " + set.Name,
"isOn": set.IsOn,
})
continue
}
}
@@ -78,15 +84,18 @@ func (this *PolicyAction) RunGet(params struct {
if len(firewallPolicy.Mode) == 0 {
firewallPolicy.Mode = firewallconfigs.FirewallModeDefend
}
this.Data["firewallPolicy"] = maps.Map{
"id": firewallPolicy.Id,
"name": firewallPolicy.Name,
"isOn": firewallPolicy.IsOn,
"description": firewallPolicy.Description,
"mode": firewallPolicy.Mode,
"modeInfo": firewallconfigs.FindFirewallMode(firewallPolicy.Mode),
"groups": internalGroups,
"blockOptions": firewallPolicy.BlockOptions,
"id": firewallPolicy.Id,
"name": firewallPolicy.Name,
"isOn": firewallPolicy.IsOn,
"description": firewallPolicy.Description,
"mode": firewallPolicy.Mode,
"modeInfo": firewallconfigs.FindFirewallMode(firewallPolicy.Mode),
"groups": internalGroups,
"blockOptions": firewallPolicy.BlockOptions,
"useLocalFirewall": firewallPolicy.UseLocalFirewall,
"synFlood": firewallPolicy.SYNFlood,
}
// 正在使用此策略的集群

View File

@@ -48,13 +48,25 @@ func (this *UpdateAction) RunGet(params struct {
}
this.Data["modes"] = firewallconfigs.FindAllFirewallModes()
// syn flood
if firewallPolicy.SYNFlood == nil {
firewallPolicy.SYNFlood = &firewallconfigs.SYNFloodConfig{
IsOn: false,
MinAttempts: 10,
TimeoutSeconds: 600,
IgnoreLocal: true,
}
}
this.Data["firewallPolicy"] = maps.Map{
"id": firewallPolicy.Id,
"name": firewallPolicy.Name,
"description": firewallPolicy.Description,
"isOn": firewallPolicy.IsOn,
"mode": firewallPolicy.Mode,
"blockOptions": firewallPolicy.BlockOptions,
"id": firewallPolicy.Id,
"name": firewallPolicy.Name,
"description": firewallPolicy.Description,
"isOn": firewallPolicy.IsOn,
"mode": firewallPolicy.Mode,
"blockOptions": firewallPolicy.BlockOptions,
"useLocalFirewall": firewallPolicy.UseLocalFirewall,
"synFloodConfig": firewallPolicy.SYNFlood,
}
// 预置分组
@@ -87,6 +99,8 @@ func (this *UpdateAction) RunPost(params struct {
Description string
IsOn bool
Mode string
UseLocalFirewall bool
SynFloodJSON []byte
Must *actions.Must
}) {
@@ -112,6 +126,8 @@ func (this *UpdateAction) RunPost(params struct {
FirewallGroupCodes: params.GroupCodes,
BlockOptionsJSON: params.BlockOptionsJSON,
Mode: params.Mode,
UseLocalFirewall: params.UseLocalFirewall,
SynFloodJSON: params.SynFloodJSON,
})
if err != nil {
this.ErrorPage(err)

View File

@@ -42,7 +42,7 @@ func (this *CreatePopupAction) RunPost(params struct {
}
// 创建日志
defer this.CreateLog(oplogs.LevelInfo, "创建代理服务分组 %d", createResp.ServerGroupId)
defer this.CreateLog(oplogs.LevelInfo, "创建服务分组 %d", createResp.ServerGroupId)
this.Success()
}

View File

@@ -63,6 +63,7 @@ func (this *IndexAction) RunGet(params struct {
"name": originConfig.Name,
"isOn": originConfig.IsOn,
"domains": originConfig.Domains,
"hasCert": originConfig.Cert != nil,
}
primaryOriginMaps = append(primaryOriginMaps, m)
}
@@ -77,6 +78,7 @@ func (this *IndexAction) RunGet(params struct {
"name": originConfig.Name,
"isOn": originConfig.IsOn,
"domains": originConfig.Domains,
"hasCert": originConfig.Cert != nil,
}
backupOriginMaps = append(backupOriginMaps, m)
}

View File

@@ -63,6 +63,7 @@ func (this *IndexAction) RunGet(params struct {
"name": originConfig.Name,
"isOn": originConfig.IsOn,
"domains": originConfig.Domains,
"hasCert": originConfig.Cert != nil,
}
primaryOriginMaps = append(primaryOriginMaps, m)
}
@@ -77,6 +78,7 @@ func (this *IndexAction) RunGet(params struct {
"name": originConfig.Name,
"isOn": originConfig.IsOn,
"domains": originConfig.Domains,
"hasCert": originConfig.Cert != nil,
}
backupOriginMaps = append(backupOriginMaps, m)
}

View File

@@ -63,6 +63,7 @@ func (this *IndexAction) RunGet(params struct {
"name": originConfig.Name,
"isOn": originConfig.IsOn,
"domains": originConfig.Domains,
"hasCert": originConfig.Cert != nil,
}
primaryOriginMaps = append(primaryOriginMaps, m)
}
@@ -77,6 +78,7 @@ func (this *IndexAction) RunGet(params struct {
"name": originConfig.Name,
"isOn": originConfig.IsOn,
"domains": originConfig.Domains,
"hasCert": originConfig.Cert != nil,
}
backupOriginMaps = append(backupOriginMaps, m)
}

View File

@@ -85,6 +85,7 @@ func (this *GroupAction) RunGet(params struct {
"operator": rule.Operator,
"value": rule.Value,
"isCaseInsensitive": rule.IsCaseInsensitive,
"description": rule.Description,
"isComposed": firewallconfigs.CheckCheckpointIsComposed(rule.Prefix()),
"checkpointOptions": rule.CheckpointOptions,
"err": errString,

View File

@@ -113,6 +113,7 @@ func (this *AllowListAction) RunGet(params struct {
"ipTo": item.IpTo,
"createdTime": timeutil.FormatTime("Y-m-d", item.CreatedAt),
"expiredTime": expiredTime,
"lifeSeconds": item.ExpiredAt - time.Now().Unix(),
"reason": item.Reason,
"type": item.Type,
"isExpired": item.ExpiredAt > 0 && item.ExpiredAt < time.Now().Unix(),

View File

@@ -113,6 +113,7 @@ func (this *DenyListAction) RunGet(params struct {
"ipTo": item.IpTo,
"createdTime": timeutil.FormatTime("Y-m-d", item.CreatedAt),
"expiredTime": expiredTime,
"lifeSeconds": item.ExpiredAt - time.Now().Unix(),
"reason": item.Reason,
"type": item.Type,
"isExpired": item.ExpiredAt > 0 && item.ExpiredAt < time.Now().Unix(),

View File

@@ -14,7 +14,7 @@ func (this *SortAction) RunPost(params struct {
GroupIds []int64
}) {
// 创建日志
defer this.CreateLog(oplogs.LevelInfo, "修改代理分组排序")
defer this.CreateLog(oplogs.LevelInfo, "修改服务分组排序")
_, err := this.RPC().ServerGroupRPC().UpdateServerGroupOrders(this.AdminContext(), &pb.UpdateServerGroupOrdersRequest{ServerGroupIds: params.GroupIds})
if err != nil {

View File

@@ -266,7 +266,7 @@ func (this *IndexAction) RunGet(params struct {
Role: nodeconfigs.NodeRoleNode,
Offset: 0,
Size: 20,
Level: "",
Level: "error,success,warning",
FixedState: int32(configutils.BoolStateNo),
AllServers: true,
})

View File

@@ -10,6 +10,7 @@ import (
func init() {
TeaGo.BeforeStart(func(server *TeaGo.Server) {
server.
Data("teaMenu", "servers").
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeServer)).
Helper(NewHelper()).
Prefix("/servers").

View File

@@ -22,14 +22,28 @@ func (this *IndexAction) Init() {
func (this *IndexAction) RunGet(params struct {
Ip string
GlobalOnly bool
Unread bool
}) {
this.Data["type"] = ""
this.Data["ip"] = params.Ip
this.Data["globalOnly"] = params.GlobalOnly
this.Data["unread"] = params.Unread
countUnreadResp, err := this.RPC().IPItemRPC().CountAllEnabledIPItems(this.AdminContext(), &pb.CountAllEnabledIPItemsRequest{
Ip: params.Ip,
GlobalOnly: params.GlobalOnly,
Unread: true,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Data["countUnread"] = countUnreadResp.Count
countResp, err := this.RPC().IPItemRPC().CountAllEnabledIPItems(this.AdminContext(), &pb.CountAllEnabledIPItemsRequest{
Ip: params.Ip,
GlobalOnly: params.GlobalOnly,
Unread: params.Unread,
})
if err != nil {
this.ErrorPage(err)
@@ -42,6 +56,7 @@ func (this *IndexAction) RunGet(params struct {
itemsResp, err := this.RPC().IPItemRPC().ListAllEnabledIPItems(this.AdminContext(), &pb.ListAllEnabledIPItemsRequest{
Ip: params.Ip,
GlobalOnly: params.GlobalOnly,
Unread: params.Unread,
Offset: page.Offset,
Size: page.Size,
})
@@ -118,6 +133,16 @@ func (this *IndexAction) RunGet(params struct {
}
}
// node
var sourceNodeMap = maps.Map{"id": 0}
if item.SourceNode != nil && item.SourceNode.NodeCluster != nil {
sourceNodeMap = maps.Map{
"id": item.SourceNode.Id,
"name": item.SourceNode.Name,
"clusterId": item.SourceNode.NodeCluster.Id,
}
}
itemMaps = append(itemMaps, maps.Map{
"id": item.Id,
"ipFrom": item.IpFrom,
@@ -127,11 +152,14 @@ func (this *IndexAction) RunGet(params struct {
"expiredTime": expiredTime,
"reason": item.Reason,
"type": item.Type,
"isRead": item.IsRead,
"lifeSeconds": item.ExpiredAt - time.Now().Unix(),
"eventLevelName": firewallconfigs.FindFirewallEventLevelName(item.EventLevel),
"sourcePolicy": sourcePolicyMap,
"sourceGroup": sourceGroupMap,
"sourceSet": sourceSetMap,
"sourceServer": sourceServerMap,
"sourceNode": sourceNodeMap,
"list": listMap,
"policy": policyMap,
})

View File

@@ -32,6 +32,7 @@ func init() {
GetPost("/updateIPPopup", new(UpdateIPPopupAction)).
Post("/deleteIP", new(DeleteIPAction)).
Get("/accessLogsPopup", new(AccessLogsPopupAction)).
Post("/readAll", new(ReadAllAction)).
// 防火墙
GetPost("/bindHTTPFirewallPopup", new(BindHTTPFirewallPopupAction)).

View File

@@ -8,6 +8,7 @@ import (
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
"github.com/iwind/TeaGo/maps"
timeutil "github.com/iwind/TeaGo/utils/time"
"time"
)
type ItemsAction struct {
@@ -112,6 +113,7 @@ func (this *ItemsAction) RunGet(params struct {
"sourceGroup": sourceGroupMap,
"sourceSet": sourceSetMap,
"sourceServer": sourceServerMap,
"lifeSeconds": item.ExpiredAt - time.Now().Unix(),
})
}
this.Data["items"] = itemMaps

View File

@@ -0,0 +1,24 @@
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package iplists
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
)
type ReadAllAction struct {
actionutils.ParentAction
}
func (this *ReadAllAction) RunPost(params struct{}) {
defer this.CreateLogInfo("将IP名单置为已读")
_, err := this.RPC().IPItemRPC().UpdateIPItemsRead(this.AdminContext(), &pb.UpdateIPItemsReadRequest{})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -22,12 +22,14 @@ func (this *IndexAction) Init() {
}
func (this *IndexAction) RunGet(params struct {
Day string
Keyword string
Ip string
Domain string
HasError int
HasWAF int
ClusterId int64
NodeId int64
Day string
Keyword string
Ip string
Domain string
HasError int
HasWAF int
RequestId string
ServerId int64
@@ -38,6 +40,8 @@ func (this *IndexAction) RunGet(params struct {
params.Day = timeutil.Format("Y-m-d")
}
this.Data["clusterId"] = params.ClusterId
this.Data["nodeId"] = params.NodeId
this.Data["serverId"] = 0
this.Data["path"] = this.Request.URL.Path
this.Data["day"] = params.Day
@@ -66,6 +70,8 @@ func (this *IndexAction) RunGet(params struct {
var before = time.Now()
resp, err := this.RPC().HTTPAccessLogRPC().ListHTTPAccessLogs(this.AdminContext(), &pb.ListHTTPAccessLogsRequest{
RequestId: params.RequestId,
NodeClusterId: params.ClusterId,
NodeId: params.NodeId,
ServerId: params.ServerId,
HasError: params.HasError > 0,
HasFirewallPolicy: params.HasWAF > 0,
@@ -108,6 +114,8 @@ func (this *IndexAction) RunGet(params struct {
this.Data["hasPrev"] = true
prevResp, err := this.RPC().HTTPAccessLogRPC().ListHTTPAccessLogs(this.AdminContext(), &pb.ListHTTPAccessLogsRequest{
RequestId: params.RequestId,
NodeClusterId: params.ClusterId,
NodeId: params.NodeId,
ServerId: params.ServerId,
HasError: params.HasError > 0,
HasFirewallPolicy: params.HasWAF > 0,

View File

@@ -29,6 +29,9 @@ func (this *HistoryAction) RunGet(params struct {
RequestId string
HasError int
ClusterId int64
NodeId int64
PageSize int
}) {
if len(params.Day) == 0 {
@@ -44,6 +47,8 @@ func (this *HistoryAction) RunGet(params struct {
this.Data["hasError"] = params.HasError
this.Data["hasWAF"] = params.HasWAF
this.Data["pageSize"] = params.PageSize
this.Data["clusterId"] = params.ClusterId
this.Data["nodeId"] = params.NodeId
day := params.Day
ipList := []string{}
@@ -66,6 +71,8 @@ func (this *HistoryAction) RunGet(params struct {
Keyword: params.Keyword,
Ip: params.Ip,
Domain: params.Domain,
NodeId: params.NodeId,
NodeClusterId: params.ClusterId,
Size: size,
})
if err != nil {
@@ -102,6 +109,8 @@ func (this *HistoryAction) RunGet(params struct {
Keyword: params.Keyword,
Ip: params.Ip,
Domain: params.Domain,
NodeId: params.NodeId,
NodeClusterId: params.ClusterId,
Size: size,
Reverse: true,
})

View File

@@ -22,6 +22,8 @@ func (this *IndexAction) RunGet(params struct {
RequestId string
Ip string
Domain string
ClusterId int64
NodeId int64
Keyword string
}) {
this.Data["serverId"] = params.ServerId
@@ -30,6 +32,8 @@ func (this *IndexAction) RunGet(params struct {
this.Data["domain"] = params.Domain
this.Data["keyword"] = params.Keyword
this.Data["path"] = this.Request.URL.Path
this.Data["clusterId"] = params.ClusterId
this.Data["nodeId"] = params.NodeId
// 记录最近使用
_, err := this.RPC().LatestItemRPC().IncreaseLatestItem(this.AdminContext(), &pb.IncreaseLatestItemRequest{
@@ -50,19 +54,23 @@ func (this *IndexAction) RunPost(params struct {
Keyword string
Ip string
Domain string
ClusterId int64
NodeId int64
Must *actions.Must
}) {
isReverse := len(params.RequestId) > 0
accessLogsResp, err := this.RPC().HTTPAccessLogRPC().ListHTTPAccessLogs(this.AdminContext(), &pb.ListHTTPAccessLogsRequest{
ServerId: params.ServerId,
RequestId: params.RequestId,
Size: 20,
Day: timeutil.Format("Ymd"),
Keyword: params.Keyword,
Ip: params.Ip,
Domain: params.Domain,
Reverse: isReverse,
ServerId: params.ServerId,
RequestId: params.RequestId,
Size: 20,
Day: timeutil.Format("Ymd"),
Keyword: params.Keyword,
Ip: params.Ip,
Domain: params.Domain,
NodeId: params.NodeId,
NodeClusterId: params.ClusterId,
Reverse: isReverse,
})
if err != nil {
this.ErrorPage(err)

View File

@@ -24,6 +24,8 @@ func (this *TodayAction) RunGet(params struct {
Keyword string
Ip string
Domain string
ClusterId int64
NodeId int64
PageSize int
}) {
@@ -40,6 +42,8 @@ func (this *TodayAction) RunGet(params struct {
this.Data["ip"] = params.Ip
this.Data["domain"] = params.Domain
this.Data["hasWAF"] = params.HasWAF
this.Data["clusterId"] = params.ClusterId
this.Data["nodeId"] = params.NodeId
resp, err := this.RPC().HTTPAccessLogRPC().ListHTTPAccessLogs(this.AdminContext(), &pb.ListHTTPAccessLogsRequest{
RequestId: params.RequestId,
@@ -50,6 +54,8 @@ func (this *TodayAction) RunGet(params struct {
Keyword: params.Keyword,
Ip: params.Ip,
Domain: params.Domain,
NodeId: params.NodeId,
NodeClusterId: params.ClusterId,
Size: size,
})
if err != nil {
@@ -87,6 +93,8 @@ func (this *TodayAction) RunGet(params struct {
Keyword: params.Keyword,
Ip: params.Ip,
Domain: params.Domain,
NodeId: params.NodeId,
NodeClusterId: params.ClusterId,
Size: size,
Reverse: true,
})

View File

@@ -48,8 +48,9 @@ func (this *ViewPopupAction) RunGet(params struct {
if policyResp.HttpFirewallPolicy != nil {
wafMap = maps.Map{
"policy": maps.Map{
"id": policyResp.HttpFirewallPolicy.Id,
"name": policyResp.HttpFirewallPolicy.Name,
"id": policyResp.HttpFirewallPolicy.Id,
"name": policyResp.HttpFirewallPolicy.Name,
"serverId": policyResp.HttpFirewallPolicy.ServerId,
},
}
if accessLog.FirewallRuleGroupId > 0 {

View File

@@ -64,6 +64,7 @@ func (this *IndexAction) RunGet(params struct {
"name": originConfig.Name,
"isOn": originConfig.IsOn,
"domains": originConfig.Domains,
"hasCert": originConfig.Cert != nil,
}
primaryOriginMaps = append(primaryOriginMaps, m)
}
@@ -78,6 +79,7 @@ func (this *IndexAction) RunGet(params struct {
"name": originConfig.Name,
"isOn": originConfig.IsOn,
"domains": originConfig.Domains,
"hasCert": originConfig.Cert != nil,
}
backupOriginMaps = append(backupOriginMaps, m)
}

View File

@@ -8,6 +8,7 @@ import (
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/sslconfigs"
"github.com/iwind/TeaGo/actions"
"net/url"
"regexp"
@@ -62,6 +63,8 @@ func (this *AddPopupAction) RunPost(params struct {
MaxIdleConns int32
IdleTimeout int
CertIdsJSON []byte
DomainsJSON []byte
Description string
@@ -129,6 +132,31 @@ func (this *AddPopupAction) RunPost(params struct {
return
}
// 证书
var certIds = []int64{}
if len(params.CertIdsJSON) > 0 {
err = json.Unmarshal(params.CertIdsJSON, &certIds)
if err != nil {
this.ErrorPage(err)
return
}
}
var certRefJSON []byte
if len(certIds) > 0 {
var certId = certIds[0]
if certId > 0 {
var certRef = &sslconfigs.SSLCertRef{
IsOn: true,
CertId: certId,
}
certRefJSON, err = json.Marshal(certRef)
if err != nil {
this.ErrorPage(err)
return
}
}
}
var domains = []string{}
if len(params.DomainsJSON) > 0 {
err = json.Unmarshal(params.DomainsJSON, &domains)
@@ -158,6 +186,7 @@ func (this *AddPopupAction) RunPost(params struct {
IdleTimeoutJSON: idleTimeoutJSON,
MaxConns: params.MaxConns,
MaxIdleConns: params.MaxIdleConns,
CertRefJSON: certRefJSON,
Domains: domains,
})
if err != nil {

View File

@@ -7,6 +7,7 @@ import (
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/sslconfigs"
"github.com/iwind/TeaGo/actions"
"github.com/iwind/TeaGo/maps"
"github.com/iwind/TeaGo/types"
@@ -86,6 +87,12 @@ func (this *UpdatePopupAction) RunGet(params struct {
config.Domains = []string{}
}
// 重置数据
if config.Cert != nil {
config.Cert.CertData = nil
config.Cert.KeyData = nil
}
this.Data["origin"] = maps.Map{
"id": config.Id,
"protocol": config.Addr.Protocol,
@@ -99,6 +106,7 @@ func (this *UpdatePopupAction) RunGet(params struct {
"idleTimeout": idleTimeout,
"maxConns": config.MaxConns,
"maxIdleConns": config.MaxIdleConns,
"cert": config.Cert,
"domains": config.Domains,
}
@@ -121,6 +129,7 @@ func (this *UpdatePopupAction) RunPost(params struct {
MaxIdleConns int32
IdleTimeout int
CertIdsJSON []byte
DomainsJSON []byte
Description string
@@ -188,6 +197,31 @@ func (this *UpdatePopupAction) RunPost(params struct {
return
}
// 证书
var certIds = []int64{}
if len(params.CertIdsJSON) > 0 {
err = json.Unmarshal(params.CertIdsJSON, &certIds)
if err != nil {
this.ErrorPage(err)
return
}
}
var certRefJSON []byte
if len(certIds) > 0 {
var certId = certIds[0]
if certId > 0 {
var certRef = &sslconfigs.SSLCertRef{
IsOn: true,
CertId: certId,
}
certRefJSON, err = json.Marshal(certRef)
if err != nil {
this.ErrorPage(err)
return
}
}
}
var domains = []string{}
if len(params.DomainsJSON) > 0 {
err = json.Unmarshal(params.DomainsJSON, &domains)
@@ -218,6 +252,7 @@ func (this *UpdatePopupAction) RunPost(params struct {
IdleTimeoutJSON: idleTimeoutJSON,
MaxConns: params.MaxConns,
MaxIdleConns: params.MaxIdleConns,
CertRefJSON: certRefJSON,
Domains: domains,
})
if err != nil {

View File

@@ -27,11 +27,13 @@ func (this *CreatePopupAction) RunGet(params struct {
}
func (this *CreatePopupAction) RunPost(params struct {
Mode string
BeforeURL string
AfterURL string
MatchPrefix bool
MatchRegexp bool
KeepRequestURI bool
KeepArgs bool
Status int
CondsJSON []byte
IsOn bool
@@ -99,12 +101,14 @@ func (this *CreatePopupAction) RunPost(params struct {
}
this.Data["redirect"] = maps.Map{
"mode": params.Mode,
"status": params.Status,
"beforeURL": params.BeforeURL,
"afterURL": params.AfterURL,
"matchPrefix": params.MatchPrefix,
"matchRegexp": params.MatchRegexp,
"keepRequestURI": params.KeepRequestURI,
"keepArgs": params.KeepArgs,
"conds": conds,
"isOn": params.IsOn,
}

View File

@@ -91,6 +91,7 @@ func (this *IndexAction) RunGet(params struct {
"name": originConfig.Name,
"isOn": originConfig.IsOn,
"domains": originConfig.Domains,
"hasCert": originConfig.Cert != nil,
}
primaryOriginMaps = append(primaryOriginMaps, m)
}
@@ -105,6 +106,7 @@ func (this *IndexAction) RunGet(params struct {
"name": originConfig.Name,
"isOn": originConfig.IsOn,
"domains": originConfig.Domains,
"hasCert": originConfig.Cert != nil,
}
backupOriginMaps = append(backupOriginMaps, m)
}

View File

@@ -85,6 +85,7 @@ func (this *GroupAction) RunGet(params struct {
"operator": rule.Operator,
"value": rule.Value,
"isCaseInsensitive": rule.IsCaseInsensitive,
"description": rule.Description,
"isComposed": firewallconfigs.CheckCheckpointIsComposed(rule.Prefix()),
"checkpointOptions": rule.CheckpointOptions,
"err": errString,

View File

@@ -113,6 +113,7 @@ func (this *AllowListAction) RunGet(params struct {
"ipTo": item.IpTo,
"createdTime": timeutil.FormatTime("Y-m-d", item.CreatedAt),
"expiredTime": expiredTime,
"lifeSeconds": item.ExpiredAt - time.Now().Unix(),
"reason": item.Reason,
"type": item.Type,
"isExpired": item.ExpiredAt > 0 && item.ExpiredAt < time.Now().Unix(),

View File

@@ -52,7 +52,7 @@ func (this *CountriesAction) RunGet(params struct {
return
}
countryMaps := []maps.Map{}
for _, country := range countriesResp.Countries {
for _, country := range countriesResp.RegionCountries {
countryMaps = append(countryMaps, maps.Map{
"id": country.Id,
"name": country.Name,

View File

@@ -113,6 +113,7 @@ func (this *DenyListAction) RunGet(params struct {
"ipTo": item.IpTo,
"createdTime": timeutil.FormatTime("Y-m-d", item.CreatedAt),
"expiredTime": expiredTime,
"lifeSeconds": item.ExpiredAt - time.Now().Unix(),
"reason": item.Reason,
"type": item.Type,
"isExpired": item.ExpiredAt > 0 && item.ExpiredAt < time.Now().Unix(),

View File

@@ -47,14 +47,14 @@ func (this *ProvincesAction) RunGet(params struct {
}
provincesResp, err := this.RPC().RegionProvinceRPC().FindAllEnabledRegionProvincesWithCountryId(this.AdminContext(), &pb.FindAllEnabledRegionProvincesWithCountryIdRequest{
CountryId: int64(ChinaCountryId),
RegionCountryId: int64(ChinaCountryId),
})
if err != nil {
this.ErrorPage(err)
return
}
provinceMaps := []maps.Map{}
for _, province := range provincesResp.Provinces {
for _, province := range provincesResp.RegionProvinces {
provinceMaps = append(provinceMaps, maps.Map{
"id": province.Id,
"name": province.Name,

View File

@@ -378,6 +378,16 @@ func (this *ServerHelper) createSettingsMenu(secondMenuItem string, serverIdStri
"isActive": secondMenuItem == "traffic",
"isOn": serverConfig.TrafficLimit != nil && serverConfig.TrafficLimit.IsOn,
})
if serverConfig.Web != nil && serverConfig.Web.RequestScripts != nil {
_ = serverConfig.Web.RequestScripts.Init()
}
menuItems = append(menuItems, maps.Map{
"name": "边缘脚本",
"url": "/servers/server/settings/requestScripts?serverId=" + serverIdString,
"isActive": secondMenuItem == "requestScripts",
"isOn": serverConfig.Web != nil && serverConfig.Web.RequestScripts != nil && !serverConfig.Web.RequestScripts.IsEmpty(),
})
}
menuItems = append(menuItems, maps.Map{

View File

@@ -31,12 +31,12 @@ func (this *IndexAction) RunGet(params struct{}) {
// 国家和地区
countryMaps := []maps.Map{}
for _, countryId := range config.AllowCountryIds {
countryResp, err := this.RPC().RegionCountryRPC().FindEnabledRegionCountry(this.AdminContext(), &pb.FindEnabledRegionCountryRequest{CountryId: countryId})
countryResp, err := this.RPC().RegionCountryRPC().FindEnabledRegionCountry(this.AdminContext(), &pb.FindEnabledRegionCountryRequest{RegionCountryId: countryId})
if err != nil {
this.ErrorPage(err)
return
}
country := countryResp.Country
country := countryResp.RegionCountry
if country != nil {
countryMaps = append(countryMaps, maps.Map{
"id": country.Id,
@@ -49,12 +49,12 @@ func (this *IndexAction) RunGet(params struct{}) {
// 省份
provinceMaps := []maps.Map{}
for _, provinceId := range config.AllowProvinceIds {
provinceResp, err := this.RPC().RegionProvinceRPC().FindEnabledRegionProvince(this.AdminContext(), &pb.FindEnabledRegionProvinceRequest{ProvinceId: provinceId})
provinceResp, err := this.RPC().RegionProvinceRPC().FindEnabledRegionProvince(this.AdminContext(), &pb.FindEnabledRegionProvinceRequest{RegionProvinceId: provinceId})
if err != nil {
this.ErrorPage(err)
return
}
province := provinceResp.Province
province := provinceResp.RegionProvince
if province != nil {
provinceMaps = append(provinceMaps, maps.Map{
"id": province.Id,

View File

@@ -6,11 +6,14 @@ import (
"encoding/json"
teaconst "github.com/TeaOSLab/EdgeAdmin/internal/const"
"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/maps"
"github.com/iwind/TeaGo/types"
stringutil "github.com/iwind/TeaGo/utils/string"
"io/ioutil"
"net/http"
"runtime"
"strings"
)
@@ -25,6 +28,22 @@ func (this *IndexAction) Init() {
func (this *IndexAction) RunGet(params struct{}) {
this.Data["version"] = teaconst.Version
valueResp, err := this.RPC().SysSettingRPC().ReadSysSetting(this.AdminContext(), &pb.ReadSysSettingRequest{Code: systemconfigs.SettingCodeCheckUpdates})
if err != nil {
this.ErrorPage(err)
return
}
var valueJSON = valueResp.ValueJSON
var config = &systemconfigs.CheckUpdatesConfig{AutoCheck: false}
if len(valueJSON) > 0 {
err = json.Unmarshal(valueJSON, config)
if err != nil {
this.ErrorPage(err)
return
}
}
this.Data["config"] = config
this.Show()
}
@@ -37,8 +56,8 @@ func (this *IndexAction) RunPost(params struct {
}
var apiURL = teaconst.UpdatesURL
apiURL = strings.ReplaceAll(apiURL, "${os}", "linux") //runtime.GOOS)
apiURL = strings.ReplaceAll(apiURL, "${arch}", "amd64") // runtime.GOARCH)
apiURL = strings.ReplaceAll(apiURL, "${os}", runtime.GOOS)
apiURL = strings.ReplaceAll(apiURL, "${arch}", runtime.GOARCH)
resp, err := http.Get(apiURL)
if err != nil {
this.Data["result"] = maps.Map{
@@ -109,7 +128,6 @@ func (this *IndexAction) RunPost(params struct {
"isOk": false,
"message": "找不到更新信息",
}
this.Success()
this.Success()
}

View File

@@ -14,6 +14,7 @@ func init() {
Helper(settingutils.NewHelper("updates")).
Prefix("/settings/updates").
GetPost("", new(IndexAction)).
Post("/update", new(UpdateAction)).
EndAll()
})
}

View File

@@ -0,0 +1,59 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package updates
import (
"encoding/json"
teaconst "github.com/TeaOSLab/EdgeAdmin/internal/const"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/TeaOSLab/EdgeCommon/pkg/systemconfigs"
)
type UpdateAction struct {
actionutils.ParentAction
}
func (this *UpdateAction) RunPost(params struct {
AutoCheck bool
}) {
valueResp, err := this.RPC().SysSettingRPC().ReadSysSetting(this.AdminContext(), &pb.ReadSysSettingRequest{Code: systemconfigs.SettingCodeCheckUpdates})
if err != nil {
this.ErrorPage(err)
return
}
var valueJSON = valueResp.ValueJSON
var config = &systemconfigs.CheckUpdatesConfig{AutoCheck: false}
if len(valueJSON) > 0 {
err = json.Unmarshal(valueJSON, config)
if err != nil {
this.ErrorPage(err)
return
}
}
config.AutoCheck = params.AutoCheck
configJSON, err := json.Marshal(config)
if err != nil {
this.ErrorPage(err)
return
}
_, err = this.RPC().SysSettingRPC().UpdateSysSetting(this.AdminContext(), &pb.UpdateSysSettingRequest{
Code: systemconfigs.SettingCodeCheckUpdates,
ValueJSON: configJSON,
})
if err != nil {
this.ErrorPage(err)
return
}
// 重置状态
if !config.AutoCheck {
teaconst.NewVersionCode = ""
teaconst.NewVersionDownloadURL = ""
}
this.Success()
}

View File

@@ -246,6 +246,8 @@ func (this *InstallAction) RunPost(params struct {
// 这里我们尝试多次是为了等待API节点启动完毕
if err != nil {
time.Sleep(1 * time.Second)
} else {
break
}
}
if err != nil {

View File

@@ -29,7 +29,7 @@ func (this *SelectCountriesPopupAction) RunGet(params struct {
return
}
countryMaps := []maps.Map{}
for _, country := range countriesResp.Countries {
for _, country := range countriesResp.RegionCountries {
countryMaps = append(countryMaps, maps.Map{
"id": country.Id,
"name": country.Name,
@@ -50,12 +50,12 @@ func (this *SelectCountriesPopupAction) RunPost(params struct {
}) {
countryMaps := []maps.Map{}
for _, countryId := range params.CountryIds {
countryResp, err := this.RPC().RegionCountryRPC().FindEnabledRegionCountry(this.AdminContext(), &pb.FindEnabledRegionCountryRequest{CountryId: countryId})
countryResp, err := this.RPC().RegionCountryRPC().FindEnabledRegionCountry(this.AdminContext(), &pb.FindEnabledRegionCountryRequest{RegionCountryId: countryId})
if err != nil {
this.ErrorPage(err)
return
}
country := countryResp.Country
country := countryResp.RegionCountry
if country == nil {
continue
}

View File

@@ -24,13 +24,13 @@ func (this *SelectProvincesPopupAction) RunGet(params struct {
}) {
selectedProvinceIds := utils.SplitNumbers(params.ProvinceIds)
provincesResp, err := this.RPC().RegionProvinceRPC().FindAllEnabledRegionProvincesWithCountryId(this.AdminContext(), &pb.FindAllEnabledRegionProvincesWithCountryIdRequest{CountryId: ChinaCountryId})
provincesResp, err := this.RPC().RegionProvinceRPC().FindAllEnabledRegionProvincesWithCountryId(this.AdminContext(), &pb.FindAllEnabledRegionProvincesWithCountryIdRequest{RegionCountryId: ChinaCountryId})
if err != nil {
this.ErrorPage(err)
return
}
provinceMaps := []maps.Map{}
for _, province := range provincesResp.Provinces {
for _, province := range provincesResp.RegionProvinces {
provinceMaps = append(provinceMaps, maps.Map{
"id": province.Id,
"name": province.Name,
@@ -50,12 +50,12 @@ func (this *SelectProvincesPopupAction) RunPost(params struct {
}) {
provinceMaps := []maps.Map{}
for _, provinceId := range params.ProvinceIds {
provinceResp, err := this.RPC().RegionProvinceRPC().FindEnabledRegionProvince(this.AdminContext(), &pb.FindEnabledRegionProvinceRequest{ProvinceId: provinceId})
provinceResp, err := this.RPC().RegionProvinceRPC().FindEnabledRegionProvince(this.AdminContext(), &pb.FindEnabledRegionProvinceRequest{RegionProvinceId: provinceId})
if err != nil {
this.ErrorPage(err)
return
}
province := provinceResp.Province
province := provinceResp.RegionProvince
if province == nil {
continue
}

View File

@@ -16,9 +16,16 @@ func (this *IndexAction) Init() {
}
func (this *IndexAction) RunGet(params struct {
Keyword string
Keyword string
Verifying bool
}) {
countResp, err := this.RPC().UserRPC().CountAllEnabledUsers(this.AdminContext(), &pb.CountAllEnabledUsersRequest{Keyword: params.Keyword})
this.Data["keyword"] = params.Keyword
this.Data["isVerifying"] = params.Verifying
countResp, err := this.RPC().UserRPC().CountAllEnabledUsers(this.AdminContext(), &pb.CountAllEnabledUsersRequest{
Keyword: params.Keyword,
IsVerifying: params.Verifying,
})
if err != nil {
this.ErrorPage(err)
return
@@ -28,15 +35,16 @@ func (this *IndexAction) RunGet(params struct {
this.Data["page"] = page.AsHTML()
usersResp, err := this.RPC().UserRPC().ListEnabledUsers(this.AdminContext(), &pb.ListEnabledUsersRequest{
Keyword: params.Keyword,
Offset: page.Offset,
Size: page.Size,
Keyword: params.Keyword,
IsVerifying: params.Verifying,
Offset: page.Offset,
Size: page.Size,
})
if err != nil {
this.ErrorPage(err)
return
}
userMaps := []maps.Map{}
var userMaps = []maps.Map{}
for _, user := range usersResp.Users {
var clusterMap maps.Map = nil
if user.NodeCluster != nil {
@@ -45,16 +53,20 @@ func (this *IndexAction) RunGet(params struct {
"name": user.NodeCluster.Name,
}
}
userMaps = append(userMaps, maps.Map{
"id": user.Id,
"username": user.Username,
"isOn": user.IsOn,
"fullname": user.Fullname,
"email": user.Email,
"mobile": user.Mobile,
"tel": user.Tel,
"createdTime": timeutil.FormatTime("Y-m-d H:i:s", user.CreatedAt),
"cluster": clusterMap,
"id": user.Id,
"username": user.Username,
"isOn": user.IsOn,
"fullname": user.Fullname,
"email": user.Email,
"mobile": user.Mobile,
"tel": user.Tel,
"createdTime": timeutil.FormatTime("Y-m-d H:i:s", user.CreatedAt),
"cluster": clusterMap,
"registeredIP": user.RegisteredIP,
"isVerified": user.IsVerified,
"isRejected": user.IsRejected,
})
}
this.Data["users"] = userMaps

View File

@@ -19,6 +19,7 @@ func init() {
GetPost("/update", new(UpdateAction)).
Post("/delete", new(DeleteAction)).
GetPost("/features", new(FeaturesAction)).
GetPost("/verifyPopup", new(VerifyPopupAction)).
// AccessKeys
Prefix("/users/accessKeys").
@@ -26,7 +27,6 @@ func init() {
GetPost("/createPopup", new(accesskeys.CreatePopupAction)).
Post("/delete", new(accesskeys.DeleteAction)).
Post("/updateIsOn", new(accesskeys.UpdateIsOnAction)).
EndAll()
})
}

View File

@@ -20,6 +20,11 @@ func (this *UserAction) RunGet(params struct {
}) {
err := userutils.InitUser(this.Parent(), params.UserId)
if err != nil {
if err == userutils.ErrUserNotFound {
this.RedirectURL("/users")
return
}
this.ErrorPage(err)
return
}
@@ -51,17 +56,35 @@ func (this *UserAction) RunGet(params struct {
}
countAccessKeys := countAccessKeyResp.Count
// IP地址
var registeredRegion = ""
if len(user.RegisteredIP) > 0 {
regionResp, err := this.RPC().IPLibraryRPC().LookupIPRegion(this.AdminContext(), &pb.LookupIPRegionRequest{Ip: user.RegisteredIP})
if err != nil {
this.ErrorPage(err)
return
}
if regionResp.IpRegion != nil {
registeredRegion = regionResp.IpRegion.Summary
}
}
this.Data["user"] = maps.Map{
"id": user.Id,
"username": user.Username,
"fullname": user.Fullname,
"email": user.Email,
"tel": user.Tel,
"remark": user.Remark,
"mobile": user.Mobile,
"isOn": user.IsOn,
"cluster": clusterMap,
"countAccessKeys": countAccessKeys,
"id": user.Id,
"username": user.Username,
"fullname": user.Fullname,
"email": user.Email,
"tel": user.Tel,
"remark": user.Remark,
"mobile": user.Mobile,
"isOn": user.IsOn,
"cluster": clusterMap,
"countAccessKeys": countAccessKeys,
"isRejected": user.IsRejected,
"rejectReason": user.RejectReason,
"isVerified": user.IsVerified,
"registeredIP": user.RegisteredIP,
"registeredRegion": registeredRegion,
}
this.Show()

View File

@@ -7,6 +7,8 @@ import (
"github.com/iwind/TeaGo/maps"
)
var ErrUserNotFound = errors.New("not found user")
// InitUser 查找用户基本信息
func InitUser(p *actionutils.ParentAction, userId int64) error {
resp, err := p.RPC().UserRPC().FindEnabledUser(p.AdminContext(), &pb.FindEnabledUserRequest{UserId: userId})
@@ -14,7 +16,7 @@ func InitUser(p *actionutils.ParentAction, userId int64) error {
return err
}
if resp.User == nil {
return errors.New("not found user")
return ErrUserNotFound
}
// AccessKey数量

View File

@@ -0,0 +1,56 @@
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package users
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/actions"
)
type VerifyPopupAction struct {
actionutils.ParentAction
}
func (this *VerifyPopupAction) RunGet(params struct {
UserId int64
}) {
this.Data["userId"] = params.UserId
this.Show()
}
func (this *VerifyPopupAction) RunPost(params struct {
UserId int64
Result string
RejectReason string
Must *actions.Must
CSRF *actionutils.CSRF
}) {
defer this.CreateLogInfo("审核用户:%d 结果:%s", params.UserId, params.Result)
if params.Result == "pass" {
params.RejectReason = ""
}
_, err := this.RPC().UserRPC().VerifyUser(this.AdminContext(), &pb.VerifyUserRequest{
UserId: params.UserId,
IsRejected: params.Result == "reject" || params.Result == "delete",
RejectReason: params.RejectReason,
})
if err != nil {
this.ErrorPage(err)
return
}
if params.Result == "delete" {
_, err = this.RPC().UserRPC().DeleteUser(this.AdminContext(), &pb.DeleteUserRequest{UserId: params.UserId})
if err != nil {
this.ErrorPage(err)
return
}
}
this.Success()
}

View File

@@ -9,7 +9,7 @@ import (
"github.com/iwind/TeaGo/maps"
)
func FindAllMenuMaps(nodeLogsType string, countUnreadNodeLogs int64) []maps.Map {
func FindAllMenuMaps(nodeLogsType string, countUnreadNodeLogs int64, countUnreadIPItems int64) []maps.Map {
return []maps.Map{
{
"code": "dashboard",
@@ -50,9 +50,10 @@ func FindAllMenuMaps(nodeLogsType string, countUnreadNodeLogs int64) []maps.Map
"code": "waf",
},
{
"name": "IP名单",
"url": "/servers/iplists",
"code": "iplist",
"name": "IP名单",
"url": "/servers/iplists",
"code": "iplist",
"badge": countUnreadIPItems,
},
{
"name": "统计指标",

Some files were not shown because too many files have changed in this diff Show More