Compare commits
97 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
567ffc80b6 | ||
|
|
5d15a08ac8 | ||
|
|
2b84037346 | ||
|
|
536f11e617 | ||
|
|
5d367a384e | ||
|
|
04933e6bf0 | ||
|
|
12abe9aa69 | ||
|
|
cba642a4bc | ||
|
|
9fce0ac0aa | ||
|
|
681812b619 | ||
|
|
6d0be57698 | ||
|
|
1d521602e1 | ||
|
|
2f67e7937a | ||
|
|
e0078a42dc | ||
|
|
3ec875d49d | ||
|
|
35028d1310 | ||
|
|
7ba3d7c4bb | ||
|
|
c05e64098c | ||
|
|
e82ee56a2c | ||
|
|
5681b61aea | ||
|
|
d6ce7eab25 | ||
|
|
bf597fe41c | ||
|
|
6a920f964f | ||
|
|
977b66ba4e | ||
|
|
4659c29358 | ||
|
|
e3bc95b275 | ||
|
|
bf51255e13 | ||
|
|
915fe6837b | ||
|
|
d1237215c0 | ||
|
|
8ba5cfdfa6 | ||
|
|
0d1097425d | ||
|
|
0789a9ecc8 | ||
|
|
400f764b74 | ||
|
|
46e036e3a4 | ||
|
|
17e6264af8 | ||
|
|
468b6ae125 | ||
|
|
e5f5ee4f6a | ||
|
|
3695082ec2 | ||
|
|
f384d86014 | ||
|
|
34bf5028c3 | ||
|
|
8b727aa939 | ||
|
|
9432600de6 | ||
|
|
bb790ec687 | ||
|
|
8bad658d7c | ||
|
|
a66cc9c08a | ||
|
|
0dc24fb342 | ||
|
|
b965ac6232 | ||
|
|
08d61013c8 | ||
|
|
7796f65814 | ||
|
|
02a3afb9ad | ||
|
|
15a11c384b | ||
|
|
57b8496d89 | ||
|
|
7bbe44f5d2 | ||
|
|
ac11ab0431 | ||
|
|
12e352964c | ||
|
|
7daefc4384 | ||
|
|
29541becd0 | ||
|
|
ef6dc82f88 | ||
|
|
6d66d93180 | ||
|
|
3ded17b920 | ||
|
|
d35651f570 | ||
|
|
235300d034 | ||
|
|
2f7ebf5166 | ||
|
|
4819cc87c6 | ||
|
|
c5da383d1e | ||
|
|
2da17329fa | ||
|
|
70d84acf76 | ||
|
|
fef99a0023 | ||
|
|
76d0935e8f | ||
|
|
42dfe5ada9 | ||
|
|
ef136c25e1 | ||
|
|
4251635a8a | ||
|
|
13f00104dd | ||
|
|
b0b82b29c1 | ||
|
|
e0d43ad3d9 | ||
|
|
ae15115af7 | ||
|
|
a2890c6cb0 | ||
|
|
2b00ece07f | ||
|
|
2e3c34571f | ||
|
|
b8b10b5176 | ||
|
|
e6e62bbd24 | ||
|
|
05e9bbf1d6 | ||
|
|
bf94c2395f | ||
|
|
4a749ca345 | ||
|
|
80ffe6c9a3 | ||
|
|
5414b5a8f9 | ||
|
|
e3ba85a326 | ||
|
|
154fa69dbb | ||
|
|
76c44973e9 | ||
|
|
26fdc82cc1 | ||
|
|
dcc587182c | ||
|
|
7cee1ff5ff | ||
|
|
78b8e3bf0b | ||
|
|
bd4c014c12 | ||
|
|
daa263cd68 | ||
|
|
e2965d39af | ||
|
|
8279d15ebb |
@@ -1,23 +1,30 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/apps"
|
"github.com/TeaOSLab/EdgeAdmin/internal/apps"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/configs"
|
"github.com/TeaOSLab/EdgeAdmin/internal/configs"
|
||||||
teaconst "github.com/TeaOSLab/EdgeAdmin/internal/const"
|
teaconst "github.com/TeaOSLab/EdgeAdmin/internal/const"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/gen"
|
"github.com/TeaOSLab/EdgeAdmin/internal/gen"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/nodes"
|
"github.com/TeaOSLab/EdgeAdmin/internal/nodes"
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/utils"
|
||||||
_ "github.com/TeaOSLab/EdgeAdmin/internal/web"
|
_ "github.com/TeaOSLab/EdgeAdmin/internal/web"
|
||||||
|
"github.com/iwind/TeaGo/Tea"
|
||||||
_ "github.com/iwind/TeaGo/bootstrap"
|
_ "github.com/iwind/TeaGo/bootstrap"
|
||||||
"github.com/iwind/TeaGo/maps"
|
"github.com/iwind/TeaGo/maps"
|
||||||
"github.com/iwind/gosock/pkg/gosock"
|
"github.com/iwind/gosock/pkg/gosock"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
app := apps.NewAppCmd().
|
var app = apps.NewAppCmd().
|
||||||
Version(teaconst.Version).
|
Version(teaconst.Version).
|
||||||
Product(teaconst.ProductName).
|
Product(teaconst.ProductName).
|
||||||
Usage(teaconst.ProcessName+" [-v|start|stop|restart|service|daemon|reset|recover|demo]").
|
Usage(teaconst.ProcessName+" [-v|start|stop|restart|service|daemon|reset|recover|demo|upgrade]").
|
||||||
Usage(teaconst.ProcessName+" [dev|prod]").
|
Usage(teaconst.ProcessName+" [dev|prod]").
|
||||||
Option("-h", "show this help").
|
Option("-h", "show this help").
|
||||||
Option("-v", "show version").
|
Option("-v", "show version").
|
||||||
@@ -30,7 +37,8 @@ func main() {
|
|||||||
Option("recover", "enter recovery mode").
|
Option("recover", "enter recovery mode").
|
||||||
Option("demo", "switch to demo mode").
|
Option("demo", "switch to demo mode").
|
||||||
Option("dev", "switch to 'dev' mode").
|
Option("dev", "switch to 'dev' mode").
|
||||||
Option("prod", "switch to 'prod' mode")
|
Option("prod", "switch to 'prod' mode").
|
||||||
|
Option("upgrade", "upgrade from official site")
|
||||||
|
|
||||||
app.On("daemon", func() {
|
app.On("daemon", func() {
|
||||||
nodes.NewAdminNode().Daemon()
|
nodes.NewAdminNode().Daemon()
|
||||||
@@ -49,6 +57,20 @@ func main() {
|
|||||||
fmt.Println("[ERROR]reset failed: " + err.Error())
|
fmt.Println("[ERROR]reset failed: " + err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// reset local api
|
||||||
|
var apiNodeExe = Tea.Root + "/edge-api/bin/edge-api"
|
||||||
|
_, err = os.Stat(apiNodeExe)
|
||||||
|
if err == nil {
|
||||||
|
var cmd = exec.Command(apiNodeExe, "reset")
|
||||||
|
var stderr = &bytes.Buffer{}
|
||||||
|
cmd.Stderr = stderr
|
||||||
|
err = cmd.Run()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("reset api node failed: " + stderr.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fmt.Println("done")
|
fmt.Println("done")
|
||||||
})
|
})
|
||||||
app.On("recover", func() {
|
app.On("recover", func() {
|
||||||
@@ -115,8 +137,42 @@ func main() {
|
|||||||
fmt.Println("switch to '" + env + "' ok")
|
fmt.Println("switch to '" + env + "' ok")
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
app.On("upgrade", func() {
|
||||||
|
var manager = utils.NewUpgradeManager("admin")
|
||||||
|
log.Println("checking latest version ...")
|
||||||
|
var ticker = time.NewTicker(1 * time.Second)
|
||||||
|
go func() {
|
||||||
|
var lastProgress float32 = 0
|
||||||
|
var isStarted = false
|
||||||
|
for range ticker.C {
|
||||||
|
if manager.IsDownloading() {
|
||||||
|
if !isStarted {
|
||||||
|
log.Println("start downloading v" + manager.NewVersion() + " ...")
|
||||||
|
isStarted = true
|
||||||
|
}
|
||||||
|
var progress = manager.Progress()
|
||||||
|
if progress >= 0 {
|
||||||
|
if progress == 0 || progress == 1 || progress-lastProgress >= 0.1 {
|
||||||
|
lastProgress = progress
|
||||||
|
log.Println(fmt.Sprintf("%.2f%%", manager.Progress()*100))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
err := manager.Start()
|
||||||
|
if err != nil {
|
||||||
|
log.Println("upgrade failed: " + err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
log.Println("finished!")
|
||||||
|
log.Println("restarting ...")
|
||||||
|
app.RunRestart()
|
||||||
|
})
|
||||||
app.Run(func() {
|
app.Run(func() {
|
||||||
adminNode := nodes.NewAdminNode()
|
var adminNode = nodes.NewAdminNode()
|
||||||
adminNode.Run()
|
adminNode.Run()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -123,7 +123,7 @@ func (this *AppCmd) On(arg string, callback func()) {
|
|||||||
// Run 运行
|
// Run 运行
|
||||||
func (this *AppCmd) Run(main func()) {
|
func (this *AppCmd) Run(main func()) {
|
||||||
// 获取参数
|
// 获取参数
|
||||||
args := os.Args[1:]
|
var args = os.Args[1:]
|
||||||
if len(args) > 0 {
|
if len(args) > 0 {
|
||||||
switch args[0] {
|
switch args[0] {
|
||||||
case "-v", "version", "-version", "--version":
|
case "-v", "version", "-version", "--version":
|
||||||
@@ -139,7 +139,7 @@ func (this *AppCmd) Run(main func()) {
|
|||||||
this.runStop()
|
this.runStop()
|
||||||
return
|
return
|
||||||
case "restart":
|
case "restart":
|
||||||
this.runRestart()
|
this.RunRestart()
|
||||||
return
|
return
|
||||||
case "status":
|
case "status":
|
||||||
this.runStatus()
|
this.runStatus()
|
||||||
@@ -160,7 +160,7 @@ func (this *AppCmd) Run(main func()) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 日志
|
// 日志
|
||||||
writer := new(LogWriter)
|
var writer = new(LogWriter)
|
||||||
writer.Init()
|
writer.Init()
|
||||||
logs.SetWriter(writer)
|
logs.SetWriter(writer)
|
||||||
|
|
||||||
@@ -210,7 +210,7 @@ func (this *AppCmd) runStop() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 重启
|
// 重启
|
||||||
func (this *AppCmd) runRestart() {
|
func (this *AppCmd) RunRestart() {
|
||||||
this.runStop()
|
this.runStop()
|
||||||
time.Sleep(1 * time.Second)
|
time.Sleep(1 * time.Second)
|
||||||
this.runStart()
|
this.runStart()
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestLoadAdminModuleMapping(t *testing.T) {
|
func TestLoadAdminModuleMapping(t *testing.T) {
|
||||||
m, err := LoadAdminModuleMapping()
|
m, err := loadAdminModuleMapping()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import (
|
|||||||
func TestLoadUIConfig(t *testing.T) {
|
func TestLoadUIConfig(t *testing.T) {
|
||||||
for i := 0; i < 10; i++ {
|
for i := 0; i < 10; i++ {
|
||||||
before := time.Now()
|
before := time.Now()
|
||||||
config, err := LoadUIConfig()
|
config, err := LoadAdminUIConfig()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -20,7 +20,7 @@ func TestLoadUIConfig(t *testing.T) {
|
|||||||
|
|
||||||
func TestLoadUIConfig2(t *testing.T) {
|
func TestLoadUIConfig2(t *testing.T) {
|
||||||
for i := 0; i < 10; i++ {
|
for i := 0; i < 10; i++ {
|
||||||
config, err := LoadUIConfig()
|
config, err := LoadAdminUIConfig()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,10 +61,11 @@ func LoadAPIConfig() (*APIConfig, error) {
|
|||||||
|
|
||||||
// ResetAPIConfig 重置配置
|
// ResetAPIConfig 重置配置
|
||||||
func ResetAPIConfig() error {
|
func ResetAPIConfig() error {
|
||||||
filename := "api.yaml"
|
var filename = "api.yaml"
|
||||||
|
|
||||||
|
// 重置 configs/api.yaml
|
||||||
{
|
{
|
||||||
configFile := Tea.ConfigFile(filename)
|
var configFile = Tea.ConfigFile(filename)
|
||||||
stat, err := os.Stat(configFile)
|
stat, err := os.Stat(configFile)
|
||||||
if err == nil && !stat.IsDir() {
|
if err == nil && !stat.IsDir() {
|
||||||
err = os.Remove(configFile)
|
err = os.Remove(configFile)
|
||||||
@@ -77,7 +78,7 @@ func ResetAPIConfig() error {
|
|||||||
// 重置 ~/.edge-admin/api.yaml
|
// 重置 ~/.edge-admin/api.yaml
|
||||||
homeDir, homeErr := os.UserHomeDir()
|
homeDir, homeErr := os.UserHomeDir()
|
||||||
if homeErr == nil {
|
if homeErr == nil {
|
||||||
configFile := homeDir + "/." + teaconst.ProcessName + "/" + filename
|
var configFile = homeDir + "/." + teaconst.ProcessName + "/" + filename
|
||||||
stat, err := os.Stat(configFile)
|
stat, err := os.Stat(configFile)
|
||||||
if err == nil && !stat.IsDir() {
|
if err == nil && !stat.IsDir() {
|
||||||
err = os.Remove(configFile)
|
err = os.Remove(configFile)
|
||||||
@@ -89,7 +90,7 @@ func ResetAPIConfig() error {
|
|||||||
|
|
||||||
// 重置 /etc/edge-admin/api.yaml
|
// 重置 /etc/edge-admin/api.yaml
|
||||||
{
|
{
|
||||||
configFile := "/etc/" + teaconst.ProcessName + "/" + filename
|
var configFile = "/etc/" + teaconst.ProcessName + "/" + filename
|
||||||
stat, err := os.Stat(configFile)
|
stat, err := os.Stat(configFile)
|
||||||
if err == nil && !stat.IsDir() {
|
if err == nil && !stat.IsDir() {
|
||||||
err = os.Remove(configFile)
|
err = os.Remove(configFile)
|
||||||
|
|||||||
@@ -14,13 +14,7 @@ func TestLoadAPIConfig(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestAPIConfig_WriteFile(t *testing.T) {
|
func TestAPIConfig_WriteFile(t *testing.T) {
|
||||||
config := &APIConfig{
|
config := &APIConfig{}
|
||||||
RPC: struct {
|
|
||||||
Endpoints []string `yaml:"endpoints"`
|
|
||||||
}{},
|
|
||||||
NodeId: "1",
|
|
||||||
Secret: "2",
|
|
||||||
}
|
|
||||||
err := config.WriteFile("/tmp/api_config.yaml")
|
err := config.WriteFile("/tmp/api_config.yaml")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
package teaconst
|
package teaconst
|
||||||
|
|
||||||
const (
|
const (
|
||||||
Version = "0.5.2"
|
Version = "0.5.7"
|
||||||
|
|
||||||
APINodeVersion = "0.5.2"
|
APINodeVersion = "0.5.7"
|
||||||
|
|
||||||
ProductName = "Edge Admin"
|
ProductName = "Edge Admin"
|
||||||
ProcessName = "edge-admin"
|
ProcessName = "edge-admin"
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
package nodes
|
package nodes
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/configs"
|
"github.com/TeaOSLab/EdgeAdmin/internal/configs"
|
||||||
teaconst "github.com/TeaOSLab/EdgeAdmin/internal/const"
|
teaconst "github.com/TeaOSLab/EdgeAdmin/internal/const"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/errors"
|
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/events"
|
"github.com/TeaOSLab/EdgeAdmin/internal/events"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/utils"
|
"github.com/TeaOSLab/EdgeAdmin/internal/utils"
|
||||||
"github.com/iwind/TeaGo"
|
"github.com/iwind/TeaGo"
|
||||||
@@ -90,7 +90,7 @@ func (this *AdminNode) Run() {
|
|||||||
EndAll().
|
EndAll().
|
||||||
Session(sessions.NewFileSessionManager(86400, secret), teaconst.CookieSID).
|
Session(sessions.NewFileSessionManager(86400, secret), teaconst.CookieSID).
|
||||||
ReadHeaderTimeout(3 * time.Second).
|
ReadHeaderTimeout(3 * time.Second).
|
||||||
ReadTimeout(600 * time.Second).
|
ReadTimeout(1200 * time.Second).
|
||||||
Start()
|
Start()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -98,10 +98,6 @@ func (this *RPCClient) NodeRegionRPC() pb.NodeRegionServiceClient {
|
|||||||
return pb.NewNodeRegionServiceClient(this.pickConn())
|
return pb.NewNodeRegionServiceClient(this.pickConn())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *RPCClient) NodePriceItemRPC() pb.NodePriceItemServiceClient {
|
|
||||||
return pb.NewNodePriceItemServiceClient(this.pickConn())
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *RPCClient) NodeIPAddressRPC() pb.NodeIPAddressServiceClient {
|
func (this *RPCClient) NodeIPAddressRPC() pb.NodeIPAddressServiceClient {
|
||||||
return pb.NewNodeIPAddressServiceClient(this.pickConn())
|
return pb.NewNodeIPAddressServiceClient(this.pickConn())
|
||||||
}
|
}
|
||||||
@@ -174,18 +170,10 @@ func (this *RPCClient) APIMethodStatRPC() pb.APIMethodStatServiceClient {
|
|||||||
return pb.NewAPIMethodStatServiceClient(this.pickConn())
|
return pb.NewAPIMethodStatServiceClient(this.pickConn())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *RPCClient) UserNodeRPC() pb.UserNodeServiceClient {
|
|
||||||
return pb.NewUserNodeServiceClient(this.pickConn())
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *RPCClient) DBNodeRPC() pb.DBNodeServiceClient {
|
func (this *RPCClient) DBNodeRPC() pb.DBNodeServiceClient {
|
||||||
return pb.NewDBNodeServiceClient(this.pickConn())
|
return pb.NewDBNodeServiceClient(this.pickConn())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *RPCClient) MonitorNodeRPC() pb.MonitorNodeServiceClient {
|
|
||||||
return pb.NewMonitorNodeServiceClient(this.pickConn())
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *RPCClient) DBRPC() pb.DBServiceClient {
|
func (this *RPCClient) DBRPC() pb.DBServiceClient {
|
||||||
return pb.NewDBServiceClient(this.pickConn())
|
return pb.NewDBServiceClient(this.pickConn())
|
||||||
}
|
}
|
||||||
@@ -407,26 +395,6 @@ func (this *RPCClient) UserRPC() pb.UserServiceClient {
|
|||||||
return pb.NewUserServiceClient(this.pickConn())
|
return pb.NewUserServiceClient(this.pickConn())
|
||||||
}
|
}
|
||||||
|
|
||||||
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())
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *RPCClient) UserAccountLogRPC() pb.UserAccountLogServiceClient {
|
|
||||||
return pb.NewUserAccountLogServiceClient(this.pickConn())
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *RPCClient) UserAccountDailyStatRPC() pb.UserAccountDailyStatServiceClient {
|
|
||||||
return pb.NewUserAccountDailyStatServiceClient(this.pickConn())
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *RPCClient) UserAccessKeyRPC() pb.UserAccessKeyServiceClient {
|
func (this *RPCClient) UserAccessKeyRPC() pb.UserAccessKeyServiceClient {
|
||||||
return pb.NewUserAccessKeyServiceClient(this.pickConn())
|
return pb.NewUserAccessKeyServiceClient(this.pickConn())
|
||||||
}
|
}
|
||||||
@@ -483,14 +451,6 @@ func (this *RPCClient) ServerStatBoardChartRPC() pb.ServerStatBoardChartServiceC
|
|||||||
return pb.NewServerStatBoardChartServiceClient(this.pickConn())
|
return pb.NewServerStatBoardChartServiceClient(this.pickConn())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *RPCClient) PlanRPC() pb.PlanServiceClient {
|
|
||||||
return pb.NewPlanServiceClient(this.pickConn())
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *RPCClient) UserPlanRPC() pb.UserPlanServiceClient {
|
|
||||||
return pb.NewUserPlanServiceClient(this.pickConn())
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *RPCClient) TrafficDailyStatRPC() pb.TrafficDailyStatServiceClient {
|
func (this *RPCClient) TrafficDailyStatRPC() pb.TrafficDailyStatServiceClient {
|
||||||
return pb.NewTrafficDailyStatServiceClient(this.pickConn())
|
return pb.NewTrafficDailyStatServiceClient(this.pickConn())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import (
|
|||||||
"github.com/iwind/TeaGo/logs"
|
"github.com/iwind/TeaGo/logs"
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
"google.golang.org/grpc/credentials"
|
"google.golang.org/grpc/credentials"
|
||||||
|
"google.golang.org/grpc/credentials/insecure"
|
||||||
"net/url"
|
"net/url"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -143,8 +144,9 @@ func (this *SyncAPINodesTask) testEndpoints(endpoints []string) bool {
|
|||||||
cancel()
|
cancel()
|
||||||
}()
|
}()
|
||||||
var conn *grpc.ClientConn
|
var conn *grpc.ClientConn
|
||||||
|
|
||||||
if u.Scheme == "http" {
|
if u.Scheme == "http" {
|
||||||
conn, err = grpc.DialContext(ctx, u.Host, grpc.WithInsecure(), grpc.WithBlock())
|
conn, err = grpc.DialContext(ctx, u.Host, grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithBlock())
|
||||||
} else if u.Scheme == "https" {
|
} else if u.Scheme == "https" {
|
||||||
conn, err = grpc.DialContext(ctx, u.Host, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{
|
conn, err = grpc.DialContext(ctx, u.Host, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{
|
||||||
InsecureSkipVerify: true,
|
InsecureSkipVerify: true,
|
||||||
|
|||||||
12
internal/utils/email.go
Normal file
12
internal/utils/email.go
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||||
|
|
||||||
|
package utils
|
||||||
|
|
||||||
|
import "regexp"
|
||||||
|
|
||||||
|
var emailReg = regexp.MustCompile(`(?i)^[a-z\d]+([._+-]*[a-z\d]+)*@([a-z\d]+[a-z\d-]*[a-z\d]+\.)+[a-z\d]+$`)
|
||||||
|
|
||||||
|
// ValidateEmail 校验电子邮箱格式
|
||||||
|
func ValidateEmail(email string) bool {
|
||||||
|
return emailReg.MatchString(email)
|
||||||
|
}
|
||||||
22
internal/utils/email_test.go
Normal file
22
internal/utils/email_test.go
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||||
|
|
||||||
|
package utils_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
||||||
|
"github.com/iwind/TeaGo/assert"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestValidateEmail(t *testing.T) {
|
||||||
|
var a = assert.NewAssertion(t)
|
||||||
|
a.IsTrue(utils.ValidateEmail("aaaa@gmail.com"))
|
||||||
|
a.IsTrue(utils.ValidateEmail("a.b@gmail.com"))
|
||||||
|
a.IsTrue(utils.ValidateEmail("a.b.c.d@gmail.com"))
|
||||||
|
a.IsTrue(utils.ValidateEmail("aaaa@gmail.com.cn"))
|
||||||
|
a.IsTrue(utils.ValidateEmail("hello.world.123@gmail.123.com"))
|
||||||
|
a.IsTrue(utils.ValidateEmail("10000@qq.com"))
|
||||||
|
a.IsFalse(utils.ValidateEmail("aaaa.@gmail.com"))
|
||||||
|
a.IsFalse(utils.ValidateEmail("aaaa@gmail"))
|
||||||
|
a.IsFalse(utils.ValidateEmail("aaaa@123"))
|
||||||
|
}
|
||||||
@@ -3,7 +3,9 @@ package numberutils
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/iwind/TeaGo/types"
|
"github.com/iwind/TeaGo/types"
|
||||||
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
func FormatInt64(value int64) string {
|
func FormatInt64(value int64) string {
|
||||||
@@ -28,17 +30,35 @@ func FormatBytes(bytes int64) string {
|
|||||||
if bytes < Pow1024(1) {
|
if bytes < Pow1024(1) {
|
||||||
return FormatInt64(bytes) + "B"
|
return FormatInt64(bytes) + "B"
|
||||||
} else if bytes < Pow1024(2) {
|
} else if bytes < Pow1024(2) {
|
||||||
return fmt.Sprintf("%.2fKB", float64(bytes)/float64(Pow1024(1)))
|
return TrimZeroSuffix(fmt.Sprintf("%.2fKB", float64(bytes)/float64(Pow1024(1))))
|
||||||
} else if bytes < Pow1024(3) {
|
} else if bytes < Pow1024(3) {
|
||||||
return fmt.Sprintf("%.2fMB", float64(bytes)/float64(Pow1024(2)))
|
return TrimZeroSuffix(fmt.Sprintf("%.2fMB", float64(bytes)/float64(Pow1024(2))))
|
||||||
} else if bytes < Pow1024(4) {
|
} else if bytes < Pow1024(4) {
|
||||||
return fmt.Sprintf("%.2fGB", float64(bytes)/float64(Pow1024(3)))
|
return TrimZeroSuffix(fmt.Sprintf("%.2fGB", float64(bytes)/float64(Pow1024(3))))
|
||||||
} else if bytes < Pow1024(5) {
|
} else if bytes < Pow1024(5) {
|
||||||
return fmt.Sprintf("%.2fTB", float64(bytes)/float64(Pow1024(4)))
|
return TrimZeroSuffix(fmt.Sprintf("%.2fTB", float64(bytes)/float64(Pow1024(4))))
|
||||||
} else if bytes < Pow1024(6) {
|
} else if bytes < Pow1024(6) {
|
||||||
return fmt.Sprintf("%.2fPB", float64(bytes)/float64(Pow1024(5)))
|
return TrimZeroSuffix(fmt.Sprintf("%.2fPB", float64(bytes)/float64(Pow1024(5))))
|
||||||
} else {
|
} else {
|
||||||
return fmt.Sprintf("%.2fEB", float64(bytes)/float64(Pow1024(6)))
|
return TrimZeroSuffix(fmt.Sprintf("%.2fEB", float64(bytes)/float64(Pow1024(6))))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func FormatBits(bits int64) string {
|
||||||
|
if bits < Pow1024(1) {
|
||||||
|
return FormatInt64(bits) + "bps"
|
||||||
|
} else if bits < Pow1024(2) {
|
||||||
|
return TrimZeroSuffix(fmt.Sprintf("%.4fKbps", float64(bits)/float64(Pow1024(1))))
|
||||||
|
} else if bits < Pow1024(3) {
|
||||||
|
return TrimZeroSuffix(fmt.Sprintf("%.4fMbps", float64(bits)/float64(Pow1024(2))))
|
||||||
|
} else if bits < Pow1024(4) {
|
||||||
|
return TrimZeroSuffix(fmt.Sprintf("%.4fGbps", float64(bits)/float64(Pow1024(3))))
|
||||||
|
} else if bits < Pow1024(5) {
|
||||||
|
return TrimZeroSuffix(fmt.Sprintf("%.4fTbps", float64(bits)/float64(Pow1024(4))))
|
||||||
|
} else if bits < Pow1024(6) {
|
||||||
|
return TrimZeroSuffix(fmt.Sprintf("%.4fPbps", float64(bits)/float64(Pow1024(5))))
|
||||||
|
} else {
|
||||||
|
return TrimZeroSuffix(fmt.Sprintf("%.4fEbps", float64(bits)/float64(Pow1024(6))))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -62,9 +82,19 @@ func FormatFloat(f interface{}, decimal int) string {
|
|||||||
switch x := f.(type) {
|
switch x := f.(type) {
|
||||||
case float32, float64:
|
case float32, float64:
|
||||||
var s = fmt.Sprintf("%."+types.String(decimal)+"f", x)
|
var s = fmt.Sprintf("%."+types.String(decimal)+"f", x)
|
||||||
|
|
||||||
|
// 分隔
|
||||||
|
var dotIndex = strings.Index(s, ".")
|
||||||
|
if dotIndex > 0 {
|
||||||
|
var d = s[:dotIndex]
|
||||||
|
var f2 = s[dotIndex:]
|
||||||
|
f2 = strings.TrimRight(strings.TrimRight(f2, "0"), ".")
|
||||||
|
return formatDigit(d) + f2
|
||||||
|
}
|
||||||
|
|
||||||
return s
|
return s
|
||||||
case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64:
|
case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64:
|
||||||
return types.String(x)
|
return formatDigit(types.String(x))
|
||||||
case string:
|
case string:
|
||||||
return x
|
return x
|
||||||
}
|
}
|
||||||
@@ -74,3 +104,44 @@ func FormatFloat(f interface{}, decimal int) string {
|
|||||||
func FormatFloat2(f interface{}) string {
|
func FormatFloat2(f interface{}) string {
|
||||||
return FormatFloat(f, 2)
|
return FormatFloat(f, 2)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var decimalReg = regexp.MustCompile(`^(\d+\.\d+)([a-zA-Z]+)?$`)
|
||||||
|
|
||||||
|
// TrimZeroSuffix 去除小数数字尾部多余的0
|
||||||
|
func TrimZeroSuffix(s string) string {
|
||||||
|
var matches = decimalReg.FindStringSubmatch(s)
|
||||||
|
if len(matches) < 3 {
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
return strings.TrimRight(strings.TrimRight(matches[1], "0"), ".") + matches[2]
|
||||||
|
}
|
||||||
|
|
||||||
|
func formatDigit(d string) string {
|
||||||
|
if len(d) == 0 {
|
||||||
|
return d
|
||||||
|
}
|
||||||
|
|
||||||
|
var prefix = ""
|
||||||
|
if d[0] < '0' || d[0] > '9' {
|
||||||
|
prefix = d[:1]
|
||||||
|
d = d[1:]
|
||||||
|
}
|
||||||
|
|
||||||
|
var l = len(d)
|
||||||
|
if l > 3 {
|
||||||
|
var pieces = l / 3
|
||||||
|
var commIndex = l - pieces*3
|
||||||
|
var d2 = ""
|
||||||
|
if commIndex > 0 {
|
||||||
|
d2 = d[:commIndex] + ", "
|
||||||
|
}
|
||||||
|
for i := 0; i < pieces; i++ {
|
||||||
|
d2 += d[commIndex+i*3 : commIndex+i*3+3]
|
||||||
|
if i != pieces-1 {
|
||||||
|
d2 += ", "
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return prefix + d2
|
||||||
|
}
|
||||||
|
return prefix + d
|
||||||
|
}
|
||||||
|
|||||||
@@ -33,4 +33,35 @@ func TestFormatFloat(t *testing.T) {
|
|||||||
t.Log(numberutils.FormatFloat(100.23456, 2))
|
t.Log(numberutils.FormatFloat(100.23456, 2))
|
||||||
t.Log(numberutils.FormatFloat(100.000023, 2))
|
t.Log(numberutils.FormatFloat(100.000023, 2))
|
||||||
t.Log(numberutils.FormatFloat(100.012, 2))
|
t.Log(numberutils.FormatFloat(100.012, 2))
|
||||||
|
t.Log(numberutils.FormatFloat(123.012, 2))
|
||||||
|
t.Log(numberutils.FormatFloat(1234.012, 2))
|
||||||
|
t.Log(numberutils.FormatFloat(12345.012, 2))
|
||||||
|
t.Log(numberutils.FormatFloat(123456.012, 2))
|
||||||
|
t.Log(numberutils.FormatFloat(1234567.012, 2))
|
||||||
|
t.Log(numberutils.FormatFloat(12345678.012, 2))
|
||||||
|
t.Log(numberutils.FormatFloat(123456789.012, 2))
|
||||||
|
t.Log(numberutils.FormatFloat(1234567890.012, 2))
|
||||||
|
t.Log(numberutils.FormatFloat(123, 2))
|
||||||
|
t.Log(numberutils.FormatFloat(1234, 2))
|
||||||
|
t.Log(numberutils.FormatFloat(1234.00001, 4))
|
||||||
|
t.Log(numberutils.FormatFloat(1234.56700, 4))
|
||||||
|
t.Log(numberutils.FormatFloat(-1234.56700, 2))
|
||||||
|
t.Log(numberutils.FormatFloat(-221745.12, 2))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTrimZeroSuffix(t *testing.T) {
|
||||||
|
for _, s := range []string{
|
||||||
|
"1",
|
||||||
|
"1.0000",
|
||||||
|
"1.10",
|
||||||
|
"100",
|
||||||
|
"100.0000",
|
||||||
|
"100.0",
|
||||||
|
"100.0123",
|
||||||
|
"100.0010",
|
||||||
|
"100.000KB",
|
||||||
|
"100.010MB",
|
||||||
|
} {
|
||||||
|
t.Log(s, "=>", numberutils.TrimZeroSuffix(s))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -111,7 +111,8 @@ func (this *ServiceManager) installSystemdService(systemd, exePath string, args
|
|||||||
shortName := teaconst.SystemdServiceName
|
shortName := teaconst.SystemdServiceName
|
||||||
longName := "GoEdge Admin" // TODO 将来可以修改
|
longName := "GoEdge Admin" // TODO 将来可以修改
|
||||||
|
|
||||||
desc := `# Provides: ` + shortName + `
|
desc := `### BEGIN INIT INFO
|
||||||
|
# Provides: ` + shortName + `
|
||||||
# Required-Start: $all
|
# Required-Start: $all
|
||||||
# Required-Stop:
|
# Required-Stop:
|
||||||
# Default-Start: 2 3 4 5
|
# Default-Start: 2 3 4 5
|
||||||
|
|||||||
292
internal/utils/upgrade_manager.go
Normal file
292
internal/utils/upgrade_manager.go
Normal file
@@ -0,0 +1,292 @@
|
|||||||
|
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||||
|
|
||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"crypto/tls"
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
teaconst "github.com/TeaOSLab/EdgeAdmin/internal/const"
|
||||||
|
"github.com/iwind/TeaGo/Tea"
|
||||||
|
"github.com/iwind/TeaGo/maps"
|
||||||
|
"github.com/iwind/TeaGo/types"
|
||||||
|
stringutil "github.com/iwind/TeaGo/utils/string"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"path/filepath"
|
||||||
|
"runtime"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type UpgradeFileWriter struct {
|
||||||
|
rawWriter io.Writer
|
||||||
|
written int64
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewUpgradeFileWriter(rawWriter io.Writer) *UpgradeFileWriter {
|
||||||
|
return &UpgradeFileWriter{rawWriter: rawWriter}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *UpgradeFileWriter) Write(p []byte) (n int, err error) {
|
||||||
|
n, err = this.rawWriter.Write(p)
|
||||||
|
this.written += int64(n)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *UpgradeFileWriter) TotalWritten() int64 {
|
||||||
|
return this.written
|
||||||
|
}
|
||||||
|
|
||||||
|
type UpgradeManager struct {
|
||||||
|
client *http.Client
|
||||||
|
|
||||||
|
component string
|
||||||
|
|
||||||
|
newVersion string
|
||||||
|
contentLength int64
|
||||||
|
isDownloading bool
|
||||||
|
writer *UpgradeFileWriter
|
||||||
|
body io.ReadCloser
|
||||||
|
isCancelled bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewUpgradeManager(component string) *UpgradeManager {
|
||||||
|
return &UpgradeManager{
|
||||||
|
component: component,
|
||||||
|
client: &http.Client{
|
||||||
|
Transport: &http.Transport{
|
||||||
|
TLSClientConfig: &tls.Config{
|
||||||
|
InsecureSkipVerify: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
CheckRedirect: nil,
|
||||||
|
Jar: nil,
|
||||||
|
Timeout: 30 * time.Minute,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *UpgradeManager) Start() error {
|
||||||
|
if this.isDownloading {
|
||||||
|
return errors.New("another process is running")
|
||||||
|
}
|
||||||
|
|
||||||
|
this.isDownloading = true
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
this.client.CloseIdleConnections()
|
||||||
|
this.isDownloading = false
|
||||||
|
}()
|
||||||
|
|
||||||
|
// 检查unzip
|
||||||
|
unzipExe, _ := exec.LookPath("unzip")
|
||||||
|
if len(unzipExe) == 0 {
|
||||||
|
// TODO install unzip automatically or pack with a static 'unzip' file
|
||||||
|
return errors.New("can not find 'unzip' command")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查cp
|
||||||
|
cpExe, _ := exec.LookPath("cp")
|
||||||
|
if len(cpExe) == 0 {
|
||||||
|
return errors.New("can not find 'cp' command")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查新版本
|
||||||
|
var downloadURL = ""
|
||||||
|
{
|
||||||
|
var url = teaconst.UpdatesURL
|
||||||
|
var osName = runtime.GOOS
|
||||||
|
if Tea.IsTesting() && osName == "darwin" {
|
||||||
|
osName = "linux"
|
||||||
|
}
|
||||||
|
url = strings.ReplaceAll(url, "${os}", osName)
|
||||||
|
url = strings.ReplaceAll(url, "${arch}", runtime.GOARCH)
|
||||||
|
req, err := http.NewRequest(http.MethodGet, url, nil)
|
||||||
|
if err != nil {
|
||||||
|
return errors.New("create url request failed: " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := this.client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return errors.New("read latest version failed: " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
_ = resp.Body.Close()
|
||||||
|
}()
|
||||||
|
|
||||||
|
if resp.StatusCode != http.StatusOK {
|
||||||
|
return errors.New("read latest version failed: invalid response code '" + types.String(resp.StatusCode) + "'")
|
||||||
|
}
|
||||||
|
|
||||||
|
data, err := io.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return errors.New("read latest version failed: " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
var m = maps.Map{}
|
||||||
|
err = json.Unmarshal(data, &m)
|
||||||
|
if err != nil {
|
||||||
|
return errors.New("invalid response data: " + err.Error() + ", origin data: " + string(data))
|
||||||
|
}
|
||||||
|
|
||||||
|
var code = m.GetInt("code")
|
||||||
|
if code != 200 {
|
||||||
|
return errors.New(m.GetString("message"))
|
||||||
|
}
|
||||||
|
|
||||||
|
var dataMap = m.GetMap("data")
|
||||||
|
var downloadHost = dataMap.GetString("host")
|
||||||
|
var versions = dataMap.GetSlice("versions")
|
||||||
|
var downloadPath = ""
|
||||||
|
for _, component := range versions {
|
||||||
|
var componentMap = maps.NewMap(component)
|
||||||
|
if componentMap.Has("version") {
|
||||||
|
if componentMap.GetString("code") == this.component {
|
||||||
|
var version = componentMap.GetString("version")
|
||||||
|
if stringutil.VersionCompare(version, teaconst.Version) > 0 {
|
||||||
|
this.newVersion = version
|
||||||
|
downloadPath = componentMap.GetString("url")
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(downloadPath) == 0 {
|
||||||
|
return errors.New("no latest version to download")
|
||||||
|
}
|
||||||
|
|
||||||
|
downloadURL = downloadHost + downloadPath
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
req, err := http.NewRequest(http.MethodGet, downloadURL, nil)
|
||||||
|
if err != nil {
|
||||||
|
return errors.New("create download request failed: " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := this.client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return errors.New("download failed: " + downloadURL + ": " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
_ = resp.Body.Close()
|
||||||
|
}()
|
||||||
|
|
||||||
|
if resp.StatusCode != http.StatusOK {
|
||||||
|
return errors.New("download failed: " + downloadURL + ": invalid response code '" + types.String(resp.StatusCode) + "'")
|
||||||
|
}
|
||||||
|
|
||||||
|
this.contentLength = resp.ContentLength
|
||||||
|
this.body = resp.Body
|
||||||
|
|
||||||
|
// download to tmp
|
||||||
|
var tmpDir = os.TempDir()
|
||||||
|
var filename = filepath.Base(downloadURL)
|
||||||
|
|
||||||
|
var destFile = tmpDir + "/" + filename
|
||||||
|
_ = os.Remove(destFile)
|
||||||
|
|
||||||
|
fp, err := os.Create(destFile)
|
||||||
|
if err != nil {
|
||||||
|
return errors.New("create file failed: " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
// 删除安装文件
|
||||||
|
_ = os.Remove(destFile)
|
||||||
|
}()
|
||||||
|
|
||||||
|
this.writer = NewUpgradeFileWriter(fp)
|
||||||
|
|
||||||
|
_, err = io.Copy(this.writer, resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
_ = fp.Close()
|
||||||
|
if this.isCancelled {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return errors.New("download failed: " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
_ = fp.Close()
|
||||||
|
|
||||||
|
// unzip
|
||||||
|
var unzipDir = tmpDir + "/edge-" + this.component + "-tmp"
|
||||||
|
stat, err := os.Stat(unzipDir)
|
||||||
|
if err == nil && stat.IsDir() {
|
||||||
|
err = os.RemoveAll(unzipDir)
|
||||||
|
if err != nil {
|
||||||
|
return errors.New("remove old dir '" + unzipDir + "' failed: " + err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var unzipCmd = exec.Command(unzipExe, "-q", "-o", destFile, "-d", unzipDir)
|
||||||
|
var unzipStderr = &bytes.Buffer{}
|
||||||
|
unzipCmd.Stderr = unzipStderr
|
||||||
|
err = unzipCmd.Run()
|
||||||
|
if err != nil {
|
||||||
|
return errors.New("unzip installation file failed: " + err.Error() + ": " + unzipStderr.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
installationFiles, err := filepath.Glob(unzipDir + "/edge-" + this.component + "/*")
|
||||||
|
if err != nil {
|
||||||
|
return errors.New("lookup installation files failed: " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
// cp to target dir
|
||||||
|
currentExe, err := os.Executable()
|
||||||
|
if err != nil {
|
||||||
|
return errors.New("reveal current executable file path failed: " + err.Error())
|
||||||
|
}
|
||||||
|
var targetDir = filepath.Dir(filepath.Dir(currentExe))
|
||||||
|
if !Tea.IsTesting() {
|
||||||
|
for _, installationFile := range installationFiles {
|
||||||
|
var cpCmd = exec.Command(cpExe, "-R", "-f", installationFile, targetDir)
|
||||||
|
var cpStderr = &bytes.Buffer{}
|
||||||
|
cpCmd.Stderr = cpStderr
|
||||||
|
err = cpCmd.Run()
|
||||||
|
if err != nil {
|
||||||
|
return errors.New("overwrite installation files failed: '" + cpCmd.String() + "': " + cpStderr.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove tmp
|
||||||
|
_ = os.RemoveAll(unzipDir)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *UpgradeManager) IsDownloading() bool {
|
||||||
|
return this.isDownloading
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *UpgradeManager) Progress() float32 {
|
||||||
|
if this.contentLength <= 0 {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
if this.writer == nil {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
return float32(this.writer.TotalWritten()) / float32(this.contentLength)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *UpgradeManager) NewVersion() string {
|
||||||
|
return this.newVersion
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *UpgradeManager) Cancel() error {
|
||||||
|
this.isCancelled = true
|
||||||
|
this.isDownloading = false
|
||||||
|
|
||||||
|
if this.body != nil {
|
||||||
|
_ = this.body.Close()
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
35
internal/utils/upgrade_manager_test.go
Normal file
35
internal/utils/upgrade_manager_test.go
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||||
|
|
||||||
|
package utils_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/utils"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestNewUpgradeManager(t *testing.T) {
|
||||||
|
var manager = utils.NewUpgradeManager("admin")
|
||||||
|
|
||||||
|
var ticker = time.NewTicker(2 * time.Second)
|
||||||
|
go func() {
|
||||||
|
for range ticker.C {
|
||||||
|
if manager.IsDownloading() {
|
||||||
|
t.Logf("%.2f%%", manager.Progress()*100)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
/**go func() {
|
||||||
|
time.Sleep(5 * time.Second)
|
||||||
|
if manager.IsDownloading() {
|
||||||
|
t.Log("cancel downloading")
|
||||||
|
_ = manager.Cancel()
|
||||||
|
}
|
||||||
|
}()**/
|
||||||
|
|
||||||
|
err := manager.Start()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,6 +11,7 @@ import (
|
|||||||
"github.com/iwind/TeaGo/actions"
|
"github.com/iwind/TeaGo/actions"
|
||||||
"github.com/iwind/TeaGo/logs"
|
"github.com/iwind/TeaGo/logs"
|
||||||
"github.com/iwind/TeaGo/maps"
|
"github.com/iwind/TeaGo/maps"
|
||||||
|
"github.com/iwind/gosock/pkg/gosock"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
@@ -18,6 +19,7 @@ import (
|
|||||||
"reflect"
|
"reflect"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Fail 提示服务器错误信息
|
// Fail 提示服务器错误信息
|
||||||
@@ -45,6 +47,25 @@ func FailPage(action actions.ActionWrapper, err error) {
|
|||||||
|
|
||||||
var isRPCConnError bool
|
var isRPCConnError bool
|
||||||
err, isRPCConnError = rpcerrors.HumanError(err, apiEndpoints, Tea.ConfigFile("api.yaml"))
|
err, isRPCConnError = rpcerrors.HumanError(err, apiEndpoints, Tea.ConfigFile("api.yaml"))
|
||||||
|
var apiNodeIsStarting = false
|
||||||
|
var apiNodeProgress = ""
|
||||||
|
if isRPCConnError {
|
||||||
|
// API节点是否正在启动
|
||||||
|
var sock = gosock.NewTmpSock("edge-api")
|
||||||
|
reply, err := sock.SendTimeout(&gosock.Command{
|
||||||
|
Code: "starting",
|
||||||
|
Params: nil,
|
||||||
|
}, 1*time.Second)
|
||||||
|
if err == nil && reply != nil {
|
||||||
|
var params = maps.NewMap(reply.Params)
|
||||||
|
if params.GetBool("isStarting") {
|
||||||
|
apiNodeIsStarting = true
|
||||||
|
|
||||||
|
var progressMap = params.GetMap("progress")
|
||||||
|
apiNodeProgress = progressMap.GetString("description")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
action.Object().ResponseWriter.WriteHeader(http.StatusInternalServerError)
|
action.Object().ResponseWriter.WriteHeader(http.StatusInternalServerError)
|
||||||
if len(action.Object().Request.Header.Get("X-Requested-With")) > 0 {
|
if len(action.Object().Request.Header.Get("X-Requested-With")) > 0 {
|
||||||
@@ -90,14 +111,25 @@ func FailPage(action actions.ActionWrapper, err error) {
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div style="background: #eee; border: 1px #ccc solid; padding: 10px; font-size: 12px; line-height: 1.8">
|
<div style="background: #eee; border: 1px #ccc solid; padding: 10px; font-size: 12px; line-height: 1.8">
|
||||||
` + teaconst.ErrServer + `
|
`
|
||||||
|
if apiNodeIsStarting { // API节点正在启动
|
||||||
|
html += "<div class=\"red\">API节点正在启动,请耐心等待完成"
|
||||||
|
|
||||||
|
if len(apiNodeProgress) > 0 {
|
||||||
|
html += ":" + apiNodeProgress
|
||||||
|
}
|
||||||
|
|
||||||
|
html += "</div>"
|
||||||
|
} else {
|
||||||
|
html += teaconst.ErrServer + `
|
||||||
<div>可以通过查看 <strong><em>$安装目录/logs/run.log</em></strong> 日志文件查看具体的错误提示。</div>
|
<div>可以通过查看 <strong><em>$安装目录/logs/run.log</em></strong> 日志文件查看具体的错误提示。</div>
|
||||||
<hr/>
|
<hr/>
|
||||||
<div class="red">Error: ` + err.Error() + `</div>`
|
<div class="red">Error: ` + err.Error() + `</div>`
|
||||||
|
|
||||||
if len(issuesHTML) > 0 {
|
if len(issuesHTML) > 0 {
|
||||||
html += ` <hr/>
|
html += ` <hr/>
|
||||||
<div class="red">` + issuesHTML + `</div>`
|
<div class="red">` + issuesHTML + `</div>`
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
action.Object().WriteString(html + `
|
action.Object().WriteString(html + `
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ func (this *DeleteAction) RunPost(params struct {
|
|||||||
var apiNode = nodeResp.ApiNode
|
var apiNode = nodeResp.ApiNode
|
||||||
if apiNode == nil {
|
if apiNode == nil {
|
||||||
this.Success()
|
this.Success()
|
||||||
|
return
|
||||||
}
|
}
|
||||||
if apiNode.IsOn {
|
if apiNode.IsOn {
|
||||||
countResp, err := this.RPC().APINodeRPC().CountAllEnabledAndOnAPINodes(this.AdminContext(), &pb.CountAllEnabledAndOnAPINodesRequest{})
|
countResp, err := this.RPC().APINodeRPC().CountAllEnabledAndOnAPINodes(this.AdminContext(), &pb.CountAllEnabledAndOnAPINodesRequest{})
|
||||||
|
|||||||
@@ -5,11 +5,14 @@ import (
|
|||||||
"github.com/TeaOSLab/EdgeAdmin/internal/oplogs"
|
"github.com/TeaOSLab/EdgeAdmin/internal/oplogs"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/utils"
|
"github.com/TeaOSLab/EdgeAdmin/internal/utils"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/clusterutils"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/grants/grantutils"
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/grants/grantutils"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
"github.com/iwind/TeaGo/actions"
|
"github.com/iwind/TeaGo/actions"
|
||||||
"github.com/iwind/TeaGo/maps"
|
"github.com/iwind/TeaGo/maps"
|
||||||
|
"net"
|
||||||
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
@@ -27,7 +30,7 @@ func (this *CreateNodeAction) Init() {
|
|||||||
func (this *CreateNodeAction) RunGet(params struct {
|
func (this *CreateNodeAction) RunGet(params struct {
|
||||||
ClusterId int64
|
ClusterId int64
|
||||||
}) {
|
}) {
|
||||||
leftMenuItems := []maps.Map{
|
var leftMenuItems = []maps.Map{
|
||||||
{
|
{
|
||||||
"name": "单个创建",
|
"name": "单个创建",
|
||||||
"url": "/clusters/cluster/createNode?clusterId=" + strconv.FormatInt(params.ClusterId, 10),
|
"url": "/clusters/cluster/createNode?clusterId=" + strconv.FormatInt(params.ClusterId, 10),
|
||||||
@@ -47,7 +50,7 @@ func (this *CreateNodeAction) RunGet(params struct {
|
|||||||
this.ErrorPage(err)
|
this.ErrorPage(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
dnsRouteMaps := []maps.Map{}
|
var dnsRouteMaps = []maps.Map{}
|
||||||
this.Data["dnsDomainId"] = 0
|
this.Data["dnsDomainId"] = 0
|
||||||
if clusterDNSResp.Domain != nil {
|
if clusterDNSResp.Domain != nil {
|
||||||
domainId := clusterDNSResp.Domain.Id
|
domainId := clusterDNSResp.Domain.Id
|
||||||
@@ -76,8 +79,8 @@ func (this *CreateNodeAction) RunGet(params struct {
|
|||||||
this.ErrorPage(err)
|
this.ErrorPage(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
apiNodes := apiNodesResp.ApiNodes
|
var apiNodes = apiNodesResp.ApiNodes
|
||||||
apiEndpoints := []string{}
|
var apiEndpoints = []string{}
|
||||||
for _, apiNode := range apiNodes {
|
for _, apiNode := range apiNodes {
|
||||||
if !apiNode.IsOn {
|
if !apiNode.IsOn {
|
||||||
continue
|
continue
|
||||||
@@ -86,6 +89,9 @@ func (this *CreateNodeAction) RunGet(params struct {
|
|||||||
}
|
}
|
||||||
this.Data["apiEndpoints"] = "\"" + strings.Join(apiEndpoints, "\", \"") + "\""
|
this.Data["apiEndpoints"] = "\"" + strings.Join(apiEndpoints, "\", \"") + "\""
|
||||||
|
|
||||||
|
// 安装文件下载
|
||||||
|
this.Data["installerFiles"] = clusterutils.ListInstallerFiles()
|
||||||
|
|
||||||
this.Show()
|
this.Show()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -118,7 +124,7 @@ func (this *CreateNodeAction) RunPost(params struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// IP地址
|
// IP地址
|
||||||
ipAddresses := []maps.Map{}
|
var ipAddresses = []maps.Map{}
|
||||||
if len(params.IpAddressesJSON) > 0 {
|
if len(params.IpAddressesJSON) > 0 {
|
||||||
err := json.Unmarshal(params.IpAddressesJSON, &ipAddresses)
|
err := json.Unmarshal(params.IpAddressesJSON, &ipAddresses)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -127,10 +133,29 @@ func (this *CreateNodeAction) RunPost(params struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(ipAddresses) == 0 {
|
if len(ipAddresses) == 0 {
|
||||||
this.Fail("请至少输入一个IP地址")
|
// 检查Name中是否包含IP
|
||||||
|
var ipv4Reg = regexp.MustCompile(`\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}`)
|
||||||
|
var ipMatches = ipv4Reg.FindStringSubmatch(params.Name)
|
||||||
|
if len(ipMatches) > 0 {
|
||||||
|
var nodeIP = ipMatches[0]
|
||||||
|
if net.ParseIP(nodeIP) != nil {
|
||||||
|
ipAddresses = []maps.Map{
|
||||||
|
{
|
||||||
|
"ip": nodeIP,
|
||||||
|
"canAccess": true,
|
||||||
|
"isOn": true,
|
||||||
|
"isUp": true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(ipAddresses) == 0 {
|
||||||
|
this.Fail("请至少输入一个IP地址")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dnsRouteCodes := []string{}
|
var dnsRouteCodes = []string{}
|
||||||
if len(params.DnsRoutesJSON) > 0 {
|
if len(params.DnsRoutesJSON) > 0 {
|
||||||
err := json.Unmarshal(params.DnsRoutesJSON, &dnsRouteCodes)
|
err := json.Unmarshal(params.DnsRoutesJSON, &dnsRouteCodes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -140,7 +165,7 @@ func (this *CreateNodeAction) RunPost(params struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO 检查登录授权
|
// TODO 检查登录授权
|
||||||
loginInfo := &pb.NodeLogin{
|
var loginInfo = &pb.NodeLogin{
|
||||||
Id: 0,
|
Id: 0,
|
||||||
Name: "SSH",
|
Name: "SSH",
|
||||||
Type: "ssh",
|
Type: "ssh",
|
||||||
@@ -165,7 +190,7 @@ func (this *CreateNodeAction) RunPost(params struct {
|
|||||||
this.ErrorPage(err)
|
this.ErrorPage(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
nodeId := createResp.NodeId
|
var nodeId = createResp.NodeId
|
||||||
|
|
||||||
// IP地址
|
// IP地址
|
||||||
var resultIPAddresses = []string{}
|
var resultIPAddresses = []string{}
|
||||||
|
|||||||
@@ -0,0 +1,70 @@
|
|||||||
|
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||||
|
|
||||||
|
package cluster
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
|
"github.com/iwind/TeaGo/Tea"
|
||||||
|
"github.com/iwind/TeaGo/types"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"regexp"
|
||||||
|
)
|
||||||
|
|
||||||
|
type DownloadInstallerAction struct {
|
||||||
|
actionutils.ParentAction
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *DownloadInstallerAction) Init() {
|
||||||
|
this.Nav("", "", "")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *DownloadInstallerAction) RunGet(params struct {
|
||||||
|
Name string
|
||||||
|
}) {
|
||||||
|
if len(params.Name) == 0 {
|
||||||
|
this.ResponseWriter.WriteHeader(http.StatusNotFound)
|
||||||
|
this.WriteString("file not found")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查文件名
|
||||||
|
// 以防止路径穿越等风险
|
||||||
|
if !regexp.MustCompile(`^[a-zA-Z0-9.-]+$`).MatchString(params.Name) {
|
||||||
|
this.ResponseWriter.WriteHeader(http.StatusNotFound)
|
||||||
|
this.WriteString("file not found")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var zipFile = Tea.Root + "/edge-api/deploy/" + params.Name
|
||||||
|
fp, err := os.OpenFile(zipFile, os.O_RDWR, 0444)
|
||||||
|
if err != nil {
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
this.ResponseWriter.WriteHeader(http.StatusNotFound)
|
||||||
|
this.WriteString("file not found")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.ResponseWriter.WriteHeader(http.StatusInternalServerError)
|
||||||
|
this.WriteString("file can not be opened")
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
_ = fp.Close()
|
||||||
|
}()
|
||||||
|
|
||||||
|
stat, err := fp.Stat()
|
||||||
|
if err != nil {
|
||||||
|
this.ResponseWriter.WriteHeader(http.StatusInternalServerError)
|
||||||
|
this.WriteString("file can not be opened")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.AddHeader("Content-Disposition", "attachment; filename=\""+params.Name+"\";")
|
||||||
|
this.AddHeader("Content-Type", "application/zip")
|
||||||
|
this.AddHeader("Content-Length", types.String(stat.Size()))
|
||||||
|
_, _ = io.Copy(this.ResponseWriter, fp)
|
||||||
|
}
|
||||||
@@ -48,7 +48,7 @@ func (this *CreatePopupAction) RunPost(params struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 创建日志
|
// 创建日志
|
||||||
defer this.CreateLog(oplogs.LevelInfo, "创建节点分组", createResp.NodeGroupId)
|
defer this.CreateLog(oplogs.LevelInfo, "创建节点分组 %d", createResp.NodeGroupId)
|
||||||
|
|
||||||
this.Success()
|
this.Success()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ func init() {
|
|||||||
GetPost("/updateNodeSSH", new(UpdateNodeSSHAction)).
|
GetPost("/updateNodeSSH", new(UpdateNodeSSHAction)).
|
||||||
GetPost("/installManual", new(InstallManualAction)).
|
GetPost("/installManual", new(InstallManualAction)).
|
||||||
Post("/suggestLoginPorts", new(SuggestLoginPortsAction)).
|
Post("/suggestLoginPorts", new(SuggestLoginPortsAction)).
|
||||||
|
Get("/downloadInstaller", new(DownloadInstallerAction)).
|
||||||
|
|
||||||
// 节点相关
|
// 节点相关
|
||||||
Prefix("/clusters/cluster/node").
|
Prefix("/clusters/cluster/node").
|
||||||
|
|||||||
@@ -318,6 +318,7 @@ func (this *DetailAction) RunGet(params struct {
|
|||||||
"level": node.Level,
|
"level": node.Level,
|
||||||
"levelInfo": nodeconfigs.FindNodeLevel(int(node.Level)),
|
"levelInfo": nodeconfigs.FindNodeLevel(int(node.Level)),
|
||||||
"lnAddrs": lnAddrs,
|
"lnAddrs": lnAddrs,
|
||||||
|
"enableIPLists": node.EnableIPLists,
|
||||||
|
|
||||||
"status": maps.Map{
|
"status": maps.Map{
|
||||||
"isActive": status.IsActive,
|
"isActive": status.IsActive,
|
||||||
|
|||||||
@@ -1,12 +1,16 @@
|
|||||||
package node
|
package node
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/oplogs"
|
"github.com/TeaOSLab/EdgeAdmin/internal/oplogs"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/cluster/node/nodeutils"
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/cluster/node/nodeutils"
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/clusterutils"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
"github.com/iwind/TeaGo/actions"
|
"github.com/iwind/TeaGo/actions"
|
||||||
"github.com/iwind/TeaGo/maps"
|
"github.com/iwind/TeaGo/maps"
|
||||||
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -32,6 +36,20 @@ func (this *InstallAction) RunGet(params struct {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 最近运行目录
|
||||||
|
var exeRoot = ""
|
||||||
|
if len(node.StatusJSON) > 0 {
|
||||||
|
var nodeStatus = &nodeconfigs.NodeStatus{}
|
||||||
|
err = json.Unmarshal(node.StatusJSON, nodeStatus)
|
||||||
|
if err == nil {
|
||||||
|
var exePath = nodeStatus.ExePath
|
||||||
|
if len(exePath) > 0 {
|
||||||
|
exeRoot = filepath.Dir(filepath.Dir(exePath))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.Data["exeRoot"] = exeRoot
|
||||||
|
|
||||||
// 安装信息
|
// 安装信息
|
||||||
if node.InstallStatus != nil {
|
if node.InstallStatus != nil {
|
||||||
this.Data["installStatus"] = maps.Map{
|
this.Data["installStatus"] = maps.Map{
|
||||||
@@ -70,7 +88,7 @@ func (this *InstallAction) RunGet(params struct {
|
|||||||
this.ErrorPage(err)
|
this.ErrorPage(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
apiNodes := apiNodesResp.ApiNodes
|
var apiNodes = apiNodesResp.ApiNodes
|
||||||
apiEndpoints := []string{}
|
apiEndpoints := []string{}
|
||||||
for _, apiNode := range apiNodes {
|
for _, apiNode := range apiNodes {
|
||||||
if !apiNode.IsOn {
|
if !apiNode.IsOn {
|
||||||
@@ -87,6 +105,10 @@ func (this *InstallAction) RunGet(params struct {
|
|||||||
nodeMap["secret"] = node.Secret
|
nodeMap["secret"] = node.Secret
|
||||||
nodeMap["cluster"] = clusterMap
|
nodeMap["cluster"] = clusterMap
|
||||||
|
|
||||||
|
// 安装文件
|
||||||
|
var installerFiles = clusterutils.ListInstallerFiles()
|
||||||
|
this.Data["installerFiles"] = installerFiles
|
||||||
|
|
||||||
this.Show()
|
this.Show()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -100,14 +100,15 @@ func (this *UpdateAction) RunGet(params struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var nodeMap = maps.Map{
|
var nodeMap = maps.Map{
|
||||||
"id": node.Id,
|
"id": node.Id,
|
||||||
"name": node.Name,
|
"name": node.Name,
|
||||||
"ipAddresses": ipAddressMaps,
|
"ipAddresses": ipAddressMaps,
|
||||||
"cluster": clusterMap,
|
"cluster": clusterMap,
|
||||||
"isOn": node.IsOn,
|
"isOn": node.IsOn,
|
||||||
"group": groupMap,
|
"group": groupMap,
|
||||||
"region": regionMap,
|
"region": regionMap,
|
||||||
"level": node.Level,
|
"level": node.Level,
|
||||||
|
"enableIPLists": node.EnableIPLists,
|
||||||
}
|
}
|
||||||
|
|
||||||
if node.LnAddrs == nil {
|
if node.LnAddrs == nil {
|
||||||
@@ -157,6 +158,7 @@ func (this *UpdateAction) RunPost(params struct {
|
|||||||
IsOn bool
|
IsOn bool
|
||||||
Level int32
|
Level int32
|
||||||
LnAddrs []string
|
LnAddrs []string
|
||||||
|
EnableIPLists bool
|
||||||
|
|
||||||
Must *actions.Must
|
Must *actions.Must
|
||||||
}) {
|
}) {
|
||||||
@@ -234,6 +236,7 @@ func (this *UpdateAction) RunPost(params struct {
|
|||||||
IsOn: params.IsOn,
|
IsOn: params.IsOn,
|
||||||
Level: params.Level,
|
Level: params.Level,
|
||||||
LnAddrs: lnAddrs,
|
LnAddrs: lnAddrs,
|
||||||
|
EnableIPLists: params.EnableIPLists,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
this.ErrorPage(err)
|
this.ErrorPage(err)
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/dns/domains/domainutils"
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/dns/domains/domainutils"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
"github.com/iwind/TeaGo/actions"
|
"github.com/iwind/TeaGo/actions"
|
||||||
|
"github.com/iwind/TeaGo/maps"
|
||||||
)
|
)
|
||||||
|
|
||||||
type IndexAction struct {
|
type IndexAction struct {
|
||||||
@@ -41,10 +42,23 @@ func (this *IndexAction) RunGet(params struct {
|
|||||||
this.Data["dnsName"] = dnsInfoResp.Name
|
this.Data["dnsName"] = dnsInfoResp.Name
|
||||||
this.Data["nodesAutoSync"] = dnsInfoResp.NodesAutoSync
|
this.Data["nodesAutoSync"] = dnsInfoResp.NodesAutoSync
|
||||||
this.Data["serversAutoSync"] = dnsInfoResp.ServersAutoSync
|
this.Data["serversAutoSync"] = dnsInfoResp.ServersAutoSync
|
||||||
|
|
||||||
|
var domainProviderMap = maps.Map{
|
||||||
|
"id": 0,
|
||||||
|
"name": "",
|
||||||
|
}
|
||||||
if dnsInfoResp.Domain != nil {
|
if dnsInfoResp.Domain != nil {
|
||||||
this.Data["domainId"] = dnsInfoResp.Domain.Id
|
this.Data["domainId"] = dnsInfoResp.Domain.Id
|
||||||
this.Data["domainName"] = dnsInfoResp.Domain.Name
|
this.Data["domainName"] = dnsInfoResp.Domain.Name
|
||||||
|
|
||||||
|
if dnsInfoResp.Provider != nil {
|
||||||
|
domainProviderMap = maps.Map{
|
||||||
|
"id": dnsInfoResp.Provider.Id,
|
||||||
|
"name": dnsInfoResp.Provider.Name,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
this.Data["domainProvider"] = domainProviderMap
|
||||||
|
|
||||||
if len(dnsInfoResp.CnameRecords) == 0 {
|
if len(dnsInfoResp.CnameRecords) == 0 {
|
||||||
this.Data["cnameRecords"] = []string{}
|
this.Data["cnameRecords"] = []string{}
|
||||||
|
|||||||
@@ -0,0 +1,160 @@
|
|||||||
|
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||||
|
|
||||||
|
package globalServerConfig
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||||
|
"github.com/iwind/TeaGo/actions"
|
||||||
|
"github.com/iwind/TeaGo/maps"
|
||||||
|
)
|
||||||
|
|
||||||
|
type IndexAction struct {
|
||||||
|
actionutils.ParentAction
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *IndexAction) Init() {
|
||||||
|
this.Nav("", "setting", "")
|
||||||
|
this.SecondMenu("globalServerConfig")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *IndexAction) RunGet(params struct {
|
||||||
|
ClusterId int64
|
||||||
|
}) {
|
||||||
|
configResp, err := this.RPC().NodeClusterRPC().FindNodeClusterGlobalServerConfig(this.AdminContext(), &pb.FindNodeClusterGlobalServerConfigRequest{NodeClusterId: params.ClusterId})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var configJSON = configResp.GlobalServerConfigJSON
|
||||||
|
var config = serverconfigs.DefaultGlobalServerConfig()
|
||||||
|
if len(configJSON) > 0 {
|
||||||
|
err = json.Unmarshal(configJSON, config)
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.Data["config"] = config
|
||||||
|
|
||||||
|
var httpAllDomainMismatchActionContentHTML = ""
|
||||||
|
if config.HTTPAll.DomainMismatchAction != nil {
|
||||||
|
httpAllDomainMismatchActionContentHTML = config.HTTPAll.DomainMismatchAction.Options.GetString("contentHTML")
|
||||||
|
} else {
|
||||||
|
httpAllDomainMismatchActionContentHTML = `<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8"/>
|
||||||
|
<title>404 not found</title>
|
||||||
|
<style>
|
||||||
|
* { font-family: Roboto, system-ui, sans-serif; }
|
||||||
|
h3, p { text-align: center; }
|
||||||
|
p { color: grey; }
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h3>Error: 404 Page Not Found</h3>
|
||||||
|
<h3>找不到您要访问的页面。</h3>
|
||||||
|
|
||||||
|
<p>原因:找不到当前访问域名对应的网站,请联系网站管理员。</p>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>`
|
||||||
|
}
|
||||||
|
this.Data["httpAllDomainMismatchActionContentHTML"] = httpAllDomainMismatchActionContentHTML
|
||||||
|
|
||||||
|
this.Show()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *IndexAction) RunPost(params struct {
|
||||||
|
ClusterId int64
|
||||||
|
|
||||||
|
HttpAllMatchDomainStrictly bool
|
||||||
|
HttpAllDomainMismatchActionContentHTML string
|
||||||
|
HttpAllAllowMismatchDomainsJSON []byte
|
||||||
|
HttpAllAllowNodeIP bool
|
||||||
|
HttpAllDefaultDomain string
|
||||||
|
|
||||||
|
HttpAccessLogEnableRequestHeaders bool
|
||||||
|
HttpAccessLogEnableResponseHeaders bool
|
||||||
|
HttpAccessLogCommonRequestHeadersOnly bool
|
||||||
|
HttpAccessLogEnableCookies bool
|
||||||
|
|
||||||
|
LogRecordServerError bool
|
||||||
|
|
||||||
|
Must *actions.Must
|
||||||
|
CSRF *actionutils.CSRF
|
||||||
|
}) {
|
||||||
|
defer this.CreateLogInfo("修改集群 %d 全局配置", params.ClusterId)
|
||||||
|
|
||||||
|
configResp, err := this.RPC().NodeClusterRPC().FindNodeClusterGlobalServerConfig(this.AdminContext(), &pb.FindNodeClusterGlobalServerConfigRequest{NodeClusterId: params.ClusterId})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var configJSON = configResp.GlobalServerConfigJSON
|
||||||
|
var config = serverconfigs.DefaultGlobalServerConfig()
|
||||||
|
if len(configJSON) > 0 {
|
||||||
|
err = json.Unmarshal(configJSON, config)
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
config.HTTPAll.MatchDomainStrictly = params.HttpAllMatchDomainStrictly
|
||||||
|
config.HTTPAll.DomainMismatchAction = &serverconfigs.DomainMismatchAction{
|
||||||
|
Code: serverconfigs.DomainMismatchActionPage,
|
||||||
|
Options: maps.Map{
|
||||||
|
"statusCode": 404,
|
||||||
|
"contentHTML": params.HttpAllDomainMismatchActionContentHTML,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
var allowMismatchDomains = []string{}
|
||||||
|
if len(params.HttpAllAllowMismatchDomainsJSON) > 0 {
|
||||||
|
err = json.Unmarshal(params.HttpAllAllowMismatchDomainsJSON, &allowMismatchDomains)
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
config.HTTPAll.AllowMismatchDomains = allowMismatchDomains
|
||||||
|
config.HTTPAll.AllowNodeIP = params.HttpAllAllowNodeIP
|
||||||
|
config.HTTPAll.DefaultDomain = params.HttpAllDefaultDomain
|
||||||
|
|
||||||
|
config.HTTPAccessLog.EnableRequestHeaders = params.HttpAccessLogEnableRequestHeaders
|
||||||
|
config.HTTPAccessLog.EnableResponseHeaders = params.HttpAccessLogEnableResponseHeaders
|
||||||
|
config.HTTPAccessLog.CommonRequestHeadersOnly = params.HttpAccessLogCommonRequestHeadersOnly
|
||||||
|
config.HTTPAccessLog.EnableCookies = params.HttpAccessLogEnableCookies
|
||||||
|
|
||||||
|
config.Log.RecordServerError = params.LogRecordServerError
|
||||||
|
|
||||||
|
err = config.Init()
|
||||||
|
if err != nil {
|
||||||
|
this.Fail("配置校验失败:" + err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
configJSON, err = json.Marshal(config)
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = this.RPC().NodeClusterRPC().UpdateNodeClusterGlobalServerConfig(this.AdminContext(), &pb.UpdateNodeClusterGlobalServerConfigRequest{
|
||||||
|
NodeClusterId: params.ClusterId,
|
||||||
|
GlobalServerConfigJSON: configJSON,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Success()
|
||||||
|
}
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||||
|
|
||||||
|
package health
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
|
"net"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type CheckDomainAction struct {
|
||||||
|
actionutils.ParentAction
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *CheckDomainAction) RunPost(params struct {
|
||||||
|
Host string
|
||||||
|
ClusterId int64
|
||||||
|
}) {
|
||||||
|
this.Data["isOk"] = true // 默认为TRUE
|
||||||
|
|
||||||
|
var host = params.Host
|
||||||
|
if len(host) > 0 &&
|
||||||
|
!strings.Contains(host, "{") /** 包含变量 **/ {
|
||||||
|
h, _, err := net.SplitHostPort(host)
|
||||||
|
if err == nil && len(h) > 0 {
|
||||||
|
host = h
|
||||||
|
}
|
||||||
|
|
||||||
|
// 是否为IP
|
||||||
|
if net.ParseIP(host) != nil {
|
||||||
|
this.Success()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
host = strings.ToLower(host)
|
||||||
|
resp, err := this.RPC().ServerRPC().CheckServerNameDuplicationInNodeCluster(this.AdminContext(), &pb.CheckServerNameDuplicationInNodeClusterRequest{
|
||||||
|
NodeClusterId: params.ClusterId,
|
||||||
|
ServerNames: []string{host},
|
||||||
|
SupportWildcard: true,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if len(resp.DuplicatedServerNames) == 0 {
|
||||||
|
this.Data["isOk"] = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Success()
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
package settings
|
package settings
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/oplogs"
|
"github.com/TeaOSLab/EdgeAdmin/internal/oplogs"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/grants/grantutils"
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/grants/grantutils"
|
||||||
@@ -44,7 +45,7 @@ func (this *IndexAction) RunGet(params struct {
|
|||||||
this.ErrorPage(err)
|
this.ErrorPage(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
grant := grantResp.NodeGrant
|
var grant = grantResp.NodeGrant
|
||||||
if grant != nil {
|
if grant != nil {
|
||||||
grantMap = maps.Map{
|
grantMap = maps.Map{
|
||||||
"id": grant.Id,
|
"id": grant.Id,
|
||||||
@@ -65,13 +66,40 @@ func (this *IndexAction) RunGet(params struct {
|
|||||||
}
|
}
|
||||||
this.Data["timeZoneLocation"] = nodeconfigs.FindTimeZoneLocation(cluster.TimeZone)
|
this.Data["timeZoneLocation"] = nodeconfigs.FindTimeZoneLocation(cluster.TimeZone)
|
||||||
|
|
||||||
|
// 时钟
|
||||||
|
var clockConfig = nodeconfigs.DefaultClockConfig()
|
||||||
|
if len(cluster.ClockJSON) > 0 {
|
||||||
|
err = json.Unmarshal(cluster.ClockJSON, clockConfig)
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if clockConfig == nil {
|
||||||
|
clockConfig = nodeconfigs.DefaultClockConfig()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SSH参数
|
||||||
|
var sshParams = nodeconfigs.DefaultSSHParams()
|
||||||
|
if len(cluster.SshParamsJSON) > 0 {
|
||||||
|
err = json.Unmarshal(cluster.SshParamsJSON, sshParams)
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this.Data["cluster"] = maps.Map{
|
this.Data["cluster"] = maps.Map{
|
||||||
"id": cluster.Id,
|
"id": cluster.Id,
|
||||||
"name": cluster.Name,
|
"name": cluster.Name,
|
||||||
"installDir": cluster.InstallDir,
|
"installDir": cluster.InstallDir,
|
||||||
"timeZone": cluster.TimeZone,
|
"timeZone": cluster.TimeZone,
|
||||||
"nodeMaxThreads": cluster.NodeMaxThreads,
|
"nodeMaxThreads": cluster.NodeMaxThreads,
|
||||||
"autoOpenPorts": cluster.AutoOpenPorts,
|
"autoOpenPorts": cluster.AutoOpenPorts,
|
||||||
|
"clock": clockConfig,
|
||||||
|
"autoRemoteStart": cluster.AutoRemoteStart,
|
||||||
|
"autoInstallNftables": cluster.AutoInstallNftables,
|
||||||
|
"sshParams": sshParams,
|
||||||
}
|
}
|
||||||
|
|
||||||
// 默认值
|
// 默认值
|
||||||
@@ -84,13 +112,18 @@ func (this *IndexAction) RunGet(params struct {
|
|||||||
|
|
||||||
// RunPost 保存设置
|
// RunPost 保存设置
|
||||||
func (this *IndexAction) RunPost(params struct {
|
func (this *IndexAction) RunPost(params struct {
|
||||||
ClusterId int64
|
ClusterId int64
|
||||||
Name string
|
Name string
|
||||||
GrantId int64
|
GrantId int64
|
||||||
InstallDir string
|
SshParamsPort int
|
||||||
TimeZone string
|
InstallDir string
|
||||||
NodeMaxThreads int32
|
TimeZone string
|
||||||
AutoOpenPorts bool
|
NodeMaxThreads int32
|
||||||
|
AutoOpenPorts bool
|
||||||
|
ClockAutoSync bool
|
||||||
|
ClockServer string
|
||||||
|
AutoRemoteStart bool
|
||||||
|
AutoInstallNftables bool
|
||||||
|
|
||||||
Must *actions.Must
|
Must *actions.Must
|
||||||
}) {
|
}) {
|
||||||
@@ -108,14 +141,43 @@ func (this *IndexAction) RunPost(params struct {
|
|||||||
Lte(int64(nodeconfigs.DefaultMaxThreadsMax), "单节点最大线程数最大值不能大于"+types.String(nodeconfigs.DefaultMaxThreadsMax))
|
Lte(int64(nodeconfigs.DefaultMaxThreadsMax), "单节点最大线程数最大值不能大于"+types.String(nodeconfigs.DefaultMaxThreadsMax))
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := this.RPC().NodeClusterRPC().UpdateNodeCluster(this.AdminContext(), &pb.UpdateNodeClusterRequest{
|
// ssh
|
||||||
NodeClusterId: params.ClusterId,
|
var sshParams = nodeconfigs.DefaultSSHParams()
|
||||||
Name: params.Name,
|
sshParams.Port = params.SshParamsPort
|
||||||
NodeGrantId: params.GrantId,
|
sshParamsJSON, err := json.Marshal(sshParams)
|
||||||
InstallDir: params.InstallDir,
|
if err != nil {
|
||||||
TimeZone: params.TimeZone,
|
this.ErrorPage(err)
|
||||||
NodeMaxThreads: params.NodeMaxThreads,
|
return
|
||||||
AutoOpenPorts: params.AutoOpenPorts,
|
}
|
||||||
|
|
||||||
|
// clock
|
||||||
|
var clockConfig = nodeconfigs.DefaultClockConfig()
|
||||||
|
clockConfig.AutoSync = params.ClockAutoSync
|
||||||
|
clockConfig.Server = params.ClockServer
|
||||||
|
clockConfigJSON, err := json.Marshal(clockConfig)
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = clockConfig.Init()
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = this.RPC().NodeClusterRPC().UpdateNodeCluster(this.AdminContext(), &pb.UpdateNodeClusterRequest{
|
||||||
|
NodeClusterId: params.ClusterId,
|
||||||
|
Name: params.Name,
|
||||||
|
NodeGrantId: params.GrantId,
|
||||||
|
InstallDir: params.InstallDir,
|
||||||
|
TimeZone: params.TimeZone,
|
||||||
|
NodeMaxThreads: params.NodeMaxThreads,
|
||||||
|
AutoOpenPorts: params.AutoOpenPorts,
|
||||||
|
ClockJSON: clockConfigJSON,
|
||||||
|
AutoRemoteStart: params.AutoRemoteStart,
|
||||||
|
AutoInstallNftables: params.AutoInstallNftables,
|
||||||
|
SshParamsJSON: sshParamsJSON,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
this.ErrorPage(err)
|
this.ErrorPage(err)
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
ddosProtection "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/cluster/settings/ddos-protection"
|
ddosProtection "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/cluster/settings/ddos-protection"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/cluster/settings/dns"
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/cluster/settings/dns"
|
||||||
firewallActions "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/cluster/settings/firewall-actions"
|
firewallActions "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/cluster/settings/firewall-actions"
|
||||||
|
globalServerConfig "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/cluster/settings/global-server-config"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/cluster/settings/health"
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/cluster/settings/health"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/cluster/settings/metrics"
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/cluster/settings/metrics"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/cluster/settings/services"
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/cluster/settings/services"
|
||||||
@@ -28,6 +29,7 @@ func init() {
|
|||||||
// 健康检查
|
// 健康检查
|
||||||
GetPost("/health", new(health.IndexAction)).
|
GetPost("/health", new(health.IndexAction)).
|
||||||
GetPost("/health/runPopup", new(health.RunPopupAction)).
|
GetPost("/health/runPopup", new(health.RunPopupAction)).
|
||||||
|
Post("/health/checkDomain", new(health.CheckDomainAction)).
|
||||||
|
|
||||||
// 缓存
|
// 缓存
|
||||||
GetPost("/cache", new(cache.IndexAction)).
|
GetPost("/cache", new(cache.IndexAction)).
|
||||||
@@ -71,6 +73,10 @@ func init() {
|
|||||||
GetPost("", new(ddosProtection.IndexAction)).
|
GetPost("", new(ddosProtection.IndexAction)).
|
||||||
GetPost("/status", new(ddosProtection.StatusAction)).
|
GetPost("/status", new(ddosProtection.StatusAction)).
|
||||||
|
|
||||||
|
// 全局服务配置
|
||||||
|
Prefix("/clusters/cluster/settings/global-server-config").
|
||||||
|
GetPost("", new(globalServerConfig.IndexAction)).
|
||||||
|
|
||||||
//
|
//
|
||||||
EndAll()
|
EndAll()
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -153,6 +153,12 @@ func (this *ClusterHelper) createSettingMenu(cluster *pb.NodeCluster, info *pb.F
|
|||||||
"isOn": info != nil && info.HasDDoSProtection,
|
"isOn": info != nil && info.HasDDoSProtection,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
items = append(items, maps.Map{
|
||||||
|
"name": "服务设置",
|
||||||
|
"url": "/clusters/cluster/settings/global-server-config?clusterId=" + clusterId,
|
||||||
|
"isActive": selectedItem == "globalServerConfig",
|
||||||
|
})
|
||||||
|
|
||||||
items = append(items, maps.Map{
|
items = append(items, maps.Map{
|
||||||
"name": "-",
|
"name": "-",
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -0,0 +1,66 @@
|
|||||||
|
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||||
|
|
||||||
|
package clusterutils
|
||||||
|
|
||||||
|
import (
|
||||||
|
teaconst "github.com/TeaOSLab/EdgeAdmin/internal/const"
|
||||||
|
"github.com/iwind/TeaGo/Tea"
|
||||||
|
"path/filepath"
|
||||||
|
"regexp"
|
||||||
|
"sort"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type installerFile struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
OS string `json:"os"`
|
||||||
|
Arch string `json:"arch"`
|
||||||
|
Version string `json:"version"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func ListInstallerFiles() []*installerFile {
|
||||||
|
var dir = Tea.Root + "/edge-api/deploy"
|
||||||
|
matches, err := filepath.Glob(dir + "/edge-node-*.zip")
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var result = []*installerFile{}
|
||||||
|
var reg = regexp.MustCompile(`^edge-node-(\w+)-(\w+)-v([\w.]+)\.zip$`)
|
||||||
|
for _, match := range matches {
|
||||||
|
var baseName = filepath.Base(match)
|
||||||
|
var subMatches = reg.FindStringSubmatch(baseName)
|
||||||
|
if len(subMatches) >= 4 {
|
||||||
|
var osName = subMatches[1]
|
||||||
|
if len(osName) > 0 {
|
||||||
|
osName = strings.ToUpper(osName[:1]) + osName[1:]
|
||||||
|
}
|
||||||
|
|
||||||
|
var arch = subMatches[2]
|
||||||
|
if arch == "amd64" {
|
||||||
|
arch = "x86_64"
|
||||||
|
}
|
||||||
|
|
||||||
|
var version = subMatches[3]
|
||||||
|
if version != teaconst.Version { // 只能下载当前版本
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
result = append(result, &installerFile{
|
||||||
|
Name: subMatches[0],
|
||||||
|
OS: osName,
|
||||||
|
Arch: arch,
|
||||||
|
Version: version,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 排序,将x86_64排在最上面
|
||||||
|
if len(result) > 0 {
|
||||||
|
sort.Slice(result, func(i, j int) bool {
|
||||||
|
return result[i].Arch == "x86_64"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/dns/domains/domainutils"
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/dns/domains/domainutils"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||||
"github.com/iwind/TeaGo/actions"
|
"github.com/iwind/TeaGo/actions"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -55,14 +56,19 @@ func (this *CreateAction) RunPost(params struct {
|
|||||||
// WAF策略
|
// WAF策略
|
||||||
HttpFirewallPolicyId int64
|
HttpFirewallPolicyId int64
|
||||||
|
|
||||||
|
// 服务配置
|
||||||
|
MatchDomainStrictly bool
|
||||||
|
|
||||||
// SSH相关
|
// SSH相关
|
||||||
GrantId int64
|
GrantId int64
|
||||||
InstallDir string
|
InstallDir string
|
||||||
SystemdServiceIsOn bool
|
SystemdServiceIsOn bool
|
||||||
|
AutoInstallNftables bool
|
||||||
|
|
||||||
// DNS相关
|
// DNS相关
|
||||||
DnsDomainId int64
|
DnsDomainId int64
|
||||||
DnsName string
|
DnsName string
|
||||||
|
DnsTTL int32
|
||||||
|
|
||||||
Must *actions.Must
|
Must *actions.Must
|
||||||
}) {
|
}) {
|
||||||
@@ -92,8 +98,17 @@ func (this *CreateAction) RunPost(params struct {
|
|||||||
|
|
||||||
// TODO 检查DnsDomainId的有效性
|
// TODO 检查DnsDomainId的有效性
|
||||||
|
|
||||||
|
// 全局服务配置
|
||||||
|
var globalServerConfig = serverconfigs.DefaultGlobalServerConfig()
|
||||||
|
globalServerConfig.HTTPAll.MatchDomainStrictly = params.MatchDomainStrictly
|
||||||
|
globalServerConfigJSON, err := json.Marshal(globalServerConfig)
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// 系统服务
|
// 系统服务
|
||||||
systemServices := map[string]interface{}{}
|
var systemServices = map[string]any{}
|
||||||
if params.SystemdServiceIsOn {
|
if params.SystemdServiceIsOn {
|
||||||
systemServices[nodeconfigs.SystemServiceTypeSystemd] = &nodeconfigs.SystemdServiceConfig{
|
systemServices[nodeconfigs.SystemServiceTypeSystemd] = &nodeconfigs.SystemdServiceConfig{
|
||||||
IsOn: true,
|
IsOn: true,
|
||||||
@@ -106,14 +121,17 @@ func (this *CreateAction) RunPost(params struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
createResp, err := this.RPC().NodeClusterRPC().CreateNodeCluster(this.AdminContext(), &pb.CreateNodeClusterRequest{
|
createResp, err := this.RPC().NodeClusterRPC().CreateNodeCluster(this.AdminContext(), &pb.CreateNodeClusterRequest{
|
||||||
Name: params.Name,
|
Name: params.Name,
|
||||||
NodeGrantId: params.GrantId,
|
NodeGrantId: params.GrantId,
|
||||||
InstallDir: params.InstallDir,
|
InstallDir: params.InstallDir,
|
||||||
DnsDomainId: params.DnsDomainId,
|
DnsDomainId: params.DnsDomainId,
|
||||||
DnsName: params.DnsName,
|
DnsName: params.DnsName,
|
||||||
HttpCachePolicyId: params.CachePolicyId,
|
DnsTTL: params.DnsTTL,
|
||||||
HttpFirewallPolicyId: params.HttpFirewallPolicyId,
|
HttpCachePolicyId: params.CachePolicyId,
|
||||||
SystemServicesJSON: systemServicesJSON,
|
HttpFirewallPolicyId: params.HttpFirewallPolicyId,
|
||||||
|
SystemServicesJSON: systemServicesJSON,
|
||||||
|
GlobalServerConfigJSON: globalServerConfigJSON,
|
||||||
|
AutoInstallNftables: params.AutoInstallNftables,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
this.ErrorPage(err)
|
this.ErrorPage(err)
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ type IndexAction struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (this *IndexAction) Init() {
|
func (this *IndexAction) Init() {
|
||||||
this.Nav("", "", "region")
|
this.Nav("", "", "index")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *IndexAction) RunGet(params struct{}) {
|
func (this *IndexAction) RunGet(params struct{}) {
|
||||||
@@ -20,7 +20,7 @@ func (this *IndexAction) RunGet(params struct{}) {
|
|||||||
this.ErrorPage(err)
|
this.ErrorPage(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
regionMaps := []maps.Map{}
|
var regionMaps = []maps.Map{}
|
||||||
for _, region := range regionsResp.NodeRegions {
|
for _, region := range regionsResp.NodeRegions {
|
||||||
countNodesResp, err := this.RPC().NodeRPC().CountAllEnabledNodesWithNodeRegionId(this.AdminContext(), &pb.CountAllEnabledNodesWithNodeRegionIdRequest{NodeRegionId: region.Id})
|
countNodesResp, err := this.RPC().NodeRPC().CountAllEnabledNodesWithNodeRegionId(this.AdminContext(), &pb.CountAllEnabledNodesWithNodeRegionIdRequest{NodeRegionId: region.Id})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -18,9 +18,13 @@ func init() {
|
|||||||
GetPost("/updatePopup", new(UpdatePopupAction)).
|
GetPost("/updatePopup", new(UpdatePopupAction)).
|
||||||
Post("/delete", new(DeleteAction)).
|
Post("/delete", new(DeleteAction)).
|
||||||
Post("/sort", new(SortAction)).
|
Post("/sort", new(SortAction)).
|
||||||
|
Get("/nodes", new(NodesAction)).
|
||||||
|
GetPost("/updateNodeRegionPopup", new(UpdateNodeRegionPopupAction)).
|
||||||
|
|
||||||
|
//
|
||||||
GetPost("/selectPopup", new(SelectPopupAction)).
|
GetPost("/selectPopup", new(SelectPopupAction)).
|
||||||
GetPost("/prices", new(PricesAction)).
|
|
||||||
GetPost("/updatePricePopup", new(UpdatePricePopupAction)).
|
//
|
||||||
EndAll()
|
EndAll()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,50 +0,0 @@
|
|||||||
package items
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/regions/regionutils"
|
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
|
||||||
"github.com/iwind/TeaGo/actions"
|
|
||||||
)
|
|
||||||
|
|
||||||
type CreatePopupAction struct {
|
|
||||||
actionutils.ParentAction
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *CreatePopupAction) Init() {
|
|
||||||
this.Nav("", "", "")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *CreatePopupAction) RunGet(params struct{}) {
|
|
||||||
this.Show()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *CreatePopupAction) RunPost(params struct {
|
|
||||||
Name string
|
|
||||||
BitsFrom int64
|
|
||||||
BitsTo int64
|
|
||||||
|
|
||||||
Must *actions.Must
|
|
||||||
CSRF *actionutils.CSRF
|
|
||||||
}) {
|
|
||||||
params.Must.
|
|
||||||
Field("name", params.Name).
|
|
||||||
Require("请输入名称").
|
|
||||||
Field("bitsFrom", params.BitsFrom).
|
|
||||||
Gte(0, "请输入不小于0的整数").
|
|
||||||
Field("bitsTo", params.BitsTo).
|
|
||||||
Gte(0, "请输入不小于0的整数")
|
|
||||||
|
|
||||||
createResp, err := this.RPC().NodePriceItemRPC().CreateNodePriceItem(this.AdminContext(), &pb.CreateNodePriceItemRequest{
|
|
||||||
Name: params.Name,
|
|
||||||
Type: regionutils.PriceTypeTraffic,
|
|
||||||
BitsFrom: params.BitsFrom * 1000 * 1000,
|
|
||||||
BitsTo: params.BitsTo * 1000 * 1000,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
this.ErrorPage(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer this.CreateLogInfo("创建流量价格项目", createResp.NodePriceItemId)
|
|
||||||
this.Success()
|
|
||||||
}
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
package items
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
|
||||||
)
|
|
||||||
|
|
||||||
type DeleteAction struct {
|
|
||||||
actionutils.ParentAction
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *DeleteAction) RunPost(params struct {
|
|
||||||
ItemId int64
|
|
||||||
}) {
|
|
||||||
defer this.CreateLogInfo("删除流量价格项目 %d", params.ItemId)
|
|
||||||
|
|
||||||
_, err := this.RPC().NodePriceItemRPC().DeleteNodePriceItem(this.AdminContext(), &pb.DeleteNodePriceItemRequest{NodePriceItemId: params.ItemId})
|
|
||||||
if err != nil {
|
|
||||||
this.ErrorPage(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
this.Success()
|
|
||||||
}
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
package items
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
|
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
|
|
||||||
"github.com/iwind/TeaGo"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
|
||||||
server.
|
|
||||||
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeNode)).
|
|
||||||
Data("teaMenu", "clusters").
|
|
||||||
Data("teaSubMenu", "region").
|
|
||||||
Prefix("/clusters/regions/items").
|
|
||||||
GetPost("/createPopup", new(CreatePopupAction)).
|
|
||||||
GetPost("/updatePopup", new(UpdatePopupAction)).
|
|
||||||
Post("/delete", new(DeleteAction)).
|
|
||||||
EndAll()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
@@ -1,73 +0,0 @@
|
|||||||
package items
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
|
||||||
"github.com/iwind/TeaGo/actions"
|
|
||||||
"github.com/iwind/TeaGo/maps"
|
|
||||||
)
|
|
||||||
|
|
||||||
type UpdatePopupAction struct {
|
|
||||||
actionutils.ParentAction
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *UpdatePopupAction) Init() {
|
|
||||||
this.Nav("", "", "")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *UpdatePopupAction) RunGet(params struct {
|
|
||||||
ItemId int64
|
|
||||||
}) {
|
|
||||||
itemResp, err := this.RPC().NodePriceItemRPC().FindEnabledNodePriceItem(this.AdminContext(), &pb.FindEnabledNodePriceItemRequest{NodePriceItemId: params.ItemId})
|
|
||||||
if err != nil {
|
|
||||||
this.ErrorPage(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
item := itemResp.NodePriceItem
|
|
||||||
if item == nil {
|
|
||||||
this.NotFound("nodePriceItem", params.ItemId)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
this.Data["item"] = maps.Map{
|
|
||||||
"id": item.Id,
|
|
||||||
"name": item.Name,
|
|
||||||
"bitsFrom": item.BitsFrom,
|
|
||||||
"bitsTo": item.BitsTo,
|
|
||||||
}
|
|
||||||
|
|
||||||
this.Show()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *UpdatePopupAction) RunPost(params struct {
|
|
||||||
ItemId int64
|
|
||||||
Name string
|
|
||||||
BitsFrom int64
|
|
||||||
BitsTo int64
|
|
||||||
|
|
||||||
Must *actions.Must
|
|
||||||
CSRF *actionutils.CSRF
|
|
||||||
}) {
|
|
||||||
defer this.CreateLogInfo("修改流量价格项目", params.ItemId)
|
|
||||||
|
|
||||||
params.Must.
|
|
||||||
Field("name", params.Name).
|
|
||||||
Require("请输入名称").
|
|
||||||
Field("bitsFrom", params.BitsFrom).
|
|
||||||
Gte(0, "请输入不小于0的整数").
|
|
||||||
Field("bitsTo", params.BitsTo).
|
|
||||||
Gte(0, "请输入不小于0的整数")
|
|
||||||
|
|
||||||
_, err := this.RPC().NodePriceItemRPC().UpdateNodePriceItem(this.AdminContext(), &pb.UpdateNodePriceItemRequest{
|
|
||||||
NodePriceItemId: params.ItemId,
|
|
||||||
Name: params.Name,
|
|
||||||
BitsFrom: params.BitsFrom * 1000 * 1000,
|
|
||||||
BitsTo: params.BitsTo * 1000 * 1000,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
this.ErrorPage(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
this.Success()
|
|
||||||
}
|
|
||||||
92
internal/web/actions/default/clusters/regions/nodes.go
Normal file
92
internal/web/actions/default/clusters/regions/nodes.go
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||||
|
|
||||||
|
package regions
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
|
"github.com/iwind/TeaGo/maps"
|
||||||
|
)
|
||||||
|
|
||||||
|
type NodesAction struct {
|
||||||
|
actionutils.ParentAction
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *NodesAction) Init() {
|
||||||
|
this.Nav("", "", "node")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *NodesAction) RunGet(params struct {
|
||||||
|
RegionId int64
|
||||||
|
}) {
|
||||||
|
this.Data["regionId"] = params.RegionId
|
||||||
|
|
||||||
|
// 所有区域
|
||||||
|
regionsResp, err := this.RPC().NodeRegionRPC().FindAllAvailableNodeRegions(this.AdminContext(), &pb.FindAllAvailableNodeRegionsRequest{})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var regionMaps = []maps.Map{}
|
||||||
|
for _, region := range regionsResp.NodeRegions {
|
||||||
|
regionMaps = append(regionMaps, maps.Map{
|
||||||
|
"id": region.Id,
|
||||||
|
"name": region.Name,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
this.Data["regions"] = regionMaps
|
||||||
|
|
||||||
|
// 节点数量
|
||||||
|
countResp, err := this.RPC().NodeRPC().CountAllNodeRegionInfo(this.AdminContext(), &pb.CountAllNodeRegionInfoRequest{NodeRegionId: params.RegionId})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var page = this.NewPage(countResp.Count)
|
||||||
|
this.Data["page"] = page.AsHTML()
|
||||||
|
|
||||||
|
// 节点列表
|
||||||
|
var hasNodesWithoutRegion = false
|
||||||
|
nodesResp, err := this.RPC().NodeRPC().ListNodeRegionInfo(this.AdminContext(), &pb.ListNodeRegionInfoRequest{
|
||||||
|
NodeRegionId: params.RegionId,
|
||||||
|
Offset: page.Offset,
|
||||||
|
Size: page.Size,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var nodeMaps = []maps.Map{}
|
||||||
|
for _, node := range nodesResp.InfoList {
|
||||||
|
// region
|
||||||
|
var regionMap maps.Map
|
||||||
|
if node.NodeRegion != nil {
|
||||||
|
regionMap = maps.Map{
|
||||||
|
"id": node.NodeRegion.Id,
|
||||||
|
"name": node.NodeRegion.Name,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
hasNodesWithoutRegion = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// cluster
|
||||||
|
var clusterMap maps.Map
|
||||||
|
if node.NodeCluster != nil {
|
||||||
|
clusterMap = maps.Map{
|
||||||
|
"id": node.NodeCluster.Id,
|
||||||
|
"name": node.NodeCluster.Name,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nodeMaps = append(nodeMaps, maps.Map{
|
||||||
|
"id": node.Id,
|
||||||
|
"name": node.Name,
|
||||||
|
"region": regionMap,
|
||||||
|
"cluster": clusterMap,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
this.Data["nodes"] = nodeMaps
|
||||||
|
this.Data["hasNodesWithoutRegion"] = hasNodesWithoutRegion
|
||||||
|
|
||||||
|
this.Show()
|
||||||
|
}
|
||||||
@@ -1,86 +0,0 @@
|
|||||||
package regions
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/utils/numberutils"
|
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/regions/regionutils"
|
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
|
||||||
"github.com/iwind/TeaGo/maps"
|
|
||||||
)
|
|
||||||
|
|
||||||
type PricesAction struct {
|
|
||||||
actionutils.ParentAction
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *PricesAction) Init() {
|
|
||||||
this.Nav("", "", "price")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *PricesAction) RunGet(params struct{}) {
|
|
||||||
// 所有价格项目
|
|
||||||
itemsResp, err := this.RPC().NodePriceItemRPC().FindAllAvailableNodePriceItems(this.AdminContext(), &pb.FindAllAvailableNodePriceItemsRequest{Type: regionutils.PriceTypeTraffic})
|
|
||||||
if err != nil {
|
|
||||||
this.ErrorPage(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
itemMaps := []maps.Map{}
|
|
||||||
for _, item := range itemsResp.NodePriceItems {
|
|
||||||
|
|
||||||
itemMaps = append(itemMaps, maps.Map{
|
|
||||||
"id": item.Id,
|
|
||||||
"name": item.Name,
|
|
||||||
"bitsFromString": this.formatBits(item.BitsFrom),
|
|
||||||
"bitsToString": this.formatBits(item.BitsTo),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
this.Data["items"] = itemMaps
|
|
||||||
|
|
||||||
// 所有区域
|
|
||||||
regionsResp, err := this.RPC().NodeRegionRPC().FindAllEnabledNodeRegions(this.AdminContext(), &pb.FindAllEnabledNodeRegionsRequest{})
|
|
||||||
if err != nil {
|
|
||||||
this.ErrorPage(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
regionMaps := []maps.Map{}
|
|
||||||
for _, region := range regionsResp.NodeRegions {
|
|
||||||
pricesMap := map[string]float32{}
|
|
||||||
if len(region.PricesJSON) > 0 {
|
|
||||||
err = json.Unmarshal(region.PricesJSON, &pricesMap)
|
|
||||||
if err != nil {
|
|
||||||
this.ErrorPage(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
regionMaps = append(regionMaps, maps.Map{
|
|
||||||
"id": region.Id,
|
|
||||||
"isOn": region.IsOn,
|
|
||||||
"name": region.Name,
|
|
||||||
"prices": pricesMap,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
this.Data["regions"] = regionMaps
|
|
||||||
|
|
||||||
this.Show()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *PricesAction) formatBits(bits int64) string {
|
|
||||||
sizeHuman := ""
|
|
||||||
if bits < 1000 {
|
|
||||||
sizeHuman = numberutils.FormatInt64(bits) + "BPS"
|
|
||||||
} else if bits < 1_000_000 {
|
|
||||||
sizeHuman = fmt.Sprintf("%.2fKBPS", float64(bits)/1000)
|
|
||||||
} else if bits < 1_000_000_000 {
|
|
||||||
sizeHuman = fmt.Sprintf("%.2fMBPS", float64(bits)/1000/1000)
|
|
||||||
} else if bits < 1_000_000_000_000 {
|
|
||||||
sizeHuman = fmt.Sprintf("%.2fGBPS", float64(bits)/1000/1000/1000)
|
|
||||||
} else if bits < 1_000_000_000_000_000 {
|
|
||||||
sizeHuman = fmt.Sprintf("%.2fTBPS", float64(bits)/1000/1000/1000/1000)
|
|
||||||
} else if bits < 1_000_000_000_000_000_000 {
|
|
||||||
sizeHuman = fmt.Sprintf("%.2fPBPS", float64(bits)/1000/1000/1000/1000/1000)
|
|
||||||
} else {
|
|
||||||
sizeHuman = fmt.Sprintf("%.2fEBPS", float64(bits)/1000/1000/1000/1000/1000/1000)
|
|
||||||
}
|
|
||||||
return sizeHuman
|
|
||||||
}
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
package regionutils
|
|
||||||
|
|
||||||
const (
|
|
||||||
PriceTypeTraffic = "traffic"
|
|
||||||
)
|
|
||||||
@@ -40,12 +40,18 @@ func (this *SelectPopupAction) RunPost(params struct {
|
|||||||
Must *actions.Must
|
Must *actions.Must
|
||||||
CSRF *actionutils.CSRF
|
CSRF *actionutils.CSRF
|
||||||
}) {
|
}) {
|
||||||
|
if params.RegionId <= 0 {
|
||||||
|
this.Data["region"] = nil
|
||||||
|
this.Success()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
regionResp, err := this.RPC().NodeRegionRPC().FindEnabledNodeRegion(this.AdminContext(), &pb.FindEnabledNodeRegionRequest{NodeRegionId: params.RegionId})
|
regionResp, err := this.RPC().NodeRegionRPC().FindEnabledNodeRegion(this.AdminContext(), &pb.FindEnabledNodeRegionRequest{NodeRegionId: params.RegionId})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
this.ErrorPage(err)
|
this.ErrorPage(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
region := regionResp.NodeRegion
|
var region = regionResp.NodeRegion
|
||||||
if region == nil {
|
if region == nil {
|
||||||
this.NotFound("nodeRegion", params.RegionId)
|
this.NotFound("nodeRegion", params.RegionId)
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -0,0 +1,97 @@
|
|||||||
|
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||||
|
|
||||||
|
package regions
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
|
"github.com/iwind/TeaGo/actions"
|
||||||
|
"github.com/iwind/TeaGo/maps"
|
||||||
|
)
|
||||||
|
|
||||||
|
type UpdateNodeRegionPopupAction struct {
|
||||||
|
actionutils.ParentAction
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *UpdateNodeRegionPopupAction) Init() {
|
||||||
|
this.Nav("", "", "")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *UpdateNodeRegionPopupAction) RunGet(params struct {
|
||||||
|
NodeId int64
|
||||||
|
RegionId int64
|
||||||
|
}) {
|
||||||
|
// node
|
||||||
|
nodeResp, err := this.RPC().NodeRPC().FindEnabledNode(this.AdminContext(), &pb.FindEnabledNodeRequest{NodeId: params.NodeId})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var node = nodeResp.Node
|
||||||
|
if node == nil {
|
||||||
|
this.NotFound("node", params.NodeId)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.Data["node"] = maps.Map{
|
||||||
|
"id": node.Id,
|
||||||
|
"name": node.Name,
|
||||||
|
}
|
||||||
|
|
||||||
|
// region
|
||||||
|
this.Data["region"] = maps.Map{
|
||||||
|
"id": 0,
|
||||||
|
"name": "",
|
||||||
|
}
|
||||||
|
if params.RegionId > 0 {
|
||||||
|
regionResp, err := this.RPC().NodeRegionRPC().FindEnabledNodeRegion(this.AdminContext(), &pb.FindEnabledNodeRegionRequest{NodeRegionId: params.RegionId})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var region = regionResp.NodeRegion
|
||||||
|
if region != nil {
|
||||||
|
this.Data["region"] = maps.Map{
|
||||||
|
"id": region.Id,
|
||||||
|
"name": region.Name,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// all regions
|
||||||
|
regionsResp, err := this.RPC().NodeRegionRPC().FindAllAvailableNodeRegions(this.AdminContext(), &pb.FindAllAvailableNodeRegionsRequest{})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var regionMaps = []maps.Map{}
|
||||||
|
for _, region := range regionsResp.NodeRegions {
|
||||||
|
regionMaps = append(regionMaps, maps.Map{
|
||||||
|
"id": region.Id,
|
||||||
|
"name": region.Name,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
this.Data["regions"] = regionMaps
|
||||||
|
|
||||||
|
this.Show()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *UpdateNodeRegionPopupAction) RunPost(params struct {
|
||||||
|
NodeId int64
|
||||||
|
RegionId int64
|
||||||
|
|
||||||
|
Must *actions.Must
|
||||||
|
CSRF *actionutils.CSRF
|
||||||
|
}) {
|
||||||
|
defer this.CreateLogInfo("修改节点 %d 区域到 %d", params.RegionId)
|
||||||
|
|
||||||
|
_, err := this.RPC().NodeRPC().UpdateNodeRegionInfo(this.AdminContext(), &pb.UpdateNodeRegionInfoRequest{
|
||||||
|
NodeId: params.NodeId,
|
||||||
|
NodeRegionId: params.RegionId,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Success()
|
||||||
|
}
|
||||||
@@ -1,94 +0,0 @@
|
|||||||
package regions
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/utils/numberutils"
|
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
|
||||||
"github.com/iwind/TeaGo/actions"
|
|
||||||
"github.com/iwind/TeaGo/maps"
|
|
||||||
)
|
|
||||||
|
|
||||||
type UpdatePricePopupAction struct {
|
|
||||||
actionutils.ParentAction
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *UpdatePricePopupAction) Init() {
|
|
||||||
this.Nav("", "", "")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *UpdatePricePopupAction) RunGet(params struct {
|
|
||||||
RegionId int64
|
|
||||||
ItemId int64
|
|
||||||
}) {
|
|
||||||
// 区域
|
|
||||||
regionResp, err := this.RPC().NodeRegionRPC().FindEnabledNodeRegion(this.AdminContext(), &pb.FindEnabledNodeRegionRequest{NodeRegionId: params.RegionId})
|
|
||||||
if err != nil {
|
|
||||||
this.ErrorPage(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
region := regionResp.NodeRegion
|
|
||||||
if region == nil {
|
|
||||||
this.NotFound("nodeRegion", params.RegionId)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
this.Data["region"] = maps.Map{
|
|
||||||
"id": region.Id,
|
|
||||||
"isOn": region.IsOn,
|
|
||||||
"name": region.Name,
|
|
||||||
}
|
|
||||||
|
|
||||||
// 当前价格
|
|
||||||
pricesMap := map[string]float32{}
|
|
||||||
if len(region.PricesJSON) > 0 {
|
|
||||||
err = json.Unmarshal(region.PricesJSON, &pricesMap)
|
|
||||||
if err != nil {
|
|
||||||
this.ErrorPage(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.Data["price"] = pricesMap[numberutils.FormatInt64(params.ItemId)]
|
|
||||||
|
|
||||||
// 价格项
|
|
||||||
itemResp, err := this.RPC().NodePriceItemRPC().FindEnabledNodePriceItem(this.AdminContext(), &pb.FindEnabledNodePriceItemRequest{NodePriceItemId: params.ItemId})
|
|
||||||
if err != nil {
|
|
||||||
this.ErrorPage(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
item := itemResp.NodePriceItem
|
|
||||||
if item == nil {
|
|
||||||
this.NotFound("nodePriceItem", params.ItemId)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
this.Data["item"] = maps.Map{
|
|
||||||
"id": item.Id,
|
|
||||||
"name": item.Name,
|
|
||||||
"bitsFrom": item.BitsFrom,
|
|
||||||
"bitsTo": item.BitsTo,
|
|
||||||
}
|
|
||||||
|
|
||||||
this.Show()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *UpdatePricePopupAction) RunPost(params struct {
|
|
||||||
RegionId int64
|
|
||||||
ItemId int64
|
|
||||||
Price float32
|
|
||||||
|
|
||||||
Must *actions.Must
|
|
||||||
CSRF *actionutils.CSRF
|
|
||||||
}) {
|
|
||||||
defer this.CreateLogInfo("修改区域 %d-价格项 %d 的价格", params.RegionId, params.ItemId)
|
|
||||||
|
|
||||||
_, err := this.RPC().NodeRegionRPC().UpdateNodeRegionPrice(this.AdminContext(), &pb.UpdateNodeRegionPriceRequest{
|
|
||||||
NodeRegionId: params.RegionId,
|
|
||||||
NodeItemId: params.ItemId,
|
|
||||||
Price: params.Price,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
this.ErrorPage(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
this.Success()
|
|
||||||
}
|
|
||||||
@@ -76,16 +76,14 @@ func (this *IndexAction) RunPost(params struct{}) {
|
|||||||
this.Data["dashboard"] = maps.Map{
|
this.Data["dashboard"] = maps.Map{
|
||||||
"defaultClusterId": resp.DefaultNodeClusterId,
|
"defaultClusterId": resp.DefaultNodeClusterId,
|
||||||
|
|
||||||
"countServers": resp.CountServers,
|
"countServers": resp.CountServers,
|
||||||
"countNodeClusters": resp.CountNodeClusters,
|
"countNodeClusters": resp.CountNodeClusters,
|
||||||
"countNodes": resp.CountNodes,
|
"countNodes": resp.CountNodes,
|
||||||
"countOfflineNodes": resp.CountOfflineNodes,
|
"countOfflineNodes": resp.CountOfflineNodes,
|
||||||
"countUsers": resp.CountUsers,
|
"countUsers": resp.CountUsers,
|
||||||
"countAPINodes": resp.CountAPINodes,
|
"countAPINodes": resp.CountAPINodes,
|
||||||
"countOfflineAPINodes": resp.CountOfflineAPINodes,
|
"countOfflineAPINodes": resp.CountOfflineAPINodes,
|
||||||
"countDBNodes": resp.CountDBNodes,
|
"countDBNodes": resp.CountDBNodes,
|
||||||
"countUserNodes": resp.CountUserNodes,
|
|
||||||
"countOfflineUserNodes": resp.CountOfflineUserNodes,
|
|
||||||
|
|
||||||
"canGoServers": configloaders.AllowModule(this.AdminId(), configloaders.AdminModuleCodeServer),
|
"canGoServers": configloaders.AllowModule(this.AdminId(), configloaders.AdminModuleCodeServer),
|
||||||
"canGoNodes": configloaders.AllowModule(this.AdminId(), configloaders.AdminModuleCodeNode),
|
"canGoNodes": configloaders.AllowModule(this.AdminId(), configloaders.AdminModuleCodeNode),
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ func (this *ClusterAction) RunGet(params struct {
|
|||||||
}
|
}
|
||||||
var defaultRoute = dnsResp.DefaultRoute
|
var defaultRoute = dnsResp.DefaultRoute
|
||||||
domainName := ""
|
domainName := ""
|
||||||
dnsMap := maps.Map{
|
var dnsMap = maps.Map{
|
||||||
"dnsName": dnsResp.Name,
|
"dnsName": dnsResp.Name,
|
||||||
"domainId": 0,
|
"domainId": 0,
|
||||||
"domainName": "",
|
"domainName": "",
|
||||||
@@ -76,14 +76,14 @@ func (this *ClusterAction) RunGet(params struct {
|
|||||||
this.ErrorPage(err)
|
this.ErrorPage(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
nodeMaps := []maps.Map{}
|
var nodeMaps = []maps.Map{}
|
||||||
for _, node := range nodesResp.Nodes {
|
for _, node := range nodesResp.Nodes {
|
||||||
if len(node.Routes) > 0 {
|
if len(node.Routes) > 0 {
|
||||||
for _, route := range node.Routes {
|
for _, route := range node.Routes {
|
||||||
// 检查是否已解析
|
// 检查是否已解析
|
||||||
isResolved := false
|
var isResolved = false
|
||||||
if cluster.DnsDomainId > 0 && len(cluster.DnsName) > 0 && len(node.IpAddr) > 0 {
|
if cluster.DnsDomainId > 0 && len(cluster.DnsName) > 0 && len(node.IpAddr) > 0 {
|
||||||
recordType := "A"
|
var recordType = "A"
|
||||||
if utils.IsIPv6(node.IpAddr) {
|
if utils.IsIPv6(node.IpAddr) {
|
||||||
recordType = "AAAA"
|
recordType = "AAAA"
|
||||||
}
|
}
|
||||||
@@ -102,9 +102,10 @@ func (this *ClusterAction) RunGet(params struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
nodeMaps = append(nodeMaps, maps.Map{
|
nodeMaps = append(nodeMaps, maps.Map{
|
||||||
"id": node.Id,
|
"id": node.Id,
|
||||||
"name": node.Name,
|
"name": node.Name,
|
||||||
"ipAddr": node.IpAddr,
|
"ipAddr": node.IpAddr,
|
||||||
|
"ipAddrId": node.NodeIPAddressId,
|
||||||
"route": maps.Map{
|
"route": maps.Map{
|
||||||
"name": route.Name,
|
"name": route.Name,
|
||||||
"code": route.Code,
|
"code": route.Code,
|
||||||
@@ -117,7 +118,7 @@ func (this *ClusterAction) RunGet(params struct {
|
|||||||
// 默认线路
|
// 默认线路
|
||||||
var isResolved = false
|
var isResolved = false
|
||||||
if len(defaultRoute) > 0 {
|
if len(defaultRoute) > 0 {
|
||||||
recordType := "A"
|
var recordType = "A"
|
||||||
if utils.IsIPv6(node.IpAddr) {
|
if utils.IsIPv6(node.IpAddr) {
|
||||||
recordType = "AAAA"
|
recordType = "AAAA"
|
||||||
}
|
}
|
||||||
@@ -135,9 +136,10 @@ func (this *ClusterAction) RunGet(params struct {
|
|||||||
isResolved = checkResp.IsOk
|
isResolved = checkResp.IsOk
|
||||||
}
|
}
|
||||||
nodeMaps = append(nodeMaps, maps.Map{
|
nodeMaps = append(nodeMaps, maps.Map{
|
||||||
"id": node.Id,
|
"id": node.Id,
|
||||||
"name": node.Name,
|
"name": node.Name,
|
||||||
"ipAddr": node.IpAddr,
|
"ipAddr": node.IpAddr,
|
||||||
|
"ipAddrId": node.NodeIPAddressId,
|
||||||
"route": maps.Map{
|
"route": maps.Map{
|
||||||
"name": "",
|
"name": "",
|
||||||
"code": "",
|
"code": "",
|
||||||
@@ -155,7 +157,7 @@ func (this *ClusterAction) RunGet(params struct {
|
|||||||
this.ErrorPage(err)
|
this.ErrorPage(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
serverMaps := []maps.Map{}
|
var serverMaps = []maps.Map{}
|
||||||
for _, server := range serversResp.Servers {
|
for _, server := range serversResp.Servers {
|
||||||
// 检查是否已解析
|
// 检查是否已解析
|
||||||
isResolved := false
|
isResolved := false
|
||||||
@@ -198,7 +200,7 @@ func (this *ClusterAction) RunGet(params struct {
|
|||||||
this.ErrorPage(err)
|
this.ErrorPage(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
issueMaps := []maps.Map{}
|
var issueMaps = []maps.Map{}
|
||||||
for _, issue := range issuesResp.Issues {
|
for _, issue := range issuesResp.Issues {
|
||||||
issueMaps = append(issueMaps, maps.Map{
|
issueMaps = append(issueMaps, maps.Map{
|
||||||
"target": issue.Target,
|
"target": issue.Target,
|
||||||
@@ -218,7 +220,7 @@ func (this *ClusterAction) RunGet(params struct {
|
|||||||
this.ErrorPage(err)
|
this.ErrorPage(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
taskMaps := []maps.Map{}
|
var taskMaps = []maps.Map{}
|
||||||
for _, task := range resp.DnsTasks {
|
for _, task := range resp.DnsTasks {
|
||||||
var clusterMap maps.Map = nil
|
var clusterMap maps.Map = nil
|
||||||
var nodeMap maps.Map = nil
|
var nodeMap maps.Map = nil
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ type DomainOptionsAction struct {
|
|||||||
func (this *DomainOptionsAction) RunPost(params struct {
|
func (this *DomainOptionsAction) RunPost(params struct {
|
||||||
ProviderId int64
|
ProviderId int64
|
||||||
}) {
|
}) {
|
||||||
domainsResp, err := this.RPC().DNSDomainRPC().FindAllEnabledBasicDNSDomainsWithDNSProviderId(this.AdminContext(), &pb.FindAllEnabledBasicDNSDomainsWithDNSProviderIdRequest{
|
domainsResp, err := this.RPC().DNSDomainRPC().FindAllBasicDNSDomainsWithDNSProviderId(this.AdminContext(), &pb.FindAllBasicDNSDomainsWithDNSProviderIdRequest{
|
||||||
DnsProviderId: params.ProviderId,
|
DnsProviderId: params.ProviderId,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ func (this *ClustersPopupAction) RunGet(params struct {
|
|||||||
DomainId int64
|
DomainId int64
|
||||||
}) {
|
}) {
|
||||||
// 域名信息
|
// 域名信息
|
||||||
domainResp, err := this.RPC().DNSDomainRPC().FindEnabledBasicDNSDomain(this.AdminContext(), &pb.FindEnabledBasicDNSDomainRequest{
|
domainResp, err := this.RPC().DNSDomainRPC().FindBasicDNSDomain(this.AdminContext(), &pb.FindBasicDNSDomainRequest{
|
||||||
DnsDomainId: params.DomainId,
|
DnsDomainId: params.DomainId,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -17,9 +17,9 @@ func ValidateDomainFormat(domain string) bool {
|
|||||||
if piece == "-" ||
|
if piece == "-" ||
|
||||||
strings.HasPrefix(piece, "-") ||
|
strings.HasPrefix(piece, "-") ||
|
||||||
strings.HasSuffix(piece, "-") ||
|
strings.HasSuffix(piece, "-") ||
|
||||||
//strings.Contains(piece, "--") ||
|
|
||||||
len(piece) > 63 ||
|
len(piece) > 63 ||
|
||||||
!regexp.MustCompile(`^[a-z0-9-]+$`).MatchString(piece) {
|
// 我们允许中文、大写字母、下划线,防止有些特殊场景下需要
|
||||||
|
!regexp.MustCompile(`^[\p{Han}_a-zA-Z0-9-]+$`).MatchString(piece) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -77,7 +77,8 @@ func ValidateRecordName(name string) bool {
|
|||||||
strings.HasSuffix(piece, "-") ||
|
strings.HasSuffix(piece, "-") ||
|
||||||
//strings.Contains(piece, "--") ||
|
//strings.Contains(piece, "--") ||
|
||||||
len(piece) > 63 ||
|
len(piece) > 63 ||
|
||||||
!regexp.MustCompile(`^[_a-z0-9-]+$`).MatchString(piece) {
|
// 我们允许中文、大写字母、下划线,防止有些特殊场景下需要
|
||||||
|
!regexp.MustCompile(`^[\p{Han}_a-zA-Z0-9-]+$`).MatchString(piece) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ func (this *NodesPopupAction) RunGet(params struct {
|
|||||||
DomainId int64
|
DomainId int64
|
||||||
}) {
|
}) {
|
||||||
// 域名信息
|
// 域名信息
|
||||||
domainResp, err := this.RPC().DNSDomainRPC().FindEnabledBasicDNSDomain(this.AdminContext(), &pb.FindEnabledBasicDNSDomainRequest{
|
domainResp, err := this.RPC().DNSDomainRPC().FindBasicDNSDomain(this.AdminContext(), &pb.FindBasicDNSDomainRequest{
|
||||||
DnsDomainId: params.DomainId,
|
DnsDomainId: params.DomainId,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -25,12 +25,12 @@ func (this *SelectPopupAction) RunGet(params struct {
|
|||||||
|
|
||||||
// 域名信息
|
// 域名信息
|
||||||
if params.DomainId > 0 {
|
if params.DomainId > 0 {
|
||||||
domainResp, err := this.RPC().DNSDomainRPC().FindEnabledDNSDomain(this.AdminContext(), &pb.FindEnabledDNSDomainRequest{DnsDomainId: params.DomainId})
|
domainResp, err := this.RPC().DNSDomainRPC().FindDNSDomain(this.AdminContext(), &pb.FindDNSDomainRequest{DnsDomainId: params.DomainId})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
this.ErrorPage(err)
|
this.ErrorPage(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
domain := domainResp.DnsDomain
|
var domain = domainResp.DnsDomain
|
||||||
if domain != nil {
|
if domain != nil {
|
||||||
this.Data["domainId"] = domain.Id
|
this.Data["domainId"] = domain.Id
|
||||||
this.Data["domainName"] = domain.Name
|
this.Data["domainName"] = domain.Name
|
||||||
@@ -53,7 +53,7 @@ func (this *SelectPopupAction) RunGet(params struct {
|
|||||||
this.ErrorPage(err)
|
this.ErrorPage(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
providerTypeMaps := []maps.Map{}
|
var providerTypeMaps = []maps.Map{}
|
||||||
for _, providerType := range providerTypesResp.ProviderTypes {
|
for _, providerType := range providerTypesResp.ProviderTypes {
|
||||||
providerTypeMaps = append(providerTypeMaps, maps.Map{
|
providerTypeMaps = append(providerTypeMaps, maps.Map{
|
||||||
"name": providerType.Name,
|
"name": providerType.Name,
|
||||||
@@ -73,15 +73,29 @@ func (this *SelectPopupAction) RunPost(params struct {
|
|||||||
}) {
|
}) {
|
||||||
this.Data["domainId"] = params.DomainId
|
this.Data["domainId"] = params.DomainId
|
||||||
this.Data["domainName"] = ""
|
this.Data["domainName"] = ""
|
||||||
|
this.Data["providerName"] = ""
|
||||||
|
|
||||||
if params.DomainId > 0 {
|
if params.DomainId > 0 {
|
||||||
domainResp, err := this.RPC().DNSDomainRPC().FindEnabledDNSDomain(this.AdminContext(), &pb.FindEnabledDNSDomainRequest{DnsDomainId: params.DomainId})
|
domainResp, err := this.RPC().DNSDomainRPC().FindDNSDomain(this.AdminContext(), &pb.FindDNSDomainRequest{DnsDomainId: params.DomainId})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
this.ErrorPage(err)
|
this.ErrorPage(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if domainResp.DnsDomain != nil {
|
if domainResp.DnsDomain != nil {
|
||||||
this.Data["domainName"] = domainResp.DnsDomain.Name
|
this.Data["domainName"] = domainResp.DnsDomain.Name
|
||||||
|
|
||||||
|
// 服务商名称
|
||||||
|
var providerId = domainResp.DnsDomain.ProviderId
|
||||||
|
if providerId > 0 {
|
||||||
|
providerResp, err := this.RPC().DNSProviderRPC().FindEnabledDNSProvider(this.AdminContext(), &pb.FindEnabledDNSProviderRequest{DnsProviderId: providerId})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if providerResp.DnsProvider != nil {
|
||||||
|
this.Data["providerName"] = providerResp.DnsProvider.Name
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
this.Data["domainId"] = 0
|
this.Data["domainId"] = 0
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ func (this *ServersPopupAction) RunGet(params struct {
|
|||||||
DomainId int64
|
DomainId int64
|
||||||
}) {
|
}) {
|
||||||
// 域名信息
|
// 域名信息
|
||||||
domainResp, err := this.RPC().DNSDomainRPC().FindEnabledBasicDNSDomain(this.AdminContext(), &pb.FindEnabledBasicDNSDomainRequest{
|
domainResp, err := this.RPC().DNSDomainRPC().FindBasicDNSDomain(this.AdminContext(), &pb.FindBasicDNSDomainRequest{
|
||||||
DnsDomainId: params.DomainId,
|
DnsDomainId: params.DomainId,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ func (this *UpdatePopupAction) Init() {
|
|||||||
func (this *UpdatePopupAction) RunGet(params struct {
|
func (this *UpdatePopupAction) RunGet(params struct {
|
||||||
DomainId int64
|
DomainId int64
|
||||||
}) {
|
}) {
|
||||||
domainResp, err := this.RPC().DNSDomainRPC().FindEnabledDNSDomain(this.AdminContext(), &pb.FindEnabledDNSDomainRequest{DnsDomainId: params.DomainId})
|
domainResp, err := this.RPC().DNSDomainRPC().FindDNSDomain(this.AdminContext(), &pb.FindDNSDomainRequest{DnsDomainId: params.DomainId})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
this.ErrorPage(err)
|
this.ErrorPage(err)
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ func (this *IndexAction) RunGet(params struct {
|
|||||||
providerTypeName := ""
|
providerTypeName := ""
|
||||||
|
|
||||||
if cluster.DnsDomainId > 0 {
|
if cluster.DnsDomainId > 0 {
|
||||||
domainResp, err := this.RPC().DNSDomainRPC().FindEnabledBasicDNSDomain(this.AdminContext(), &pb.FindEnabledBasicDNSDomainRequest{DnsDomainId: domainId})
|
domainResp, err := this.RPC().DNSDomainRPC().FindBasicDNSDomain(this.AdminContext(), &pb.FindBasicDNSDomainRequest{DnsDomainId: domainId})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
this.ErrorPage(err)
|
this.ErrorPage(err)
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -22,12 +22,14 @@ func (this *UpdateNodePopupAction) Init() {
|
|||||||
func (this *UpdateNodePopupAction) RunGet(params struct {
|
func (this *UpdateNodePopupAction) RunGet(params struct {
|
||||||
ClusterId int64
|
ClusterId int64
|
||||||
NodeId int64
|
NodeId int64
|
||||||
|
IpAddrId int64
|
||||||
}) {
|
}) {
|
||||||
this.Data["nodeId"] = params.NodeId
|
this.Data["nodeId"] = params.NodeId
|
||||||
|
|
||||||
dnsInfoResp, err := this.RPC().NodeRPC().FindEnabledNodeDNS(this.AdminContext(), &pb.FindEnabledNodeDNSRequest{
|
dnsInfoResp, err := this.RPC().NodeRPC().FindEnabledNodeDNS(this.AdminContext(), &pb.FindEnabledNodeDNSRequest{
|
||||||
NodeId: params.NodeId,
|
NodeId: params.NodeId,
|
||||||
NodeClusterId: params.ClusterId,
|
NodeClusterId: params.ClusterId,
|
||||||
|
NodeIPAddrId: params.IpAddrId,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
this.ErrorPage(err)
|
this.ErrorPage(err)
|
||||||
@@ -39,12 +41,13 @@ func (this *UpdateNodePopupAction) RunGet(params struct {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
this.Data["ipAddr"] = dnsInfo.IpAddr
|
this.Data["ipAddr"] = dnsInfo.IpAddr
|
||||||
|
this.Data["ipAddrId"] = dnsInfo.NodeIPAddressId
|
||||||
this.Data["routes"] = domainutils.ConvertRoutesToMaps(dnsInfo)
|
this.Data["routes"] = domainutils.ConvertRoutesToMaps(dnsInfo)
|
||||||
this.Data["domainId"] = dnsInfo.DnsDomainId
|
this.Data["domainId"] = dnsInfo.DnsDomainId
|
||||||
this.Data["domainName"] = dnsInfo.DnsDomainName
|
this.Data["domainName"] = dnsInfo.DnsDomainName
|
||||||
|
|
||||||
// 读取所有线路
|
// 读取所有线路
|
||||||
allRouteMaps := []maps.Map{}
|
var allRouteMaps = []maps.Map{}
|
||||||
if dnsInfo.DnsDomainId > 0 {
|
if dnsInfo.DnsDomainId > 0 {
|
||||||
routesResp, err := this.RPC().DNSDomainRPC().FindAllDNSDomainRoutes(this.AdminContext(), &pb.FindAllDNSDomainRoutesRequest{DnsDomainId: dnsInfo.DnsDomainId})
|
routesResp, err := this.RPC().DNSDomainRPC().FindAllDNSDomainRoutes(this.AdminContext(), &pb.FindAllDNSDomainRoutesRequest{DnsDomainId: dnsInfo.DnsDomainId})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -75,6 +78,7 @@ func (this *UpdateNodePopupAction) RunGet(params struct {
|
|||||||
func (this *UpdateNodePopupAction) RunPost(params struct {
|
func (this *UpdateNodePopupAction) RunPost(params struct {
|
||||||
NodeId int64
|
NodeId int64
|
||||||
IpAddr string
|
IpAddr string
|
||||||
|
IpAddrId int64
|
||||||
DomainId int64
|
DomainId int64
|
||||||
DnsRoutesJSON []byte
|
DnsRoutesJSON []byte
|
||||||
|
|
||||||
@@ -84,7 +88,7 @@ func (this *UpdateNodePopupAction) RunPost(params struct {
|
|||||||
// 操作日志
|
// 操作日志
|
||||||
defer this.CreateLog(oplogs.LevelInfo, "修改节点 %d 的DNS设置", params.NodeId)
|
defer this.CreateLog(oplogs.LevelInfo, "修改节点 %d 的DNS设置", params.NodeId)
|
||||||
|
|
||||||
routes := []string{}
|
var routes = []string{}
|
||||||
if len(params.DnsRoutesJSON) > 0 {
|
if len(params.DnsRoutesJSON) > 0 {
|
||||||
err := json.Unmarshal(params.DnsRoutesJSON, &routes)
|
err := json.Unmarshal(params.DnsRoutesJSON, &routes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -103,10 +107,11 @@ func (this *UpdateNodePopupAction) RunPost(params struct {
|
|||||||
|
|
||||||
// 执行修改
|
// 执行修改
|
||||||
_, err := this.RPC().NodeRPC().UpdateNodeDNS(this.AdminContext(), &pb.UpdateNodeDNSRequest{
|
_, err := this.RPC().NodeRPC().UpdateNodeDNS(this.AdminContext(), &pb.UpdateNodeDNSRequest{
|
||||||
NodeId: params.NodeId,
|
NodeId: params.NodeId,
|
||||||
IpAddr: params.IpAddr,
|
IpAddr: params.IpAddr,
|
||||||
DnsDomainId: params.DomainId,
|
NodeIPAddressId: params.IpAddrId,
|
||||||
Routes: routes,
|
DnsDomainId: params.DomainId,
|
||||||
|
Routes: routes,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
this.ErrorPage(err)
|
this.ErrorPage(err)
|
||||||
|
|||||||
@@ -73,6 +73,12 @@ func (this *CreatePopupAction) RunPost(params struct {
|
|||||||
ParamCustomHTTPURL string
|
ParamCustomHTTPURL string
|
||||||
ParamCustomHTTPSecret string
|
ParamCustomHTTPSecret string
|
||||||
|
|
||||||
|
// EdgeDNS API
|
||||||
|
ParamEdgeDNSAPIRole string
|
||||||
|
ParamEdgeDNSAPIHost string
|
||||||
|
ParamEdgeDNSAPIAccessKeyId string
|
||||||
|
ParamEdgeDNSAPIAccessKeySecret string
|
||||||
|
|
||||||
Must *actions.Must
|
Must *actions.Must
|
||||||
CSRF *actionutils.CSRF
|
CSRF *actionutils.CSRF
|
||||||
}) {
|
}) {
|
||||||
@@ -121,6 +127,20 @@ func (this *CreatePopupAction) RunPost(params struct {
|
|||||||
Email("请输入正确格式的邮箱地址")
|
Email("请输入正确格式的邮箱地址")
|
||||||
apiParams["apiKey"] = params.ParamCloudFlareAPIKey
|
apiParams["apiKey"] = params.ParamCloudFlareAPIKey
|
||||||
apiParams["email"] = params.ParamCloudFlareEmail
|
apiParams["email"] = params.ParamCloudFlareEmail
|
||||||
|
case "edgeDNSAPI":
|
||||||
|
params.Must.
|
||||||
|
Field("paramEdgeDNSAPIHost", params.ParamEdgeDNSAPIHost).
|
||||||
|
Require("请输入API地址").
|
||||||
|
Field("paramEdgeDNSAPIRole", params.ParamEdgeDNSAPIRole).
|
||||||
|
Require("请选择AccessKey类型").
|
||||||
|
Field("paramEdgeDNSAPIAccessKeyId", params.ParamEdgeDNSAPIAccessKeyId).
|
||||||
|
Require("请输入AccessKey ID").
|
||||||
|
Field("paramEdgeDNSAPIAccessKeySecret", params.ParamEdgeDNSAPIAccessKeySecret).
|
||||||
|
Require("请输入AccessKey密钥")
|
||||||
|
apiParams["host"] = params.ParamEdgeDNSAPIHost
|
||||||
|
apiParams["role"] = params.ParamEdgeDNSAPIRole
|
||||||
|
apiParams["accessKeyId"] = params.ParamEdgeDNSAPIAccessKeyId
|
||||||
|
apiParams["accessKeySecret"] = params.ParamEdgeDNSAPIAccessKeySecret
|
||||||
case "customHTTP":
|
case "customHTTP":
|
||||||
params.Must.
|
params.Must.
|
||||||
Field("paramCustomHTTPURL", params.ParamCustomHTTPURL).
|
Field("paramCustomHTTPURL", params.ParamCustomHTTPURL).
|
||||||
|
|||||||
@@ -59,20 +59,20 @@ func (this *IndexAction) RunGet(params struct {
|
|||||||
}
|
}
|
||||||
var providerMaps = []maps.Map{}
|
var providerMaps = []maps.Map{}
|
||||||
for _, provider := range providersResp.DnsProviders {
|
for _, provider := range providersResp.DnsProviders {
|
||||||
dataUpdatedTime := ""
|
var dataUpdatedTime = ""
|
||||||
if provider.DataUpdatedAt > 0 {
|
if provider.DataUpdatedAt > 0 {
|
||||||
dataUpdatedTime = timeutil.FormatTime("Y-m-d H:i:s", provider.DataUpdatedAt)
|
dataUpdatedTime = timeutil.FormatTime("Y-m-d H:i:s", provider.DataUpdatedAt)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 域名
|
// 域名
|
||||||
countDomainsResp, err := this.RPC().DNSDomainRPC().CountAllEnabledDNSDomainsWithDNSProviderId(this.AdminContext(), &pb.CountAllEnabledDNSDomainsWithDNSProviderIdRequest{
|
countDomainsResp, err := this.RPC().DNSDomainRPC().CountAllDNSDomainsWithDNSProviderId(this.AdminContext(), &pb.CountAllDNSDomainsWithDNSProviderIdRequest{
|
||||||
DnsProviderId: provider.Id,
|
DnsProviderId: provider.Id,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
this.ErrorPage(err)
|
this.ErrorPage(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
countDomains := countDomainsResp.Count
|
var countDomains = countDomainsResp.Count
|
||||||
|
|
||||||
providerMaps = append(providerMaps, maps.Map{
|
providerMaps = append(providerMaps, maps.Map{
|
||||||
"id": provider.Id,
|
"id": provider.Id,
|
||||||
|
|||||||
@@ -18,19 +18,24 @@ func (this *ProviderAction) Init() {
|
|||||||
|
|
||||||
func (this *ProviderAction) RunGet(params struct {
|
func (this *ProviderAction) RunGet(params struct {
|
||||||
ProviderId int64
|
ProviderId int64
|
||||||
|
Page int
|
||||||
|
Filter string
|
||||||
}) {
|
}) {
|
||||||
|
this.Data["pageNo"] = params.Page
|
||||||
|
this.Data["filter"] = params.Filter
|
||||||
|
|
||||||
providerResp, err := this.RPC().DNSProviderRPC().FindEnabledDNSProvider(this.AdminContext(), &pb.FindEnabledDNSProviderRequest{DnsProviderId: params.ProviderId})
|
providerResp, err := this.RPC().DNSProviderRPC().FindEnabledDNSProvider(this.AdminContext(), &pb.FindEnabledDNSProviderRequest{DnsProviderId: params.ProviderId})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
this.ErrorPage(err)
|
this.ErrorPage(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
provider := providerResp.DnsProvider
|
var provider = providerResp.DnsProvider
|
||||||
if provider == nil {
|
if provider == nil {
|
||||||
this.NotFound("dnsProvider", params.ProviderId)
|
this.NotFound("dnsProvider", params.ProviderId)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
apiParams := maps.Map{}
|
var apiParams = maps.Map{}
|
||||||
if len(provider.ApiParamsJSON) > 0 {
|
if len(provider.ApiParamsJSON) > 0 {
|
||||||
err = json.Unmarshal(provider.ApiParamsJSON, &apiParams)
|
err = json.Unmarshal(provider.ApiParamsJSON, &apiParams)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -55,13 +60,33 @@ func (this *ProviderAction) RunGet(params struct {
|
|||||||
"localEdgeDNS": localEdgeDNSMap,
|
"localEdgeDNS": localEdgeDNSMap,
|
||||||
}
|
}
|
||||||
|
|
||||||
// 域名
|
// 域名数量
|
||||||
domainsResp, err := this.RPC().DNSDomainRPC().FindAllEnabledDNSDomainsWithDNSProviderId(this.AdminContext(), &pb.FindAllEnabledDNSDomainsWithDNSProviderIdRequest{DnsProviderId: provider.Id})
|
countDomainsResp, err := this.RPC().DNSDomainRPC().CountAllDNSDomainsWithDNSProviderId(this.AdminContext(), &pb.CountAllDNSDomainsWithDNSProviderIdRequest{
|
||||||
|
DnsProviderId: params.ProviderId,
|
||||||
|
IsDeleted: params.Filter == "deleted",
|
||||||
|
IsDown: params.Filter == "down",
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
this.ErrorPage(err)
|
this.ErrorPage(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
domainMaps := []maps.Map{}
|
var countDomains = countDomainsResp.Count
|
||||||
|
var page = this.NewPage(countDomains)
|
||||||
|
this.Data["page"] = page.AsHTML()
|
||||||
|
|
||||||
|
// 域名
|
||||||
|
domainsResp, err := this.RPC().DNSDomainRPC().ListBasicDNSDomainsWithDNSProviderId(this.AdminContext(), &pb.ListBasicDNSDomainsWithDNSProviderIdRequest{
|
||||||
|
DnsProviderId: params.ProviderId,
|
||||||
|
IsDeleted: params.Filter == "deleted",
|
||||||
|
IsDown: params.Filter == "down",
|
||||||
|
Offset: page.Offset,
|
||||||
|
Size: page.Size,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var domainMaps = []maps.Map{}
|
||||||
for _, domain := range domainsResp.DnsDomains {
|
for _, domain := range domainsResp.DnsDomains {
|
||||||
dataUpdatedTime := ""
|
dataUpdatedTime := ""
|
||||||
if domain.DataUpdatedAt > 0 {
|
if domain.DataUpdatedAt > 0 {
|
||||||
|
|||||||
@@ -100,6 +100,12 @@ func (this *UpdatePopupAction) RunPost(params struct {
|
|||||||
ParamCustomHTTPURL string
|
ParamCustomHTTPURL string
|
||||||
ParamCustomHTTPSecret string
|
ParamCustomHTTPSecret string
|
||||||
|
|
||||||
|
// EdgeDNS API
|
||||||
|
ParamEdgeDNSAPIHost string
|
||||||
|
ParamEdgeDNSAPIRole string
|
||||||
|
ParamEdgeDNSAPIAccessKeyId string
|
||||||
|
ParamEdgeDNSAPIAccessKeySecret string
|
||||||
|
|
||||||
Must *actions.Must
|
Must *actions.Must
|
||||||
CSRF *actionutils.CSRF
|
CSRF *actionutils.CSRF
|
||||||
}) {
|
}) {
|
||||||
@@ -150,6 +156,20 @@ func (this *UpdatePopupAction) RunPost(params struct {
|
|||||||
Email("请输入正确格式的邮箱地址")
|
Email("请输入正确格式的邮箱地址")
|
||||||
apiParams["apiKey"] = params.ParamCloudFlareAPIKey
|
apiParams["apiKey"] = params.ParamCloudFlareAPIKey
|
||||||
apiParams["email"] = params.ParamCloudFlareEmail
|
apiParams["email"] = params.ParamCloudFlareEmail
|
||||||
|
case "edgeDNSAPI":
|
||||||
|
params.Must.
|
||||||
|
Field("paramEdgeDNSAPIHost", params.ParamEdgeDNSAPIHost).
|
||||||
|
Require("请输入API地址").
|
||||||
|
Field("paramEdgeDNSAPIRole", params.ParamEdgeDNSAPIRole).
|
||||||
|
Require("请选择AccessKey类型").
|
||||||
|
Field("paramEdgeDNSAPIAccessKeyId", params.ParamEdgeDNSAPIAccessKeyId).
|
||||||
|
Require("请输入AccessKey ID").
|
||||||
|
Field("paramEdgeDNSAPIAccessKeySecret", params.ParamEdgeDNSAPIAccessKeySecret).
|
||||||
|
Require("请输入AccessKey密钥")
|
||||||
|
apiParams["host"] = params.ParamEdgeDNSAPIHost
|
||||||
|
apiParams["role"] = params.ParamEdgeDNSAPIRole
|
||||||
|
apiParams["accessKeyId"] = params.ParamEdgeDNSAPIAccessKeyId
|
||||||
|
apiParams["accessKeySecret"] = params.ParamEdgeDNSAPIAccessKeySecret
|
||||||
case "customHTTP":
|
case "customHTTP":
|
||||||
params.Must.
|
params.Must.
|
||||||
Field("paramCustomHTTPURL", params.ParamCustomHTTPURL).
|
Field("paramCustomHTTPURL", params.ParamCustomHTTPURL).
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package acme
|
package acme
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/dns/domains/domainutils"
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/dns/domains/domainutils"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
@@ -25,7 +26,7 @@ func (this *UpdateTaskPopupAction) RunGet(params struct {
|
|||||||
this.ErrorPage(err)
|
this.ErrorPage(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
task := taskResp.AcmeTask
|
var task = taskResp.AcmeTask
|
||||||
if task == nil {
|
if task == nil {
|
||||||
this.NotFound("acmeTask", params.TaskId)
|
this.NotFound("acmeTask", params.TaskId)
|
||||||
return
|
return
|
||||||
@@ -74,7 +75,7 @@ func (this *UpdateTaskPopupAction) RunGet(params struct {
|
|||||||
this.ErrorPage(err)
|
this.ErrorPage(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
providerMaps := []maps.Map{}
|
var providerMaps = []maps.Map{}
|
||||||
for _, provider := range providersResp.DnsProviders {
|
for _, provider := range providersResp.DnsProviders {
|
||||||
providerMaps = append(providerMaps, maps.Map{
|
providerMaps = append(providerMaps, maps.Map{
|
||||||
"id": provider.Id,
|
"id": provider.Id,
|
||||||
@@ -93,7 +94,7 @@ func (this *UpdateTaskPopupAction) RunPost(params struct {
|
|||||||
AcmeUserId int64
|
AcmeUserId int64
|
||||||
DnsProviderId int64
|
DnsProviderId int64
|
||||||
DnsDomain string
|
DnsDomain string
|
||||||
Domains []string
|
DomainsJSON []byte
|
||||||
AutoRenew bool
|
AutoRenew bool
|
||||||
AuthURL string
|
AuthURL string
|
||||||
|
|
||||||
@@ -123,11 +124,20 @@ func (this *UpdateTaskPopupAction) RunPost(params struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(params.Domains) == 0 {
|
var domains = []string{}
|
||||||
|
if len(params.DomainsJSON) > 0 {
|
||||||
|
err := json.Unmarshal(params.DomainsJSON, &domains)
|
||||||
|
if err != nil {
|
||||||
|
this.Fail("解析域名数据失败:" + err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(domains) == 0 {
|
||||||
this.Fail("请输入证书域名列表")
|
this.Fail("请输入证书域名列表")
|
||||||
}
|
}
|
||||||
realDomains := []string{}
|
var realDomains = []string{}
|
||||||
for _, domain := range params.Domains {
|
for _, domain := range domains {
|
||||||
domain = strings.ToLower(domain)
|
domain = strings.ToLower(domain)
|
||||||
if params.AuthType == "dns" {
|
if params.AuthType == "dns" {
|
||||||
if !strings.HasSuffix(domain, "."+dnsDomain) && domain != dnsDomain {
|
if !strings.HasSuffix(domain, "."+dnsDomain) && domain != dnsDomain {
|
||||||
|
|||||||
@@ -15,7 +15,11 @@ func (this *CreatePopupAction) Init() {
|
|||||||
this.Nav("", "", "")
|
this.Nav("", "", "")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *CreatePopupAction) RunGet(params struct{}) {
|
func (this *CreatePopupAction) RunGet(params struct {
|
||||||
|
ProviderCode string
|
||||||
|
}) {
|
||||||
|
this.Data["providerCode"] = params.ProviderCode
|
||||||
|
|
||||||
// 服务商
|
// 服务商
|
||||||
providersResp, err := this.RPC().ACMEProviderRPC().FindAllACMEProviders(this.AdminContext(), &pb.FindAllACMEProvidersRequest{})
|
providersResp, err := this.RPC().ACMEProviderRPC().FindAllACMEProviders(this.AdminContext(), &pb.FindAllACMEProvidersRequest{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -30,9 +30,10 @@ func (this *SelectPopupAction) RunGet(params struct {
|
|||||||
// TODO 列出常用和最新的证书供用户选择
|
// TODO 列出常用和最新的证书供用户选择
|
||||||
|
|
||||||
this.Data["keyword"] = params.Keyword
|
this.Data["keyword"] = params.Keyword
|
||||||
|
this.Data["selectedCertIds"] = params.SelectedCertIds
|
||||||
|
|
||||||
// 已经选择的证书
|
// 已经选择的证书
|
||||||
selectedCertIds := []string{}
|
var selectedCertIds = []string{}
|
||||||
if len(params.SelectedCertIds) > 0 {
|
if len(params.SelectedCertIds) > 0 {
|
||||||
selectedCertIds = strings.Split(params.SelectedCertIds, ",")
|
selectedCertIds = strings.Split(params.SelectedCertIds, ",")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import (
|
|||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||||
"github.com/iwind/TeaGo/actions"
|
"github.com/iwind/TeaGo/actions"
|
||||||
"github.com/iwind/TeaGo/maps"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -65,7 +64,7 @@ func (this *IndexAction) RunPost(params struct {
|
|||||||
DefaultDomain string
|
DefaultDomain string
|
||||||
}) {
|
}) {
|
||||||
// 创建日志
|
// 创建日志
|
||||||
defer this.CreateLog(oplogs.LevelInfo, "保存代理服务全局配置")
|
defer this.CreateLog(oplogs.LevelInfo, "保存网站服务全局配置")
|
||||||
|
|
||||||
if len(params.GlobalConfigJSON) == 0 {
|
if len(params.GlobalConfigJSON) == 0 {
|
||||||
this.Fail("错误的配置信息,请刷新当前页面后重试")
|
this.Fail("错误的配置信息,请刷新当前页面后重试")
|
||||||
@@ -84,27 +83,6 @@ func (this *IndexAction) RunPost(params struct {
|
|||||||
allowMismatchDomains = append(allowMismatchDomains, domain)
|
allowMismatchDomains = append(allowMismatchDomains, domain)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
globalConfig.HTTPAll.AllowMismatchDomains = allowMismatchDomains
|
|
||||||
|
|
||||||
// 不匹配域名的动作
|
|
||||||
switch params.DomainMismatchAction {
|
|
||||||
case "close":
|
|
||||||
globalConfig.HTTPAll.DomainMismatchAction = &serverconfigs.DomainMismatchAction{
|
|
||||||
Code: "close",
|
|
||||||
Options: nil,
|
|
||||||
}
|
|
||||||
case "page":
|
|
||||||
if params.DomainMismatchActionPageStatusCode <= 0 {
|
|
||||||
params.DomainMismatchActionPageStatusCode = 404
|
|
||||||
}
|
|
||||||
globalConfig.HTTPAll.DomainMismatchAction = &serverconfigs.DomainMismatchAction{
|
|
||||||
Code: "page",
|
|
||||||
Options: maps.Map{
|
|
||||||
"statusCode": params.DomainMismatchActionPageStatusCode,
|
|
||||||
"contentHTML": params.DomainMismatchActionPageContentHTML,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TCP端口范围
|
// TCP端口范围
|
||||||
if params.TcpAllPortRangeMin < 1024 {
|
if params.TcpAllPortRangeMin < 1024 {
|
||||||
|
|||||||
@@ -80,9 +80,9 @@ func (this *UpdateIPPopupAction) RunPost(params struct {
|
|||||||
|
|
||||||
var ipToLong uint64
|
var ipToLong uint64
|
||||||
if len(params.IpTo) > 0 && !utils.IsIPv4(params.IpTo) {
|
if len(params.IpTo) > 0 && !utils.IsIPv4(params.IpTo) {
|
||||||
ipToLong = utils.IP2Long(params.IpTo)
|
|
||||||
this.Fail("请输入正确的结束IP")
|
this.Fail("请输入正确的结束IP")
|
||||||
}
|
}
|
||||||
|
ipToLong = utils.IP2Long(params.IpTo)
|
||||||
|
|
||||||
if ipFromLong > 0 && ipToLong > 0 && ipFromLong > ipToLong {
|
if ipFromLong > 0 && ipToLong > 0 && ipFromLong > ipToLong {
|
||||||
params.IpTo, params.IpFrom = params.IpFrom, params.IpTo
|
params.IpTo, params.IpFrom = params.IpFrom, params.IpTo
|
||||||
|
|||||||
@@ -109,6 +109,10 @@ func (this *SettingAction) RunPost(params struct {
|
|||||||
FollowRedirects: reverseProxyConfig.FollowRedirects,
|
FollowRedirects: reverseProxyConfig.FollowRedirects,
|
||||||
ProxyProtocolJSON: proxyProtocolJSON,
|
ProxyProtocolJSON: proxyProtocolJSON,
|
||||||
})
|
})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
this.Success()
|
this.Success()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,5 +24,4 @@ func (this *IndexAction) RunGet(params struct {
|
|||||||
} else {
|
} else {
|
||||||
this.RedirectURL("/servers/groups/group/settings/httpReverseProxy?groupId=" + types.String(params.GroupId))
|
this.RedirectURL("/servers/groups/group/settings/httpReverseProxy?groupId=" + types.String(params.GroupId))
|
||||||
}
|
}
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -109,6 +109,10 @@ func (this *SettingAction) RunPost(params struct {
|
|||||||
FollowRedirects: reverseProxyConfig.FollowRedirects,
|
FollowRedirects: reverseProxyConfig.FollowRedirects,
|
||||||
ProxyProtocolJSON: proxyProtocolJSON,
|
ProxyProtocolJSON: proxyProtocolJSON,
|
||||||
})
|
})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
this.Success()
|
this.Success()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -96,8 +96,12 @@ func (this *SettingAction) RunPost(params struct {
|
|||||||
StripPrefix: reverseProxyConfig.StripPrefix,
|
StripPrefix: reverseProxyConfig.StripPrefix,
|
||||||
AutoFlush: reverseProxyConfig.AutoFlush,
|
AutoFlush: reverseProxyConfig.AutoFlush,
|
||||||
AddHeaders: reverseProxyConfig.AddHeaders,
|
AddHeaders: reverseProxyConfig.AddHeaders,
|
||||||
FollowRedirects: reverseProxyConfig.FollowRedirects,
|
FollowRedirects: reverseProxyConfig.FollowRedirects,
|
||||||
})
|
})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
this.Success()
|
this.Success()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -79,9 +79,9 @@ func (this *UpdateIPPopupAction) RunPost(params struct {
|
|||||||
|
|
||||||
var ipToLong uint64
|
var ipToLong uint64
|
||||||
if len(params.IpTo) > 0 && !utils.IsIPv4(params.IpTo) {
|
if len(params.IpTo) > 0 && !utils.IsIPv4(params.IpTo) {
|
||||||
ipToLong = utils.IP2Long(params.IpTo)
|
|
||||||
this.Fail("请输入正确的结束IP")
|
this.Fail("请输入正确的结束IP")
|
||||||
}
|
}
|
||||||
|
ipToLong = utils.IP2Long(params.IpTo)
|
||||||
|
|
||||||
if ipFromLong > 0 && ipToLong > 0 && ipFromLong > ipToLong {
|
if ipFromLong > 0 && ipToLong > 0 && ipFromLong > ipToLong {
|
||||||
params.IpTo, params.IpFrom = params.IpFrom, params.IpTo
|
params.IpTo, params.IpFrom = params.IpFrom, params.IpTo
|
||||||
|
|||||||
26
internal/web/actions/default/servers/headers/options.go
Normal file
26
internal/web/actions/default/servers/headers/options.go
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||||
|
|
||||||
|
package headers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||||
|
)
|
||||||
|
|
||||||
|
type OptionsAction struct {
|
||||||
|
actionutils.ParentAction
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *OptionsAction) RunPost(params struct {
|
||||||
|
Type string
|
||||||
|
}) {
|
||||||
|
if params.Type == "request" {
|
||||||
|
this.Data["headers"] = serverconfigs.AllHTTPCommonRequestHeaders
|
||||||
|
} else if params.Type == "response" {
|
||||||
|
this.Data["headers"] = serverconfigs.AllHTTPCommonResponseHeaders
|
||||||
|
} else {
|
||||||
|
this.Data["headers"] = []string{}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Success()
|
||||||
|
}
|
||||||
@@ -3,7 +3,6 @@ package servers
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
|
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/utils/numberutils"
|
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/configutils"
|
"github.com/TeaOSLab/EdgeCommon/pkg/configutils"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
||||||
@@ -90,15 +89,16 @@ func (this *IndexAction) RunGet(params struct {
|
|||||||
|
|
||||||
// 服务列表
|
// 服务列表
|
||||||
serversResp, err := this.RPC().ServerRPC().ListEnabledServersMatch(this.AdminContext(), &pb.ListEnabledServersMatchRequest{
|
serversResp, err := this.RPC().ServerRPC().ListEnabledServersMatch(this.AdminContext(), &pb.ListEnabledServersMatchRequest{
|
||||||
Offset: page.Offset,
|
Offset: page.Offset,
|
||||||
Size: page.Size,
|
Size: page.Size,
|
||||||
NodeClusterId: params.ClusterId,
|
NodeClusterId: params.ClusterId,
|
||||||
ServerGroupId: params.GroupId,
|
ServerGroupId: params.GroupId,
|
||||||
Keyword: params.Keyword,
|
Keyword: params.Keyword,
|
||||||
AuditingFlag: params.AuditingFlag,
|
AuditingFlag: params.AuditingFlag,
|
||||||
TrafficOutDesc: params.TrafficOutOrder == "desc",
|
TrafficOutDesc: params.TrafficOutOrder == "desc",
|
||||||
TrafficOutAsc: params.TrafficOutOrder == "asc",
|
TrafficOutAsc: params.TrafficOutOrder == "asc",
|
||||||
UserId: params.UserId,
|
UserId: params.UserId,
|
||||||
|
IgnoreServerNames: true,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
this.ErrorPage(err)
|
this.ErrorPage(err)
|
||||||
@@ -176,27 +176,35 @@ func (this *IndexAction) RunGet(params struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 域名列表
|
// 域名列表
|
||||||
var serverNames = []*serverconfigs.ServerNameConfig{}
|
|
||||||
if server.IsAuditing || (server.AuditingResult != nil && !server.AuditingResult.IsOk) {
|
if server.IsAuditing || (server.AuditingResult != nil && !server.AuditingResult.IsOk) {
|
||||||
server.ServerNamesJSON = server.AuditingServerNamesJSON
|
server.ServerNamesJSON = server.AuditingServerNamesJSON
|
||||||
|
|
||||||
|
if len(config.ServerNames) == 0 {
|
||||||
|
// 审核中的域名
|
||||||
|
if len(server.ServerNamesJSON) > 0 {
|
||||||
|
var serverNames = []*serverconfigs.ServerNameConfig{}
|
||||||
|
err = json.Unmarshal(server.ServerNamesJSON, &serverNames)
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
config.ServerNames = serverNames
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
var auditingIsOk = true
|
var auditingIsOk = true
|
||||||
if !server.IsAuditing && server.AuditingResult != nil && !server.AuditingResult.IsOk {
|
if !server.IsAuditing && server.AuditingResult != nil && !server.AuditingResult.IsOk {
|
||||||
auditingIsOk = false
|
auditingIsOk = false
|
||||||
}
|
}
|
||||||
if len(server.ServerNamesJSON) > 0 {
|
var firstServerName = ""
|
||||||
err = json.Unmarshal(server.ServerNamesJSON, &serverNames)
|
for _, serverNameConfig := range config.ServerNames {
|
||||||
if err != nil {
|
if len(serverNameConfig.Name) > 0 {
|
||||||
this.ErrorPage(err)
|
firstServerName = serverNameConfig.Name
|
||||||
return
|
break
|
||||||
}
|
}
|
||||||
}
|
if len(serverNameConfig.SubNames) > 0 {
|
||||||
var countServerNames = 0
|
firstServerName = serverNameConfig.SubNames[0]
|
||||||
for _, serverName := range serverNames {
|
break
|
||||||
if len(serverName.SubNames) == 0 {
|
|
||||||
countServerNames++
|
|
||||||
} else {
|
|
||||||
countServerNames += len(serverName.SubNames)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -216,9 +224,9 @@ func (this *IndexAction) RunGet(params struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 统计数据
|
// 统计数据
|
||||||
var bandwidth = ""
|
var bandwidthBits int64 = 0
|
||||||
if server.BandwidthBytes > 0 {
|
if server.BandwidthBytes > 0 {
|
||||||
bandwidth = numberutils.FormatBytes(server.BandwidthBytes)
|
bandwidthBits = server.BandwidthBytes * 8
|
||||||
}
|
}
|
||||||
|
|
||||||
serverMaps = append(serverMaps, maps.Map{
|
serverMaps = append(serverMaps, maps.Map{
|
||||||
@@ -232,13 +240,13 @@ func (this *IndexAction) RunGet(params struct {
|
|||||||
"ports": portMaps,
|
"ports": portMaps,
|
||||||
"serverTypeName": serverconfigs.FindServerType(server.Type).GetString("name"),
|
"serverTypeName": serverconfigs.FindServerType(server.Type).GetString("name"),
|
||||||
"groups": groupMaps,
|
"groups": groupMaps,
|
||||||
"serverNames": serverNames,
|
"firstServerName": firstServerName,
|
||||||
"countServerNames": countServerNames,
|
"countServerNames": server.CountServerNames,
|
||||||
"isAuditing": server.IsAuditing,
|
"isAuditing": server.IsAuditing,
|
||||||
"auditingIsOk": auditingIsOk,
|
"auditingIsOk": auditingIsOk,
|
||||||
"user": userMap,
|
"user": userMap,
|
||||||
"auditingTime": auditingTime,
|
"auditingTime": auditingTime,
|
||||||
"bandwidth": bandwidth,
|
"bandwidthBits": bandwidthBits,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
this.Data["servers"] = serverMaps
|
this.Data["servers"] = serverMaps
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package servers
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
|
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/headers"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/users"
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/users"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
|
||||||
"github.com/iwind/TeaGo"
|
"github.com/iwind/TeaGo"
|
||||||
@@ -26,10 +27,13 @@ func init() {
|
|||||||
Get("/serverNamesPopup", new(ServerNamesPopupAction)).
|
Get("/serverNamesPopup", new(ServerNamesPopupAction)).
|
||||||
Post("/status", new(StatusAction)).
|
Post("/status", new(StatusAction)).
|
||||||
|
|
||||||
//
|
// user
|
||||||
Post("/users/options", new(users.OptionsAction)).
|
Post("/users/options", new(users.OptionsAction)).
|
||||||
Post("/users/plans", new(users.PlansAction)).
|
Post("/users/plans", new(users.PlansAction)).
|
||||||
|
|
||||||
|
// header
|
||||||
|
Post("/headers/options", new(headers.OptionsAction)).
|
||||||
|
|
||||||
//
|
//
|
||||||
EndAll()
|
EndAll()
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -97,9 +97,9 @@ func (this *CreateIPPopupAction) RunPost(params struct {
|
|||||||
|
|
||||||
var ipToLong uint64
|
var ipToLong uint64
|
||||||
if len(params.IpTo) > 0 && !utils.IsIPv4(params.IpTo) {
|
if len(params.IpTo) > 0 && !utils.IsIPv4(params.IpTo) {
|
||||||
ipToLong = utils.IP2Long(params.IpTo)
|
|
||||||
this.Fail("请输入正确的结束IP")
|
this.Fail("请输入正确的结束IP")
|
||||||
}
|
}
|
||||||
|
ipToLong = utils.IP2Long(params.IpTo)
|
||||||
|
|
||||||
if ipFromLong > 0 && ipToLong > 0 && ipFromLong > ipToLong {
|
if ipFromLong > 0 && ipToLong > 0 && ipFromLong > ipToLong {
|
||||||
params.IpTo, params.IpFrom = params.IpFrom, params.IpTo
|
params.IpTo, params.IpFrom = params.IpFrom, params.IpTo
|
||||||
|
|||||||
@@ -21,21 +21,21 @@ func (this *IndexAction) Init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (this *IndexAction) RunGet(params struct {
|
func (this *IndexAction) RunGet(params struct {
|
||||||
Ip string
|
Keyword string
|
||||||
GlobalOnly bool
|
GlobalOnly bool
|
||||||
Unread bool
|
Unread bool
|
||||||
EventLevel string
|
EventLevel string
|
||||||
ListType string
|
ListType string
|
||||||
}) {
|
}) {
|
||||||
this.Data["type"] = ""
|
this.Data["type"] = ""
|
||||||
this.Data["ip"] = params.Ip
|
this.Data["keyword"] = params.Keyword
|
||||||
this.Data["globalOnly"] = params.GlobalOnly
|
this.Data["globalOnly"] = params.GlobalOnly
|
||||||
this.Data["unread"] = params.Unread
|
this.Data["unread"] = params.Unread
|
||||||
this.Data["eventLevel"] = params.EventLevel
|
this.Data["eventLevel"] = params.EventLevel
|
||||||
this.Data["listType"] = params.ListType
|
this.Data["listType"] = params.ListType
|
||||||
|
|
||||||
countUnreadResp, err := this.RPC().IPItemRPC().CountAllEnabledIPItems(this.AdminContext(), &pb.CountAllEnabledIPItemsRequest{
|
countUnreadResp, err := this.RPC().IPItemRPC().CountAllEnabledIPItems(this.AdminContext(), &pb.CountAllEnabledIPItemsRequest{
|
||||||
Ip: params.Ip,
|
Keyword: params.Keyword,
|
||||||
GlobalOnly: params.GlobalOnly,
|
GlobalOnly: params.GlobalOnly,
|
||||||
Unread: true,
|
Unread: true,
|
||||||
EventLevel: params.EventLevel,
|
EventLevel: params.EventLevel,
|
||||||
@@ -48,7 +48,7 @@ func (this *IndexAction) RunGet(params struct {
|
|||||||
this.Data["countUnread"] = countUnreadResp.Count
|
this.Data["countUnread"] = countUnreadResp.Count
|
||||||
|
|
||||||
countResp, err := this.RPC().IPItemRPC().CountAllEnabledIPItems(this.AdminContext(), &pb.CountAllEnabledIPItemsRequest{
|
countResp, err := this.RPC().IPItemRPC().CountAllEnabledIPItems(this.AdminContext(), &pb.CountAllEnabledIPItemsRequest{
|
||||||
Ip: params.Ip,
|
Keyword: params.Keyword,
|
||||||
GlobalOnly: params.GlobalOnly,
|
GlobalOnly: params.GlobalOnly,
|
||||||
Unread: params.Unread,
|
Unread: params.Unread,
|
||||||
EventLevel: params.EventLevel,
|
EventLevel: params.EventLevel,
|
||||||
@@ -63,7 +63,7 @@ func (this *IndexAction) RunGet(params struct {
|
|||||||
this.Data["page"] = page.AsHTML()
|
this.Data["page"] = page.AsHTML()
|
||||||
|
|
||||||
itemsResp, err := this.RPC().IPItemRPC().ListAllEnabledIPItems(this.AdminContext(), &pb.ListAllEnabledIPItemsRequest{
|
itemsResp, err := this.RPC().IPItemRPC().ListAllEnabledIPItems(this.AdminContext(), &pb.ListAllEnabledIPItemsRequest{
|
||||||
Ip: params.Ip,
|
Keyword: params.Keyword,
|
||||||
GlobalOnly: params.GlobalOnly,
|
GlobalOnly: params.GlobalOnly,
|
||||||
Unread: params.Unread,
|
Unread: params.Unread,
|
||||||
EventLevel: params.EventLevel,
|
EventLevel: params.EventLevel,
|
||||||
|
|||||||
@@ -79,9 +79,9 @@ func (this *UpdateIPPopupAction) RunPost(params struct {
|
|||||||
|
|
||||||
var ipToLong uint64
|
var ipToLong uint64
|
||||||
if len(params.IpTo) > 0 && !utils.IsIPv4(params.IpTo) {
|
if len(params.IpTo) > 0 && !utils.IsIPv4(params.IpTo) {
|
||||||
ipToLong = utils.IP2Long(params.IpTo)
|
|
||||||
this.Fail("请输入正确的结束IP")
|
this.Fail("请输入正确的结束IP")
|
||||||
}
|
}
|
||||||
|
ipToLong = utils.IP2Long(params.IpTo)
|
||||||
|
|
||||||
if ipFromLong > 0 && ipToLong > 0 && ipFromLong > ipToLong {
|
if ipFromLong > 0 && ipToLong > 0 && ipFromLong > ipToLong {
|
||||||
params.IpTo, params.IpFrom = params.IpFrom, params.IpTo
|
params.IpTo, params.IpFrom = params.IpFrom, params.IpTo
|
||||||
|
|||||||
@@ -41,9 +41,6 @@ func (this *UpdateRefsAction) RunPost(params struct {
|
|||||||
|
|
||||||
// 校验配置
|
// 校验配置
|
||||||
var cacheConfig = webConfig.Cache
|
var cacheConfig = webConfig.Cache
|
||||||
if webConfig == nil {
|
|
||||||
this.Success()
|
|
||||||
}
|
|
||||||
|
|
||||||
var refs = []*serverconfigs.HTTPCacheRef{}
|
var refs = []*serverconfigs.HTTPCacheRef{}
|
||||||
err = json.Unmarshal(params.RefsJSON, &refs)
|
err = json.Unmarshal(params.RefsJSON, &refs)
|
||||||
|
|||||||
@@ -19,8 +19,10 @@ func (this *CreateDeletePopupAction) Init() {
|
|||||||
|
|
||||||
func (this *CreateDeletePopupAction) RunGet(params struct {
|
func (this *CreateDeletePopupAction) RunGet(params struct {
|
||||||
HeaderPolicyId int64
|
HeaderPolicyId int64
|
||||||
|
Type string
|
||||||
}) {
|
}) {
|
||||||
this.Data["headerPolicyId"] = params.HeaderPolicyId
|
this.Data["headerPolicyId"] = params.HeaderPolicyId
|
||||||
|
this.Data["type"] = params.Type
|
||||||
|
|
||||||
this.Show()
|
this.Show()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
|
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
|
||||||
"github.com/iwind/TeaGo/actions"
|
"github.com/iwind/TeaGo/actions"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
type CreateSetPopupAction struct {
|
type CreateSetPopupAction struct {
|
||||||
@@ -45,6 +46,8 @@ func (this *CreateSetPopupAction) RunPost(params struct {
|
|||||||
// 日志
|
// 日志
|
||||||
defer this.CreateLog(oplogs.LevelInfo, "设置请求Header,HeaderPolicyId:%d, Name:%s, Value:%s", params.HeaderPolicyId, params.Name, params.Value)
|
defer this.CreateLog(oplogs.LevelInfo, "设置请求Header,HeaderPolicyId:%d, Name:%s, Value:%s", params.HeaderPolicyId, params.Name, params.Value)
|
||||||
|
|
||||||
|
params.Name = strings.TrimSuffix(params.Name, ":")
|
||||||
|
|
||||||
params.Must.
|
params.Must.
|
||||||
Field("name", params.Name).
|
Field("name", params.Name).
|
||||||
Require("请输入Header名称")
|
Require("请输入Header名称")
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import (
|
|||||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
|
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
|
||||||
)
|
)
|
||||||
|
|
||||||
// 删除Header
|
// DeleteAction 删除Header
|
||||||
type DeleteAction struct {
|
type DeleteAction struct {
|
||||||
actionutils.ParentAction
|
actionutils.ParentAction
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
|
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
|
||||||
"github.com/iwind/TeaGo/actions"
|
"github.com/iwind/TeaGo/actions"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
type UpdateSetPopupAction struct {
|
type UpdateSetPopupAction struct {
|
||||||
@@ -60,6 +61,8 @@ func (this *UpdateSetPopupAction) RunPost(params struct {
|
|||||||
// 日志
|
// 日志
|
||||||
defer this.CreateLog(oplogs.LevelInfo, "修改设置请求Header,HeaderPolicyId:%d, Name:%s, Value:%s", params.HeaderId, params.Name, params.Value)
|
defer this.CreateLog(oplogs.LevelInfo, "修改设置请求Header,HeaderPolicyId:%d, Name:%s, Value:%s", params.HeaderId, params.Name, params.Value)
|
||||||
|
|
||||||
|
params.Name = strings.TrimSuffix(params.Name, ":")
|
||||||
|
|
||||||
params.Must.
|
params.Must.
|
||||||
Field("name", params.Name).
|
Field("name", params.Name).
|
||||||
Require("请输入Header名称")
|
Require("请输入Header名称")
|
||||||
|
|||||||
@@ -65,34 +65,7 @@ func (this *IndexAction) RunGet(params struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 套餐
|
// 套餐
|
||||||
var userPlanMap = maps.Map{"id": server.UserPlanId, "dayTo": "", "plan": maps.Map{}}
|
this.initUserPlan(server)
|
||||||
if server.UserPlanId > 0 {
|
|
||||||
userPlanResp, err := this.RPC().UserPlanRPC().FindEnabledUserPlan(this.AdminContext(), &pb.FindEnabledUserPlanRequest{UserPlanId: server.UserPlanId})
|
|
||||||
if err != nil {
|
|
||||||
this.ErrorPage(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
var userPlan = userPlanResp.UserPlan
|
|
||||||
if userPlan != nil {
|
|
||||||
planResp, err := this.RPC().PlanRPC().FindEnabledPlan(this.AdminContext(), &pb.FindEnabledPlanRequest{PlanId: userPlan.PlanId})
|
|
||||||
if err != nil {
|
|
||||||
this.ErrorPage(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
var plan = planResp.Plan
|
|
||||||
if plan != nil {
|
|
||||||
userPlanMap = maps.Map{
|
|
||||||
"id": userPlan.Id,
|
|
||||||
"dayTo": userPlan.DayTo,
|
|
||||||
"plan": maps.Map{
|
|
||||||
"id": plan.Id,
|
|
||||||
"name": plan.Name,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.Data["userPlan"] = userPlanMap
|
|
||||||
|
|
||||||
// 集群
|
// 集群
|
||||||
clusterId := int64(0)
|
clusterId := int64(0)
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||||
|
//go:build !plus
|
||||||
|
|
||||||
|
package settings
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
|
"github.com/iwind/TeaGo/maps"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (this *IndexAction) initUserPlan(server *pb.Server) {
|
||||||
|
var userPlanMap = maps.Map{"id": server.UserPlanId, "dayTo": "", "plan": maps.Map{}}
|
||||||
|
this.Data["userPlan"] = userPlanMap
|
||||||
|
}
|
||||||
@@ -103,6 +103,12 @@ func (this *LocationHelper) createMenus(serverIdString string, locationIdString
|
|||||||
"isActive": secondMenuItem == "access",
|
"isActive": secondMenuItem == "access",
|
||||||
"isOn": locationConfig != nil && locationConfig.Web != nil && locationConfig.Web.Auth != nil && locationConfig.Web.Auth.IsPrior,
|
"isOn": locationConfig != nil && locationConfig.Web != nil && locationConfig.Web.Auth != nil && locationConfig.Web.Auth.IsPrior,
|
||||||
})
|
})
|
||||||
|
menuItems = append(menuItems, maps.Map{
|
||||||
|
"name": "防盗链",
|
||||||
|
"url": "/servers/server/settings/locations/referers?serverId=" + serverIdString + "&locationId=" + locationIdString,
|
||||||
|
"isActive": secondMenuItem == "referer",
|
||||||
|
"isOn": locationConfig.Web != nil && locationConfig.Web.Referers != nil && locationConfig.Web.Referers.IsPrior,
|
||||||
|
})
|
||||||
menuItems = append(menuItems, maps.Map{
|
menuItems = append(menuItems, maps.Map{
|
||||||
"name": "字符编码",
|
"name": "字符编码",
|
||||||
"url": "/servers/server/settings/locations/charset?serverId=" + serverIdString + "&locationId=" + locationIdString,
|
"url": "/servers/server/settings/locations/charset?serverId=" + serverIdString + "&locationId=" + locationIdString,
|
||||||
|
|||||||
@@ -0,0 +1,68 @@
|
|||||||
|
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||||
|
|
||||||
|
package uam
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||||
|
"github.com/iwind/TeaGo/actions"
|
||||||
|
)
|
||||||
|
|
||||||
|
type IndexAction struct {
|
||||||
|
actionutils.ParentAction
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *IndexAction) Init() {
|
||||||
|
this.Nav("", "setting", "index")
|
||||||
|
this.SecondMenu("referer")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *IndexAction) RunGet(params struct {
|
||||||
|
LocationId int64
|
||||||
|
}) {
|
||||||
|
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithLocationId(this.AdminContext(), params.LocationId)
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Data["webId"] = webConfig.Id
|
||||||
|
|
||||||
|
var referersConfig = webConfig.Referers
|
||||||
|
if referersConfig == nil {
|
||||||
|
referersConfig = &serverconfigs.ReferersConfig{
|
||||||
|
IsPrior: false,
|
||||||
|
IsOn: false,
|
||||||
|
AllowEmpty: true,
|
||||||
|
AllowSameDomain: true,
|
||||||
|
AllowDomains: nil,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Data["referersConfig"] = referersConfig
|
||||||
|
|
||||||
|
this.Show()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *IndexAction) RunPost(params struct {
|
||||||
|
WebId int64
|
||||||
|
ReferersJSON []byte
|
||||||
|
|
||||||
|
Must *actions.Must
|
||||||
|
CSRF *actionutils.CSRF
|
||||||
|
}) {
|
||||||
|
defer this.CreateLogInfo("修改Web %d 防盗链设置", params.WebId)
|
||||||
|
|
||||||
|
_, err := this.RPC().HTTPWebRPC().UpdateHTTPWebReferers(this.AdminContext(), &pb.UpdateHTTPWebReferersRequest{
|
||||||
|
HttpWebId: params.WebId,
|
||||||
|
ReferersJSON: params.ReferersJSON,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Success()
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package uam
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/server/settings/locations/locationutils"
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/serverutils"
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
|
||||||
|
"github.com/iwind/TeaGo"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
||||||
|
server.
|
||||||
|
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeServer)).
|
||||||
|
Helper(locationutils.NewLocationHelper()).
|
||||||
|
Helper(serverutils.NewServerHelper()).
|
||||||
|
Data("tinyMenuItem", "referer").
|
||||||
|
Prefix("/servers/server/settings/locations/referers").
|
||||||
|
GetPost("", new(IndexAction)).
|
||||||
|
EndAll()
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -100,6 +100,10 @@ func (this *SettingAction) RunPost(params struct {
|
|||||||
FollowRedirects: reverseProxyConfig.FollowRedirects,
|
FollowRedirects: reverseProxyConfig.FollowRedirects,
|
||||||
ProxyProtocolJSON: proxyProtocolJSON,
|
ProxyProtocolJSON: proxyProtocolJSON,
|
||||||
})
|
})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
this.Success()
|
this.Success()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,9 +6,9 @@ import (
|
|||||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
|
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
|
||||||
"github.com/iwind/TeaGo/actions"
|
"github.com/iwind/TeaGo/actions"
|
||||||
"github.com/iwind/TeaGo/maps"
|
|
||||||
"net/url"
|
"net/url"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
type CreatePopupAction struct {
|
type CreatePopupAction struct {
|
||||||
@@ -27,6 +27,9 @@ func (this *CreatePopupAction) RunGet(params struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (this *CreatePopupAction) RunPost(params struct {
|
func (this *CreatePopupAction) RunPost(params struct {
|
||||||
|
Type string
|
||||||
|
|
||||||
|
// URL
|
||||||
Mode string
|
Mode string
|
||||||
BeforeURL string
|
BeforeURL string
|
||||||
AfterURL string
|
AfterURL string
|
||||||
@@ -34,51 +37,129 @@ func (this *CreatePopupAction) RunPost(params struct {
|
|||||||
MatchRegexp bool
|
MatchRegexp bool
|
||||||
KeepRequestURI bool
|
KeepRequestURI bool
|
||||||
KeepArgs bool
|
KeepArgs bool
|
||||||
Status int
|
|
||||||
CondsJSON []byte
|
// 域名
|
||||||
IsOn bool
|
DomainsAll bool
|
||||||
|
DomainsBeforeJSON []byte
|
||||||
|
DomainAfter string
|
||||||
|
DomainAfterScheme string
|
||||||
|
|
||||||
|
// 端口
|
||||||
|
PortsAll bool
|
||||||
|
PortsBefore []string
|
||||||
|
PortAfter int
|
||||||
|
PortAfterScheme string
|
||||||
|
|
||||||
|
Status int
|
||||||
|
CondsJSON []byte
|
||||||
|
IsOn bool
|
||||||
|
|
||||||
Must *actions.Must
|
Must *actions.Must
|
||||||
CSRF *actionutils.CSRF
|
CSRF *actionutils.CSRF
|
||||||
}) {
|
}) {
|
||||||
params.Must.
|
var config = &serverconfigs.HTTPHostRedirectConfig{}
|
||||||
Field("beforeURL", params.BeforeURL).
|
config.Type = params.Type
|
||||||
Require("请填写跳转前的URL")
|
config.Status = params.Status
|
||||||
|
config.IsOn = params.IsOn
|
||||||
|
|
||||||
|
switch params.Type {
|
||||||
|
case serverconfigs.HTTPHostRedirectTypeURL:
|
||||||
|
params.Must.
|
||||||
|
Field("beforeURL", params.BeforeURL).
|
||||||
|
Require("请填写跳转前的URL")
|
||||||
|
|
||||||
|
// 校验格式
|
||||||
|
if params.MatchRegexp {
|
||||||
|
_, err := regexp.Compile(params.BeforeURL)
|
||||||
|
if err != nil {
|
||||||
|
this.Fail("跳转前URL正则表达式错误:" + err.Error())
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
u, err := url.Parse(params.BeforeURL)
|
||||||
|
if err != nil {
|
||||||
|
this.FailField("beforeURL", "请输入正确的跳转前URL")
|
||||||
|
}
|
||||||
|
if (u.Scheme != "http" && u.Scheme != "https") ||
|
||||||
|
len(u.Host) == 0 {
|
||||||
|
this.FailField("beforeURL", "请输入正确的跳转前URL")
|
||||||
|
}
|
||||||
|
|
||||||
// 校验格式
|
|
||||||
if params.MatchRegexp {
|
|
||||||
_, err := regexp.Compile(params.BeforeURL)
|
|
||||||
if err != nil {
|
|
||||||
this.Fail("跳转前URL正则表达式错误:" + err.Error())
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
u, err := url.Parse(params.BeforeURL)
|
|
||||||
if err != nil {
|
|
||||||
this.FailField("beforeURL", "请输入正确的跳转前URL")
|
|
||||||
}
|
|
||||||
if (u.Scheme != "http" && u.Scheme != "https") ||
|
|
||||||
len(u.Host) == 0 {
|
|
||||||
this.FailField("beforeURL", "请输入正确的跳转前URL")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
params.Must.
|
||||||
|
Field("afterURL", params.AfterURL).
|
||||||
|
Require("请填写跳转后URL")
|
||||||
|
|
||||||
params.Must.
|
// 校验格式
|
||||||
Field("afterURL", params.AfterURL).
|
if params.MatchRegexp {
|
||||||
Require("请填写跳转后URL")
|
// 正则表达式情况下不做校验
|
||||||
|
} else {
|
||||||
|
u, err := url.Parse(params.AfterURL)
|
||||||
|
if err != nil {
|
||||||
|
this.FailField("afterURL", "请输入正确的跳转后URL")
|
||||||
|
}
|
||||||
|
if (u.Scheme != "http" && u.Scheme != "https") ||
|
||||||
|
len(u.Host) == 0 {
|
||||||
|
this.FailField("afterURL", "请输入正确的跳转后URL")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 校验格式
|
config.Mode = params.Mode
|
||||||
if params.MatchRegexp {
|
config.BeforeURL = params.BeforeURL
|
||||||
// 正则表达式情况下不做校验
|
config.AfterURL = params.AfterURL
|
||||||
} else {
|
config.MatchPrefix = params.MatchPrefix
|
||||||
u, err := url.Parse(params.AfterURL)
|
config.MatchRegexp = params.MatchRegexp
|
||||||
if err != nil {
|
config.KeepRequestURI = params.KeepRequestURI
|
||||||
this.FailField("afterURL", "请输入正确的跳转后URL")
|
config.KeepArgs = params.KeepArgs
|
||||||
|
case serverconfigs.HTTPHostRedirectTypeDomain:
|
||||||
|
config.DomainsAll = params.DomainsAll
|
||||||
|
var domainsBefore = []string{}
|
||||||
|
if len(params.DomainsBeforeJSON) > 0 {
|
||||||
|
err := json.Unmarshal(params.DomainsBeforeJSON, &domainsBefore)
|
||||||
|
if err != nil {
|
||||||
|
this.Fail("错误的域名格式:" + err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (u.Scheme != "http" && u.Scheme != "https") ||
|
config.DomainsBefore = domainsBefore
|
||||||
len(u.Host) == 0 {
|
if !params.DomainsAll {
|
||||||
this.FailField("afterURL", "请输入正确的跳转后URL")
|
if len(domainsBefore) == 0 {
|
||||||
|
this.Fail("请输入跳转前域名")
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
if len(params.DomainAfter) == 0 {
|
||||||
|
this.FailField("domainAfter", "请输入跳转后域名")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
config.DomainAfter = params.DomainAfter
|
||||||
|
config.DomainAfterScheme = params.DomainAfterScheme
|
||||||
|
case serverconfigs.HTTPHostRedirectTypePort:
|
||||||
|
config.PortsAll = params.PortsAll
|
||||||
|
|
||||||
|
config.PortsBefore = params.PortsBefore
|
||||||
|
var portReg = regexp.MustCompile(`^\d+$`)
|
||||||
|
var portRangeReg = regexp.MustCompile(`^\d+-\d+$`)
|
||||||
|
if !config.PortsAll {
|
||||||
|
for _, port := range params.PortsBefore {
|
||||||
|
port = strings.ReplaceAll(port, " ", "")
|
||||||
|
if !portReg.MatchString(port) && !portRangeReg.MatchString(port) {
|
||||||
|
this.Fail("端口号" + port + "填写错误(请输入单个端口号或一个端口范围)")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(params.PortsBefore) == 0 {
|
||||||
|
this.Fail("请输入跳转前端口")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if params.PortAfter <= 0 {
|
||||||
|
this.FailField("portAfter", "请输入跳转后端口")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
config.PortAfter = params.PortAfter
|
||||||
|
config.PortAfterScheme = params.PortAfterScheme
|
||||||
}
|
}
|
||||||
|
|
||||||
params.Must.
|
params.Must.
|
||||||
@@ -99,19 +180,16 @@ func (this *CreatePopupAction) RunPost(params struct {
|
|||||||
this.Fail("匹配条件校验失败:" + err.Error())
|
this.Fail("匹配条件校验失败:" + err.Error())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
config.Conds = conds
|
||||||
|
|
||||||
this.Data["redirect"] = maps.Map{
|
// 校验配置
|
||||||
"mode": params.Mode,
|
err := config.Init()
|
||||||
"status": params.Status,
|
if err != nil {
|
||||||
"beforeURL": params.BeforeURL,
|
this.Fail("配置校验失败:" + err.Error())
|
||||||
"afterURL": params.AfterURL,
|
return
|
||||||
"matchPrefix": params.MatchPrefix,
|
|
||||||
"matchRegexp": params.MatchRegexp,
|
|
||||||
"keepRequestURI": params.KeepRequestURI,
|
|
||||||
"keepArgs": params.KeepArgs,
|
|
||||||
"conds": conds,
|
|
||||||
"isOn": params.IsOn,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.Data["redirect"] = config
|
||||||
|
|
||||||
this.Success()
|
this.Success()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,70 @@
|
|||||||
|
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||||
|
|
||||||
|
package uam
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||||
|
"github.com/iwind/TeaGo/actions"
|
||||||
|
)
|
||||||
|
|
||||||
|
type IndexAction struct {
|
||||||
|
actionutils.ParentAction
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *IndexAction) Init() {
|
||||||
|
this.Nav("", "setting", "index")
|
||||||
|
this.SecondMenu("referer")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *IndexAction) RunGet(params struct {
|
||||||
|
ServerId int64
|
||||||
|
}) {
|
||||||
|
this.Data["serverId"] = params.ServerId
|
||||||
|
|
||||||
|
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithServerId(this.AdminContext(), params.ServerId)
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Data["webId"] = webConfig.Id
|
||||||
|
|
||||||
|
var referersConfig = webConfig.Referers
|
||||||
|
if referersConfig == nil {
|
||||||
|
referersConfig = &serverconfigs.ReferersConfig{
|
||||||
|
IsPrior: false,
|
||||||
|
IsOn: false,
|
||||||
|
AllowEmpty: true,
|
||||||
|
AllowSameDomain: true,
|
||||||
|
AllowDomains: nil,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Data["referersConfig"] = referersConfig
|
||||||
|
|
||||||
|
this.Show()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *IndexAction) RunPost(params struct {
|
||||||
|
WebId int64
|
||||||
|
ReferersJSON []byte
|
||||||
|
|
||||||
|
Must *actions.Must
|
||||||
|
CSRF *actionutils.CSRF
|
||||||
|
}) {
|
||||||
|
defer this.CreateLogInfo("修改Web %d 防盗链设置", params.WebId)
|
||||||
|
|
||||||
|
_, err := this.RPC().HTTPWebRPC().UpdateHTTPWebReferers(this.AdminContext(), &pb.UpdateHTTPWebReferersRequest{
|
||||||
|
HttpWebId: params.WebId,
|
||||||
|
ReferersJSON: params.ReferersJSON,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Success()
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package uam
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/serverutils"
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
|
||||||
|
"github.com/iwind/TeaGo"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
||||||
|
server.
|
||||||
|
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeServer)).
|
||||||
|
Helper(serverutils.NewServerHelper()).
|
||||||
|
Prefix("/servers/server/settings/referers").
|
||||||
|
GetPost("", new(IndexAction)).
|
||||||
|
EndAll()
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -79,9 +79,9 @@ func (this *UpdateIPPopupAction) RunPost(params struct {
|
|||||||
|
|
||||||
var ipToLong uint64
|
var ipToLong uint64
|
||||||
if len(params.IpTo) > 0 && !utils.IsIPv4(params.IpTo) {
|
if len(params.IpTo) > 0 && !utils.IsIPv4(params.IpTo) {
|
||||||
ipToLong = utils.IP2Long(params.IpTo)
|
|
||||||
this.Fail("请输入正确的结束IP")
|
this.Fail("请输入正确的结束IP")
|
||||||
}
|
}
|
||||||
|
ipToLong = utils.IP2Long(params.IpTo)
|
||||||
|
|
||||||
if ipFromLong > 0 && ipToLong > 0 && ipFromLong > ipToLong {
|
if ipFromLong > 0 && ipToLong > 0 && ipFromLong > ipToLong {
|
||||||
params.IpTo, params.IpFrom = params.IpFrom, params.IpTo
|
params.IpTo, params.IpFrom = params.IpFrom, params.IpTo
|
||||||
|
|||||||
@@ -309,6 +309,12 @@ func (this *ServerHelper) createSettingsMenu(secondMenuItem string, serverIdStri
|
|||||||
"isActive": secondMenuItem == "access",
|
"isActive": secondMenuItem == "access",
|
||||||
"isOn": serverConfig.Web != nil && serverConfig.Web.Auth != nil && serverConfig.Web.Auth.IsOn,
|
"isOn": serverConfig.Web != nil && serverConfig.Web.Auth != nil && serverConfig.Web.Auth.IsOn,
|
||||||
})
|
})
|
||||||
|
menuItems = append(menuItems, maps.Map{
|
||||||
|
"name": "防盗链",
|
||||||
|
"url": "/servers/server/settings/referers?serverId=" + serverIdString,
|
||||||
|
"isActive": secondMenuItem == "referer",
|
||||||
|
"isOn": serverConfig.Web != nil && serverConfig.Web.Referers != nil && serverConfig.Web.Referers.IsOn,
|
||||||
|
})
|
||||||
menuItems = append(menuItems, maps.Map{
|
menuItems = append(menuItems, maps.Map{
|
||||||
"name": "字符编码",
|
"name": "字符编码",
|
||||||
"url": "/servers/server/settings/charset?serverId=" + serverIdString,
|
"url": "/servers/server/settings/charset?serverId=" + serverIdString,
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||||
|
//go:build !plus
|
||||||
|
|
||||||
package users
|
package users
|
||||||
|
|
||||||
import (
|
import (
|
||||||
teaconst "github.com/TeaOSLab/EdgeAdmin/internal/const"
|
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
|
||||||
"github.com/iwind/TeaGo/maps"
|
"github.com/iwind/TeaGo/maps"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -17,33 +16,6 @@ func (this *PlansAction) RunPost(params struct {
|
|||||||
UserId int64
|
UserId int64
|
||||||
ServerId int64
|
ServerId int64
|
||||||
}) {
|
}) {
|
||||||
if !teaconst.IsPlus || params.UserId <= 0 {
|
this.Data["plans"] = []maps.Map{}
|
||||||
this.Data["plans"] = []maps.Map{}
|
|
||||||
this.Success()
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO 优化用户套餐查询
|
|
||||||
userPlansResp, err := this.RPC().UserPlanRPC().FindAllEnabledUserPlansForServer(this.AdminContext(), &pb.FindAllEnabledUserPlansForServerRequest{
|
|
||||||
UserId: params.UserId,
|
|
||||||
ServerId: params.ServerId,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
this.ErrorPage(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
var userPlanMaps = []maps.Map{}
|
|
||||||
for _, userPlan := range userPlansResp.UserPlans {
|
|
||||||
if userPlan.Plan == nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
userPlanMaps = append(userPlanMaps, maps.Map{
|
|
||||||
"id": userPlan.Id,
|
|
||||||
"name": userPlan.Plan.Name,
|
|
||||||
"dayTo": userPlan.DayTo,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
this.Data["plans"] = userPlanMaps
|
|
||||||
|
|
||||||
this.Success()
|
this.Success()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/userconfigs"
|
||||||
"github.com/iwind/TeaGo/actions"
|
"github.com/iwind/TeaGo/actions"
|
||||||
"io"
|
"io"
|
||||||
)
|
)
|
||||||
@@ -37,6 +38,8 @@ func (this *IndexAction) RunGet(params struct{}) {
|
|||||||
}
|
}
|
||||||
this.Data["timeZoneLocation"] = nodeconfigs.FindTimeZoneLocation(config.TimeZone)
|
this.Data["timeZoneLocation"] = nodeconfigs.FindTimeZoneLocation(config.TimeZone)
|
||||||
|
|
||||||
|
this.filterConfig(config)
|
||||||
|
|
||||||
this.Show()
|
this.Show()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -52,6 +55,9 @@ func (this *IndexAction) RunPost(params struct {
|
|||||||
DefaultPageSize int
|
DefaultPageSize int
|
||||||
TimeZone string
|
TimeZone string
|
||||||
|
|
||||||
|
SupportModuleCDN bool
|
||||||
|
SupportModuleNS bool
|
||||||
|
|
||||||
Must *actions.Must
|
Must *actions.Must
|
||||||
CSRF *actionutils.CSRF
|
CSRF *actionutils.CSRF
|
||||||
}) {
|
}) {
|
||||||
@@ -85,6 +91,14 @@ func (this *IndexAction) RunPost(params struct {
|
|||||||
config.DefaultPageSize = 10
|
config.DefaultPageSize = 10
|
||||||
}
|
}
|
||||||
|
|
||||||
|
config.Modules = []userconfigs.UserModule{}
|
||||||
|
if params.SupportModuleCDN {
|
||||||
|
config.Modules = append(config.Modules, userconfigs.UserModuleCDN)
|
||||||
|
}
|
||||||
|
if params.SupportModuleNS {
|
||||||
|
config.Modules = append(config.Modules, userconfigs.UserModuleNS)
|
||||||
|
}
|
||||||
|
|
||||||
// 上传Favicon文件
|
// 上传Favicon文件
|
||||||
if params.FaviconFile != nil {
|
if params.FaviconFile != nil {
|
||||||
createResp, err := this.RPC().FileRPC().CreateFile(this.AdminContext(), &pb.CreateFileRequest{
|
createResp, err := this.RPC().FileRPC().CreateFile(this.AdminContext(), &pb.CreateFileRequest{
|
||||||
|
|||||||
12
internal/web/actions/default/settings/ui/index_ext.go
Normal file
12
internal/web/actions/default/settings/ui/index_ext.go
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||||
|
//go:build !plus
|
||||||
|
|
||||||
|
package ui
|
||||||
|
|
||||||
|
import "github.com/TeaOSLab/EdgeCommon/pkg/systemconfigs"
|
||||||
|
|
||||||
|
func (this *IndexAction) filterConfig(config *systemconfigs.AdminUIConfig) {
|
||||||
|
this.Data["supportModuleCDN"] = true
|
||||||
|
this.Data["supportModuleNS"] = true
|
||||||
|
this.Data["nsIsVisible"] = false
|
||||||
|
}
|
||||||
@@ -48,25 +48,25 @@ func (this *ValidateApiAction) RunPost(params struct {
|
|||||||
if params.Mode == "new" {
|
if params.Mode == "new" {
|
||||||
params.Must.
|
params.Must.
|
||||||
Field("newPort", params.NewPort).
|
Field("newPort", params.NewPort).
|
||||||
Require("请输入节点端口").
|
Require("请输入API节点端口").
|
||||||
Match(`^\d+$`, "节点端口只能是数字").
|
Match(`^\d+$`, "API节点端口只能是数字").
|
||||||
MinLength(4, "请输入4位以上的数字").
|
MinLength(4, "请输入4位以上的数字端口号").
|
||||||
MaxLength(5, "请输入5位以下的数字")
|
MaxLength(5, "请输入5位以下的数字端口号")
|
||||||
newPort := types.Int(params.NewPort)
|
var newPort = types.Int(params.NewPort)
|
||||||
if newPort < 1024 {
|
if newPort < 1024 {
|
||||||
this.FailField("newPort", "端口号不能小于1024")
|
this.FailField("newPort", "API端口号不能小于1024")
|
||||||
}
|
}
|
||||||
if newPort > 65534 {
|
if newPort > 65534 {
|
||||||
this.FailField("newPort", "端口号不能大于65534")
|
this.FailField("newPort", "API端口号不能大于65534")
|
||||||
}
|
}
|
||||||
|
|
||||||
if net.ParseIP(params.NewHost) == nil {
|
if net.ParseIP(params.NewHost) == nil {
|
||||||
this.FailField("newHost", "请输入正确的节点主机地址")
|
this.FailField("newHost", "请输入正确的API节点主机地址")
|
||||||
}
|
}
|
||||||
|
|
||||||
params.Must.
|
params.Must.
|
||||||
Field("newHost", params.NewHost).
|
Field("newHost", params.NewHost).
|
||||||
Require("请输入节点主机地址")
|
Require("请输入API节点主机地址")
|
||||||
|
|
||||||
this.Success()
|
this.Success()
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ func (this *CountryOptionsAction) RunPost(params struct{}) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var letter = ""
|
var letter = ""
|
||||||
if len(country.Pinyin) > 0 && len(country.Pinyin) > 0 && len(country.Pinyin[0]) > 0 {
|
if len(country.Pinyin) > 0 && len(country.Pinyin[0]) > 0 {
|
||||||
letter = strings.ToUpper(country.Pinyin[0][:1])
|
letter = strings.ToUpper(country.Pinyin[0][:1])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,10 @@ import (
|
|||||||
"github.com/TeaOSLab/EdgeAdmin/internal/setup"
|
"github.com/TeaOSLab/EdgeAdmin/internal/setup"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/systemconfigs"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/userconfigs"
|
||||||
"github.com/iwind/TeaGo/actions"
|
"github.com/iwind/TeaGo/actions"
|
||||||
|
"github.com/iwind/TeaGo/lists"
|
||||||
"github.com/iwind/TeaGo/logs"
|
"github.com/iwind/TeaGo/logs"
|
||||||
"github.com/iwind/TeaGo/maps"
|
"github.com/iwind/TeaGo/maps"
|
||||||
"net"
|
"net"
|
||||||
@@ -192,7 +195,7 @@ func (this *userMustAuth) BeforeAction(actionPtr actions.ActionWrapper, paramNam
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
config, err := configloaders.LoadAdminUIConfig()
|
uiConfig, err := configloaders.LoadAdminUIConfig()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
action.WriteString(err.Error())
|
action.WriteString(err.Error())
|
||||||
return false
|
return false
|
||||||
@@ -203,11 +206,11 @@ func (this *userMustAuth) BeforeAction(actionPtr actions.ActionWrapper, paramNam
|
|||||||
return action.Data["teaTitle"].(string)
|
return action.Data["teaTitle"].(string)
|
||||||
})
|
})
|
||||||
|
|
||||||
action.Data["teaShowVersion"] = config.ShowVersion
|
action.Data["teaShowVersion"] = uiConfig.ShowVersion
|
||||||
action.Data["teaTitle"] = config.AdminSystemName
|
action.Data["teaTitle"] = uiConfig.AdminSystemName
|
||||||
action.Data["teaName"] = config.ProductName
|
action.Data["teaName"] = uiConfig.ProductName
|
||||||
action.Data["teaFaviconFileId"] = config.FaviconFileId
|
action.Data["teaFaviconFileId"] = uiConfig.FaviconFileId
|
||||||
action.Data["teaLogoFileId"] = config.LogoFileId
|
action.Data["teaLogoFileId"] = uiConfig.LogoFileId
|
||||||
action.Data["teaUsername"] = configloaders.FindAdminFullname(adminId)
|
action.Data["teaUsername"] = configloaders.FindAdminFullname(adminId)
|
||||||
action.Data["teaTheme"] = configloaders.FindAdminTheme(adminId)
|
action.Data["teaTheme"] = configloaders.FindAdminTheme(adminId)
|
||||||
|
|
||||||
@@ -216,15 +219,15 @@ func (this *userMustAuth) BeforeAction(actionPtr actions.ActionWrapper, paramNam
|
|||||||
if !action.Data.Has("teaMenu") {
|
if !action.Data.Has("teaMenu") {
|
||||||
action.Data["teaMenu"] = ""
|
action.Data["teaMenu"] = ""
|
||||||
}
|
}
|
||||||
action.Data["teaModules"] = this.modules(actionPtr, adminId)
|
action.Data["teaModules"] = this.modules(actionPtr, adminId, uiConfig)
|
||||||
action.Data["teaSubMenus"] = []map[string]interface{}{}
|
action.Data["teaSubMenus"] = []map[string]interface{}{}
|
||||||
action.Data["teaTabbar"] = []map[string]interface{}{}
|
action.Data["teaTabbar"] = []map[string]interface{}{}
|
||||||
if len(config.Version) == 0 {
|
if len(uiConfig.Version) == 0 {
|
||||||
action.Data["teaVersion"] = teaconst.Version
|
action.Data["teaVersion"] = teaconst.Version
|
||||||
} else {
|
} else {
|
||||||
action.Data["teaVersion"] = config.Version
|
action.Data["teaVersion"] = uiConfig.Version
|
||||||
}
|
}
|
||||||
action.Data["teaShowOpenSourceInfo"] = config.ShowOpenSourceInfo
|
action.Data["teaShowOpenSourceInfo"] = uiConfig.ShowOpenSourceInfo
|
||||||
action.Data["teaIsSuper"] = false
|
action.Data["teaIsSuper"] = false
|
||||||
action.Data["teaIsPlus"] = teaconst.IsPlus
|
action.Data["teaIsPlus"] = teaconst.IsPlus
|
||||||
action.Data["teaDemoEnabled"] = teaconst.IsDemoMode
|
action.Data["teaDemoEnabled"] = teaconst.IsDemoMode
|
||||||
@@ -251,7 +254,7 @@ func (this *userMustAuth) BeforeAction(actionPtr actions.ActionWrapper, paramNam
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 菜单配置
|
// 菜单配置
|
||||||
func (this *userMustAuth) modules(actionPtr actions.ActionWrapper, adminId int64) []maps.Map {
|
func (this *userMustAuth) modules(actionPtr actions.ActionWrapper, adminId int64, adminUIConfig *systemconfigs.AdminUIConfig) []maps.Map {
|
||||||
// 父级动作
|
// 父级动作
|
||||||
var action = actionPtr.Object()
|
var action = actionPtr.Object()
|
||||||
|
|
||||||
@@ -269,14 +272,27 @@ func (this *userMustAuth) modules(actionPtr actions.ActionWrapper, adminId int64
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
result := []maps.Map{}
|
var result = []maps.Map{}
|
||||||
for _, m := range FindAllMenuMaps(nodeLogsType, countUnreadNodeLogs, countUnreadIPItems) {
|
for _, m := range FindAllMenuMaps(nodeLogsType, countUnreadNodeLogs, countUnreadIPItems) {
|
||||||
if m.GetString("code") == "finance" && !configloaders.ShowFinance() {
|
if m.GetString("code") == "finance" && !configloaders.ShowFinance() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
module := m.GetString("module")
|
var module = m.GetString("module")
|
||||||
if configloaders.AllowModule(adminId, module) {
|
if configloaders.AllowModule(adminId, module) {
|
||||||
|
if module == "ns" && !adminUIConfig.ContainsModule(userconfigs.UserModuleNS) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if lists.ContainsString([]string{
|
||||||
|
configloaders.AdminModuleCodeNode,
|
||||||
|
configloaders.AdminModuleCodeDNS,
|
||||||
|
configloaders.AdminModuleCodePlan,
|
||||||
|
configloaders.AdminModuleCodeServer,
|
||||||
|
configloaders.AdminModuleCodeDashboard,
|
||||||
|
}, module) && !adminUIConfig.ContainsModule(userconfigs.UserModuleCDN) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
result = append(result, m)
|
result = append(result, m)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"github.com/TeaOSLab/EdgeAdmin/internal/events"
|
"github.com/TeaOSLab/EdgeAdmin/internal/events"
|
||||||
nodes "github.com/TeaOSLab/EdgeAdmin/internal/rpc"
|
nodes "github.com/TeaOSLab/EdgeAdmin/internal/rpc"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/utils"
|
"github.com/TeaOSLab/EdgeAdmin/internal/utils"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/configutils"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/systemconfigs"
|
"github.com/TeaOSLab/EdgeCommon/pkg/systemconfigs"
|
||||||
"github.com/iwind/TeaGo/lists"
|
"github.com/iwind/TeaGo/lists"
|
||||||
@@ -145,7 +146,7 @@ func checkRequestSecurity(securityConfig *systemconfigs.SecurityConfig, req *htt
|
|||||||
if err == nil && len(realDomain) > 0 {
|
if err == nil && len(realDomain) > 0 {
|
||||||
domain = realDomain
|
domain = realDomain
|
||||||
}
|
}
|
||||||
if !lists.ContainsString(securityConfig.AllowDomains, domain) {
|
if !configutils.MatchDomains(securityConfig.AllowDomains, domain) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user