mirror of
https://github.com/TeaOSLab/EdgeAdmin.git
synced 2025-11-03 12:20:28 +08:00
[用户节点]可以管理用户节点
This commit is contained in:
@@ -1,3 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
env GOOS=linux GOARCH=amd64 go build -ldflags="-s -w" -o edge-admin main.go
|
||||
Binary file not shown.
@@ -9,13 +9,13 @@ import (
|
||||
"reflect"
|
||||
)
|
||||
|
||||
var sharedUIConfig *systemconfigs.UIConfig = nil
|
||||
var sharedUIConfig *systemconfigs.AdminUIConfig = nil
|
||||
|
||||
const (
|
||||
UISettingName = "adminUIConfig"
|
||||
)
|
||||
|
||||
func LoadUIConfig() (*systemconfigs.UIConfig, error) {
|
||||
func LoadUIConfig() (*systemconfigs.AdminUIConfig, error) {
|
||||
locker.Lock()
|
||||
defer locker.Unlock()
|
||||
|
||||
@@ -24,11 +24,11 @@ func LoadUIConfig() (*systemconfigs.UIConfig, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
v := reflect.Indirect(reflect.ValueOf(config)).Interface().(systemconfigs.UIConfig)
|
||||
v := reflect.Indirect(reflect.ValueOf(config)).Interface().(systemconfigs.AdminUIConfig)
|
||||
return &v, nil
|
||||
}
|
||||
|
||||
func UpdateUIConfig(uiConfig *systemconfigs.UIConfig) error {
|
||||
func UpdateUIConfig(uiConfig *systemconfigs.AdminUIConfig) error {
|
||||
locker.Lock()
|
||||
defer locker.Unlock()
|
||||
|
||||
@@ -52,7 +52,7 @@ func UpdateUIConfig(uiConfig *systemconfigs.UIConfig) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func loadUIConfig() (*systemconfigs.UIConfig, error) {
|
||||
func loadUIConfig() (*systemconfigs.AdminUIConfig, error) {
|
||||
if sharedUIConfig != nil {
|
||||
return sharedUIConfig, nil
|
||||
}
|
||||
@@ -71,7 +71,7 @@ func loadUIConfig() (*systemconfigs.UIConfig, error) {
|
||||
return sharedUIConfig, nil
|
||||
}
|
||||
|
||||
config := &systemconfigs.UIConfig{}
|
||||
config := &systemconfigs.AdminUIConfig{}
|
||||
err = json.Unmarshal(resp.ValueJSON, config)
|
||||
if err != nil {
|
||||
logs.Println("[UI_MANAGER]" + err.Error())
|
||||
@@ -82,8 +82,8 @@ func loadUIConfig() (*systemconfigs.UIConfig, error) {
|
||||
return sharedUIConfig, nil
|
||||
}
|
||||
|
||||
func defaultUIConfig() *systemconfigs.UIConfig {
|
||||
return &systemconfigs.UIConfig{
|
||||
func defaultUIConfig() *systemconfigs.AdminUIConfig {
|
||||
return &systemconfigs.AdminUIConfig{
|
||||
ProductName: "GoEdge",
|
||||
AdminSystemName: "GoEdge管理员系统",
|
||||
ShowOpenSourceInfo: true,
|
||||
|
||||
@@ -34,6 +34,10 @@ func (this *AdminNode) Run() {
|
||||
// 检查server配置
|
||||
err := this.checkServer()
|
||||
if err != nil {
|
||||
if err != nil {
|
||||
logs.Println("[NODE]" + err.Error())
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -58,6 +62,7 @@ func (this *AdminNode) Run() {
|
||||
// 启动API节点
|
||||
this.startAPINode()
|
||||
|
||||
// 启动Web服务
|
||||
TeaGo.NewServer(false).
|
||||
AccessLog(false).
|
||||
EndAll().
|
||||
@@ -129,7 +134,7 @@ func (this *AdminNode) startAPINode() {
|
||||
|
||||
// 生成Secret
|
||||
func (this *AdminNode) genSecret() string {
|
||||
tmpFile := os.TempDir() + "/edge-secret.tmp"
|
||||
tmpFile := os.TempDir() + "/edge-admin-secret.tmp"
|
||||
data, err := ioutil.ReadFile(tmpFile)
|
||||
if err == nil && len(data) == 32 {
|
||||
return string(data)
|
||||
|
||||
@@ -95,6 +95,10 @@ func (this *RPCClient) APINodeRPC() pb.APINodeServiceClient {
|
||||
return pb.NewAPINodeServiceClient(this.pickConn())
|
||||
}
|
||||
|
||||
func (this *RPCClient) UserNodeRPC() pb.UserNodeServiceClient {
|
||||
return pb.NewUserNodeServiceClient(this.pickConn())
|
||||
}
|
||||
|
||||
func (this *RPCClient) DBNodeRPC() pb.DBNodeServiceClient {
|
||||
return pb.NewDBNodeServiceClient(this.pickConn())
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ func init() {
|
||||
server.
|
||||
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeSetting)).
|
||||
Helper(NewHelper()).
|
||||
Helper(settingutils.NewHelper("apiNodes")).
|
||||
Helper(settingutils.NewAdvancedHelper("apiNodes")).
|
||||
Prefix("/api").
|
||||
Get("", new(IndexAction)).
|
||||
GetPost("/node/createPopup", new(node.CreatePopupAction)).
|
||||
|
||||
@@ -12,7 +12,7 @@ func init() {
|
||||
server.
|
||||
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeSetting)).
|
||||
Helper(new(Helper)).
|
||||
Helper(settingutils.NewHelper("dbNodes")).
|
||||
Helper(settingutils.NewAdvancedHelper("dbNodes")).
|
||||
Prefix("/db").
|
||||
Get("", new(IndexAction)).
|
||||
GetPost("/createPopup", new(CreatePopupAction)).
|
||||
|
||||
16
internal/web/actions/default/settings/advanced.go
Normal file
16
internal/web/actions/default/settings/advanced.go
Normal file
@@ -0,0 +1,16 @@
|
||||
package settings
|
||||
|
||||
import "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
|
||||
type AdvancedAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *AdvancedAction) Init() {
|
||||
this.Nav("", "", "")
|
||||
}
|
||||
|
||||
func (this *AdvancedAction) RunGet(params struct{}) {
|
||||
// 跳转到高级设置的第一个Tab
|
||||
this.RedirectURL("/settings/database")
|
||||
}
|
||||
@@ -11,7 +11,7 @@ func init() {
|
||||
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
||||
server.
|
||||
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeSetting)).
|
||||
Helper(settingutils.NewHelper("database")).
|
||||
Helper(settingutils.NewAdvancedHelper("database")).
|
||||
Prefix("/settings/database").
|
||||
Get("", new(IndexAction)).
|
||||
GetPost("/update", new(UpdateAction)).
|
||||
|
||||
@@ -13,6 +13,7 @@ func init() {
|
||||
Helper(NewHelper()).
|
||||
Prefix("/settings").
|
||||
Get("", new(IndexAction)).
|
||||
Get("/advanced", new(AdvancedAction)).
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
package settingutils
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
)
|
||||
|
||||
type AdvancedHelper struct {
|
||||
tab string
|
||||
}
|
||||
|
||||
func NewAdvancedHelper(tab string) *AdvancedHelper {
|
||||
return &AdvancedHelper{
|
||||
tab: tab,
|
||||
}
|
||||
}
|
||||
|
||||
func (this *AdvancedHelper) BeforeAction(actionPtr actions.ActionWrapper) (goNext bool) {
|
||||
goNext = true
|
||||
|
||||
action := actionPtr.Object()
|
||||
|
||||
// 左侧菜单
|
||||
action.Data["teaMenu"] = "settings"
|
||||
action.Data["teaSubMenu"] = "advanced"
|
||||
|
||||
// 标签栏
|
||||
tabbar := actionutils.NewTabbar()
|
||||
var session = action.Session()
|
||||
var adminId = session.GetInt64("adminId")
|
||||
if configloaders.AllowModule(adminId, configloaders.AdminModuleCodeSetting) {
|
||||
tabbar.Add("数据库", "", "/settings/database", "", this.tab == "database")
|
||||
tabbar.Add("API节点", "", "/api", "", this.tab == "apiNodes")
|
||||
tabbar.Add("用户节点", "", "/settings/userNodes", "", this.tab == "userNodes")
|
||||
tabbar.Add("日志数据库", "", "/db", "", this.tab == "dbNodes")
|
||||
}
|
||||
actionutils.SetTabbar(actionPtr, tabbar)
|
||||
|
||||
return
|
||||
}
|
||||
@@ -32,9 +32,6 @@ func (this *Helper) BeforeAction(actionPtr actions.ActionWrapper) (goNext bool)
|
||||
tabbar.Add("Web服务", "", "/settings/server", "", this.tab == "server")
|
||||
tabbar.Add("界面设置", "", "/settings/ui", "", this.tab == "ui")
|
||||
tabbar.Add("安全设置", "", "/settings/security", "", this.tab == "security")
|
||||
tabbar.Add("数据库", "", "/settings/database", "", this.tab == "database")
|
||||
tabbar.Add("API节点", "", "/api", "", this.tab == "apiNodes")
|
||||
tabbar.Add("日志数据库", "", "/db", "", this.tab == "dbNodes")
|
||||
tabbar.Add("IP库", "", "/settings/ip-library", "", this.tab == "ipLibrary")
|
||||
tabbar.Add("备份", "", "/settings/backup", "", this.tab == "backup")
|
||||
}
|
||||
28
internal/web/actions/default/settings/user-nodes/delete.go
Normal file
28
internal/web/actions/default/settings/user-nodes/delete.go
Normal file
@@ -0,0 +1,28 @@
|
||||
package usernodes
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/oplogs"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
)
|
||||
|
||||
type DeleteAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *DeleteAction) RunPost(params struct {
|
||||
NodeId int64
|
||||
}) {
|
||||
// TODO 检查权限
|
||||
|
||||
_, err := this.RPC().UserNodeRPC().DeleteUserNode(this.AdminContext(), &pb.DeleteUserNodeRequest{NodeId: params.NodeId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
// 创建日志
|
||||
defer this.CreateLog(oplogs.LevelInfo, "删除用户节点 %d", params.NodeId)
|
||||
|
||||
this.Success()
|
||||
}
|
||||
15
internal/web/actions/default/settings/user-nodes/helper.go
Normal file
15
internal/web/actions/default/settings/user-nodes/helper.go
Normal file
@@ -0,0 +1,15 @@
|
||||
package usernodes
|
||||
|
||||
import (
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
)
|
||||
|
||||
type Helper struct {
|
||||
}
|
||||
|
||||
func NewHelper() *Helper {
|
||||
return &Helper{}
|
||||
}
|
||||
|
||||
func (this *Helper) BeforeAction(action *actions.ActionObject) {
|
||||
}
|
||||
50
internal/web/actions/default/settings/user-nodes/index.go
Normal file
50
internal/web/actions/default/settings/user-nodes/index.go
Normal file
@@ -0,0 +1,50 @@
|
||||
package usernodes
|
||||
|
||||
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("", "node", "index")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct{}) {
|
||||
countResp, err := this.RPC().UserNodeRPC().CountAllEnabledUserNodes(this.AdminContext(), &pb.CountAllEnabledUserNodesRequest{})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
count := countResp.Count
|
||||
page := this.NewPage(count)
|
||||
this.Data["page"] = page.AsHTML()
|
||||
|
||||
nodeMaps := []maps.Map{}
|
||||
if count > 0 {
|
||||
nodesResp, err := this.RPC().UserNodeRPC().ListEnabledUserNodes(this.AdminContext(), &pb.ListEnabledUserNodesRequest{
|
||||
Offset: page.Offset,
|
||||
Size: page.Size,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
for _, node := range nodesResp.Nodes {
|
||||
nodeMaps = append(nodeMaps, maps.Map{
|
||||
"id": node.Id,
|
||||
"isOn": node.IsOn,
|
||||
"name": node.Name,
|
||||
"accessAddrs": node.AccessAddrs,
|
||||
})
|
||||
}
|
||||
}
|
||||
this.Data["nodes"] = nodeMaps
|
||||
|
||||
this.Show()
|
||||
}
|
||||
23
internal/web/actions/default/settings/user-nodes/init.go
Normal file
23
internal/web/actions/default/settings/user-nodes/init.go
Normal file
@@ -0,0 +1,23 @@
|
||||
package usernodes
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/settings/settingutils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/settings/user-nodes/node"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
|
||||
"github.com/iwind/TeaGo"
|
||||
)
|
||||
|
||||
func init() {
|
||||
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
||||
server.
|
||||
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeSetting)).
|
||||
Helper(NewHelper()).
|
||||
Helper(settingutils.NewAdvancedHelper("userNodes")).
|
||||
Prefix("/settings/userNodes").
|
||||
Get("", new(IndexAction)).
|
||||
GetPost("/node/createPopup", new(node.CreatePopupAction)).
|
||||
Post("/delete", new(DeleteAction)).
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package node
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"net"
|
||||
)
|
||||
|
||||
// 添加地址
|
||||
type CreateAddrPopupAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *CreateAddrPopupAction) Init() {
|
||||
this.Nav("", "", "")
|
||||
}
|
||||
|
||||
func (this *CreateAddrPopupAction) RunGet(params struct {
|
||||
}) {
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *CreateAddrPopupAction) RunPost(params struct {
|
||||
Protocol string
|
||||
Addr string
|
||||
Must *actions.Must
|
||||
}) {
|
||||
params.Must.
|
||||
Field("addr", params.Addr).
|
||||
Require("请输入访问地址")
|
||||
|
||||
|
||||
host, port, err := net.SplitHostPort(params.Addr)
|
||||
if err != nil {
|
||||
this.FailField("addr", "错误的访问地址")
|
||||
}
|
||||
|
||||
addrConfig := &serverconfigs.NetworkAddressConfig{
|
||||
Protocol: serverconfigs.Protocol(params.Protocol),
|
||||
Host: host,
|
||||
PortRange: port,
|
||||
}
|
||||
this.Data["addr"] = addrConfig
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
package node
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/oplogs"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/sslconfigs"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
)
|
||||
|
||||
type CreatePopupAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *CreatePopupAction) Init() {
|
||||
this.Nav("", "node", "create")
|
||||
}
|
||||
|
||||
func (this *CreatePopupAction) RunGet(params struct{}) {
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *CreatePopupAction) RunPost(params struct {
|
||||
Name string
|
||||
Description string
|
||||
ListensJSON []byte
|
||||
CertIdsJSON []byte
|
||||
AccessAddrsJSON []byte
|
||||
IsOn bool
|
||||
|
||||
Must *actions.Must
|
||||
}) {
|
||||
params.Must.
|
||||
Field("name", params.Name).
|
||||
Require("请输入用户节点名称")
|
||||
|
||||
httpConfig := &serverconfigs.HTTPProtocolConfig{}
|
||||
httpsConfig := &serverconfigs.HTTPSProtocolConfig{}
|
||||
|
||||
// 监听地址
|
||||
listens := []*serverconfigs.NetworkAddressConfig{}
|
||||
err := json.Unmarshal(params.ListensJSON, &listens)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if len(listens) == 0 {
|
||||
this.Fail("请添加至少一个进程监听地址")
|
||||
}
|
||||
for _, addr := range listens {
|
||||
if addr.Protocol.IsHTTPFamily() {
|
||||
httpConfig.IsOn = true
|
||||
httpConfig.Listen = append(httpConfig.Listen, addr)
|
||||
} else if addr.Protocol.IsHTTPSFamily() {
|
||||
httpsConfig.IsOn = true
|
||||
httpsConfig.Listen = append(httpsConfig.Listen, addr)
|
||||
}
|
||||
}
|
||||
|
||||
// 证书
|
||||
certIds := []int64{}
|
||||
if len(params.CertIdsJSON) > 0 {
|
||||
err = json.Unmarshal(params.CertIdsJSON, &certIds)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
if httpsConfig.IsOn && len(httpsConfig.Listen) > 0 && len(certIds) == 0 {
|
||||
this.Fail("请添加至少一个证书")
|
||||
}
|
||||
|
||||
certRefs := []*sslconfigs.SSLCertRef{}
|
||||
for _, certId := range certIds {
|
||||
certRefs = append(certRefs, &sslconfigs.SSLCertRef{
|
||||
IsOn: true,
|
||||
CertId: certId,
|
||||
})
|
||||
}
|
||||
certRefsJSON, err := json.Marshal(certRefs)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
// 创建策略
|
||||
if len(certIds) > 0 {
|
||||
sslPolicyCreateResp, err := this.RPC().SSLPolicyRPC().CreateSSLPolicy(this.AdminContext(), &pb.CreateSSLPolicyRequest{
|
||||
CertsJSON: certRefsJSON,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
sslPolicyId := sslPolicyCreateResp.SslPolicyId
|
||||
httpsConfig.SSLPolicyRef = &sslconfigs.SSLPolicyRef{
|
||||
IsOn: true,
|
||||
SSLPolicyId: sslPolicyId,
|
||||
}
|
||||
}
|
||||
|
||||
// 访问地址
|
||||
accessAddrs := []*serverconfigs.NetworkAddressConfig{}
|
||||
err = json.Unmarshal(params.AccessAddrsJSON, &accessAddrs)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if len(accessAddrs) == 0 {
|
||||
this.Fail("请添加至少一个外部访问地址")
|
||||
}
|
||||
|
||||
httpJSON, err := json.Marshal(httpConfig)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
httpsJSON, err := json.Marshal(httpsConfig)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
createResp, err := this.RPC().UserNodeRPC().CreateUserNode(this.AdminContext(), &pb.CreateUserNodeRequest{
|
||||
Name: params.Name,
|
||||
Description: params.Description,
|
||||
HttpJSON: httpJSON,
|
||||
HttpsJSON: httpsJSON,
|
||||
AccessAddrsJSON: params.AccessAddrsJSON,
|
||||
IsOn: params.IsOn,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
// 创建日志
|
||||
defer this.CreateLog(oplogs.LevelInfo, "创建用户节点 %d", createResp.NodeId)
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package node
|
||||
|
||||
import (
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type Helper struct {
|
||||
}
|
||||
|
||||
func NewHelper() *Helper {
|
||||
return &Helper{}
|
||||
}
|
||||
|
||||
func (this *Helper) BeforeAction(action *actions.ActionObject) (goNext bool) {
|
||||
if action.Request.Method != http.MethodGet {
|
||||
return true
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
102
internal/web/actions/default/settings/user-nodes/node/index.go
Normal file
102
internal/web/actions/default/settings/user-nodes/node/index.go
Normal file
@@ -0,0 +1,102 @@
|
||||
package node
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/sslconfigs"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
type IndexAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *IndexAction) Init() {
|
||||
this.Nav("", "", "index")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct {
|
||||
NodeId int64
|
||||
}) {
|
||||
nodeResp, err := this.RPC().UserNodeRPC().FindEnabledUserNode(this.AdminContext(), &pb.FindEnabledUserNodeRequest{NodeId: params.NodeId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
node := nodeResp.Node
|
||||
if node == nil {
|
||||
this.NotFound("userNode", params.NodeId)
|
||||
return
|
||||
}
|
||||
|
||||
// 监听地址
|
||||
httpConfig := &serverconfigs.HTTPProtocolConfig{}
|
||||
if len(node.HttpJSON) > 0 {
|
||||
err = json.Unmarshal(node.HttpJSON, httpConfig)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
httpsConfig := &serverconfigs.HTTPSProtocolConfig{}
|
||||
if len(node.HttpsJSON) > 0 {
|
||||
err = json.Unmarshal(node.HttpsJSON, httpsConfig)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// 监听地址
|
||||
listens := []*serverconfigs.NetworkAddressConfig{}
|
||||
listens = append(listens, httpConfig.Listen...)
|
||||
listens = append(listens, httpsConfig.Listen...)
|
||||
|
||||
// 证书信息
|
||||
certs := []*sslconfigs.SSLCertConfig{}
|
||||
sslPolicyId := int64(0)
|
||||
if httpsConfig.SSLPolicyRef != nil && httpsConfig.SSLPolicyRef.SSLPolicyId > 0 {
|
||||
sslPolicyConfigResp, err := this.RPC().SSLPolicyRPC().FindEnabledSSLPolicyConfig(this.AdminContext(), &pb.FindEnabledSSLPolicyConfigRequest{SslPolicyId: httpsConfig.SSLPolicyRef.SSLPolicyId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
sslPolicyConfigJSON := sslPolicyConfigResp.SslPolicyJSON
|
||||
if len(sslPolicyConfigJSON) > 0 {
|
||||
sslPolicyId = httpsConfig.SSLPolicyRef.SSLPolicyId
|
||||
|
||||
sslPolicy := &sslconfigs.SSLPolicy{}
|
||||
err = json.Unmarshal(sslPolicyConfigJSON, sslPolicy)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
certs = sslPolicy.Certs
|
||||
}
|
||||
}
|
||||
|
||||
// 访问地址
|
||||
accessAddrs := []*serverconfigs.NetworkAddressConfig{}
|
||||
if len(node.AccessAddrsJSON) > 0 {
|
||||
err = json.Unmarshal(node.AccessAddrsJSON, &accessAddrs)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
this.Data["node"] = maps.Map{
|
||||
"id": node.Id,
|
||||
"name": node.Name,
|
||||
"description": node.Description,
|
||||
"isOn": node.IsOn,
|
||||
"listens": listens,
|
||||
"accessAddrs": accessAddrs,
|
||||
"hasHTTPS": sslPolicyId > 0,
|
||||
"certs": certs,
|
||||
}
|
||||
|
||||
this.Show()
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package node
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/settings/settingutils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
|
||||
"github.com/iwind/TeaGo"
|
||||
)
|
||||
|
||||
func init() {
|
||||
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
||||
server.
|
||||
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeSetting)).
|
||||
Helper(settingutils.NewAdvancedHelper("userNodes")).
|
||||
Prefix("/settings/userNodes/node").
|
||||
|
||||
// 这里不受Helper的约束
|
||||
GetPost("/createAddrPopup", new(CreateAddrPopupAction)).
|
||||
GetPost("/updateAddrPopup", new(UpdateAddrPopupAction)).
|
||||
|
||||
// 节点相关
|
||||
Helper(NewHelper()).
|
||||
Get("", new(IndexAction)).
|
||||
GetPost("/update", new(UpdateAction)).
|
||||
Get("/install", new(InstallAction)).
|
||||
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package node
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type InstallAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *InstallAction) Init() {
|
||||
this.Nav("", "", "install")
|
||||
}
|
||||
|
||||
func (this *InstallAction) RunGet(params struct {
|
||||
NodeId int64
|
||||
}) {
|
||||
// 用户节点信息
|
||||
nodeResp, err := this.RPC().UserNodeRPC().FindEnabledUserNode(this.AdminContext(), &pb.FindEnabledUserNodeRequest{NodeId: params.NodeId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
node := nodeResp.Node
|
||||
if node == nil {
|
||||
this.NotFound("userNode", params.NodeId)
|
||||
return
|
||||
}
|
||||
|
||||
this.Data["node"] = maps.Map{
|
||||
"id": node.Id,
|
||||
"name": node.Name,
|
||||
"uniqueId": node.UniqueId,
|
||||
"secret": node.Secret,
|
||||
}
|
||||
|
||||
// API节点列表
|
||||
apiNodesResp, err := this.RPC().APINodeRPC().FindAllEnabledAPINodes(this.AdminContext(), &pb.FindAllEnabledAPINodesRequest{})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
apiNodes := apiNodesResp.Nodes
|
||||
apiEndpoints := []string{}
|
||||
for _, apiNode := range apiNodes {
|
||||
if !apiNode.IsOn {
|
||||
continue
|
||||
}
|
||||
apiEndpoints = append(apiEndpoints, apiNode.AccessAddrs...)
|
||||
}
|
||||
this.Data["apiEndpoints"] = "\"" + strings.Join(apiEndpoints, "\", \"") + "\""
|
||||
|
||||
this.Show()
|
||||
}
|
||||
240
internal/web/actions/default/settings/user-nodes/node/update.go
Normal file
240
internal/web/actions/default/settings/user-nodes/node/update.go
Normal file
@@ -0,0 +1,240 @@
|
||||
package node
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/oplogs"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/sslconfigs"
|
||||
"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 {
|
||||
NodeId int64
|
||||
}) {
|
||||
nodeResp, err := this.RPC().UserNodeRPC().FindEnabledUserNode(this.AdminContext(), &pb.FindEnabledUserNodeRequest{
|
||||
NodeId: params.NodeId,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
node := nodeResp.Node
|
||||
if node == nil {
|
||||
this.WriteString("要操作的节点不存在")
|
||||
return
|
||||
}
|
||||
|
||||
httpConfig := &serverconfigs.HTTPProtocolConfig{}
|
||||
if len(node.HttpJSON) > 0 {
|
||||
err = json.Unmarshal(node.HttpJSON, httpConfig)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
httpsConfig := &serverconfigs.HTTPSProtocolConfig{}
|
||||
if len(node.HttpsJSON) > 0 {
|
||||
err = json.Unmarshal(node.HttpsJSON, httpsConfig)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// 监听地址
|
||||
listens := []*serverconfigs.NetworkAddressConfig{}
|
||||
listens = append(listens, httpConfig.Listen...)
|
||||
listens = append(listens, httpsConfig.Listen...)
|
||||
|
||||
// 证书信息
|
||||
certs := []*sslconfigs.SSLCertConfig{}
|
||||
sslPolicyId := int64(0)
|
||||
if httpsConfig.SSLPolicyRef != nil && httpsConfig.SSLPolicyRef.SSLPolicyId > 0 {
|
||||
sslPolicyConfigResp, err := this.RPC().SSLPolicyRPC().FindEnabledSSLPolicyConfig(this.AdminContext(), &pb.FindEnabledSSLPolicyConfigRequest{SslPolicyId: httpsConfig.SSLPolicyRef.SSLPolicyId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
sslPolicyConfigJSON := sslPolicyConfigResp.SslPolicyJSON
|
||||
if len(sslPolicyConfigJSON) > 0 {
|
||||
sslPolicyId = httpsConfig.SSLPolicyRef.SSLPolicyId
|
||||
|
||||
sslPolicy := &sslconfigs.SSLPolicy{}
|
||||
err = json.Unmarshal(sslPolicyConfigJSON, sslPolicy)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
certs = sslPolicy.Certs
|
||||
}
|
||||
}
|
||||
|
||||
accessAddrs := []*serverconfigs.NetworkAddressConfig{}
|
||||
if len(node.AccessAddrsJSON) > 0 {
|
||||
err = json.Unmarshal(node.AccessAddrsJSON, &accessAddrs)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
this.Data["node"] = maps.Map{
|
||||
"id": node.Id,
|
||||
"name": node.Name,
|
||||
"description": node.Description,
|
||||
"isOn": node.IsOn,
|
||||
"listens": listens,
|
||||
"certs": certs,
|
||||
"sslPolicyId": sslPolicyId,
|
||||
"accessAddrs": accessAddrs,
|
||||
}
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
// 保存基础设置
|
||||
func (this *UpdateAction) RunPost(params struct {
|
||||
NodeId int64
|
||||
Name string
|
||||
SslPolicyId int64
|
||||
ListensJSON []byte
|
||||
CertIdsJSON []byte
|
||||
AccessAddrsJSON []byte
|
||||
Description string
|
||||
IsOn bool
|
||||
|
||||
Must *actions.Must
|
||||
}) {
|
||||
params.Must.
|
||||
Field("name", params.Name).
|
||||
Require("请输入用户节点名称")
|
||||
|
||||
httpConfig := &serverconfigs.HTTPProtocolConfig{}
|
||||
httpsConfig := &serverconfigs.HTTPSProtocolConfig{}
|
||||
|
||||
// 监听地址
|
||||
listens := []*serverconfigs.NetworkAddressConfig{}
|
||||
err := json.Unmarshal(params.ListensJSON, &listens)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if len(listens) == 0 {
|
||||
this.Fail("请添加至少一个进程监听地址")
|
||||
}
|
||||
for _, addr := range listens {
|
||||
if addr.Protocol.IsHTTPFamily() {
|
||||
httpConfig.IsOn = true
|
||||
httpConfig.Listen = append(httpConfig.Listen, addr)
|
||||
} else if addr.Protocol.IsHTTPSFamily() {
|
||||
httpsConfig.IsOn = true
|
||||
httpsConfig.Listen = append(httpsConfig.Listen, addr)
|
||||
}
|
||||
}
|
||||
|
||||
// 证书
|
||||
certIds := []int64{}
|
||||
if len(params.CertIdsJSON) > 0 {
|
||||
err = json.Unmarshal(params.CertIdsJSON, &certIds)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
if httpsConfig.IsOn && len(httpsConfig.Listen) > 0 && len(certIds) == 0 {
|
||||
this.Fail("请添加至少一个证书")
|
||||
}
|
||||
|
||||
certRefs := []*sslconfigs.SSLCertRef{}
|
||||
for _, certId := range certIds {
|
||||
certRefs = append(certRefs, &sslconfigs.SSLCertRef{
|
||||
IsOn: true,
|
||||
CertId: certId,
|
||||
})
|
||||
}
|
||||
certRefsJSON, err := json.Marshal(certRefs)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
// 创建策略
|
||||
sslPolicyId := params.SslPolicyId
|
||||
if sslPolicyId == 0 {
|
||||
if len(certIds) > 0 {
|
||||
sslPolicyCreateResp, err := this.RPC().SSLPolicyRPC().CreateSSLPolicy(this.AdminContext(), &pb.CreateSSLPolicyRequest{
|
||||
CertsJSON: certRefsJSON,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
sslPolicyId = sslPolicyCreateResp.SslPolicyId
|
||||
}
|
||||
} else {
|
||||
_, err = this.RPC().SSLPolicyRPC().UpdateSSLPolicy(this.AdminContext(), &pb.UpdateSSLPolicyRequest{
|
||||
SslPolicyId: sslPolicyId,
|
||||
CertsJSON: certRefsJSON,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
httpsConfig.SSLPolicyRef = &sslconfigs.SSLPolicyRef{
|
||||
IsOn: true,
|
||||
SSLPolicyId: sslPolicyId,
|
||||
}
|
||||
|
||||
// 访问地址
|
||||
accessAddrs := []*serverconfigs.NetworkAddressConfig{}
|
||||
err = json.Unmarshal(params.AccessAddrsJSON, &accessAddrs)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if len(accessAddrs) == 0 {
|
||||
this.Fail("请添加至少一个外部访问地址")
|
||||
}
|
||||
|
||||
httpJSON, err := json.Marshal(httpConfig)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
httpsJSON, err := json.Marshal(httpsConfig)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
_, err = this.RPC().UserNodeRPC().UpdateUserNode(this.AdminContext(), &pb.UpdateUserNodeRequest{
|
||||
NodeId: params.NodeId,
|
||||
Name: params.Name,
|
||||
Description: params.Description,
|
||||
HttpJSON: httpJSON,
|
||||
HttpsJSON: httpsJSON,
|
||||
AccessAddrsJSON: params.AccessAddrsJSON,
|
||||
IsOn: params.IsOn,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
// 创建日志
|
||||
defer this.CreateLog(oplogs.LevelInfo, "修改用户节点 %d", params.NodeId)
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package node
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"net"
|
||||
)
|
||||
|
||||
type UpdateAddrPopupAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *UpdateAddrPopupAction) Init() {
|
||||
this.Nav("", "", "")
|
||||
}
|
||||
|
||||
func (this *UpdateAddrPopupAction) RunGet(params struct{}) {
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *UpdateAddrPopupAction) RunPost(params struct {
|
||||
Protocol string
|
||||
Addr string
|
||||
Must *actions.Must
|
||||
}) {
|
||||
params.Must.
|
||||
Field("addr", params.Addr).
|
||||
Require("请输入访问地址")
|
||||
host, port, err := net.SplitHostPort(params.Addr)
|
||||
if err != nil {
|
||||
this.FailField("addr", "错误的访问地址")
|
||||
}
|
||||
|
||||
addrConfig := &serverconfigs.NetworkAddressConfig{
|
||||
Protocol: serverconfigs.Protocol(params.Protocol),
|
||||
Host: host,
|
||||
PortRange: port,
|
||||
}
|
||||
this.Data["addr"] = addrConfig
|
||||
this.Success()
|
||||
}
|
||||
@@ -226,6 +226,13 @@ func (this *userMustAuth) modules(adminId int64) []maps.Map {
|
||||
"module": configloaders.AdminModuleCodeSetting,
|
||||
"name": "系统设置",
|
||||
"icon": "setting",
|
||||
"subItems": []maps.Map{
|
||||
{
|
||||
"name": "高级设置",
|
||||
"url": "/settings/advanced",
|
||||
"code": "advanced",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -85,6 +85,7 @@ import (
|
||||
_ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/settings/server"
|
||||
_ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/settings/ui"
|
||||
_ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/settings/upgrade"
|
||||
_ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/settings/user-nodes"
|
||||
_ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/setup"
|
||||
_ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/ui"
|
||||
_ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/users"
|
||||
|
||||
@@ -2,7 +2,7 @@ Vue.component("network-addresses-view", {
|
||||
props: ["v-addresses"],
|
||||
template: `<div>
|
||||
<div class="ui label tiny basic" v-if="vAddresses != null" v-for="addr in vAddresses">
|
||||
{{addr.protocol}}://{{addr.host}}:{{addr.portRange}}
|
||||
{{addr.protocol}}://<span v-if="addr.host.length > 0">{{addr.host}}</span><span v-else>*</span>:{{addr.portRange}}
|
||||
</div>
|
||||
</div>`
|
||||
})
|
||||
35
web/views/@default/settings/user-nodes/index.html
Normal file
35
web/views/@default/settings/user-nodes/index.html
Normal file
@@ -0,0 +1,35 @@
|
||||
{$layout}
|
||||
|
||||
<first-menu>
|
||||
<a href="" class="item" @click.prevent="createNode()">[添加节点]</a>
|
||||
</first-menu>
|
||||
|
||||
<p class="comment" v-if="nodes.length == 0">暂时还没有节点。</p>
|
||||
|
||||
<table class="ui table selectable celled" v-if="nodes.length > 0">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>节点名称</th>
|
||||
<th>访问地址</th>
|
||||
<th class="center width10">状态</th>
|
||||
<th class="two op">操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr v-for="node in nodes">
|
||||
<td>{{node.name}}</td>
|
||||
<td>
|
||||
<div v-if="node.accessAddrs != null && node.accessAddrs.length > 0">
|
||||
<span class="ui label tiny basic" v-for="addr in node.accessAddrs">{{addr}}</span>
|
||||
</div>
|
||||
</td>
|
||||
<td class="center">
|
||||
<label-on :v-is-on="node.isOn"></label-on>
|
||||
</td>
|
||||
<td>
|
||||
<a :href="'/settings/userNodes/node?nodeId=' + node.id">详情</a>
|
||||
<a href="" @click.prevent="deleteNode(node.id)">删除</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<div class="page" v-html="page"></div>
|
||||
26
web/views/@default/settings/user-nodes/index.js
Normal file
26
web/views/@default/settings/user-nodes/index.js
Normal file
@@ -0,0 +1,26 @@
|
||||
Tea.context(function () {
|
||||
// 创建节点
|
||||
this.createNode = function () {
|
||||
teaweb.popup("/settings/userNodes/node/createPopup", {
|
||||
width: "50em",
|
||||
height: "30em",
|
||||
callback: function () {
|
||||
teaweb.success("保存成功", function () {
|
||||
teaweb.reload()
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 删除节点
|
||||
this.deleteNode = function (nodeId) {
|
||||
let that = this
|
||||
teaweb.confirm("确定要删除此节点吗?", function () {
|
||||
that.$post("/settings/userNodes/delete")
|
||||
.params({
|
||||
nodeId: nodeId
|
||||
})
|
||||
.refresh()
|
||||
})
|
||||
}
|
||||
})
|
||||
7
web/views/@default/settings/user-nodes/node/@menu.html
Normal file
7
web/views/@default/settings/user-nodes/node/@menu.html
Normal file
@@ -0,0 +1,7 @@
|
||||
<first-menu>
|
||||
<menu-item href="/settings/userNodes">节点列表</menu-item>
|
||||
<span class="item">|</span>
|
||||
<menu-item :href="'/settings/userNodes/node?nodeId=' + node.id" code="index">"{{node.name}}"详情</menu-item>
|
||||
<menu-item :href="'/settings/userNodes/node/install?nodeId=' + node.id" code="install">安装节点</menu-item>
|
||||
<menu-item :href="'/settings/userNodes/node/update?nodeId=' + node.id" code="update">修改节点</menu-item>
|
||||
</first-menu>
|
||||
@@ -0,0 +1,24 @@
|
||||
{$layout "layout_popup"}
|
||||
|
||||
<h3>添加访问地址</h3>
|
||||
<form class="ui form" method="post" data-tea-action="$" data-tea-success="success">
|
||||
<table class="ui table definition selectable">
|
||||
<tr>
|
||||
<td>网络协议</td>
|
||||
<td>
|
||||
<select class="ui dropdown auto-width" name="protocol">
|
||||
<option value="http">HTTP</option>
|
||||
<option value="https">HTTPS</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="title">访问地址</td>
|
||||
<td>
|
||||
<input type="text" name="addr" maxlength="100" ref="focus"/>
|
||||
<p class="comment">可以是"IP:端口"或者"域名:端口"。</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<submit-btn></submit-btn>
|
||||
</form>
|
||||
55
web/views/@default/settings/user-nodes/node/createPopup.html
Normal file
55
web/views/@default/settings/user-nodes/node/createPopup.html
Normal file
@@ -0,0 +1,55 @@
|
||||
{$layout "layout_popup"}
|
||||
|
||||
<h3>添加用户节点</h3>
|
||||
<form class="ui form" method="post" data-tea-action="$" data-tea-success="success">
|
||||
<table class="ui table selectable definition">
|
||||
<tr>
|
||||
<td class="title">节点名称 *</td>
|
||||
<td>
|
||||
<input type="text" name="name" maxlength="100" ref="focus"/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>进程监听端口 *</td>
|
||||
<td>
|
||||
<network-addresses-box :v-name="'listensJSON'" :v-server-type="'httpWeb'" @change="changeListens"></network-addresses-box>
|
||||
<p class="comment">用户节点进程监听的网络端口。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-if="hasHTTPS">
|
||||
<td>HTTPS证书 *</td>
|
||||
<td>
|
||||
<ssl-certs-box :v-protocol="'https'"></ssl-certs-box>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>外部访问地址 *</td>
|
||||
<td>
|
||||
<api-node-addresses-box :v-name="'accessAddrsJSON'"></api-node-addresses-box>
|
||||
<p class="comment">可以公开访问的网络地址。</p>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td colspan="2"><more-options-indicator></more-options-indicator></td>
|
||||
</tr>
|
||||
<tbody v-show="moreOptionsVisible">
|
||||
<tr>
|
||||
<td>描述</td>
|
||||
<td>
|
||||
<textarea name="description" maxlength="200" rows="3"></textarea>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>是否启用</td>
|
||||
<td>
|
||||
<div class="ui checkbox">
|
||||
<input type="checkbox" name="isOn" value="1" checked="checked"/>
|
||||
<label></label>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<submit-btn></submit-btn>
|
||||
</form>
|
||||
@@ -0,0 +1,8 @@
|
||||
Tea.context(function () {
|
||||
this.hasHTTPS = false
|
||||
this.changeListens = function (addrs) {
|
||||
this.hasHTTPS = addrs.$any(function (k, v) {
|
||||
return v.protocol == "https"
|
||||
})
|
||||
}
|
||||
})
|
||||
44
web/views/@default/settings/user-nodes/node/index.html
Normal file
44
web/views/@default/settings/user-nodes/node/index.html
Normal file
@@ -0,0 +1,44 @@
|
||||
{$layout}
|
||||
{$template "menu"}
|
||||
|
||||
<table class="ui table selectable definition">
|
||||
<tr>
|
||||
<td class="title">节点名称</td>
|
||||
<td>
|
||||
{{node.name}}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>状态</td>
|
||||
<td>
|
||||
<label-on :v-is-on="node.isOn"></label-on>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>进程监听端口</td>
|
||||
<td>
|
||||
<network-addresses-view :v-addresses="node.listens"></network-addresses-view>
|
||||
<p class="comment">用户节点进程监听的网络端口。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-if="node.hasHTTPS">
|
||||
<td>HTTPS证书</td>
|
||||
<td>
|
||||
<ssl-certs-view :v-certs="node.certs"></ssl-certs-view>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>外部访问地址</td>
|
||||
<td>
|
||||
<network-addresses-view :v-addresses="node.accessAddrs"></network-addresses-view>
|
||||
<p class="comment">可以公开访问的网络地址。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>描述</td>
|
||||
<td>
|
||||
<span v-if="node.description.length > 0">{{node.description}}</span>
|
||||
<span v-else class="disabled">暂时还没有描述。</span>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
23
web/views/@default/settings/user-nodes/node/install.html
Normal file
23
web/views/@default/settings/user-nodes/node/install.html
Normal file
@@ -0,0 +1,23 @@
|
||||
{$layout}
|
||||
{$template "menu"}
|
||||
|
||||
<h3>安装步骤</h3>
|
||||
<ol class="ui list">
|
||||
<li>按照下面的配置信息替换<code-label>configs/api.yaml</code-label>内容</li>
|
||||
<li>使用<code-label>bin/edge-user start</code-label>启动节点</li>
|
||||
<li>可以在<code-label>logs/run.log</code-label>中查看启动是否有异常</li>
|
||||
</ol>
|
||||
|
||||
<div class="ui divider"></div>
|
||||
<h3>配置信息</h3>
|
||||
<table class="ui table definition selectable">
|
||||
<tr>
|
||||
<td class="title">configs/api.yaml<em><br/><download-link :v-element="'api-code'" :v-file="'api.yaml'">[下载]</download-link></em></td>
|
||||
<td>
|
||||
<pre id="api-code">rpc:
|
||||
endpoints: [ {{apiEndpoints}} ]
|
||||
nodeId: "{{node.uniqueId}}"
|
||||
secret: "{{node.secret}}"</pre>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
58
web/views/@default/settings/user-nodes/node/update.html
Normal file
58
web/views/@default/settings/user-nodes/node/update.html
Normal file
@@ -0,0 +1,58 @@
|
||||
{$layout}
|
||||
|
||||
{$template "menu"}
|
||||
|
||||
<form method="post" class="ui form" data-tea-action="$" data-tea-success="success">
|
||||
<input type="hidden" name="nodeId" :value="node.id"/>
|
||||
<input type="hidden" name="sslPolicyId" :value="node.sslPolicyId"/>
|
||||
<table class="ui table selectable definition">
|
||||
<tr>
|
||||
<td class="title">节点名称 *</td>
|
||||
<td>
|
||||
<input type="text" name="name" maxlength="100" ref="focus" v-model="node.name"/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>进程监听端口 *</td>
|
||||
<td>
|
||||
<network-addresses-box :v-name="'listensJSON'" :v-server-type="'httpWeb'" :v-addresses="node.listens" @change="changeListens"></network-addresses-box>
|
||||
<p class="comment">API节点进程监听的网络端口。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-if="hasHTTPS">
|
||||
<td>HTTPS证书 *</td>
|
||||
<td>
|
||||
<ssl-certs-box :v-certs="node.certs" :v-protocol="'https'"></ssl-certs-box>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>外部访问地址 *</td>
|
||||
<td>
|
||||
<api-node-addresses-box :v-name="'accessAddrsJSON'" :v-addrs="node.accessAddrs"></api-node-addresses-box>
|
||||
<p class="comment">边缘节点和管理平台等外部节点访问API节点的网络地址。</p>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td colspan="2"><more-options-indicator></more-options-indicator></td>
|
||||
</tr>
|
||||
<tbody v-show="moreOptionsVisible">
|
||||
<tr>
|
||||
<td>描述</td>
|
||||
<td>
|
||||
<textarea name="description" maxlength="200" rows="3" v-model="node.description"></textarea>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>是否启用</td>
|
||||
<td>
|
||||
<div class="ui checkbox">
|
||||
<input type="checkbox" name="isOn" value="1" v-model="node.isOn"/>
|
||||
<label></label>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<submit-btn></submit-btn>
|
||||
</form>
|
||||
12
web/views/@default/settings/user-nodes/node/update.js
Normal file
12
web/views/@default/settings/user-nodes/node/update.js
Normal file
@@ -0,0 +1,12 @@
|
||||
Tea.context(function () {
|
||||
this.success = NotifySuccess("保存成功", "/settings/userNodes/node?nodeId=" + this.node.id)
|
||||
|
||||
this.hasHTTPS = this.node.listens.$any(function (k, v) {
|
||||
return v.protocol == "https"
|
||||
})
|
||||
this.changeListens = function (addrs) {
|
||||
this.hasHTTPS = addrs.$any(function (k, v) {
|
||||
return v.protocol == "https"
|
||||
})
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,24 @@
|
||||
{$layout "layout_popup"}
|
||||
|
||||
<h3>修改访问地址</h3>
|
||||
<form method="post" class="ui form" data-tea-action="$" data-tea-success="success">
|
||||
<table class="ui table definition selectable">
|
||||
<tr>
|
||||
<td>网络协议</td>
|
||||
<td>
|
||||
<select class="ui dropdown auto-width" name="protocol" v-model="protocol">
|
||||
<option value="http">HTTP</option>
|
||||
<option value="https">HTTPS</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="title">访问地址</td>
|
||||
<td>
|
||||
<input type="text" name="addr" maxlength="100" ref="focus" v-model="addr"/>
|
||||
<p class="comment">可以是"IP:端口"或者"域名:端口"。</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<submit-btn></submit-btn>
|
||||
</form>
|
||||
@@ -0,0 +1,5 @@
|
||||
Tea.context(function () {
|
||||
let addr = window.parent.UPDATING_ADDR
|
||||
this.protocol = addr.protocol
|
||||
this.addr = addr.host + ":" + addr.portRange
|
||||
})
|
||||
Reference in New Issue
Block a user