Compare commits
185 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1b7dc8eb96 | ||
|
|
7c0af45dd0 | ||
|
|
daea270132 | ||
|
|
a42e3ac4a6 | ||
|
|
c94c526b43 | ||
|
|
e531787773 | ||
|
|
0eda84a99a | ||
|
|
89b791448a | ||
|
|
2239328b2e | ||
|
|
e440a46080 | ||
|
|
4a0fec6e35 | ||
|
|
a9b46987bc | ||
|
|
6771afead5 | ||
|
|
553fca2981 | ||
|
|
8ef1e36b8b | ||
|
|
9e6c49b67c | ||
|
|
170632ddbc | ||
|
|
4a74488cac | ||
|
|
5fd6a08988 | ||
|
|
c86b91ead6 | ||
|
|
aeebb763c1 | ||
|
|
b05630e3e0 | ||
|
|
51905a0ee3 | ||
|
|
869ebd59d1 | ||
|
|
8a6aedca16 | ||
|
|
cf98c3453a | ||
|
|
1b6f234f39 | ||
|
|
26c7f0f566 | ||
|
|
617ad9b16e | ||
|
|
04a6792dbf | ||
|
|
f2bf8f2dbf | ||
|
|
3aba0abd24 | ||
|
|
b56ccc7cef | ||
|
|
aeebf55e60 | ||
|
|
9a9e0d25f3 | ||
|
|
6b3033e240 | ||
|
|
2859a59340 | ||
|
|
45367dd579 | ||
|
|
fee3fd743f | ||
|
|
ba4cfea47c | ||
|
|
5c11f07f8e | ||
|
|
ffac080611 | ||
|
|
f7a1e60735 | ||
|
|
f22651821c | ||
|
|
b2a5a9ac9b | ||
|
|
245af2bd77 | ||
|
|
9dd2b1d35c | ||
|
|
bdbfd3e055 | ||
|
|
1518c03d2b | ||
|
|
45920d4df2 | ||
|
|
1c106ac6eb | ||
|
|
9f4a32b4ac | ||
|
|
2565b10491 | ||
|
|
34d632a401 | ||
|
|
a9df27c0e1 | ||
|
|
313011a168 | ||
|
|
5c595aad83 | ||
|
|
2c67eac63c | ||
|
|
d20c20cb33 | ||
|
|
fa76f032be | ||
|
|
3f74910640 | ||
|
|
22bd2a57e9 | ||
|
|
e45a1d0367 | ||
|
|
ee7acdc6a0 | ||
|
|
32264f2700 | ||
|
|
249ea32973 | ||
|
|
9c31b69a58 | ||
|
|
6e985cf6cc | ||
|
|
0f35b45704 | ||
|
|
ba9245e724 | ||
|
|
6e806f2822 | ||
|
|
7c6842a859 | ||
|
|
39f9fa0e6b | ||
|
|
0c8ae8960d | ||
|
|
ffd6a20829 | ||
|
|
2ee3e2782c | ||
|
|
61324c28c6 | ||
|
|
e9f70ecb90 | ||
|
|
cc3b802575 | ||
|
|
9b780ff4a3 | ||
|
|
deb1a33e78 | ||
|
|
5021350aa0 | ||
|
|
41b3dab135 | ||
|
|
ecf94170c8 | ||
|
|
56acdf3ce3 | ||
|
|
5d6d970d49 | ||
|
|
b501cf3c88 | ||
|
|
deac2baa18 | ||
|
|
b1e3f54055 | ||
|
|
8ebf79ffbe | ||
|
|
8d7307cddf | ||
|
|
c547837ae3 | ||
|
|
b408996e72 | ||
|
|
6b5866524d | ||
|
|
4994dfb488 | ||
|
|
5d5040651e | ||
|
|
5252188a68 | ||
|
|
3f664882d5 | ||
|
|
15f2a2d517 | ||
|
|
6637b0fb8f | ||
|
|
a06eeb9129 | ||
|
|
a24fce2c22 | ||
|
|
ddbdb64fc4 | ||
|
|
38c6d545ec | ||
|
|
fe880abbb0 | ||
|
|
081ed76c39 | ||
|
|
613a00686f | ||
|
|
11739ee671 | ||
|
|
d06951e3b5 | ||
|
|
63bbacd4d8 | ||
|
|
6ba130b62c | ||
|
|
5529d644ac | ||
|
|
7e5e6fb5b4 | ||
|
|
f5fb1911f7 | ||
|
|
e26e129a63 | ||
|
|
280cedad8d | ||
|
|
7c3d5aa69c | ||
|
|
7224ba1123 | ||
|
|
0f7d5057fd | ||
|
|
43f2804ced | ||
|
|
5bb83555a4 | ||
|
|
af4d14364c | ||
|
|
105e717eb2 | ||
|
|
697ec6f6e3 | ||
|
|
e07c99f34d | ||
|
|
c047bd5896 | ||
|
|
d97ac01d79 | ||
|
|
df19a04ad1 | ||
|
|
cbce8a9934 | ||
|
|
7739a84828 | ||
|
|
96f711b43f | ||
|
|
96b3ae5e7d | ||
|
|
d0508e257a | ||
|
|
ec8548f133 | ||
|
|
f217b4190b | ||
|
|
9a3b9ee8f8 | ||
|
|
1c299c767b | ||
|
|
03b46f4c24 | ||
|
|
0f40b6438a | ||
|
|
4549d93e0d | ||
|
|
844cec1011 | ||
|
|
0464c6ce43 | ||
|
|
0cdaa9bb70 | ||
|
|
dade2eb4ff | ||
|
|
42e1cd560e | ||
|
|
5db14ec84a | ||
|
|
22aca2e80c | ||
|
|
4f105f9327 | ||
|
|
e2a218dd63 | ||
|
|
f9c0226fa0 | ||
|
|
fcccd69cee | ||
|
|
cc60c827da | ||
|
|
3c44e14386 | ||
|
|
7f765f4267 | ||
|
|
2262e6f3ca | ||
|
|
4349d165ac | ||
|
|
9d396af447 | ||
|
|
a665457014 | ||
|
|
92ddd04b07 | ||
|
|
b5f93d6fbc | ||
|
|
374b75b9f1 | ||
|
|
47b7d283a3 | ||
|
|
03a3b8b38f | ||
|
|
d2a27f16d7 | ||
|
|
b9837f526b | ||
|
|
2393f3a701 | ||
|
|
b910339e6e | ||
|
|
438445dab8 | ||
|
|
dc7e62c388 | ||
|
|
3ed8f9ca55 | ||
|
|
0282b5e75f | ||
|
|
f5f8218940 | ||
|
|
a634046757 | ||
|
|
6a4d86e084 | ||
|
|
9f9b41c63d | ||
|
|
d813f6515b | ||
|
|
730a445ef6 | ||
|
|
938947548b | ||
|
|
2d5085e652 | ||
|
|
e665e299f2 | ||
|
|
30b9c5eda5 | ||
|
|
fbf29e774a | ||
|
|
5429971553 | ||
|
|
df81bde6fd | ||
|
|
cb8b56ceb8 |
74
.golangci.yaml
Normal file
74
.golangci.yaml
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
# https://golangci-lint.run/usage/configuration/
|
||||||
|
|
||||||
|
linters:
|
||||||
|
enable-all: true
|
||||||
|
disable:
|
||||||
|
- ifshort
|
||||||
|
- exhaustivestruct
|
||||||
|
- golint
|
||||||
|
- nosnakecase
|
||||||
|
- scopelint
|
||||||
|
- varcheck
|
||||||
|
- structcheck
|
||||||
|
- interfacer
|
||||||
|
- maligned
|
||||||
|
- deadcode
|
||||||
|
- dogsled
|
||||||
|
- wrapcheck
|
||||||
|
- wastedassign
|
||||||
|
- varnamelen
|
||||||
|
- testpackage
|
||||||
|
- thelper
|
||||||
|
- nilerr
|
||||||
|
- sqlclosecheck
|
||||||
|
- paralleltest
|
||||||
|
- nonamedreturns
|
||||||
|
- nlreturn
|
||||||
|
- nakedret
|
||||||
|
- ireturn
|
||||||
|
- interfacebloat
|
||||||
|
- gosmopolitan
|
||||||
|
- gomnd
|
||||||
|
- goerr113
|
||||||
|
- gochecknoglobals
|
||||||
|
- exhaustruct
|
||||||
|
- errorlint
|
||||||
|
- depguard
|
||||||
|
- exhaustive
|
||||||
|
- containedctx
|
||||||
|
- wsl
|
||||||
|
- cyclop
|
||||||
|
- dupword
|
||||||
|
- errchkjson
|
||||||
|
- contextcheck
|
||||||
|
- tagalign
|
||||||
|
- dupl
|
||||||
|
- forbidigo
|
||||||
|
- funlen
|
||||||
|
- goconst
|
||||||
|
- godox
|
||||||
|
- gosec
|
||||||
|
- lll
|
||||||
|
- nestif
|
||||||
|
- revive
|
||||||
|
- unparam
|
||||||
|
- stylecheck
|
||||||
|
- gocritic
|
||||||
|
- gofumpt
|
||||||
|
- gomoddirectives
|
||||||
|
- godot
|
||||||
|
- gofmt
|
||||||
|
- gocognit
|
||||||
|
- mirror
|
||||||
|
- gocyclo
|
||||||
|
- gochecknoinits
|
||||||
|
- gci
|
||||||
|
- maintidx
|
||||||
|
- prealloc
|
||||||
|
- goimports
|
||||||
|
- errname
|
||||||
|
- musttag
|
||||||
|
- forcetypeassert
|
||||||
|
- whitespace
|
||||||
|
- noctx
|
||||||
|
- reassign
|
||||||
@@ -46,7 +46,7 @@
|
|||||||
* [开发者指南](https://goedge.cn/docs/Developer/Build.md)
|
* [开发者指南](https://goedge.cn/docs/Developer/Build.md)
|
||||||
|
|
||||||
## 架构
|
## 架构
|
||||||

|

|
||||||
|
|
||||||
其中的组件源码地址如下:
|
其中的组件源码地址如下:
|
||||||
* [边缘节点](https://github.com/TeaOSLab/EdgeNode)
|
* [边缘节点](https://github.com/TeaOSLab/EdgeNode)
|
||||||
|
|||||||
@@ -57,9 +57,11 @@ function build() {
|
|||||||
if [ "$(which uglifyjs)" ]; then
|
if [ "$(which uglifyjs)" ]; then
|
||||||
echo "compress to component.js ..."
|
echo "compress to component.js ..."
|
||||||
uglifyjs --compress --mangle -- "${JS_ROOT}"/components.src.js > "${JS_ROOT}"/components.js
|
uglifyjs --compress --mangle -- "${JS_ROOT}"/components.src.js > "${JS_ROOT}"/components.js
|
||||||
|
uglifyjs --compress --mangle -- "${JS_ROOT}"/utils.js > "${JS_ROOT}"/utils.min.js
|
||||||
else
|
else
|
||||||
echo "copy to component.js ..."
|
echo "copy to component.js ..."
|
||||||
cp "${JS_ROOT}"/components.src.js "${JS_ROOT}"/components.js
|
cp "${JS_ROOT}"/components.src.js "${JS_ROOT}"/components.js
|
||||||
|
cp "${JS_ROOT}"/utils.js "${JS_ROOT}"/utils.min.js
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# create dir & copy files
|
# create dir & copy files
|
||||||
|
|||||||
1
build/configs/.gitignore
vendored
1
build/configs/.gitignore
vendored
@@ -1,4 +1,5 @@
|
|||||||
api.yaml
|
api.yaml
|
||||||
|
api_admin.yaml
|
||||||
server.yaml
|
server.yaml
|
||||||
api_db.yaml
|
api_db.yaml
|
||||||
*.pem
|
*.pem
|
||||||
|
|||||||
@@ -1,4 +0,0 @@
|
|||||||
rpc:
|
|
||||||
endpoints: [ "http://127.0.0.1:8003" ]
|
|
||||||
nodeId: ""
|
|
||||||
secret: ""
|
|
||||||
3
build/configs/api_admin.template.yaml
Normal file
3
build/configs/api_admin.template.yaml
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
rpc.endpoints: [ "http://127.0.0.1:8003" ]
|
||||||
|
nodeId: ""
|
||||||
|
secret: ""
|
||||||
@@ -2,15 +2,21 @@
|
|||||||
|
|
||||||
JS_ROOT=../web/public/js
|
JS_ROOT=../web/public/js
|
||||||
|
|
||||||
echo "generate component.src.js ..."
|
echo "generating component.src.js ..."
|
||||||
go run -tags=community ../cmd/edge-admin/main.go generate
|
go run -tags=community ../cmd/edge-admin/main.go generate
|
||||||
|
|
||||||
if [ `which uglifyjs` ]; then
|
if [ "$(which uglifyjs)" ]; then
|
||||||
echo "compress to component.js ..."
|
echo "compress to component.js ..."
|
||||||
uglifyjs --compress --mangle -- ${JS_ROOT}/components.src.js > ${JS_ROOT}/components.js
|
uglifyjs --compress --mangle -- ${JS_ROOT}/components.src.js > ${JS_ROOT}/components.js
|
||||||
|
|
||||||
|
echo "compress to utils.min.js ..."
|
||||||
|
uglifyjs --compress --mangle -- ${JS_ROOT}/utils.js > ${JS_ROOT}/utils.min.js
|
||||||
else
|
else
|
||||||
echo "copy to component.js ..."
|
echo "copy to component.js ..."
|
||||||
cp ${JS_ROOT}/components.src.js ${JS_ROOT}/components.js
|
cp ${JS_ROOT}/components.src.js ${JS_ROOT}/components.js
|
||||||
|
|
||||||
|
echo "copy to utils.min.js ..."
|
||||||
|
cp ${JS_ROOT}/utils.js ${JS_ROOT}/utils.min.js
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "ok"
|
echo "ok"
|
||||||
@@ -161,7 +161,7 @@ func main() {
|
|||||||
if progress >= 0 {
|
if progress >= 0 {
|
||||||
if progress == 0 || progress == 1 || progress-lastProgress >= 0.1 {
|
if progress == 0 || progress == 1 || progress-lastProgress >= 0.1 {
|
||||||
lastProgress = progress
|
lastProgress = progress
|
||||||
log.Println(fmt.Sprintf("%.2f%%", manager.Progress()*100))
|
log.Printf("%.2f%%", manager.Progress()*100)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 72 KiB |
BIN
doc/architect-zh.png
Normal file
BIN
doc/architect-zh.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.4 MiB |
@@ -1,11 +1,15 @@
|
|||||||
FROM alpine:latest
|
FROM --platform=linux/amd64 alpine:latest
|
||||||
LABEL maintainer="goedge.cdn@gmail.com"
|
LABEL maintainer="goedge.cdn@gmail.com"
|
||||||
ENV TZ "Asia/Shanghai"
|
ENV TZ "Asia/Shanghai"
|
||||||
ENV VERSION 1.2.2
|
ENV VERSION 1.3.0
|
||||||
ENV ROOT_DIR /usr/local/goedge
|
ENV ROOT_DIR /usr/local/goedge
|
||||||
ENV TAR_FILE edge-admin-linux-amd64-plus-v${VERSION}.zip
|
ENV TAR_FILE edge-admin-linux-amd64-plus-v${VERSION}.zip
|
||||||
|
|
||||||
|
# remote official repository
|
||||||
ENV TAR_URL "https://dl.goedge.cn/edge/v${VERSION}/edge-admin-linux-amd64-plus-v${VERSION}.zip"
|
ENV TAR_URL "https://dl.goedge.cn/edge/v${VERSION}/edge-admin-linux-amd64-plus-v${VERSION}.zip"
|
||||||
#ENV TAR_URL "http://192.168.2.60:8080/edge-admin-linux-amd64-plus-v${VERSION}.zip" # your local repository
|
|
||||||
|
# your local repository
|
||||||
|
#ENV TAR_URL "http://192.168.2.61:8080/edge-admin-linux-amd64-plus-v${VERSION}.zip"
|
||||||
|
|
||||||
RUN apk add --no-cache tzdata
|
RUN apk add --no-cache tzdata
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package apps
|
package apps
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
teaconst "github.com/TeaOSLab/EdgeAdmin/internal/const"
|
teaconst "github.com/TeaOSLab/EdgeAdmin/internal/const"
|
||||||
"github.com/iwind/TeaGo/logs"
|
"github.com/iwind/TeaGo/logs"
|
||||||
@@ -9,8 +10,10 @@ import (
|
|||||||
"github.com/iwind/gosock/pkg/gosock"
|
"github.com/iwind/gosock/pkg/gosock"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -186,13 +189,16 @@ func (this *AppCmd) runStart() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd := exec.Command(os.Args[0])
|
var cmd = exec.Command(this.exe())
|
||||||
err := cmd.Start()
|
err := cmd.Start()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(this.product+" start failed:", err.Error())
|
fmt.Println(this.product+" start failed:", err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// create symbolic links
|
||||||
|
_ = this.createSymLinks()
|
||||||
|
|
||||||
fmt.Println(this.product+" started ok, pid:", cmd.Process.Pid)
|
fmt.Println(this.product+" started ok, pid:", cmd.Process.Pid)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -239,3 +245,58 @@ func (this *AppCmd) getPID() int {
|
|||||||
}
|
}
|
||||||
return maps.NewMap(reply.Params).GetInt("pid")
|
return maps.NewMap(reply.Params).GetInt("pid")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (this *AppCmd) exe() string {
|
||||||
|
var exe, _ = os.Executable()
|
||||||
|
if len(exe) == 0 {
|
||||||
|
exe = os.Args[0]
|
||||||
|
}
|
||||||
|
return exe
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建软链接
|
||||||
|
func (this *AppCmd) createSymLinks() error {
|
||||||
|
if runtime.GOOS != "linux" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var exe, _ = os.Executable()
|
||||||
|
if len(exe) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var errorList = []string{}
|
||||||
|
|
||||||
|
// bin
|
||||||
|
{
|
||||||
|
var target = "/usr/bin/" + teaconst.ProcessName
|
||||||
|
old, _ := filepath.EvalSymlinks(target)
|
||||||
|
if old != exe {
|
||||||
|
_ = os.Remove(target)
|
||||||
|
err := os.Symlink(exe, target)
|
||||||
|
if err != nil {
|
||||||
|
errorList = append(errorList, err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// log
|
||||||
|
{
|
||||||
|
var realPath = filepath.Dir(filepath.Dir(exe)) + "/logs/run.log"
|
||||||
|
var target = "/var/log/" + teaconst.ProcessName + ".log"
|
||||||
|
old, _ := filepath.EvalSymlinks(target)
|
||||||
|
if old != realPath {
|
||||||
|
_ = os.Remove(target)
|
||||||
|
err := os.Symlink(realPath, target)
|
||||||
|
if err != nil {
|
||||||
|
errorList = append(errorList, err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(errorList) > 0 {
|
||||||
|
return errors.New(strings.Join(errorList, "\n"))
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package configs
|
package configs
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
teaconst "github.com/TeaOSLab/EdgeAdmin/internal/const"
|
teaconst "github.com/TeaOSLab/EdgeAdmin/internal/const"
|
||||||
"github.com/iwind/TeaGo/Tea"
|
"github.com/iwind/TeaGo/Tea"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
@@ -8,12 +9,19 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const ConfigFileName = "api_admin.yaml"
|
||||||
|
const oldConfigFileName = "api.yaml"
|
||||||
|
|
||||||
// APIConfig API配置
|
// APIConfig API配置
|
||||||
type APIConfig struct {
|
type APIConfig struct {
|
||||||
RPC struct {
|
OldRPC struct {
|
||||||
Endpoints []string `yaml:"endpoints"`
|
Endpoints []string `yaml:"endpoints"`
|
||||||
DisableUpdate bool `yaml:"disableUpdate"`
|
DisableUpdate bool `yaml:"disableUpdate"`
|
||||||
} `yaml:"rpc"`
|
} `yaml:"rpc,omitempty"`
|
||||||
|
|
||||||
|
RPCEndpoints []string `yaml:"rpc.endpoints,flow" json:"rpc.endpoints"`
|
||||||
|
RPCDisableUpdate bool `yaml:"rpc.disableUpdate" json:"rpc.disableUpdate"`
|
||||||
|
|
||||||
NodeId string `yaml:"nodeId"`
|
NodeId string `yaml:"nodeId"`
|
||||||
Secret string `yaml:"secret"`
|
Secret string `yaml:"secret"`
|
||||||
}
|
}
|
||||||
@@ -21,23 +29,29 @@ type APIConfig struct {
|
|||||||
// LoadAPIConfig 加载API配置
|
// LoadAPIConfig 加载API配置
|
||||||
func LoadAPIConfig() (*APIConfig, error) {
|
func LoadAPIConfig() (*APIConfig, error) {
|
||||||
// 候选文件
|
// 候选文件
|
||||||
var localFile = Tea.ConfigFile("api.yaml")
|
var realFile = Tea.ConfigFile(ConfigFileName)
|
||||||
|
var oldRealFile = Tea.ConfigFile(oldConfigFileName)
|
||||||
var isFromLocal = false
|
var isFromLocal = false
|
||||||
var paths = []string{localFile}
|
var paths = []string{realFile, oldRealFile}
|
||||||
homeDir, homeErr := os.UserHomeDir()
|
homeDir, homeErr := os.UserHomeDir()
|
||||||
if homeErr == nil {
|
if homeErr == nil {
|
||||||
paths = append(paths, homeDir+"/."+teaconst.ProcessName+"/api.yaml")
|
paths = append(paths, homeDir+"/."+teaconst.ProcessName+"/"+ConfigFileName)
|
||||||
}
|
}
|
||||||
paths = append(paths, "/etc/"+teaconst.ProcessName+"/api.yaml")
|
paths = append(paths, "/etc/"+teaconst.ProcessName+"/"+ConfigFileName)
|
||||||
|
|
||||||
var data []byte
|
var data []byte
|
||||||
var err error
|
var err error
|
||||||
|
var isFromOld = false
|
||||||
for _, path := range paths {
|
for _, path := range paths {
|
||||||
data, err = os.ReadFile(path)
|
data, err = os.ReadFile(path)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
if path == localFile {
|
if path == realFile || path == oldRealFile {
|
||||||
isFromLocal = true
|
isFromLocal = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 自动生成新的配置文件
|
||||||
|
isFromOld = path == oldRealFile
|
||||||
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -51,9 +65,20 @@ func LoadAPIConfig() (*APIConfig, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = config.Init()
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.New("init error: " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
if !isFromLocal {
|
if !isFromLocal {
|
||||||
// 恢复文件
|
// 恢复文件
|
||||||
_ = os.WriteFile(localFile, data, 0666)
|
_ = os.WriteFile(realFile, data, 0666)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 自动生成新配置文件
|
||||||
|
if isFromOld {
|
||||||
|
config.OldRPC.Endpoints = nil
|
||||||
|
_ = config.WriteFile(Tea.ConfigFile(ConfigFileName))
|
||||||
}
|
}
|
||||||
|
|
||||||
return config, nil
|
return config, nil
|
||||||
@@ -61,9 +86,9 @@ func LoadAPIConfig() (*APIConfig, error) {
|
|||||||
|
|
||||||
// ResetAPIConfig 重置配置
|
// ResetAPIConfig 重置配置
|
||||||
func ResetAPIConfig() error {
|
func ResetAPIConfig() error {
|
||||||
var filename = "api.yaml"
|
var filename = ConfigFileName
|
||||||
|
|
||||||
// 重置 configs/api.yaml
|
// 重置 configs/api_admin.yaml
|
||||||
{
|
{
|
||||||
var configFile = Tea.ConfigFile(filename)
|
var configFile = Tea.ConfigFile(filename)
|
||||||
stat, err := os.Stat(configFile)
|
stat, err := os.Stat(configFile)
|
||||||
@@ -75,7 +100,7 @@ func ResetAPIConfig() error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 重置 ~/.edge-admin/api.yaml
|
// 重置 ~/.edge-admin/api_admin.yaml
|
||||||
homeDir, homeErr := os.UserHomeDir()
|
homeDir, homeErr := os.UserHomeDir()
|
||||||
if homeErr == nil {
|
if homeErr == nil {
|
||||||
var configFile = homeDir + "/." + teaconst.ProcessName + "/" + filename
|
var configFile = homeDir + "/." + teaconst.ProcessName + "/" + filename
|
||||||
@@ -88,7 +113,7 @@ func ResetAPIConfig() error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 重置 /etc/edge-admin/api.yaml
|
// 重置 /etc/edge-admin/api_admin.yaml
|
||||||
{
|
{
|
||||||
var configFile = "/etc/" + teaconst.ProcessName + "/" + filename
|
var configFile = "/etc/" + teaconst.ProcessName + "/" + filename
|
||||||
stat, err := os.Stat(configFile)
|
stat, err := os.Stat(configFile)
|
||||||
@@ -103,6 +128,22 @@ func ResetAPIConfig() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func IsNewInstalled() bool {
|
||||||
|
homeDir, err := os.UserHomeDir()
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, filename := range []string{ConfigFileName, oldConfigFileName} {
|
||||||
|
_, err = os.Stat(homeDir + "/." + teaconst.ProcessName + "/" + filename)
|
||||||
|
if err == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
// WriteFile 写入API配置
|
// WriteFile 写入API配置
|
||||||
func (this *APIConfig) WriteFile(path string) error {
|
func (this *APIConfig) WriteFile(path string) error {
|
||||||
data, err := yaml.Marshal(this)
|
data, err := yaml.Marshal(this)
|
||||||
@@ -159,11 +200,27 @@ func (this *APIConfig) WriteFile(path string) error {
|
|||||||
// Clone 克隆当前配置
|
// Clone 克隆当前配置
|
||||||
func (this *APIConfig) Clone() *APIConfig {
|
func (this *APIConfig) Clone() *APIConfig {
|
||||||
return &APIConfig{
|
return &APIConfig{
|
||||||
RPC: struct {
|
|
||||||
Endpoints []string `yaml:"endpoints"`
|
|
||||||
DisableUpdate bool `yaml:"disableUpdate"`
|
|
||||||
}{},
|
|
||||||
NodeId: this.NodeId,
|
NodeId: this.NodeId,
|
||||||
Secret: this.Secret,
|
Secret: this.Secret,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (this *APIConfig) Init() error {
|
||||||
|
// compatible with old
|
||||||
|
if len(this.RPCEndpoints) == 0 && len(this.OldRPC.Endpoints) > 0 {
|
||||||
|
this.RPCEndpoints = this.OldRPC.Endpoints
|
||||||
|
this.RPCDisableUpdate = this.OldRPC.DisableUpdate
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(this.RPCEndpoints) == 0 {
|
||||||
|
return errors.New("no valid 'rpc.endpoints'")
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(this.NodeId) == 0 {
|
||||||
|
return errors.New("'nodeId' required")
|
||||||
|
}
|
||||||
|
if len(this.Secret) == 0 {
|
||||||
|
return errors.New("'secret' required")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package configs
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
_ "github.com/iwind/TeaGo/bootstrap"
|
_ "github.com/iwind/TeaGo/bootstrap"
|
||||||
|
"gopkg.in/yaml.v3"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -11,10 +12,16 @@ func TestLoadAPIConfig(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
t.Log(config)
|
t.Log(config)
|
||||||
|
|
||||||
|
configData, err := yaml.Marshal(config)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
t.Log(string(configData))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAPIConfig_WriteFile(t *testing.T) {
|
func TestAPIConfig_WriteFile(t *testing.T) {
|
||||||
config := &APIConfig{}
|
var config = &APIConfig{}
|
||||||
err := config.WriteFile("/tmp/api_config.yaml")
|
err := config.WriteFile("/tmp/api_config.yaml")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
package teaconst
|
package teaconst
|
||||||
|
|
||||||
const (
|
const (
|
||||||
Version = "1.2.2"
|
Version = "1.3.0"
|
||||||
|
|
||||||
APINodeVersion = "1.2.2"
|
APINodeVersion = "1.3.0"
|
||||||
|
|
||||||
ProductName = "Edge Admin"
|
ProductName = "Edge Admin"
|
||||||
ProcessName = "edge-admin"
|
ProcessName = "edge-admin"
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ func TestAES128CFBMethod_Encrypt(t *testing.T) {
|
|||||||
dst = dst[:len(src)]
|
dst = dst[:len(src)]
|
||||||
t.Log("dst:", string(dst))
|
t.Log("dst:", string(dst))
|
||||||
|
|
||||||
src = make([]byte, len(src))
|
|
||||||
src, err = method.Decrypt(dst)
|
src, err = method.Decrypt(dst)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@@ -64,7 +63,6 @@ func TestAES128CFBMethod_Encrypt2(t *testing.T) {
|
|||||||
|
|
||||||
for _, dst := range sources {
|
for _, dst := range sources {
|
||||||
dst2 := append([]byte{}, dst...)
|
dst2 := append([]byte{}, dst...)
|
||||||
src2 := make([]byte, len(dst2))
|
|
||||||
src2, err := method.Decrypt(dst2)
|
src2, err := method.Decrypt(dst2)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
|||||||
@@ -5,20 +5,20 @@ import "sync"
|
|||||||
var eventsMap = map[string][]func(){} // event => []callbacks
|
var eventsMap = map[string][]func(){} // event => []callbacks
|
||||||
var locker = sync.Mutex{}
|
var locker = sync.Mutex{}
|
||||||
|
|
||||||
// 增加事件回调
|
// On 增加事件回调
|
||||||
func On(event string, callback func()) {
|
func On(event string, callback func()) {
|
||||||
locker.Lock()
|
locker.Lock()
|
||||||
defer locker.Unlock()
|
defer locker.Unlock()
|
||||||
|
|
||||||
callbacks, _ := eventsMap[event]
|
var callbacks = eventsMap[event]
|
||||||
callbacks = append(callbacks, callback)
|
callbacks = append(callbacks, callback)
|
||||||
eventsMap[event] = callbacks
|
eventsMap[event] = callbacks
|
||||||
}
|
}
|
||||||
|
|
||||||
// 通知事件
|
// Notify 通知事件
|
||||||
func Notify(event string) {
|
func Notify(event string) {
|
||||||
locker.Lock()
|
locker.Lock()
|
||||||
callbacks, _ := eventsMap[event]
|
var callbacks = eventsMap[event]
|
||||||
locker.Unlock()
|
locker.Unlock()
|
||||||
|
|
||||||
for _, callback := range callbacks {
|
for _, callback := range callbacks {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ package gen
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"fmt"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/server/settings/conds/condutils"
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/server/settings/conds/condutils"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||||
@@ -22,7 +22,7 @@ import (
|
|||||||
func Generate() error {
|
func Generate() error {
|
||||||
err := generateComponentsJSFile()
|
err := generateComponentsJSFile()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("generate 'components.src.js' failed: " + err.Error())
|
return fmt.Errorf("generate 'components.src.js' failed: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@@ -63,7 +63,7 @@ func generateComponentsJSFile() error {
|
|||||||
} else {
|
} else {
|
||||||
buffer.WriteString("window.REQUEST_COND_COMPONENTS = ")
|
buffer.WriteString("window.REQUEST_COND_COMPONENTS = ")
|
||||||
buffer.Write(typesJSON)
|
buffer.Write(typesJSON)
|
||||||
buffer.Write([]byte{'\n', '\n'})
|
buffer.Write([]byte{';', '\n', '\n'})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 条件操作符
|
// 条件操作符
|
||||||
@@ -73,7 +73,7 @@ func generateComponentsJSFile() error {
|
|||||||
} else {
|
} else {
|
||||||
buffer.WriteString("window.REQUEST_COND_OPERATORS = ")
|
buffer.WriteString("window.REQUEST_COND_OPERATORS = ")
|
||||||
buffer.Write(requestOperatorsJSON)
|
buffer.Write(requestOperatorsJSON)
|
||||||
buffer.Write([]byte{'\n', '\n'})
|
buffer.Write([]byte{';', '\n', '\n'})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 请求变量
|
// 请求变量
|
||||||
@@ -83,7 +83,7 @@ func generateComponentsJSFile() error {
|
|||||||
} else {
|
} else {
|
||||||
buffer.WriteString("window.REQUEST_VARIABLES = ")
|
buffer.WriteString("window.REQUEST_VARIABLES = ")
|
||||||
buffer.Write(requestVariablesJSON)
|
buffer.Write(requestVariablesJSON)
|
||||||
buffer.Write([]byte{'\n', '\n'})
|
buffer.Write([]byte{';', '\n', '\n'})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 指标
|
// 指标
|
||||||
@@ -93,7 +93,7 @@ func generateComponentsJSFile() error {
|
|||||||
} else {
|
} else {
|
||||||
buffer.WriteString("window.METRIC_HTTP_KEYS = ")
|
buffer.WriteString("window.METRIC_HTTP_KEYS = ")
|
||||||
buffer.Write(metricHTTPKeysJSON)
|
buffer.Write(metricHTTPKeysJSON)
|
||||||
buffer.Write([]byte{'\n', '\n'})
|
buffer.Write([]byte{';', '\n', '\n'})
|
||||||
}
|
}
|
||||||
|
|
||||||
// IP地址阈值项目
|
// IP地址阈值项目
|
||||||
@@ -103,7 +103,7 @@ func generateComponentsJSFile() error {
|
|||||||
} else {
|
} else {
|
||||||
buffer.WriteString("window.IP_ADDR_THRESHOLD_ITEMS = ")
|
buffer.WriteString("window.IP_ADDR_THRESHOLD_ITEMS = ")
|
||||||
buffer.Write(ipAddrThresholdItemsJSON)
|
buffer.Write(ipAddrThresholdItemsJSON)
|
||||||
buffer.Write([]byte{'\n', '\n'})
|
buffer.Write([]byte{';', '\n', '\n'})
|
||||||
}
|
}
|
||||||
|
|
||||||
// IP地址阈值动作
|
// IP地址阈值动作
|
||||||
@@ -113,7 +113,7 @@ func generateComponentsJSFile() error {
|
|||||||
} else {
|
} else {
|
||||||
buffer.WriteString("window.IP_ADDR_THRESHOLD_ACTIONS = ")
|
buffer.WriteString("window.IP_ADDR_THRESHOLD_ACTIONS = ")
|
||||||
buffer.Write(ipAddrThresholdActionsJSON)
|
buffer.Write(ipAddrThresholdActionsJSON)
|
||||||
buffer.Write([]byte{'\n', '\n'})
|
buffer.Write([]byte{';', '\n', '\n'})
|
||||||
}
|
}
|
||||||
|
|
||||||
// WAF操作符
|
// WAF操作符
|
||||||
@@ -123,7 +123,17 @@ func generateComponentsJSFile() error {
|
|||||||
} else {
|
} else {
|
||||||
buffer.WriteString("window.WAF_RULE_OPERATORS = ")
|
buffer.WriteString("window.WAF_RULE_OPERATORS = ")
|
||||||
buffer.Write(wafOperatorsJSON)
|
buffer.Write(wafOperatorsJSON)
|
||||||
buffer.Write([]byte{'\n', '\n'})
|
buffer.Write([]byte{';', '\n', '\n'})
|
||||||
|
}
|
||||||
|
|
||||||
|
// WAF验证码类型
|
||||||
|
captchaTypesJSON, err := json.Marshal(firewallconfigs.FindAllCaptchaTypes())
|
||||||
|
if err != nil {
|
||||||
|
logs.Println("ComponentsAction marshal captcha types failed: " + err.Error())
|
||||||
|
} else {
|
||||||
|
buffer.WriteString("window.WAF_CAPTCHA_TYPES = ")
|
||||||
|
buffer.Write(captchaTypesJSON)
|
||||||
|
buffer.Write([]byte{';', '\n', '\n'})
|
||||||
}
|
}
|
||||||
|
|
||||||
fp, err := os.OpenFile(filepath.Clean(Tea.PublicFile("/js/components.src.js")), os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0777)
|
fp, err := os.OpenFile(filepath.Clean(Tea.PublicFile("/js/components.src.js")), os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0777)
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package nodes
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/configs"
|
"github.com/TeaOSLab/EdgeAdmin/internal/configs"
|
||||||
teaconst "github.com/TeaOSLab/EdgeAdmin/internal/const"
|
teaconst "github.com/TeaOSLab/EdgeAdmin/internal/const"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/events"
|
"github.com/TeaOSLab/EdgeAdmin/internal/events"
|
||||||
@@ -65,7 +66,7 @@ func (this *AdminNode) Run() {
|
|||||||
this.addPortsToFirewall()
|
this.addPortsToFirewall()
|
||||||
|
|
||||||
// 监听信号
|
// 监听信号
|
||||||
sigQueue := make(chan os.Signal)
|
var sigQueue = make(chan os.Signal, 8)
|
||||||
signal.Notify(sigQueue, syscall.SIGTERM, syscall.SIGINT, syscall.SIGKILL, syscall.SIGQUIT)
|
signal.Notify(sigQueue, syscall.SIGTERM, syscall.SIGINT, syscall.SIGKILL, syscall.SIGQUIT)
|
||||||
go func() {
|
go func() {
|
||||||
for range sigQueue {
|
for range sigQueue {
|
||||||
@@ -106,8 +107,7 @@ func (this *AdminNode) Run() {
|
|||||||
// Daemon 实现守护进程
|
// Daemon 实现守护进程
|
||||||
func (this *AdminNode) Daemon() {
|
func (this *AdminNode) Daemon() {
|
||||||
var sock = gosock.NewTmpSock(teaconst.ProcessName)
|
var sock = gosock.NewTmpSock(teaconst.ProcessName)
|
||||||
isDebug := lists.ContainsString(os.Args, "debug")
|
var isDebug = lists.ContainsString(os.Args, "debug")
|
||||||
isDebug = true
|
|
||||||
for {
|
for {
|
||||||
conn, err := sock.Dial()
|
conn, err := sock.Dial()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -185,7 +185,7 @@ func (this *AdminNode) checkServer() error {
|
|||||||
if err == nil {
|
if err == nil {
|
||||||
err = os.WriteFile(configFile, data, 0666)
|
err = os.WriteFile(configFile, data, 0666)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("create config file failed: " + err.Error())
|
return fmt.Errorf("create config file failed: %w", err)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
templateYAML := `# environment code
|
templateYAML := `# environment code
|
||||||
@@ -205,11 +205,11 @@ https:
|
|||||||
`
|
`
|
||||||
err = os.WriteFile(configFile, []byte(templateYAML), 0666)
|
err = os.WriteFile(configFile, []byte(templateYAML), 0666)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("create config file failed: " + err.Error())
|
return fmt.Errorf("create config file failed: %w", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return errors.New("can not read config from 'configs/server.yaml': " + err.Error())
|
return fmt.Errorf("can not read config from 'configs/server.yaml': %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@@ -255,7 +255,7 @@ func (this *AdminNode) addPortsToFirewall() {
|
|||||||
|
|
||||||
// 启动API节点
|
// 启动API节点
|
||||||
func (this *AdminNode) startAPINode() {
|
func (this *AdminNode) startAPINode() {
|
||||||
configPath := Tea.Root + "/edge-api/configs/api.yaml"
|
var configPath = Tea.Root + "/edge-api/configs/api.yaml"
|
||||||
_, err := os.Stat(configPath)
|
_, err := os.Stat(configPath)
|
||||||
canStart := false
|
canStart := false
|
||||||
if err == nil {
|
if err == nil {
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/configs"
|
"github.com/TeaOSLab/EdgeAdmin/internal/configs"
|
||||||
teaconst "github.com/TeaOSLab/EdgeAdmin/internal/const"
|
teaconst "github.com/TeaOSLab/EdgeAdmin/internal/const"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/encrypt"
|
"github.com/TeaOSLab/EdgeAdmin/internal/encrypt"
|
||||||
@@ -279,34 +280,6 @@ func (this *RPCClient) MessageRPC() pb.MessageServiceClient {
|
|||||||
return pb.NewMessageServiceClient(this.pickConn())
|
return pb.NewMessageServiceClient(this.pickConn())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *RPCClient) MessageRecipientGroupRPC() pb.MessageRecipientGroupServiceClient {
|
|
||||||
return pb.NewMessageRecipientGroupServiceClient(this.pickConn())
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *RPCClient) MessageRecipientRPC() pb.MessageRecipientServiceClient {
|
|
||||||
return pb.NewMessageRecipientServiceClient(this.pickConn())
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *RPCClient) MessageMediaRPC() pb.MessageMediaServiceClient {
|
|
||||||
return pb.NewMessageMediaServiceClient(this.pickConn())
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *RPCClient) MessageMediaInstanceRPC() pb.MessageMediaInstanceServiceClient {
|
|
||||||
return pb.NewMessageMediaInstanceServiceClient(this.pickConn())
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *RPCClient) MessageTaskRPC() pb.MessageTaskServiceClient {
|
|
||||||
return pb.NewMessageTaskServiceClient(this.pickConn())
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *RPCClient) MessageTaskLogRPC() pb.MessageTaskLogServiceClient {
|
|
||||||
return pb.NewMessageTaskLogServiceClient(this.pickConn())
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *RPCClient) MessageReceiverRPC() pb.MessageReceiverServiceClient {
|
|
||||||
return pb.NewMessageReceiverServiceClient(this.pickConn())
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *RPCClient) IPLibraryRPC() pb.IPLibraryServiceClient {
|
func (this *RPCClient) IPLibraryRPC() pb.IPLibraryServiceClient {
|
||||||
return pb.NewIPLibraryServiceClient(this.pickConn())
|
return pb.NewIPLibraryServiceClient(this.pickConn())
|
||||||
}
|
}
|
||||||
@@ -415,14 +388,6 @@ func (this *RPCClient) NodeTaskRPC() pb.NodeTaskServiceClient {
|
|||||||
return pb.NewNodeTaskServiceClient(this.pickConn())
|
return pb.NewNodeTaskServiceClient(this.pickConn())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *RPCClient) AuthorityKeyRPC() pb.AuthorityKeyServiceClient {
|
|
||||||
return pb.NewAuthorityKeyServiceClient(this.pickConn())
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *RPCClient) AuthorityNodeRPC() pb.AuthorityNodeServiceClient {
|
|
||||||
return pb.NewAuthorityNodeServiceClient(this.pickConn())
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *RPCClient) LatestItemRPC() pb.LatestItemServiceClient {
|
func (this *RPCClient) LatestItemRPC() pb.LatestItemServiceClient {
|
||||||
return pb.NewLatestItemServiceClient(this.pickConn())
|
return pb.NewLatestItemServiceClient(this.pickConn())
|
||||||
}
|
}
|
||||||
@@ -522,10 +487,10 @@ func (this *RPCClient) init() error {
|
|||||||
|
|
||||||
// 重新连接
|
// 重新连接
|
||||||
var conns = []*grpc.ClientConn{}
|
var conns = []*grpc.ClientConn{}
|
||||||
for _, endpoint := range this.apiConfig.RPC.Endpoints {
|
for _, endpoint := range this.apiConfig.RPCEndpoints {
|
||||||
u, err := url.Parse(endpoint)
|
u, err := url.Parse(endpoint)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("parse endpoint failed: " + err.Error())
|
return fmt.Errorf("parse endpoint failed: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var apiHost = u.Host
|
var apiHost = u.Host
|
||||||
|
|||||||
@@ -2,8 +2,6 @@ package setup
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/configs"
|
"github.com/TeaOSLab/EdgeAdmin/internal/configs"
|
||||||
teaconst "github.com/TeaOSLab/EdgeAdmin/internal/const"
|
|
||||||
"os"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var isConfigured bool
|
var isConfigured bool
|
||||||
@@ -21,13 +19,5 @@ func IsConfigured() bool {
|
|||||||
|
|
||||||
// IsNewInstalled IsNew 检查是否新安装
|
// IsNewInstalled IsNew 检查是否新安装
|
||||||
func IsNewInstalled() bool {
|
func IsNewInstalled() bool {
|
||||||
homeDir, err := os.UserHomeDir()
|
return configs.IsNewInstalled()
|
||||||
if err != nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
_, err = os.Stat(homeDir + "/." + teaconst.ProcessName + "/api.yaml")
|
|
||||||
if err != nil {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ package tasks
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
teaconst "github.com/TeaOSLab/EdgeAdmin/internal/const"
|
teaconst "github.com/TeaOSLab/EdgeAdmin/internal/const"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/events"
|
"github.com/TeaOSLab/EdgeAdmin/internal/events"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/goman"
|
"github.com/TeaOSLab/EdgeAdmin/internal/goman"
|
||||||
@@ -59,11 +60,11 @@ func (this *CheckUpdatesTask) Loop() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
var valueJSON = valueResp.ValueJSON
|
var valueJSON = valueResp.ValueJSON
|
||||||
var config = &systemconfigs.CheckUpdatesConfig{AutoCheck: false}
|
var config = systemconfigs.NewCheckUpdatesConfig()
|
||||||
if len(valueJSON) > 0 {
|
if len(valueJSON) > 0 {
|
||||||
err = json.Unmarshal(valueJSON, config)
|
err = json.Unmarshal(valueJSON, config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("decode config failed: " + err.Error())
|
return fmt.Errorf("decode config failed: %w", err)
|
||||||
}
|
}
|
||||||
if !config.AutoCheck {
|
if !config.AutoCheck {
|
||||||
return nil
|
return nil
|
||||||
@@ -90,7 +91,7 @@ func (this *CheckUpdatesTask) Loop() error {
|
|||||||
apiURL = strings.ReplaceAll(apiURL, "${version}", teaconst.Version)
|
apiURL = strings.ReplaceAll(apiURL, "${version}", teaconst.Version)
|
||||||
resp, err := http.Get(apiURL)
|
resp, err := http.Get(apiURL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("read api failed: " + err.Error())
|
return fmt.Errorf("read api failed: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
@@ -98,13 +99,13 @@ func (this *CheckUpdatesTask) Loop() error {
|
|||||||
}()
|
}()
|
||||||
data, err := io.ReadAll(resp.Body)
|
data, err := io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("read api failed: " + err.Error())
|
return fmt.Errorf("read api failed: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var apiResponse = &Response{}
|
var apiResponse = &Response{}
|
||||||
err = json.Unmarshal(data, apiResponse)
|
err = json.Unmarshal(data, apiResponse)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("decode version data failed: " + err.Error())
|
return fmt.Errorf("decode version data failed: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if apiResponse.Code != 200 {
|
if apiResponse.Code != 200 {
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ func (this *SyncAPINodesTask) Loop() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 是否禁止自动升级
|
// 是否禁止自动升级
|
||||||
if config.RPC.DisableUpdate {
|
if config.RPCDisableUpdate {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,7 +88,7 @@ func (this *SyncAPINodesTask) Loop() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 和现有的对比
|
// 和现有的对比
|
||||||
if this.isSame(newEndpoints, config.RPC.Endpoints) {
|
if this.isSame(newEndpoints, config.RPCEndpoints) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,14 +99,14 @@ func (this *SyncAPINodesTask) Loop() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 修改RPC对象配置
|
// 修改RPC对象配置
|
||||||
config.RPC.Endpoints = newEndpoints
|
config.RPCEndpoints = newEndpoints
|
||||||
err = rpcClient.UpdateConfig(config)
|
err = rpcClient.UpdateConfig(config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// 保存到文件
|
// 保存到文件
|
||||||
err = config.WriteFile(Tea.ConfigFile("api.yaml"))
|
err = config.WriteFile(Tea.ConfigFile(configs.ConfigFileName))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,8 +10,10 @@ var DefaultCache = NewCache()
|
|||||||
// TTL缓存
|
// TTL缓存
|
||||||
// 最大的缓存时间为30 * 86400
|
// 最大的缓存时间为30 * 86400
|
||||||
// Piece数据结构:
|
// Piece数据结构:
|
||||||
// Piece1 | Piece2 | Piece3 | ...
|
//
|
||||||
// [ Item1, Item2, ... | ...
|
// Piece1 | Piece2 | Piece3 | ...
|
||||||
|
// [ Item1, Item2, ... | ...
|
||||||
|
//
|
||||||
// KeyMap列表数据结构
|
// KeyMap列表数据结构
|
||||||
// { timestamp1 => [key1, key2, ...] }, ...
|
// { timestamp1 => [key1, key2, ...] }, ...
|
||||||
type Cache struct {
|
type Cache struct {
|
||||||
@@ -109,19 +111,11 @@ func (this *Cache) Read(key string) (item *Item) {
|
|||||||
return this.pieces[uint64Key%this.countPieces].Read(uint64Key)
|
return this.pieces[uint64Key%this.countPieces].Read(uint64Key)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *Cache) readIntKey(key uint64) (value *Item) {
|
|
||||||
return this.pieces[key%this.countPieces].Read(key)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *Cache) Delete(key string) {
|
func (this *Cache) Delete(key string) {
|
||||||
uint64Key := HashKey([]byte(key))
|
uint64Key := HashKey([]byte(key))
|
||||||
this.pieces[uint64Key%this.countPieces].Delete(uint64Key)
|
this.pieces[uint64Key%this.countPieces].Delete(uint64Key)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *Cache) deleteIntKey(key uint64) {
|
|
||||||
this.pieces[key%this.countPieces].Delete(key)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *Cache) Count() (count int) {
|
func (this *Cache) Count() (count int) {
|
||||||
for _, piece := range this.pieces {
|
for _, piece := range this.pieces {
|
||||||
count += piece.Count()
|
count += piece.Count()
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ func (this *Upgrader) Upgrade() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
var newAPIConfig = apiConfig.Clone()
|
var newAPIConfig = apiConfig.Clone()
|
||||||
newAPIConfig.RPC.Endpoints = apiNode.AccessAddrs
|
newAPIConfig.RPCEndpoints = apiNode.AccessAddrs
|
||||||
|
|
||||||
rpcClient, err := rpc.NewRPCClient(newAPIConfig, false)
|
rpcClient, err := rpc.NewRPCClient(newAPIConfig, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -79,7 +79,7 @@ func (this *Upgrader) Upgrade() error {
|
|||||||
// 升级API节点
|
// 升级API节点
|
||||||
err = this.upgradeAPINode(sharedClient.Context(0), rpcClient)
|
err = this.upgradeAPINode(sharedClient.Context(0), rpcClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("upgrade api node failed: " + err.Error())
|
return fmt.Errorf("upgrade api node failed: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@@ -109,7 +109,7 @@ func (this *Upgrader) upgradeAPINode(ctx context.Context, rpcClient *rpc.RPCClie
|
|||||||
|
|
||||||
localVersion, err := lookupLocalVersion()
|
localVersion, err := lookupLocalVersion()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("lookup version failed: " + err.Error())
|
return fmt.Errorf("lookup version failed: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 检查要升级的文件
|
// 检查要升级的文件
|
||||||
@@ -251,7 +251,7 @@ func (this *Upgrader) upgradeNodes(ctx context.Context, rpcClient *rpc.RPCClient
|
|||||||
if !ok || stringutil.VersionCompare(remoteDeployFile.Version, deployFile.Version) < 0 {
|
if !ok || stringutil.VersionCompare(remoteDeployFile.Version, deployFile.Version) < 0 {
|
||||||
err = this.uploadNodeDeployFile(ctx, rpcClient, deployFile.Path)
|
err = this.uploadNodeDeployFile(ctx, rpcClient, deployFile.Path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("upload deploy file '" + filepath.Base(deployFile.Path) + "' failed: " + err.Error())
|
return fmt.Errorf("upload deploy file '%s' failed: %w", filepath.Base(deployFile.Path), err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -284,7 +284,7 @@ func (this *Upgrader) upgradeNSNodes(ctx context.Context, rpcClient *rpc.RPCClie
|
|||||||
if !ok || stringutil.VersionCompare(remoteDeployFile.Version, deployFile.Version) < 0 {
|
if !ok || stringutil.VersionCompare(remoteDeployFile.Version, deployFile.Version) < 0 {
|
||||||
err = this.uploadNodeDeployFile(ctx, rpcClient, deployFile.Path)
|
err = this.uploadNodeDeployFile(ctx, rpcClient, deployFile.Path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("upload deploy file '" + filepath.Base(deployFile.Path) + "' failed: " + err.Error())
|
return fmt.Errorf("upload deploy file '%s' failed: %w", filepath.Base(deployFile.Path), err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ package utils
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"reflect"
|
"reflect"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -24,7 +25,36 @@ func JSONClone(v interface{}) (interface{}, error) {
|
|||||||
return nv, nil
|
return nv, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// 判断JSON数据是否为null
|
// JSONIsNull 判断JSON数据是否为null
|
||||||
func JSONIsNull(jsonData []byte) bool {
|
func JSONIsNull(jsonData []byte) bool {
|
||||||
return len(jsonData) == 0 || bytes.Equal(jsonData, []byte("null"))
|
return len(jsonData) == 0 || bytes.Equal(jsonData, []byte("null"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// JSONDecodeConfig 解码并重新编码
|
||||||
|
// 是为了去除原有JSON中不需要的数据
|
||||||
|
func JSONDecodeConfig(data []byte, ptr any) (encodeJSON []byte, err error) {
|
||||||
|
err = json.Unmarshal(data, ptr)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
encodeJSON, err = json.Marshal(ptr)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// validate config
|
||||||
|
if ptr != nil {
|
||||||
|
config, ok := ptr.(interface {
|
||||||
|
Init() error
|
||||||
|
})
|
||||||
|
if ok {
|
||||||
|
initErr := config.Init()
|
||||||
|
if initErr != nil {
|
||||||
|
err = errors.New("validate config failed: " + initErr.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ func (this *ServiceManager) setup() {
|
|||||||
this.onceLocker.Do(func() {
|
this.onceLocker.Do(func() {
|
||||||
logFile := files.NewFile(Tea.Root + "/logs/service.log")
|
logFile := files.NewFile(Tea.Root + "/logs/service.log")
|
||||||
if logFile.Exists() {
|
if logFile.Exists() {
|
||||||
logFile.Delete()
|
_ = logFile.Delete()
|
||||||
}
|
}
|
||||||
|
|
||||||
//logger
|
//logger
|
||||||
|
|||||||
@@ -59,10 +59,10 @@ func (this *ServiceManager) Uninstall() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// disable service
|
// disable service
|
||||||
exec.Command(systemd, "disable", teaconst.SystemdServiceName+".service").Start()
|
_ = exec.Command(systemd, "disable", teaconst.SystemdServiceName+".service").Start()
|
||||||
|
|
||||||
// reload
|
// reload
|
||||||
exec.Command(systemd, "daemon-reload")
|
_ = exec.Command(systemd, "daemon-reload").Start()
|
||||||
|
|
||||||
return files.NewFile(systemdServiceFile).Delete()
|
return files.NewFile(systemdServiceFile).Delete()
|
||||||
}
|
}
|
||||||
@@ -143,10 +143,10 @@ WantedBy=multi-user.target`
|
|||||||
}
|
}
|
||||||
|
|
||||||
// stop current systemd service if running
|
// stop current systemd service if running
|
||||||
exec.Command(systemd, "stop", shortName+".service")
|
_ = exec.Command(systemd, "stop", shortName+".service").Start()
|
||||||
|
|
||||||
// reload
|
// reload
|
||||||
exec.Command(systemd, "daemon-reload")
|
_ = exec.Command(systemd, "daemon-reload").Start()
|
||||||
|
|
||||||
// enable
|
// enable
|
||||||
cmd := exec.Command(systemd, "enable", shortName+".service")
|
cmd := exec.Command(systemd, "enable", shortName+".service")
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ package utils
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
teaconst "github.com/TeaOSLab/EdgeAdmin/internal/const"
|
||||||
"github.com/iwind/TeaGo/Tea"
|
"github.com/iwind/TeaGo/Tea"
|
||||||
"golang.org/x/sys/windows"
|
"golang.org/x/sys/windows"
|
||||||
"golang.org/x/sys/windows/svc"
|
"golang.org/x/sys/windows/svc"
|
||||||
@@ -15,7 +16,7 @@ import (
|
|||||||
func (this *ServiceManager) Install(exePath string, args []string) error {
|
func (this *ServiceManager) Install(exePath string, args []string) error {
|
||||||
m, err := mgr.Connect()
|
m, err := mgr.Connect()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("connecting: %s please 'Run as administrator' again", err.Error())
|
return fmt.Errorf("connecting: %w please 'Run as administrator' again", err)
|
||||||
}
|
}
|
||||||
defer m.Disconnect()
|
defer m.Disconnect()
|
||||||
s, err := m.OpenService(this.Name)
|
s, err := m.OpenService(this.Name)
|
||||||
@@ -30,7 +31,7 @@ func (this *ServiceManager) Install(exePath string, args []string) error {
|
|||||||
StartType: windows.SERVICE_AUTO_START,
|
StartType: windows.SERVICE_AUTO_START,
|
||||||
}, args...)
|
}, args...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("creating: %s", err.Error())
|
return fmt.Errorf("creating: %w", err)
|
||||||
}
|
}
|
||||||
defer s.Close()
|
defer s.Close()
|
||||||
|
|
||||||
@@ -46,12 +47,12 @@ func (this *ServiceManager) Start() error {
|
|||||||
defer m.Disconnect()
|
defer m.Disconnect()
|
||||||
s, err := m.OpenService(this.Name)
|
s, err := m.OpenService(this.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("could not access service: %v", err)
|
return fmt.Errorf("could not access service: %w", err)
|
||||||
}
|
}
|
||||||
defer s.Close()
|
defer s.Close()
|
||||||
err = s.Start("service")
|
err = s.Start("service")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("could not start service: %v", err)
|
return fmt.Errorf("could not start service: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@@ -61,12 +62,12 @@ func (this *ServiceManager) Start() error {
|
|||||||
func (this *ServiceManager) Uninstall() error {
|
func (this *ServiceManager) Uninstall() error {
|
||||||
m, err := mgr.Connect()
|
m, err := mgr.Connect()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("connecting: %s please 'Run as administrator' again", err.Error())
|
return fmt.Errorf("connecting: %w please 'Run as administrator' again", err)
|
||||||
}
|
}
|
||||||
defer m.Disconnect()
|
defer m.Disconnect()
|
||||||
s, err := m.OpenService(this.Name)
|
s, err := m.OpenService(this.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("open service: %s", err.Error())
|
return fmt.Errorf("open service: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// shutdown service
|
// shutdown service
|
||||||
@@ -78,7 +79,7 @@ func (this *ServiceManager) Uninstall() error {
|
|||||||
defer s.Close()
|
defer s.Close()
|
||||||
err = s.Delete()
|
err = s.Delete()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("deleting: %s", err.Error())
|
return fmt.Errorf("deleting: %w", err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
95
internal/utils/unzip.go
Normal file
95
internal/utils/unzip.go
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"archive/zip"
|
||||||
|
"errors"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Unzip struct {
|
||||||
|
zipFile string
|
||||||
|
targetDir string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewUnzip(zipFile string, targetDir string) *Unzip {
|
||||||
|
return &Unzip{
|
||||||
|
zipFile: zipFile,
|
||||||
|
targetDir: targetDir,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *Unzip) Run() error {
|
||||||
|
if len(this.zipFile) == 0 {
|
||||||
|
return errors.New("zip file should not be empty")
|
||||||
|
}
|
||||||
|
if len(this.targetDir) == 0 {
|
||||||
|
return errors.New("target dir should not be empty")
|
||||||
|
}
|
||||||
|
|
||||||
|
reader, err := zip.OpenReader(this.zipFile)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
_ = reader.Close()
|
||||||
|
}()
|
||||||
|
|
||||||
|
for _, file := range reader.File {
|
||||||
|
var info = file.FileInfo()
|
||||||
|
var target = this.targetDir + "/" + file.Name
|
||||||
|
|
||||||
|
// 目录
|
||||||
|
if info.IsDir() {
|
||||||
|
stat, err := os.Stat(target)
|
||||||
|
if err != nil {
|
||||||
|
if !os.IsNotExist(err) {
|
||||||
|
return err
|
||||||
|
} else {
|
||||||
|
err = os.MkdirAll(target, info.Mode())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if !stat.IsDir() {
|
||||||
|
err = os.MkdirAll(target, info.Mode())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// 文件
|
||||||
|
err = func(file *zip.File, target string) error {
|
||||||
|
fileReader, err := file.Open()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
_ = fileReader.Close()
|
||||||
|
}()
|
||||||
|
|
||||||
|
// remove old
|
||||||
|
_ = os.Remove(target)
|
||||||
|
|
||||||
|
// create new
|
||||||
|
fileWriter, err := os.OpenFile(target, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, file.FileInfo().Mode())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
_ = fileWriter.Close()
|
||||||
|
}()
|
||||||
|
|
||||||
|
_, err = io.Copy(fileWriter, fileReader)
|
||||||
|
return err
|
||||||
|
}(file, target)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
teaconst "github.com/TeaOSLab/EdgeAdmin/internal/const"
|
teaconst "github.com/TeaOSLab/EdgeAdmin/internal/const"
|
||||||
"github.com/iwind/TeaGo/Tea"
|
"github.com/iwind/TeaGo/Tea"
|
||||||
"github.com/iwind/TeaGo/maps"
|
"github.com/iwind/TeaGo/maps"
|
||||||
@@ -87,10 +88,6 @@ func (this *UpgradeManager) Start() error {
|
|||||||
|
|
||||||
// 检查unzip
|
// 检查unzip
|
||||||
unzipExe, _ := exec.LookPath("unzip")
|
unzipExe, _ := exec.LookPath("unzip")
|
||||||
if len(unzipExe) == 0 {
|
|
||||||
// TODO install unzip automatically or pack with a static 'unzip' file
|
|
||||||
return errors.New("can not find 'unzip' command")
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检查cp
|
// 检查cp
|
||||||
cpExe, _ := exec.LookPath("cp")
|
cpExe, _ := exec.LookPath("cp")
|
||||||
@@ -111,13 +108,13 @@ func (this *UpgradeManager) Start() error {
|
|||||||
url = strings.ReplaceAll(url, "${version}", teaconst.Version)
|
url = strings.ReplaceAll(url, "${version}", teaconst.Version)
|
||||||
req, err := http.NewRequest(http.MethodGet, url, nil)
|
req, err := http.NewRequest(http.MethodGet, url, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("create url request failed: " + err.Error())
|
return fmt.Errorf("create url request failed: %w", err)
|
||||||
}
|
}
|
||||||
req.Header.Set("User-Agent", "Edge-Admin/"+teaconst.Version)
|
req.Header.Set("User-Agent", "Edge-Admin/"+teaconst.Version)
|
||||||
|
|
||||||
resp, err := this.client.Do(req)
|
resp, err := this.client.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("read latest version failed: " + err.Error())
|
return fmt.Errorf("read latest version failed: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
@@ -130,13 +127,13 @@ func (this *UpgradeManager) Start() error {
|
|||||||
|
|
||||||
data, err := io.ReadAll(resp.Body)
|
data, err := io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("read latest version failed: " + err.Error())
|
return fmt.Errorf("read latest version failed: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var m = maps.Map{}
|
var m = maps.Map{}
|
||||||
err = json.Unmarshal(data, &m)
|
err = json.Unmarshal(data, &m)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("invalid response data: " + err.Error() + ", origin data: " + string(data))
|
return fmt.Errorf("invalid response data: %w, origin data: %s", err, string(data))
|
||||||
}
|
}
|
||||||
|
|
||||||
var code = m.GetInt("code")
|
var code = m.GetInt("code")
|
||||||
@@ -172,13 +169,13 @@ func (this *UpgradeManager) Start() error {
|
|||||||
{
|
{
|
||||||
req, err := http.NewRequest(http.MethodGet, downloadURL, nil)
|
req, err := http.NewRequest(http.MethodGet, downloadURL, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("create download request failed: " + err.Error())
|
return fmt.Errorf("create download request failed: %w", err)
|
||||||
}
|
}
|
||||||
req.Header.Set("User-Agent", "Edge-Admin/"+teaconst.Version)
|
req.Header.Set("User-Agent", "Edge-Admin/"+teaconst.Version)
|
||||||
|
|
||||||
resp, err := this.client.Do(req)
|
resp, err := this.client.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("download failed: " + downloadURL + ": " + err.Error())
|
return fmt.Errorf("download failed: '%s': %w", downloadURL, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
@@ -201,7 +198,7 @@ func (this *UpgradeManager) Start() error {
|
|||||||
|
|
||||||
fp, err := os.Create(destFile)
|
fp, err := os.Create(destFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("create file failed: " + err.Error())
|
return fmt.Errorf("create file failed: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
@@ -217,7 +214,7 @@ func (this *UpgradeManager) Start() error {
|
|||||||
if this.isCancelled {
|
if this.isCancelled {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return errors.New("download failed: " + err.Error())
|
return fmt.Errorf("download failed: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
_ = fp.Close()
|
_ = fp.Close()
|
||||||
@@ -228,26 +225,38 @@ func (this *UpgradeManager) Start() error {
|
|||||||
if err == nil && stat.IsDir() {
|
if err == nil && stat.IsDir() {
|
||||||
err = os.RemoveAll(unzipDir)
|
err = os.RemoveAll(unzipDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("remove old dir '" + unzipDir + "' failed: " + err.Error())
|
return fmt.Errorf("remove old dir '%s' failed: %w", unzipDir, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var unzipCmd = exec.Command(unzipExe, "-q", "-o", destFile, "-d", unzipDir)
|
|
||||||
var unzipStderr = &bytes.Buffer{}
|
if len(unzipExe) > 0 {
|
||||||
unzipCmd.Stderr = unzipStderr
|
var unzipCmd = exec.Command(unzipExe, "-q", "-o", destFile, "-d", unzipDir)
|
||||||
err = unzipCmd.Run()
|
var unzipStderr = &bytes.Buffer{}
|
||||||
if err != nil {
|
unzipCmd.Stderr = unzipStderr
|
||||||
return errors.New("unzip installation file failed: " + err.Error() + ": " + unzipStderr.String())
|
err = unzipCmd.Run()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unzip installation file failed: %w: %s", err, unzipStderr.String())
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
var unzipCmd = &Unzip{
|
||||||
|
zipFile: destFile,
|
||||||
|
targetDir: unzipDir,
|
||||||
|
}
|
||||||
|
err = unzipCmd.Run()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unzip installation file failed: %w", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
installationFiles, err := filepath.Glob(unzipDir + "/edge-" + this.component + "/*")
|
installationFiles, err := filepath.Glob(unzipDir + "/edge-" + this.component + "/*")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("lookup installation files failed: " + err.Error())
|
return fmt.Errorf("lookup installation files failed: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// cp to target dir
|
// cp to target dir
|
||||||
currentExe, err := os.Executable()
|
currentExe, err := os.Executable()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("reveal current executable file path failed: " + err.Error())
|
return fmt.Errorf("reveal current executable file path failed: %w", err)
|
||||||
}
|
}
|
||||||
var targetDir = filepath.Dir(filepath.Dir(currentExe))
|
var targetDir = filepath.Dir(filepath.Dir(currentExe))
|
||||||
if !Tea.IsTesting() {
|
if !Tea.IsTesting() {
|
||||||
|
|||||||
@@ -107,13 +107,13 @@ func MatchPath(action *actions.ActionObject, path string) bool {
|
|||||||
|
|
||||||
// FindParentAction 查找父级Action
|
// FindParentAction 查找父级Action
|
||||||
func FindParentAction(actionPtr actions.ActionWrapper) *ParentAction {
|
func FindParentAction(actionPtr actions.ActionWrapper) *ParentAction {
|
||||||
parentActionValue := reflect.ValueOf(actionPtr).Elem().FieldByName("ParentAction")
|
action, ok := actionPtr.(interface {
|
||||||
if parentActionValue.IsValid() {
|
Parent() *ParentAction
|
||||||
parentAction, isOk := parentActionValue.Interface().(ParentAction)
|
})
|
||||||
if isOk {
|
if ok {
|
||||||
return &parentAction
|
return action.Parent()
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -140,7 +140,7 @@ func findStack(err string) string {
|
|||||||
filename = filename[strings.Index(filename, "src"):]
|
filename = filename[strings.Index(filename, "src"):]
|
||||||
}
|
}
|
||||||
|
|
||||||
err += "\n\t\t" + string(filename) + ":" + fmt.Sprintf("%d", lineNo)
|
err += "\n\t\t" + filename + ":" + fmt.Sprintf("%d", lineNo)
|
||||||
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -155,11 +155,11 @@ func parseAPIErr(action actions.ActionWrapper, err error) (apiNodeIsStarting boo
|
|||||||
var apiEndpoints = []string{}
|
var apiEndpoints = []string{}
|
||||||
apiConfig, apiConfigErr := configs.LoadAPIConfig()
|
apiConfig, apiConfigErr := configs.LoadAPIConfig()
|
||||||
if apiConfigErr == nil && apiConfig != nil {
|
if apiConfigErr == nil && apiConfig != nil {
|
||||||
apiEndpoints = append(apiEndpoints, apiConfig.RPC.Endpoints...)
|
apiEndpoints = append(apiEndpoints, apiConfig.RPCEndpoints...)
|
||||||
}
|
}
|
||||||
|
|
||||||
var isRPCConnError bool
|
var isRPCConnError bool
|
||||||
err, isRPCConnError = rpcerrors.HumanError(err, apiEndpoints, Tea.ConfigFile("api.yaml"))
|
_, isRPCConnError = rpcerrors.HumanError(err, apiEndpoints, Tea.ConfigFile(configs.ConfigFileName))
|
||||||
if isRPCConnError {
|
if isRPCConnError {
|
||||||
// API节点是否正在启动
|
// API节点是否正在启动
|
||||||
var sock = gosock.NewTmpSock("edge-api")
|
var sock = gosock.NewTmpSock("edge-api")
|
||||||
|
|||||||
@@ -67,5 +67,5 @@ func (this *OtpQrcodeAction) RunGet(params struct {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
this.AddHeader("Content-Type", "image/png")
|
this.AddHeader("Content-Type", "image/png")
|
||||||
this.Write(data)
|
_, _ = this.Write(data)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,82 +0,0 @@
|
|||||||
package recipients
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/utils"
|
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
|
||||||
"github.com/iwind/TeaGo/actions"
|
|
||||||
"regexp"
|
|
||||||
)
|
|
||||||
|
|
||||||
type CreatePopupAction struct {
|
|
||||||
actionutils.ParentAction
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *CreatePopupAction) Init() {
|
|
||||||
this.Nav("", "", "")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *CreatePopupAction) RunGet(params struct{}) {
|
|
||||||
this.Show()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *CreatePopupAction) RunPost(params struct {
|
|
||||||
AdminId int64
|
|
||||||
InstanceId int64
|
|
||||||
User string
|
|
||||||
|
|
||||||
TelegramToken string
|
|
||||||
|
|
||||||
GroupIds string
|
|
||||||
Description string
|
|
||||||
|
|
||||||
TimeFromHour string
|
|
||||||
TimeFromMinute string
|
|
||||||
TimeFromSecond string
|
|
||||||
|
|
||||||
TimeToHour string
|
|
||||||
TimeToMinute string
|
|
||||||
TimeToSecond string
|
|
||||||
|
|
||||||
Must *actions.Must
|
|
||||||
CSRF *actionutils.CSRF
|
|
||||||
}) {
|
|
||||||
params.Must.
|
|
||||||
Field("adminId", params.AdminId).
|
|
||||||
Gt(0, "请选择系统用户").
|
|
||||||
Field("instanceId", params.InstanceId).
|
|
||||||
Gt(0, "请选择媒介")
|
|
||||||
|
|
||||||
groupIds := utils.SplitNumbers(params.GroupIds)
|
|
||||||
|
|
||||||
var digitReg = regexp.MustCompile(`^\d+$`)
|
|
||||||
|
|
||||||
var timeFrom = ""
|
|
||||||
if digitReg.MatchString(params.TimeFromHour) && digitReg.MatchString(params.TimeFromMinute) && digitReg.MatchString(params.TimeFromSecond) {
|
|
||||||
timeFrom = params.TimeFromHour + ":" + params.TimeFromMinute + ":" + params.TimeFromSecond
|
|
||||||
}
|
|
||||||
|
|
||||||
var timeTo = ""
|
|
||||||
if digitReg.MatchString(params.TimeToHour) && digitReg.MatchString(params.TimeToMinute) && digitReg.MatchString(params.TimeToSecond) {
|
|
||||||
timeTo = params.TimeToHour + ":" + params.TimeToMinute + ":" + params.TimeToSecond
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := this.RPC().MessageRecipientRPC().CreateMessageRecipient(this.AdminContext(), &pb.CreateMessageRecipientRequest{
|
|
||||||
AdminId: params.AdminId,
|
|
||||||
MessageMediaInstanceId: params.InstanceId,
|
|
||||||
User: params.User,
|
|
||||||
MessageRecipientGroupIds: groupIds,
|
|
||||||
Description: params.Description,
|
|
||||||
TimeFrom: timeFrom,
|
|
||||||
TimeTo: timeTo,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
this.ErrorPage(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
defer this.CreateLogInfo(codes.MessageRecipient_LogCreateMessageRecipient, resp.MessageRecipientId)
|
|
||||||
|
|
||||||
this.Success()
|
|
||||||
}
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
package recipients
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
|
||||||
)
|
|
||||||
|
|
||||||
type DeleteAction struct {
|
|
||||||
actionutils.ParentAction
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *DeleteAction) RunPost(params struct {
|
|
||||||
RecipientId int64
|
|
||||||
}) {
|
|
||||||
defer this.CreateLogInfo(codes.MessageRecipient_LogDeleteMessageRecipient, params.RecipientId)
|
|
||||||
|
|
||||||
_, err := this.RPC().MessageRecipientRPC().DeleteMessageRecipient(this.AdminContext(), &pb.DeleteMessageRecipientRequest{MessageRecipientId: params.RecipientId})
|
|
||||||
if err != nil {
|
|
||||||
this.ErrorPage(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
this.Success()
|
|
||||||
}
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
package groups
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
|
||||||
"github.com/iwind/TeaGo/actions"
|
|
||||||
)
|
|
||||||
|
|
||||||
type CreatePopupAction struct {
|
|
||||||
actionutils.ParentAction
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *CreatePopupAction) Init() {
|
|
||||||
this.Nav("", "", "")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *CreatePopupAction) RunGet(params struct{}) {
|
|
||||||
this.Show()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *CreatePopupAction) RunPost(params struct {
|
|
||||||
Name string
|
|
||||||
|
|
||||||
Must *actions.Must
|
|
||||||
CSRF *actionutils.CSRF
|
|
||||||
}) {
|
|
||||||
params.Must.
|
|
||||||
Field("name", params.Name).
|
|
||||||
Require("请输入分组名称")
|
|
||||||
|
|
||||||
_, err := this.RPC().MessageRecipientGroupRPC().CreateMessageRecipientGroup(this.AdminContext(), &pb.CreateMessageRecipientGroupRequest{Name: params.Name})
|
|
||||||
if err != nil {
|
|
||||||
this.ErrorPage(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
this.Success()
|
|
||||||
}
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
package groups
|
|
||||||
|
|
||||||
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 {
|
|
||||||
GroupId int64
|
|
||||||
}) {
|
|
||||||
_, err := this.RPC().MessageRecipientGroupRPC().DeleteMessageRecipientGroup(this.AdminContext(), &pb.DeleteMessageRecipientGroupRequest{MessageRecipientGroupId: params.GroupId})
|
|
||||||
if err != nil {
|
|
||||||
this.ErrorPage(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
this.Success()
|
|
||||||
}
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
package groups
|
|
||||||
|
|
||||||
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("", "", "group")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *IndexAction) RunGet(params struct{}) {
|
|
||||||
groupsResp, err := this.RPC().MessageRecipientGroupRPC().FindAllEnabledMessageRecipientGroups(this.AdminContext(), &pb.FindAllEnabledMessageRecipientGroupsRequest{})
|
|
||||||
if err != nil {
|
|
||||||
this.ErrorPage(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
groupMaps := []maps.Map{}
|
|
||||||
for _, group := range groupsResp.MessageRecipientGroups {
|
|
||||||
groupMaps = append(groupMaps, maps.Map{
|
|
||||||
"id": group.Id,
|
|
||||||
"name": group.Name,
|
|
||||||
"isOn": group.IsOn,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
this.Data["groups"] = groupMaps
|
|
||||||
|
|
||||||
this.Show()
|
|
||||||
}
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
package groups
|
|
||||||
|
|
||||||
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.AdminModuleCodeAdmin)).
|
|
||||||
Data("teaMenu", "admins").
|
|
||||||
Data("teaSubMenu", "recipients").
|
|
||||||
Prefix("/admins/recipients/groups").
|
|
||||||
Get("", new(IndexAction)).
|
|
||||||
GetPost("/createPopup", new(CreatePopupAction)).
|
|
||||||
GetPost("/updatePopup", new(UpdatePopupAction)).
|
|
||||||
Post("/delete", new(DeleteAction)).
|
|
||||||
Get("/selectPopup", new(SelectPopupAction)).
|
|
||||||
EndAll()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
package groups
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/utils"
|
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
|
||||||
"github.com/iwind/TeaGo/lists"
|
|
||||||
"github.com/iwind/TeaGo/maps"
|
|
||||||
)
|
|
||||||
|
|
||||||
type SelectPopupAction struct {
|
|
||||||
actionutils.ParentAction
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *SelectPopupAction) RunGet(params struct {
|
|
||||||
GroupIds string
|
|
||||||
}) {
|
|
||||||
selectedGroupIds := utils.SplitNumbers(params.GroupIds)
|
|
||||||
|
|
||||||
groupsResp, err := this.RPC().MessageRecipientGroupRPC().FindAllEnabledMessageRecipientGroups(this.AdminContext(), &pb.FindAllEnabledMessageRecipientGroupsRequest{})
|
|
||||||
if err != nil {
|
|
||||||
this.ErrorPage(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
groupMaps := []maps.Map{}
|
|
||||||
for _, group := range groupsResp.MessageRecipientGroups {
|
|
||||||
if lists.ContainsInt64(selectedGroupIds, group.Id) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
groupMaps = append(groupMaps, maps.Map{
|
|
||||||
"id": group.Id,
|
|
||||||
"name": group.Name,
|
|
||||||
"isOn": group.IsOn,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
this.Data["groups"] = groupMaps
|
|
||||||
|
|
||||||
this.Show()
|
|
||||||
}
|
|
||||||
@@ -1,64 +0,0 @@
|
|||||||
package groups
|
|
||||||
|
|
||||||
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 {
|
|
||||||
GroupId int64
|
|
||||||
}) {
|
|
||||||
groupResp, err := this.RPC().MessageRecipientGroupRPC().FindEnabledMessageRecipientGroup(this.AdminContext(), &pb.FindEnabledMessageRecipientGroupRequest{MessageRecipientGroupId: params.GroupId})
|
|
||||||
if err != nil {
|
|
||||||
this.ErrorPage(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
group := groupResp.MessageRecipientGroup
|
|
||||||
if group == nil {
|
|
||||||
this.NotFound("messageRecipientGroup", params.GroupId)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
this.Data["group"] = maps.Map{
|
|
||||||
"id": group.Id,
|
|
||||||
"name": group.Name,
|
|
||||||
"isOn": group.IsOn,
|
|
||||||
}
|
|
||||||
|
|
||||||
this.Show()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *UpdatePopupAction) RunPost(params struct {
|
|
||||||
GroupId int64
|
|
||||||
Name string
|
|
||||||
IsOn bool
|
|
||||||
|
|
||||||
Must *actions.Must
|
|
||||||
CSRF *actionutils.CSRF
|
|
||||||
}) {
|
|
||||||
params.Must.
|
|
||||||
Field("name", params.Name).
|
|
||||||
Require("请输入分组名称")
|
|
||||||
|
|
||||||
_, err := this.RPC().MessageRecipientGroupRPC().UpdateMessageRecipientGroup(this.AdminContext(), &pb.UpdateMessageRecipientGroupRequest{
|
|
||||||
MessageRecipientGroupId: params.GroupId,
|
|
||||||
Name: params.Name,
|
|
||||||
IsOn: params.IsOn,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
this.ErrorPage(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
this.Success()
|
|
||||||
}
|
|
||||||
@@ -1,74 +0,0 @@
|
|||||||
package recipients
|
|
||||||
|
|
||||||
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("", "", "recipient")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *IndexAction) RunGet(params struct {
|
|
||||||
}) {
|
|
||||||
// TODO 增加系统用户、媒介类型等条件搜索
|
|
||||||
countResp, err := this.RPC().MessageRecipientRPC().CountAllEnabledMessageRecipients(this.AdminContext(), &pb.CountAllEnabledMessageRecipientsRequest{
|
|
||||||
AdminId: 0,
|
|
||||||
MediaType: "",
|
|
||||||
MessageRecipientGroupId: 0,
|
|
||||||
Keyword: "",
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
this.ErrorPage(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
count := countResp.Count
|
|
||||||
page := this.NewPage(count)
|
|
||||||
this.Data["page"] = page.AsHTML()
|
|
||||||
|
|
||||||
recipientsResp, err := this.RPC().MessageRecipientRPC().ListEnabledMessageRecipients(this.AdminContext(), &pb.ListEnabledMessageRecipientsRequest{
|
|
||||||
AdminId: 0,
|
|
||||||
MediaType: "",
|
|
||||||
MessageRecipientGroupId: 0,
|
|
||||||
Keyword: "",
|
|
||||||
Offset: page.Offset,
|
|
||||||
Size: page.Size,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
this.ErrorPage(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
recipientMaps := []maps.Map{}
|
|
||||||
for _, recipient := range recipientsResp.MessageRecipients {
|
|
||||||
if recipient.Admin == nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if recipient.MessageMediaInstance == nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
recipientMaps = append(recipientMaps, maps.Map{
|
|
||||||
"id": recipient.Id,
|
|
||||||
"admin": maps.Map{
|
|
||||||
"id": recipient.Admin.Id,
|
|
||||||
"fullname": recipient.Admin.Fullname,
|
|
||||||
"username": recipient.Admin.Username,
|
|
||||||
},
|
|
||||||
"groups": recipient.MessageRecipientGroups,
|
|
||||||
"isOn": recipient.IsOn,
|
|
||||||
"instance": maps.Map{
|
|
||||||
"name": recipient.MessageMediaInstance.Name,
|
|
||||||
},
|
|
||||||
"user": recipient.User,
|
|
||||||
"description": recipient.Description,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
this.Data["recipients"] = recipientMaps
|
|
||||||
|
|
||||||
this.Show()
|
|
||||||
}
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
package recipients
|
|
||||||
|
|
||||||
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.AdminModuleCodeAdmin)).
|
|
||||||
Data("teaMenu", "admins").
|
|
||||||
Data("teaSubMenu", "recipients").
|
|
||||||
Prefix("/admins/recipients").
|
|
||||||
Get("", new(IndexAction)).
|
|
||||||
GetPost("/createPopup", new(CreatePopupAction)).
|
|
||||||
GetPost("/update", new(UpdateAction)).
|
|
||||||
Post("/delete", new(DeleteAction)).
|
|
||||||
Post("/mediaOptions", new(MediaOptionsAction)).
|
|
||||||
Get("/recipient", new(RecipientAction)).
|
|
||||||
GetPost("/test", new(TestAction)).
|
|
||||||
EndAll()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
@@ -1,267 +0,0 @@
|
|||||||
package instances
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/monitorconfigs"
|
|
||||||
"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{}) {
|
|
||||||
this.Show()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *CreatePopupAction) RunPost(params struct {
|
|
||||||
Name string
|
|
||||||
MediaType string
|
|
||||||
|
|
||||||
EmailSmtp string
|
|
||||||
EmailUsername string
|
|
||||||
EmailPassword string
|
|
||||||
EmailFrom string
|
|
||||||
|
|
||||||
WebHookURL string
|
|
||||||
WebHookMethod string
|
|
||||||
WebHookHeaderNames []string
|
|
||||||
WebHookHeaderValues []string
|
|
||||||
WebHookContentType string
|
|
||||||
WebHookParamNames []string
|
|
||||||
WebHookParamValues []string
|
|
||||||
WebHookBody string
|
|
||||||
|
|
||||||
ScriptType string
|
|
||||||
ScriptPath string
|
|
||||||
ScriptLang string
|
|
||||||
ScriptCode string
|
|
||||||
ScriptCwd string
|
|
||||||
ScriptEnvNames []string
|
|
||||||
ScriptEnvValues []string
|
|
||||||
|
|
||||||
DingTalkWebHookURL string
|
|
||||||
|
|
||||||
QyWeixinCorporateId string
|
|
||||||
QyWeixinAgentId string
|
|
||||||
QyWeixinAppSecret string
|
|
||||||
QyWeixinTextFormat string
|
|
||||||
|
|
||||||
QyWeixinRobotWebHookURL string
|
|
||||||
QyWeixinRobotTextFormat string
|
|
||||||
|
|
||||||
AliyunSmsSign string
|
|
||||||
AliyunSmsTemplateCode string
|
|
||||||
AliyunSmsTemplateVarNames []string
|
|
||||||
AliyunSmsTemplateVarValues []string
|
|
||||||
AliyunSmsAccessKeyId string
|
|
||||||
AliyunSmsAccessKeySecret string
|
|
||||||
|
|
||||||
TelegramToken string
|
|
||||||
|
|
||||||
RateMinutes int32
|
|
||||||
RateCount int32
|
|
||||||
|
|
||||||
HashLife int32
|
|
||||||
|
|
||||||
Description string
|
|
||||||
|
|
||||||
Must *actions.Must
|
|
||||||
CSRF *actionutils.CSRF
|
|
||||||
}) {
|
|
||||||
params.Must.
|
|
||||||
Field("name", params.Name).
|
|
||||||
Require("请输入媒介名称").
|
|
||||||
Field("mediaType", params.MediaType).
|
|
||||||
Require("请选择媒介类型")
|
|
||||||
|
|
||||||
options := maps.Map{}
|
|
||||||
|
|
||||||
switch params.MediaType {
|
|
||||||
case "email":
|
|
||||||
params.Must.
|
|
||||||
Field("emailSmtp", params.EmailSmtp).
|
|
||||||
Require("请输入SMTP地址").
|
|
||||||
Field("emailUsername", params.EmailUsername).
|
|
||||||
Require("请输入邮箱账号").
|
|
||||||
Field("emailPassword", params.EmailPassword).
|
|
||||||
Require("请输入密码或授权码")
|
|
||||||
|
|
||||||
options["smtp"] = params.EmailSmtp
|
|
||||||
options["username"] = params.EmailUsername
|
|
||||||
options["password"] = params.EmailPassword
|
|
||||||
options["from"] = params.EmailFrom
|
|
||||||
case "webHook":
|
|
||||||
params.Must.
|
|
||||||
Field("webHookURL", params.WebHookURL).
|
|
||||||
Require("请输入URL地址").
|
|
||||||
Match("(?i)^(http|https)://", "URL地址必须以http或https开头").
|
|
||||||
Field("webHookMethod", params.WebHookMethod).
|
|
||||||
Require("请选择请求方法")
|
|
||||||
|
|
||||||
options["url"] = params.WebHookURL
|
|
||||||
options["method"] = params.WebHookMethod
|
|
||||||
options["contentType"] = params.WebHookContentType
|
|
||||||
|
|
||||||
headers := []maps.Map{}
|
|
||||||
if len(params.WebHookHeaderNames) > 0 {
|
|
||||||
for index, name := range params.WebHookHeaderNames {
|
|
||||||
if index < len(params.WebHookHeaderValues) {
|
|
||||||
headers = append(headers, maps.Map{
|
|
||||||
"name": name,
|
|
||||||
"value": params.WebHookHeaderValues[index],
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
options["headers"] = headers
|
|
||||||
|
|
||||||
if params.WebHookContentType == "params" {
|
|
||||||
webHookParams := []maps.Map{}
|
|
||||||
for index, name := range params.WebHookParamNames {
|
|
||||||
if index < len(params.WebHookParamValues) {
|
|
||||||
webHookParams = append(webHookParams, maps.Map{
|
|
||||||
"name": name,
|
|
||||||
"value": params.WebHookParamValues[index],
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
options["params"] = webHookParams
|
|
||||||
} else if params.WebHookContentType == "body" {
|
|
||||||
options["body"] = params.WebHookBody
|
|
||||||
}
|
|
||||||
case "script":
|
|
||||||
if params.ScriptType == "path" {
|
|
||||||
params.Must.
|
|
||||||
Field("scriptPath", params.ScriptPath).
|
|
||||||
Require("请输入脚本路径")
|
|
||||||
} else if params.ScriptType == "code" {
|
|
||||||
params.Must.
|
|
||||||
Field("scriptCode", params.ScriptCode).
|
|
||||||
Require("请输入脚本代码")
|
|
||||||
} else {
|
|
||||||
params.Must.
|
|
||||||
Field("scriptPath", params.ScriptPath).
|
|
||||||
Require("请输入脚本路径")
|
|
||||||
}
|
|
||||||
|
|
||||||
options["scriptType"] = params.ScriptType
|
|
||||||
options["path"] = params.ScriptPath
|
|
||||||
options["scriptLang"] = params.ScriptLang
|
|
||||||
options["script"] = params.ScriptCode
|
|
||||||
options["cwd"] = params.ScriptCwd
|
|
||||||
|
|
||||||
env := []maps.Map{}
|
|
||||||
for index, envName := range params.ScriptEnvNames {
|
|
||||||
if index < len(params.ScriptEnvValues) {
|
|
||||||
env = append(env, maps.Map{
|
|
||||||
"name": envName,
|
|
||||||
"value": params.ScriptEnvValues[index],
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
options["env"] = env
|
|
||||||
case "dingTalk":
|
|
||||||
params.Must.
|
|
||||||
Field("dingTalkWebHookURL", params.DingTalkWebHookURL).
|
|
||||||
Require("请输入Hook地址").
|
|
||||||
Match("^https:", "Hook地址必须以https://开头")
|
|
||||||
|
|
||||||
options["webHookURL"] = params.DingTalkWebHookURL
|
|
||||||
case "qyWeixin":
|
|
||||||
params.Must.
|
|
||||||
Field("qyWeixinCorporateId", params.QyWeixinCorporateId).
|
|
||||||
Require("请输入企业ID").
|
|
||||||
Field("qyWeixinAgentId", params.QyWeixinAgentId).
|
|
||||||
Require("请输入应用AgentId").
|
|
||||||
Field("qyWeixinSecret", params.QyWeixinAppSecret).
|
|
||||||
Require("请输入应用Secret")
|
|
||||||
|
|
||||||
options["corporateId"] = params.QyWeixinCorporateId
|
|
||||||
options["agentId"] = params.QyWeixinAgentId
|
|
||||||
options["appSecret"] = params.QyWeixinAppSecret
|
|
||||||
options["textFormat"] = params.QyWeixinTextFormat
|
|
||||||
case "qyWeixinRobot":
|
|
||||||
params.Must.
|
|
||||||
Field("qyWeixinRobotWebHookURL", params.QyWeixinRobotWebHookURL).
|
|
||||||
Require("请输入WebHook地址").
|
|
||||||
Match("^https:", "WebHook地址必须以https://开头")
|
|
||||||
|
|
||||||
options["webHookURL"] = params.QyWeixinRobotWebHookURL
|
|
||||||
options["textFormat"] = params.QyWeixinRobotTextFormat
|
|
||||||
case "aliyunSms":
|
|
||||||
params.Must.
|
|
||||||
Field("aliyunSmsSign", params.AliyunSmsSign).
|
|
||||||
Require("请输入签名名称").
|
|
||||||
Field("aliyunSmsTemplateCode", params.AliyunSmsTemplateCode).
|
|
||||||
Require("请输入模板CODE").
|
|
||||||
Field("aliyunSmsAccessKeyId", params.AliyunSmsAccessKeyId).
|
|
||||||
Require("请输入AccessKey ID").
|
|
||||||
Field("aliyunSmsAccessKeySecret", params.AliyunSmsAccessKeySecret).
|
|
||||||
Require("请输入AccessKey Secret")
|
|
||||||
|
|
||||||
options["sign"] = params.AliyunSmsSign
|
|
||||||
options["templateCode"] = params.AliyunSmsTemplateCode
|
|
||||||
options["accessKeyId"] = params.AliyunSmsAccessKeyId
|
|
||||||
options["accessKeySecret"] = params.AliyunSmsAccessKeySecret
|
|
||||||
|
|
||||||
variables := []maps.Map{}
|
|
||||||
for index, name := range params.AliyunSmsTemplateVarNames {
|
|
||||||
if index < len(params.AliyunSmsTemplateVarValues) {
|
|
||||||
variables = append(variables, maps.Map{
|
|
||||||
"name": name,
|
|
||||||
"value": params.AliyunSmsTemplateVarValues[index],
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
options["variables"] = variables
|
|
||||||
case "telegram":
|
|
||||||
params.Must.
|
|
||||||
Field("telegramToken", params.TelegramToken).
|
|
||||||
Require("请输入机器人Token")
|
|
||||||
options["token"] = params.TelegramToken
|
|
||||||
default:
|
|
||||||
this.Fail("错误的媒介类型")
|
|
||||||
}
|
|
||||||
|
|
||||||
optionsJSON, err := json.Marshal(options)
|
|
||||||
if err != nil {
|
|
||||||
this.ErrorPage(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var rateConfig = &monitorconfigs.RateConfig{
|
|
||||||
Minutes: params.RateMinutes,
|
|
||||||
Count: params.RateCount,
|
|
||||||
}
|
|
||||||
rateJSON, err := json.Marshal(rateConfig)
|
|
||||||
if err != nil {
|
|
||||||
this.ErrorPage(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := this.RPC().MessageMediaInstanceRPC().CreateMessageMediaInstance(this.AdminContext(), &pb.CreateMessageMediaInstanceRequest{
|
|
||||||
Name: params.Name,
|
|
||||||
MediaType: params.MediaType,
|
|
||||||
ParamsJSON: optionsJSON,
|
|
||||||
Description: params.Description,
|
|
||||||
RateJSON: rateJSON,
|
|
||||||
HashLife: params.HashLife,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
this.ErrorPage(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
defer this.CreateLogInfo(codes.MessageMediaInstance_LogCreateMessageMediaInstance, resp.MessageMediaInstanceId)
|
|
||||||
|
|
||||||
this.Success()
|
|
||||||
}
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
package instances
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
|
||||||
)
|
|
||||||
|
|
||||||
type DeleteAction struct {
|
|
||||||
actionutils.ParentAction
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *DeleteAction) RunPost(params struct {
|
|
||||||
InstanceId int64
|
|
||||||
}) {
|
|
||||||
defer this.CreateLogInfo(codes.MessageMediaInstance_LogDeleteMessageMediaInstance, params.InstanceId)
|
|
||||||
|
|
||||||
_, err := this.RPC().MessageMediaInstanceRPC().DeleteMessageMediaInstance(this.AdminContext(), &pb.DeleteMessageMediaInstanceRequest{MessageMediaInstanceId: params.InstanceId})
|
|
||||||
if err != nil {
|
|
||||||
this.ErrorPage(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
this.Success()
|
|
||||||
}
|
|
||||||
@@ -1,61 +0,0 @@
|
|||||||
package instances
|
|
||||||
|
|
||||||
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("", "", "instance")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *IndexAction) RunGet(params struct {
|
|
||||||
}) {
|
|
||||||
// TODO 增加系统用户、媒介类型等条件搜索
|
|
||||||
countResp, err := this.RPC().MessageMediaInstanceRPC().CountAllEnabledMessageMediaInstances(this.AdminContext(), &pb.CountAllEnabledMessageMediaInstancesRequest{
|
|
||||||
MediaType: "",
|
|
||||||
Keyword: "",
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
this.ErrorPage(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
count := countResp.Count
|
|
||||||
page := this.NewPage(count)
|
|
||||||
this.Data["page"] = page.AsHTML()
|
|
||||||
|
|
||||||
instancesResp, err := this.RPC().MessageMediaInstanceRPC().ListEnabledMessageMediaInstances(this.AdminContext(), &pb.ListEnabledMessageMediaInstancesRequest{
|
|
||||||
MediaType: "",
|
|
||||||
Keyword: "",
|
|
||||||
Offset: page.Offset,
|
|
||||||
Size: page.Size,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
this.ErrorPage(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
instanceMaps := []maps.Map{}
|
|
||||||
for _, instance := range instancesResp.MessageMediaInstances {
|
|
||||||
if instance.MessageMedia == nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
instanceMaps = append(instanceMaps, maps.Map{
|
|
||||||
"id": instance.Id,
|
|
||||||
"name": instance.Name,
|
|
||||||
"isOn": instance.IsOn,
|
|
||||||
"media": maps.Map{
|
|
||||||
"name": instance.MessageMedia.Name,
|
|
||||||
},
|
|
||||||
"description": instance.Description,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
this.Data["instances"] = instanceMaps
|
|
||||||
|
|
||||||
this.Show()
|
|
||||||
}
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
package instances
|
|
||||||
|
|
||||||
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.AdminModuleCodeAdmin)).
|
|
||||||
Data("teaMenu", "admins").
|
|
||||||
Data("teaSubMenu", "instances").
|
|
||||||
Prefix("/admins/recipients/instances").
|
|
||||||
Get("", new(IndexAction)).
|
|
||||||
GetPost("/createPopup", new(CreatePopupAction)).
|
|
||||||
GetPost("/update", new(UpdateAction)).
|
|
||||||
Post("/delete", new(DeleteAction)).
|
|
||||||
Get("/instance", new(InstanceAction)).
|
|
||||||
GetPost("/test", new(TestAction)).
|
|
||||||
Post("/options", new(OptionsAction)).
|
|
||||||
EndAll()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
@@ -1,67 +0,0 @@
|
|||||||
package instances
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/monitorconfigs"
|
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
|
||||||
"github.com/iwind/TeaGo/maps"
|
|
||||||
)
|
|
||||||
|
|
||||||
type InstanceAction struct {
|
|
||||||
actionutils.ParentAction
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *InstanceAction) Init() {
|
|
||||||
this.Nav("", "", "instance")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *InstanceAction) RunGet(params struct {
|
|
||||||
InstanceId int64
|
|
||||||
}) {
|
|
||||||
instanceResp, err := this.RPC().MessageMediaInstanceRPC().FindEnabledMessageMediaInstance(this.AdminContext(), &pb.FindEnabledMessageMediaInstanceRequest{MessageMediaInstanceId: params.InstanceId})
|
|
||||||
if err != nil {
|
|
||||||
this.ErrorPage(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
instance := instanceResp.MessageMediaInstance
|
|
||||||
if instance == nil || instance.MessageMedia == nil {
|
|
||||||
this.NotFound("messageMediaInstance", params.InstanceId)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
mediaParams := maps.Map{}
|
|
||||||
if len(instance.ParamsJSON) > 0 {
|
|
||||||
err = json.Unmarshal(instance.ParamsJSON, &mediaParams)
|
|
||||||
if err != nil {
|
|
||||||
this.ErrorPage(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 频率
|
|
||||||
var rateConfig = &monitorconfigs.RateConfig{}
|
|
||||||
if len(instance.RateJSON) > 0 {
|
|
||||||
err = json.Unmarshal(instance.RateJSON, rateConfig)
|
|
||||||
if err != nil {
|
|
||||||
this.ErrorPage(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.Data["instance"] = maps.Map{
|
|
||||||
"id": instance.Id,
|
|
||||||
"name": instance.Name,
|
|
||||||
"isOn": instance.IsOn,
|
|
||||||
"media": maps.Map{
|
|
||||||
"type": instance.MessageMedia.Type,
|
|
||||||
"name": instance.MessageMedia.Name,
|
|
||||||
},
|
|
||||||
"description": instance.Description,
|
|
||||||
"params": mediaParams,
|
|
||||||
"rate": rateConfig,
|
|
||||||
"hashLife": instance.HashLife,
|
|
||||||
}
|
|
||||||
|
|
||||||
this.Show()
|
|
||||||
}
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
package instances
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
|
||||||
"github.com/iwind/TeaGo/maps"
|
|
||||||
)
|
|
||||||
|
|
||||||
// 媒介类型选项
|
|
||||||
type OptionsAction struct {
|
|
||||||
actionutils.ParentAction
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *OptionsAction) RunPost(params struct{}) {
|
|
||||||
resp, err := this.RPC().MessageMediaInstanceRPC().ListEnabledMessageMediaInstances(this.AdminContext(), &pb.ListEnabledMessageMediaInstancesRequest{
|
|
||||||
Offset: 0,
|
|
||||||
Size: 1000,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
this.ErrorPage(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
instanceMaps := []maps.Map{}
|
|
||||||
for _, instance := range resp.MessageMediaInstances {
|
|
||||||
instanceMaps = append(instanceMaps, maps.Map{
|
|
||||||
"id": instance.Id,
|
|
||||||
"name": instance.Name,
|
|
||||||
"description": instance.Description,
|
|
||||||
"media": maps.Map{
|
|
||||||
"type": instance.MessageMedia.Type,
|
|
||||||
"name": instance.MessageMedia.Name,
|
|
||||||
"userDescription": instance.MessageMedia.UserDescription,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
this.Data["instances"] = instanceMaps
|
|
||||||
|
|
||||||
this.Success()
|
|
||||||
}
|
|
||||||
@@ -1,88 +0,0 @@
|
|||||||
package instances
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
|
||||||
"github.com/iwind/TeaGo/actions"
|
|
||||||
"github.com/iwind/TeaGo/maps"
|
|
||||||
)
|
|
||||||
|
|
||||||
type TestAction struct {
|
|
||||||
actionutils.ParentAction
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *TestAction) Init() {
|
|
||||||
this.Nav("", "", "test")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *TestAction) RunGet(params struct {
|
|
||||||
InstanceId int64
|
|
||||||
}) {
|
|
||||||
instanceResp, err := this.RPC().MessageMediaInstanceRPC().FindEnabledMessageMediaInstance(this.AdminContext(), &pb.FindEnabledMessageMediaInstanceRequest{MessageMediaInstanceId: params.InstanceId})
|
|
||||||
if err != nil {
|
|
||||||
this.ErrorPage(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
instance := instanceResp.MessageMediaInstance
|
|
||||||
if instance == nil || instance.MessageMedia == nil {
|
|
||||||
this.NotFound("messageMediaInstance", params.InstanceId)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
mediaParams := maps.Map{}
|
|
||||||
if len(instance.ParamsJSON) > 0 {
|
|
||||||
err = json.Unmarshal(instance.ParamsJSON, &mediaParams)
|
|
||||||
if err != nil {
|
|
||||||
this.ErrorPage(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.Data["instance"] = maps.Map{
|
|
||||||
"id": instance.Id,
|
|
||||||
"isOn": instance.IsOn,
|
|
||||||
"media": maps.Map{
|
|
||||||
"type": instance.MessageMedia.Type,
|
|
||||||
"name": instance.MessageMedia.Name,
|
|
||||||
"userDescription": instance.MessageMedia.UserDescription,
|
|
||||||
},
|
|
||||||
"description": instance.Description,
|
|
||||||
"params": mediaParams,
|
|
||||||
}
|
|
||||||
|
|
||||||
this.Show()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *TestAction) RunPost(params struct {
|
|
||||||
InstanceId int64
|
|
||||||
Subject string
|
|
||||||
Body string
|
|
||||||
User string
|
|
||||||
|
|
||||||
Must *actions.Must
|
|
||||||
CSRF *actionutils.CSRF
|
|
||||||
}) {
|
|
||||||
params.Must.
|
|
||||||
Field("instanceId", params.InstanceId).
|
|
||||||
Gt(0, "请选择正确的媒介")
|
|
||||||
|
|
||||||
resp, err := this.RPC().MessageTaskRPC().CreateMessageTask(this.AdminContext(), &pb.CreateMessageTaskRequest{
|
|
||||||
RecipientId: 0,
|
|
||||||
InstanceId: params.InstanceId,
|
|
||||||
User: params.User,
|
|
||||||
Subject: params.Subject,
|
|
||||||
Body: params.Body,
|
|
||||||
IsPrimary: true,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
this.ErrorPage(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
this.Data["taskId"] = resp.MessageTaskId
|
|
||||||
|
|
||||||
defer this.CreateLogInfo(codes.MessageTask_LogCreateTestingMessageTask, resp.MessageTaskId)
|
|
||||||
|
|
||||||
this.Success()
|
|
||||||
}
|
|
||||||
@@ -1,317 +0,0 @@
|
|||||||
package instances
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/monitorconfigs"
|
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
|
||||||
"github.com/iwind/TeaGo/actions"
|
|
||||||
"github.com/iwind/TeaGo/maps"
|
|
||||||
)
|
|
||||||
|
|
||||||
type UpdateAction struct {
|
|
||||||
actionutils.ParentAction
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *UpdateAction) Init() {
|
|
||||||
this.Nav("", "", "update")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *UpdateAction) RunGet(params struct {
|
|
||||||
InstanceId int64
|
|
||||||
}) {
|
|
||||||
instanceResp, err := this.RPC().MessageMediaInstanceRPC().FindEnabledMessageMediaInstance(this.AdminContext(), &pb.FindEnabledMessageMediaInstanceRequest{MessageMediaInstanceId: params.InstanceId})
|
|
||||||
if err != nil {
|
|
||||||
this.ErrorPage(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
instance := instanceResp.MessageMediaInstance
|
|
||||||
if instance == nil || instance.MessageMedia == nil {
|
|
||||||
this.NotFound("messageMediaInstance", params.InstanceId)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
mediaParams := maps.Map{}
|
|
||||||
if len(instance.ParamsJSON) > 0 {
|
|
||||||
err = json.Unmarshal(instance.ParamsJSON, &mediaParams)
|
|
||||||
if err != nil {
|
|
||||||
this.ErrorPage(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var rateConfig = &monitorconfigs.RateConfig{}
|
|
||||||
if len(instance.RateJSON) > 0 {
|
|
||||||
err = json.Unmarshal(instance.RateJSON, rateConfig)
|
|
||||||
if err != nil {
|
|
||||||
this.ErrorPage(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.Data["instance"] = maps.Map{
|
|
||||||
"id": instance.Id,
|
|
||||||
"name": instance.Name,
|
|
||||||
"isOn": instance.IsOn,
|
|
||||||
"media": maps.Map{
|
|
||||||
"type": instance.MessageMedia.Type,
|
|
||||||
"name": instance.MessageMedia.Name,
|
|
||||||
},
|
|
||||||
"description": instance.Description,
|
|
||||||
"params": mediaParams,
|
|
||||||
"rate": rateConfig,
|
|
||||||
"hashLife": instance.HashLife,
|
|
||||||
}
|
|
||||||
|
|
||||||
this.Show()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *UpdateAction) RunPost(params struct {
|
|
||||||
InstanceId int64
|
|
||||||
Name string
|
|
||||||
MediaType string
|
|
||||||
|
|
||||||
EmailSmtp string
|
|
||||||
EmailUsername string
|
|
||||||
EmailPassword string
|
|
||||||
EmailFrom string
|
|
||||||
|
|
||||||
WebHookURL string
|
|
||||||
WebHookMethod string
|
|
||||||
WebHookHeaderNames []string
|
|
||||||
WebHookHeaderValues []string
|
|
||||||
WebHookContentType string
|
|
||||||
WebHookParamNames []string
|
|
||||||
WebHookParamValues []string
|
|
||||||
WebHookBody string
|
|
||||||
|
|
||||||
ScriptType string
|
|
||||||
ScriptPath string
|
|
||||||
ScriptLang string
|
|
||||||
ScriptCode string
|
|
||||||
ScriptCwd string
|
|
||||||
ScriptEnvNames []string
|
|
||||||
ScriptEnvValues []string
|
|
||||||
|
|
||||||
DingTalkWebHookURL string
|
|
||||||
|
|
||||||
QyWeixinCorporateId string
|
|
||||||
QyWeixinAgentId string
|
|
||||||
QyWeixinAppSecret string
|
|
||||||
QyWeixinTextFormat string
|
|
||||||
|
|
||||||
QyWeixinRobotWebHookURL string
|
|
||||||
QyWeixinRobotTextFormat string
|
|
||||||
|
|
||||||
AliyunSmsSign string
|
|
||||||
AliyunSmsTemplateCode string
|
|
||||||
AliyunSmsTemplateVarNames []string
|
|
||||||
AliyunSmsTemplateVarValues []string
|
|
||||||
AliyunSmsAccessKeyId string
|
|
||||||
AliyunSmsAccessKeySecret string
|
|
||||||
|
|
||||||
TelegramToken string
|
|
||||||
|
|
||||||
GroupIds string
|
|
||||||
Description string
|
|
||||||
IsOn bool
|
|
||||||
|
|
||||||
RateMinutes int32
|
|
||||||
RateCount int32
|
|
||||||
|
|
||||||
HashLife int32
|
|
||||||
|
|
||||||
Must *actions.Must
|
|
||||||
CSRF *actionutils.CSRF
|
|
||||||
}) {
|
|
||||||
defer this.CreateLogInfo(codes.MessageMediaInstance_LogUpdateMessageMediaInstance, params.InstanceId)
|
|
||||||
|
|
||||||
params.Must.
|
|
||||||
Field("name", params.Name).
|
|
||||||
Require("请输入媒介名称").
|
|
||||||
Field("mediaType", params.MediaType).
|
|
||||||
Require("请选择媒介类型")
|
|
||||||
|
|
||||||
options := maps.Map{}
|
|
||||||
|
|
||||||
switch params.MediaType {
|
|
||||||
case "email":
|
|
||||||
params.Must.
|
|
||||||
Field("emailSmtp", params.EmailSmtp).
|
|
||||||
Require("请输入SMTP地址").
|
|
||||||
Field("emailUsername", params.EmailUsername).
|
|
||||||
Require("请输入邮箱账号").
|
|
||||||
Field("emailPassword", params.EmailPassword).
|
|
||||||
Require("请输入密码或授权码")
|
|
||||||
|
|
||||||
options["smtp"] = params.EmailSmtp
|
|
||||||
options["username"] = params.EmailUsername
|
|
||||||
options["password"] = params.EmailPassword
|
|
||||||
options["from"] = params.EmailFrom
|
|
||||||
case "webHook":
|
|
||||||
params.Must.
|
|
||||||
Field("webHookURL", params.WebHookURL).
|
|
||||||
Require("请输入URL地址").
|
|
||||||
Match("(?i)^(http|https)://", "URL地址必须以http或https开头").
|
|
||||||
Field("webHookMethod", params.WebHookMethod).
|
|
||||||
Require("请选择请求方法")
|
|
||||||
|
|
||||||
options["url"] = params.WebHookURL
|
|
||||||
options["method"] = params.WebHookMethod
|
|
||||||
options["contentType"] = params.WebHookContentType
|
|
||||||
|
|
||||||
headers := []maps.Map{}
|
|
||||||
if len(params.WebHookHeaderNames) > 0 {
|
|
||||||
for index, name := range params.WebHookHeaderNames {
|
|
||||||
if index < len(params.WebHookHeaderValues) {
|
|
||||||
headers = append(headers, maps.Map{
|
|
||||||
"name": name,
|
|
||||||
"value": params.WebHookHeaderValues[index],
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
options["headers"] = headers
|
|
||||||
|
|
||||||
if params.WebHookContentType == "params" {
|
|
||||||
webHookParams := []maps.Map{}
|
|
||||||
for index, name := range params.WebHookParamNames {
|
|
||||||
if index < len(params.WebHookParamValues) {
|
|
||||||
webHookParams = append(webHookParams, maps.Map{
|
|
||||||
"name": name,
|
|
||||||
"value": params.WebHookParamValues[index],
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
options["params"] = webHookParams
|
|
||||||
} else if params.WebHookContentType == "body" {
|
|
||||||
options["body"] = params.WebHookBody
|
|
||||||
}
|
|
||||||
case "script":
|
|
||||||
if params.ScriptType == "path" {
|
|
||||||
params.Must.
|
|
||||||
Field("scriptPath", params.ScriptPath).
|
|
||||||
Require("请输入脚本路径")
|
|
||||||
} else if params.ScriptType == "code" {
|
|
||||||
params.Must.
|
|
||||||
Field("scriptCode", params.ScriptCode).
|
|
||||||
Require("请输入脚本代码")
|
|
||||||
} else {
|
|
||||||
params.Must.
|
|
||||||
Field("scriptPath", params.ScriptPath).
|
|
||||||
Require("请输入脚本路径")
|
|
||||||
}
|
|
||||||
|
|
||||||
options["scriptType"] = params.ScriptType
|
|
||||||
options["path"] = params.ScriptPath
|
|
||||||
options["scriptLang"] = params.ScriptLang
|
|
||||||
options["script"] = params.ScriptCode
|
|
||||||
options["cwd"] = params.ScriptCwd
|
|
||||||
|
|
||||||
env := []maps.Map{}
|
|
||||||
for index, envName := range params.ScriptEnvNames {
|
|
||||||
if index < len(params.ScriptEnvValues) {
|
|
||||||
env = append(env, maps.Map{
|
|
||||||
"name": envName,
|
|
||||||
"value": params.ScriptEnvValues[index],
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
options["env"] = env
|
|
||||||
case "dingTalk":
|
|
||||||
params.Must.
|
|
||||||
Field("dingTalkWebHookURL", params.DingTalkWebHookURL).
|
|
||||||
Require("请输入Hook地址").
|
|
||||||
Match("^https:", "Hook地址必须以https://开头")
|
|
||||||
|
|
||||||
options["webHookURL"] = params.DingTalkWebHookURL
|
|
||||||
case "qyWeixin":
|
|
||||||
params.Must.
|
|
||||||
Field("qyWeixinCorporateId", params.QyWeixinCorporateId).
|
|
||||||
Require("请输入企业ID").
|
|
||||||
Field("qyWeixinAgentId", params.QyWeixinAgentId).
|
|
||||||
Require("请输入应用AgentId").
|
|
||||||
Field("qyWeixinSecret", params.QyWeixinAppSecret).
|
|
||||||
Require("请输入应用Secret")
|
|
||||||
|
|
||||||
options["corporateId"] = params.QyWeixinCorporateId
|
|
||||||
options["agentId"] = params.QyWeixinAgentId
|
|
||||||
options["appSecret"] = params.QyWeixinAppSecret
|
|
||||||
options["textFormat"] = params.QyWeixinTextFormat
|
|
||||||
case "qyWeixinRobot":
|
|
||||||
params.Must.
|
|
||||||
Field("qyWeixinRobotWebHookURL", params.QyWeixinRobotWebHookURL).
|
|
||||||
Require("请输入WebHook地址").
|
|
||||||
Match("^https:", "WebHook地址必须以https://开头")
|
|
||||||
|
|
||||||
options["webHookURL"] = params.QyWeixinRobotWebHookURL
|
|
||||||
options["textFormat"] = params.QyWeixinRobotTextFormat
|
|
||||||
case "aliyunSms":
|
|
||||||
params.Must.
|
|
||||||
Field("aliyunSmsSign", params.AliyunSmsSign).
|
|
||||||
Require("请输入签名名称").
|
|
||||||
Field("aliyunSmsTemplateCode", params.AliyunSmsTemplateCode).
|
|
||||||
Require("请输入模板CODE").
|
|
||||||
Field("aliyunSmsAccessKeyId", params.AliyunSmsAccessKeyId).
|
|
||||||
Require("请输入AccessKey ID").
|
|
||||||
Field("aliyunSmsAccessKeySecret", params.AliyunSmsAccessKeySecret).
|
|
||||||
Require("请输入AccessKey Secret")
|
|
||||||
|
|
||||||
options["sign"] = params.AliyunSmsSign
|
|
||||||
options["templateCode"] = params.AliyunSmsTemplateCode
|
|
||||||
options["accessKeyId"] = params.AliyunSmsAccessKeyId
|
|
||||||
options["accessKeySecret"] = params.AliyunSmsAccessKeySecret
|
|
||||||
|
|
||||||
variables := []maps.Map{}
|
|
||||||
for index, name := range params.AliyunSmsTemplateVarNames {
|
|
||||||
if index < len(params.AliyunSmsTemplateVarValues) {
|
|
||||||
variables = append(variables, maps.Map{
|
|
||||||
"name": name,
|
|
||||||
"value": params.AliyunSmsTemplateVarValues[index],
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
options["variables"] = variables
|
|
||||||
case "telegram":
|
|
||||||
params.Must.
|
|
||||||
Field("telegramToken", params.TelegramToken).
|
|
||||||
Require("请输入机器人Token")
|
|
||||||
options["token"] = params.TelegramToken
|
|
||||||
default:
|
|
||||||
this.Fail("错误的媒介类型")
|
|
||||||
}
|
|
||||||
|
|
||||||
optionsJSON, err := json.Marshal(options)
|
|
||||||
if err != nil {
|
|
||||||
this.ErrorPage(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var rateConfig = &monitorconfigs.RateConfig{
|
|
||||||
Minutes: params.RateMinutes,
|
|
||||||
Count: params.RateCount,
|
|
||||||
}
|
|
||||||
rateJSON, err := json.Marshal(rateConfig)
|
|
||||||
if err != nil {
|
|
||||||
this.ErrorPage(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = this.RPC().MessageMediaInstanceRPC().UpdateMessageMediaInstance(this.AdminContext(), &pb.UpdateMessageMediaInstanceRequest{
|
|
||||||
MessageMediaInstanceId: params.InstanceId,
|
|
||||||
Name: params.Name,
|
|
||||||
MediaType: params.MediaType,
|
|
||||||
ParamsJSON: optionsJSON,
|
|
||||||
Description: params.Description,
|
|
||||||
RateJSON: rateJSON,
|
|
||||||
HashLife: params.HashLife,
|
|
||||||
IsOn: params.IsOn,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
this.ErrorPage(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
this.Success()
|
|
||||||
}
|
|
||||||
@@ -1,61 +0,0 @@
|
|||||||
package logs
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
|
||||||
"github.com/iwind/TeaGo/maps"
|
|
||||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
|
||||||
)
|
|
||||||
|
|
||||||
type IndexAction struct {
|
|
||||||
actionutils.ParentAction
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *IndexAction) Init() {
|
|
||||||
this.Nav("", "", "log")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *IndexAction) RunGet(params struct{}) {
|
|
||||||
countResp, err := this.RPC().MessageTaskLogRPC().CountMessageTaskLogs(this.AdminContext(), &pb.CountMessageTaskLogsRequest{})
|
|
||||||
if err != nil {
|
|
||||||
this.ErrorPage(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
page := this.NewPage(countResp.Count)
|
|
||||||
this.Data["page"] = page.AsHTML()
|
|
||||||
|
|
||||||
logsResp, err := this.RPC().MessageTaskLogRPC().ListMessageTaskLogs(this.AdminContext(), &pb.ListMessageTaskLogsRequest{
|
|
||||||
Offset: page.Offset,
|
|
||||||
Size: page.Size,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
this.ErrorPage(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
logMaps := []maps.Map{}
|
|
||||||
for _, log := range logsResp.MessageTaskLogs {
|
|
||||||
if log.MessageTask.MessageRecipient != nil {
|
|
||||||
log.MessageTask.User = log.MessageTask.MessageRecipient.User
|
|
||||||
}
|
|
||||||
logMaps = append(logMaps, maps.Map{
|
|
||||||
"task": maps.Map{
|
|
||||||
"id": log.MessageTask.Id,
|
|
||||||
"user": log.MessageTask.User,
|
|
||||||
"subject": log.MessageTask.Subject,
|
|
||||||
"body": log.MessageTask.Body,
|
|
||||||
"instance": maps.Map{
|
|
||||||
"id": log.MessageTask.MessageMediaInstance.Id,
|
|
||||||
"name": log.MessageTask.MessageMediaInstance.Name,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"isOk": log.IsOk,
|
|
||||||
"error": log.Error,
|
|
||||||
"response": log.Response,
|
|
||||||
"createdTime": timeutil.FormatTime("Y-m-d H:i:s", log.CreatedAt),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
this.Data["logs"] = logMaps
|
|
||||||
|
|
||||||
this.Show()
|
|
||||||
}
|
|
||||||
@@ -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.AdminModuleCodeAdmin)).
|
|
||||||
Data("teaMenu", "admins").
|
|
||||||
Data("teaSubMenu", "recipients").
|
|
||||||
Prefix("/admins/recipients/logs").
|
|
||||||
Get("", new(IndexAction)).
|
|
||||||
EndAll()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
package recipients
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
|
||||||
"github.com/iwind/TeaGo/maps"
|
|
||||||
)
|
|
||||||
|
|
||||||
// 媒介类型选项
|
|
||||||
type MediaOptionsAction struct {
|
|
||||||
actionutils.ParentAction
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *MediaOptionsAction) RunPost(params struct{}) {
|
|
||||||
resp, err := this.RPC().MessageMediaRPC().FindAllMessageMedias(this.AdminContext(), &pb.FindAllMessageMediasRequest{})
|
|
||||||
if err != nil {
|
|
||||||
this.ErrorPage(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
mediaMaps := []maps.Map{}
|
|
||||||
for _, media := range resp.MessageMedias {
|
|
||||||
mediaMaps = append(mediaMaps, maps.Map{
|
|
||||||
"id": media.Id,
|
|
||||||
"type": media.Type,
|
|
||||||
"name": media.Name,
|
|
||||||
"description": media.Description,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
this.Data["medias"] = mediaMaps
|
|
||||||
|
|
||||||
this.Success()
|
|
||||||
}
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
package recipients
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
|
||||||
"github.com/iwind/TeaGo/maps"
|
|
||||||
)
|
|
||||||
|
|
||||||
type RecipientAction struct {
|
|
||||||
actionutils.ParentAction
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *RecipientAction) Init() {
|
|
||||||
this.Nav("", "", "recipient")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *RecipientAction) RunGet(params struct {
|
|
||||||
RecipientId int64
|
|
||||||
}) {
|
|
||||||
recipientResp, err := this.RPC().MessageRecipientRPC().FindEnabledMessageRecipient(this.AdminContext(), &pb.FindEnabledMessageRecipientRequest{MessageRecipientId: params.RecipientId})
|
|
||||||
if err != nil {
|
|
||||||
this.ErrorPage(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
recipient := recipientResp.MessageRecipient
|
|
||||||
if recipient == nil || recipient.Admin == nil || recipient.MessageMediaInstance == nil {
|
|
||||||
this.NotFound("messageRecipient", params.RecipientId)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
this.Data["recipient"] = maps.Map{
|
|
||||||
"id": recipient.Id,
|
|
||||||
"admin": maps.Map{
|
|
||||||
"id": recipient.Admin.Id,
|
|
||||||
"fullname": recipient.Admin.Fullname,
|
|
||||||
"username": recipient.Admin.Username,
|
|
||||||
},
|
|
||||||
"groups": recipient.MessageRecipientGroups,
|
|
||||||
"isOn": recipient.IsOn,
|
|
||||||
"instance": maps.Map{
|
|
||||||
"id": recipient.MessageMediaInstance.Id,
|
|
||||||
"name": recipient.MessageMediaInstance.Name,
|
|
||||||
"description": recipient.MessageMediaInstance.Description,
|
|
||||||
},
|
|
||||||
"user": recipient.User,
|
|
||||||
"description": recipient.Description,
|
|
||||||
"timeFrom": recipient.TimeFrom,
|
|
||||||
"timeTo": recipient.TimeTo,
|
|
||||||
}
|
|
||||||
|
|
||||||
this.Show()
|
|
||||||
}
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
|
||||||
|
|
||||||
package tasks
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
|
||||||
)
|
|
||||||
|
|
||||||
type DeleteAction struct {
|
|
||||||
actionutils.ParentAction
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *DeleteAction) RunPost(params struct {
|
|
||||||
TaskId int64
|
|
||||||
}) {
|
|
||||||
defer this.CreateLogInfo(codes.MessageTask_LogDeleteMessageTask, params.TaskId)
|
|
||||||
|
|
||||||
_, err := this.RPC().MessageTaskRPC().DeleteMessageTask(this.AdminContext(), &pb.DeleteMessageTaskRequest{MessageTaskId: params.TaskId})
|
|
||||||
if err != nil {
|
|
||||||
this.ErrorPage(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
this.Success()
|
|
||||||
}
|
|
||||||
@@ -1,103 +0,0 @@
|
|||||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
|
||||||
|
|
||||||
package tasks
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
|
||||||
"github.com/iwind/TeaGo/maps"
|
|
||||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
|
||||||
)
|
|
||||||
|
|
||||||
type IndexAction struct {
|
|
||||||
actionutils.ParentAction
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *IndexAction) Init() {
|
|
||||||
this.Nav("", "", "task")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *IndexAction) RunGet(params struct {
|
|
||||||
Status int32
|
|
||||||
}) {
|
|
||||||
this.Data["status"] = params.Status
|
|
||||||
if params.Status > 3 {
|
|
||||||
params.Status = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
countWaitingResp, err := this.RPC().MessageTaskRPC().CountMessageTasksWithStatus(this.AdminContext(), &pb.CountMessageTasksWithStatusRequest{Status: pb.CountMessageTasksWithStatusRequest_MessageTaskStatusNone})
|
|
||||||
if err != nil {
|
|
||||||
this.ErrorPage(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
var countWaiting = countWaitingResp.Count
|
|
||||||
this.Data["countWaiting"] = countWaiting
|
|
||||||
|
|
||||||
countFailedResp, err := this.RPC().MessageTaskRPC().CountMessageTasksWithStatus(this.AdminContext(), &pb.CountMessageTasksWithStatusRequest{Status: pb.CountMessageTasksWithStatusRequest_MessageTaskStatusFailed})
|
|
||||||
if err != nil {
|
|
||||||
this.ErrorPage(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
var countFailed = countFailedResp.Count
|
|
||||||
this.Data["countFailed"] = countFailed
|
|
||||||
|
|
||||||
// 列表
|
|
||||||
var total = int64(0)
|
|
||||||
switch params.Status {
|
|
||||||
case 0:
|
|
||||||
total = countWaiting
|
|
||||||
case 3:
|
|
||||||
total = countFailed
|
|
||||||
}
|
|
||||||
page := this.NewPage(total)
|
|
||||||
this.Data["page"] = page.AsHTML()
|
|
||||||
|
|
||||||
var taskMaps = []maps.Map{}
|
|
||||||
tasksResp, err := this.RPC().MessageTaskRPC().ListMessageTasksWithStatus(this.AdminContext(), &pb.ListMessageTasksWithStatusRequest{
|
|
||||||
Status: pb.ListMessageTasksWithStatusRequest_Status(params.Status),
|
|
||||||
Offset: page.Offset,
|
|
||||||
Size: page.Size,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
this.ErrorPage(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
for _, task := range tasksResp.MessageTasks {
|
|
||||||
var resultMap = maps.Map{}
|
|
||||||
var result = task.Result
|
|
||||||
if result != nil {
|
|
||||||
resultMap = maps.Map{
|
|
||||||
"isOk": result.IsOk,
|
|
||||||
"error": result.Error,
|
|
||||||
"response": result.Response,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//var recipients = []string{}
|
|
||||||
var user = ""
|
|
||||||
var instanceMap maps.Map
|
|
||||||
if task.MessageRecipient != nil {
|
|
||||||
user = task.MessageRecipient.User
|
|
||||||
if task.MessageRecipient.MessageMediaInstance != nil {
|
|
||||||
instanceMap = maps.Map{
|
|
||||||
"id": task.MessageRecipient.MessageMediaInstance.Id,
|
|
||||||
"name": task.MessageRecipient.MessageMediaInstance.Name,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
taskMaps = append(taskMaps, maps.Map{
|
|
||||||
"id": task.Id,
|
|
||||||
"subject": task.Subject,
|
|
||||||
"body": task.Body,
|
|
||||||
"createdTime": timeutil.FormatTime("Y-m-d H:i:s", task.CreatedAt),
|
|
||||||
"result": resultMap,
|
|
||||||
"status": task.Status,
|
|
||||||
"user": user,
|
|
||||||
"instance": instanceMap,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
this.Data["tasks"] = taskMaps
|
|
||||||
|
|
||||||
this.Show()
|
|
||||||
}
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
package tasks
|
|
||||||
|
|
||||||
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.AdminModuleCodeAdmin)).
|
|
||||||
Data("teaMenu", "admins").
|
|
||||||
Data("teaSubMenu", "recipients").
|
|
||||||
Prefix("/admins/recipients/tasks").
|
|
||||||
Get("", new(IndexAction)).
|
|
||||||
Post("/taskInfo", new(TaskInfoAction)).
|
|
||||||
Post("/delete", new(DeleteAction)).
|
|
||||||
EndAll()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
package tasks
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
|
||||||
"github.com/iwind/TeaGo/maps"
|
|
||||||
)
|
|
||||||
|
|
||||||
type TaskInfoAction struct {
|
|
||||||
actionutils.ParentAction
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *TaskInfoAction) Init() {
|
|
||||||
this.Nav("", "", "")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *TaskInfoAction) RunPost(params struct {
|
|
||||||
TaskId int64
|
|
||||||
}) {
|
|
||||||
resp, err := this.RPC().MessageTaskRPC().FindEnabledMessageTask(this.AdminContext(), &pb.FindEnabledMessageTaskRequest{MessageTaskId: params.TaskId})
|
|
||||||
if err != nil {
|
|
||||||
this.ErrorPage(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if resp.MessageTask == nil {
|
|
||||||
this.NotFound("messageTask", params.TaskId)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
result := resp.MessageTask.Result
|
|
||||||
this.Data["status"] = resp.MessageTask.Status
|
|
||||||
this.Data["result"] = maps.Map{
|
|
||||||
"isOk": result.IsOk,
|
|
||||||
"response": result.Response,
|
|
||||||
"error": result.Error,
|
|
||||||
}
|
|
||||||
|
|
||||||
this.Success()
|
|
||||||
}
|
|
||||||
@@ -1,114 +0,0 @@
|
|||||||
package recipients
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
|
||||||
"github.com/iwind/TeaGo/actions"
|
|
||||||
"github.com/iwind/TeaGo/maps"
|
|
||||||
)
|
|
||||||
|
|
||||||
type TestAction struct {
|
|
||||||
actionutils.ParentAction
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *TestAction) Init() {
|
|
||||||
this.Nav("", "", "test")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *TestAction) RunGet(params struct {
|
|
||||||
RecipientId int64
|
|
||||||
}) {
|
|
||||||
recipientResp, err := this.RPC().MessageRecipientRPC().FindEnabledMessageRecipient(this.AdminContext(), &pb.FindEnabledMessageRecipientRequest{MessageRecipientId: params.RecipientId})
|
|
||||||
if err != nil {
|
|
||||||
this.ErrorPage(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
recipient := recipientResp.MessageRecipient
|
|
||||||
if recipient == nil || recipient.Admin == nil || recipient.MessageMediaInstance == nil {
|
|
||||||
this.NotFound("messageRecipient", params.RecipientId)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
this.Data["recipient"] = maps.Map{
|
|
||||||
"id": recipient.Id,
|
|
||||||
"admin": maps.Map{
|
|
||||||
"id": recipient.Admin.Id,
|
|
||||||
"fullname": recipient.Admin.Fullname,
|
|
||||||
"username": recipient.Admin.Username,
|
|
||||||
},
|
|
||||||
"instance": maps.Map{
|
|
||||||
"id": recipient.MessageMediaInstance.Id,
|
|
||||||
"name": recipient.MessageMediaInstance.Name,
|
|
||||||
"description": recipient.MessageMediaInstance.Description,
|
|
||||||
},
|
|
||||||
"user": recipient.User,
|
|
||||||
}
|
|
||||||
|
|
||||||
instanceResp, err := this.RPC().MessageMediaInstanceRPC().FindEnabledMessageMediaInstance(this.AdminContext(), &pb.FindEnabledMessageMediaInstanceRequest{MessageMediaInstanceId: recipient.MessageMediaInstance.Id})
|
|
||||||
if err != nil {
|
|
||||||
this.ErrorPage(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
instance := instanceResp.MessageMediaInstance
|
|
||||||
if instance == nil || instance.MessageMedia == nil {
|
|
||||||
this.NotFound("messageMediaInstance", recipient.MessageMediaInstance.Id)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
mediaParams := maps.Map{}
|
|
||||||
if len(instance.ParamsJSON) > 0 {
|
|
||||||
err = json.Unmarshal(instance.ParamsJSON, &mediaParams)
|
|
||||||
if err != nil {
|
|
||||||
this.ErrorPage(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.Data["instance"] = maps.Map{
|
|
||||||
"id": instance.Id,
|
|
||||||
"isOn": instance.IsOn,
|
|
||||||
"media": maps.Map{
|
|
||||||
"type": instance.MessageMedia.Type,
|
|
||||||
"name": instance.MessageMedia.Name,
|
|
||||||
"userDescription": instance.MessageMedia.UserDescription,
|
|
||||||
},
|
|
||||||
"description": instance.Description,
|
|
||||||
"params": mediaParams,
|
|
||||||
}
|
|
||||||
|
|
||||||
this.Show()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *TestAction) RunPost(params struct {
|
|
||||||
InstanceId int64
|
|
||||||
Subject string
|
|
||||||
Body string
|
|
||||||
User string
|
|
||||||
|
|
||||||
Must *actions.Must
|
|
||||||
CSRF *actionutils.CSRF
|
|
||||||
}) {
|
|
||||||
params.Must.
|
|
||||||
Field("instanceId", params.InstanceId).
|
|
||||||
Gt(0, "请选择正确的媒介")
|
|
||||||
|
|
||||||
resp, err := this.RPC().MessageTaskRPC().CreateMessageTask(this.AdminContext(), &pb.CreateMessageTaskRequest{
|
|
||||||
RecipientId: 0,
|
|
||||||
InstanceId: params.InstanceId,
|
|
||||||
User: params.User,
|
|
||||||
Subject: params.Subject,
|
|
||||||
Body: params.Body,
|
|
||||||
IsPrimary: true,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
this.ErrorPage(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
this.Data["taskId"] = resp.MessageTaskId
|
|
||||||
|
|
||||||
defer this.CreateLogInfo(codes.MessageTask_LogCreateTestingMessageTask, resp.MessageTaskId)
|
|
||||||
|
|
||||||
this.Success()
|
|
||||||
}
|
|
||||||
@@ -1,144 +0,0 @@
|
|||||||
package recipients
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/utils"
|
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
|
||||||
"github.com/iwind/TeaGo/actions"
|
|
||||||
"github.com/iwind/TeaGo/maps"
|
|
||||||
"regexp"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
type UpdateAction struct {
|
|
||||||
actionutils.ParentAction
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *UpdateAction) Init() {
|
|
||||||
this.Nav("", "", "update")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *UpdateAction) RunGet(params struct {
|
|
||||||
RecipientId int64
|
|
||||||
}) {
|
|
||||||
recipientResp, err := this.RPC().MessageRecipientRPC().FindEnabledMessageRecipient(this.AdminContext(), &pb.FindEnabledMessageRecipientRequest{MessageRecipientId: params.RecipientId})
|
|
||||||
if err != nil {
|
|
||||||
this.ErrorPage(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
recipient := recipientResp.MessageRecipient
|
|
||||||
if recipient == nil || recipient.Admin == nil || recipient.MessageMediaInstance == nil {
|
|
||||||
this.NotFound("messageRecipient", params.RecipientId)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var timeFromHour = ""
|
|
||||||
var timeFromMinute = ""
|
|
||||||
var timeFromSecond = ""
|
|
||||||
|
|
||||||
if len(recipient.TimeFrom) > 0 {
|
|
||||||
var pieces = strings.Split(recipient.TimeFrom, ":")
|
|
||||||
timeFromHour = pieces[0]
|
|
||||||
timeFromMinute = pieces[1]
|
|
||||||
timeFromSecond = pieces[2]
|
|
||||||
}
|
|
||||||
|
|
||||||
var timeToHour = ""
|
|
||||||
var timeToMinute = ""
|
|
||||||
var timeToSecond = ""
|
|
||||||
if len(recipient.TimeTo) > 0 {
|
|
||||||
var pieces = strings.Split(recipient.TimeTo, ":")
|
|
||||||
timeToHour = pieces[0]
|
|
||||||
timeToMinute = pieces[1]
|
|
||||||
timeToSecond = pieces[2]
|
|
||||||
}
|
|
||||||
|
|
||||||
this.Data["recipient"] = maps.Map{
|
|
||||||
"id": recipient.Id,
|
|
||||||
"admin": maps.Map{
|
|
||||||
"id": recipient.Admin.Id,
|
|
||||||
"fullname": recipient.Admin.Fullname,
|
|
||||||
"username": recipient.Admin.Username,
|
|
||||||
},
|
|
||||||
"groups": recipient.MessageRecipientGroups,
|
|
||||||
"isOn": recipient.IsOn,
|
|
||||||
"instance": maps.Map{
|
|
||||||
"id": recipient.MessageMediaInstance.Id,
|
|
||||||
"name": recipient.MessageMediaInstance.Name,
|
|
||||||
},
|
|
||||||
"user": recipient.User,
|
|
||||||
"description": recipient.Description,
|
|
||||||
"timeFromHour": timeFromHour,
|
|
||||||
"timeFromMinute": timeFromMinute,
|
|
||||||
"timeFromSecond": timeFromSecond,
|
|
||||||
"timeToHour": timeToHour,
|
|
||||||
"timeToMinute": timeToMinute,
|
|
||||||
"timeToSecond": timeToSecond,
|
|
||||||
}
|
|
||||||
|
|
||||||
this.Show()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *UpdateAction) RunPost(params struct {
|
|
||||||
RecipientId int64
|
|
||||||
|
|
||||||
AdminId int64
|
|
||||||
User string
|
|
||||||
InstanceId int64
|
|
||||||
|
|
||||||
GroupIds string
|
|
||||||
Description string
|
|
||||||
IsOn bool
|
|
||||||
|
|
||||||
TimeFromHour string
|
|
||||||
TimeFromMinute string
|
|
||||||
TimeFromSecond string
|
|
||||||
|
|
||||||
TimeToHour string
|
|
||||||
TimeToMinute string
|
|
||||||
TimeToSecond string
|
|
||||||
|
|
||||||
Must *actions.Must
|
|
||||||
CSRF *actionutils.CSRF
|
|
||||||
}) {
|
|
||||||
defer this.CreateLogInfo(codes.MessageRecipient_LogUpdateMessageRecipient, params.RecipientId)
|
|
||||||
|
|
||||||
params.Must.
|
|
||||||
Field("adminId", params.AdminId).
|
|
||||||
Gt(0, "请选择系统用户").
|
|
||||||
Field("instanceId", params.InstanceId).
|
|
||||||
Gt(0, "请选择媒介")
|
|
||||||
|
|
||||||
groupIds := utils.SplitNumbers(params.GroupIds)
|
|
||||||
|
|
||||||
var digitReg = regexp.MustCompile(`^\d+$`)
|
|
||||||
|
|
||||||
var timeFrom = ""
|
|
||||||
if digitReg.MatchString(params.TimeFromHour) && digitReg.MatchString(params.TimeFromMinute) && digitReg.MatchString(params.TimeFromSecond) {
|
|
||||||
timeFrom = params.TimeFromHour + ":" + params.TimeFromMinute + ":" + params.TimeFromSecond
|
|
||||||
}
|
|
||||||
|
|
||||||
var timeTo = ""
|
|
||||||
if digitReg.MatchString(params.TimeToHour) && digitReg.MatchString(params.TimeToMinute) && digitReg.MatchString(params.TimeToSecond) {
|
|
||||||
timeTo = params.TimeToHour + ":" + params.TimeToMinute + ":" + params.TimeToSecond
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err := this.RPC().MessageRecipientRPC().UpdateMessageRecipient(this.AdminContext(), &pb.UpdateMessageRecipientRequest{
|
|
||||||
MessageRecipientId: params.RecipientId,
|
|
||||||
AdminId: params.AdminId,
|
|
||||||
MessageMediaInstanceId: params.InstanceId,
|
|
||||||
User: params.User,
|
|
||||||
MessageRecipientGroupIds: groupIds,
|
|
||||||
Description: params.Description,
|
|
||||||
IsOn: params.IsOn,
|
|
||||||
TimeFrom: timeFrom,
|
|
||||||
TimeTo: timeTo,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
this.ErrorPage(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
this.Success()
|
|
||||||
}
|
|
||||||
@@ -297,7 +297,7 @@ func (this *DetailAction) RunGet(params struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 缓存硬盘 & 内存容量
|
// 缓存硬盘 & 内存容量
|
||||||
var maxCacheDiskCapacity maps.Map = nil
|
var maxCacheDiskCapacity maps.Map
|
||||||
if node.MaxCacheDiskCapacity != nil {
|
if node.MaxCacheDiskCapacity != nil {
|
||||||
maxCacheDiskCapacity = maps.Map{
|
maxCacheDiskCapacity = maps.Map{
|
||||||
"count": node.MaxCacheDiskCapacity.Count,
|
"count": node.MaxCacheDiskCapacity.Count,
|
||||||
@@ -310,7 +310,7 @@ func (this *DetailAction) RunGet(params struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var maxCacheMemoryCapacity maps.Map = nil
|
var maxCacheMemoryCapacity maps.Map
|
||||||
if node.MaxCacheMemoryCapacity != nil {
|
if node.MaxCacheMemoryCapacity != nil {
|
||||||
maxCacheMemoryCapacity = maps.Map{
|
maxCacheMemoryCapacity = maps.Map{
|
||||||
"count": node.MaxCacheMemoryCapacity.Count,
|
"count": node.MaxCacheMemoryCapacity.Count,
|
||||||
@@ -389,6 +389,7 @@ func (this *DetailAction) RunGet(params struct {
|
|||||||
"exePath": status.ExePath,
|
"exePath": status.ExePath,
|
||||||
"apiSuccessPercent": status.APISuccessPercent,
|
"apiSuccessPercent": status.APISuccessPercent,
|
||||||
"apiAvgCostSeconds": status.APIAvgCostSeconds,
|
"apiAvgCostSeconds": status.APIAvgCostSeconds,
|
||||||
|
"diskWritingSpeedMB": status.DiskWritingSpeedMB,
|
||||||
},
|
},
|
||||||
|
|
||||||
"group": groupMap,
|
"group": groupMap,
|
||||||
|
|||||||
@@ -2,9 +2,11 @@ package node
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/utils"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/cluster/node/nodeutils"
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/cluster/node/nodeutils"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/clusterutils"
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/clusterutils"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/configutils"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
@@ -109,6 +111,26 @@ func (this *InstallAction) RunGet(params struct {
|
|||||||
var installerFiles = clusterutils.ListInstallerFiles()
|
var installerFiles = clusterutils.ListInstallerFiles()
|
||||||
this.Data["installerFiles"] = installerFiles
|
this.Data["installerFiles"] = installerFiles
|
||||||
|
|
||||||
|
// SSH主机地址
|
||||||
|
this.Data["sshAddr"] = ""
|
||||||
|
if node.NodeLogin != nil && node.NodeLogin.Type == "ssh" && !utils.JSONIsNull(node.NodeLogin.Params) {
|
||||||
|
var loginParams = maps.Map{}
|
||||||
|
err = json.Unmarshal(node.NodeLogin.Params, &loginParams)
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var host = loginParams.GetString("host")
|
||||||
|
if len(host) > 0 {
|
||||||
|
var port = loginParams.GetString("port")
|
||||||
|
if port == "0" {
|
||||||
|
port = "22"
|
||||||
|
}
|
||||||
|
this.Data["sshAddr"] = configutils.QuoteIP(host) + ":" + port
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this.Show()
|
this.Show()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ func (this *IndexAction) RunGet(params struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 缓存硬盘 & 内存容量
|
// 缓存硬盘 & 内存容量
|
||||||
var maxCacheDiskCapacity maps.Map = nil
|
var maxCacheDiskCapacity maps.Map
|
||||||
if node.MaxCacheDiskCapacity != nil {
|
if node.MaxCacheDiskCapacity != nil {
|
||||||
maxCacheDiskCapacity = maps.Map{
|
maxCacheDiskCapacity = maps.Map{
|
||||||
"count": node.MaxCacheDiskCapacity.Count,
|
"count": node.MaxCacheDiskCapacity.Count,
|
||||||
@@ -46,7 +46,7 @@ func (this *IndexAction) RunGet(params struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var maxCacheMemoryCapacity maps.Map = nil
|
var maxCacheMemoryCapacity maps.Map
|
||||||
if node.MaxCacheMemoryCapacity != nil {
|
if node.MaxCacheMemoryCapacity != nil {
|
||||||
maxCacheMemoryCapacity = maps.Map{
|
maxCacheMemoryCapacity = maps.Map{
|
||||||
"count": node.MaxCacheMemoryCapacity.Count,
|
"count": node.MaxCacheMemoryCapacity.Count,
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import (
|
|||||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
"github.com/iwind/TeaGo/actions"
|
"github.com/iwind/TeaGo/actions"
|
||||||
|
"github.com/iwind/TeaGo/lists"
|
||||||
"github.com/iwind/TeaGo/maps"
|
"github.com/iwind/TeaGo/maps"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -35,6 +36,7 @@ func (this *IndexAction) RunGet(params struct {
|
|||||||
clusters = append(clusters, node.SecondaryNodeClusters...)
|
clusters = append(clusters, node.SecondaryNodeClusters...)
|
||||||
var allDNSRouteMaps = map[int64][]maps.Map{} // domain id => routes
|
var allDNSRouteMaps = map[int64][]maps.Map{} // domain id => routes
|
||||||
var routeMaps = map[int64][]maps.Map{} // domain id => routes
|
var routeMaps = map[int64][]maps.Map{} // domain id => routes
|
||||||
|
var domainIds = []int64{}
|
||||||
for _, cluster := range clusters {
|
for _, cluster := range clusters {
|
||||||
dnsInfoResp, err := this.RPC().NodeRPC().FindEnabledNodeDNS(this.AdminContext(), &pb.FindEnabledNodeDNSRequest{
|
dnsInfoResp, err := this.RPC().NodeRPC().FindEnabledNodeDNS(this.AdminContext(), &pb.FindEnabledNodeDNSRequest{
|
||||||
NodeId: params.NodeId,
|
NodeId: params.NodeId,
|
||||||
@@ -49,6 +51,13 @@ func (this *IndexAction) RunGet(params struct {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
var domainId = dnsInfo.DnsDomainId
|
var domainId = dnsInfo.DnsDomainId
|
||||||
|
|
||||||
|
// remove same domain
|
||||||
|
if lists.ContainsInt64(domainIds, domainId) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
domainIds = append(domainIds, domainId)
|
||||||
|
|
||||||
var domainName = dnsInfo.DnsDomainName
|
var domainName = dnsInfo.DnsDomainName
|
||||||
if len(dnsInfo.Routes) > 0 {
|
if len(dnsInfo.Routes) > 0 {
|
||||||
for _, route := range dnsInfo.Routes {
|
for _, route := range dnsInfo.Routes {
|
||||||
@@ -102,15 +111,23 @@ func (this *IndexAction) RunPost(params struct {
|
|||||||
}) {
|
}) {
|
||||||
defer this.CreateLogInfo(codes.NodeDNS_LogUpdateNodeDNS, params.NodeId)
|
defer this.CreateLogInfo(codes.NodeDNS_LogUpdateNodeDNS, params.NodeId)
|
||||||
|
|
||||||
dnsRouteCodes := []string{}
|
var rawRouteCodes = []string{}
|
||||||
if len(params.DnsRoutesJSON) > 0 {
|
if len(params.DnsRoutesJSON) > 0 {
|
||||||
err := json.Unmarshal(params.DnsRoutesJSON, &dnsRouteCodes)
|
err := json.Unmarshal(params.DnsRoutesJSON, &rawRouteCodes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
this.ErrorPage(err)
|
this.ErrorPage(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// remove duplications
|
||||||
|
var dnsRouteCodes = []string{}
|
||||||
|
for _, routeCode := range rawRouteCodes {
|
||||||
|
if !lists.ContainsString(dnsRouteCodes, routeCode) {
|
||||||
|
dnsRouteCodes = append(dnsRouteCodes, routeCode)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_, err := this.RPC().NodeRPC().UpdateNodeDNS(this.AdminContext(), &pb.UpdateNodeDNSRequest{
|
_, err := this.RPC().NodeRPC().UpdateNodeDNS(this.AdminContext(), &pb.UpdateNodeDNSRequest{
|
||||||
NodeId: params.NodeId,
|
NodeId: params.NodeId,
|
||||||
IpAddr: "",
|
IpAddr: "",
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ func (this *IndexAction) RunGet(params struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var grantMap = maps.Map{}
|
var grantMap = maps.Map{}
|
||||||
grantId := loginParams.GetInt64("grantId")
|
var grantId = loginParams.GetInt64("grantId")
|
||||||
if grantId > 0 {
|
if grantId > 0 {
|
||||||
grantResp, err := this.RPC().NodeGrantRPC().FindEnabledNodeGrant(this.AdminContext(), &pb.FindEnabledNodeGrantRequest{NodeGrantId: grantId})
|
grantResp, err := this.RPC().NodeGrantRPC().FindEnabledNodeGrant(this.AdminContext(), &pb.FindEnabledNodeGrantRequest{NodeGrantId: grantId})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -1,62 +0,0 @@
|
|||||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
|
||||||
|
|
||||||
package thresholds
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/cluster/node/nodeutils"
|
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
|
||||||
"github.com/iwind/TeaGo/maps"
|
|
||||||
)
|
|
||||||
|
|
||||||
type IndexAction struct {
|
|
||||||
actionutils.ParentAction
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *IndexAction) Init() {
|
|
||||||
this.Nav("", "node", "update")
|
|
||||||
this.SecondMenu("threshold")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *IndexAction) RunGet(params struct {
|
|
||||||
ClusterId int64
|
|
||||||
NodeId int64
|
|
||||||
}) {
|
|
||||||
_, err := nodeutils.InitNodeInfo(this.Parent(), params.NodeId)
|
|
||||||
if err != nil {
|
|
||||||
this.ErrorPage(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
this.Data["nodeId"] = params.NodeId
|
|
||||||
|
|
||||||
// 列出所有阈值
|
|
||||||
thresholdsResp, err := this.RPC().NodeThresholdRPC().FindAllEnabledNodeThresholds(this.AdminContext(), &pb.FindAllEnabledNodeThresholdsRequest{
|
|
||||||
Role: "node",
|
|
||||||
NodeClusterId: params.ClusterId,
|
|
||||||
NodeId: params.NodeId,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
this.ErrorPage(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
thresholdMaps := []maps.Map{}
|
|
||||||
for _, threshold := range thresholdsResp.NodeThresholds {
|
|
||||||
thresholdMaps = append(thresholdMaps, maps.Map{
|
|
||||||
"id": threshold.Id,
|
|
||||||
"itemName": nodeconfigs.FindNodeValueItemName(threshold.Item),
|
|
||||||
"paramName": nodeconfigs.FindNodeValueItemParamName(threshold.Item, threshold.Param),
|
|
||||||
"operatorName": nodeconfigs.FindNodeValueOperatorName(threshold.Operator),
|
|
||||||
"value": nodeconfigs.UnmarshalNodeValue(threshold.ValueJSON),
|
|
||||||
"sumMethodName": nodeconfigs.FindNodeValueSumMethodName(threshold.SumMethod),
|
|
||||||
"duration": threshold.Duration,
|
|
||||||
"durationUnitName": nodeconfigs.FindNodeValueDurationUnitName(threshold.DurationUnit),
|
|
||||||
"isOn": threshold.IsOn,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
this.Data["thresholds"] = thresholdMaps
|
|
||||||
|
|
||||||
this.Show()
|
|
||||||
}
|
|
||||||
@@ -14,7 +14,7 @@ type IndexAction struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (this *IndexAction) Init() {
|
func (this *IndexAction) Init() {
|
||||||
this.Nav("", "setting", "")
|
this.Nav("", "setting", "index")
|
||||||
this.SecondMenu("dns")
|
this.SecondMenu("dns")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,303 @@
|
|||||||
|
// Copyright 2023 GoEdge CDN goedge.cdn@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||||
|
|
||||||
|
package dns
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/utils"
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
|
"github.com/iwind/TeaGo/maps"
|
||||||
|
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type RecordsAction struct {
|
||||||
|
actionutils.ParentAction
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *RecordsAction) Init() {
|
||||||
|
this.Nav("", "setting", "records")
|
||||||
|
this.SecondMenu("dns")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *RecordsAction) RunGet(params struct {
|
||||||
|
ClusterId int64
|
||||||
|
}) {
|
||||||
|
// 集群信息
|
||||||
|
clusterResp, err := this.RPC().NodeClusterRPC().FindEnabledNodeCluster(this.AdminContext(), &pb.FindEnabledNodeClusterRequest{NodeClusterId: params.ClusterId})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var cluster = clusterResp.NodeCluster
|
||||||
|
if cluster == nil {
|
||||||
|
this.NotFound("nodeCluster", params.ClusterId)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.Data["cluster"] = maps.Map{
|
||||||
|
"id": cluster.Id,
|
||||||
|
"name": cluster.Name,
|
||||||
|
}
|
||||||
|
|
||||||
|
// DNS信息
|
||||||
|
dnsResp, err := this.RPC().NodeClusterRPC().FindEnabledNodeClusterDNS(this.AdminContext(), &pb.FindEnabledNodeClusterDNSRequest{NodeClusterId: params.ClusterId})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var defaultRoute = dnsResp.DefaultRoute
|
||||||
|
var domainName = ""
|
||||||
|
var dnsMap = maps.Map{
|
||||||
|
"dnsName": dnsResp.Name,
|
||||||
|
"domainId": 0,
|
||||||
|
"domainName": "",
|
||||||
|
"providerId": 0,
|
||||||
|
"providerName": "",
|
||||||
|
"providerTypeName": "",
|
||||||
|
}
|
||||||
|
if dnsResp.Domain != nil {
|
||||||
|
domainName = dnsResp.Domain.Name
|
||||||
|
dnsMap["domainId"] = dnsResp.Domain.Id
|
||||||
|
dnsMap["domainName"] = dnsResp.Domain.Name
|
||||||
|
}
|
||||||
|
if dnsResp.Provider != nil {
|
||||||
|
dnsMap["providerId"] = dnsResp.Provider.Id
|
||||||
|
dnsMap["providerName"] = dnsResp.Provider.Name
|
||||||
|
dnsMap["providerTypeName"] = dnsResp.Provider.TypeName
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(dnsResp.CnameRecords) > 0 {
|
||||||
|
dnsMap["cnameRecords"] = dnsResp.CnameRecords
|
||||||
|
} else {
|
||||||
|
dnsMap["cnameRecords"] = []string{}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Data["dnsInfo"] = dnsMap
|
||||||
|
|
||||||
|
// 未安装的节点
|
||||||
|
notInstalledNodesResp, err := this.RPC().NodeRPC().FindAllEnabledNodesDNSWithNodeClusterId(this.AdminContext(), &pb.FindAllEnabledNodesDNSWithNodeClusterIdRequest{
|
||||||
|
NodeClusterId: params.ClusterId,
|
||||||
|
IsInstalled: false,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var allNodes = notInstalledNodesResp.Nodes
|
||||||
|
|
||||||
|
// 节点DNS解析记录
|
||||||
|
nodesResp, err := this.RPC().NodeRPC().FindAllEnabledNodesDNSWithNodeClusterId(this.AdminContext(), &pb.FindAllEnabledNodesDNSWithNodeClusterIdRequest{
|
||||||
|
NodeClusterId: params.ClusterId,
|
||||||
|
IsInstalled: true,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var installedNodeIdsMap = map[int64]bool{}
|
||||||
|
for _, node := range nodesResp.Nodes {
|
||||||
|
installedNodeIdsMap[node.Id] = true
|
||||||
|
}
|
||||||
|
|
||||||
|
allNodes = append(allNodes, nodesResp.Nodes...)
|
||||||
|
|
||||||
|
var nodeMaps = []maps.Map{}
|
||||||
|
for _, node := range allNodes {
|
||||||
|
var isInstalled = installedNodeIdsMap[node.Id]
|
||||||
|
|
||||||
|
if len(node.Routes) > 0 {
|
||||||
|
for _, route := range node.Routes {
|
||||||
|
// 检查是否已解析
|
||||||
|
var isResolved = false
|
||||||
|
if isInstalled && cluster.DnsDomainId > 0 && len(cluster.DnsName) > 0 && len(node.IpAddr) > 0 {
|
||||||
|
var recordType = "A"
|
||||||
|
if utils.IsIPv6(node.IpAddr) {
|
||||||
|
recordType = "AAAA"
|
||||||
|
}
|
||||||
|
checkResp, err := this.RPC().DNSDomainRPC().ExistDNSDomainRecord(this.AdminContext(), &pb.ExistDNSDomainRecordRequest{
|
||||||
|
DnsDomainId: cluster.DnsDomainId,
|
||||||
|
Name: cluster.DnsName,
|
||||||
|
Type: recordType,
|
||||||
|
Route: route.Code,
|
||||||
|
Value: node.IpAddr,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
isResolved = checkResp.IsOk
|
||||||
|
}
|
||||||
|
|
||||||
|
nodeMaps = append(nodeMaps, maps.Map{
|
||||||
|
"id": node.Id,
|
||||||
|
"name": node.Name,
|
||||||
|
"ipAddr": node.IpAddr,
|
||||||
|
"ipAddrId": node.NodeIPAddressId,
|
||||||
|
"route": maps.Map{
|
||||||
|
"name": route.Name,
|
||||||
|
"code": route.Code,
|
||||||
|
},
|
||||||
|
"clusterId": node.NodeClusterId,
|
||||||
|
"isResolved": isResolved,
|
||||||
|
"isInstalled": isInstalled,
|
||||||
|
"isBackup": node.IsBackupForCluster || node.IsBackupForGroup,
|
||||||
|
"isOffline": node.IsOffline,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 默认线路
|
||||||
|
var isResolved = false
|
||||||
|
if isInstalled && len(defaultRoute) > 0 {
|
||||||
|
var recordType = "A"
|
||||||
|
if utils.IsIPv6(node.IpAddr) {
|
||||||
|
recordType = "AAAA"
|
||||||
|
}
|
||||||
|
checkResp, err := this.RPC().DNSDomainRPC().ExistDNSDomainRecord(this.AdminContext(), &pb.ExistDNSDomainRecordRequest{
|
||||||
|
DnsDomainId: cluster.DnsDomainId,
|
||||||
|
Name: cluster.DnsName,
|
||||||
|
Type: recordType,
|
||||||
|
Route: defaultRoute,
|
||||||
|
Value: node.IpAddr,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
isResolved = checkResp.IsOk
|
||||||
|
}
|
||||||
|
nodeMaps = append(nodeMaps, maps.Map{
|
||||||
|
"id": node.Id,
|
||||||
|
"name": node.Name,
|
||||||
|
"ipAddr": node.IpAddr,
|
||||||
|
"ipAddrId": node.NodeIPAddressId,
|
||||||
|
"route": maps.Map{
|
||||||
|
"name": "",
|
||||||
|
"code": "",
|
||||||
|
},
|
||||||
|
"clusterId": node.NodeClusterId,
|
||||||
|
"isResolved": isResolved,
|
||||||
|
"isInstalled": isInstalled,
|
||||||
|
"isBackup": node.IsBackupForCluster || node.IsBackupForGroup,
|
||||||
|
"isOffline": node.IsOffline,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.Data["nodes"] = nodeMaps
|
||||||
|
|
||||||
|
// 代理服务解析记录
|
||||||
|
serversResp, err := this.RPC().ServerRPC().FindAllEnabledServersDNSWithNodeClusterId(this.AdminContext(), &pb.FindAllEnabledServersDNSWithNodeClusterIdRequest{NodeClusterId: params.ClusterId})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var serverMaps = []maps.Map{}
|
||||||
|
for _, server := range serversResp.Servers {
|
||||||
|
// 检查是否已解析
|
||||||
|
isResolved := false
|
||||||
|
if cluster.DnsDomainId > 0 && len(cluster.DnsName) > 0 && len(server.DnsName) > 0 && len(domainName) > 0 {
|
||||||
|
checkResp, err := this.RPC().DNSDomainRPC().ExistDNSDomainRecord(this.AdminContext(), &pb.ExistDNSDomainRecordRequest{
|
||||||
|
DnsDomainId: cluster.DnsDomainId,
|
||||||
|
Name: server.DnsName,
|
||||||
|
Type: "CNAME",
|
||||||
|
Value: cluster.DnsName + "." + domainName,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
isResolved = checkResp.IsOk
|
||||||
|
}
|
||||||
|
|
||||||
|
serverMaps = append(serverMaps, maps.Map{
|
||||||
|
"id": server.Id,
|
||||||
|
"name": server.Name,
|
||||||
|
"dnsName": server.DnsName,
|
||||||
|
"isResolved": isResolved,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
this.Data["servers"] = serverMaps
|
||||||
|
|
||||||
|
// 检查解析记录是否有变化
|
||||||
|
checkChangesResp, err := this.RPC().NodeClusterRPC().CheckNodeClusterDNSChanges(this.AdminContext(), &pb.CheckNodeClusterDNSChangesRequest{NodeClusterId: params.ClusterId})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.Data["dnsHasChanges"] = checkChangesResp.IsChanged
|
||||||
|
|
||||||
|
// 需要解决的问题
|
||||||
|
issuesResp, err := this.RPC().DNSRPC().FindAllDNSIssues(this.AdminContext(), &pb.FindAllDNSIssuesRequest{
|
||||||
|
NodeClusterId: params.ClusterId,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var issueMaps = []maps.Map{}
|
||||||
|
for _, issue := range issuesResp.Issues {
|
||||||
|
issueMaps = append(issueMaps, maps.Map{
|
||||||
|
"target": issue.Target,
|
||||||
|
"targetId": issue.TargetId,
|
||||||
|
"type": issue.Type,
|
||||||
|
"description": issue.Description,
|
||||||
|
"params": issue.Params,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
this.Data["issues"] = issueMaps
|
||||||
|
|
||||||
|
// 当前正在执行的任务
|
||||||
|
resp, err := this.RPC().DNSTaskRPC().FindAllDoingDNSTasks(this.AdminContext(), &pb.FindAllDoingDNSTasksRequest{
|
||||||
|
NodeClusterId: params.ClusterId,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var taskMaps = []maps.Map{}
|
||||||
|
for _, task := range resp.DnsTasks {
|
||||||
|
var clusterMap maps.Map = nil
|
||||||
|
var nodeMap maps.Map = nil
|
||||||
|
var serverMap maps.Map = nil
|
||||||
|
var domainMap maps.Map = nil
|
||||||
|
|
||||||
|
if task.NodeCluster != nil {
|
||||||
|
clusterMap = maps.Map{
|
||||||
|
"id": task.NodeCluster.Id,
|
||||||
|
"name": task.NodeCluster.Name,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if task.Node != nil {
|
||||||
|
nodeMap = maps.Map{
|
||||||
|
"id": task.Node.Id,
|
||||||
|
"name": task.Node.Name,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if task.Server != nil {
|
||||||
|
serverMap = maps.Map{
|
||||||
|
"id": task.Server.Id,
|
||||||
|
"name": task.Server.Name,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if task.DnsDomain != nil {
|
||||||
|
domainMap = maps.Map{
|
||||||
|
"id": task.DnsDomain.Id,
|
||||||
|
"name": task.DnsDomain.Name,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
taskMaps = append(taskMaps, maps.Map{
|
||||||
|
"id": task.Id,
|
||||||
|
"type": task.Type,
|
||||||
|
"isDone": task.IsDone,
|
||||||
|
"isOk": task.IsOk,
|
||||||
|
"error": task.Error,
|
||||||
|
"updatedTime": timeutil.FormatTime("Y-m-d H:i:s", task.UpdatedAt),
|
||||||
|
"cluster": clusterMap,
|
||||||
|
"node": nodeMap,
|
||||||
|
"server": serverMap,
|
||||||
|
"domain": domainMap,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
this.Data["tasks"] = taskMaps
|
||||||
|
|
||||||
|
this.Show()
|
||||||
|
}
|
||||||
@@ -10,6 +10,8 @@ import (
|
|||||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||||
"github.com/iwind/TeaGo/actions"
|
"github.com/iwind/TeaGo/actions"
|
||||||
"github.com/iwind/TeaGo/maps"
|
"github.com/iwind/TeaGo/maps"
|
||||||
|
"github.com/iwind/TeaGo/types"
|
||||||
|
"regexp"
|
||||||
)
|
)
|
||||||
|
|
||||||
type IndexAction struct {
|
type IndexAction struct {
|
||||||
@@ -41,9 +43,20 @@ func (this *IndexAction) RunGet(params struct {
|
|||||||
}
|
}
|
||||||
this.Data["config"] = config
|
this.Data["config"] = config
|
||||||
|
|
||||||
var httpAllDomainMismatchActionContentHTML = ""
|
var httpAllDomainMismatchActionCode = serverconfigs.DomainMismatchActionPage
|
||||||
|
var httpAllDomainMismatchActionContentHTML string
|
||||||
|
var httpAllDomainMismatchActionStatusCode = "404"
|
||||||
if config.HTTPAll.DomainMismatchAction != nil {
|
if config.HTTPAll.DomainMismatchAction != nil {
|
||||||
httpAllDomainMismatchActionContentHTML = config.HTTPAll.DomainMismatchAction.Options.GetString("contentHTML")
|
httpAllDomainMismatchActionCode = config.HTTPAll.DomainMismatchAction.Code
|
||||||
|
|
||||||
|
if config.HTTPAll.DomainMismatchAction.Options != nil {
|
||||||
|
// 即使是非 page 处理动作,也读取这些内容,以便于在切换到 page 时,可以顺利读取到先前的设置
|
||||||
|
httpAllDomainMismatchActionContentHTML = config.HTTPAll.DomainMismatchAction.Options.GetString("contentHTML")
|
||||||
|
var statusCode = config.HTTPAll.DomainMismatchAction.Options.GetInt("statusCode")
|
||||||
|
if statusCode > 0 {
|
||||||
|
httpAllDomainMismatchActionStatusCode = types.String(statusCode)
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
httpAllDomainMismatchActionContentHTML = `<!DOCTYPE html>
|
httpAllDomainMismatchActionContentHTML = `<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
@@ -66,7 +79,9 @@ p { color: grey; }
|
|||||||
</html>`
|
</html>`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.Data["httpAllDomainMismatchActionCode"] = httpAllDomainMismatchActionCode
|
||||||
this.Data["httpAllDomainMismatchActionContentHTML"] = httpAllDomainMismatchActionContentHTML
|
this.Data["httpAllDomainMismatchActionContentHTML"] = httpAllDomainMismatchActionContentHTML
|
||||||
|
this.Data["httpAllDomainMismatchActionStatusCode"] = httpAllDomainMismatchActionStatusCode
|
||||||
|
|
||||||
this.Show()
|
this.Show()
|
||||||
}
|
}
|
||||||
@@ -75,17 +90,24 @@ func (this *IndexAction) RunPost(params struct {
|
|||||||
ClusterId int64
|
ClusterId int64
|
||||||
|
|
||||||
HttpAllMatchDomainStrictly bool
|
HttpAllMatchDomainStrictly bool
|
||||||
|
HttpAllDomainMismatchActionCode string
|
||||||
HttpAllDomainMismatchActionContentHTML string
|
HttpAllDomainMismatchActionContentHTML string
|
||||||
|
HttpAllDomainMismatchActionStatusCode string
|
||||||
HttpAllAllowMismatchDomainsJSON []byte
|
HttpAllAllowMismatchDomainsJSON []byte
|
||||||
HttpAllAllowNodeIP bool
|
HttpAllAllowNodeIP bool
|
||||||
HttpAllDefaultDomain string
|
HttpAllDefaultDomain string
|
||||||
HttpAllNodeIPPageHTML string
|
HttpAllNodeIPPageHTML string
|
||||||
HttpAllNodeIPShowPage bool
|
HttpAllNodeIPShowPage bool
|
||||||
|
HttpAllEnableServerAddrVariable bool
|
||||||
|
|
||||||
HttpAllServerName string
|
HttpAllDomainAuditingIsOn bool
|
||||||
HttpAllSupportsLowVersionHTTP bool
|
HttpAllDomainAuditingPrompt string
|
||||||
HttpAllMatchCertFromAllServers bool
|
|
||||||
HttpAllForceLnRequest bool
|
HttpAllServerName string
|
||||||
|
HttpAllSupportsLowVersionHTTP bool
|
||||||
|
HttpAllMatchCertFromAllServers bool
|
||||||
|
HttpAllForceLnRequest bool
|
||||||
|
HttpAllLnRequestSchedulingMethod string
|
||||||
|
|
||||||
HttpAccessLogIsOn bool
|
HttpAccessLogIsOn bool
|
||||||
HttpAccessLogEnableRequestHeaders bool
|
HttpAccessLogEnableRequestHeaders bool
|
||||||
@@ -100,6 +122,11 @@ func (this *IndexAction) RunPost(params struct {
|
|||||||
PerformanceAutoWriteTimeout bool
|
PerformanceAutoWriteTimeout bool
|
||||||
PerformanceDebug bool
|
PerformanceDebug bool
|
||||||
|
|
||||||
|
// TCP端口设置
|
||||||
|
TcpAllPortRangeMin int
|
||||||
|
TcpAllPortRangeMax int
|
||||||
|
TcpAllDenyPorts []int
|
||||||
|
|
||||||
Must *actions.Must
|
Must *actions.Must
|
||||||
CSRF *actionutils.CSRF
|
CSRF *actionutils.CSRF
|
||||||
}) {
|
}) {
|
||||||
@@ -121,11 +148,18 @@ func (this *IndexAction) RunPost(params struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var domainMisMatchStatusCodeString = params.HttpAllDomainMismatchActionStatusCode
|
||||||
|
if !regexp.MustCompile(`^\d{3}$`).MatchString(domainMisMatchStatusCodeString) {
|
||||||
|
this.FailField("httpAllDomainMismatchActionContentStatusCode", "请输入正确的状态码")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var domainMisMatchStatusCode = types.Int(domainMisMatchStatusCodeString)
|
||||||
|
|
||||||
config.HTTPAll.MatchDomainStrictly = params.HttpAllMatchDomainStrictly
|
config.HTTPAll.MatchDomainStrictly = params.HttpAllMatchDomainStrictly
|
||||||
config.HTTPAll.DomainMismatchAction = &serverconfigs.DomainMismatchAction{
|
config.HTTPAll.DomainMismatchAction = &serverconfigs.DomainMismatchAction{
|
||||||
Code: serverconfigs.DomainMismatchActionPage,
|
Code: params.HttpAllDomainMismatchActionCode,
|
||||||
Options: maps.Map{
|
Options: maps.Map{
|
||||||
"statusCode": 404,
|
"statusCode": domainMisMatchStatusCode,
|
||||||
"contentHTML": params.HttpAllDomainMismatchActionContentHTML,
|
"contentHTML": params.HttpAllDomainMismatchActionContentHTML,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -146,11 +180,16 @@ func (this *IndexAction) RunPost(params struct {
|
|||||||
config.HTTPAll.NodeIPShowPage = params.HttpAllNodeIPShowPage
|
config.HTTPAll.NodeIPShowPage = params.HttpAllNodeIPShowPage
|
||||||
config.HTTPAll.NodeIPPageHTML = params.HttpAllNodeIPPageHTML
|
config.HTTPAll.NodeIPPageHTML = params.HttpAllNodeIPPageHTML
|
||||||
|
|
||||||
|
config.HTTPAll.DomainAuditingIsOn = params.HttpAllDomainAuditingIsOn
|
||||||
|
config.HTTPAll.DomainAuditingPrompt = params.HttpAllDomainAuditingPrompt
|
||||||
|
|
||||||
// HTTP All
|
// HTTP All
|
||||||
config.HTTPAll.ServerName = params.HttpAllServerName
|
config.HTTPAll.ServerName = params.HttpAllServerName
|
||||||
config.HTTPAll.SupportsLowVersionHTTP = params.HttpAllSupportsLowVersionHTTP
|
config.HTTPAll.SupportsLowVersionHTTP = params.HttpAllSupportsLowVersionHTTP
|
||||||
config.HTTPAll.MatchCertFromAllServers = params.HttpAllMatchCertFromAllServers
|
config.HTTPAll.MatchCertFromAllServers = params.HttpAllMatchCertFromAllServers
|
||||||
config.HTTPAll.ForceLnRequest = params.HttpAllForceLnRequest
|
config.HTTPAll.ForceLnRequest = params.HttpAllForceLnRequest
|
||||||
|
config.HTTPAll.LnRequestSchedulingMethod = params.HttpAllLnRequestSchedulingMethod
|
||||||
|
config.HTTPAll.EnableServerAddrVariable = params.HttpAllEnableServerAddrVariable
|
||||||
|
|
||||||
// 访问日志
|
// 访问日志
|
||||||
config.HTTPAccessLog.IsOn = params.HttpAccessLogIsOn
|
config.HTTPAccessLog.IsOn = params.HttpAccessLogIsOn
|
||||||
@@ -163,6 +202,23 @@ func (this *IndexAction) RunPost(params struct {
|
|||||||
// 日志
|
// 日志
|
||||||
config.Log.RecordServerError = params.LogRecordServerError
|
config.Log.RecordServerError = params.LogRecordServerError
|
||||||
|
|
||||||
|
// TCP
|
||||||
|
if params.TcpAllPortRangeMin < 1024 {
|
||||||
|
params.TcpAllPortRangeMin = 1024
|
||||||
|
}
|
||||||
|
if params.TcpAllPortRangeMax > 65534 {
|
||||||
|
params.TcpAllPortRangeMax = 65534
|
||||||
|
} else if params.TcpAllPortRangeMax < 1024 {
|
||||||
|
params.TcpAllPortRangeMax = 1024
|
||||||
|
}
|
||||||
|
if params.TcpAllPortRangeMin > params.TcpAllPortRangeMax {
|
||||||
|
params.TcpAllPortRangeMin, params.TcpAllPortRangeMax = params.TcpAllPortRangeMax, params.TcpAllPortRangeMin
|
||||||
|
}
|
||||||
|
|
||||||
|
config.TCPAll.DenyPorts = params.TcpAllDenyPorts
|
||||||
|
config.TCPAll.PortRangeMin = params.TcpAllPortRangeMin
|
||||||
|
config.TCPAll.PortRangeMax = params.TcpAllPortRangeMax
|
||||||
|
|
||||||
// 性能
|
// 性能
|
||||||
config.Performance.AutoReadTimeout = params.PerformanceAutoReadTimeout
|
config.Performance.AutoReadTimeout = params.PerformanceAutoReadTimeout
|
||||||
config.Performance.AutoWriteTimeout = params.PerformanceAutoWriteTimeout
|
config.Performance.AutoWriteTimeout = params.PerformanceAutoWriteTimeout
|
||||||
|
|||||||
@@ -112,6 +112,7 @@ func (this *IndexAction) RunGet(params struct {
|
|||||||
"clock": clockConfig,
|
"clock": clockConfig,
|
||||||
"autoRemoteStart": cluster.AutoRemoteStart,
|
"autoRemoteStart": cluster.AutoRemoteStart,
|
||||||
"autoInstallNftables": cluster.AutoInstallNftables,
|
"autoInstallNftables": cluster.AutoInstallNftables,
|
||||||
|
"autoSystemTuning": cluster.AutoSystemTuning,
|
||||||
"sshParams": sshParams,
|
"sshParams": sshParams,
|
||||||
"domainName": fullDomainName,
|
"domainName": fullDomainName,
|
||||||
}
|
}
|
||||||
@@ -139,6 +140,7 @@ func (this *IndexAction) RunPost(params struct {
|
|||||||
ClockCheckChrony bool
|
ClockCheckChrony bool
|
||||||
AutoRemoteStart bool
|
AutoRemoteStart bool
|
||||||
AutoInstallNftables bool
|
AutoInstallNftables bool
|
||||||
|
AutoSystemTuning bool
|
||||||
|
|
||||||
Must *actions.Must
|
Must *actions.Must
|
||||||
}) {
|
}) {
|
||||||
@@ -193,6 +195,7 @@ func (this *IndexAction) RunPost(params struct {
|
|||||||
ClockJSON: clockConfigJSON,
|
ClockJSON: clockConfigJSON,
|
||||||
AutoRemoteStart: params.AutoRemoteStart,
|
AutoRemoteStart: params.AutoRemoteStart,
|
||||||
AutoInstallNftables: params.AutoInstallNftables,
|
AutoInstallNftables: params.AutoInstallNftables,
|
||||||
|
AutoSystemTuning: params.AutoSystemTuning,
|
||||||
SshParamsJSON: sshParamsJSON,
|
SshParamsJSON: sshParamsJSON,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ import (
|
|||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/cluster/settings/health"
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/cluster/settings/health"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/cluster/settings/metrics"
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/cluster/settings/metrics"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/cluster/settings/services"
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/cluster/settings/services"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/cluster/settings/toa"
|
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/cluster/settings/waf"
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/cluster/settings/waf"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/cluster/settings/webp"
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/cluster/settings/webp"
|
||||||
clusters "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/clusterutils"
|
clusters "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/clusterutils"
|
||||||
@@ -41,12 +40,9 @@ func init() {
|
|||||||
// DNS
|
// DNS
|
||||||
Prefix("/clusters/cluster/settings/dns").
|
Prefix("/clusters/cluster/settings/dns").
|
||||||
GetPost("", new(dns.IndexAction)).
|
GetPost("", new(dns.IndexAction)).
|
||||||
|
Get("/records", new(dns.RecordsAction)).
|
||||||
Post("/randomName", new(dns.RandomNameAction)).
|
Post("/randomName", new(dns.RandomNameAction)).
|
||||||
|
|
||||||
// TOA
|
|
||||||
Prefix("/clusters/cluster/settings/toa").
|
|
||||||
GetPost("", new(toa.IndexAction)).
|
|
||||||
|
|
||||||
// 系统服务设置
|
// 系统服务设置
|
||||||
Prefix("/clusters/cluster/settings/services").
|
Prefix("/clusters/cluster/settings/services").
|
||||||
GetPost("", new(services.IndexAction)).
|
GetPost("", new(services.IndexAction)).
|
||||||
|
|||||||
@@ -1,83 +0,0 @@
|
|||||||
package toa
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
|
||||||
"github.com/iwind/TeaGo/actions"
|
|
||||||
)
|
|
||||||
|
|
||||||
type IndexAction struct {
|
|
||||||
actionutils.ParentAction
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *IndexAction) Init() {
|
|
||||||
this.Nav("", "setting", "")
|
|
||||||
this.SecondMenu("toa")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *IndexAction) RunGet(params struct {
|
|
||||||
ClusterId int64
|
|
||||||
}) {
|
|
||||||
toaResp, err := this.RPC().NodeClusterRPC().FindEnabledNodeClusterTOA(this.AdminContext(), &pb.FindEnabledNodeClusterTOARequest{NodeClusterId: params.ClusterId})
|
|
||||||
if err != nil {
|
|
||||||
this.ErrorPage(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if len(toaResp.ToaJSON) == 0 {
|
|
||||||
this.Data["toa"] = nodeconfigs.DefaultTOAConfig()
|
|
||||||
} else {
|
|
||||||
config := &nodeconfigs.TOAConfig{}
|
|
||||||
err = json.Unmarshal(toaResp.ToaJSON, config)
|
|
||||||
if err != nil {
|
|
||||||
this.ErrorPage(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
this.Data["toa"] = config
|
|
||||||
}
|
|
||||||
|
|
||||||
this.Show()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *IndexAction) RunPost(params struct {
|
|
||||||
ClusterId int64
|
|
||||||
IsOn bool
|
|
||||||
AutoSetup bool
|
|
||||||
OptionType uint8
|
|
||||||
MinQueueId uint8
|
|
||||||
MaxQueueId uint8
|
|
||||||
|
|
||||||
Must *actions.Must
|
|
||||||
CSRF *actionutils.CSRF
|
|
||||||
}) {
|
|
||||||
defer this.CreateLogInfo(codes.NodeTOA_LogUpdateClusterTOA, params.ClusterId)
|
|
||||||
|
|
||||||
config := &nodeconfigs.TOAConfig{
|
|
||||||
IsOn: params.IsOn,
|
|
||||||
Debug: false, // 暂时不允许打开调试
|
|
||||||
OptionType: params.OptionType,
|
|
||||||
MinQueueId: params.MinQueueId,
|
|
||||||
MaxQueueId: params.MaxQueueId,
|
|
||||||
AutoSetup: params.AutoSetup,
|
|
||||||
}
|
|
||||||
|
|
||||||
configJSON, err := json.Marshal(config)
|
|
||||||
if err != nil {
|
|
||||||
this.ErrorPage(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = this.RPC().NodeClusterRPC().UpdateNodeClusterTOA(this.AdminContext(), &pb.UpdateNodeClusterTOARequest{
|
|
||||||
NodeClusterId: params.ClusterId,
|
|
||||||
ToaJSON: configJSON,
|
|
||||||
})
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
this.ErrorPage(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
this.Success()
|
|
||||||
}
|
|
||||||
@@ -64,6 +64,7 @@ func (this *CreateAction) RunPost(params struct {
|
|||||||
InstallDir string
|
InstallDir string
|
||||||
SystemdServiceIsOn bool
|
SystemdServiceIsOn bool
|
||||||
AutoInstallNftables bool
|
AutoInstallNftables bool
|
||||||
|
AutoSystemTuning bool
|
||||||
|
|
||||||
// DNS相关
|
// DNS相关
|
||||||
DnsDomainId int64
|
DnsDomainId int64
|
||||||
@@ -132,6 +133,7 @@ func (this *CreateAction) RunPost(params struct {
|
|||||||
SystemServicesJSON: systemServicesJSON,
|
SystemServicesJSON: systemServicesJSON,
|
||||||
GlobalServerConfigJSON: globalServerConfigJSON,
|
GlobalServerConfigJSON: globalServerConfigJSON,
|
||||||
AutoInstallNftables: params.AutoInstallNftables,
|
AutoInstallNftables: params.AutoInstallNftables,
|
||||||
|
AutoSystemTuning: params.AutoSystemTuning,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
this.ErrorPage(err)
|
this.ErrorPage(err)
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
teaconst "github.com/TeaOSLab/EdgeAdmin/internal/const"
|
teaconst "github.com/TeaOSLab/EdgeAdmin/internal/const"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/rpc"
|
"github.com/TeaOSLab/EdgeAdmin/internal/rpc"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/utils/sizes"
|
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
"github.com/iwind/TeaGo/lists"
|
"github.com/iwind/TeaGo/lists"
|
||||||
@@ -19,6 +18,7 @@ import (
|
|||||||
"os/exec"
|
"os/exec"
|
||||||
"regexp"
|
"regexp"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CheckDiskPartitions 检查服务器磁盘空间
|
// CheckDiskPartitions 检查服务器磁盘空间
|
||||||
@@ -47,9 +47,17 @@ func CheckDiskPartitions(thresholdPercent float64) (path string, usage uint64, u
|
|||||||
if p.Fstype != rootFS {
|
if p.Fstype != rootFS {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// skip some specified partitions on macOS
|
||||||
|
if runtime.GOOS == "darwin" {
|
||||||
|
if strings.Contains(p.Mountpoint, "/Developer/") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
stat, _ := disk.Usage(p.Mountpoint)
|
stat, _ := disk.Usage(p.Mountpoint)
|
||||||
if stat != nil {
|
if stat != nil {
|
||||||
if stat.Used < 2*uint64(sizes.G) {
|
if stat.Used < (5<<30) || stat.Free > (100<<30) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if stat.UsedPercent > thresholdPercent {
|
if stat.UsedPercent > thresholdPercent {
|
||||||
|
|||||||
@@ -154,17 +154,6 @@ func (this *IndexAction) RunPost(params struct{}) {
|
|||||||
"version": "",
|
"version": "",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if resp.MonitorNodeUpgradeInfo != nil {
|
|
||||||
this.Data["monitorNodeUpgradeInfo"] = maps.Map{
|
|
||||||
"count": resp.MonitorNodeUpgradeInfo.CountNodes,
|
|
||||||
"version": resp.MonitorNodeUpgradeInfo.NewVersion,
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.Data["monitorNodeUpgradeInfo"] = maps.Map{
|
|
||||||
"count": 0,
|
|
||||||
"version": "",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if resp.ApiNodeUpgradeInfo != nil {
|
if resp.ApiNodeUpgradeInfo != nil {
|
||||||
this.Data["apiNodeUpgradeInfo"] = maps.Map{
|
this.Data["apiNodeUpgradeInfo"] = maps.Map{
|
||||||
"count": resp.ApiNodeUpgradeInfo.CountNodes,
|
"count": resp.ApiNodeUpgradeInfo.CountNodes,
|
||||||
@@ -176,39 +165,6 @@ func (this *IndexAction) RunPost(params struct{}) {
|
|||||||
"version": "",
|
"version": "",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if resp.UserNodeUpgradeInfo != nil {
|
|
||||||
this.Data["userNodeUpgradeInfo"] = maps.Map{
|
|
||||||
"count": resp.UserNodeUpgradeInfo.CountNodes,
|
|
||||||
"version": resp.UserNodeUpgradeInfo.NewVersion,
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.Data["userNodeUpgradeInfo"] = maps.Map{
|
|
||||||
"count": 0,
|
|
||||||
"version": 0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if resp.AuthorityNodeUpgradeInfo != nil {
|
|
||||||
this.Data["authorityNodeUpgradeInfo"] = maps.Map{
|
|
||||||
"count": resp.AuthorityNodeUpgradeInfo.CountNodes,
|
|
||||||
"version": resp.AuthorityNodeUpgradeInfo.NewVersion,
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.Data["authorityNodeUpgradeInfo"] = maps.Map{
|
|
||||||
"count": 0,
|
|
||||||
"version": "",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if resp.NsNodeUpgradeInfo != nil {
|
|
||||||
this.Data["nsNodeUpgradeInfo"] = maps.Map{
|
|
||||||
"count": resp.NsNodeUpgradeInfo.CountNodes,
|
|
||||||
"version": resp.NsNodeUpgradeInfo.NewVersion,
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.Data["nsNodeUpgradeInfo"] = maps.Map{
|
|
||||||
"count": 0,
|
|
||||||
"version": "",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 域名排行
|
// 域名排行
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ func (this *Helper) BeforeAction(action *actions.ActionObject) {
|
|||||||
|
|
||||||
action.Data["teaMenu"] = "db"
|
action.Data["teaMenu"] = "db"
|
||||||
|
|
||||||
selectedTabbar, _ := action.Data["mainTab"]
|
var selectedTabbar = action.Data["mainTab"]
|
||||||
|
|
||||||
var tabbar = actionutils.NewTabbar()
|
var tabbar = actionutils.NewTabbar()
|
||||||
tabbar.Add(this.Lang(action, codes.DBNode_TabNodes), "", "/db", "", selectedTabbar == "db")
|
tabbar.Add(this.Lang(action, codes.DBNode_TabNodes), "", "/db", "", selectedTabbar == "db")
|
||||||
|
|||||||
@@ -63,6 +63,10 @@ func (this *LogsAction) RunGet(params struct {
|
|||||||
Offset: page.Offset,
|
Offset: page.Offset,
|
||||||
Size: page.Size,
|
Size: page.Size,
|
||||||
})
|
})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
logs := []maps.Map{}
|
logs := []maps.Map{}
|
||||||
for _, log := range logsResp.NodeLogs {
|
for _, log := range logsResp.NodeLogs {
|
||||||
|
|||||||
@@ -101,9 +101,7 @@ func ValidateRecordValue(recordType dnsconfigs.RecordType, value string) (messag
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
case dnsconfigs.RecordTypeCNAME:
|
case dnsconfigs.RecordTypeCNAME:
|
||||||
if strings.HasSuffix(value, ".") {
|
value = strings.TrimSuffix(value, ".")
|
||||||
value = value[:len(value)-1]
|
|
||||||
}
|
|
||||||
if !strings.Contains(value, ".") || !ValidateDomainFormat(value) {
|
if !strings.Contains(value, ".") || !ValidateDomainFormat(value) {
|
||||||
message = "请输入正确的域名"
|
message = "请输入正确的域名"
|
||||||
return
|
return
|
||||||
@@ -118,17 +116,13 @@ func ValidateRecordValue(recordType dnsconfigs.RecordType, value string) (messag
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
case dnsconfigs.RecordTypeNS:
|
case dnsconfigs.RecordTypeNS:
|
||||||
if strings.HasSuffix(value, ".") {
|
value = strings.TrimSuffix(value, ".")
|
||||||
value = value[:len(value)-1]
|
|
||||||
}
|
|
||||||
if !strings.Contains(value, ".") || !ValidateDomainFormat(value) {
|
if !strings.Contains(value, ".") || !ValidateDomainFormat(value) {
|
||||||
message = "请输入正确的DNS服务器域名"
|
message = "请输入正确的DNS服务器域名"
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
case dnsconfigs.RecordTypeMX:
|
case dnsconfigs.RecordTypeMX:
|
||||||
if strings.HasSuffix(value, ".") {
|
value = strings.TrimSuffix(value, ".")
|
||||||
value = value[:len(value)-1]
|
|
||||||
}
|
|
||||||
if !strings.Contains(value, ".") || !ValidateDomainFormat(value) {
|
if !strings.Contains(value, ".") || !ValidateDomainFormat(value) {
|
||||||
message = "请输入正确的邮件服务器域名"
|
message = "请输入正确的邮件服务器域名"
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ func (this *IndexAction) RunGet(params struct {
|
|||||||
|
|
||||||
// 格式化域名
|
// 格式化域名
|
||||||
var domain = params.Domain
|
var domain = params.Domain
|
||||||
domain = regexp.MustCompile(`^(www\.)`).ReplaceAllString(params.Domain, "")
|
domain = regexp.MustCompile(`^(www\.)`).ReplaceAllString(domain, "")
|
||||||
domain = strings.ToLower(domain)
|
domain = strings.ToLower(domain)
|
||||||
|
|
||||||
countResp, err := this.RPC().DNSProviderRPC().CountAllEnabledDNSProviders(this.AdminContext(), &pb.CountAllEnabledDNSProvidersRequest{
|
countResp, err := this.RPC().DNSProviderRPC().CountAllEnabledDNSProviders(this.AdminContext(), &pb.CountAllEnabledDNSProvidersRequest{
|
||||||
|
|||||||
@@ -57,6 +57,6 @@ func (this *FileAction) RunGet(params struct {
|
|||||||
if chunkResp.FileChunk == nil {
|
if chunkResp.FileChunk == nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
this.Write(chunkResp.FileChunk.Data)
|
_, _ = this.Write(chunkResp.FileChunk.Data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,11 +3,11 @@ package log
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/iplibrary"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||||
"github.com/tealeg/xlsx/v3"
|
"github.com/tealeg/xlsx/v3"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type ExportExcelAction struct {
|
type ExportExcelAction struct {
|
||||||
@@ -65,23 +65,11 @@ func (this *ExportExcelAction) RunGet(params struct {
|
|||||||
for _, log := range logsResp.Logs {
|
for _, log := range logsResp.Logs {
|
||||||
var regionName = ""
|
var regionName = ""
|
||||||
var ispName = ""
|
var ispName = ""
|
||||||
regionResp, err := this.RPC().IPLibraryRPC().LookupIPRegion(this.AdminContext(), &pb.LookupIPRegionRequest{Ip: log.Ip})
|
|
||||||
if err != nil {
|
|
||||||
this.ErrorPage(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if regionResp.IpRegion != nil {
|
|
||||||
regionName = regionResp.IpRegion.Summary
|
|
||||||
|
|
||||||
// remove isp from regionName
|
var ipRegion = iplibrary.LookupIP(log.Ip)
|
||||||
var index = strings.LastIndex(regionName, "|")
|
if ipRegion != nil && ipRegion.IsOk() {
|
||||||
if index > 0 {
|
regionName = ipRegion.RegionSummary()
|
||||||
regionName = regionName[:index]
|
ispName = ipRegion.ProviderName()
|
||||||
}
|
|
||||||
|
|
||||||
if len(regionResp.IpRegion.Isp) > 0 {
|
|
||||||
ispName = regionResp.IpRegion.Isp
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var row = sheet.AddRow()
|
var row = sheet.AddRow()
|
||||||
@@ -123,5 +111,5 @@ func (this *ExportExcelAction) RunGet(params struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.AddHeader("Content-Length", strconv.Itoa(buf.Len()))
|
this.AddHeader("Content-Length", strconv.Itoa(buf.Len()))
|
||||||
this.Write(buf.Bytes())
|
_, _ = this.Write(buf.Bytes())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package log
|
|||||||
import (
|
import (
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
|
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/iplibrary"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
"github.com/iwind/TeaGo/maps"
|
"github.com/iwind/TeaGo/maps"
|
||||||
@@ -84,14 +85,10 @@ func (this *IndexAction) RunGet(params struct {
|
|||||||
}
|
}
|
||||||
var logMaps = []maps.Map{}
|
var logMaps = []maps.Map{}
|
||||||
for _, log := range logsResp.Logs {
|
for _, log := range logsResp.Logs {
|
||||||
regionName := ""
|
var regionName = ""
|
||||||
regionResp, err := this.RPC().IPLibraryRPC().LookupIPRegion(this.AdminContext(), &pb.LookupIPRegionRequest{Ip: log.Ip})
|
var ipRegion = iplibrary.LookupIP(log.Ip)
|
||||||
if err != nil {
|
if ipRegion != nil && ipRegion.IsOk() {
|
||||||
this.ErrorPage(err)
|
regionName = ipRegion.Summary()
|
||||||
return
|
|
||||||
}
|
|
||||||
if regionResp.IpRegion != nil {
|
|
||||||
regionName = regionResp.IpRegion.Summary
|
|
||||||
}
|
}
|
||||||
|
|
||||||
logMaps = append(logMaps, maps.Map{
|
logMaps = append(logMaps, maps.Map{
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ func UpdateNodeIPAddresses(parentAction *actionutils.ParentAction, nodeId int64,
|
|||||||
if addrId > 0 {
|
if addrId > 0 {
|
||||||
resultAddrIds = append(resultAddrIds, addrId)
|
resultAddrIds = append(resultAddrIds, addrId)
|
||||||
|
|
||||||
var isOn = false
|
var isOn bool
|
||||||
if !addr.Has("isOn") { // 兼容老版本
|
if !addr.Has("isOn") { // 兼容老版本
|
||||||
isOn = true
|
isOn = true
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -101,14 +101,9 @@ func SendMessageToCluster(ctx context.Context, clusterId int64, code string, msg
|
|||||||
apiNode := apiNodeResp.ApiNode
|
apiNode := apiNodeResp.ApiNode
|
||||||
|
|
||||||
apiRPCClient, err := rpc.NewRPCClient(&configs.APIConfig{
|
apiRPCClient, err := rpc.NewRPCClient(&configs.APIConfig{
|
||||||
RPC: struct {
|
RPCEndpoints: apiNode.AccessAddrs,
|
||||||
Endpoints []string `yaml:"endpoints"`
|
NodeId: apiNode.UniqueId,
|
||||||
DisableUpdate bool `yaml:"disableUpdate"`
|
Secret: apiNode.Secret,
|
||||||
}{
|
|
||||||
Endpoints: apiNode.AccessAddrs,
|
|
||||||
},
|
|
||||||
NodeId: apiNode.UniqueId,
|
|
||||||
Secret: apiNode.Secret,
|
|
||||||
}, false)
|
}, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
locker.Lock()
|
locker.Lock()
|
||||||
@@ -282,14 +277,9 @@ func SendMessageToNodeIds(ctx context.Context, nodeIds []int64, code string, msg
|
|||||||
apiNode := apiNodeResp.ApiNode
|
apiNode := apiNodeResp.ApiNode
|
||||||
|
|
||||||
apiRPCClient, err := rpc.NewRPCClient(&configs.APIConfig{
|
apiRPCClient, err := rpc.NewRPCClient(&configs.APIConfig{
|
||||||
RPC: struct {
|
RPCEndpoints: apiNode.AccessAddrs,
|
||||||
Endpoints []string `yaml:"endpoints"`
|
NodeId: apiNode.UniqueId,
|
||||||
DisableUpdate bool `yaml:"disableUpdate"`
|
Secret: apiNode.Secret,
|
||||||
}{
|
|
||||||
Endpoints: apiNode.AccessAddrs,
|
|
||||||
},
|
|
||||||
NodeId: apiNode.UniqueId,
|
|
||||||
Secret: apiNode.Secret,
|
|
||||||
}, false)
|
}, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
locker.Lock()
|
locker.Lock()
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
package recover
|
package recovers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
teaconst "github.com/TeaOSLab/EdgeAdmin/internal/const"
|
teaconst "github.com/TeaOSLab/EdgeAdmin/internal/const"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||||
|
|
||||||
package recover
|
package recovers
|
||||||
|
|
||||||
import "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
import "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
package recover
|
package recovers
|
||||||
|
|
||||||
import "github.com/iwind/TeaGo"
|
import "github.com/iwind/TeaGo"
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||||
|
|
||||||
package recover
|
package recovers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
@@ -35,14 +35,9 @@ func (this *UpdateHostsAction) RunPost(params struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
client, err := rpc.NewRPCClient(&configs.APIConfig{
|
client, err := rpc.NewRPCClient(&configs.APIConfig{
|
||||||
RPC: struct {
|
RPCEndpoints: []string{params.Protocol + "://" + configutils.QuoteIP(params.Host) + ":" + params.Port},
|
||||||
Endpoints []string `yaml:"endpoints"`
|
NodeId: params.NodeId,
|
||||||
DisableUpdate bool `yaml:"disableUpdate"`
|
Secret: params.NodeSecret,
|
||||||
}{
|
|
||||||
Endpoints: []string{params.Protocol + "://" + configutils.QuoteIP(params.Host) + ":" + params.Port},
|
|
||||||
},
|
|
||||||
NodeId: params.NodeId,
|
|
||||||
Secret: params.NodeSecret,
|
|
||||||
}, false)
|
}, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
this.FailField("host", "测试API节点时出错,请检查配置,错误信息:"+err.Error())
|
this.FailField("host", "测试API节点时出错,请检查配置,错误信息:"+err.Error())
|
||||||
@@ -165,23 +160,18 @@ func (this *UpdateHostsAction) RunPost(params struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 修改api.yaml
|
// 修改api_admin.yaml
|
||||||
var apiConfig = &configs.APIConfig{
|
var apiConfig = &configs.APIConfig{
|
||||||
RPC: struct {
|
RPCEndpoints: endpoints,
|
||||||
Endpoints []string `yaml:"endpoints"`
|
NodeId: adminAPIToken.NodeId,
|
||||||
DisableUpdate bool `yaml:"disableUpdate"`
|
Secret: adminAPIToken.Secret,
|
||||||
}{
|
|
||||||
Endpoints: endpoints,
|
|
||||||
},
|
|
||||||
NodeId: adminAPIToken.NodeId,
|
|
||||||
Secret: adminAPIToken.Secret,
|
|
||||||
}
|
}
|
||||||
err = apiConfig.WriteFile(Tea.Root + "/configs/api.yaml")
|
err = apiConfig.WriteFile(Tea.Root + "/configs/" + configs.ConfigFileName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
this.Fail("保存configs/api.yaml失败:" + err.Error())
|
this.Fail("保存configs/" + configs.ConfigFileName + "失败:" + err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
// 加载api.yaml
|
// 加载api_admin.yaml
|
||||||
rpcClient, err := rpc.SharedRPC()
|
rpcClient, err := rpc.SharedRPC()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
this.Fail("初始化RPC失败:" + err.Error())
|
this.Fail("初始化RPC失败:" + err.Error())
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
package recover
|
package recovers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
@@ -42,14 +42,9 @@ func (this *ValidateApiAction) RunPost(params struct {
|
|||||||
Field("nodeSecret", params.NodeSecret).
|
Field("nodeSecret", params.NodeSecret).
|
||||||
Require("请输入节点secret")
|
Require("请输入节点secret")
|
||||||
client, err := rpc.NewRPCClient(&configs.APIConfig{
|
client, err := rpc.NewRPCClient(&configs.APIConfig{
|
||||||
RPC: struct {
|
RPCEndpoints: []string{params.Protocol + "://" + configutils.QuoteIP(params.Host) + ":" + params.Port},
|
||||||
Endpoints []string `yaml:"endpoints"`
|
NodeId: params.NodeId,
|
||||||
DisableUpdate bool `yaml:"disableUpdate"`
|
Secret: params.NodeSecret,
|
||||||
}{
|
|
||||||
Endpoints: []string{params.Protocol + "://" + configutils.QuoteIP(params.Host) + ":" + params.Port},
|
|
||||||
},
|
|
||||||
NodeId: params.NodeId,
|
|
||||||
Secret: params.NodeSecret,
|
|
||||||
}, false)
|
}, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
this.FailField("host", "测试API节点时出错,请检查配置,错误信息:"+err.Error())
|
this.FailField("host", "测试API节点时出错,请检查配置,错误信息:"+err.Error())
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
"github.com/iwind/TeaGo/actions"
|
"github.com/iwind/TeaGo/actions"
|
||||||
"github.com/iwind/TeaGo/maps"
|
"github.com/iwind/TeaGo/maps"
|
||||||
|
"net"
|
||||||
"net/url"
|
"net/url"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -43,6 +44,14 @@ func (this *AddServerNamePopupAction) RunPost(params struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 去除端口
|
||||||
|
if regexp.MustCompile(`:\d+$`).MatchString(serverName) {
|
||||||
|
host, _, err := net.SplitHostPort(serverName)
|
||||||
|
if err == nil && len(host) > 0 {
|
||||||
|
serverName = host
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
params.Must.
|
params.Must.
|
||||||
Field("serverName", serverName).
|
Field("serverName", serverName).
|
||||||
Require("请输入域名")
|
Require("请输入域名")
|
||||||
@@ -72,6 +81,14 @@ func (this *AddServerNamePopupAction) RunPost(params struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 去除端口
|
||||||
|
if regexp.MustCompile(`:\d+$`).MatchString(serverName) {
|
||||||
|
host, _, err := net.SplitHostPort(serverName)
|
||||||
|
if err == nil && len(host) > 0 {
|
||||||
|
serverName = host
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 转成小写
|
// 转成小写
|
||||||
serverName = strings.ToLower(serverName)
|
serverName = strings.ToLower(serverName)
|
||||||
|
|
||||||
|
|||||||
@@ -17,12 +17,16 @@ func (this *IndexAction) Init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (this *IndexAction) RunGet(params struct {
|
func (this *IndexAction) RunGet(params struct {
|
||||||
UserId int64
|
UserId int64
|
||||||
Type string
|
Type string
|
||||||
Keyword string
|
Keyword string
|
||||||
|
UserType string
|
||||||
}) {
|
}) {
|
||||||
this.Data["type"] = params.Type
|
this.Data["type"] = params.Type
|
||||||
this.Data["keyword"] = params.Keyword
|
this.Data["keyword"] = params.Keyword
|
||||||
|
this.Data["userType"] = params.UserType
|
||||||
|
|
||||||
|
var userOnly = params.UserId > 0 || params.UserType == "user"
|
||||||
|
|
||||||
// 当前用户
|
// 当前用户
|
||||||
this.Data["searchingUserId"] = params.UserId
|
this.Data["searchingUserId"] = params.UserId
|
||||||
@@ -58,8 +62,9 @@ func (this *IndexAction) RunGet(params struct {
|
|||||||
{
|
{
|
||||||
// all
|
// all
|
||||||
resp, err := this.RPC().ACMETaskRPC().CountAllEnabledACMETasks(this.AdminContext(), &pb.CountAllEnabledACMETasksRequest{
|
resp, err := this.RPC().ACMETaskRPC().CountAllEnabledACMETasks(this.AdminContext(), &pb.CountAllEnabledACMETasksRequest{
|
||||||
UserId: params.UserId,
|
UserId: params.UserId,
|
||||||
Keyword: params.Keyword,
|
Keyword: params.Keyword,
|
||||||
|
UserOnly: userOnly,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
this.ErrorPage(err)
|
this.ErrorPage(err)
|
||||||
@@ -72,6 +77,7 @@ func (this *IndexAction) RunGet(params struct {
|
|||||||
UserId: params.UserId,
|
UserId: params.UserId,
|
||||||
IsAvailable: true,
|
IsAvailable: true,
|
||||||
Keyword: params.Keyword,
|
Keyword: params.Keyword,
|
||||||
|
UserOnly: userOnly,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
this.ErrorPage(err)
|
this.ErrorPage(err)
|
||||||
@@ -84,6 +90,7 @@ func (this *IndexAction) RunGet(params struct {
|
|||||||
UserId: params.UserId,
|
UserId: params.UserId,
|
||||||
IsExpired: true,
|
IsExpired: true,
|
||||||
Keyword: params.Keyword,
|
Keyword: params.Keyword,
|
||||||
|
UserOnly: userOnly,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
this.ErrorPage(err)
|
this.ErrorPage(err)
|
||||||
@@ -96,6 +103,7 @@ func (this *IndexAction) RunGet(params struct {
|
|||||||
UserId: params.UserId,
|
UserId: params.UserId,
|
||||||
ExpiringDays: 7,
|
ExpiringDays: 7,
|
||||||
Keyword: params.Keyword,
|
Keyword: params.Keyword,
|
||||||
|
UserOnly: userOnly,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
this.ErrorPage(err)
|
this.ErrorPage(err)
|
||||||
@@ -108,6 +116,7 @@ func (this *IndexAction) RunGet(params struct {
|
|||||||
UserId: params.UserId,
|
UserId: params.UserId,
|
||||||
ExpiringDays: 30,
|
ExpiringDays: 30,
|
||||||
Keyword: params.Keyword,
|
Keyword: params.Keyword,
|
||||||
|
UserOnly: userOnly,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
this.ErrorPage(err)
|
this.ErrorPage(err)
|
||||||
@@ -130,10 +139,11 @@ func (this *IndexAction) RunGet(params struct {
|
|||||||
case "":
|
case "":
|
||||||
page = this.NewPage(countAll)
|
page = this.NewPage(countAll)
|
||||||
tasksResp, err = this.RPC().ACMETaskRPC().ListEnabledACMETasks(this.AdminContext(), &pb.ListEnabledACMETasksRequest{
|
tasksResp, err = this.RPC().ACMETaskRPC().ListEnabledACMETasks(this.AdminContext(), &pb.ListEnabledACMETasksRequest{
|
||||||
UserId: params.UserId,
|
UserId: params.UserId,
|
||||||
Offset: page.Offset,
|
Offset: page.Offset,
|
||||||
Size: page.Size,
|
Size: page.Size,
|
||||||
Keyword: params.Keyword,
|
Keyword: params.Keyword,
|
||||||
|
UserOnly: userOnly,
|
||||||
})
|
})
|
||||||
case "available":
|
case "available":
|
||||||
page = this.NewPage(countAvailable)
|
page = this.NewPage(countAvailable)
|
||||||
@@ -143,6 +153,7 @@ func (this *IndexAction) RunGet(params struct {
|
|||||||
Offset: page.Offset,
|
Offset: page.Offset,
|
||||||
Size: page.Size,
|
Size: page.Size,
|
||||||
Keyword: params.Keyword,
|
Keyword: params.Keyword,
|
||||||
|
UserOnly: userOnly,
|
||||||
})
|
})
|
||||||
case "expired":
|
case "expired":
|
||||||
page = this.NewPage(countExpired)
|
page = this.NewPage(countExpired)
|
||||||
@@ -152,6 +163,7 @@ func (this *IndexAction) RunGet(params struct {
|
|||||||
Offset: page.Offset,
|
Offset: page.Offset,
|
||||||
Size: page.Size,
|
Size: page.Size,
|
||||||
Keyword: params.Keyword,
|
Keyword: params.Keyword,
|
||||||
|
UserOnly: userOnly,
|
||||||
})
|
})
|
||||||
case "7days":
|
case "7days":
|
||||||
page = this.NewPage(count7Days)
|
page = this.NewPage(count7Days)
|
||||||
@@ -161,6 +173,7 @@ func (this *IndexAction) RunGet(params struct {
|
|||||||
Offset: page.Offset,
|
Offset: page.Offset,
|
||||||
Size: page.Size,
|
Size: page.Size,
|
||||||
Keyword: params.Keyword,
|
Keyword: params.Keyword,
|
||||||
|
UserOnly: userOnly,
|
||||||
})
|
})
|
||||||
case "30days":
|
case "30days":
|
||||||
page = this.NewPage(count30Days)
|
page = this.NewPage(count30Days)
|
||||||
@@ -170,14 +183,16 @@ func (this *IndexAction) RunGet(params struct {
|
|||||||
Offset: page.Offset,
|
Offset: page.Offset,
|
||||||
Size: page.Size,
|
Size: page.Size,
|
||||||
Keyword: params.Keyword,
|
Keyword: params.Keyword,
|
||||||
|
UserOnly: userOnly,
|
||||||
})
|
})
|
||||||
default:
|
default:
|
||||||
page = this.NewPage(countAll)
|
page = this.NewPage(countAll)
|
||||||
tasksResp, err = this.RPC().ACMETaskRPC().ListEnabledACMETasks(this.AdminContext(), &pb.ListEnabledACMETasksRequest{
|
tasksResp, err = this.RPC().ACMETaskRPC().ListEnabledACMETasks(this.AdminContext(), &pb.ListEnabledACMETasksRequest{
|
||||||
UserId: params.UserId,
|
UserId: params.UserId,
|
||||||
Keyword: params.Keyword,
|
Keyword: params.Keyword,
|
||||||
Offset: page.Offset,
|
UserOnly: userOnly,
|
||||||
Size: page.Size,
|
Offset: page.Offset,
|
||||||
|
Size: page.Size,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -242,6 +257,23 @@ func (this *IndexAction) RunGet(params struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// user
|
||||||
|
userResp, err := this.RPC().ACMETaskRPC().FindACMETaskUser(this.AdminContext(), &pb.FindACMETaskUserRequest{AcmeTaskId: task.Id})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var taskUserMap = maps.Map{
|
||||||
|
"id": 0,
|
||||||
|
}
|
||||||
|
if userResp.User != nil {
|
||||||
|
taskUserMap = maps.Map{
|
||||||
|
"id": userResp.User.Id,
|
||||||
|
"username": userResp.User.Username,
|
||||||
|
"fullname": userResp.User.Fullname,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
taskMaps = append(taskMaps, maps.Map{
|
taskMaps = append(taskMaps, maps.Map{
|
||||||
"id": task.Id,
|
"id": task.Id,
|
||||||
"authType": task.AuthType,
|
"authType": task.AuthType,
|
||||||
@@ -257,6 +289,7 @@ func (this *IndexAction) RunGet(params struct {
|
|||||||
"autoRenew": task.AutoRenew,
|
"autoRenew": task.AutoRenew,
|
||||||
"cert": certMap,
|
"cert": certMap,
|
||||||
"log": logMap,
|
"log": logMap,
|
||||||
|
"user": taskUserMap,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
this.Data["tasks"] = taskMaps
|
this.Data["tasks"] = taskMaps
|
||||||
|
|||||||
@@ -36,5 +36,5 @@ func (this *DownloadCertAction) RunGet(params struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.AddHeader("Content-Disposition", "attachment; filename=\"cert-"+strconv.FormatInt(params.CertId, 10)+".pem\";")
|
this.AddHeader("Content-Disposition", "attachment; filename=\"cert-"+strconv.FormatInt(params.CertId, 10)+".pem\";")
|
||||||
this.Write(certConfig.CertData)
|
_, _ = this.Write(certConfig.CertData)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,5 +36,5 @@ func (this *DownloadKeyAction) RunGet(params struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.AddHeader("Content-Disposition", "attachment; filename=\"key-"+strconv.FormatInt(params.CertId, 10)+".pem\";")
|
this.AddHeader("Content-Disposition", "attachment; filename=\"key-"+strconv.FormatInt(params.CertId, 10)+".pem\";")
|
||||||
this.Write(certConfig.KeyData)
|
_, _ = this.Write(certConfig.KeyData)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,13 +19,19 @@ func (this *IndexAction) Init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (this *IndexAction) RunGet(params struct {
|
func (this *IndexAction) RunGet(params struct {
|
||||||
UserId int64
|
UserId int64
|
||||||
Type string
|
Type string // [empty] | ca | 7days | ...
|
||||||
Keyword string
|
Keyword string
|
||||||
|
UserType string
|
||||||
}) {
|
}) {
|
||||||
this.Data["type"] = params.Type
|
this.Data["type"] = params.Type
|
||||||
this.Data["keyword"] = params.Keyword
|
this.Data["keyword"] = params.Keyword
|
||||||
|
|
||||||
|
if params.UserId > 0 {
|
||||||
|
params.UserType = "user"
|
||||||
|
}
|
||||||
|
this.Data["userType"] = params.UserType
|
||||||
|
|
||||||
// 当前用户
|
// 当前用户
|
||||||
this.Data["searchingUserId"] = params.UserId
|
this.Data["searchingUserId"] = params.UserId
|
||||||
var userMap = maps.Map{
|
var userMap = maps.Map{
|
||||||
@@ -50,19 +56,22 @@ func (this *IndexAction) RunGet(params struct {
|
|||||||
}
|
}
|
||||||
this.Data["user"] = userMap
|
this.Data["user"] = userMap
|
||||||
|
|
||||||
var countAll = int64(0)
|
var countAll int64
|
||||||
var countCA = int64(0)
|
var countCA int64
|
||||||
var countAvailable = int64(0)
|
var countAvailable int64
|
||||||
var countExpired = int64(0)
|
var countExpired int64
|
||||||
var count7Days = int64(0)
|
var count7Days int64
|
||||||
var count30Days = int64(0)
|
var count30Days int64
|
||||||
|
|
||||||
|
var userOnly = params.UserType == "user" || params.UserId > 0
|
||||||
|
|
||||||
// 计算数量
|
// 计算数量
|
||||||
{
|
{
|
||||||
// all
|
// all
|
||||||
resp, err := this.RPC().SSLCertRPC().CountSSLCerts(this.AdminContext(), &pb.CountSSLCertRequest{
|
resp, err := this.RPC().SSLCertRPC().CountSSLCerts(this.AdminContext(), &pb.CountSSLCertRequest{
|
||||||
UserId: params.UserId,
|
UserId: params.UserId,
|
||||||
Keyword: params.Keyword,
|
Keyword: params.Keyword,
|
||||||
|
UserOnly: userOnly,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
this.ErrorPage(err)
|
this.ErrorPage(err)
|
||||||
@@ -72,9 +81,10 @@ func (this *IndexAction) RunGet(params struct {
|
|||||||
|
|
||||||
// CA
|
// CA
|
||||||
resp, err = this.RPC().SSLCertRPC().CountSSLCerts(this.AdminContext(), &pb.CountSSLCertRequest{
|
resp, err = this.RPC().SSLCertRPC().CountSSLCerts(this.AdminContext(), &pb.CountSSLCertRequest{
|
||||||
UserId: params.UserId,
|
UserId: params.UserId,
|
||||||
IsCA: true,
|
IsCA: true,
|
||||||
Keyword: params.Keyword,
|
Keyword: params.Keyword,
|
||||||
|
UserOnly: userOnly,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
this.ErrorPage(err)
|
this.ErrorPage(err)
|
||||||
@@ -87,6 +97,7 @@ func (this *IndexAction) RunGet(params struct {
|
|||||||
UserId: params.UserId,
|
UserId: params.UserId,
|
||||||
IsAvailable: true,
|
IsAvailable: true,
|
||||||
Keyword: params.Keyword,
|
Keyword: params.Keyword,
|
||||||
|
UserOnly: userOnly,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
this.ErrorPage(err)
|
this.ErrorPage(err)
|
||||||
@@ -99,6 +110,7 @@ func (this *IndexAction) RunGet(params struct {
|
|||||||
UserId: params.UserId,
|
UserId: params.UserId,
|
||||||
IsExpired: true,
|
IsExpired: true,
|
||||||
Keyword: params.Keyword,
|
Keyword: params.Keyword,
|
||||||
|
UserOnly: userOnly,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
this.ErrorPage(err)
|
this.ErrorPage(err)
|
||||||
@@ -111,6 +123,7 @@ func (this *IndexAction) RunGet(params struct {
|
|||||||
UserId: params.UserId,
|
UserId: params.UserId,
|
||||||
ExpiringDays: 7,
|
ExpiringDays: 7,
|
||||||
Keyword: params.Keyword,
|
Keyword: params.Keyword,
|
||||||
|
UserOnly: userOnly,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
this.ErrorPage(err)
|
this.ErrorPage(err)
|
||||||
@@ -123,6 +136,7 @@ func (this *IndexAction) RunGet(params struct {
|
|||||||
UserId: params.UserId,
|
UserId: params.UserId,
|
||||||
ExpiringDays: 30,
|
ExpiringDays: 30,
|
||||||
Keyword: params.Keyword,
|
Keyword: params.Keyword,
|
||||||
|
UserOnly: userOnly,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
this.ErrorPage(err)
|
this.ErrorPage(err)
|
||||||
@@ -146,19 +160,21 @@ func (this *IndexAction) RunGet(params struct {
|
|||||||
case "":
|
case "":
|
||||||
page = this.NewPage(countAll)
|
page = this.NewPage(countAll)
|
||||||
listResp, err = this.RPC().SSLCertRPC().ListSSLCerts(this.AdminContext(), &pb.ListSSLCertsRequest{
|
listResp, err = this.RPC().SSLCertRPC().ListSSLCerts(this.AdminContext(), &pb.ListSSLCertsRequest{
|
||||||
UserId: params.UserId,
|
UserId: params.UserId,
|
||||||
Offset: page.Offset,
|
Offset: page.Offset,
|
||||||
Size: page.Size,
|
Size: page.Size,
|
||||||
Keyword: params.Keyword,
|
Keyword: params.Keyword,
|
||||||
|
UserOnly: userOnly,
|
||||||
})
|
})
|
||||||
case "ca":
|
case "ca":
|
||||||
page = this.NewPage(countCA)
|
page = this.NewPage(countCA)
|
||||||
listResp, err = this.RPC().SSLCertRPC().ListSSLCerts(this.AdminContext(), &pb.ListSSLCertsRequest{
|
listResp, err = this.RPC().SSLCertRPC().ListSSLCerts(this.AdminContext(), &pb.ListSSLCertsRequest{
|
||||||
UserId: params.UserId,
|
UserId: params.UserId,
|
||||||
IsCA: true,
|
IsCA: true,
|
||||||
Offset: page.Offset,
|
Offset: page.Offset,
|
||||||
Size: page.Size,
|
Size: page.Size,
|
||||||
Keyword: params.Keyword,
|
Keyword: params.Keyword,
|
||||||
|
UserOnly: userOnly,
|
||||||
})
|
})
|
||||||
case "available":
|
case "available":
|
||||||
page = this.NewPage(countAvailable)
|
page = this.NewPage(countAvailable)
|
||||||
@@ -168,6 +184,7 @@ func (this *IndexAction) RunGet(params struct {
|
|||||||
Offset: page.Offset,
|
Offset: page.Offset,
|
||||||
Size: page.Size,
|
Size: page.Size,
|
||||||
Keyword: params.Keyword,
|
Keyword: params.Keyword,
|
||||||
|
UserOnly: userOnly,
|
||||||
})
|
})
|
||||||
case "expired":
|
case "expired":
|
||||||
page = this.NewPage(countExpired)
|
page = this.NewPage(countExpired)
|
||||||
@@ -177,6 +194,7 @@ func (this *IndexAction) RunGet(params struct {
|
|||||||
Offset: page.Offset,
|
Offset: page.Offset,
|
||||||
Size: page.Size,
|
Size: page.Size,
|
||||||
Keyword: params.Keyword,
|
Keyword: params.Keyword,
|
||||||
|
UserOnly: userOnly,
|
||||||
})
|
})
|
||||||
case "7days":
|
case "7days":
|
||||||
page = this.NewPage(count7Days)
|
page = this.NewPage(count7Days)
|
||||||
@@ -195,14 +213,16 @@ func (this *IndexAction) RunGet(params struct {
|
|||||||
Offset: page.Offset,
|
Offset: page.Offset,
|
||||||
Size: page.Size,
|
Size: page.Size,
|
||||||
Keyword: params.Keyword,
|
Keyword: params.Keyword,
|
||||||
|
UserOnly: userOnly,
|
||||||
})
|
})
|
||||||
default:
|
default:
|
||||||
page = this.NewPage(countAll)
|
page = this.NewPage(countAll)
|
||||||
listResp, err = this.RPC().SSLCertRPC().ListSSLCerts(this.AdminContext(), &pb.ListSSLCertsRequest{
|
listResp, err = this.RPC().SSLCertRPC().ListSSLCerts(this.AdminContext(), &pb.ListSSLCertsRequest{
|
||||||
UserId: params.UserId,
|
UserId: params.UserId,
|
||||||
Keyword: params.Keyword,
|
Keyword: params.Keyword,
|
||||||
Offset: page.Offset,
|
UserOnly: userOnly,
|
||||||
Size: page.Size,
|
Offset: page.Offset,
|
||||||
|
Size: page.Size,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -221,6 +241,7 @@ func (this *IndexAction) RunGet(params struct {
|
|||||||
var certMaps = []maps.Map{}
|
var certMaps = []maps.Map{}
|
||||||
var nowTime = time.Now().Unix()
|
var nowTime = time.Now().Unix()
|
||||||
for _, certConfig := range certConfigs {
|
for _, certConfig := range certConfigs {
|
||||||
|
// count servers
|
||||||
countServersResp, err := this.RPC().ServerRPC().CountAllEnabledServersWithSSLCertId(this.AdminContext(), &pb.CountAllEnabledServersWithSSLCertIdRequest{
|
countServersResp, err := this.RPC().ServerRPC().CountAllEnabledServersWithSSLCertId(this.AdminContext(), &pb.CountAllEnabledServersWithSSLCertIdRequest{
|
||||||
SslCertId: certConfig.Id,
|
SslCertId: certConfig.Id,
|
||||||
})
|
})
|
||||||
@@ -229,6 +250,23 @@ func (this *IndexAction) RunGet(params struct {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// user
|
||||||
|
userResp, err := this.RPC().SSLCertRPC().FindSSLCertUser(this.AdminContext(), &pb.FindSSLCertUserRequest{SslCertId: certConfig.Id})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var certUserMap = maps.Map{
|
||||||
|
"id": 0,
|
||||||
|
}
|
||||||
|
if userResp.User != nil {
|
||||||
|
certUserMap = maps.Map{
|
||||||
|
"id": userResp.User.Id,
|
||||||
|
"username": userResp.User.Username,
|
||||||
|
"fullname": userResp.User.Fullname,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
certMaps = append(certMaps, maps.Map{
|
certMaps = append(certMaps, maps.Map{
|
||||||
"isOn": certConfig.IsOn,
|
"isOn": certConfig.IsOn,
|
||||||
"beginDay": timeutil.FormatTime("Y-m-d", certConfig.TimeBeginAt),
|
"beginDay": timeutil.FormatTime("Y-m-d", certConfig.TimeBeginAt),
|
||||||
@@ -236,6 +274,7 @@ func (this *IndexAction) RunGet(params struct {
|
|||||||
"isExpired": nowTime > certConfig.TimeEndAt,
|
"isExpired": nowTime > certConfig.TimeEndAt,
|
||||||
"isAvailable": nowTime <= certConfig.TimeEndAt,
|
"isAvailable": nowTime <= certConfig.TimeEndAt,
|
||||||
"countServers": countServersResp.Count,
|
"countServers": countServersResp.Count,
|
||||||
|
"user": certUserMap,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
this.Data["certInfos"] = certMaps
|
this.Data["certInfos"] = certMaps
|
||||||
|
|||||||
@@ -172,6 +172,11 @@ func (this *SelectPopupAction) RunGet(params struct {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if listResp == nil {
|
if listResp == nil {
|
||||||
this.ErrorPage(errors.New("'listResp' should not be nil"))
|
this.ErrorPage(errors.New("'listResp' should not be nil"))
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package certs
|
package certs
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||||
@@ -120,7 +121,7 @@ func (this *UpdatePopupAction) RunPost(params struct {
|
|||||||
|
|
||||||
// 校验
|
// 校验
|
||||||
certConfig.IsCA = params.IsCA
|
certConfig.IsCA = params.IsCA
|
||||||
err = certConfig.Init(nil)
|
err = certConfig.Init(context.TODO())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if params.IsCA {
|
if params.IsCA {
|
||||||
this.Fail("证书校验错误:" + err.Error())
|
this.Fail("证书校验错误:" + err.Error())
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ package certs
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"context"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||||
@@ -156,7 +157,7 @@ func (this *UploadBatchPopupAction) RunPost(params struct {
|
|||||||
CertData: certData,
|
CertData: certData,
|
||||||
KeyData: keyData,
|
KeyData: keyData,
|
||||||
}
|
}
|
||||||
err := certConfig.Init(nil)
|
err := certConfig.Init(context.TODO())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
this.Fail("证书验证失败:" + err.Error())
|
this.Fail("证书验证失败:" + err.Error())
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package certs
|
package certs
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||||
@@ -60,8 +61,8 @@ func (this *UploadPopupAction) RunPost(params struct {
|
|||||||
Field("name", params.Name).
|
Field("name", params.Name).
|
||||||
Require("请输入证书说明")
|
Require("请输入证书说明")
|
||||||
|
|
||||||
var certData = []byte{}
|
var certData []byte
|
||||||
var keyData = []byte{}
|
var keyData []byte
|
||||||
|
|
||||||
if params.TextMode {
|
if params.TextMode {
|
||||||
if len(params.CertText) == 0 {
|
if len(params.CertText) == 0 {
|
||||||
@@ -104,7 +105,7 @@ func (this *UploadPopupAction) RunPost(params struct {
|
|||||||
CertData: certData,
|
CertData: certData,
|
||||||
KeyData: keyData,
|
KeyData: keyData,
|
||||||
}
|
}
|
||||||
err := certConfig.Init(nil)
|
err := certConfig.Init(context.TODO())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if params.IsCA {
|
if params.IsCA {
|
||||||
this.Fail("证书校验错误:" + err.Error())
|
this.Fail("证书校验错误:" + err.Error())
|
||||||
|
|||||||
@@ -35,5 +35,5 @@ func (this *ViewCertAction) RunGet(params struct {
|
|||||||
this.ErrorPage(err)
|
this.ErrorPage(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
this.Write(certConfig.CertData)
|
_, _ = this.Write(certConfig.CertData)
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user