Compare commits
119 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6a484af775 | ||
|
|
3074d41cf2 | ||
|
|
54199058e3 | ||
|
|
87a533791b | ||
|
|
c3109bb2c6 | ||
|
|
031cb836d2 | ||
|
|
aa0a9134cb | ||
|
|
749eac74fe | ||
|
|
ac39908737 | ||
|
|
bb8f4bf488 | ||
|
|
db0d157a74 | ||
|
|
bd8e1bbe71 | ||
|
|
7aba898cf5 | ||
|
|
baf039755f | ||
|
|
70977f7d80 | ||
|
|
884342d6af | ||
|
|
411b0fb4c2 | ||
|
|
8053fb2399 | ||
|
|
ed42dcab9c | ||
|
|
866b5b0f2f | ||
|
|
5834a1a0fa | ||
|
|
8c6d845603 | ||
|
|
667f363f3c | ||
|
|
e209ff38d9 | ||
|
|
ea915993b6 | ||
|
|
72d0468c6a | ||
|
|
35ae13b1c3 | ||
|
|
1d9460f565 | ||
|
|
e9a3ed71b4 | ||
|
|
e344e5b7e6 | ||
|
|
e814064403 | ||
|
|
f5aeb5cbcd | ||
|
|
f41164b892 | ||
|
|
03073c8364 | ||
|
|
a359bff531 | ||
|
|
3789ac6433 | ||
|
|
9f53f59f18 | ||
|
|
521bd746e3 | ||
|
|
3d8e43a42b | ||
|
|
9452e1852d | ||
|
|
3920d24af6 | ||
|
|
3af11e6ba8 | ||
|
|
7bcde46d49 | ||
|
|
0b73041718 | ||
|
|
dcdc0cb8c1 | ||
|
|
ad6ac1aad6 | ||
|
|
249dc6accd | ||
|
|
939e5999ca | ||
|
|
1f91e57d56 | ||
|
|
81e749dc60 | ||
|
|
241b2afda8 | ||
|
|
94cc29f227 | ||
|
|
6d6659eee1 | ||
|
|
5220be0775 | ||
|
|
07ebbf0863 | ||
|
|
b60c767fc5 | ||
|
|
371c3b78c3 | ||
|
|
6a3aa219d5 | ||
|
|
df586ddfdd | ||
|
|
f3b2bbfec0 | ||
|
|
3ea2114798 | ||
|
|
809cf70e0e | ||
|
|
390619535f | ||
|
|
3392ac1fa8 | ||
|
|
b09d94abbe | ||
|
|
03ac01d21f | ||
|
|
12b1d785e5 | ||
|
|
71c58e9d2e | ||
|
|
13c2997a52 | ||
|
|
47b840cac9 | ||
|
|
3f7f243f50 | ||
|
|
1d1e83b18d | ||
|
|
6f3a602c76 | ||
|
|
afb7a4c6a7 | ||
|
|
d0c950d4ca | ||
|
|
63ee7d5211 | ||
|
|
6b0d875745 | ||
|
|
a47a9b9c0c | ||
|
|
27040a3e5c | ||
|
|
c7a8a40e22 | ||
|
|
408de6af63 | ||
|
|
8a324afaa1 | ||
|
|
54bc4cede0 | ||
|
|
4cfbea80b0 | ||
|
|
64cb8286bd | ||
|
|
3e92e0afc6 | ||
|
|
8a91308280 | ||
|
|
3da861d71e | ||
|
|
3566e18e99 | ||
|
|
6e608e627a | ||
|
|
65f7fb979b | ||
|
|
558b5e14f1 | ||
|
|
a5ee2dd03b | ||
|
|
9e9fe78b8d | ||
|
|
265e126faf | ||
|
|
af440e5c5b | ||
|
|
32b8c91113 | ||
|
|
dbc60ccca4 | ||
|
|
d5b5af5d3a | ||
|
|
8c1bd3bc4e | ||
|
|
8f638186a3 | ||
|
|
0b5a27e674 | ||
|
|
870f1aaaec | ||
|
|
23cb4dcbe5 | ||
|
|
4f125b4244 | ||
|
|
2b9de7938f | ||
|
|
75bb07184f | ||
|
|
1fb491d2e1 | ||
|
|
0bc8bdd841 | ||
|
|
71d4e2626e | ||
|
|
0b26cbdd01 | ||
|
|
ca72b3c18b | ||
|
|
8676f2711b | ||
|
|
788a86bdcf | ||
|
|
0df6b4b220 | ||
|
|
f14dcd5c28 | ||
|
|
f86548e046 | ||
|
|
9dea11ab11 | ||
|
|
00749f806c |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1,3 +1,5 @@
|
||||
*_plus.go
|
||||
*-plus.sh
|
||||
*_plus.html
|
||||
*_plus.js
|
||||
*@plus.js
|
||||
@@ -58,13 +58,20 @@ function build() {
|
||||
rm -f $(basename $EDGE_API_ZIP_FILE)
|
||||
cd -
|
||||
|
||||
# generate files
|
||||
echo "generating files ..."
|
||||
go run -tags $TAG $ROOT/../cmd/edge-admin/main.go generate
|
||||
|
||||
# build
|
||||
echo "building "${NAME}" ..."
|
||||
env GOOS=$OS GOARCH=$GOARCH go build -tags $TAG -ldflags="-s -w" -o $DIST/bin/${NAME} $ROOT/../cmd/edge-admin/main.go
|
||||
env GOOS=$OS GOARCH=$ARCH go build -tags $TAG -ldflags="-s -w" -o $DIST/bin/${NAME} $ROOT/../cmd/edge-admin/main.go
|
||||
|
||||
# delete hidden files
|
||||
find $DIST -name ".DS_Store" -delete
|
||||
find $DIST -name ".gitignore" -delete
|
||||
find $DIST -name "*.less" -delete
|
||||
find $DIST -name "*.css.map" -delete
|
||||
find $DIST -name "*.js.map" -delete
|
||||
|
||||
# zip
|
||||
echo "zip files ..."
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/apps"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/configs"
|
||||
teaconst "github.com/TeaOSLab/EdgeAdmin/internal/const"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/gen"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/nodes"
|
||||
_ "github.com/TeaOSLab/EdgeAdmin/internal/web"
|
||||
_ "github.com/iwind/TeaGo/bootstrap"
|
||||
@@ -70,6 +71,13 @@ func main() {
|
||||
}
|
||||
fmt.Println("change demo mode successfully")
|
||||
})
|
||||
app.On("generate", func() {
|
||||
err := gen.Generate()
|
||||
if err != nil {
|
||||
fmt.Println("generate failed: " + err.Error())
|
||||
return
|
||||
}
|
||||
})
|
||||
app.Run(func() {
|
||||
adminNode := nodes.NewAdminNode()
|
||||
adminNode.Run()
|
||||
|
||||
6
go.mod
6
go.mod
@@ -10,9 +10,11 @@ require (
|
||||
github.com/go-sql-driver/mysql v1.5.0
|
||||
github.com/go-yaml/yaml v2.1.0+incompatible
|
||||
github.com/google/go-cmp v0.5.6 // indirect
|
||||
github.com/iwind/TeaGo v0.0.0-20210720011303-fc255c995afa
|
||||
github.com/iwind/gosock v0.0.0-20210722083328-12b2d66abec3
|
||||
github.com/iwind/TeaGo v0.0.0-20211026123858-7de7a21cad24
|
||||
github.com/iwind/gosock v0.0.0-20211103081026-ee4652210ca4
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/miekg/dns v1.1.35
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
|
||||
github.com/tealeg/xlsx/v3 v3.2.3
|
||||
github.com/xlzd/gotp v0.0.0-20181030022105-c8557ba2c119
|
||||
|
||||
14
go.sum
14
go.sum
@@ -62,12 +62,18 @@ github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/
|
||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/iwind/TeaGo v0.0.0-20210628135026-38575a4ab060/go.mod h1:KU4mS7QNiZ7QWEuDBk1zw0/Q2LrAPZv3tycEFBsuUwc=
|
||||
github.com/iwind/TeaGo v0.0.0-20210720011303-fc255c995afa h1:woN88uEmRRUNFD7pRZEtX9heDcjFn0ClMxjF5ButKow=
|
||||
github.com/iwind/TeaGo v0.0.0-20210720011303-fc255c995afa/go.mod h1:KU4mS7QNiZ7QWEuDBk1zw0/Q2LrAPZv3tycEFBsuUwc=
|
||||
github.com/iwind/TeaGo v0.0.0-20210831140440-a2a442471b13 h1:HuEJ5xJfujW1Q6rNDhOu5LQXEBB2qLPah3jYslT8Gz4=
|
||||
github.com/iwind/TeaGo v0.0.0-20210831140440-a2a442471b13/go.mod h1:KU4mS7QNiZ7QWEuDBk1zw0/Q2LrAPZv3tycEFBsuUwc=
|
||||
github.com/iwind/TeaGo v0.0.0-20211026123858-7de7a21cad24 h1:1cGulkD2SNJJRok5OKwyhP/Ddm+PgSWKOupn0cR36/A=
|
||||
github.com/iwind/TeaGo v0.0.0-20211026123858-7de7a21cad24/go.mod h1:KU4mS7QNiZ7QWEuDBk1zw0/Q2LrAPZv3tycEFBsuUwc=
|
||||
github.com/iwind/gosock v0.0.0-20210722083328-12b2d66abec3 h1:aBSonas7vFcgTj9u96/bWGILGv1ZbUSTLiOzcI1ZT6c=
|
||||
github.com/iwind/gosock v0.0.0-20210722083328-12b2d66abec3/go.mod h1:H5Q7SXwbx3a97ecJkaS2sD77gspzE7HFUafBO0peEyA=
|
||||
github.com/iwind/gosock v0.0.0-20211103081026-ee4652210ca4 h1:VWGsCqTzObdlbf7UUE3oceIpcEKi4C/YBUszQXk118A=
|
||||
github.com/iwind/gosock v0.0.0-20211103081026-ee4652210ca4/go.mod h1:H5Q7SXwbx3a97ecJkaS2sD77gspzE7HFUafBO0peEyA=
|
||||
github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68=
|
||||
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
@@ -77,8 +83,12 @@ github.com/miekg/dns v1.1.35 h1:oTfOaDH+mZkdcgdIjH6yBajRGtIwcwcaR+rt23ZSrJs=
|
||||
github.com/miekg/dns v1.1.35/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg=
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
||||
|
||||
@@ -19,6 +19,7 @@ const (
|
||||
AdminModuleCodeAdmin AdminModuleCode = "admin" // 系统用户
|
||||
AdminModuleCodeUser AdminModuleCode = "user" // 平台用户
|
||||
AdminModuleCodeFinance AdminModuleCode = "finance" // 财务
|
||||
AdminModuleCodePlan AdminModuleCode = "plan" // 套餐
|
||||
AdminModuleCodeLog AdminModuleCode = "log" // 日志
|
||||
AdminModuleCodeSetting AdminModuleCode = "setting" // 设置
|
||||
AdminModuleCodeCommon AdminModuleCode = "common" // 只要登录就可以访问的模块
|
||||
@@ -182,7 +183,7 @@ func AllModuleMaps() []maps.Map {
|
||||
}
|
||||
if teaconst.IsPlus {
|
||||
m = append(m, maps.Map{
|
||||
"name": "自建DNS",
|
||||
"name": "智能DNS",
|
||||
"code": AdminModuleCodeNS,
|
||||
"url": "/ns",
|
||||
})
|
||||
@@ -203,6 +204,11 @@ func AllModuleMaps() []maps.Map {
|
||||
"code": AdminModuleCodeFinance,
|
||||
"url": "/finance",
|
||||
},
|
||||
{
|
||||
"name": "套餐管理",
|
||||
"code": AdminModuleCodePlan,
|
||||
"url": "/plans",
|
||||
},
|
||||
{
|
||||
"name": "日志审计",
|
||||
"code": AdminModuleCodeLog,
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package teaconst
|
||||
|
||||
const (
|
||||
Version = "0.3.1"
|
||||
Version = "0.3.5.2"
|
||||
|
||||
APINodeVersion = "0.3.1"
|
||||
APINodeVersion = "0.3.5.2"
|
||||
|
||||
ProductName = "Edge Admin"
|
||||
ProcessName = "edge-admin"
|
||||
|
||||
129
internal/gen/generate.go
Normal file
129
internal/gen/generate.go
Normal file
@@ -0,0 +1,129 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package gen
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/server/settings/conds/condutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/files"
|
||||
"github.com/iwind/TeaGo/logs"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
func Generate() error {
|
||||
err := generateComponentsJSFile()
|
||||
if err != nil {
|
||||
return errors.New("generate 'components.js' failed: " + err.Error())
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// 生成Javascript文件
|
||||
func generateComponentsJSFile() error {
|
||||
var buffer = bytes.NewBuffer([]byte{})
|
||||
|
||||
var webRoot string
|
||||
if Tea.IsTesting() {
|
||||
webRoot = Tea.Root + "/../web/public/js/components/"
|
||||
} else {
|
||||
webRoot = Tea.Root + "/web/public/js/components/"
|
||||
}
|
||||
f := files.NewFile(webRoot)
|
||||
|
||||
f.Range(func(file *files.File) {
|
||||
if !file.IsFile() {
|
||||
return
|
||||
}
|
||||
if file.Ext() != ".js" {
|
||||
return
|
||||
}
|
||||
data, err := file.ReadAll()
|
||||
if err != nil {
|
||||
logs.Error(err)
|
||||
return
|
||||
}
|
||||
buffer.Write(data)
|
||||
buffer.Write([]byte{'\n', '\n'})
|
||||
})
|
||||
|
||||
// 条件组件
|
||||
typesJSON, err := json.Marshal(condutils.ReadAllAvailableCondTypes())
|
||||
if err != nil {
|
||||
logs.Println("ComponentsAction marshal request cond types failed: " + err.Error())
|
||||
} else {
|
||||
buffer.WriteString("window.REQUEST_COND_COMPONENTS = ")
|
||||
buffer.Write(typesJSON)
|
||||
buffer.Write([]byte{'\n', '\n'})
|
||||
}
|
||||
|
||||
// 条件操作符
|
||||
requestOperatorsJSON, err := json.Marshal(shared.AllRequestOperators())
|
||||
if err != nil {
|
||||
logs.Println("ComponentsAction marshal request operators failed: " + err.Error())
|
||||
} else {
|
||||
buffer.WriteString("window.REQUEST_COND_OPERATORS = ")
|
||||
buffer.Write(requestOperatorsJSON)
|
||||
buffer.Write([]byte{'\n', '\n'})
|
||||
}
|
||||
|
||||
// 请求变量
|
||||
requestVariablesJSON, err := json.Marshal(shared.DefaultRequestVariables())
|
||||
if err != nil {
|
||||
logs.Println("ComponentsAction marshal request variables failed: " + err.Error())
|
||||
} else {
|
||||
buffer.WriteString("window.REQUEST_VARIABLES = ")
|
||||
buffer.Write(requestVariablesJSON)
|
||||
buffer.Write([]byte{'\n', '\n'})
|
||||
}
|
||||
|
||||
// 指标
|
||||
metricHTTPKeysJSON, err := json.Marshal(serverconfigs.FindAllMetricKeyDefinitions(serverconfigs.MetricItemCategoryHTTP))
|
||||
if err != nil {
|
||||
logs.Println("ComponentsAction marshal metric http keys failed: " + err.Error())
|
||||
} else {
|
||||
buffer.WriteString("window.METRIC_HTTP_KEYS = ")
|
||||
buffer.Write(metricHTTPKeysJSON)
|
||||
buffer.Write([]byte{'\n', '\n'})
|
||||
}
|
||||
|
||||
// IP地址阈值项目
|
||||
ipAddrThresholdItemsJSON, err := json.Marshal(nodeconfigs.FindAllIPAddressThresholdItems())
|
||||
if err != nil {
|
||||
logs.Println("ComponentsAction marshal ip addr threshold items failed: " + err.Error())
|
||||
} else {
|
||||
buffer.WriteString("window.IP_ADDR_THRESHOLD_ITEMS = ")
|
||||
buffer.Write(ipAddrThresholdItemsJSON)
|
||||
buffer.Write([]byte{'\n', '\n'})
|
||||
}
|
||||
|
||||
// IP地址阈值动作
|
||||
ipAddrThresholdActionsJSON, err := json.Marshal(nodeconfigs.FindAllIPAddressThresholdActions())
|
||||
if err != nil {
|
||||
logs.Println("ComponentsAction marshal ip addr threshold actions failed: " + err.Error())
|
||||
} else {
|
||||
buffer.WriteString("window.IP_ADDR_THRESHOLD_ACTIONS = ")
|
||||
buffer.Write(ipAddrThresholdActionsJSON)
|
||||
buffer.Write([]byte{'\n', '\n'})
|
||||
}
|
||||
|
||||
fp, err := os.OpenFile(filepath.Clean(Tea.PublicFile("/js/components.js")), os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0777)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = io.Copy(fp, buffer)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
13
internal/gen/generate_test.go
Normal file
13
internal/gen/generate_test.go
Normal file
@@ -0,0 +1,13 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package gen
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestGenerate(t *testing.T) {
|
||||
err := Generate()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log("ok")
|
||||
}
|
||||
@@ -326,6 +326,16 @@ func (this *AdminNode) listenSock() error {
|
||||
case "demo":
|
||||
teaconst.IsDemoMode = !teaconst.IsDemoMode
|
||||
_ = cmd.ReplyOk()
|
||||
case "info":
|
||||
exePath, _ := os.Executable()
|
||||
_ = cmd.Reply(&gosock.Command{
|
||||
Code: "info",
|
||||
Params: map[string]interface{}{
|
||||
"pid": os.Getpid(),
|
||||
"version": teaconst.Version,
|
||||
"path": exePath,
|
||||
},
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
@@ -27,11 +27,11 @@ type RPCClient struct {
|
||||
apiConfig *configs.APIConfig
|
||||
conns []*grpc.ClientConn
|
||||
|
||||
locker sync.Mutex
|
||||
locker sync.RWMutex
|
||||
}
|
||||
|
||||
// NewRPCClient 构造新的RPC客户端
|
||||
func NewRPCClient(apiConfig *configs.APIConfig) (*RPCClient, error) {
|
||||
func NewRPCClient(apiConfig *configs.APIConfig, isPrimary bool) (*RPCClient, error) {
|
||||
if apiConfig == nil {
|
||||
return nil, errors.New("api config should not be nil")
|
||||
}
|
||||
@@ -46,7 +46,9 @@ func NewRPCClient(apiConfig *configs.APIConfig) (*RPCClient, error) {
|
||||
}
|
||||
|
||||
// 设置RPC
|
||||
dao.SetRPC(client)
|
||||
if isPrimary {
|
||||
dao.SetRPC(client)
|
||||
}
|
||||
|
||||
return client, nil
|
||||
}
|
||||
@@ -364,6 +366,14 @@ func (this *RPCClient) ACMETaskRPC() pb.ACMETaskServiceClient {
|
||||
return pb.NewACMETaskServiceClient(this.pickConn())
|
||||
}
|
||||
|
||||
func (this *RPCClient) ACMEProviderRPC() pb.ACMEProviderServiceClient {
|
||||
return pb.NewACMEProviderServiceClient(this.pickConn())
|
||||
}
|
||||
|
||||
func (this *RPCClient) ACMEProviderAccountRPC() pb.ACMEProviderAccountServiceClient {
|
||||
return pb.NewACMEProviderAccountServiceClient(this.pickConn())
|
||||
}
|
||||
|
||||
func (this *RPCClient) UserRPC() pb.UserServiceClient {
|
||||
return pb.NewUserServiceClient(this.pickConn())
|
||||
}
|
||||
@@ -372,6 +382,18 @@ func (this *RPCClient) UserBillRPC() pb.UserBillServiceClient {
|
||||
return pb.NewUserBillServiceClient(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 {
|
||||
return pb.NewUserAccessKeyServiceClient(this.pickConn())
|
||||
}
|
||||
@@ -456,6 +478,14 @@ func (this *RPCClient) ServerStatBoardChartRPC() pb.ServerStatBoardChartServiceC
|
||||
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())
|
||||
}
|
||||
|
||||
// Context 构造Admin上下文
|
||||
func (this *RPCClient) Context(adminId int64) context.Context {
|
||||
ctx := context.Background()
|
||||
@@ -505,7 +535,11 @@ func (this *RPCClient) APIContext(apiNodeId int64) context.Context {
|
||||
// UpdateConfig 修改配置
|
||||
func (this *RPCClient) UpdateConfig(config *configs.APIConfig) error {
|
||||
this.apiConfig = config
|
||||
return this.init()
|
||||
|
||||
this.locker.Lock()
|
||||
err := this.init()
|
||||
this.locker.Unlock()
|
||||
return err
|
||||
}
|
||||
|
||||
// 初始化
|
||||
@@ -583,3 +617,20 @@ func (this *RPCClient) pickConn() *grpc.ClientConn {
|
||||
|
||||
return this.conns[rands.Int(0, len(this.conns)-1)]
|
||||
}
|
||||
|
||||
// Close 关闭
|
||||
func (this *RPCClient) Close() error {
|
||||
this.locker.Lock()
|
||||
defer this.locker.Unlock()
|
||||
|
||||
var lastErr error
|
||||
for _, conn := range this.conns {
|
||||
var err = conn.Close()
|
||||
if err != nil {
|
||||
lastErr = err
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
return lastErr
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ func SharedRPC() (*RPCClient, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
client, err := NewRPCClient(config)
|
||||
client, err := NewRPCClient(config, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@ package setup
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/configs"
|
||||
teaconst "github.com/TeaOSLab/EdgeAdmin/internal/const"
|
||||
"os"
|
||||
)
|
||||
|
||||
var isConfigured bool
|
||||
@@ -16,3 +18,16 @@ func IsConfigured() bool {
|
||||
isConfigured = err == nil
|
||||
return isConfigured
|
||||
}
|
||||
|
||||
// IsNewInstalled IsNew 检查是否新安装
|
||||
func IsNewInstalled() bool {
|
||||
homeDir, err := os.UserHomeDir()
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
_, err = os.Stat(homeDir + "/." + teaconst.ProcessName + "/api.yaml")
|
||||
if err != nil {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ func (this *SyncAPINodesTask) Loop() error {
|
||||
}
|
||||
|
||||
newEndpoints := []string{}
|
||||
for _, node := range resp.Nodes {
|
||||
for _, node := range resp.ApiNodes {
|
||||
if !node.IsOn {
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/configutils"
|
||||
"github.com/miekg/dns"
|
||||
)
|
||||
|
||||
@@ -16,13 +17,19 @@ func LookupCNAME(host string) (string, error) {
|
||||
|
||||
m.SetQuestion(host+".", dns.TypeCNAME)
|
||||
m.RecursionDesired = true
|
||||
r, _, err := c.Exchange(m, config.Servers[0]+":"+config.Port)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if len(r.Answer) == 0 {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
return r.Answer[0].(*dns.CNAME).Target, nil
|
||||
var lastErr error
|
||||
for _, serverAddr := range config.Servers {
|
||||
r, _, err := c.Exchange(m, configutils.QuoteIP(serverAddr)+":"+config.Port)
|
||||
if err != nil {
|
||||
lastErr = err
|
||||
continue
|
||||
}
|
||||
if len(r.Answer) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
return r.Answer[0].(*dns.CNAME).Target, nil
|
||||
}
|
||||
return "", lastErr
|
||||
}
|
||||
|
||||
@@ -19,6 +19,8 @@ type ParentAction struct {
|
||||
actions.ActionObject
|
||||
|
||||
rpcClient *rpc.RPCClient
|
||||
|
||||
ctx context.Context
|
||||
}
|
||||
|
||||
// Parent 可以调用自身的一个简便方法
|
||||
@@ -117,6 +119,10 @@ func (this *ParentAction) RPC() *rpc.RPCClient {
|
||||
|
||||
// AdminContext 获取Context
|
||||
func (this *ParentAction) AdminContext() context.Context {
|
||||
if this.ctx != nil {
|
||||
return this.ctx
|
||||
}
|
||||
|
||||
if this.rpcClient == nil {
|
||||
rpcClient, err := rpc.SharedRPC()
|
||||
if err != nil {
|
||||
@@ -125,7 +131,8 @@ func (this *ParentAction) AdminContext() context.Context {
|
||||
}
|
||||
this.rpcClient = rpcClient
|
||||
}
|
||||
return this.rpcClient.Context(this.AdminId())
|
||||
this.ctx = this.rpcClient.Context(this.AdminId())
|
||||
return this.ctx
|
||||
}
|
||||
|
||||
// ViewData 视图里可以使用的数据
|
||||
|
||||
@@ -13,16 +13,35 @@ type DeleteAction struct {
|
||||
func (this *DeleteAction) RunPost(params struct {
|
||||
NodeId int64
|
||||
}) {
|
||||
// TODO 检查权限
|
||||
// 创建日志
|
||||
defer this.CreateLog(oplogs.LevelInfo, "删除API节点 %d", params.NodeId)
|
||||
|
||||
_, err := this.RPC().APINodeRPC().DeleteAPINode(this.AdminContext(), &pb.DeleteAPINodeRequest{NodeId: params.NodeId})
|
||||
// 检查是否是唯一的节点
|
||||
nodeResp, err := this.RPC().APINodeRPC().FindEnabledAPINode(this.AdminContext(), &pb.FindEnabledAPINodeRequest{ApiNodeId: params.NodeId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var apiNode = nodeResp.ApiNode
|
||||
if apiNode == nil {
|
||||
this.Success()
|
||||
}
|
||||
if apiNode.IsOn {
|
||||
countResp, err := this.RPC().APINodeRPC().CountAllEnabledAndOnAPINodes(this.AdminContext(), &pb.CountAllEnabledAndOnAPINodesRequest{})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if countResp.Count == 1 {
|
||||
this.Fail("无法删除此节点:必须保留至少一个可用的API节点")
|
||||
}
|
||||
}
|
||||
|
||||
_, err = this.RPC().APINodeRPC().DeleteAPINode(this.AdminContext(), &pb.DeleteAPINodeRequest{ApiNodeId: params.NodeId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
// 创建日志
|
||||
defer this.CreateLog(oplogs.LevelInfo, "删除API节点 %d", params.NodeId)
|
||||
|
||||
this.Success()
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ func (this *IndexAction) RunGet(params struct{}) {
|
||||
return
|
||||
}
|
||||
|
||||
for _, node := range nodesResp.Nodes {
|
||||
for _, node := range nodesResp.ApiNodes {
|
||||
// 状态
|
||||
status := &nodeconfigs.NodeStatus{}
|
||||
if len(node.StatusJSON) > 0 {
|
||||
|
||||
@@ -180,7 +180,7 @@ func (this *CreatePopupAction) RunPost(params struct {
|
||||
}
|
||||
|
||||
// 创建日志
|
||||
defer this.CreateLog(oplogs.LevelInfo, "创建API节点 %d", createResp.NodeId)
|
||||
defer this.CreateLog(oplogs.LevelInfo, "创建API节点 %d", createResp.ApiNodeId)
|
||||
|
||||
this.Success()
|
||||
}
|
||||
|
||||
@@ -20,12 +20,12 @@ func (this *IndexAction) Init() {
|
||||
func (this *IndexAction) RunGet(params struct {
|
||||
NodeId int64
|
||||
}) {
|
||||
nodeResp, err := this.RPC().APINodeRPC().FindEnabledAPINode(this.AdminContext(), &pb.FindEnabledAPINodeRequest{NodeId: params.NodeId})
|
||||
nodeResp, err := this.RPC().APINodeRPC().FindEnabledAPINode(this.AdminContext(), &pb.FindEnabledAPINodeRequest{ApiNodeId: params.NodeId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
node := nodeResp.Node
|
||||
node := nodeResp.ApiNode
|
||||
if node == nil {
|
||||
this.NotFound("apiNode", params.NodeId)
|
||||
return
|
||||
|
||||
@@ -21,12 +21,12 @@ func (this *InstallAction) RunGet(params struct {
|
||||
NodeId int64
|
||||
}) {
|
||||
// API节点信息
|
||||
nodeResp, err := this.RPC().APINodeRPC().FindEnabledAPINode(this.AdminContext(), &pb.FindEnabledAPINodeRequest{NodeId: params.NodeId})
|
||||
nodeResp, err := this.RPC().APINodeRPC().FindEnabledAPINode(this.AdminContext(), &pb.FindEnabledAPINodeRequest{ApiNodeId: params.NodeId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
node := nodeResp.Node
|
||||
node := nodeResp.ApiNode
|
||||
if node == nil {
|
||||
this.NotFound("apiNode", params.NodeId)
|
||||
return
|
||||
|
||||
@@ -31,12 +31,12 @@ func (this *LogsAction) RunGet(params struct {
|
||||
this.Data["keyword"] = params.Keyword
|
||||
this.Data["level"] = params.Level
|
||||
|
||||
apiNodeResp, err := this.RPC().APINodeRPC().FindEnabledAPINode(this.AdminContext(), &pb.FindEnabledAPINodeRequest{NodeId: params.NodeId})
|
||||
apiNodeResp, err := this.RPC().APINodeRPC().FindEnabledAPINode(this.AdminContext(), &pb.FindEnabledAPINodeRequest{ApiNodeId: params.NodeId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
apiNode := apiNodeResp.Node
|
||||
apiNode := apiNodeResp.ApiNode
|
||||
if apiNode == nil {
|
||||
this.NotFound("apiNode", params.NodeId)
|
||||
return
|
||||
|
||||
@@ -23,13 +23,13 @@ func (this *UpdateAction) RunGet(params struct {
|
||||
NodeId int64
|
||||
}) {
|
||||
nodeResp, err := this.RPC().APINodeRPC().FindEnabledAPINode(this.AdminContext(), &pb.FindEnabledAPINodeRequest{
|
||||
NodeId: params.NodeId,
|
||||
ApiNodeId: params.NodeId,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
node := nodeResp.Node
|
||||
node := nodeResp.ApiNode
|
||||
if node == nil {
|
||||
this.WriteString("要操作的节点不存在")
|
||||
return
|
||||
@@ -281,7 +281,7 @@ func (this *UpdateAction) RunPost(params struct {
|
||||
}
|
||||
|
||||
_, err = this.RPC().APINodeRPC().UpdateAPINode(this.AdminContext(), &pb.UpdateAPINodeRequest{
|
||||
NodeId: params.NodeId,
|
||||
ApiNodeId: params.NodeId,
|
||||
Name: params.Name,
|
||||
Description: params.Description,
|
||||
HttpJSON: httpJSON,
|
||||
|
||||
@@ -75,7 +75,7 @@ func (this *CreateNodeAction) RunGet(params struct {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
apiNodes := apiNodesResp.Nodes
|
||||
apiNodes := apiNodesResp.ApiNodes
|
||||
apiEndpoints := []string{}
|
||||
for _, apiNode := range apiNodes {
|
||||
if !apiNode.IsOn {
|
||||
|
||||
@@ -19,6 +19,7 @@ func init() {
|
||||
server.
|
||||
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeNode)).
|
||||
Helper(clusters.NewClusterHelper()).
|
||||
Data("teaMenu", "clusters").
|
||||
Prefix("/clusters/cluster").
|
||||
Get("", new(IndexAction)).
|
||||
Get("/nodes", new(NodesAction)).
|
||||
|
||||
@@ -49,7 +49,7 @@ func (this *InstallNodesAction) RunGet(params struct {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
for _, apiNode := range apiNodesResp.Nodes {
|
||||
for _, apiNode := range apiNodesResp.ApiNodes {
|
||||
if !apiNode.IsOn {
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ func (this *InstallAction) RunGet(params struct {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
apiNodes := apiNodesResp.Nodes
|
||||
apiNodes := apiNodesResp.ApiNodes
|
||||
apiEndpoints := []string{}
|
||||
for _, apiNode := range apiNodes {
|
||||
if !apiNode.IsOn {
|
||||
|
||||
@@ -69,6 +69,20 @@ func (this *LogsAction) RunGet(params struct {
|
||||
|
||||
logs := []maps.Map{}
|
||||
for _, log := range logsResp.NodeLogs {
|
||||
// 服务信息
|
||||
var serverMap = maps.Map{"id": 0}
|
||||
if log.ServerId > 0 {
|
||||
serverResp, err := this.RPC().ServerRPC().FindEnabledUserServerBasic(this.AdminContext(), &pb.FindEnabledUserServerBasicRequest{ServerId: log.ServerId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var server = serverResp.Server
|
||||
if server != nil {
|
||||
serverMap = maps.Map{"id": server.Id, "name": server.Name}
|
||||
}
|
||||
}
|
||||
|
||||
logs = append(logs, maps.Map{
|
||||
"tag": log.Tag,
|
||||
"description": log.Description,
|
||||
@@ -76,6 +90,7 @@ func (this *LogsAction) RunGet(params struct {
|
||||
"level": log.Level,
|
||||
"isToday": timeutil.FormatTime("Y-m-d", log.CreatedAt) == timeutil.Format("Y-m-d"),
|
||||
"count": log.Count,
|
||||
"server": serverMap,
|
||||
})
|
||||
}
|
||||
this.Data["logs"] = logs
|
||||
|
||||
@@ -4,6 +4,7 @@ package nodeutils
|
||||
|
||||
import (
|
||||
"errors"
|
||||
teaconst "github.com/TeaOSLab/EdgeAdmin/internal/const"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
@@ -49,7 +50,7 @@ func InitNodeInfo(parentAction *actionutils.ParentAction, nodeId int64) (*pb.Nod
|
||||
var query = "clusterId=" + types.String(clusterId) + "&nodeId=" + types.String(nodeId)
|
||||
var menuItem = parentAction.Data.GetString("secondMenuItem")
|
||||
|
||||
parentAction.Data["leftMenuItems"] = []maps.Map{
|
||||
var menuItems = []maps.Map{
|
||||
{
|
||||
"name": "基础设置",
|
||||
"url": prefix + "/update?" + query,
|
||||
@@ -65,11 +66,17 @@ func InitNodeInfo(parentAction *actionutils.ParentAction, nodeId int64) (*pb.Nod
|
||||
"url": prefix + "/settings/cache?" + query,
|
||||
"isActive": menuItem == "cache",
|
||||
},
|
||||
{
|
||||
"name": "阈值设置",
|
||||
"url": prefix + "/settings/thresholds?" + query,
|
||||
"isActive": menuItem == "threshold",
|
||||
},
|
||||
}
|
||||
if teaconst.IsPlus {
|
||||
menuItems = append(menuItems, []maps.Map{
|
||||
{
|
||||
"name": "阈值设置",
|
||||
"url": prefix + "/settings/thresholds?" + query,
|
||||
"isActive": menuItem == "threshold",
|
||||
},
|
||||
}...)
|
||||
}
|
||||
menuItems = append(menuItems, []maps.Map{
|
||||
{
|
||||
"name": "SSH设置",
|
||||
"url": prefix + "/settings/ssh?" + query,
|
||||
@@ -80,7 +87,8 @@ func InitNodeInfo(parentAction *actionutils.ParentAction, nodeId int64) (*pb.Nod
|
||||
"url": prefix + "/settings/system?" + query,
|
||||
"isActive": menuItem == "system",
|
||||
},
|
||||
}
|
||||
}...)
|
||||
parentAction.Data["leftMenuItems"] = menuItems
|
||||
|
||||
return nodeResp.Node, nil
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/oplogs"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/grants/grantutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
@@ -21,6 +22,7 @@ func (this *IndexAction) Init() {
|
||||
func (this *IndexAction) RunGet(params struct {
|
||||
ClusterId int64
|
||||
}) {
|
||||
// 基本信息
|
||||
clusterResp, err := this.RPC().NodeClusterRPC().FindEnabledNodeCluster(this.AdminContext(), &pb.FindEnabledNodeClusterRequest{NodeClusterId: params.ClusterId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
@@ -53,10 +55,20 @@ func (this *IndexAction) RunGet(params struct {
|
||||
}
|
||||
this.Data["grant"] = grantMap
|
||||
|
||||
// 时区
|
||||
this.Data["timeZoneGroups"] = nodeconfigs.FindAllTimeZoneGroups()
|
||||
this.Data["timeZoneLocations"] = nodeconfigs.FindAllTimeZoneLocations()
|
||||
|
||||
if len(cluster.TimeZone) == 0 {
|
||||
cluster.TimeZone = nodeconfigs.DefaultTimeZoneLocation
|
||||
}
|
||||
this.Data["timeZoneLocation"] = nodeconfigs.FindTimeZoneLocation(cluster.TimeZone)
|
||||
|
||||
this.Data["cluster"] = maps.Map{
|
||||
"id": cluster.Id,
|
||||
"name": cluster.Name,
|
||||
"installDir": cluster.InstallDir,
|
||||
"timeZone": cluster.TimeZone,
|
||||
}
|
||||
|
||||
this.Show()
|
||||
@@ -68,6 +80,7 @@ func (this *IndexAction) RunPost(params struct {
|
||||
Name string
|
||||
GrantId int64
|
||||
InstallDir string
|
||||
TimeZone string
|
||||
|
||||
Must *actions.Must
|
||||
}) {
|
||||
@@ -83,6 +96,7 @@ func (this *IndexAction) RunPost(params struct {
|
||||
Name: params.Name,
|
||||
NodeGrantId: params.GrantId,
|
||||
InstallDir: params.InstallDir,
|
||||
TimeZone: params.TimeZone,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
|
||||
@@ -12,7 +12,8 @@ func NewClustersHelper() *ClustersHelper {
|
||||
return &ClustersHelper{}
|
||||
}
|
||||
|
||||
func (this *ClustersHelper) BeforeAction(action *actions.ActionObject) {
|
||||
func (this *ClustersHelper) BeforeAction(actionPtr actions.ActionWrapper) {
|
||||
var action = actionPtr.Object()
|
||||
if action.Request.Method != http.MethodGet {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ func (this *CreateAction) RunPost(params struct {
|
||||
Username string
|
||||
Password string
|
||||
PrivateKey string
|
||||
Passphrase string
|
||||
Description string
|
||||
|
||||
Must *actions.Must
|
||||
@@ -58,6 +59,7 @@ func (this *CreateAction) RunPost(params struct {
|
||||
Username: params.Username,
|
||||
Password: params.Password,
|
||||
PrivateKey: params.PrivateKey,
|
||||
Passphrase: params.Passphrase,
|
||||
Description: params.Description,
|
||||
NodeId: 0,
|
||||
})
|
||||
|
||||
@@ -29,6 +29,7 @@ func (this *CreatePopupAction) RunPost(params struct {
|
||||
Username string
|
||||
Password string
|
||||
PrivateKey string
|
||||
Passphrase string
|
||||
Description string
|
||||
|
||||
Must *actions.Must
|
||||
@@ -59,6 +60,7 @@ func (this *CreatePopupAction) RunPost(params struct {
|
||||
Username: params.Username,
|
||||
Password: params.Password,
|
||||
PrivateKey: params.PrivateKey,
|
||||
Passphrase: params.Passphrase,
|
||||
Description: params.Description,
|
||||
NodeId: 0,
|
||||
})
|
||||
|
||||
@@ -40,6 +40,7 @@ func (this *GrantAction) RunGet(params struct {
|
||||
"username": grant.Username,
|
||||
"password": strings.Repeat("*", len(grant.Password)),
|
||||
"privateKey": grant.PrivateKey,
|
||||
"passphrase": strings.Repeat("*", len(grant.Passphrase)),
|
||||
"description": grant.Description,
|
||||
"su": grant.Su,
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ func init() {
|
||||
server.
|
||||
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeNode)).
|
||||
Helper(clusterutils.NewClustersHelper()).
|
||||
Data("teaMenu", "clusters").
|
||||
Data("teaSubMenu", "grant").
|
||||
Prefix("/clusters/grants").
|
||||
|
||||
|
||||
@@ -43,6 +43,7 @@ func (this *UpdateAction) RunGet(params struct {
|
||||
"username": grant.Username,
|
||||
"password": grant.Password,
|
||||
"privateKey": grant.PrivateKey,
|
||||
"passphrase": grant.Passphrase,
|
||||
"description": grant.Description,
|
||||
"su": grant.Su,
|
||||
}
|
||||
@@ -57,6 +58,7 @@ func (this *UpdateAction) RunPost(params struct {
|
||||
Username string
|
||||
Password string
|
||||
PrivateKey string
|
||||
Passphrase string
|
||||
Description string
|
||||
|
||||
Must *actions.Must
|
||||
@@ -93,6 +95,7 @@ func (this *UpdateAction) RunPost(params struct {
|
||||
Username: params.Username,
|
||||
Password: params.Password,
|
||||
PrivateKey: params.PrivateKey,
|
||||
Passphrase: params.Passphrase,
|
||||
Description: params.Description,
|
||||
NodeId: 0,
|
||||
})
|
||||
|
||||
@@ -43,6 +43,7 @@ func (this *UpdatePopupAction) RunGet(params struct {
|
||||
"password": grant.Password,
|
||||
"description": grant.Description,
|
||||
"privateKey": grant.PrivateKey,
|
||||
"passphrase": grant.Passphrase,
|
||||
}
|
||||
|
||||
this.Show()
|
||||
@@ -56,6 +57,7 @@ func (this *UpdatePopupAction) RunPost(params struct {
|
||||
Username string
|
||||
Password string
|
||||
PrivateKey string
|
||||
Passphrase string
|
||||
Description string
|
||||
|
||||
Must *actions.Must
|
||||
@@ -91,6 +93,7 @@ func (this *UpdatePopupAction) RunPost(params struct {
|
||||
Username: params.Username,
|
||||
Password: params.Password,
|
||||
PrivateKey: params.PrivateKey,
|
||||
Passphrase: params.Passphrase,
|
||||
Description: params.Description,
|
||||
NodeId: params.NodeId,
|
||||
})
|
||||
|
||||
@@ -121,6 +121,10 @@ func (this *IndexAction) RunGet(params struct {
|
||||
this.ErrorPage(err)
|
||||
}
|
||||
|
||||
if cluster.TimeZone == nodeconfigs.DefaultTimeZoneLocation {
|
||||
cluster.TimeZone = ""
|
||||
}
|
||||
|
||||
clusterMaps = append(clusterMaps, maps.Map{
|
||||
"id": cluster.Id,
|
||||
"name": cluster.Name,
|
||||
@@ -132,6 +136,7 @@ func (this *IndexAction) RunGet(params struct {
|
||||
"dnsName": cluster.DnsName,
|
||||
"dnsDomainName": dnsDomainName,
|
||||
"countServers": countServersResp.Count,
|
||||
"timeZone": cluster.TimeZone,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ func init() {
|
||||
server.
|
||||
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeNode)).
|
||||
Helper(clusterutils.NewClustersHelper()).
|
||||
Data("teaMenu", "clusters").
|
||||
Prefix("/clusters").
|
||||
Get("", new(IndexAction)).
|
||||
GetPost("/create", new(CreateAction)).
|
||||
|
||||
@@ -2,6 +2,7 @@ package logs
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
@@ -12,6 +13,11 @@ type IndexAction struct {
|
||||
}
|
||||
|
||||
func (this *IndexAction) Init() {
|
||||
if this.ParamString("type") == "unread" {
|
||||
this.FirstMenu("unread")
|
||||
} else {
|
||||
this.FirstMenu("index")
|
||||
}
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct {
|
||||
@@ -19,19 +25,34 @@ func (this *IndexAction) RunGet(params struct {
|
||||
DayTo string
|
||||
Keyword string
|
||||
Level string
|
||||
Type string
|
||||
}) {
|
||||
this.Data["dayFrom"] = params.DayFrom
|
||||
this.Data["dayTo"] = params.DayTo
|
||||
this.Data["keyword"] = params.Keyword
|
||||
this.Data["level"] = params.Level
|
||||
this.Data["type"] = params.Type
|
||||
|
||||
// 未读数量
|
||||
countUnreadResp, err := this.RPC().NodeLogRPC().CountNodeLogs(this.AdminContext(), &pb.CountNodeLogsRequest{
|
||||
Role: nodeconfigs.NodeRoleNode,
|
||||
IsUnread: true,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
this.Data["countUnreadLogs"] = countUnreadResp.Count
|
||||
|
||||
// 日志数量
|
||||
countResp, err := this.RPC().NodeLogRPC().CountNodeLogs(this.AdminContext(), &pb.CountNodeLogsRequest{
|
||||
NodeId: 0,
|
||||
Role: "node",
|
||||
DayFrom: params.DayFrom,
|
||||
DayTo: params.DayTo,
|
||||
Keyword: params.Keyword,
|
||||
Level: params.Level,
|
||||
NodeId: 0,
|
||||
Role: nodeconfigs.NodeRoleNode,
|
||||
DayFrom: params.DayFrom,
|
||||
DayTo: params.DayTo,
|
||||
Keyword: params.Keyword,
|
||||
Level: params.Level,
|
||||
IsUnread: params.Type == "unread",
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
@@ -42,14 +63,15 @@ func (this *IndexAction) RunGet(params struct {
|
||||
this.Data["page"] = page.AsHTML()
|
||||
|
||||
logsResp, err := this.RPC().NodeLogRPC().ListNodeLogs(this.AdminContext(), &pb.ListNodeLogsRequest{
|
||||
NodeId: 0,
|
||||
Role: "node",
|
||||
DayFrom: params.DayFrom,
|
||||
DayTo: params.DayTo,
|
||||
Keyword: params.Keyword,
|
||||
Level: params.Level,
|
||||
Offset: page.Offset,
|
||||
Size: page.Size,
|
||||
NodeId: 0,
|
||||
Role: nodeconfigs.NodeRoleNode,
|
||||
DayFrom: params.DayFrom,
|
||||
DayTo: params.DayTo,
|
||||
Keyword: params.Keyword,
|
||||
Level: params.Level,
|
||||
IsUnread: params.Type == "unread",
|
||||
Offset: page.Offset,
|
||||
Size: page.Size,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
@@ -68,13 +90,29 @@ func (this *IndexAction) RunGet(params struct {
|
||||
continue
|
||||
}
|
||||
|
||||
// 服务信息
|
||||
var serverMap = maps.Map{"id": 0}
|
||||
if log.ServerId > 0 {
|
||||
serverResp, err := this.RPC().ServerRPC().FindEnabledUserServerBasic(this.AdminContext(), &pb.FindEnabledUserServerBasicRequest{ServerId: log.ServerId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var server = serverResp.Server
|
||||
if server != nil {
|
||||
serverMap = maps.Map{"id": server.Id, "name": server.Name}
|
||||
}
|
||||
}
|
||||
|
||||
logs = append(logs, maps.Map{
|
||||
"id": log.Id,
|
||||
"tag": log.Tag,
|
||||
"description": log.Description,
|
||||
"createdTime": timeutil.FormatTime("Y-m-d H:i:s", log.CreatedAt),
|
||||
"level": log.Level,
|
||||
"isToday": timeutil.FormatTime("Y-m-d", log.CreatedAt) == timeutil.Format("Y-m-d"),
|
||||
"count": log.Count,
|
||||
"isRead": log.IsRead,
|
||||
"node": maps.Map{
|
||||
"id": node.Id,
|
||||
"cluster": maps.Map{
|
||||
@@ -83,6 +121,7 @@ func (this *IndexAction) RunGet(params struct {
|
||||
},
|
||||
"name": node.Name,
|
||||
},
|
||||
"server": serverMap,
|
||||
})
|
||||
}
|
||||
this.Data["logs"] = logs
|
||||
|
||||
@@ -14,6 +14,8 @@ func init() {
|
||||
Data("teaSubMenu", "log").
|
||||
Prefix("/clusters/logs").
|
||||
Get("", new(IndexAction)).
|
||||
Post("/readLogs", new(ReadLogsAction)).
|
||||
Post("/readAllLogs", new(ReadAllLogsAction)).
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
|
||||
24
internal/web/actions/default/clusters/logs/readAllLogs.go
Normal file
24
internal/web/actions/default/clusters/logs/readAllLogs.go
Normal file
@@ -0,0 +1,24 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package logs
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
)
|
||||
|
||||
type ReadAllLogsAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *ReadAllLogsAction) RunPost(params struct {
|
||||
LogIds []int64
|
||||
}) {
|
||||
_, err := this.RPC().NodeLogRPC().UpdateAllNodeLogsRead(this.AdminContext(), &pb.UpdateAllNodeLogsReadRequest{})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
26
internal/web/actions/default/clusters/logs/readLogs.go
Normal file
26
internal/web/actions/default/clusters/logs/readLogs.go
Normal file
@@ -0,0 +1,26 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package logs
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
)
|
||||
|
||||
type ReadLogsAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *ReadLogsAction) RunPost(params struct {
|
||||
LogIds []int64
|
||||
}) {
|
||||
_, err := this.RPC().NodeLogRPC().UpdateNodeLogsRead(this.AdminContext(), &pb.UpdateNodeLogsReadRequest{
|
||||
NodeLogIds: params.LogIds,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -21,6 +21,7 @@ func (this *SelectPopupAction) Init() {
|
||||
func (this *SelectPopupAction) RunGet(params struct {
|
||||
SelectedClusterIds string
|
||||
Keyword string
|
||||
PageSize int64
|
||||
}) {
|
||||
this.Data["keyword"] = params.Keyword
|
||||
|
||||
@@ -36,6 +37,9 @@ func (this *SelectPopupAction) RunGet(params struct {
|
||||
var count = countResp.Count
|
||||
var page = this.NewPage(count)
|
||||
page.Size = 6
|
||||
if params.PageSize > 0 {
|
||||
page.Size = params.PageSize
|
||||
}
|
||||
this.Data["page"] = page.AsHTML()
|
||||
|
||||
clustersResp, err := this.RPC().NodeClusterRPC().ListEnabledNodeClusters(this.AdminContext(), &pb.ListEnabledNodeClustersRequest{
|
||||
|
||||
@@ -55,13 +55,16 @@ func (this *IndexAction) RunPost(params struct{}) {
|
||||
this.Data["dashboard"] = maps.Map{
|
||||
"defaultClusterId": resp.DefaultNodeClusterId,
|
||||
|
||||
"countServers": resp.CountServers,
|
||||
"countNodeClusters": resp.CountNodeClusters,
|
||||
"countNodes": resp.CountNodes,
|
||||
"countUsers": resp.CountUsers,
|
||||
"countAPINodes": resp.CountAPINodes,
|
||||
"countDBNodes": resp.CountDBNodes,
|
||||
"countUserNodes": resp.CountUserNodes,
|
||||
"countServers": resp.CountServers,
|
||||
"countNodeClusters": resp.CountNodeClusters,
|
||||
"countNodes": resp.CountNodes,
|
||||
"countOfflineNodes": resp.CountOfflineNodes,
|
||||
"countUsers": resp.CountUsers,
|
||||
"countAPINodes": resp.CountAPINodes,
|
||||
"countOfflineAPINodes": resp.CountOfflineAPINodes,
|
||||
"countDBNodes": resp.CountDBNodes,
|
||||
"countUserNodes": resp.CountUserNodes,
|
||||
"countOfflineUserNodes": resp.CountOfflineUserNodes,
|
||||
|
||||
"canGoServers": configloaders.AllowModule(this.AdminId(), configloaders.AdminModuleCodeServer),
|
||||
"canGoNodes": configloaders.AllowModule(this.AdminId(), configloaders.AdminModuleCodeNode),
|
||||
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
// 域名列表选项
|
||||
// DomainOptionsAction 域名列表选项
|
||||
type DomainOptionsAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
@@ -23,8 +23,8 @@ func (this *DomainOptionsAction) RunPost(params struct {
|
||||
}
|
||||
domainMaps := []maps.Map{}
|
||||
for _, domain := range domainsResp.DnsDomains {
|
||||
// 未开启的先跳过
|
||||
if !domain.IsOn {
|
||||
// 未开启或者已删除的先跳过
|
||||
if !domain.IsOn || domain.IsDeleted {
|
||||
continue
|
||||
}
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@ func ValidateRecordName(name string) bool {
|
||||
strings.HasSuffix(piece, "-") ||
|
||||
strings.Contains(piece, "--") ||
|
||||
len(piece) > 63 ||
|
||||
!regexp.MustCompile(`^[a-z0-9-]+$`).MatchString(piece) {
|
||||
!regexp.MustCompile(`^[_a-z0-9-]+$`).MatchString(piece) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
27
internal/web/actions/default/dns/domains/recover.go
Normal file
27
internal/web/actions/default/dns/domains/recover.go
Normal file
@@ -0,0 +1,27 @@
|
||||
package domains
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/oplogs"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
)
|
||||
|
||||
type RecoverAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *RecoverAction) RunPost(params struct {
|
||||
DomainId int64
|
||||
}) {
|
||||
// 记录日志
|
||||
defer this.CreateLog(oplogs.LevelInfo, "从DNS服务商中恢复域名 %d", params.DomainId)
|
||||
|
||||
// 执行恢复
|
||||
_, err := this.RPC().DNSDomainRPC().RecoverDNSDomain(this.AdminContext(), &pb.RecoverDNSDomainRequest{DnsDomainId: params.DomainId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -52,7 +52,7 @@ func (this *UpdatePopupAction) RunPost(params struct {
|
||||
// TODO 检查DomainId
|
||||
|
||||
// 记录日志
|
||||
defer this.CreateLog(oplogs.LevelInfo, "修改管理域名到DNS服务商 %d", params.DomainId)
|
||||
defer this.CreateLog(oplogs.LevelInfo, "修改DNS服务商域名 %d", params.DomainId)
|
||||
|
||||
params.Must.
|
||||
Field("name", params.Name).
|
||||
|
||||
@@ -43,6 +43,7 @@ func init() {
|
||||
GetPost("/createPopup", new(domains.CreatePopupAction)).
|
||||
GetPost("/updatePopup", new(domains.UpdatePopupAction)).
|
||||
Post("/delete", new(domains.DeleteAction)).
|
||||
Post("/recover", new(domains.RecoverAction)).
|
||||
Post("/sync", new(domains.SyncAction)).
|
||||
Get("/routesPopup", new(domains.RoutesPopupAction)).
|
||||
GetPost("/selectPopup", new(domains.SelectPopupAction)).
|
||||
|
||||
@@ -83,6 +83,7 @@ func (this *ProviderAction) RunGet(params struct {
|
||||
"name": domain.Name,
|
||||
"isOn": domain.IsOn,
|
||||
"isUp": domain.IsUp,
|
||||
"isDeleted": domain.IsDeleted,
|
||||
"dataUpdatedTime": dataUpdatedTime,
|
||||
"countRoutes": len(domain.Routes),
|
||||
"countServerRecords": domain.CountServerRecords,
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
package bills
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
"time"
|
||||
)
|
||||
|
||||
type GenerateAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *GenerateAction) Init() {
|
||||
this.Nav("", "", "generate")
|
||||
}
|
||||
|
||||
func (this *GenerateAction) RunGet(params struct{}) {
|
||||
this.Data["month"] = timeutil.Format("Ym", time.Now().AddDate(0, -1, 0))
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *GenerateAction) RunPost(params struct {
|
||||
Month string
|
||||
|
||||
Must *actions.Must
|
||||
}) {
|
||||
defer this.CreateLogInfo("手动生成上个月(" + params.Month + ")账单")
|
||||
|
||||
_, err := this.RPC().UserBillRPC().GenerateAllUserBills(this.AdminContext(), &pb.GenerateAllUserBillsRequest{Month: params.Month})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
this.Success()
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
package bills
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
type IndexAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *IndexAction) Init() {
|
||||
this.Nav("", "", "index")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct {
|
||||
PaidFlag int32 `default:"-1"`
|
||||
UserId int64
|
||||
Month string
|
||||
}) {
|
||||
countResp, err := this.RPC().UserBillRPC().CountAllUserBills(this.AdminContext(), &pb.CountAllUserBillsRequest{})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
page := this.NewPage(countResp.Count)
|
||||
this.Data["page"] = page.AsHTML()
|
||||
|
||||
billsResp, err := this.RPC().UserBillRPC().ListUserBills(this.AdminContext(), &pb.ListUserBillsRequest{
|
||||
PaidFlag: params.PaidFlag,
|
||||
UserId: params.UserId,
|
||||
Month: params.Month,
|
||||
Offset: page.Offset,
|
||||
Size: page.Size,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
billMaps := []maps.Map{}
|
||||
for _, bill := range billsResp.UserBills {
|
||||
var userMap maps.Map = nil
|
||||
if bill.User != nil {
|
||||
userMap = maps.Map{
|
||||
"id": bill.User.Id,
|
||||
"fullname": bill.User.Fullname,
|
||||
}
|
||||
}
|
||||
billMaps = append(billMaps, maps.Map{
|
||||
"id": bill.Id,
|
||||
"isPaid": bill.IsPaid,
|
||||
"month": bill.Month,
|
||||
"amount": fmt.Sprintf("%.2f", bill.Amount),
|
||||
"typeName": bill.TypeName,
|
||||
"user": userMap,
|
||||
"description": bill.Description,
|
||||
})
|
||||
}
|
||||
this.Data["bills"] = billMaps
|
||||
|
||||
this.Show()
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
package bills
|
||||
|
||||
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.AdminModuleCodeFinance)).
|
||||
Data("teaMenu", "finance").
|
||||
|
||||
// 财务管理
|
||||
Prefix("/finance/bills").
|
||||
Get("", new(IndexAction)).
|
||||
GetPost("/generate", new(GenerateAction)).
|
||||
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
@@ -43,6 +43,12 @@ func (this *IndexAction) RunGet(params struct {
|
||||
return
|
||||
}
|
||||
|
||||
//// 是否新安装
|
||||
if setup.IsNewInstalled() {
|
||||
this.RedirectURL("/setup/confirm")
|
||||
return
|
||||
}
|
||||
|
||||
// 已登录跳转到dashboard
|
||||
if params.Auth.IsUser() {
|
||||
this.RedirectURL("/dashboard")
|
||||
|
||||
@@ -48,6 +48,7 @@ func SendMessageToCluster(ctx context.Context, clusterId int64, code string, msg
|
||||
|
||||
wg := &sync.WaitGroup{}
|
||||
wg.Add(len(nodes))
|
||||
|
||||
for _, node := range nodes {
|
||||
// TODO 检查是否在线
|
||||
|
||||
@@ -68,7 +69,7 @@ func SendMessageToCluster(ctx context.Context, clusterId int64, code string, msg
|
||||
apiNodeId := node.ConnectedAPINodeIds[0]
|
||||
rpcClient, ok := rpcMap[apiNodeId]
|
||||
if !ok {
|
||||
apiNodeResp, err := defaultRPCClient.APINodeRPC().FindEnabledAPINode(ctx, &pb.FindEnabledAPINodeRequest{NodeId: apiNodeId})
|
||||
apiNodeResp, err := defaultRPCClient.APINodeRPC().FindEnabledAPINode(ctx, &pb.FindEnabledAPINodeRequest{ApiNodeId: apiNodeId})
|
||||
if err != nil {
|
||||
locker.Lock()
|
||||
results = append(results, &MessageResult{
|
||||
@@ -82,7 +83,7 @@ func SendMessageToCluster(ctx context.Context, clusterId int64, code string, msg
|
||||
continue
|
||||
}
|
||||
|
||||
if apiNodeResp.Node == nil {
|
||||
if apiNodeResp.ApiNode == nil {
|
||||
locker.Lock()
|
||||
results = append(results, &MessageResult{
|
||||
NodeId: node.Id,
|
||||
@@ -94,7 +95,7 @@ func SendMessageToCluster(ctx context.Context, clusterId int64, code string, msg
|
||||
wg.Done()
|
||||
continue
|
||||
}
|
||||
apiNode := apiNodeResp.Node
|
||||
apiNode := apiNodeResp.ApiNode
|
||||
|
||||
apiRPCClient, err := rpc.NewRPCClient(&configs.APIConfig{
|
||||
RPC: struct {
|
||||
@@ -104,7 +105,7 @@ func SendMessageToCluster(ctx context.Context, clusterId int64, code string, msg
|
||||
},
|
||||
NodeId: apiNode.UniqueId,
|
||||
Secret: apiNode.Secret,
|
||||
})
|
||||
}, false)
|
||||
if err != nil {
|
||||
locker.Lock()
|
||||
results = append(results, &MessageResult{
|
||||
@@ -162,6 +163,11 @@ func SendMessageToCluster(ctx context.Context, clusterId int64, code string, msg
|
||||
})
|
||||
}
|
||||
|
||||
// 关闭RPC
|
||||
for _, rpcClient := range rpcMap {
|
||||
_ = rpcClient.Close()
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -243,7 +249,7 @@ func SendMessageToNodeIds(ctx context.Context, nodeIds []int64, code string, msg
|
||||
apiNodeId := node.ConnectedAPINodeIds[0]
|
||||
rpcClient, ok := rpcMap[apiNodeId]
|
||||
if !ok {
|
||||
apiNodeResp, err := defaultRPCClient.APINodeRPC().FindEnabledAPINode(ctx, &pb.FindEnabledAPINodeRequest{NodeId: apiNodeId})
|
||||
apiNodeResp, err := defaultRPCClient.APINodeRPC().FindEnabledAPINode(ctx, &pb.FindEnabledAPINodeRequest{ApiNodeId: apiNodeId})
|
||||
if err != nil {
|
||||
locker.Lock()
|
||||
results = append(results, &MessageResult{
|
||||
@@ -257,7 +263,7 @@ func SendMessageToNodeIds(ctx context.Context, nodeIds []int64, code string, msg
|
||||
continue
|
||||
}
|
||||
|
||||
if apiNodeResp.Node == nil {
|
||||
if apiNodeResp.ApiNode == nil {
|
||||
locker.Lock()
|
||||
results = append(results, &MessageResult{
|
||||
NodeId: node.Id,
|
||||
@@ -269,7 +275,7 @@ func SendMessageToNodeIds(ctx context.Context, nodeIds []int64, code string, msg
|
||||
wg.Done()
|
||||
continue
|
||||
}
|
||||
apiNode := apiNodeResp.Node
|
||||
apiNode := apiNodeResp.ApiNode
|
||||
|
||||
apiRPCClient, err := rpc.NewRPCClient(&configs.APIConfig{
|
||||
RPC: struct {
|
||||
@@ -279,7 +285,7 @@ func SendMessageToNodeIds(ctx context.Context, nodeIds []int64, code string, msg
|
||||
},
|
||||
NodeId: apiNode.UniqueId,
|
||||
Secret: apiNode.Secret,
|
||||
})
|
||||
}, false)
|
||||
if err != nil {
|
||||
locker.Lock()
|
||||
results = append(results, &MessageResult{
|
||||
@@ -337,5 +343,10 @@ func SendMessageToNodeIds(ctx context.Context, nodeIds []int64, code string, msg
|
||||
})
|
||||
}
|
||||
|
||||
// 关闭RPC
|
||||
for _, rpcClient := range rpcMap {
|
||||
_ = rpcClient.Close()
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
package cluster
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/ns/clusters/cluster/node"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/ns/clusters/clusterutils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
|
||||
"github.com/iwind/TeaGo"
|
||||
)
|
||||
|
||||
func init() {
|
||||
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
||||
server.
|
||||
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeNS)).
|
||||
Helper(new(clusterutils.ClusterHelper)).
|
||||
Data("teaMenu", "ns").
|
||||
Data("teaSubMenu", "cluster").
|
||||
Prefix("/ns/clusters/cluster").
|
||||
Get("", new(IndexAction)).
|
||||
GetPost("/delete", new(DeleteAction)).
|
||||
GetPost("/createNode", new(CreateNodeAction)).
|
||||
Post("/deleteNode", new(DeleteNodeAction)).
|
||||
Get("/upgradeRemote", new(UpgradeRemoteAction)).
|
||||
GetPost("/updateNodeSSH", new(UpdateNodeSSHAction)).
|
||||
|
||||
// 节点相关
|
||||
Prefix("/ns/clusters/cluster/node").
|
||||
Get("", new(node.IndexAction)).
|
||||
Get("/logs", new(node.LogsAction)).
|
||||
GetPost("/update", new(node.UpdateAction)).
|
||||
GetPost("/install", new(node.InstallAction)).
|
||||
Post("/status", new(node.StatusAction)).
|
||||
Post("/updateInstallStatus", new(node.UpdateInstallStatusAction)).
|
||||
Post("/start", new(node.StartAction)).
|
||||
Post("/stop", new(node.StopAction)).
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
@@ -73,7 +73,7 @@ func (this *InstallAction) RunGet(params struct {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
apiNodes := apiNodesResp.Nodes
|
||||
apiNodes := apiNodesResp.ApiNodes
|
||||
apiEndpoints := []string{}
|
||||
for _, apiNode := range apiNodes {
|
||||
if !apiNode.IsOn {
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
package accessLog
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/ns/clusters/clusterutils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
|
||||
"github.com/iwind/TeaGo"
|
||||
)
|
||||
|
||||
func init() {
|
||||
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
||||
server.
|
||||
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeNS)).
|
||||
Helper(new(clusterutils.ClusterHelper)).
|
||||
Data("teaMenu", "ns").
|
||||
Data("teaSubMenu", "cluster").
|
||||
Prefix("/ns/clusters/cluster/settings/accessLog").
|
||||
GetPost("", new(IndexAction)).
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
package cluster
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/ns/clusters/clusterutils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
|
||||
"github.com/iwind/TeaGo"
|
||||
)
|
||||
|
||||
func init() {
|
||||
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
||||
server.
|
||||
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeNS)).
|
||||
Helper(new(clusterutils.ClusterHelper)).
|
||||
Data("teaMenu", "ns").
|
||||
Data("teaSubMenu", "cluster").
|
||||
Prefix("/ns/clusters/cluster/settings").
|
||||
GetPost("", new(IndexAction)).
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
package recursion
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/ns/clusters/clusterutils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
|
||||
"github.com/iwind/TeaGo"
|
||||
)
|
||||
|
||||
func init() {
|
||||
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
||||
server.
|
||||
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeNS)).
|
||||
Helper(new(clusterutils.ClusterHelper)).
|
||||
Data("teaMenu", "ns").
|
||||
Data("teaSubMenu", "cluster").
|
||||
Prefix("/ns/clusters/cluster/settings/recursion").
|
||||
GetPost("", new(IndexAction)).
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
package clusters
|
||||
|
||||
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.AdminModuleCodeNS)).
|
||||
Data("teaMenu", "ns").
|
||||
Data("teaSubMenu", "cluster").
|
||||
Prefix("/ns/clusters").
|
||||
Get("", new(IndexAction)).
|
||||
GetPost("/create", new(CreateAction)).
|
||||
Post("/options", new(OptionsAction)).
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
package logs
|
||||
|
||||
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.AdminModuleCodeNS)).
|
||||
Data("teaMenu", "ns").
|
||||
Data("teaSubMenu", "log").
|
||||
Prefix("/ns/clusters/logs").
|
||||
Get("", new(IndexAction)).
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
package clusters
|
||||
|
||||
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.AdminModuleCodeNS)).
|
||||
Data("teaMenu", "ns").
|
||||
Data("teaSubMenu", "route").
|
||||
Prefix("/ns/routes").
|
||||
Get("", new(IndexAction)).
|
||||
Get("/route", new(RouteAction)).
|
||||
GetPost("/createPopup", new(CreatePopupAction)).
|
||||
GetPost("/updatePopup", new(UpdatePopupAction)).
|
||||
Post("/delete", new(DeleteAction)).
|
||||
Post("/sort", new(SortAction)).
|
||||
Post("/options", new(OptionsAction)).
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package accesslogs
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/ns/settings/settingutils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
|
||||
"github.com/iwind/TeaGo"
|
||||
)
|
||||
|
||||
func init() {
|
||||
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
||||
server.
|
||||
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeNS)).
|
||||
Helper(new(settingutils.Helper)).
|
||||
Data("teaMenu", "ns").
|
||||
Data("teaSubMenu", "setting").
|
||||
Prefix("/ns/settings/accesslogs").
|
||||
GetPost("", new(IndexAction)).
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
package users
|
||||
|
||||
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.AdminModuleCodeNS)).
|
||||
Data("teaMenu", "ns").
|
||||
Data("teaSubMenu", "domain").
|
||||
Prefix("/ns/users").
|
||||
Post("/options", new(OptionsAction)).
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
@@ -42,7 +42,7 @@ func (this *UpdateHostsAction) RunPost(params struct {
|
||||
},
|
||||
NodeId: params.NodeId,
|
||||
Secret: params.NodeSecret,
|
||||
})
|
||||
}, false)
|
||||
if err != nil {
|
||||
this.FailField("host", "测试API节点时出错,请检查配置,错误信息:"+err.Error())
|
||||
}
|
||||
@@ -51,6 +51,10 @@ func (this *UpdateHostsAction) RunPost(params struct {
|
||||
this.FailField("host", "无法连接此API节点,错误信息:"+err.Error())
|
||||
}
|
||||
|
||||
defer func() {
|
||||
_ = client.Close()
|
||||
}()
|
||||
|
||||
// 获取管理员节点信息
|
||||
apiTokensResp, err := client.APITokenRPC().FindAllEnabledAPITokens(client.APIContext(0), &pb.FindAllEnabledAPITokensRequest{Role: "admin"})
|
||||
if err != nil {
|
||||
@@ -69,7 +73,7 @@ func (this *UpdateHostsAction) RunPost(params struct {
|
||||
this.Fail("获取API节点列表失败,错误信息:" + err.Error())
|
||||
}
|
||||
var endpoints = []string{}
|
||||
for _, node := range nodesResp.Nodes {
|
||||
for _, node := range nodesResp.ApiNodes {
|
||||
if !node.IsOn {
|
||||
continue
|
||||
}
|
||||
@@ -144,7 +148,7 @@ func (this *UpdateHostsAction) RunPost(params struct {
|
||||
|
||||
// 保存
|
||||
_, err = client.APINodeRPC().UpdateAPINode(client.Context(0), &pb.UpdateAPINodeRequest{
|
||||
NodeId: node.Id,
|
||||
ApiNodeId: node.Id,
|
||||
Name: node.Name,
|
||||
Description: node.Description,
|
||||
HttpJSON: node.HttpJSON,
|
||||
|
||||
@@ -49,10 +49,15 @@ func (this *ValidateApiAction) RunPost(params struct {
|
||||
},
|
||||
NodeId: params.NodeId,
|
||||
Secret: params.NodeSecret,
|
||||
})
|
||||
}, false)
|
||||
if err != nil {
|
||||
this.FailField("host", "测试API节点时出错,请检查配置,错误信息:"+err.Error())
|
||||
}
|
||||
|
||||
defer func() {
|
||||
_ = client.Close()
|
||||
}()
|
||||
|
||||
_, err = client.APINodeRPC().FindCurrentAPINodeVersion(client.APIContext(0), &pb.FindCurrentAPINodeVersionRequest{})
|
||||
if err != nil {
|
||||
this.FailField("host", "无法连接此API节点,错误信息:"+err.Error())
|
||||
@@ -64,7 +69,7 @@ func (this *ValidateApiAction) RunPost(params struct {
|
||||
this.Fail("获取API节点列表失败,错误信息:" + err.Error())
|
||||
}
|
||||
var hosts = []string{}
|
||||
for _, node := range nodesResp.Nodes {
|
||||
for _, node := range nodesResp.ApiNodes {
|
||||
if !node.IsOn {
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package ipbox
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
|
||||
"github.com/iwind/TeaGo"
|
||||
)
|
||||
|
||||
func init() {
|
||||
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
||||
server.
|
||||
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeServer)).
|
||||
Prefix("/servers/accesslogs").
|
||||
Data("teaMenu", "servers").
|
||||
Data("teaSubMenu", "accesslog").
|
||||
Get("", new(IndexAction)).
|
||||
GetPost("/createPopup", new(CreatePopupAction)).
|
||||
Get("/policy", new(PolicyAction)).
|
||||
GetPost("/test", new(TestAction)).
|
||||
GetPost("/update", new(UpdateAction)).
|
||||
Post("/delete", new(DeleteAction)).
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
@@ -18,9 +19,10 @@ func (this *AddPortPopupAction) Init() {
|
||||
}
|
||||
|
||||
func (this *AddPortPopupAction) RunGet(params struct {
|
||||
ServerType string
|
||||
Protocol string
|
||||
From string
|
||||
ServerType string
|
||||
Protocol string
|
||||
From string
|
||||
SupportRange bool
|
||||
}) {
|
||||
this.Data["from"] = params.From
|
||||
|
||||
@@ -36,10 +38,14 @@ func (this *AddPortPopupAction) RunGet(params struct {
|
||||
}
|
||||
this.Data["protocols"] = protocols
|
||||
|
||||
this.Data["supportRange"] = params.SupportRange
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *AddPortPopupAction) RunPost(params struct {
|
||||
SupportRange bool
|
||||
|
||||
Protocol string
|
||||
Address string
|
||||
|
||||
@@ -50,26 +56,69 @@ func (this *AddPortPopupAction) RunPost(params struct {
|
||||
"protocol": params.Protocol,
|
||||
"host": "",
|
||||
"portRange": "",
|
||||
"minPort": 0,
|
||||
"maxPort": 0,
|
||||
}
|
||||
|
||||
// TODO 判断端口不能小于1
|
||||
// TODO 判断端口号不能大于65535
|
||||
|
||||
digitRegexp := regexp.MustCompile(`^\d+$`)
|
||||
if digitRegexp.MatchString(params.Address) {
|
||||
addr["portRange"] = params.Address
|
||||
} else if strings.Contains(params.Address, ":") {
|
||||
var portRegexp = regexp.MustCompile(`^\d+$`)
|
||||
if portRegexp.MatchString(params.Address) { // 单个端口
|
||||
addr["portRange"] = this.checkPort(params.Address)
|
||||
} else if params.SupportRange && regexp.MustCompile(`^\d+\s*-\s*\d+$`).MatchString(params.Address) { // Port1-Port2
|
||||
addr["portRange"], addr["minPort"], addr["maxPort"] = this.checkPortRange(params.Address)
|
||||
} else if strings.Contains(params.Address, ":") { // IP:Port
|
||||
index := strings.LastIndex(params.Address, ":")
|
||||
addr["host"] = strings.TrimSpace(params.Address[:index])
|
||||
port := strings.TrimSpace(params.Address[index+1:])
|
||||
if !digitRegexp.MatchString(port) {
|
||||
this.Fail("端口只能是一个数字")
|
||||
if portRegexp.MatchString(port) {
|
||||
addr["portRange"] = this.checkPort(port)
|
||||
} else if params.SupportRange && regexp.MustCompile(`^\d+\s*-\s*\d+$`).MatchString(port) { // Port1-Port2
|
||||
addr["portRange"], addr["minPort"], addr["maxPort"] = this.checkPortRange(port)
|
||||
} else {
|
||||
this.FailField("address", "请输入正确的端口或者网络地址")
|
||||
}
|
||||
addr["portRange"] = port
|
||||
} else {
|
||||
this.Fail("请输入正确的端口或者网络地址")
|
||||
this.FailField("address", "请输入正确的端口或者网络地址")
|
||||
}
|
||||
|
||||
this.Data["address"] = addr
|
||||
this.Success()
|
||||
}
|
||||
|
||||
func (this *AddPortPopupAction) checkPort(port string) (portRange string) {
|
||||
var intPort = types.Int(port)
|
||||
if intPort < 1 {
|
||||
this.FailField("address", "端口号不能小于1")
|
||||
}
|
||||
if intPort > 65535 {
|
||||
this.FailField("address", "端口号不能大于65535")
|
||||
}
|
||||
return port
|
||||
}
|
||||
|
||||
func (this *AddPortPopupAction) checkPortRange(port string) (portRange string, minPort int, maxPort int) {
|
||||
var pieces = strings.Split(port, "-")
|
||||
var piece1 = strings.TrimSpace(pieces[0])
|
||||
var piece2 = strings.TrimSpace(pieces[1])
|
||||
var port1 = types.Int(piece1)
|
||||
var port2 = types.Int(piece2)
|
||||
|
||||
if port1 < 1 {
|
||||
this.FailField("address", "端口号不能小于1")
|
||||
}
|
||||
if port1 > 65535 {
|
||||
this.FailField("address", "端口号不能大于65535")
|
||||
}
|
||||
|
||||
if port2 < 1 {
|
||||
this.FailField("address", "端口号不能小于1")
|
||||
}
|
||||
if port2 > 65535 {
|
||||
this.FailField("address", "端口号不能大于65535")
|
||||
}
|
||||
|
||||
if port1 > port2 {
|
||||
port1, port2 = port2, port1
|
||||
}
|
||||
|
||||
return types.String(port1) + "-" + types.String(port2), port1, port2
|
||||
}
|
||||
|
||||
@@ -0,0 +1,100 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package accounts
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
type CreatePopupAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *CreatePopupAction) Init() {
|
||||
this.Nav("", "", "")
|
||||
}
|
||||
|
||||
func (this *CreatePopupAction) RunGet(params struct {
|
||||
ProviderCode string
|
||||
}) {
|
||||
this.Data["providerCode"] = params.ProviderCode
|
||||
|
||||
// 服务商列表
|
||||
providersResp, err := this.RPC().ACMEProviderRPC().FindAllACMEProviders(this.AdminContext(), &pb.FindAllACMEProvidersRequest{})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
var providerMaps = []maps.Map{}
|
||||
for _, provider := range providersResp.AcmeProviders {
|
||||
providerMaps = append(providerMaps, maps.Map{
|
||||
"name": provider.Name,
|
||||
"code": provider.Code,
|
||||
"description": provider.Description,
|
||||
"requireEAB": provider.RequireEAB,
|
||||
"eabDescription": provider.EabDescription,
|
||||
})
|
||||
}
|
||||
|
||||
this.Data["providers"] = providerMaps
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *CreatePopupAction) RunPost(params struct {
|
||||
Name string
|
||||
ProviderCode string
|
||||
EabKid string
|
||||
EabKey string
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
var accountId int64
|
||||
defer func() {
|
||||
this.CreateLogInfo("创建ACME服务商账号 %d", accountId)
|
||||
}()
|
||||
|
||||
params.Must.
|
||||
Field("name", params.Name).
|
||||
Require("请输入账号名称").
|
||||
Field("providerCode", params.ProviderCode).
|
||||
Require("请选择服务商")
|
||||
|
||||
providerResp, err := this.RPC().ACMEProviderRPC().FindACMEProviderWithCode(this.AdminContext(), &pb.FindACMEProviderWithCodeRequest{AcmeProviderCode: params.ProviderCode})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
var provider = providerResp.AcmeProvider
|
||||
if provider == nil {
|
||||
this.Fail("请选择服务商")
|
||||
}
|
||||
|
||||
if provider.RequireEAB {
|
||||
params.Must.
|
||||
Field("eabKid", params.EabKid).
|
||||
Require("请输入EAB Kid").
|
||||
Field("eabKey", params.EabKey).
|
||||
Require("请输入EAB HMAC Key")
|
||||
}
|
||||
|
||||
createResp, err := this.RPC().ACMEProviderAccountRPC().CreateACMEProviderAccount(this.AdminContext(), &pb.CreateACMEProviderAccountRequest{
|
||||
Name: params.Name,
|
||||
ProviderCode: params.ProviderCode,
|
||||
EabKid: params.EabKid,
|
||||
EabKey: params.EabKey,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
accountId = createResp.AcmeProviderAccountId
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package accounts
|
||||
|
||||
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 {
|
||||
AccountId int64
|
||||
}) {
|
||||
defer this.CreateLogInfo("删除ACME服务商账号 %d", params.AccountId)
|
||||
|
||||
_, err := this.RPC().ACMEProviderAccountRPC().DeleteACMEProviderAccount(this.AdminContext(), &pb.DeleteACMEProviderAccountRequest{AcmeProviderAccountId: params.AccountId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package accounts
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
type IndexAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *IndexAction) Init() {
|
||||
this.Nav("", "", "account")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct{}) {
|
||||
countResp, err := this.RPC().ACMEProviderAccountRPC().CountAllEnabledACMEProviderAccounts(this.AdminContext(), &pb.CountAllEnabledACMEProviderAccountsRequest{})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var count = countResp.Count
|
||||
var page = this.NewPage(count)
|
||||
this.Data["page"] = page.AsHTML()
|
||||
|
||||
accountsResp, err := this.RPC().ACMEProviderAccountRPC().ListEnabledACMEProviderAccounts(this.AdminContext(), &pb.ListEnabledACMEProviderAccountsRequest{
|
||||
Offset: page.Offset,
|
||||
Size: page.Size,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
var accountMaps = []maps.Map{}
|
||||
for _, account := range accountsResp.AcmeProviderAccounts {
|
||||
var providerMap maps.Map
|
||||
if account.AcmeProvider != nil {
|
||||
providerMap = maps.Map{
|
||||
"name": account.AcmeProvider.Name,
|
||||
"code": account.AcmeProvider.Code,
|
||||
"requireEAB": account.AcmeProvider.RequireEAB,
|
||||
}
|
||||
}
|
||||
|
||||
accountMaps = append(accountMaps, maps.Map{
|
||||
"id": account.Id,
|
||||
"isOn": account.IsOn,
|
||||
"name": account.Name,
|
||||
"eabKid": account.EabKid,
|
||||
"eabKey": account.EabKey,
|
||||
"provider": providerMap,
|
||||
})
|
||||
}
|
||||
this.Data["accounts"] = accountMaps
|
||||
|
||||
this.Show()
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package accounts
|
||||
|
||||
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 {
|
||||
AccountId int64
|
||||
}) {
|
||||
// 账号信息
|
||||
accountResp, err := this.RPC().ACMEProviderAccountRPC().FindEnabledACMEProviderAccount(this.AdminContext(), &pb.FindEnabledACMEProviderAccountRequest{AcmeProviderAccountId: params.AccountId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var account = accountResp.AcmeProviderAccount
|
||||
if account == nil {
|
||||
this.NotFound("ACMEProviderAccount", params.AccountId)
|
||||
return
|
||||
}
|
||||
|
||||
var providerMap maps.Map
|
||||
if account.AcmeProvider != nil {
|
||||
providerMap = maps.Map{
|
||||
"name": account.AcmeProvider.Name,
|
||||
"code": account.AcmeProvider.Code,
|
||||
"description": account.AcmeProvider.Description,
|
||||
"eabDescription": account.AcmeProvider.EabDescription,
|
||||
"requireEAB": account.AcmeProvider.RequireEAB,
|
||||
}
|
||||
}
|
||||
|
||||
this.Data["account"] = maps.Map{
|
||||
"id": account.Id,
|
||||
"name": account.Name,
|
||||
"isOn": account.IsOn,
|
||||
"providerCode": account.ProviderCode,
|
||||
"eabKid": account.EabKid,
|
||||
"eabKey": account.EabKey,
|
||||
"provider": providerMap,
|
||||
}
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *UpdatePopupAction) RunPost(params struct {
|
||||
AccountId int64
|
||||
Name string
|
||||
ProviderCode string
|
||||
EabKid string
|
||||
EabKey string
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
defer this.CreateLogInfo("修改ACME服务商账号 %d", params.AccountId)
|
||||
|
||||
params.Must.
|
||||
Field("name", params.Name).
|
||||
Require("请输入账号名称").
|
||||
Field("providerCode", params.ProviderCode).
|
||||
Require("请选择服务商")
|
||||
|
||||
providerResp, err := this.RPC().ACMEProviderRPC().FindACMEProviderWithCode(this.AdminContext(), &pb.FindACMEProviderWithCodeRequest{AcmeProviderCode: params.ProviderCode})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
var provider = providerResp.AcmeProvider
|
||||
if provider == nil {
|
||||
this.Fail("请选择服务商")
|
||||
}
|
||||
|
||||
if provider.RequireEAB {
|
||||
params.Must.
|
||||
Field("eabKid", params.EabKid).
|
||||
Require("请输入EAB Kid").
|
||||
Field("eabKey", params.EabKey).
|
||||
Require("请输入EAB HMAC Key")
|
||||
}
|
||||
|
||||
_, err = this.RPC().ACMEProviderAccountRPC().UpdateACMEProviderAccount(this.AdminContext(), &pb.UpdateACMEProviderAccountRequest{
|
||||
AcmeProviderAccountId: params.AccountId,
|
||||
Name: params.Name,
|
||||
EabKid: params.EabKid,
|
||||
EabKey: params.EabKey,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -35,15 +35,31 @@ func (this *CreateAction) RunGet(params struct{}) {
|
||||
}
|
||||
|
||||
userMaps = append(userMaps, maps.Map{
|
||||
"id": user.Id,
|
||||
"description": description,
|
||||
"email": user.Email,
|
||||
"id": user.Id,
|
||||
"description": description,
|
||||
"email": user.Email,
|
||||
"providerCode": user.AcmeProviderCode,
|
||||
})
|
||||
}
|
||||
this.Data["users"] = userMaps
|
||||
|
||||
// 证书服务商
|
||||
providersResp, err := this.RPC().ACMEProviderRPC().FindAllACMEProviders(this.AdminContext(), &pb.FindAllACMEProvidersRequest{})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var providerMaps = []maps.Map{}
|
||||
for _, provider := range providersResp.AcmeProviders {
|
||||
providerMaps = append(providerMaps, maps.Map{
|
||||
"name": provider.Name,
|
||||
"code": provider.Code,
|
||||
})
|
||||
}
|
||||
this.Data["providers"] = providerMaps
|
||||
|
||||
// 域名解析服务商
|
||||
providersResp, err := this.RPC().DNSProviderRPC().FindAllEnabledDNSProviders(this.AdminContext(), &pb.FindAllEnabledDNSProvidersRequest{
|
||||
dnsProvidersResp, err := this.RPC().DNSProviderRPC().FindAllEnabledDNSProviders(this.AdminContext(), &pb.FindAllEnabledDNSProvidersRequest{
|
||||
AdminId: this.AdminId(),
|
||||
UserId: 0,
|
||||
})
|
||||
@@ -51,15 +67,15 @@ func (this *CreateAction) RunGet(params struct{}) {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
providerMaps := []maps.Map{}
|
||||
for _, provider := range providersResp.DnsProviders {
|
||||
providerMaps = append(providerMaps, maps.Map{
|
||||
dnsProviderMaps := []maps.Map{}
|
||||
for _, provider := range dnsProvidersResp.DnsProviders {
|
||||
dnsProviderMaps = append(dnsProviderMaps, maps.Map{
|
||||
"id": provider.Id,
|
||||
"name": provider.Name,
|
||||
"typeName": provider.TypeName,
|
||||
})
|
||||
}
|
||||
this.Data["providers"] = providerMaps
|
||||
this.Data["dnsProviders"] = dnsProviderMaps
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
@@ -136,6 +136,26 @@ func (this *IndexAction) RunGet(params struct {
|
||||
if task.AcmeUser == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
// 服务商
|
||||
var providerMap maps.Map
|
||||
if task.AcmeUser.AcmeProvider != nil {
|
||||
providerMap = maps.Map{
|
||||
"name": task.AcmeUser.AcmeProvider.Name,
|
||||
"code": task.AcmeUser.AcmeProvider.Code,
|
||||
}
|
||||
}
|
||||
|
||||
// 账号
|
||||
var accountMap maps.Map
|
||||
if task.AcmeUser.AcmeProviderAccount != nil {
|
||||
accountMap = maps.Map{
|
||||
"id": task.AcmeUser.AcmeProviderAccount.Id,
|
||||
"name": task.AcmeUser.AcmeProviderAccount.Name,
|
||||
}
|
||||
}
|
||||
|
||||
// DNS服务商
|
||||
dnsProviderMap := maps.Map{}
|
||||
if task.AuthType == "dns" && task.DnsProvider != nil {
|
||||
dnsProviderMap = maps.Map{
|
||||
@@ -170,8 +190,10 @@ func (this *IndexAction) RunGet(params struct {
|
||||
"id": task.Id,
|
||||
"authType": task.AuthType,
|
||||
"acmeUser": maps.Map{
|
||||
"id": task.AcmeUser.Id,
|
||||
"email": task.AcmeUser.Email,
|
||||
"id": task.AcmeUser.Id,
|
||||
"email": task.AcmeUser.Email,
|
||||
"provider": providerMap,
|
||||
"account": accountMap,
|
||||
},
|
||||
"dnsProvider": dnsProviderMap,
|
||||
"dnsDomain": task.DnsDomain,
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package users
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
type AccountsWithCodeAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *AccountsWithCodeAction) RunPost(params struct {
|
||||
Code string
|
||||
}) {
|
||||
accountsResp, err := this.RPC().ACMEProviderAccountRPC().FindAllACMEProviderAccountsWithProviderCode(this.AdminContext(), &pb.FindAllACMEProviderAccountsWithProviderCodeRequest{AcmeProviderCode: params.Code})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var accountMaps = []maps.Map{}
|
||||
for _, account := range accountsResp.AcmeProviderAccounts {
|
||||
accountMaps = append(accountMaps, maps.Map{
|
||||
"id": account.Id,
|
||||
"name": account.Name,
|
||||
})
|
||||
}
|
||||
this.Data["accounts"] = accountMaps
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -16,12 +16,30 @@ func (this *CreatePopupAction) Init() {
|
||||
}
|
||||
|
||||
func (this *CreatePopupAction) RunGet(params struct{}) {
|
||||
// 服务商
|
||||
providersResp, err := this.RPC().ACMEProviderRPC().FindAllACMEProviders(this.AdminContext(), &pb.FindAllACMEProvidersRequest{})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var providerMaps = []maps.Map{}
|
||||
for _, provider := range providersResp.AcmeProviders {
|
||||
providerMaps = append(providerMaps, maps.Map{
|
||||
"code": provider.Code,
|
||||
"name": provider.Name,
|
||||
"requireEAB": provider.RequireEAB,
|
||||
})
|
||||
}
|
||||
this.Data["providers"] = providerMaps
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *CreatePopupAction) RunPost(params struct {
|
||||
Email string
|
||||
Description string
|
||||
Email string
|
||||
ProviderCode string
|
||||
AccountId int64
|
||||
Description string
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
@@ -29,11 +47,44 @@ func (this *CreatePopupAction) RunPost(params struct {
|
||||
params.Must.
|
||||
Field("email", params.Email).
|
||||
Require("请输入邮箱").
|
||||
Email("请输入正确的邮箱格式")
|
||||
Email("请输入正确的邮箱格式").
|
||||
Field("providerCode", params.ProviderCode).
|
||||
Require("请选择所属服务商")
|
||||
|
||||
providerResp, err := this.RPC().ACMEProviderRPC().FindACMEProviderWithCode(this.AdminContext(), &pb.FindACMEProviderWithCodeRequest{
|
||||
AcmeProviderCode: params.ProviderCode,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if providerResp.AcmeProvider == nil {
|
||||
this.Fail("找不到要选择的证书")
|
||||
}
|
||||
if providerResp.AcmeProvider.RequireEAB {
|
||||
if params.AccountId <= 0 {
|
||||
this.Fail("此服务商要求必须选择或创建服务商账号")
|
||||
}
|
||||
|
||||
// 同一个账号只能有一个用户
|
||||
countResp, err := this.RPC().ACMEUserRPC().
|
||||
CountACMEUsers(this.AdminContext(), &pb.CountAcmeUsersRequest{
|
||||
AcmeProviderAccountId: params.AccountId,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if countResp.Count > 0 {
|
||||
this.Fail("此服务商账号已被别的用户使用,请换成别的账号")
|
||||
}
|
||||
}
|
||||
|
||||
createResp, err := this.RPC().ACMEUserRPC().CreateACMEUser(this.AdminContext(), &pb.CreateACMEUserRequest{
|
||||
Email: params.Email,
|
||||
Description: params.Description,
|
||||
Email: params.Email,
|
||||
Description: params.Description,
|
||||
AcmeProviderCode: params.ProviderCode,
|
||||
AcmeProviderAccountId: params.AccountId,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
@@ -42,9 +93,10 @@ func (this *CreatePopupAction) RunPost(params struct {
|
||||
|
||||
// 返回数据
|
||||
this.Data["acmeUser"] = maps.Map{
|
||||
"id": createResp.AcmeUserId,
|
||||
"description": params.Description,
|
||||
"email": params.Email,
|
||||
"id": createResp.AcmeUserId,
|
||||
"description": params.Description,
|
||||
"email": params.Email,
|
||||
"providerCode": params.ProviderCode,
|
||||
}
|
||||
|
||||
// 日志
|
||||
|
||||
@@ -40,11 +40,31 @@ func (this *IndexAction) RunGet(params struct{}) {
|
||||
}
|
||||
userMaps := []maps.Map{}
|
||||
for _, user := range usersResp.AcmeUsers {
|
||||
// 服务商
|
||||
var providerMap maps.Map
|
||||
if user.AcmeProvider != nil {
|
||||
providerMap = maps.Map{
|
||||
"name": user.AcmeProvider.Name,
|
||||
"code": user.AcmeProvider.Code,
|
||||
}
|
||||
}
|
||||
|
||||
// 账号
|
||||
var accountMap maps.Map
|
||||
if user.AcmeProviderAccount != nil {
|
||||
accountMap = maps.Map{
|
||||
"id": user.AcmeProviderAccount.Id,
|
||||
"name": user.AcmeProviderAccount.Name,
|
||||
}
|
||||
}
|
||||
|
||||
userMaps = append(userMaps, maps.Map{
|
||||
"id": user.Id,
|
||||
"email": user.Email,
|
||||
"description": user.Description,
|
||||
"createdTime": timeutil.FormatTime("Y-m-d H:i:s", user.CreatedAt),
|
||||
"provider": providerMap,
|
||||
"account": accountMap,
|
||||
})
|
||||
}
|
||||
this.Data["users"] = userMaps
|
||||
|
||||
@@ -29,10 +29,30 @@ func (this *UpdatePopupAction) RunGet(params struct {
|
||||
return
|
||||
}
|
||||
|
||||
// 服务商
|
||||
var providerMap maps.Map
|
||||
if user.AcmeProvider != nil {
|
||||
providerMap = maps.Map{
|
||||
"name": user.AcmeProvider.Name,
|
||||
"code": user.AcmeProvider.Code,
|
||||
}
|
||||
}
|
||||
|
||||
// 账号
|
||||
var accountMap maps.Map
|
||||
if user.AcmeProviderAccount != nil {
|
||||
accountMap = maps.Map{
|
||||
"id": user.AcmeProviderAccount.Id,
|
||||
"name": user.AcmeProviderAccount.Name,
|
||||
}
|
||||
}
|
||||
|
||||
this.Data["user"] = maps.Map{
|
||||
"id": user.Id,
|
||||
"email": user.Email,
|
||||
"description": user.Description,
|
||||
"provider": providerMap,
|
||||
"account": accountMap,
|
||||
}
|
||||
|
||||
this.Show()
|
||||
|
||||
@@ -16,7 +16,7 @@ func (this *DeleteAction) RunPost(params struct {
|
||||
// 创建日志
|
||||
defer this.CreateLog(oplogs.LevelInfo, "删除SSL证书 %d", params.CertId)
|
||||
|
||||
// 是否正在被使用
|
||||
// 是否正在被服务使用
|
||||
countResp, err := this.RPC().ServerRPC().CountAllEnabledServersWithSSLCertId(this.AdminContext(), &pb.CountAllEnabledServersWithSSLCertIdRequest{SslCertId: params.CertId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
@@ -26,6 +26,26 @@ func (this *DeleteAction) RunPost(params struct {
|
||||
this.Fail("此证书正在被某些服务引用,请先修改服务后再删除。")
|
||||
}
|
||||
|
||||
// 是否正在被API节点使用
|
||||
countResp, err = this.RPC().APINodeRPC().CountAllEnabledAPINodesWithSSLCertId(this.AdminContext(), &pb.CountAllEnabledAPINodesWithSSLCertIdRequest{SslCertId: params.CertId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if countResp.Count > 0 {
|
||||
this.Fail("此证书正在被某些API节点引用,请先修改API节点后再删除")
|
||||
}
|
||||
|
||||
// 是否正在被用户节点使用
|
||||
countResp, err = this.RPC().UserNodeRPC().CountAllEnabledUserNodesWithSSLCertId(this.AdminContext(), &pb.CountAllEnabledUserNodesWithSSLCertIdRequest{SslCertId: params.CertId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if countResp.Count > 0 {
|
||||
this.Fail("此证书正在被某些用户节点引用,请先修改用户节点后再删除")
|
||||
}
|
||||
|
||||
_, err = this.RPC().SSLCertRPC().DeleteSSLCert(this.AdminContext(), &pb.DeleteSSLCertRequest{SslCertId: params.CertId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
|
||||
@@ -3,6 +3,7 @@ package certs
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/certs/acme"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/certs/acme/accounts"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/certs/acme/users"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
|
||||
"github.com/iwind/TeaGo"
|
||||
@@ -13,9 +14,7 @@ func init() {
|
||||
server.
|
||||
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeServer)).
|
||||
Helper(NewHelper()).
|
||||
|
||||
Data("teaSubMenu", "cert").
|
||||
|
||||
Prefix("/servers/certs").
|
||||
Data("leftMenuItem", "cert").
|
||||
Get("", new(IndexAction)).
|
||||
@@ -31,7 +30,7 @@ func init() {
|
||||
Get("/selectPopup", new(SelectPopupAction)).
|
||||
Get("/datajs", new(DatajsAction)).
|
||||
|
||||
// ACME
|
||||
// ACME任务
|
||||
Prefix("/servers/certs/acme").
|
||||
Data("leftMenuItem", "acme").
|
||||
Get("", new(acme.IndexAction)).
|
||||
@@ -40,13 +39,23 @@ func init() {
|
||||
GetPost("/updateTaskPopup", new(acme.UpdateTaskPopupAction)).
|
||||
Post("/deleteTask", new(acme.DeleteTaskAction)).
|
||||
|
||||
// ACME用户
|
||||
Prefix("/servers/certs/acme/users").
|
||||
Get("", new(users.IndexAction)).
|
||||
GetPost("/createPopup", new(users.CreatePopupAction)).
|
||||
GetPost("/updatePopup", new(users.UpdatePopupAction)).
|
||||
Post("/delete", new(users.DeleteAction)).
|
||||
GetPost("/selectPopup", new(users.SelectPopupAction)).
|
||||
Post("/accountsWithCode", new(users.AccountsWithCodeAction)).
|
||||
|
||||
// ACME账号
|
||||
Prefix("/servers/certs/acme/accounts").
|
||||
Get("", new(accounts.IndexAction)).
|
||||
GetPost("/createPopup", new(accounts.CreatePopupAction)).
|
||||
GetPost("/updatePopup", new(accounts.UpdatePopupAction)).
|
||||
Post("/delete", new(accounts.DeleteAction)).
|
||||
|
||||
//
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/sslconfigs"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
)
|
||||
|
||||
type UpdatePopupAction struct {
|
||||
@@ -45,6 +46,8 @@ func (this *UpdatePopupAction) RunGet(params struct {
|
||||
func (this *UpdatePopupAction) RunPost(params struct {
|
||||
CertId int64
|
||||
|
||||
TextMode bool
|
||||
|
||||
Name string
|
||||
IsCA bool
|
||||
Description string
|
||||
@@ -53,6 +56,9 @@ func (this *UpdatePopupAction) RunPost(params struct {
|
||||
CertFile *actions.File
|
||||
KeyFile *actions.File
|
||||
|
||||
CertText string
|
||||
KeyText string
|
||||
|
||||
Must *actions.Must
|
||||
}) {
|
||||
// 创建日志
|
||||
@@ -82,18 +88,31 @@ func (this *UpdatePopupAction) RunPost(params struct {
|
||||
Field("name", params.Name).
|
||||
Require("请输入证书说明")
|
||||
|
||||
if params.CertFile != nil {
|
||||
certConfig.CertData, err = params.CertFile.Read()
|
||||
if err != nil {
|
||||
this.Fail("读取证书文件内容错误,请重新上传")
|
||||
if params.TextMode {
|
||||
if len(params.CertText) > 0 {
|
||||
certConfig.CertData = []byte(params.CertText)
|
||||
}
|
||||
}
|
||||
|
||||
if !params.IsCA {
|
||||
if params.KeyFile != nil {
|
||||
certConfig.KeyData, err = params.KeyFile.Read()
|
||||
if !params.IsCA {
|
||||
if len(params.KeyText) > 0 {
|
||||
certConfig.KeyData = []byte(params.KeyText)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
if params.CertFile != nil {
|
||||
certConfig.CertData, err = params.CertFile.Read()
|
||||
if err != nil {
|
||||
this.Fail("读取密钥文件内容错误,请重新上传")
|
||||
this.FailField("certFile", "读取证书文件内容错误,请重新上传")
|
||||
}
|
||||
}
|
||||
|
||||
if !params.IsCA {
|
||||
if params.KeyFile != nil {
|
||||
certConfig.KeyData, err = params.KeyFile.Read()
|
||||
if err != nil {
|
||||
this.FailField("keyFile", "读取私钥文件内容错误,请重新上传")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -109,6 +128,10 @@ func (this *UpdatePopupAction) RunPost(params struct {
|
||||
}
|
||||
}
|
||||
|
||||
if len(timeutil.Format("Y", certConfig.TimeEnd())) != 4 {
|
||||
this.Fail("证书格式错误:无法读取到证书有效期")
|
||||
}
|
||||
|
||||
// 保存
|
||||
_, err = this.RPC().SSLCertRPC().UpdateSSLCert(this.AdminContext(), &pb.UpdateSSLCertRequest{
|
||||
SslCertId: params.CertId,
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/sslconfigs"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
)
|
||||
|
||||
type UploadPopupAction struct {
|
||||
@@ -22,6 +23,7 @@ func (this *UploadPopupAction) RunGet(params struct{}) {
|
||||
}
|
||||
|
||||
func (this *UploadPopupAction) RunPost(params struct {
|
||||
TextMode bool
|
||||
Name string
|
||||
IsCA bool
|
||||
Description string
|
||||
@@ -30,6 +32,9 @@ func (this *UploadPopupAction) RunPost(params struct {
|
||||
CertFile *actions.File
|
||||
KeyFile *actions.File
|
||||
|
||||
CertText string
|
||||
KeyText string
|
||||
|
||||
Must *actions.Must
|
||||
}) {
|
||||
params.Must.
|
||||
@@ -39,22 +44,37 @@ func (this *UploadPopupAction) RunPost(params struct {
|
||||
certData := []byte{}
|
||||
keyData := []byte{}
|
||||
|
||||
if params.CertFile == nil {
|
||||
this.Fail("请选择要上传的证书文件")
|
||||
}
|
||||
var err error
|
||||
certData, err = params.CertFile.Read()
|
||||
if err != nil {
|
||||
this.Fail("读取证书文件内容错误,请重新上传")
|
||||
}
|
||||
if params.TextMode {
|
||||
if len(params.CertText) == 0 {
|
||||
this.FailField("certText", "请输入证书内容")
|
||||
}
|
||||
|
||||
if !params.IsCA {
|
||||
if params.KeyFile == nil {
|
||||
this.Fail("请选择要上传的私钥文件")
|
||||
} else {
|
||||
keyData, err = params.KeyFile.Read()
|
||||
if err != nil {
|
||||
this.Fail("读取密钥文件内容错误,请重新上传")
|
||||
if !params.IsCA {
|
||||
if len(params.KeyText) == 0 {
|
||||
this.FailField("keyText", "请输入私钥内容")
|
||||
}
|
||||
}
|
||||
|
||||
certData = []byte(params.CertText)
|
||||
keyData = []byte(params.KeyText)
|
||||
} else {
|
||||
if params.CertFile == nil {
|
||||
this.FailField("certFile", "请选择要上传的证书文件")
|
||||
}
|
||||
var err error
|
||||
certData, err = params.CertFile.Read()
|
||||
if err != nil {
|
||||
this.FailField("certFile", "读取证书文件内容错误,请重新上传")
|
||||
}
|
||||
|
||||
if !params.IsCA {
|
||||
if params.KeyFile == nil {
|
||||
this.FailField("keyFile", "请选择要上传的私钥文件")
|
||||
} else {
|
||||
keyData, err = params.KeyFile.Read()
|
||||
if err != nil {
|
||||
this.FailField("keyFile", "读取密钥文件内容错误,请重新上传")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -65,7 +85,7 @@ func (this *UploadPopupAction) RunPost(params struct {
|
||||
CertData: certData,
|
||||
KeyData: keyData,
|
||||
}
|
||||
err = sslConfig.Init()
|
||||
err := sslConfig.Init()
|
||||
if err != nil {
|
||||
if params.IsCA {
|
||||
this.Fail("证书校验错误:" + err.Error())
|
||||
@@ -73,6 +93,9 @@ func (this *UploadPopupAction) RunPost(params struct {
|
||||
this.Fail("证书或密钥校验错误:" + err.Error())
|
||||
}
|
||||
}
|
||||
if len(timeutil.Format("Y", sslConfig.TimeEnd())) != 4 {
|
||||
this.Fail("证书格式错误:无法读取到证书有效期")
|
||||
}
|
||||
|
||||
// 保存
|
||||
createResp, err := this.RPC().SSLCertRPC().CreateSSLCert(this.AdminContext(), &pb.CreateSSLCertRequest{
|
||||
|
||||
@@ -73,6 +73,14 @@ func (this *GroupAction) RunGet(params struct {
|
||||
"name": set.Name,
|
||||
"rules": lists.Map(set.Rules, func(k int, v interface{}) interface{} {
|
||||
rule := v.(*firewallconfigs.HTTPFirewallRule)
|
||||
|
||||
// 校验
|
||||
var errString = ""
|
||||
var err = rule.Init()
|
||||
if err != nil {
|
||||
errString = err.Error()
|
||||
}
|
||||
|
||||
return maps.Map{
|
||||
"param": rule.Param,
|
||||
"paramFilters": rule.ParamFilters,
|
||||
@@ -81,6 +89,7 @@ func (this *GroupAction) RunGet(params struct {
|
||||
"isCaseInsensitive": rule.IsCaseInsensitive,
|
||||
"isComposed": firewallconfigs.CheckCheckpointIsComposed(rule.Prefix()),
|
||||
"checkpointOptions": rule.CheckpointOptions,
|
||||
"err": errString,
|
||||
}
|
||||
}),
|
||||
"isOn": set.IsOn,
|
||||
|
||||
@@ -70,10 +70,17 @@ func (this *IndexAction) RunGet(params struct {
|
||||
}
|
||||
countClusters := countClustersResp.Count
|
||||
|
||||
// mode
|
||||
if len(policy.Mode) == 0 {
|
||||
policy.Mode = firewallconfigs.FirewallModeDefend
|
||||
}
|
||||
|
||||
policyMaps = append(policyMaps, maps.Map{
|
||||
"id": policy.Id,
|
||||
"isOn": policy.IsOn,
|
||||
"name": policy.Name,
|
||||
"mode": policy.Mode,
|
||||
"modeInfo": firewallconfigs.FindFirewallMode(policy.Mode),
|
||||
"countInbound": countInbound,
|
||||
"countOutbound": countOutbound,
|
||||
"countClusters": countClusters,
|
||||
|
||||
@@ -19,6 +19,7 @@ func init() {
|
||||
GetPost("/createPopup", new(CreatePopupAction)).
|
||||
Post("/delete", new(DeleteAction)).
|
||||
Get("/policy", new(PolicyAction)).
|
||||
Post("/upgradeTemplate", new(UpgradeTemplateAction)).
|
||||
Get("/groups", new(GroupsAction)).
|
||||
Get("/group", new(GroupAction)).
|
||||
Get("/log", new(LogAction)).
|
||||
|
||||
@@ -59,14 +59,56 @@ func (this *ListsAction) RunGet(params struct {
|
||||
expiredTime = timeutil.FormatTime("Y-m-d H:i:s", item.ExpiredAt)
|
||||
}
|
||||
|
||||
// policy
|
||||
var sourcePolicyMap = maps.Map{"id": 0}
|
||||
if item.SourceHTTPFirewallPolicy != nil {
|
||||
sourcePolicyMap = maps.Map{
|
||||
"id": item.SourceHTTPFirewallPolicy.Id,
|
||||
"name": item.SourceHTTPFirewallPolicy.Name,
|
||||
"serverId": item.SourceHTTPFirewallPolicy.ServerId,
|
||||
}
|
||||
}
|
||||
|
||||
// group
|
||||
var sourceGroupMap = maps.Map{"id": 0}
|
||||
if item.SourceHTTPFirewallRuleGroup != nil {
|
||||
sourceGroupMap = maps.Map{
|
||||
"id": item.SourceHTTPFirewallRuleGroup.Id,
|
||||
"name": item.SourceHTTPFirewallRuleGroup.Name,
|
||||
}
|
||||
}
|
||||
|
||||
// set
|
||||
var sourceSetMap = maps.Map{"id": 0}
|
||||
if item.SourceHTTPFirewallRuleSet != nil {
|
||||
sourceSetMap = maps.Map{
|
||||
"id": item.SourceHTTPFirewallRuleSet.Id,
|
||||
"name": item.SourceHTTPFirewallRuleSet.Name,
|
||||
}
|
||||
}
|
||||
|
||||
// server
|
||||
var sourceServerMap = maps.Map{"id": 0}
|
||||
if item.SourceServer != nil {
|
||||
sourceServerMap = maps.Map{
|
||||
"id": item.SourceServer.Id,
|
||||
"name": item.SourceServer.Name,
|
||||
}
|
||||
}
|
||||
|
||||
itemMaps = append(itemMaps, maps.Map{
|
||||
"id": item.Id,
|
||||
"ipFrom": item.IpFrom,
|
||||
"ipTo": item.IpTo,
|
||||
"createdTime": timeutil.FormatTime("Y-m-d", item.CreatedAt),
|
||||
"expiredTime": expiredTime,
|
||||
"reason": item.Reason,
|
||||
"type": item.Type,
|
||||
"eventLevelName": firewallconfigs.FindFirewallEventLevelName(item.EventLevel),
|
||||
"sourcePolicy": sourcePolicyMap,
|
||||
"sourceGroup": sourceGroupMap,
|
||||
"sourceSet": sourceSetMap,
|
||||
"sourceServer": sourceServerMap,
|
||||
})
|
||||
}
|
||||
this.Data["items"] = itemMaps
|
||||
|
||||
@@ -60,6 +60,7 @@ func (this *TestAction) RunPost(params struct {
|
||||
"ipFrom": resp.IpItem.IpFrom,
|
||||
"ipTo": resp.IpItem.IpTo,
|
||||
"reason": resp.IpItem.Reason,
|
||||
"createdTime": timeutil.FormatTime("Y-m-d", resp.IpItem.CreatedAt),
|
||||
"expiredAt": resp.IpItem.ExpiredAt,
|
||||
"expiredTime": timeutil.FormatTime("Y-m-d H:i:s", resp.IpItem.ExpiredAt),
|
||||
"type": resp.IpItem.Type,
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
@@ -46,11 +47,44 @@ func (this *PolicyAction) RunGet(params struct {
|
||||
}
|
||||
}
|
||||
|
||||
// 检查是否有升级
|
||||
var templatePolicy = firewallconfigs.HTTPFirewallTemplate()
|
||||
var upgradeItems = []string{}
|
||||
if templatePolicy.Inbound != nil {
|
||||
for _, group := range templatePolicy.Inbound.Groups {
|
||||
if len(group.Code) == 0 {
|
||||
continue
|
||||
}
|
||||
var oldGroup = firewallPolicy.FindRuleGroupWithCode(group.Code)
|
||||
if oldGroup == nil {
|
||||
upgradeItems = append(upgradeItems, group.Name)
|
||||
continue
|
||||
}
|
||||
for _, set := range group.Sets {
|
||||
if len(set.Code) == 0 {
|
||||
continue
|
||||
}
|
||||
var oldSet = oldGroup.FindRuleSetWithCode(set.Code)
|
||||
if oldSet == nil {
|
||||
upgradeItems = append(upgradeItems, group.Name+" -- "+set.Name)
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
this.Data["upgradeItems"] = upgradeItems
|
||||
|
||||
// 模式
|
||||
if len(firewallPolicy.Mode) == 0 {
|
||||
firewallPolicy.Mode = firewallconfigs.FirewallModeDefend
|
||||
}
|
||||
this.Data["firewallPolicy"] = maps.Map{
|
||||
"id": firewallPolicy.Id,
|
||||
"name": firewallPolicy.Name,
|
||||
"isOn": firewallPolicy.IsOn,
|
||||
"description": firewallPolicy.Description,
|
||||
"mode": firewallPolicy.Mode,
|
||||
"modeInfo": firewallconfigs.FindFirewallMode(firewallPolicy.Mode),
|
||||
"groups": internalGroups,
|
||||
"blockOptions": firewallPolicy.BlockOptions,
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package waf
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/oplogs"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
|
||||
@@ -37,14 +38,22 @@ func (this *UpdateAction) RunGet(params struct {
|
||||
StatusCode: http.StatusForbidden,
|
||||
Body: "Blocked By WAF",
|
||||
URL: "",
|
||||
Timeout: 60,
|
||||
}
|
||||
}
|
||||
|
||||
// mode
|
||||
if len(firewallPolicy.Mode) == 0 {
|
||||
firewallPolicy.Mode = firewallconfigs.FirewallModeDefend
|
||||
}
|
||||
this.Data["modes"] = firewallconfigs.FindAllFirewallModes()
|
||||
|
||||
this.Data["firewallPolicy"] = maps.Map{
|
||||
"id": firewallPolicy.Id,
|
||||
"name": firewallPolicy.Name,
|
||||
"description": firewallPolicy.Description,
|
||||
"isOn": firewallPolicy.IsOn,
|
||||
"mode": firewallPolicy.Mode,
|
||||
"blockOptions": firewallPolicy.BlockOptions,
|
||||
}
|
||||
|
||||
@@ -77,6 +86,7 @@ func (this *UpdateAction) RunPost(params struct {
|
||||
BlockOptionsJSON []byte
|
||||
Description string
|
||||
IsOn bool
|
||||
Mode string
|
||||
|
||||
Must *actions.Must
|
||||
}) {
|
||||
@@ -87,13 +97,21 @@ func (this *UpdateAction) RunPost(params struct {
|
||||
Field("name", params.Name).
|
||||
Require("请输入策略名称")
|
||||
|
||||
_, err := this.RPC().HTTPFirewallPolicyRPC().UpdateHTTPFirewallPolicy(this.AdminContext(), &pb.UpdateHTTPFirewallPolicyRequest{
|
||||
// 校验JSON
|
||||
var blockOptions = &firewallconfigs.HTTPFirewallBlockAction{}
|
||||
err := json.Unmarshal(params.BlockOptionsJSON, blockOptions)
|
||||
if err != nil {
|
||||
this.Fail("拦截动作参数校验失败:" + err.Error())
|
||||
}
|
||||
|
||||
_, err = this.RPC().HTTPFirewallPolicyRPC().UpdateHTTPFirewallPolicy(this.AdminContext(), &pb.UpdateHTTPFirewallPolicyRequest{
|
||||
HttpFirewallPolicyId: params.FirewallPolicyId,
|
||||
IsOn: params.IsOn,
|
||||
Name: params.Name,
|
||||
Description: params.Description,
|
||||
FirewallGroupCodes: params.GroupCodes,
|
||||
BlockOptionsJSON: params.BlockOptionsJSON,
|
||||
Mode: params.Mode,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
|
||||
@@ -0,0 +1,124 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package waf
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
|
||||
)
|
||||
|
||||
type UpgradeTemplateAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *UpgradeTemplateAction) RunPost(params struct {
|
||||
PolicyId int64
|
||||
}) {
|
||||
defer this.CreateLogInfo("升级WAF %d 内置规则", params.PolicyId)
|
||||
|
||||
policy, err := dao.SharedHTTPFirewallPolicyDAO.FindEnabledHTTPFirewallPolicyConfig(this.AdminContext(), params.PolicyId)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if policy == nil {
|
||||
this.NotFound("firewallPolicy", params.PolicyId)
|
||||
return
|
||||
}
|
||||
|
||||
// 检查是否有升级
|
||||
var templatePolicy = firewallconfigs.HTTPFirewallTemplate()
|
||||
if templatePolicy.Inbound != nil {
|
||||
for _, group := range templatePolicy.Inbound.Groups {
|
||||
if len(group.Code) == 0 {
|
||||
continue
|
||||
}
|
||||
var oldGroup = policy.FindRuleGroupWithCode(group.Code)
|
||||
if oldGroup == nil {
|
||||
createGroupResp, err := this.RPC().HTTPFirewallRuleGroupRPC().CreateHTTPFirewallRuleGroup(this.AdminContext(), &pb.CreateHTTPFirewallRuleGroupRequest{
|
||||
IsOn: true,
|
||||
Name: group.Name,
|
||||
Code: group.Code,
|
||||
Description: group.Description,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var groupId = createGroupResp.FirewallRuleGroupId
|
||||
policy.Inbound.GroupRefs = append(policy.Inbound.GroupRefs, &firewallconfigs.HTTPFirewallRuleGroupRef{
|
||||
IsOn: true,
|
||||
GroupId: groupId,
|
||||
})
|
||||
|
||||
for _, set := range group.Sets {
|
||||
setJSON, err := json.Marshal(set)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
_, err = this.RPC().HTTPFirewallRuleGroupRPC().AddHTTPFirewallRuleGroupSet(this.AdminContext(), &pb.AddHTTPFirewallRuleGroupSetRequest{
|
||||
FirewallRuleGroupId: groupId,
|
||||
FirewallRuleSetConfigJSON: setJSON,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
for _, set := range group.Sets {
|
||||
if len(set.Code) == 0 {
|
||||
continue
|
||||
}
|
||||
var oldSet = oldGroup.FindRuleSetWithCode(set.Code)
|
||||
if oldSet == nil {
|
||||
setJSON, err := json.Marshal(set)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
_, err = this.RPC().HTTPFirewallRuleGroupRPC().AddHTTPFirewallRuleGroupSet(this.AdminContext(), &pb.AddHTTPFirewallRuleGroupSetRequest{
|
||||
FirewallRuleGroupId: oldGroup.Id,
|
||||
FirewallRuleSetConfigJSON: setJSON,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 保存inbound
|
||||
inboundJSON, err := policy.InboundJSON()
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
outboundJSON, err := policy.OutboundJSON()
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
_, err = this.RPC().HTTPFirewallPolicyRPC().UpdateHTTPFirewallPolicyGroups(this.AdminContext(), &pb.UpdateHTTPFirewallPolicyGroupsRequest{
|
||||
HttpFirewallPolicyId: params.PolicyId,
|
||||
InboundJSON: inboundJSON,
|
||||
OutboundJSON: outboundJSON,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/sslconfigs"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/logs"
|
||||
@@ -56,14 +57,26 @@ func (this *CreateAction) RunGet(params struct{}) {
|
||||
// 服务类型
|
||||
this.Data["serverTypes"] = serverconfigs.AllServerTypes()
|
||||
|
||||
// 检查是否有用户
|
||||
countUsersResp, err := this.RPC().UserRPC().CountAllEnabledUsers(this.AdminContext(), &pb.CountAllEnabledUsersRequest{})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
this.Data["hasUsers"] = countUsersResp.Count > 0
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *CreateAction) RunPost(params struct {
|
||||
Name string
|
||||
Description string
|
||||
ClusterId int64
|
||||
GroupIds []int64
|
||||
|
||||
UserId int64
|
||||
UserPlanId int64
|
||||
ClusterId int64
|
||||
|
||||
GroupIds []int64
|
||||
|
||||
ServerType string
|
||||
Addresses string
|
||||
@@ -71,8 +84,11 @@ func (this *CreateAction) RunPost(params struct {
|
||||
CertIdsJSON []byte
|
||||
Origins string
|
||||
|
||||
AccessLogIsOn bool
|
||||
WebsocketIsOn bool
|
||||
AccessLogIsOn bool
|
||||
WebsocketIsOn bool
|
||||
CacheIsOn bool
|
||||
WafIsOn bool
|
||||
RemoteAddrIsOn bool
|
||||
|
||||
WebRoot string
|
||||
|
||||
@@ -82,11 +98,24 @@ func (this *CreateAction) RunPost(params struct {
|
||||
Field("name", params.Name).
|
||||
Require("请输入服务名称")
|
||||
|
||||
if params.ClusterId <= 0 {
|
||||
this.Fail("请选择部署的集群")
|
||||
var clusterId = params.ClusterId
|
||||
|
||||
// 用户
|
||||
var userId = params.UserId
|
||||
if userId > 0 {
|
||||
clusterIdResp, err := this.RPC().UserRPC().FindUserNodeClusterId(this.AdminContext(), &pb.FindUserNodeClusterIdRequest{UserId: userId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
clusterId = clusterIdResp.NodeClusterId
|
||||
if clusterId <= 0 {
|
||||
this.Fail("请选择部署的集群")
|
||||
}
|
||||
}
|
||||
|
||||
// TODO 验证集群ID
|
||||
// 套餐
|
||||
var userPlanId = params.UserPlanId
|
||||
|
||||
// 端口地址
|
||||
var httpConfig *serverconfigs.HTTPProtocolConfig = nil
|
||||
@@ -256,7 +285,7 @@ func (this *CreateAction) RunPost(params struct {
|
||||
if len(allServerNames) > 0 {
|
||||
dupResp, err := this.RPC().ServerRPC().CheckServerNameDuplicationInNodeCluster(this.AdminContext(), &pb.CheckServerNameDuplicationInNodeClusterRequest{
|
||||
ServerNames: allServerNames,
|
||||
NodeClusterId: params.ClusterId,
|
||||
NodeClusterId: clusterId,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
@@ -355,13 +384,14 @@ func (this *CreateAction) RunPost(params struct {
|
||||
}
|
||||
|
||||
req := &pb.CreateServerRequest{
|
||||
UserId: 0,
|
||||
UserId: userId,
|
||||
UserPlanId: userPlanId,
|
||||
AdminId: this.AdminId(),
|
||||
Type: params.ServerType,
|
||||
Name: params.Name,
|
||||
ServerNamesJON: []byte(params.ServerNames),
|
||||
Description: params.Description,
|
||||
NodeClusterId: params.ClusterId,
|
||||
NodeClusterId: clusterId,
|
||||
IncludeNodesJSON: includeNodesJSON,
|
||||
ExcludeNodesJSON: excludeNodesJSON,
|
||||
WebId: webId,
|
||||
@@ -483,6 +513,75 @@ func (this *CreateAction) RunPost(params struct {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// cache
|
||||
if params.CacheIsOn {
|
||||
var cacheConfig = &serverconfigs.HTTPCacheConfig{
|
||||
IsPrior: false,
|
||||
IsOn: true,
|
||||
AddStatusHeader: true,
|
||||
PurgeIsOn: false,
|
||||
PurgeKey: "",
|
||||
CacheRefs: []*serverconfigs.HTTPCacheRef{},
|
||||
}
|
||||
cacheConfigJSON, err := json.Marshal(cacheConfig)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
_, err = this.RPC().HTTPWebRPC().UpdateHTTPWebCache(this.AdminContext(), &pb.UpdateHTTPWebCacheRequest{
|
||||
WebId: webConfig.Id,
|
||||
CacheJSON: cacheConfigJSON,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// waf
|
||||
if params.WafIsOn {
|
||||
var firewallRef = &firewallconfigs.HTTPFirewallRef{
|
||||
IsPrior: false,
|
||||
IsOn: true,
|
||||
FirewallPolicyId: 0,
|
||||
}
|
||||
firewallRefJSON, err := json.Marshal(firewallRef)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
_, err = this.RPC().HTTPWebRPC().UpdateHTTPWebFirewall(this.AdminContext(), &pb.UpdateHTTPWebFirewallRequest{
|
||||
WebId: webConfig.Id,
|
||||
FirewallJSON: firewallRefJSON,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// remoteAddr
|
||||
var remoteAddrConfig = &serverconfigs.HTTPRemoteAddrConfig{
|
||||
IsOn: true,
|
||||
Value: "${rawRemoteAddr}",
|
||||
}
|
||||
if params.RemoteAddrIsOn {
|
||||
remoteAddrConfig.Value = "${remoteAddr}"
|
||||
}
|
||||
remoteAddrConfigJSON, err := json.Marshal(remoteAddrConfig)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
_, err = this.RPC().HTTPWebRPC().UpdateHTTPWebRemoteAddr(this.AdminContext(), &pb.UpdateHTTPWebRemoteAddrRequest{
|
||||
WebId: webConfig.Id,
|
||||
RemoteAddrJSON: remoteAddrConfigJSON,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ package servergrouputils
|
||||
|
||||
import (
|
||||
"errors"
|
||||
teaconst "github.com/TeaOSLab/EdgeAdmin/internal/const"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
@@ -35,75 +36,115 @@ func InitGroup(parent *actionutils.ParentAction, groupId int64, menuItem string)
|
||||
}
|
||||
|
||||
var urlPrefix = "/servers/groups/group/settings"
|
||||
parent.Data["leftMenuItems"] = []maps.Map{
|
||||
/**{
|
||||
"name": "Web设置",
|
||||
"url": urlPrefix + "/web?groupId=" + types.String(groupId),
|
||||
"isActive": menuItem == "web",
|
||||
},**/
|
||||
var leftMenuItems = []maps.Map{
|
||||
{
|
||||
"name": "HTTP反向代理",
|
||||
"name": "HTTP代理",
|
||||
"url": urlPrefix + "/httpReverseProxy?groupId=" + types.String(groupId),
|
||||
"isActive": menuItem == "httpReverseProxy",
|
||||
"isOn": configInfoResp.HasHTTPReverseProxy,
|
||||
},
|
||||
{
|
||||
"name": "TCP反向代理",
|
||||
"name": "TCP代理",
|
||||
"url": urlPrefix + "/tcpReverseProxy?groupId=" + types.String(groupId),
|
||||
"isActive": menuItem == "tcpReverseProxy",
|
||||
"isOn": configInfoResp.HasTCPReverseProxy,
|
||||
},
|
||||
{
|
||||
"name": "UDP反向代理",
|
||||
"name": "UDP代理",
|
||||
"url": urlPrefix + "/udpReverseProxy?groupId=" + types.String(groupId),
|
||||
"isActive": menuItem == "udpReverseProxy",
|
||||
"isOn": configInfoResp.HasUDPReverseProxy,
|
||||
},
|
||||
/**{
|
||||
"name": "-",
|
||||
"url": "",
|
||||
},
|
||||
{
|
||||
"name": "WAF",
|
||||
"url": urlPrefix + "/waf?groupId=" + types.String(groupId),
|
||||
"isActive": menuItem == "waf",
|
||||
},
|
||||
{
|
||||
"name": "缓存",
|
||||
"url": urlPrefix + "/cache?groupId=" + types.String(groupId),
|
||||
"isActive": menuItem == "cache",
|
||||
},
|
||||
{
|
||||
"name": "访问日志",
|
||||
"url": urlPrefix + "/accessLog?groupId=" + types.String(groupId),
|
||||
"isActive": menuItem == "accessLog",
|
||||
},
|
||||
{
|
||||
"name": "统计",
|
||||
"url": urlPrefix + "/stat?groupId=" + types.String(groupId),
|
||||
"isActive": menuItem == "stat",
|
||||
},
|
||||
{
|
||||
"name": "Gzip压缩",
|
||||
"url": urlPrefix + "/gzip?groupId=" + types.String(groupId),
|
||||
"isActive": menuItem == "gzip",
|
||||
},
|
||||
{
|
||||
"name": "特殊页面",
|
||||
"url": urlPrefix + "/pages?groupId=" + types.String(groupId),
|
||||
"isActive": menuItem == "page",
|
||||
},
|
||||
{
|
||||
"name": "HTTP Header",
|
||||
"url": urlPrefix + "/headers?groupId=" + types.String(groupId),
|
||||
"isActive": menuItem == "header",
|
||||
},
|
||||
{
|
||||
"name": "Websocket",
|
||||
"url": urlPrefix + "/websocket?groupId=" + types.String(groupId),
|
||||
"isActive": menuItem == "websocket",
|
||||
},**/
|
||||
}
|
||||
|
||||
if teaconst.IsPlus {
|
||||
leftMenuItems = append([]maps.Map{
|
||||
{
|
||||
"name": "Web设置",
|
||||
"url": urlPrefix + "/web?groupId=" + types.String(groupId),
|
||||
"isActive": menuItem == "web",
|
||||
"isOn": configInfoResp.HasRootConfig,
|
||||
},
|
||||
}, leftMenuItems...)
|
||||
leftMenuItems = append(leftMenuItems, []maps.Map{
|
||||
{
|
||||
"name": "-",
|
||||
"url": "",
|
||||
},
|
||||
{
|
||||
"name": "WAF",
|
||||
"url": urlPrefix + "/waf?groupId=" + types.String(groupId),
|
||||
"isActive": menuItem == "waf",
|
||||
"isOn": configInfoResp.HasWAFConfig,
|
||||
},
|
||||
{
|
||||
"name": "缓存",
|
||||
"url": urlPrefix + "//cache?groupId=" + types.String(groupId),
|
||||
"isActive": menuItem == "cache",
|
||||
"isOn": configInfoResp.HasCacheConfig,
|
||||
},
|
||||
{
|
||||
"name": "字符编码",
|
||||
"url": urlPrefix + "/charset?groupId=" + types.String(groupId),
|
||||
"isActive": menuItem == "charset",
|
||||
"isOn": configInfoResp.HasCharsetConfig,
|
||||
},
|
||||
{
|
||||
"name": "访问日志",
|
||||
"url": urlPrefix + "/accessLog?groupId=" + types.String(groupId),
|
||||
"isActive": menuItem == "accessLog",
|
||||
"isOn": configInfoResp.HasAccessLogConfig,
|
||||
},
|
||||
{
|
||||
"name": "统计",
|
||||
"url": urlPrefix + "/stat?groupId=" + types.String(groupId),
|
||||
"isActive": menuItem == "stat",
|
||||
"isOn": configInfoResp.HasStatConfig,
|
||||
},
|
||||
{
|
||||
"name": "内容压缩",
|
||||
"url": urlPrefix + "/compression?groupId=" + types.String(groupId),
|
||||
"isActive": menuItem == "compression",
|
||||
"isOn": configInfoResp.HasCompressionConfig,
|
||||
},
|
||||
{
|
||||
"name": "特殊页面",
|
||||
"url": urlPrefix + "/pages?groupId=" + types.String(groupId),
|
||||
"isActive": menuItem == "pages",
|
||||
"isOn": configInfoResp.HasPagesConfig,
|
||||
},
|
||||
{
|
||||
"name": "HTTP Header",
|
||||
"url": urlPrefix + "/headers?groupId=" + types.String(groupId),
|
||||
"isActive": menuItem == "headers",
|
||||
"isOn": configInfoResp.HasRequestHeadersConfig || configInfoResp.HasResponseHeadersConfig,
|
||||
},
|
||||
{
|
||||
"name": "Websocket",
|
||||
"url": urlPrefix + "/websocket?groupId=" + types.String(groupId),
|
||||
"isActive": menuItem == "websocket",
|
||||
"isOn": configInfoResp.HasWebsocketConfig,
|
||||
},
|
||||
{
|
||||
"name": "WebP",
|
||||
"url": urlPrefix + "/webp?groupId=" + types.String(groupId),
|
||||
"isActive": menuItem == "webp",
|
||||
"isOn": configInfoResp.HasWebPConfig,
|
||||
},
|
||||
}...)
|
||||
}
|
||||
|
||||
leftMenuItems = append(leftMenuItems, maps.Map{
|
||||
"name": "-",
|
||||
"url": "",
|
||||
})
|
||||
leftMenuItems = append(leftMenuItems, maps.Map{
|
||||
"name": "访客IP地址",
|
||||
"url": urlPrefix + "/remoteAddr?groupId=" + types.String(groupId),
|
||||
"isActive": menuItem == "remoteAddr",
|
||||
"isOn": configInfoResp.HasRemoteAddrConfig,
|
||||
})
|
||||
parent.Data["leftMenuItems"] = leftMenuItems
|
||||
}
|
||||
|
||||
return group, nil
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
package accessLog
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/oplogs"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/groups/group/servergrouputils"
|
||||
"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("accessLog")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct {
|
||||
GroupId int64
|
||||
}) {
|
||||
_, err := servergrouputils.InitGroup(this.Parent(), params.GroupId, "accessLog")
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
// 获取配置
|
||||
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithServerGroupId(this.AdminContext(), params.GroupId)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
this.Data["webId"] = webConfig.Id
|
||||
this.Data["accessLogConfig"] = webConfig.AccessLogRef
|
||||
|
||||
// 通用变量
|
||||
this.Data["fields"] = serverconfigs.HTTPAccessLogFields
|
||||
this.Data["defaultFieldCodes"] = serverconfigs.HTTPAccessLogDefaultFieldsCodes
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunPost(params struct {
|
||||
WebId int64
|
||||
AccessLogJSON []byte
|
||||
|
||||
Must *actions.Must
|
||||
}) {
|
||||
// 日志
|
||||
defer this.CreateLog(oplogs.LevelInfo, "修改Web %d 的访问日志设置", params.WebId)
|
||||
|
||||
// TODO 检查参数
|
||||
|
||||
_, err := this.RPC().HTTPWebRPC().UpdateHTTPWebAccessLog(this.AdminContext(), &pb.UpdateHTTPWebAccessLogRequest{
|
||||
WebId: params.WebId,
|
||||
AccessLogJSON: params.AccessLogJSON,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package test
|
||||
package accessLog
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
|
||||
@@ -9,12 +9,11 @@ import (
|
||||
func init() {
|
||||
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
||||
server.
|
||||
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeNS)).
|
||||
Data("teaMenu", "ns").
|
||||
Data("teaSubMenu", "test").
|
||||
Prefix("/ns/test").
|
||||
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeServer)).
|
||||
Data("teaMenu", "servers").
|
||||
Data("teaSubMenu", "group").
|
||||
Prefix("/servers/groups/group/settings/accessLog").
|
||||
GetPost("", new(IndexAction)).
|
||||
Post("/nodeOptions", new(NodeOptionsAction)).
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
88
internal/web/actions/default/servers/groups/group/settings/cache/index.go
vendored
Normal file
88
internal/web/actions/default/servers/groups/group/settings/cache/index.go
vendored
Normal file
@@ -0,0 +1,88 @@
|
||||
package cache
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/oplogs"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/groups/group/servergrouputils"
|
||||
"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("cache")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct {
|
||||
GroupId int64
|
||||
}) {
|
||||
_, err := servergrouputils.InitGroup(this.Parent(), params.GroupId, "cache")
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithServerGroupId(this.AdminContext(), params.GroupId)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Data["webId"] = webConfig.Id
|
||||
this.Data["cacheConfig"] = webConfig.Cache
|
||||
|
||||
this.Data["cachePolicy"] = nil
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunPost(params struct {
|
||||
WebId int64
|
||||
CacheJSON []byte
|
||||
|
||||
Must *actions.Must
|
||||
}) {
|
||||
// 日志
|
||||
defer this.CreateLog(oplogs.LevelInfo, "修改Web %d 的缓存设置", params.WebId)
|
||||
|
||||
// 校验配置
|
||||
cacheConfig := &serverconfigs.HTTPCacheConfig{}
|
||||
err := json.Unmarshal(params.CacheJSON, cacheConfig)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
err = cacheConfig.Init()
|
||||
if err != nil {
|
||||
this.Fail("检查配置失败:" + err.Error())
|
||||
}
|
||||
|
||||
// 去除不必要的部分
|
||||
for _, cacheRef := range cacheConfig.CacheRefs {
|
||||
cacheRef.CachePolicy = nil
|
||||
}
|
||||
|
||||
cacheJSON, err := json.Marshal(cacheConfig)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
_, err = this.RPC().HTTPWebRPC().UpdateHTTPWebCache(this.AdminContext(), &pb.UpdateHTTPWebCacheRequest{
|
||||
WebId: params.WebId,
|
||||
CacheJSON: cacheJSON,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
21
internal/web/actions/default/servers/groups/group/settings/cache/init.go
vendored
Normal file
21
internal/web/actions/default/servers/groups/group/settings/cache/init.go
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
package cache
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
|
||||
"github.com/iwind/TeaGo"
|
||||
)
|
||||
|
||||
func init() {
|
||||
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
||||
server.
|
||||
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeServer)).
|
||||
Data("teaMenu", "servers").
|
||||
Data("teaSubMenu", "group").
|
||||
Prefix("/servers/groups/group/settings/cache").
|
||||
GetPost("", new(IndexAction)).
|
||||
GetPost("/purge", new(PurgeAction)).
|
||||
GetPost("/preheat", new(PreheatAction)).
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
143
internal/web/actions/default/servers/groups/group/settings/cache/preheat.go
vendored
Normal file
143
internal/web/actions/default/servers/groups/group/settings/cache/preheat.go
vendored
Normal file
@@ -0,0 +1,143 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package cache
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/oplogs"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/nodes/nodeutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/messageconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/lists"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type PreheatAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *PreheatAction) Init() {
|
||||
this.Nav("", "setting", "preheat")
|
||||
this.SecondMenu("cache")
|
||||
}
|
||||
|
||||
func (this *PreheatAction) RunGet(params struct {
|
||||
ServerId int64
|
||||
}) {
|
||||
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithServerId(this.AdminContext(), params.ServerId)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Data["webId"] = webConfig.Id
|
||||
this.Data["webConfig"] = webConfig
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *PreheatAction) RunPost(params struct {
|
||||
ServerId int64
|
||||
WebId int64
|
||||
Keys string
|
||||
|
||||
Must *actions.Must
|
||||
}) {
|
||||
|
||||
// 创建日志
|
||||
defer this.CreateLog(oplogs.LevelInfo, "预热服务 %d 缓存", params.ServerId)
|
||||
|
||||
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithId(this.AdminContext(), params.WebId)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if webConfig == nil {
|
||||
this.NotFound("httpWeb", params.WebId)
|
||||
return
|
||||
}
|
||||
var cache = webConfig.Cache
|
||||
if cache == nil || !cache.IsOn {
|
||||
this.Fail("当前没有开启缓存")
|
||||
}
|
||||
|
||||
serverResp, err := this.RPC().ServerRPC().FindEnabledUserServerBasic(this.AdminContext(), &pb.FindEnabledUserServerBasicRequest{ServerId: params.ServerId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var server = serverResp.Server
|
||||
if server == nil || server.NodeCluster == nil {
|
||||
this.NotFound("server", params.ServerId)
|
||||
return
|
||||
}
|
||||
|
||||
var clusterId = server.NodeCluster.Id
|
||||
|
||||
clusterResp, err := this.RPC().NodeClusterRPC().FindEnabledNodeCluster(this.AdminContext(), &pb.FindEnabledNodeClusterRequest{NodeClusterId: clusterId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var cluster = clusterResp.NodeCluster
|
||||
if cluster == nil {
|
||||
this.NotFound("nodeCluster", clusterId)
|
||||
return
|
||||
}
|
||||
var cachePolicyId = cluster.HttpCachePolicyId
|
||||
if cachePolicyId == 0 {
|
||||
this.Fail("当前集群没有设置缓存策略")
|
||||
}
|
||||
|
||||
cachePolicyResp, err := this.RPC().HTTPCachePolicyRPC().FindEnabledHTTPCachePolicyConfig(this.AdminContext(), &pb.FindEnabledHTTPCachePolicyConfigRequest{HttpCachePolicyId: cachePolicyId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
cachePolicyJSON := cachePolicyResp.HttpCachePolicyJSON
|
||||
if len(cachePolicyJSON) == 0 {
|
||||
this.Fail("找不到要操作的缓存策略")
|
||||
}
|
||||
|
||||
if len(params.Keys) == 0 {
|
||||
this.Fail("请输入要预热的Key列表")
|
||||
}
|
||||
|
||||
realKeys := []string{}
|
||||
for _, key := range strings.Split(params.Keys, "\n") {
|
||||
key = strings.TrimSpace(key)
|
||||
if len(key) == 0 {
|
||||
continue
|
||||
}
|
||||
if lists.ContainsString(realKeys, key) {
|
||||
continue
|
||||
}
|
||||
realKeys = append(realKeys, key)
|
||||
}
|
||||
|
||||
// 发送命令
|
||||
msg := &messageconfigs.PreheatCacheMessage{
|
||||
CachePolicyJSON: cachePolicyJSON,
|
||||
Keys: realKeys,
|
||||
}
|
||||
results, err := nodeutils.SendMessageToCluster(this.AdminContext(), clusterId, messageconfigs.MessageCodePreheatCache, msg, 300)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
isAllOk := true
|
||||
for _, result := range results {
|
||||
if !result.IsOK {
|
||||
isAllOk = false
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
this.Data["isAllOk"] = isAllOk
|
||||
this.Data["results"] = results
|
||||
|
||||
this.Success()
|
||||
}
|
||||
149
internal/web/actions/default/servers/groups/group/settings/cache/purge.go
vendored
Normal file
149
internal/web/actions/default/servers/groups/group/settings/cache/purge.go
vendored
Normal file
@@ -0,0 +1,149 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package cache
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/oplogs"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/nodes/nodeutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/messageconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/lists"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type PurgeAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *PurgeAction) Init() {
|
||||
this.Nav("", "setting", "purge")
|
||||
this.SecondMenu("cache")
|
||||
}
|
||||
|
||||
func (this *PurgeAction) RunGet(params struct {
|
||||
ServerId int64
|
||||
}) {
|
||||
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithServerId(this.AdminContext(), params.ServerId)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Data["webId"] = webConfig.Id
|
||||
this.Data["webConfig"] = webConfig
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *PurgeAction) RunPost(params struct {
|
||||
ServerId int64
|
||||
WebId int64
|
||||
Type string
|
||||
Keys string
|
||||
|
||||
Must *actions.Must
|
||||
}) {
|
||||
|
||||
// 创建日志
|
||||
defer this.CreateLog(oplogs.LevelInfo, "删除服务 %d 缓存", params.ServerId)
|
||||
|
||||
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithId(this.AdminContext(), params.WebId)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if webConfig == nil {
|
||||
this.NotFound("httpWeb", params.WebId)
|
||||
return
|
||||
}
|
||||
var cache = webConfig.Cache
|
||||
if cache == nil || !cache.IsOn {
|
||||
this.Fail("当前没有开启缓存")
|
||||
}
|
||||
|
||||
serverResp, err := this.RPC().ServerRPC().FindEnabledUserServerBasic(this.AdminContext(), &pb.FindEnabledUserServerBasicRequest{ServerId: params.ServerId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var server = serverResp.Server
|
||||
if server == nil || server.NodeCluster == nil {
|
||||
this.NotFound("server", params.ServerId)
|
||||
return
|
||||
}
|
||||
|
||||
var clusterId = server.NodeCluster.Id
|
||||
|
||||
clusterResp, err := this.RPC().NodeClusterRPC().FindEnabledNodeCluster(this.AdminContext(), &pb.FindEnabledNodeClusterRequest{NodeClusterId: clusterId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var cluster = clusterResp.NodeCluster
|
||||
if cluster == nil {
|
||||
this.NotFound("nodeCluster", clusterId)
|
||||
return
|
||||
}
|
||||
var cachePolicyId = cluster.HttpCachePolicyId
|
||||
if cachePolicyId == 0 {
|
||||
this.Fail("当前集群没有设置缓存策略")
|
||||
}
|
||||
|
||||
cachePolicyResp, err := this.RPC().HTTPCachePolicyRPC().FindEnabledHTTPCachePolicyConfig(this.AdminContext(), &pb.FindEnabledHTTPCachePolicyConfigRequest{HttpCachePolicyId: cachePolicyId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
cachePolicyJSON := cachePolicyResp.HttpCachePolicyJSON
|
||||
if len(cachePolicyJSON) == 0 {
|
||||
this.Fail("找不到要操作的缓存策略")
|
||||
}
|
||||
|
||||
if len(params.Keys) == 0 {
|
||||
this.Fail("请输入要删除的Key列表")
|
||||
}
|
||||
|
||||
realKeys := []string{}
|
||||
for _, key := range strings.Split(params.Keys, "\n") {
|
||||
key = strings.TrimSpace(key)
|
||||
if len(key) == 0 {
|
||||
continue
|
||||
}
|
||||
if lists.ContainsString(realKeys, key) {
|
||||
continue
|
||||
}
|
||||
realKeys = append(realKeys, key)
|
||||
}
|
||||
|
||||
// 发送命令
|
||||
msg := &messageconfigs.PurgeCacheMessage{
|
||||
CachePolicyJSON: cachePolicyJSON,
|
||||
Keys: realKeys,
|
||||
}
|
||||
if params.Type == "prefix" {
|
||||
msg.Type = messageconfigs.PurgeCacheMessageTypeDir
|
||||
} else {
|
||||
msg.Type = messageconfigs.PurgeCacheMessageTypeFile
|
||||
}
|
||||
results, err := nodeutils.SendMessageToCluster(this.AdminContext(), clusterId, messageconfigs.MessageCodePurgeCache, msg, 10)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
isAllOk := true
|
||||
for _, result := range results {
|
||||
if !result.IsOK {
|
||||
isAllOk = false
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
this.Data["isAllOk"] = isAllOk
|
||||
this.Data["results"] = results
|
||||
|
||||
this.Success()
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user