支持更多的分组全局设置功能

This commit is contained in:
GoEdgeLab
2021-10-07 16:47:14 +08:00
parent 17b03ff76d
commit 39bf5c70bd
126 changed files with 3969 additions and 220 deletions

View File

@@ -4,6 +4,7 @@ package servergrouputils
import (
"errors"
teaconst "github.com/TeaOSLab/EdgeAdmin/internal/const"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/maps"
@@ -35,75 +36,109 @@ func InitGroup(parent *actionutils.ParentAction, groupId int64, menuItem string)
}
var urlPrefix = "/servers/groups/group/settings"
parent.Data["leftMenuItems"] = []maps.Map{
/**{
"name": "Web设置",
"url": urlPrefix + "/web?groupId=" + types.String(groupId),
"isActive": menuItem == "web",
},**/
var leftMenuItems = []maps.Map{
{
"name": "HTTP反向代理",
"name": "HTTP代理",
"url": urlPrefix + "/httpReverseProxy?groupId=" + types.String(groupId),
"isActive": menuItem == "httpReverseProxy",
"isOn": configInfoResp.HasHTTPReverseProxy,
},
{
"name": "TCP反向代理",
"name": "TCP代理",
"url": urlPrefix + "/tcpReverseProxy?groupId=" + types.String(groupId),
"isActive": menuItem == "tcpReverseProxy",
"isOn": configInfoResp.HasTCPReverseProxy,
},
{
"name": "UDP反向代理",
"name": "UDP代理",
"url": urlPrefix + "/udpReverseProxy?groupId=" + types.String(groupId),
"isActive": menuItem == "udpReverseProxy",
"isOn": configInfoResp.HasUDPReverseProxy,
},
/**{
"name": "-",
"url": "",
},
{
"name": "WAF",
"url": urlPrefix + "/waf?groupId=" + types.String(groupId),
"isActive": menuItem == "waf",
},
{
"name": "缓存",
"url": urlPrefix + "/cache?groupId=" + types.String(groupId),
"isActive": menuItem == "cache",
},
{
"name": "访问日志",
"url": urlPrefix + "/accessLog?groupId=" + types.String(groupId),
"isActive": menuItem == "accessLog",
},
{
"name": "统计",
"url": urlPrefix + "/stat?groupId=" + types.String(groupId),
"isActive": menuItem == "stat",
},
{
"name": "Gzip压缩",
"url": urlPrefix + "/gzip?groupId=" + types.String(groupId),
"isActive": menuItem == "gzip",
},
{
"name": "特殊页面",
"url": urlPrefix + "/pages?groupId=" + types.String(groupId),
"isActive": menuItem == "page",
},
{
"name": "HTTP Header",
"url": urlPrefix + "/headers?groupId=" + types.String(groupId),
"isActive": menuItem == "header",
},
{
"name": "Websocket",
"url": urlPrefix + "/websocket?groupId=" + types.String(groupId),
"isActive": menuItem == "websocket",
},**/
}
if teaconst.IsPlus {
leftMenuItems = append([]maps.Map{
{
"name": "Web设置",
"url": urlPrefix + "/web?groupId=" + types.String(groupId),
"isActive": menuItem == "web",
"isOn": configInfoResp.HasRootConfig,
},
}, leftMenuItems...)
leftMenuItems = append(leftMenuItems, []maps.Map{
{
"name": "-",
"url": "",
},
{
"name": "WAF",
"url": urlPrefix + "/waf?groupId=" + types.String(groupId),
"isActive": menuItem == "waf",
"isOn": configInfoResp.HasWAFConfig,
},
{
"name": "缓存",
"url": urlPrefix + "//cache?groupId=" + types.String(groupId),
"isActive": menuItem == "cache",
"isOn": configInfoResp.HasCacheConfig,
},
{
"name": "字符编码",
"url": urlPrefix + "/charset?groupId=" + types.String(groupId),
"isActive": menuItem == "charset",
"isOn": configInfoResp.HasCharsetConfig,
},
{
"name": "访问日志",
"url": urlPrefix + "/accessLog?groupId=" + types.String(groupId),
"isActive": menuItem == "accessLog",
"isOn": configInfoResp.HasAccessLogConfig,
},
{
"name": "统计",
"url": urlPrefix + "/stat?groupId=" + types.String(groupId),
"isActive": menuItem == "stat",
"isOn": configInfoResp.HasStatConfig,
},
{
"name": "内容压缩",
"url": urlPrefix + "/compression?groupId=" + types.String(groupId),
"isActive": menuItem == "compression",
"isOn": configInfoResp.HasCompressionConfig,
},
{
"name": "HTTP Header",
"url": urlPrefix + "/headers?groupId=" + types.String(groupId),
"isActive": menuItem == "headers",
"isOn": configInfoResp.HasRequestHeadersConfig || configInfoResp.HasResponseHeadersConfig,
},
{
"name": "Websocket",
"url": urlPrefix + "/websocket?groupId=" + types.String(groupId),
"isActive": menuItem == "websocket",
"isOn": configInfoResp.HasWebsocketConfig,
},
{
"name": "WebP",
"url": urlPrefix + "/webp?groupId=" + types.String(groupId),
"isActive": menuItem == "webp",
"isOn": configInfoResp.HasWebPConfig,
},
}...)
}
leftMenuItems = append(leftMenuItems, maps.Map{
"name": "-",
"url": "",
})
leftMenuItems = append(leftMenuItems, maps.Map{
"name": "访客IP地址",
"url": urlPrefix + "/remoteAddr?groupId=" + types.String(groupId),
"isActive": menuItem == "remoteAddr",
"isOn": configInfoResp.HasRemoteAddrConfig,
})
parent.Data["leftMenuItems"] = leftMenuItems
}
return group, nil

View File

@@ -0,0 +1,68 @@
package accessLog
import (
"github.com/TeaOSLab/EdgeAdmin/internal/oplogs"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/groups/group/servergrouputils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
"github.com/iwind/TeaGo/actions"
)
type IndexAction struct {
actionutils.ParentAction
}
func (this *IndexAction) Init() {
this.Nav("", "setting", "index")
this.SecondMenu("accessLog")
}
func (this *IndexAction) RunGet(params struct {
GroupId int64
}) {
_, err := servergrouputils.InitGroup(this.Parent(), params.GroupId, "accessLog")
if err != nil {
this.ErrorPage(err)
return
}
// 获取配置
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithServerGroupId(this.AdminContext(), params.GroupId)
if err != nil {
this.ErrorPage(err)
return
}
this.Data["webId"] = webConfig.Id
this.Data["accessLogConfig"] = webConfig.AccessLogRef
// 通用变量
this.Data["fields"] = serverconfigs.HTTPAccessLogFields
this.Data["defaultFieldCodes"] = serverconfigs.HTTPAccessLogDefaultFieldsCodes
this.Show()
}
func (this *IndexAction) RunPost(params struct {
WebId int64
AccessLogJSON []byte
Must *actions.Must
}) {
// 日志
defer this.CreateLog(oplogs.LevelInfo, "修改Web %d 的访问日志设置", params.WebId)
// TODO 检查参数
_, err := this.RPC().HTTPWebRPC().UpdateHTTPWebAccessLog(this.AdminContext(), &pb.UpdateHTTPWebAccessLogRequest{
WebId: params.WebId,
AccessLogJSON: params.AccessLogJSON,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -0,0 +1,19 @@
package accessLog
import (
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
"github.com/iwind/TeaGo"
)
func init() {
TeaGo.BeforeStart(func(server *TeaGo.Server) {
server.
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeServer)).
Data("teaMenu", "servers").
Data("teaSubMenu", "group").
Prefix("/servers/groups/group/settings/accessLog").
GetPost("", new(IndexAction)).
EndAll()
})
}

View File

@@ -0,0 +1,88 @@
package cache
import (
"encoding/json"
"github.com/TeaOSLab/EdgeAdmin/internal/oplogs"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/groups/group/servergrouputils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
"github.com/iwind/TeaGo/actions"
)
type IndexAction struct {
actionutils.ParentAction
}
func (this *IndexAction) Init() {
this.Nav("", "setting", "index")
this.SecondMenu("cache")
}
func (this *IndexAction) RunGet(params struct {
GroupId int64
}) {
_, err := servergrouputils.InitGroup(this.Parent(), params.GroupId, "cache")
if err != nil {
this.ErrorPage(err)
return
}
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithServerGroupId(this.AdminContext(), params.GroupId)
if err != nil {
this.ErrorPage(err)
return
}
this.Data["webId"] = webConfig.Id
this.Data["cacheConfig"] = webConfig.Cache
this.Data["cachePolicy"] = nil
this.Show()
}
func (this *IndexAction) RunPost(params struct {
WebId int64
CacheJSON []byte
Must *actions.Must
}) {
// 日志
defer this.CreateLog(oplogs.LevelInfo, "修改Web %d 的缓存设置", params.WebId)
// 校验配置
cacheConfig := &serverconfigs.HTTPCacheConfig{}
err := json.Unmarshal(params.CacheJSON, cacheConfig)
if err != nil {
this.ErrorPage(err)
return
}
err = cacheConfig.Init()
if err != nil {
this.Fail("检查配置失败:" + err.Error())
}
// 去除不必要的部分
for _, cacheRef := range cacheConfig.CacheRefs {
cacheRef.CachePolicy = nil
}
cacheJSON, err := json.Marshal(cacheConfig)
if err != nil {
this.ErrorPage(err)
return
}
_, err = this.RPC().HTTPWebRPC().UpdateHTTPWebCache(this.AdminContext(), &pb.UpdateHTTPWebCacheRequest{
WebId: params.WebId,
CacheJSON: cacheJSON,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -0,0 +1,21 @@
package cache
import (
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
"github.com/iwind/TeaGo"
)
func init() {
TeaGo.BeforeStart(func(server *TeaGo.Server) {
server.
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeServer)).
Data("teaMenu", "servers").
Data("teaSubMenu", "group").
Prefix("/servers/groups/group/settings/cache").
GetPost("", new(IndexAction)).
GetPost("/purge", new(PurgeAction)).
GetPost("/preheat", new(PreheatAction)).
EndAll()
})
}

View File

@@ -0,0 +1,143 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package cache
import (
"github.com/TeaOSLab/EdgeAdmin/internal/oplogs"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/nodes/nodeutils"
"github.com/TeaOSLab/EdgeCommon/pkg/messageconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/actions"
"github.com/iwind/TeaGo/lists"
"strings"
)
type PreheatAction struct {
actionutils.ParentAction
}
func (this *PreheatAction) Init() {
this.Nav("", "setting", "preheat")
this.SecondMenu("cache")
}
func (this *PreheatAction) RunGet(params struct {
ServerId int64
}) {
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithServerId(this.AdminContext(), params.ServerId)
if err != nil {
this.ErrorPage(err)
return
}
this.Data["webId"] = webConfig.Id
this.Data["webConfig"] = webConfig
this.Show()
}
func (this *PreheatAction) RunPost(params struct {
ServerId int64
WebId int64
Keys string
Must *actions.Must
}) {
// 创建日志
defer this.CreateLog(oplogs.LevelInfo, "预热服务 %d 缓存", params.ServerId)
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithId(this.AdminContext(), params.WebId)
if err != nil {
this.ErrorPage(err)
return
}
if webConfig == nil {
this.NotFound("httpWeb", params.WebId)
return
}
var cache = webConfig.Cache
if cache == nil || !cache.IsOn {
this.Fail("当前没有开启缓存")
}
serverResp, err := this.RPC().ServerRPC().FindEnabledUserServerBasic(this.AdminContext(), &pb.FindEnabledUserServerBasicRequest{ServerId: params.ServerId})
if err != nil {
this.ErrorPage(err)
return
}
var server = serverResp.Server
if server == nil || server.NodeCluster == nil {
this.NotFound("server", params.ServerId)
return
}
var clusterId = server.NodeCluster.Id
clusterResp, err := this.RPC().NodeClusterRPC().FindEnabledNodeCluster(this.AdminContext(), &pb.FindEnabledNodeClusterRequest{NodeClusterId: clusterId})
if err != nil {
this.ErrorPage(err)
return
}
var cluster = clusterResp.NodeCluster
if cluster == nil {
this.NotFound("nodeCluster", clusterId)
return
}
var cachePolicyId = cluster.HttpCachePolicyId
if cachePolicyId == 0 {
this.Fail("当前集群没有设置缓存策略")
}
cachePolicyResp, err := this.RPC().HTTPCachePolicyRPC().FindEnabledHTTPCachePolicyConfig(this.AdminContext(), &pb.FindEnabledHTTPCachePolicyConfigRequest{HttpCachePolicyId: cachePolicyId})
if err != nil {
this.ErrorPage(err)
return
}
cachePolicyJSON := cachePolicyResp.HttpCachePolicyJSON
if len(cachePolicyJSON) == 0 {
this.Fail("找不到要操作的缓存策略")
}
if len(params.Keys) == 0 {
this.Fail("请输入要预热的Key列表")
}
realKeys := []string{}
for _, key := range strings.Split(params.Keys, "\n") {
key = strings.TrimSpace(key)
if len(key) == 0 {
continue
}
if lists.ContainsString(realKeys, key) {
continue
}
realKeys = append(realKeys, key)
}
// 发送命令
msg := &messageconfigs.PreheatCacheMessage{
CachePolicyJSON: cachePolicyJSON,
Keys: realKeys,
}
results, err := nodeutils.SendMessageToCluster(this.AdminContext(), clusterId, messageconfigs.MessageCodePreheatCache, msg, 300)
if err != nil {
this.ErrorPage(err)
return
}
isAllOk := true
for _, result := range results {
if !result.IsOK {
isAllOk = false
break
}
}
this.Data["isAllOk"] = isAllOk
this.Data["results"] = results
this.Success()
}

View File

@@ -0,0 +1,149 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package cache
import (
"github.com/TeaOSLab/EdgeAdmin/internal/oplogs"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/nodes/nodeutils"
"github.com/TeaOSLab/EdgeCommon/pkg/messageconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/actions"
"github.com/iwind/TeaGo/lists"
"strings"
)
type PurgeAction struct {
actionutils.ParentAction
}
func (this *PurgeAction) Init() {
this.Nav("", "setting", "purge")
this.SecondMenu("cache")
}
func (this *PurgeAction) RunGet(params struct {
ServerId int64
}) {
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithServerId(this.AdminContext(), params.ServerId)
if err != nil {
this.ErrorPage(err)
return
}
this.Data["webId"] = webConfig.Id
this.Data["webConfig"] = webConfig
this.Show()
}
func (this *PurgeAction) RunPost(params struct {
ServerId int64
WebId int64
Type string
Keys string
Must *actions.Must
}) {
// 创建日志
defer this.CreateLog(oplogs.LevelInfo, "删除服务 %d 缓存", params.ServerId)
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithId(this.AdminContext(), params.WebId)
if err != nil {
this.ErrorPage(err)
return
}
if webConfig == nil {
this.NotFound("httpWeb", params.WebId)
return
}
var cache = webConfig.Cache
if cache == nil || !cache.IsOn {
this.Fail("当前没有开启缓存")
}
serverResp, err := this.RPC().ServerRPC().FindEnabledUserServerBasic(this.AdminContext(), &pb.FindEnabledUserServerBasicRequest{ServerId: params.ServerId})
if err != nil {
this.ErrorPage(err)
return
}
var server = serverResp.Server
if server == nil || server.NodeCluster == nil {
this.NotFound("server", params.ServerId)
return
}
var clusterId = server.NodeCluster.Id
clusterResp, err := this.RPC().NodeClusterRPC().FindEnabledNodeCluster(this.AdminContext(), &pb.FindEnabledNodeClusterRequest{NodeClusterId: clusterId})
if err != nil {
this.ErrorPage(err)
return
}
var cluster = clusterResp.NodeCluster
if cluster == nil {
this.NotFound("nodeCluster", clusterId)
return
}
var cachePolicyId = cluster.HttpCachePolicyId
if cachePolicyId == 0 {
this.Fail("当前集群没有设置缓存策略")
}
cachePolicyResp, err := this.RPC().HTTPCachePolicyRPC().FindEnabledHTTPCachePolicyConfig(this.AdminContext(), &pb.FindEnabledHTTPCachePolicyConfigRequest{HttpCachePolicyId: cachePolicyId})
if err != nil {
this.ErrorPage(err)
return
}
cachePolicyJSON := cachePolicyResp.HttpCachePolicyJSON
if len(cachePolicyJSON) == 0 {
this.Fail("找不到要操作的缓存策略")
}
if len(params.Keys) == 0 {
this.Fail("请输入要删除的Key列表")
}
realKeys := []string{}
for _, key := range strings.Split(params.Keys, "\n") {
key = strings.TrimSpace(key)
if len(key) == 0 {
continue
}
if lists.ContainsString(realKeys, key) {
continue
}
realKeys = append(realKeys, key)
}
// 发送命令
msg := &messageconfigs.PurgeCacheMessage{
CachePolicyJSON: cachePolicyJSON,
Keys: realKeys,
}
if params.Type == "prefix" {
msg.Type = messageconfigs.PurgeCacheMessageTypeDir
} else {
msg.Type = messageconfigs.PurgeCacheMessageTypeFile
}
results, err := nodeutils.SendMessageToCluster(this.AdminContext(), clusterId, messageconfigs.MessageCodePurgeCache, msg, 10)
if err != nil {
this.ErrorPage(err)
return
}
isAllOk := true
for _, result := range results {
if !result.IsOK {
isAllOk = false
break
}
}
this.Data["isAllOk"] = isAllOk
this.Data["results"] = results
this.Success()
}

View File

@@ -0,0 +1,64 @@
package charset
import (
"github.com/TeaOSLab/EdgeAdmin/internal/oplogs"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/groups/group/servergrouputils"
"github.com/TeaOSLab/EdgeCommon/pkg/configutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/actions"
)
type IndexAction struct {
actionutils.ParentAction
}
func (this *IndexAction) Init() {
this.Nav("", "setting", "index")
this.SecondMenu("charset")
}
func (this *IndexAction) RunGet(params struct {
GroupId int64
}) {
_, err := servergrouputils.InitGroup(this.Parent(), params.GroupId, "charset")
if err != nil {
this.ErrorPage(err)
return
}
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithServerGroupId(this.AdminContext(), params.GroupId)
if err != nil {
this.ErrorPage(err)
return
}
this.Data["webId"] = webConfig.Id
this.Data["charsetConfig"] = webConfig.Charset
this.Data["usualCharsets"] = configutils.UsualCharsets
this.Data["allCharsets"] = configutils.AllCharsets
this.Show()
}
func (this *IndexAction) RunPost(params struct {
WebId int64
CharsetJSON []byte
Must *actions.Must
}) {
defer this.CreateLog(oplogs.LevelInfo, "修改Web %d 的字符集设置", params.WebId)
_, err := this.RPC().HTTPWebRPC().UpdateHTTPWebCharset(this.AdminContext(), &pb.UpdateHTTPWebCharsetRequest{
WebId: params.WebId,
CharsetJSON: params.CharsetJSON,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -0,0 +1,19 @@
package charset
import (
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
"github.com/iwind/TeaGo"
)
func init() {
TeaGo.BeforeStart(func(server *TeaGo.Server) {
server.
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeServer)).
Data("teaMenu", "servers").
Data("teaSubMenu", "group").
Prefix("/servers/groups/group/settings/charset").
GetPost("", new(IndexAction)).
EndAll()
})
}

View File

@@ -0,0 +1,78 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package compression
import (
"encoding/json"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/groups/group/servergrouputils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
"github.com/iwind/TeaGo/actions"
)
type IndexAction struct {
actionutils.ParentAction
}
func (this *IndexAction) Init() {
this.Nav("", "setting", "index")
this.SecondMenu("compression")
}
func (this *IndexAction) RunGet(params struct {
GroupId int64
}) {
_, err := servergrouputils.InitGroup(this.Parent(), params.GroupId, "compression")
if err != nil {
this.ErrorPage(err)
return
}
// WebId
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithServerGroupId(this.AdminContext(), params.GroupId)
if err != nil {
this.ErrorPage(err)
return
}
this.Data["webId"] = webConfig.Id
this.Data["compressionConfig"] = webConfig.Compression
this.Show()
}
func (this *IndexAction) RunPost(params struct {
WebId int64
CompressionJSON []byte
Must *actions.Must
CSRF *actionutils.CSRF
}) {
defer this.CreateLogInfo("修改Web %d 的压缩设置", params.WebId)
// 校验配置
var compressionConfig = &serverconfigs.HTTPCompressionConfig{}
err := json.Unmarshal(params.CompressionJSON, compressionConfig)
if err != nil {
this.Fail("配置校验失败:" + err.Error())
}
err = compressionConfig.Init()
if err != nil {
this.Fail("配置校验失败:" + err.Error())
}
_, err = this.RPC().HTTPWebRPC().UpdateHTTPWebCompression(this.AdminContext(), &pb.UpdateHTTPWebCompressionRequest{
WebId: params.WebId,
CompressionJSON: params.CompressionJSON,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -0,0 +1,19 @@
package compression
import (
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
"github.com/iwind/TeaGo"
)
func init() {
TeaGo.BeforeStart(func(server *TeaGo.Server) {
server.
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeServer)).
Data("teaMenu", "servers").
Data("teaSubMenu", "group").
Prefix("/servers/groups/group/settings/compression").
GetPost("", new(IndexAction)).
EndAll()
})
}

View File

@@ -0,0 +1,158 @@
package headers
import (
"encoding/json"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/groups/group/servergrouputils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
"github.com/iwind/TeaGo/actions"
)
type IndexAction struct {
actionutils.ParentAction
}
func (this *IndexAction) Init() {
this.Nav("", "setting", "index")
this.SecondMenu("header")
}
func (this *IndexAction) RunGet(params struct {
GroupId int64
}) {
_, err := servergrouputils.InitGroup(this.Parent(), params.GroupId, "headers")
if err != nil {
this.ErrorPage(err)
return
}
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithServerGroupId(this.AdminContext(), params.GroupId)
if err != nil {
this.ErrorPage(err)
return
}
webId := webConfig.Id
this.Data["webId"] = webId
isChanged := false
if webConfig.RequestHeaderPolicy == nil {
createHeaderPolicyResp, err := this.RPC().HTTPHeaderPolicyRPC().CreateHTTPHeaderPolicy(this.AdminContext(), &pb.CreateHTTPHeaderPolicyRequest{})
if err != nil {
this.ErrorPage(err)
return
}
headerPolicyId := createHeaderPolicyResp.HeaderPolicyId
ref := &shared.HTTPHeaderPolicyRef{
IsPrior: false,
IsOn: true,
HeaderPolicyId: headerPolicyId,
}
refJSON, err := json.Marshal(ref)
if err != nil {
this.ErrorPage(err)
return
}
_, err = this.RPC().HTTPWebRPC().UpdateHTTPWebRequestHeader(this.AdminContext(), &pb.UpdateHTTPWebRequestHeaderRequest{
WebId: webId,
HeaderJSON: refJSON,
})
if err != nil {
this.ErrorPage(err)
return
}
isChanged = true
}
if webConfig.ResponseHeaderPolicy == nil {
createHeaderPolicyResp, err := this.RPC().HTTPHeaderPolicyRPC().CreateHTTPHeaderPolicy(this.AdminContext(), &pb.CreateHTTPHeaderPolicyRequest{})
if err != nil {
this.ErrorPage(err)
return
}
headerPolicyId := createHeaderPolicyResp.HeaderPolicyId
ref := &shared.HTTPHeaderPolicyRef{
IsPrior: false,
IsOn: true,
HeaderPolicyId: headerPolicyId,
}
refJSON, err := json.Marshal(ref)
if err != nil {
this.ErrorPage(err)
return
}
_, err = this.RPC().HTTPWebRPC().UpdateHTTPWebResponseHeader(this.AdminContext(), &pb.UpdateHTTPWebResponseHeaderRequest{
WebId: webId,
HeaderJSON: refJSON,
})
if err != nil {
this.ErrorPage(err)
return
}
isChanged = true
}
// 重新获取配置
if isChanged {
webConfig, err = dao.SharedHTTPWebDAO.FindWebConfigWithServerGroupId(this.AdminContext(), params.GroupId)
if err != nil {
this.ErrorPage(err)
return
}
}
this.Data["requestHeaderRef"] = webConfig.RequestHeaderPolicyRef
this.Data["requestHeaderPolicy"] = webConfig.RequestHeaderPolicy
this.Data["responseHeaderRef"] = webConfig.ResponseHeaderPolicyRef
this.Data["responseHeaderPolicy"] = webConfig.ResponseHeaderPolicy
this.Show()
}
func (this *IndexAction) RunPost(params struct {
WebId int64
Type string
RequestHeaderJSON []byte
ResponseHeaderJSON []byte
Must *actions.Must
}) {
defer this.CreateLogInfo("修改Web %d 的Header设置", params.WebId)
switch params.Type {
case "request":
// 检查配置
var requestHeaderRef = &shared.HTTPHeaderPolicyRef{}
err := json.Unmarshal(params.RequestHeaderJSON, requestHeaderRef)
if err != nil {
this.Fail("请求Header配置校验失败" + err.Error() + ", JSON: " + string(params.RequestHeaderJSON))
}
_, err = this.RPC().HTTPWebRPC().UpdateHTTPWebRequestHeader(this.AdminContext(), &pb.UpdateHTTPWebRequestHeaderRequest{
WebId: params.WebId,
HeaderJSON: params.RequestHeaderJSON,
})
if err != nil {
this.ErrorPage(err)
return
}
case "response":
// 校验配置
var responseHeaderRef = &shared.HTTPHeaderPolicyRef{}
err := json.Unmarshal(params.ResponseHeaderJSON, responseHeaderRef)
if err != nil {
this.Fail("响应Header配置校验失败" + err.Error() + ", JSON: " + string(params.ResponseHeaderJSON))
}
_, err = this.RPC().HTTPWebRPC().UpdateHTTPWebResponseHeader(this.AdminContext(), &pb.UpdateHTTPWebResponseHeaderRequest{
WebId: params.WebId,
HeaderJSON: params.ResponseHeaderJSON,
})
if err != nil {
this.ErrorPage(err)
return
}
}
this.Success()
}

View File

@@ -0,0 +1,19 @@
package headers
import (
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
"github.com/iwind/TeaGo"
)
func init() {
TeaGo.BeforeStart(func(server *TeaGo.Server) {
server.
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeServer)).
Data("teaMenu", "servers").
Data("teaSubMenu", "group").
Prefix("/servers/groups/group/settings/headers").
GetPost("", new(IndexAction)).
EndAll()
})
}

View File

@@ -3,6 +3,7 @@
package reverseProxy
import (
teaconst "github.com/TeaOSLab/EdgeAdmin/internal/const"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/iwind/TeaGo/types"
)
@@ -18,6 +19,10 @@ func (this *IndexAction) Init() {
func (this *IndexAction) RunGet(params struct {
GroupId int64
}) {
this.RedirectURL("/servers/groups/group/settings/httpReverseProxy?groupId=" + types.String(params.GroupId))
if teaconst.IsPlus {
this.RedirectURL("/servers/groups/group/settings/web?groupId=" + types.String(params.GroupId))
} else {
this.RedirectURL("/servers/groups/group/settings/httpReverseProxy?groupId=" + types.String(params.GroupId))
}
return
}

View File

@@ -0,0 +1,68 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package remoteAddr
import (
"encoding/json"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/groups/group/servergrouputils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
"github.com/iwind/TeaGo/actions"
)
type IndexAction struct {
actionutils.ParentAction
}
func (this *IndexAction) Init() {
this.Nav("", "setting", "index")
this.SecondMenu("remoteAddr")
}
func (this *IndexAction) RunGet(params struct {
GroupId int64
}) {
_, err := servergrouputils.InitGroup(this.Parent(), params.GroupId, "remoteAddr")
if err != nil {
this.ErrorPage(err)
return
}
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithServerGroupId(this.AdminContext(), params.GroupId)
if err != nil {
this.ErrorPage(err)
return
}
this.Data["webId"] = webConfig.Id
this.Data["remoteAddrConfig"] = webConfig.RemoteAddr
this.Show()
}
func (this *IndexAction) RunPost(params struct {
WebId int64
RemoteAddrJSON []byte
Must *actions.Must
CSRF *actionutils.CSRF
}) {
var remoteAddrConfig = &serverconfigs.HTTPRemoteAddrConfig{}
err := json.Unmarshal(params.RemoteAddrJSON, remoteAddrConfig)
if err != nil {
this.Fail("参数校验失败:" + err.Error())
}
_, err = this.RPC().HTTPWebRPC().UpdateHTTPWebRemoteAddr(this.AdminContext(), &pb.UpdateHTTPWebRemoteAddrRequest{
WebId: params.WebId,
RemoteAddrJSON: params.RemoteAddrJSON,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -0,0 +1,19 @@
package remoteAddr
import (
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
"github.com/iwind/TeaGo"
)
func init() {
TeaGo.BeforeStart(func(server *TeaGo.Server) {
server.
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeServer)).
Data("teaMenu", "servers").
Data("teaSubMenu", "group").
Prefix("/servers/groups/group/settings/remoteAddr").
GetPost("", new(IndexAction)).
EndAll()
})
}

View File

@@ -0,0 +1,60 @@
package stat
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/groups/group/servergrouputils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/actions"
)
type IndexAction struct {
actionutils.ParentAction
}
func (this *IndexAction) Init() {
this.Nav("", "setting", "index")
this.SecondMenu("stat")
}
func (this *IndexAction) RunGet(params struct {
GroupId int64
}) {
_, err := servergrouputils.InitGroup(this.Parent(), params.GroupId, "stat")
if err != nil {
this.ErrorPage(err)
return
}
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithServerGroupId(this.AdminContext(), params.GroupId)
if err != nil {
this.ErrorPage(err)
return
}
this.Data["webId"] = webConfig.Id
this.Data["statConfig"] = webConfig.StatRef
this.Show()
}
func (this *IndexAction) RunPost(params struct {
WebId int64
StatJSON []byte
Must *actions.Must
}) {
defer this.CreateLogInfo("修改Web %d 的统计设置", params.WebId)
// TODO 校验配置
_, err := this.RPC().HTTPWebRPC().UpdateHTTPWebStat(this.AdminContext(), &pb.UpdateHTTPWebStatRequest{
WebId: params.WebId,
StatJSON: params.StatJSON,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -0,0 +1,19 @@
package stat
import (
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
"github.com/iwind/TeaGo"
)
func init() {
TeaGo.BeforeStart(func(server *TeaGo.Server) {
server.
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeServer)).
Data("teaMenu", "servers").
Data("teaSubMenu", "group").
Prefix("/servers/groups/group/settings/stat").
GetPost("", new(IndexAction)).
EndAll()
})
}

View File

@@ -0,0 +1,100 @@
package waf
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
"github.com/iwind/TeaGo/lists"
"github.com/iwind/TeaGo/maps"
"strings"
)
type GroupAction struct {
actionutils.ParentAction
}
func (this *GroupAction) Init() {
this.Nav("", "setting", this.ParamString("type"))
this.SecondMenu("waf")
}
func (this *GroupAction) RunGet(params struct {
FirewallPolicyId int64
GroupId int64
Type string
}) {
this.Data["type"] = params.Type
this.Data["firewallPolicyId"] = params.FirewallPolicyId
// policy
firewallPolicy, err := dao.SharedHTTPFirewallPolicyDAO.FindEnabledHTTPFirewallPolicyConfig(this.AdminContext(), params.FirewallPolicyId)
if err != nil {
this.ErrorPage(err)
return
}
if firewallPolicy == nil {
this.NotFound("firewallPolicy", params.FirewallPolicyId)
return
}
// group config
groupConfig, err := dao.SharedHTTPFirewallRuleGroupDAO.FindRuleGroupConfig(this.AdminContext(), params.GroupId)
if err != nil {
this.ErrorPage(err)
return
}
if groupConfig == nil {
this.NotFound("firewallRuleGroup", params.GroupId)
return
}
this.Data["group"] = groupConfig
// rule sets
this.Data["sets"] = lists.Map(groupConfig.Sets, func(k int, v interface{}) interface{} {
set := v.(*firewallconfigs.HTTPFirewallRuleSet)
var actionMaps = []maps.Map{}
for _, action := range set.Actions {
def := firewallconfigs.FindActionDefinition(action.Code)
if def == nil {
continue
}
actionMaps = append(actionMaps, maps.Map{
"code": strings.ToUpper(action.Code),
"name": def.Name,
"category": def.Category,
"options": action.Options,
})
}
return maps.Map{
"id": set.Id,
"name": set.Name,
"rules": lists.Map(set.Rules, func(k int, v interface{}) interface{} {
rule := v.(*firewallconfigs.HTTPFirewallRule)
var errString = ""
var err = rule.Init()
if err != nil {
errString = err.Error()
}
return maps.Map{
"param": rule.Param,
"paramFilters": rule.ParamFilters,
"operator": rule.Operator,
"value": rule.Value,
"isCaseInsensitive": rule.IsCaseInsensitive,
"isComposed": firewallconfigs.CheckCheckpointIsComposed(rule.Prefix()),
"checkpointOptions": rule.CheckpointOptions,
"err": errString,
}
}),
"isOn": set.IsOn,
"actions": actionMaps,
"connector": strings.ToUpper(set.Connector),
}
})
this.Show()
}

View File

@@ -0,0 +1,83 @@
package waf
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
"github.com/iwind/TeaGo/maps"
)
type GroupsAction struct {
actionutils.ParentAction
}
func (this *GroupsAction) Init() {
this.Nav("", "setting", this.ParamString("type"))
this.SecondMenu("waf")
}
func (this *GroupsAction) RunGet(params struct {
ServerId int64
FirewallPolicyId int64
Type string
}) {
this.Data["firewallPolicyId"] = params.FirewallPolicyId
this.Data["type"] = params.Type
firewallPolicy, err := dao.SharedHTTPFirewallPolicyDAO.FindEnabledHTTPFirewallPolicyConfig(this.AdminContext(), params.FirewallPolicyId)
if err != nil {
this.ErrorPage(err)
return
}
if firewallPolicy == nil {
this.NotFound("firewallPolicy", params.FirewallPolicyId)
return
}
groupMaps := []maps.Map{}
// inbound
if params.Type == "inbound" {
if firewallPolicy.Inbound != nil {
for _, g := range firewallPolicy.Inbound.Groups {
groupMaps = append(groupMaps, maps.Map{
"id": g.Id,
"name": g.Name,
"code": g.Code,
"isOn": g.IsOn,
"description": g.Description,
"countSets": len(g.Sets),
"canDelete": len(g.Code) == 0,
})
}
}
}
// outbound
if params.Type == "outbound" {
if firewallPolicy.Outbound != nil {
for _, g := range firewallPolicy.Outbound.Groups {
groupMaps = append(groupMaps, maps.Map{
"id": g.Id,
"name": g.Name,
"code": g.Code,
"isOn": g.IsOn,
"description": g.Description,
"countSets": len(g.Sets),
"canDelete": len(g.Code) == 0,
})
}
}
}
this.Data["groups"] = groupMaps
// WAF是否启用
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithServerId(this.AdminContext(), params.ServerId)
if err != nil {
this.ErrorPage(err)
return
}
this.Data["wafIsOn"] = webConfig.FirewallRef != nil && webConfig.FirewallRef.IsOn
this.Show()
}

View File

@@ -0,0 +1,76 @@
package waf
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/groups/group/servergrouputils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/actions"
)
type IndexAction struct {
actionutils.ParentAction
}
func (this *IndexAction) Init() {
this.Nav("", "setting", "index")
this.SecondMenu("waf")
}
func (this *IndexAction) RunGet(params struct {
GroupId int64
}) {
_, err := servergrouputils.InitGroup(this.Parent(), params.GroupId, "waf")
if err != nil {
this.ErrorPage(err)
return
}
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithServerGroupId(this.AdminContext(), params.GroupId)
if err != nil {
this.ErrorPage(err)
return
}
this.Data["webId"] = webConfig.Id
this.Data["firewallConfig"] = webConfig.FirewallRef
// 获取当前服务所在集群的WAF设置
this.Data["firewallPolicy"] = nil
// 当前的Server独立设置
if webConfig.FirewallRef == nil || webConfig.FirewallRef.FirewallPolicyId == 0 {
firewallPolicyId, err := dao.SharedHTTPWebDAO.InitEmptyHTTPFirewallPolicy(this.AdminContext(), params.GroupId, 0, webConfig.Id, webConfig.FirewallRef != nil && webConfig.FirewallRef.IsOn)
if err != nil {
this.ErrorPage(err)
return
}
this.Data["firewallPolicyId"] = firewallPolicyId
} else {
this.Data["firewallPolicyId"] = webConfig.FirewallRef.FirewallPolicyId
}
this.Show()
}
func (this *IndexAction) RunPost(params struct {
WebId int64
FirewallJSON []byte
Must *actions.Must
}) {
defer this.CreateLogInfo("修改Web %d 的WAF设置", params.WebId)
// TODO 检查配置
_, err := this.RPC().HTTPWebRPC().UpdateHTTPWebFirewall(this.AdminContext(), &pb.UpdateHTTPWebFirewallRequest{
WebId: params.WebId,
FirewallJSON: params.FirewallJSON,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -0,0 +1,33 @@
package waf
import (
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/server/settings/waf/ipadmin"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/serverutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
"github.com/iwind/TeaGo"
)
func init() {
TeaGo.BeforeStart(func(server *TeaGo.Server) {
server.
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeServer)).
Helper(serverutils.NewServerHelper()).
Data("teaMenu", "servers").
Data("teaSubMenu", "group").
Prefix("/servers/groups/group/settings/waf").
GetPost("", new(IndexAction)).
Get("/ipadmin/allowList", new(ipadmin.AllowListAction)).
Get("/ipadmin/denyList", new(ipadmin.DenyListAction)).
GetPost("/ipadmin/countries", new(ipadmin.CountriesAction)).
GetPost("/ipadmin/provinces", new(ipadmin.ProvincesAction)).
GetPost("/ipadmin/updateIPPopup", new(ipadmin.UpdateIPPopupAction)).
Post("/ipadmin/deleteIP", new(ipadmin.DeleteIPAction)).
GetPost("/ipadmin/test", new(ipadmin.TestAction)).
// 规则相关
Get("/groups", new(GroupsAction)).
Get("/group", new(GroupAction)).
EndAll()
})
}

View File

@@ -0,0 +1,95 @@
package ipadmin
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
"github.com/iwind/TeaGo/maps"
timeutil "github.com/iwind/TeaGo/utils/time"
"time"
)
type AllowListAction struct {
actionutils.ParentAction
}
func (this *AllowListAction) Init() {
this.Nav("", "setting", "allowList")
this.SecondMenu("waf")
}
func (this *AllowListAction) RunGet(params struct {
ServerId int64
FirewallPolicyId int64
}) {
this.Data["featureIsOn"] = true
this.Data["firewallPolicyId"] = params.FirewallPolicyId
listId, err := dao.SharedIPListDAO.FindAllowIPListIdWithServerId(this.AdminContext(), params.ServerId)
if err != nil {
this.ErrorPage(err)
return
}
// 创建
if listId == 0 {
listId, err = dao.SharedIPListDAO.CreateIPListForServerId(this.AdminContext(), params.ServerId, "white")
if err != nil {
this.ErrorPage(err)
return
}
}
this.Data["listId"] = listId
// 数量
countResp, err := this.RPC().IPItemRPC().CountIPItemsWithListId(this.AdminContext(), &pb.CountIPItemsWithListIdRequest{IpListId: listId})
if err != nil {
this.ErrorPage(err)
return
}
count := countResp.Count
page := this.NewPage(count)
this.Data["page"] = page.AsHTML()
// 列表
itemsResp, err := this.RPC().IPItemRPC().ListIPItemsWithListId(this.AdminContext(), &pb.ListIPItemsWithListIdRequest{
IpListId: listId,
Offset: page.Offset,
Size: page.Size,
})
if err != nil {
this.ErrorPage(err)
return
}
itemMaps := []maps.Map{}
for _, item := range itemsResp.IpItems {
expiredTime := ""
if item.ExpiredAt > 0 {
expiredTime = timeutil.FormatTime("Y-m-d H:i:s", item.ExpiredAt)
}
itemMaps = append(itemMaps, maps.Map{
"id": item.Id,
"ipFrom": item.IpFrom,
"ipTo": item.IpTo,
"expiredTime": expiredTime,
"reason": item.Reason,
"type": item.Type,
"isExpired": item.ExpiredAt > 0 && item.ExpiredAt < time.Now().Unix(),
"eventLevelName": firewallconfigs.FindFirewallEventLevelName(item.EventLevel),
})
}
this.Data["items"] = itemMaps
// WAF是否启用
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithServerId(this.AdminContext(), params.ServerId)
if err != nil {
this.ErrorPage(err)
return
}
this.Data["wafIsOn"] = webConfig.FirewallRef != nil && webConfig.FirewallRef.IsOn
this.Show()
}

View File

@@ -0,0 +1,121 @@
package ipadmin
import (
"encoding/json"
"github.com/TeaOSLab/EdgeAdmin/internal/oplogs"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
"github.com/iwind/TeaGo/actions"
"github.com/iwind/TeaGo/lists"
"github.com/iwind/TeaGo/maps"
"strings"
)
type CountriesAction struct {
actionutils.ParentAction
}
func (this *CountriesAction) Init() {
this.Nav("", "setting", "country")
this.SecondMenu("waf")
}
func (this *CountriesAction) RunGet(params struct {
FirewallPolicyId int64
ServerId int64
}) {
this.Data["featureIsOn"] = true
this.Data["firewallPolicyId"] = params.FirewallPolicyId
this.Data["subMenuItem"] = "region"
// 当前选中的地区
policyConfig, err := dao.SharedHTTPFirewallPolicyDAO.FindEnabledHTTPFirewallPolicyConfig(this.AdminContext(), params.FirewallPolicyId)
if err != nil {
this.ErrorPage(err)
return
}
if policyConfig == nil {
this.NotFound("firewallPolicy", params.FirewallPolicyId)
return
}
selectedCountryIds := []int64{}
if policyConfig.Inbound != nil && policyConfig.Inbound.Region != nil {
selectedCountryIds = policyConfig.Inbound.Region.DenyCountryIds
}
countriesResp, err := this.RPC().RegionCountryRPC().FindAllEnabledRegionCountries(this.AdminContext(), &pb.FindAllEnabledRegionCountriesRequest{})
if err != nil {
this.ErrorPage(err)
return
}
countryMaps := []maps.Map{}
for _, country := range countriesResp.Countries {
countryMaps = append(countryMaps, maps.Map{
"id": country.Id,
"name": country.Name,
"letter": strings.ToUpper(string(country.Pinyin[0][0])),
"isChecked": lists.ContainsInt64(selectedCountryIds, country.Id),
})
}
this.Data["countries"] = countryMaps
// WAF是否启用
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithServerId(this.AdminContext(), params.ServerId)
if err != nil {
this.ErrorPage(err)
return
}
this.Data["wafIsOn"] = webConfig.FirewallRef != nil && webConfig.FirewallRef.IsOn
this.Show()
}
func (this *CountriesAction) RunPost(params struct {
FirewallPolicyId int64
CountryIds []int64
Must *actions.Must
}) {
// 日志
defer this.CreateLog(oplogs.LevelInfo, "WAF策略 %d 设置禁止访问的国家和地区", params.FirewallPolicyId)
policyConfig, err := dao.SharedHTTPFirewallPolicyDAO.FindEnabledHTTPFirewallPolicyConfig(this.AdminContext(), params.FirewallPolicyId)
if err != nil {
this.ErrorPage(err)
return
}
if policyConfig == nil {
this.NotFound("firewallPolicy", params.FirewallPolicyId)
return
}
if policyConfig.Inbound == nil {
policyConfig.Inbound = &firewallconfigs.HTTPFirewallInboundConfig{IsOn: true}
}
if policyConfig.Inbound.Region == nil {
policyConfig.Inbound.Region = &firewallconfigs.HTTPFirewallRegionConfig{
IsOn: true,
}
}
policyConfig.Inbound.Region.DenyCountryIds = params.CountryIds
inboundJSON, err := json.Marshal(policyConfig.Inbound)
if err != nil {
this.ErrorPage(err)
return
}
_, err = this.RPC().HTTPFirewallPolicyRPC().UpdateHTTPFirewallInboundConfig(this.AdminContext(), &pb.UpdateHTTPFirewallInboundConfigRequest{
HttpFirewallPolicyId: params.FirewallPolicyId,
InboundJSON: inboundJSON,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -0,0 +1,29 @@
package ipadmin
import (
"github.com/TeaOSLab/EdgeAdmin/internal/oplogs"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
)
type DeleteIPAction struct {
actionutils.ParentAction
}
func (this *DeleteIPAction) RunPost(params struct {
FirewallPolicyId int64
ItemId int64
}) {
// 日志
defer this.CreateLog(oplogs.LevelInfo, "从WAF策略 %d 名单中删除IP %d", params.FirewallPolicyId, params.ItemId)
// TODO 判断权限
_, err := this.RPC().IPItemRPC().DeleteIPItem(this.AdminContext(), &pb.DeleteIPItemRequest{IpItemId: params.ItemId})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -0,0 +1,95 @@
package ipadmin
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
"github.com/iwind/TeaGo/maps"
timeutil "github.com/iwind/TeaGo/utils/time"
"time"
)
type DenyListAction struct {
actionutils.ParentAction
}
func (this *DenyListAction) Init() {
this.Nav("", "setting", "denyList")
this.SecondMenu("waf")
}
func (this *DenyListAction) RunGet(params struct {
FirewallPolicyId int64
ServerId int64
}) {
this.Data["featureIsOn"] = true
this.Data["firewallPolicyId"] = params.FirewallPolicyId
listId, err := dao.SharedIPListDAO.FindDenyIPListIdWithServerId(this.AdminContext(), params.ServerId)
if err != nil {
this.ErrorPage(err)
return
}
// 创建
if listId == 0 {
listId, err = dao.SharedIPListDAO.CreateIPListForServerId(this.AdminContext(), params.ServerId, "black")
if err != nil {
this.ErrorPage(err)
return
}
}
this.Data["listId"] = listId
// 数量
countResp, err := this.RPC().IPItemRPC().CountIPItemsWithListId(this.AdminContext(), &pb.CountIPItemsWithListIdRequest{IpListId: listId})
if err != nil {
this.ErrorPage(err)
return
}
count := countResp.Count
page := this.NewPage(count)
this.Data["page"] = page.AsHTML()
// 列表
itemsResp, err := this.RPC().IPItemRPC().ListIPItemsWithListId(this.AdminContext(), &pb.ListIPItemsWithListIdRequest{
IpListId: listId,
Offset: page.Offset,
Size: page.Size,
})
if err != nil {
this.ErrorPage(err)
return
}
itemMaps := []maps.Map{}
for _, item := range itemsResp.IpItems {
expiredTime := ""
if item.ExpiredAt > 0 {
expiredTime = timeutil.FormatTime("Y-m-d H:i:s", item.ExpiredAt)
}
itemMaps = append(itemMaps, maps.Map{
"id": item.Id,
"ipFrom": item.IpFrom,
"ipTo": item.IpTo,
"expiredTime": expiredTime,
"reason": item.Reason,
"type": item.Type,
"isExpired": item.ExpiredAt > 0 && item.ExpiredAt < time.Now().Unix(),
"eventLevelName": firewallconfigs.FindFirewallEventLevelName(item.EventLevel),
})
}
this.Data["items"] = itemMaps
// WAF是否启用
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithServerId(this.AdminContext(), params.ServerId)
if err != nil {
this.ErrorPage(err)
return
}
this.Data["wafIsOn"] = webConfig.FirewallRef != nil && webConfig.FirewallRef.IsOn
this.Show()
}

View File

@@ -0,0 +1,122 @@
package ipadmin
import (
"encoding/json"
"github.com/TeaOSLab/EdgeAdmin/internal/oplogs"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
"github.com/iwind/TeaGo/actions"
"github.com/iwind/TeaGo/lists"
"github.com/iwind/TeaGo/maps"
)
const ChinaCountryId = 1
type ProvincesAction struct {
actionutils.ParentAction
}
func (this *ProvincesAction) Init() {
this.Nav("", "setting", "province")
this.SecondMenu("waf")
}
func (this *ProvincesAction) RunGet(params struct {
FirewallPolicyId int64
ServerId int64
}) {
this.Data["featureIsOn"] = true
this.Data["firewallPolicyId"] = params.FirewallPolicyId
this.Data["subMenuItem"] = "province"
// 当前选中的省份
policyConfig, err := dao.SharedHTTPFirewallPolicyDAO.FindEnabledHTTPFirewallPolicyConfig(this.AdminContext(), params.FirewallPolicyId)
if err != nil {
this.ErrorPage(err)
return
}
if policyConfig == nil {
this.NotFound("firewallPolicy", params.FirewallPolicyId)
return
}
selectedProvinceIds := []int64{}
if policyConfig.Inbound != nil && policyConfig.Inbound.Region != nil {
selectedProvinceIds = policyConfig.Inbound.Region.DenyProvinceIds
}
provincesResp, err := this.RPC().RegionProvinceRPC().FindAllEnabledRegionProvincesWithCountryId(this.AdminContext(), &pb.FindAllEnabledRegionProvincesWithCountryIdRequest{
CountryId: int64(ChinaCountryId),
})
if err != nil {
this.ErrorPage(err)
return
}
provinceMaps := []maps.Map{}
for _, province := range provincesResp.Provinces {
provinceMaps = append(provinceMaps, maps.Map{
"id": province.Id,
"name": province.Name,
"isChecked": lists.ContainsInt64(selectedProvinceIds, province.Id),
})
}
this.Data["provinces"] = provinceMaps
// WAF是否启用
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithServerId(this.AdminContext(), params.ServerId)
if err != nil {
this.ErrorPage(err)
return
}
this.Data["wafIsOn"] = webConfig.FirewallRef != nil && webConfig.FirewallRef.IsOn
this.Show()
}
func (this *ProvincesAction) RunPost(params struct {
FirewallPolicyId int64
ProvinceIds []int64
Must *actions.Must
}) {
// 日志
defer this.CreateLog(oplogs.LevelInfo, "WAF策略 %d 设置禁止访问的省份", params.FirewallPolicyId)
policyConfig, err := dao.SharedHTTPFirewallPolicyDAO.FindEnabledHTTPFirewallPolicyConfig(this.AdminContext(), params.FirewallPolicyId)
if err != nil {
this.ErrorPage(err)
return
}
if policyConfig == nil {
this.NotFound("firewallPolicy", params.FirewallPolicyId)
return
}
if policyConfig.Inbound == nil {
policyConfig.Inbound = &firewallconfigs.HTTPFirewallInboundConfig{IsOn: true}
}
if policyConfig.Inbound.Region == nil {
policyConfig.Inbound.Region = &firewallconfigs.HTTPFirewallRegionConfig{
IsOn: true,
}
}
policyConfig.Inbound.Region.DenyProvinceIds = params.ProvinceIds
inboundJSON, err := json.Marshal(policyConfig.Inbound)
if err != nil {
this.ErrorPage(err)
return
}
_, err = this.RPC().HTTPFirewallPolicyRPC().UpdateHTTPFirewallInboundConfig(this.AdminContext(), &pb.UpdateHTTPFirewallInboundConfigRequest{
HttpFirewallPolicyId: params.FirewallPolicyId,
InboundJSON: inboundJSON,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -0,0 +1,100 @@
package ipadmin
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
"github.com/iwind/TeaGo/actions"
"github.com/iwind/TeaGo/maps"
timeutil "github.com/iwind/TeaGo/utils/time"
)
type TestAction struct {
actionutils.ParentAction
}
func (this *TestAction) Init() {
this.Nav("", "setting", "test")
this.SecondMenu("waf")
}
func (this *TestAction) RunGet(params struct {
ServerId int64
FirewallPolicyId int64
}) {
this.Data["featureIsOn"] = true
this.Data["firewallPolicyId"] = params.FirewallPolicyId
this.Data["subMenuItem"] = "province"
// WAF是否启用
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithServerId(this.AdminContext(), params.ServerId)
if err != nil {
this.ErrorPage(err)
return
}
this.Data["wafIsOn"] = webConfig.FirewallRef != nil && webConfig.FirewallRef.IsOn
this.Show()
}
func (this *TestAction) RunPost(params struct {
FirewallPolicyId int64
Ip string
Must *actions.Must
}) {
resp, err := this.RPC().HTTPFirewallPolicyRPC().CheckHTTPFirewallPolicyIPStatus(this.AdminContext(), &pb.CheckHTTPFirewallPolicyIPStatusRequest{
HttpFirewallPolicyId: params.FirewallPolicyId,
Ip: params.Ip,
})
if err != nil {
this.ErrorPage(err)
return
}
resultMap := maps.Map{
"isDone": true,
"isFound": resp.IsFound,
"isOk": resp.IsOk,
"error": resp.Error,
"isAllowed": resp.IsAllowed,
}
if resp.IpList != nil {
resultMap["list"] = maps.Map{
"id": resp.IpList.Id,
"name": resp.IpList.Name,
}
}
if resp.IpItem != nil {
resultMap["item"] = maps.Map{
"id": resp.IpItem.Id,
"ipFrom": resp.IpItem.IpFrom,
"ipTo": resp.IpItem.IpTo,
"reason": resp.IpItem.Reason,
"expiredAt": resp.IpItem.ExpiredAt,
"expiredTime": timeutil.FormatTime("Y-m-d H:i:s", resp.IpItem.ExpiredAt),
"type": resp.IpItem.Type,
"eventLevelName": firewallconfigs.FindFirewallEventLevelName(resp.IpItem.EventLevel),
}
}
if resp.RegionCountry != nil {
resultMap["country"] = maps.Map{
"id": resp.RegionCountry.Id,
"name": resp.RegionCountry.Name,
}
}
if resp.RegionProvince != nil {
resultMap["province"] = maps.Map{
"id": resp.RegionProvince.Id,
"name": resp.RegionProvince.Name,
}
}
this.Data["result"] = resultMap
this.Success()
}

View File

@@ -0,0 +1,117 @@
package ipadmin
import (
"github.com/TeaOSLab/EdgeAdmin/internal/oplogs"
"github.com/TeaOSLab/EdgeAdmin/internal/utils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/actions"
"github.com/iwind/TeaGo/maps"
)
type UpdateIPPopupAction struct {
actionutils.ParentAction
}
func (this *UpdateIPPopupAction) Init() {
this.Nav("", "", "")
}
func (this *UpdateIPPopupAction) RunGet(params struct {
ItemId int64
}) {
itemResp, err := this.RPC().IPItemRPC().FindEnabledIPItem(this.AdminContext(), &pb.FindEnabledIPItemRequest{IpItemId: params.ItemId})
if err != nil {
this.ErrorPage(err)
return
}
item := itemResp.IpItem
if item == nil {
this.NotFound("ipItem", params.ItemId)
return
}
this.Data["item"] = maps.Map{
"id": item.Id,
"ipFrom": item.IpFrom,
"ipTo": item.IpTo,
"expiredAt": item.ExpiredAt,
"reason": item.Reason,
"type": item.Type,
"eventLevel": item.EventLevel,
}
this.Data["type"] = item.Type
this.Show()
}
func (this *UpdateIPPopupAction) RunPost(params struct {
ItemId int64
IpFrom string
IpTo string
ExpiredAt int64
Reason string
Type string
EventLevel string
Must *actions.Must
CSRF *actionutils.CSRF
}) {
// 日志
defer this.CreateLog(oplogs.LevelInfo, "修改WAF策略名单中的IP %d", params.ItemId)
// TODO 校验ItemId所属用户
switch params.Type {
case "ipv4":
params.Must.
Field("ipFrom", params.IpFrom).
Require("请输入开始IP")
// 校验IP格式ipFrom/ipTo
var ipFromLong uint64
if !utils.IsIPv4(params.IpFrom) {
this.Fail("请输入正确的开始IP")
}
ipFromLong = utils.IP2Long(params.IpFrom)
var ipToLong uint64
if len(params.IpTo) > 0 && !utils.IsIPv4(params.IpTo) {
ipToLong = utils.IP2Long(params.IpTo)
this.Fail("请输入正确的结束IP")
}
if ipFromLong > 0 && ipToLong > 0 && ipFromLong > ipToLong {
params.IpTo, params.IpFrom = params.IpFrom, params.IpTo
}
case "ipv6":
params.Must.
Field("ipFrom", params.IpFrom).
Require("请输入IP")
// 校验IP格式ipFrom
if !utils.IsIPv6(params.IpFrom) {
this.Fail("请输入正确的IPv6地址")
}
case "all":
params.IpFrom = "0.0.0.0"
}
_, err := this.RPC().IPItemRPC().UpdateIPItem(this.AdminContext(), &pb.UpdateIPItemRequest{
IpItemId: params.ItemId,
IpFrom: params.IpFrom,
IpTo: params.IpTo,
ExpiredAt: params.ExpiredAt,
Reason: params.Reason,
Type: params.Type,
EventLevel: params.EventLevel,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -0,0 +1,59 @@
package web
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/groups/group/servergrouputils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/actions"
)
type IndexAction struct {
actionutils.ParentAction
}
func (this *IndexAction) Init() {
this.Nav("", "setting", "index")
this.SecondMenu("web")
}
func (this *IndexAction) RunGet(params struct {
GroupId int64
}) {
_, err := servergrouputils.InitGroup(this.Parent(), params.GroupId, "web")
if err != nil {
this.ErrorPage(err)
return
}
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithServerGroupId(this.AdminContext(), params.GroupId)
if err != nil {
this.ErrorPage(err)
return
}
this.Data["webId"] = webConfig.Id
this.Data["rootConfig"] = webConfig.Root
this.Show()
}
func (this *IndexAction) RunPost(params struct {
WebId int64
RootJSON []byte
Must *actions.Must
}) {
defer this.CreateLogInfo("修改Web %d 的首页文件名", params.WebId)
_, err := this.RPC().HTTPWebRPC().UpdateHTTPWeb(this.AdminContext(), &pb.UpdateHTTPWebRequest{
WebId: params.WebId,
RootJSON: params.RootJSON,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -0,0 +1,19 @@
package web
import (
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
"github.com/iwind/TeaGo"
)
func init() {
TeaGo.BeforeStart(func(server *TeaGo.Server) {
server.
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeServer)).
Data("teaMenu", "servers").
Data("teaSubMenu", "group").
Prefix("/servers/groups/group/settings/web").
GetPost("", new(IndexAction)).
EndAll()
})
}

View File

@@ -0,0 +1,68 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package webp
import (
"encoding/json"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/groups/group/servergrouputils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
"github.com/iwind/TeaGo/actions"
)
type IndexAction struct {
actionutils.ParentAction
}
func (this *IndexAction) Init() {
this.Nav("", "setting", "index")
this.SecondMenu("webp")
}
func (this *IndexAction) RunGet(params struct {
GroupId int64
}) {
_, err := servergrouputils.InitGroup(this.Parent(), params.GroupId, "webp")
if err != nil {
this.ErrorPage(err)
return
}
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithServerGroupId(this.AdminContext(), params.GroupId)
if err != nil {
this.ErrorPage(err)
return
}
this.Data["webId"] = webConfig.Id
this.Data["webpConfig"] = webConfig.WebP
this.Show()
}
func (this *IndexAction) RunPost(params struct {
WebId int64
WebpJSON []byte
Must *actions.Must
CSRF *actionutils.CSRF
}) {
var webpConfig = &serverconfigs.WebPImageConfig{}
err := json.Unmarshal(params.WebpJSON, webpConfig)
if err != nil {
this.Fail("参数校验失败:" + err.Error())
}
_, err = this.RPC().HTTPWebRPC().UpdateHTTPWebWebP(this.AdminContext(), &pb.UpdateHTTPWebWebPRequest{
WebId: params.WebId,
WebpJSON: params.WebpJSON,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -0,0 +1,19 @@
package webp
import (
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
"github.com/iwind/TeaGo"
)
func init() {
TeaGo.BeforeStart(func(server *TeaGo.Server) {
server.
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeServer)).
Data("teaMenu", "servers").
Data("teaSubMenu", "group").
Prefix("/servers/groups/group/settings/webp").
GetPost("", new(IndexAction)).
EndAll()
})
}

View File

@@ -0,0 +1,122 @@
package websocket
import (
"encoding/json"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/groups/group/servergrouputils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
"github.com/iwind/TeaGo/actions"
)
type IndexAction struct {
actionutils.ParentAction
}
func (this *IndexAction) Init() {
this.Nav("", "setting", "index")
this.SecondMenu("websocket")
}
func (this *IndexAction) RunGet(params struct {
GroupId int64
}) {
_, err := servergrouputils.InitGroup(this.Parent(), params.GroupId, "websocket")
if err != nil {
this.ErrorPage(err)
return
}
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithServerGroupId(this.AdminContext(), params.GroupId)
if err != nil {
this.ErrorPage(err)
return
}
this.Data["webId"] = webConfig.Id
this.Data["websocketRef"] = webConfig.WebsocketRef
this.Data["websocketConfig"] = webConfig.Websocket
this.Show()
}
func (this *IndexAction) RunPost(params struct {
WebId int64
WebsocketRefJSON []byte
WebsocketJSON []byte
Must *actions.Must
}) {
defer this.CreateLogInfo("修改Web %d 的Websocket设置", params.WebId)
// TODO 检查配置
websocketRef := &serverconfigs.HTTPWebsocketRef{}
err := json.Unmarshal(params.WebsocketRefJSON, websocketRef)
if err != nil {
this.ErrorPage(err)
return
}
websocketConfig := &serverconfigs.HTTPWebsocketConfig{}
err = json.Unmarshal(params.WebsocketJSON, websocketConfig)
if err != nil {
this.ErrorPage(err)
return
}
err = websocketConfig.Init()
if err != nil {
this.ErrorPage(err)
return
}
// 创建
handshakeTimeoutJSON, err := json.Marshal(websocketConfig.HandshakeTimeout)
if err != nil {
this.ErrorPage(err)
return
}
// 创建或修改
if websocketConfig.Id <= 0 {
createResp, err := this.RPC().HTTPWebsocketRPC().CreateHTTPWebsocket(this.AdminContext(), &pb.CreateHTTPWebsocketRequest{
HandshakeTimeoutJSON: handshakeTimeoutJSON,
AllowAllOrigins: websocketConfig.AllowAllOrigins,
AllowedOrigins: websocketConfig.AllowedOrigins,
RequestSameOrigin: websocketConfig.RequestSameOrigin,
RequestOrigin: websocketConfig.RequestOrigin,
})
if err != nil {
this.ErrorPage(err)
return
}
websocketConfig.Id = createResp.WebsocketId
} else {
_, err = this.RPC().HTTPWebsocketRPC().UpdateHTTPWebsocket(this.AdminContext(), &pb.UpdateHTTPWebsocketRequest{
WebsocketId: websocketConfig.Id,
HandshakeTimeoutJSON: handshakeTimeoutJSON,
AllowAllOrigins: websocketConfig.AllowAllOrigins,
AllowedOrigins: websocketConfig.AllowedOrigins,
RequestSameOrigin: websocketConfig.RequestSameOrigin,
RequestOrigin: websocketConfig.RequestOrigin,
})
}
websocketRef.WebsocketId = websocketConfig.Id
websocketRefJSON, err := json.Marshal(websocketRef)
if err != nil {
this.ErrorPage(err)
return
}
_, err = this.RPC().HTTPWebRPC().UpdateHTTPWebWebsocket(this.AdminContext(), &pb.UpdateHTTPWebWebsocketRequest{
WebId: params.WebId,
WebsocketJSON: websocketRefJSON,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -0,0 +1,19 @@
package websocket
import (
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
"github.com/iwind/TeaGo"
)
func init() {
TeaGo.BeforeStart(func(server *TeaGo.Server) {
server.
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeServer)).
Data("teaMenu", "servers").
Data("teaSubMenu", "group").
Prefix("/servers/groups/group/settings/websocket").
GetPost("", new(IndexAction)).
EndAll()
})
}

View File

@@ -7,6 +7,7 @@ import (
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
"github.com/iwind/TeaGo/actions"
"github.com/iwind/TeaGo/types"
)
type IndexAction struct {
@@ -21,6 +22,17 @@ func (this *IndexAction) Init() {
func (this *IndexAction) RunGet(params struct {
ServerId int64
}) {
// 服务分组设置
groupResp, err := this.RPC().ServerGroupRPC().FindEnabledServerGroupConfigInfo(this.AdminContext(), &pb.FindEnabledServerGroupConfigInfoRequest{
ServerId: params.ServerId,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Data["hasGroupConfig"] = groupResp.HasAccessLogConfig
this.Data["groupSettingURL"] = "/servers/groups/group/settings/accessLog?groupId=" + types.String(groupResp.ServerGroupId)
// 获取配置
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithServerId(this.AdminContext(), params.ServerId)
if err != nil {

View File

@@ -9,6 +9,7 @@ import (
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
"github.com/iwind/TeaGo/actions"
"github.com/iwind/TeaGo/maps"
"github.com/iwind/TeaGo/types"
)
type IndexAction struct {
@@ -23,6 +24,17 @@ func (this *IndexAction) Init() {
func (this *IndexAction) RunGet(params struct {
ServerId int64
}) {
// 服务分组设置
groupResp, err := this.RPC().ServerGroupRPC().FindEnabledServerGroupConfigInfo(this.AdminContext(), &pb.FindEnabledServerGroupConfigInfoRequest{
ServerId: params.ServerId,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Data["hasGroupConfig"] = groupResp.HasCacheConfig
this.Data["groupSettingURL"] = "/servers/groups/group/settings/cache?groupId=" + types.String(groupResp.ServerGroupId)
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithServerId(this.AdminContext(), params.ServerId)
if err != nil {
this.ErrorPage(err)

View File

@@ -7,6 +7,7 @@ import (
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/actions"
"github.com/iwind/TeaGo/types"
)
type IndexAction struct {
@@ -21,6 +22,17 @@ func (this *IndexAction) Init() {
func (this *IndexAction) RunGet(params struct {
ServerId int64
}) {
// 服务分组设置
groupResp, err := this.RPC().ServerGroupRPC().FindEnabledServerGroupConfigInfo(this.AdminContext(), &pb.FindEnabledServerGroupConfigInfoRequest{
ServerId: params.ServerId,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Data["hasGroupConfig"] = groupResp.HasCharsetConfig
this.Data["groupSettingURL"] = "/servers/groups/group/settings/charset?groupId=" + types.String(groupResp.ServerGroupId)
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithServerId(this.AdminContext(), params.ServerId)
if err != nil {
this.ErrorPage(err)

View File

@@ -9,6 +9,7 @@ import (
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
"github.com/iwind/TeaGo/actions"
"github.com/iwind/TeaGo/types"
)
type IndexAction struct {
@@ -23,6 +24,17 @@ func (this *IndexAction) Init() {
func (this *IndexAction) RunGet(params struct {
ServerId int64
}) {
// 服务分组设置
groupResp, err := this.RPC().ServerGroupRPC().FindEnabledServerGroupConfigInfo(this.AdminContext(), &pb.FindEnabledServerGroupConfigInfoRequest{
ServerId: params.ServerId,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Data["hasGroupConfig"] = groupResp.HasCompressionConfig
this.Data["groupSettingURL"] = "/servers/groups/group/settings/compression?groupId=" + types.String(groupResp.ServerGroupId)
// WebId
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithServerId(this.AdminContext(), params.ServerId)
if err != nil {

View File

@@ -18,7 +18,6 @@ func (this *CreateSetPopupAction) Init() {
}
func (this *CreateSetPopupAction) RunGet(params struct {
ServerId int64
HeaderPolicyId int64
}) {
this.Data["headerPolicyId"] = params.HeaderPolicyId

View File

@@ -6,6 +6,7 @@ import (
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
"github.com/iwind/TeaGo/types"
)
type IndexAction struct {
@@ -20,6 +21,18 @@ func (this *IndexAction) Init() {
func (this *IndexAction) RunGet(params struct {
ServerId int64
}) {
// 服务分组设置
groupResp, err := this.RPC().ServerGroupRPC().FindEnabledServerGroupConfigInfo(this.AdminContext(), &pb.FindEnabledServerGroupConfigInfoRequest{
ServerId: params.ServerId,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Data["hasGroupRequestConfig"] = groupResp.HasRequestHeadersConfig
this.Data["hasGroupResponseConfig"] = groupResp.HasResponseHeadersConfig
this.Data["groupSettingURL"] = "/servers/groups/group/settings/headers?groupId=" + types.String(groupResp.ServerGroupId)
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithServerId(this.AdminContext(), params.ServerId)
if err != nil {
this.ErrorPage(err)

View File

@@ -9,6 +9,7 @@ import (
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
"github.com/iwind/TeaGo/actions"
"github.com/iwind/TeaGo/types"
)
type IndexAction struct {
@@ -23,6 +24,17 @@ func (this *IndexAction) Init() {
func (this *IndexAction) RunGet(params struct {
ServerId int64
}) {
// 服务分组设置
groupResp, err := this.RPC().ServerGroupRPC().FindEnabledServerGroupConfigInfo(this.AdminContext(), &pb.FindEnabledServerGroupConfigInfoRequest{
ServerId: params.ServerId,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Data["hasGroupConfig"] = groupResp.HasRemoteAddrConfig
this.Data["groupSettingURL"] = "/servers/groups/group/settings/remoteAddr?groupId=" + types.String(groupResp.ServerGroupId)
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithServerId(this.AdminContext(), params.ServerId)
if err != nil {
this.ErrorPage(err)

View File

@@ -5,6 +5,7 @@ import (
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/actions"
"github.com/iwind/TeaGo/types"
)
type IndexAction struct {
@@ -19,6 +20,17 @@ func (this *IndexAction) Init() {
func (this *IndexAction) RunGet(params struct {
ServerId int64
}) {
// 服务分组设置
groupResp, err := this.RPC().ServerGroupRPC().FindEnabledServerGroupConfigInfo(this.AdminContext(), &pb.FindEnabledServerGroupConfigInfoRequest{
ServerId: params.ServerId,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Data["hasGroupConfig"] = groupResp.HasStatConfig
this.Data["groupSettingURL"] = "/servers/groups/group/settings/stat?groupId=" + types.String(groupResp.ServerGroupId)
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithServerId(this.AdminContext(), params.ServerId)
if err != nil {
this.ErrorPage(err)

View File

@@ -7,6 +7,7 @@ import (
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
"github.com/iwind/TeaGo/actions"
"github.com/iwind/TeaGo/maps"
"github.com/iwind/TeaGo/types"
)
type IndexAction struct {
@@ -21,6 +22,17 @@ func (this *IndexAction) Init() {
func (this *IndexAction) RunGet(params struct {
ServerId int64
}) {
// 服务分组设置
groupResp, err := this.RPC().ServerGroupRPC().FindEnabledServerGroupConfigInfo(this.AdminContext(), &pb.FindEnabledServerGroupConfigInfoRequest{
ServerId: params.ServerId,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Data["hasGroupConfig"] = groupResp.HasWAFConfig
this.Data["groupSettingURL"] = "/servers/groups/group/settings/waf?groupId=" + types.String(groupResp.ServerGroupId)
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithServerId(this.AdminContext(), params.ServerId)
if err != nil {
this.ErrorPage(err)
@@ -50,7 +62,7 @@ func (this *IndexAction) RunGet(params struct {
// 当前的Server独立设置
if webConfig.FirewallRef == nil || webConfig.FirewallRef.FirewallPolicyId == 0 {
firewallPolicyId, err := dao.SharedHTTPWebDAO.InitEmptyHTTPFirewallPolicy(this.AdminContext(), params.ServerId, webConfig.Id, webConfig.FirewallRef != nil && webConfig.FirewallRef.IsOn)
firewallPolicyId, err := dao.SharedHTTPWebDAO.InitEmptyHTTPFirewallPolicy(this.AdminContext(), 0, params.ServerId, webConfig.Id, webConfig.FirewallRef != nil && webConfig.FirewallRef.IsOn)
if err != nil {
this.ErrorPage(err)
return

View File

@@ -5,6 +5,7 @@ import (
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/actions"
"github.com/iwind/TeaGo/types"
)
type IndexAction struct {
@@ -19,6 +20,17 @@ func (this *IndexAction) Init() {
func (this *IndexAction) RunGet(params struct {
ServerId int64
}) {
// 分组设置
groupResp, err := this.RPC().ServerGroupRPC().FindEnabledServerGroupConfigInfo(this.AdminContext(), &pb.FindEnabledServerGroupConfigInfoRequest{
ServerId: params.ServerId,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Data["hasGroupConfig"] = groupResp.HasRootConfig
this.Data["groupSettingURL"] = "/servers/groups/group/settings/web?groupId=" + types.String(groupResp.ServerGroupId)
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithServerId(this.AdminContext(), params.ServerId)
if err != nil {
this.ErrorPage(err)

View File

@@ -9,6 +9,7 @@ import (
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
"github.com/iwind/TeaGo/actions"
"github.com/iwind/TeaGo/types"
)
type IndexAction struct {
@@ -23,6 +24,17 @@ func (this *IndexAction) Init() {
func (this *IndexAction) RunGet(params struct {
ServerId int64
}) {
// 服务分组设置
groupResp, err := this.RPC().ServerGroupRPC().FindEnabledServerGroupConfigInfo(this.AdminContext(), &pb.FindEnabledServerGroupConfigInfoRequest{
ServerId: params.ServerId,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Data["hasGroupConfig"] = groupResp.HasWebPConfig
this.Data["groupSettingURL"] = "/servers/groups/group/settings/webp?groupId=" + types.String(groupResp.ServerGroupId)
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithServerId(this.AdminContext(), params.ServerId)
if err != nil {
this.ErrorPage(err)

View File

@@ -7,6 +7,7 @@ import (
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
"github.com/iwind/TeaGo/actions"
"github.com/iwind/TeaGo/types"
)
type IndexAction struct {
@@ -21,6 +22,17 @@ func (this *IndexAction) Init() {
func (this *IndexAction) RunGet(params struct {
ServerId int64
}) {
// 服务分组设置
groupResp, err := this.RPC().ServerGroupRPC().FindEnabledServerGroupConfigInfo(this.AdminContext(), &pb.FindEnabledServerGroupConfigInfoRequest{
ServerId: params.ServerId,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Data["hasGroupConfig"] = groupResp.HasWebsocketConfig
this.Data["groupSettingURL"] = "/servers/groups/group/settings/websocket?groupId=" + types.String(groupResp.ServerGroupId)
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithServerId(this.AdminContext(), params.ServerId)
if err != nil {
this.ErrorPage(err)

View File

@@ -1,5 +1,5 @@
Vue.component("http-access-log-config-box", {
props: ["v-access-log-config", "v-fields", "v-default-field-codes", "v-is-location"],
props: ["v-access-log-config", "v-fields", "v-default-field-codes", "v-is-location", "v-is-group"],
data: function () {
let that = this
@@ -47,9 +47,9 @@ Vue.component("http-access-log-config-box", {
},
template: `<div>
<input type="hidden" name="accessLogJSON" :value="JSON.stringify(accessLog)"/>
<table class="ui table definition selectable">
<prior-checkbox :v-config="accessLog" v-if="vIsLocation"></prior-checkbox>
<tbody v-show="!vIsLocation || accessLog.isPrior">
<table class="ui table definition selectable" :class="{'opacity-mask': this.accessLog.firewallOnly}">
<prior-checkbox :v-config="accessLog" v-if="vIsLocation || vIsGroup"></prior-checkbox>
<tbody v-show="(!vIsLocation && !vIsGroup) || accessLog.isPrior">
<tr>
<td class="title">是否开启访问日志存储</td>
<td>
@@ -61,7 +61,7 @@ Vue.component("http-access-log-config-box", {
</td>
</tr>
</tbody>
<tbody v-show="(!vIsLocation || accessLog.isPrior) && accessLog.isOn">
<tbody v-show="((!vIsLocation && !vIsGroup) || accessLog.isPrior) && accessLog.isOn">
<tr>
<td>要存储的访问日志字段</td>
<td>
@@ -99,7 +99,7 @@ Vue.component("http-access-log-config-box", {
</tbody>
</table>
<div v-show="(!vIsLocation || accessLog.isPrior) && accessLog.isOn">
<div v-show="((!vIsLocation && !vIsGroup) || accessLog.isPrior) && accessLog.isOn">
<h4>WAF相关</h4>
<table class="ui table definition selectable">
<tr>

View File

@@ -1,5 +1,5 @@
Vue.component("http-cache-config-box", {
props: ["v-cache-config", "v-is-location", "v-cache-policy"],
props: ["v-cache-config", "v-is-location", "v-is-group", "v-cache-policy"],
data: function () {
let cacheConfig = this.vCacheConfig
if (cacheConfig == null) {
@@ -16,15 +16,15 @@ Vue.component("http-cache-config-box", {
},
methods: {
isOn: function () {
return (!this.vIsLocation || this.cacheConfig.isPrior) && this.cacheConfig.isOn
return ((!this.vIsLocation && !this.vIsGroup) || this.cacheConfig.isPrior) && this.cacheConfig.isOn
}
},
template: `<div>
<input type="hidden" name="cacheJSON" :value="JSON.stringify(cacheConfig)"/>
<table class="ui table definition selectable">
<prior-checkbox :v-config="cacheConfig" v-if="vIsLocation"></prior-checkbox>
<tbody v-show="!vIsLocation || cacheConfig.isPrior">
<tr>
<prior-checkbox :v-config="cacheConfig" v-if="vIsLocation || vIsGroup"></prior-checkbox>
<tbody v-show="(!vIsLocation && !vIsGroup) || cacheConfig.isPrior">
<tr v-show="!vIsGroup">
<td>缓存策略</td>
<td>
<div v-if="vCachePolicy != null">{{vCachePolicy.name}} <link-icon :href="'/servers/components/cache/policy?cachePolicyId=' + vCachePolicy.id"></link-icon>

View File

@@ -1,5 +1,5 @@
Vue.component("http-charsets-box", {
props: ["v-usual-charsets", "v-all-charsets", "v-charset-config", "v-is-location"],
props: ["v-usual-charsets", "v-all-charsets", "v-charset-config", "v-is-location", "v-is-group"],
data: function () {
let charsetConfig = this.vCharsetConfig
if (charsetConfig == null) {
@@ -23,8 +23,8 @@ Vue.component("http-charsets-box", {
template: `<div>
<input type="hidden" name="charsetJSON" :value="JSON.stringify(charsetConfig)"/>
<table class="ui table definition selectable">
<prior-checkbox :v-config="charsetConfig" v-if="vIsLocation"></prior-checkbox>
<tbody v-show="!vIsLocation || charsetConfig.isPrior">
<prior-checkbox :v-config="charsetConfig" v-if="vIsLocation || vIsGroup"></prior-checkbox>
<tbody v-show="(!vIsLocation && !vIsGroup) || charsetConfig.isPrior">
<tr>
<td class="title">是否启用</td>
<td>
@@ -35,7 +35,7 @@ Vue.component("http-charsets-box", {
</td>
</tr>
</tbody>
<tbody v-show="(!vIsLocation || charsetConfig.isPrior) && charsetConfig.isOn">
<tbody v-show="((!vIsLocation && !vIsGroup) || charsetConfig.isPrior) && charsetConfig.isOn">
<tr>
<td class="title">选择字符编码</td>
<td><select class="ui dropdown" style="width:20em" name="charset" v-model="charsetConfig.charset">
@@ -48,8 +48,8 @@ Vue.component("http-charsets-box", {
</td>
</tr>
</tbody>
<more-options-tbody @change="changeAdvancedVisible" v-if="(!vIsLocation || charsetConfig.isPrior) && charsetConfig.isOn"></more-options-tbody>
<tbody v-show="(!vIsLocation || charsetConfig.isPrior) && charsetConfig.isOn && advancedVisible">
<more-options-tbody @change="changeAdvancedVisible" v-if="((!vIsLocation && !vIsGroup) || charsetConfig.isPrior) && charsetConfig.isOn"></more-options-tbody>
<tbody v-show="((!vIsLocation && !vIsGroup) || charsetConfig.isPrior) && charsetConfig.isOn && advancedVisible">
<tr>
<td>字符编码是否大写</td>
<td>

View File

@@ -1,6 +1,6 @@
// 压缩配置
Vue.component("http-compression-config-box", {
props: ["v-compression-config", "v-is-location"],
props: ["v-compression-config", "v-is-location", "v-is-group"],
mounted: function () {
let that = this
sortLoad(function () {
@@ -92,7 +92,7 @@ Vue.component("http-compression-config-box", {
},
methods: {
isOn: function () {
return (!this.vIsLocation || this.config.isPrior) && this.config.isOn
return ((!this.vIsLocation && !this.vIsGroup) || this.config.isPrior) && this.config.isOn
},
changeExtensions: function (values) {
values.forEach(function (v, k) {
@@ -144,8 +144,8 @@ Vue.component("http-compression-config-box", {
template: `<div>
<input type="hidden" name="compressionJSON" :value="JSON.stringify(config)"/>
<table class="ui table definition selectable">
<prior-checkbox :v-config="config" v-if="vIsLocation"></prior-checkbox>
<tbody v-show="!vIsLocation || config.isPrior">
<prior-checkbox :v-config="config" v-if="vIsLocation || vIsGroup"></prior-checkbox>
<tbody v-show="(!vIsLocation && !vIsGroup) || config.isPrior">
<tr>
<td class="title">是否启用</td>
<td>

View File

@@ -1,5 +1,5 @@
Vue.component("http-firewall-config-box", {
props: ["v-firewall-config", "v-is-location", "v-firewall-policy"],
props: ["v-firewall-config", "v-is-location", "v-is-group", "v-firewall-policy"],
data: function () {
let firewall = this.vFirewallConfig
if (firewall == null) {
@@ -17,12 +17,12 @@ Vue.component("http-firewall-config-box", {
template: `<div>
<input type="hidden" name="firewallJSON" :value="JSON.stringify(firewall)"/>
<table class="ui table selectable definition">
<prior-checkbox :v-config="firewall" v-if="vIsLocation"></prior-checkbox>
<tbody v-show="!vIsLocation || firewall.isPrior">
<tr>
<prior-checkbox :v-config="firewall" v-if="vIsLocation || vIsGroup"></prior-checkbox>
<tbody v-show="(!vIsLocation && !vIsGroup) || firewall.isPrior">
<tr v-show="!vIsGroup">
<td>WAF策略</td>
<td>
<div v-if="vFirewallPolicy != null">{{vFirewallPolicy.name}} <span v-if="vFirewallPolicy.modeInfo != null">&nbsp; <span :class="{green: vFirewallPolicy.modeInfo.code == 'defend', blue: vFirewallPolicy.modeInfo.code == 'observe', grey: vFirewallPolicy.modeInfo.code == 'pass'}">[{{vFirewallPolicy.modeInfo.name}}]</span>&nbsp;</span> <link-icon :href="'/servers/components/waf/policy?firewallPolicyId=' + vFirewallPolicy.id"></link-icon>
<div v-if="vFirewallPolicy != null">{{vFirewallPolicy.name}} <span v-if="vFirewallPolicy.modeInfo != null">&nbsp; <span :class="{green: vFirewallPolicy.modeInfo.code == 'defend', blue: vFirewallPolicy.modeInfo.code == 'observe', grey: vFirewallPolicy.modeInfo.code == 'bypass'}">[{{vFirewallPolicy.modeInfo.name}}]</span>&nbsp;</span> <link-icon :href="'/servers/components/waf/policy?firewallPolicyId=' + vFirewallPolicy.id"></link-icon>
<p class="comment">使用当前服务所在集群的设置。</p>
</div>
<span v-else class="red">当前集群没有设置WAF策略当前配置无法生效。</span>

View File

@@ -1,5 +1,5 @@
Vue.component("http-header-policy-box", {
props: ["v-request-header-policy", "v-request-header-ref", "v-response-header-policy", "v-response-header-ref", "v-params", "v-is-location"],
props: ["v-request-header-policy", "v-request-header-ref", "v-response-header-policy", "v-response-header-ref", "v-params", "v-is-location", "v-is-group", "v-has-group-request-config", "v-has-group-response-config", "v-group-setting-url"],
data: function () {
let type = "request"
let hash = window.location.hash
@@ -127,7 +127,7 @@ Vue.component("http-header-policy-box", {
<input type="hidden" name="type" :value="type"/>
<!-- 请求 -->
<div v-if="vIsLocation && type == 'request'">
<div v-if="(vIsLocation || vIsGroup) && type == 'request'">
<input type="hidden" name="requestHeaderJSON" :value="JSON.stringify(requestHeaderRef)"/>
<table class="ui table definition selectable">
<prior-checkbox :v-config="requestHeaderRef"></prior-checkbox>
@@ -135,41 +135,47 @@ Vue.component("http-header-policy-box", {
<submit-btn></submit-btn>
</div>
<div v-if="(!vIsLocation || requestHeaderRef.isPrior) && type == 'request'">
<div v-if="((!vIsLocation && !vIsGroup) || requestHeaderRef.isPrior) && type == 'request'">
<div v-if="vHasGroupRequestConfig">
<div class="margin"></div>
<warning-message>由于已经在当前<a :href="vGroupSettingUrl + '#request'">服务分组</a>中进行了对应的配置,在这里的配置将不会生效。</warning-message>
</div>
<div :class="{'opacity-mask': vHasGroupRequestConfig}">
<h3>设置请求Header <a href="" @click.prevent="addSettingHeader(vRequestHeaderPolicy.id)">[添加新Header]</a></h3>
<p class="comment" v-if="requestSettingHeaders.length == 0">暂时还没有Header。</p>
<table class="ui table selectable celled" v-if="requestSettingHeaders.length > 0">
<thead>
<tr>
<th>名称</th>
<th>值</th>
<th class="two op">操作</th>
<p class="comment" v-if="requestSettingHeaders.length == 0">暂时还没有Header。</p>
<table class="ui table selectable celled" v-if="requestSettingHeaders.length > 0">
<thead>
<tr>
<th>名称</th>
<th>值</th>
<th class="two op">操作</th>
</tr>
</thead>
<tr v-for="header in requestSettingHeaders">
<td class="five wide">{{header.name}}</td>
<td>{{header.value}}</td>
<td><a href="" @click.prevent="updateSettingPopup(vRequestHeaderPolicy.id, header.id)">修改</a> &nbsp; <a href="" @click.prevent="deleteHeader(vRequestHeaderPolicy.id, 'setHeader', header.id)">删除</a> </td>
</tr>
</thead>
<tr v-for="header in requestSettingHeaders">
<td class="five wide">{{header.name}}</td>
<td>{{header.value}}</td>
<td><a href="" @click.prevent="updateSettingPopup(vRequestHeaderPolicy.id, header.id)">修改</a> &nbsp; <a href="" @click.prevent="deleteHeader(vRequestHeaderPolicy.id, 'setHeader', header.id)">删除</a> </td>
</tr>
</table>
<h3>删除请求Header</h3>
<p class="comment">这里可以设置需要从请求中删除的Header。</p>
<table class="ui table definition selectable">
<td class="title">需要删除的Header</td>
<td>
<div v-if="requestDeletingHeaders.length > 0">
<div class="ui label small basic" v-for="headerName in requestDeletingHeaders">{{headerName}} <a href=""><i class="icon remove" title="删除" @click.prevent="deleteDeletingHeader(vRequestHeaderPolicy.id, headerName)"></i></a> </div>
<div class="ui divider" ></div>
</div>
<button class="ui button small" type="button" @click.prevent="addDeletingHeader(vRequestHeaderPolicy.id, 'request')">+</button>
</td>
</table>
</table>
<h3>删除请求Header</h3>
<p class="comment">这里可以设置需要从请求中删除的Header。</p>
<table class="ui table definition selectable">
<td class="title">需要删除的Header</td>
<td>
<div v-if="requestDeletingHeaders.length > 0">
<div class="ui label small basic" v-for="headerName in requestDeletingHeaders">{{headerName}} <a href=""><i class="icon remove" title="删除" @click.prevent="deleteDeletingHeader(vRequestHeaderPolicy.id, headerName)"></i></a> </div>
<div class="ui divider" ></div>
</div>
<button class="ui button small" type="button" @click.prevent="addDeletingHeader(vRequestHeaderPolicy.id, 'request')">+</button>
</td>
</table>
</div>
</div>
<!-- 响应 -->
<div v-if="vIsLocation && type == 'response'">
<div v-if="(vIsLocation || vIsGroup) && type == 'response'">
<input type="hidden" name="responseHeaderJSON" :value="JSON.stringify(responseHeaderRef)"/>
<table class="ui table definition selectable">
<prior-checkbox :v-config="responseHeaderRef"></prior-checkbox>
@@ -177,38 +183,44 @@ Vue.component("http-header-policy-box", {
<submit-btn></submit-btn>
</div>
<div v-if="type == 'response'">
<h3>设置响应Header <a href="" @click.prevent="addSettingHeader(vResponseHeaderPolicy.id)">[添加新Header]</a></h3>
<p class="comment" style="margin-top: 0; padding-top: 0">将会覆盖已有的同名Header。</p>
<p class="comment" v-if="responseSettingHeaders.length == 0">暂时还没有Header。</p>
<table class="ui table selectable celled" v-if="responseSettingHeaders.length > 0">
<thead>
<tr>
<th>名称</th>
<th>值</th>
<th class="two op">操作</th>
<div v-if="((!vIsLocation && !vIsGroup) || requestHeaderRef.isPrior) && type == 'response'">
<div v-if="vHasGroupResponseConfig">
<div class="margin"></div>
<warning-message>由于已经在当前<a :href="vGroupSettingUrl + '#response'">服务分组</a>中进行了对应的配置,在这里的配置将不会生效。</warning-message>
</div>
<div :class="{'opacity-mask': vHasGroupResponseConfig}">
<h3>设置响应Header <a href="" @click.prevent="addSettingHeader(vResponseHeaderPolicy.id)">[添加新Header]</a></h3>
<p class="comment" style="margin-top: 0; padding-top: 0">将会覆盖已有的同名Header。</p>
<p class="comment" v-if="responseSettingHeaders.length == 0">暂时还没有Header。</p>
<table class="ui table selectable celled" v-if="responseSettingHeaders.length > 0">
<thead>
<tr>
<th>名称</th>
<th>值</th>
<th class="two op">操作</th>
</tr>
</thead>
<tr v-for="header in responseSettingHeaders">
<td class="five wide">{{header.name}}</td>
<td>{{header.value}}</td>
<td><a href="" @click.prevent="updateSettingPopup(vResponseHeaderPolicy.id, header.id)">修改</a> &nbsp; <a href="" @click.prevent="deleteHeader(vResponseHeaderPolicy.id, 'setHeader', header.id)">删除</a> </td>
</tr>
</thead>
<tr v-for="header in responseSettingHeaders">
<td class="five wide">{{header.name}}</td>
<td>{{header.value}}</td>
<td><a href="" @click.prevent="updateSettingPopup(vResponseHeaderPolicy.id, header.id)">修改</a> &nbsp; <a href="" @click.prevent="deleteHeader(vResponseHeaderPolicy.id, 'setHeader', header.id)">删除</a> </td>
</tr>
</table>
<h3>删除响应Header</h3>
<p class="comment">这里可以设置需要从响应中删除的Header。</p>
<table class="ui table definition selectable">
<td class="title">需要删除的Header</td>
<td>
<div v-if="responseDeletingHeaders.length > 0">
<div class="ui label small basic" v-for="headerName in responseDeletingHeaders">{{headerName}} <a href=""><i class="icon remove" title="删除" @click.prevent="deleteDeletingHeader(vResponseHeaderPolicy.id, headerName)"></i></a> </div>
<div class="ui divider" ></div>
</div>
<button class="ui button small" type="button" @click.prevent="addDeletingHeader(vResponseHeaderPolicy.id, 'response')">+</button>
</td>
</table>
</table>
<h3>删除响应Header</h3>
<p class="comment">这里可以设置需要从响应中删除的Header。</p>
<table class="ui table definition selectable">
<td class="title">需要删除的Header</td>
<td>
<div v-if="responseDeletingHeaders.length > 0">
<div class="ui label small basic" v-for="headerName in responseDeletingHeaders">{{headerName}} <a href=""><i class="icon remove" title="删除" @click.prevent="deleteDeletingHeader(vResponseHeaderPolicy.id, headerName)"></i></a> </div>
<div class="ui divider" ></div>
</div>
<button class="ui button small" type="button" @click.prevent="addDeletingHeader(vResponseHeaderPolicy.id, 'response')">+</button>
</td>
</table>
</div>
</div>
<div class="margin"></div>
</div>`

View File

@@ -1,5 +1,5 @@
Vue.component("http-remote-addr-config-box", {
props: ["v-remote-addr-config", "v-is-location"],
props: ["v-remote-addr-config", "v-is-location", "v-is-group"],
data: function () {
let config = this.vRemoteAddrConfig
if (config == null) {
@@ -15,14 +15,14 @@ Vue.component("http-remote-addr-config-box", {
},
methods: {
isOn: function () {
return (!this.vIsLocation || this.config.isPrior) && this.config.isOn
return ((!this.vIsLocation && !this.vIsGroup) || this.config.isPrior) && this.config.isOn
}
},
template: `<div>
<input type="hidden" name="remoteAddrJSON" :value="JSON.stringify(config)"/>
<table class="ui table definition selectable">
<prior-checkbox :v-config="config" v-if="vIsLocation"></prior-checkbox>
<tbody v-show="!vIsLocation || config.isPrior">
<prior-checkbox :v-config="config" v-if="vIsLocation || vIsGroup"></prior-checkbox>
<tbody v-show="(!vIsLocation && !vIsGroup) || config.isPrior">
<tr>
<td class="title">是否启用</td>
<td>

View File

@@ -1,5 +1,5 @@
Vue.component("http-stat-config-box", {
props: ["v-stat-config", "v-is-location"],
props: ["v-stat-config", "v-is-location", "v-is-group"],
data: function () {
let stat = this.vStatConfig
if (stat == null) {
@@ -15,8 +15,8 @@ Vue.component("http-stat-config-box", {
template: `<div>
<input type="hidden" name="statJSON" :value="JSON.stringify(stat)"/>
<table class="ui table definition selectable">
<prior-checkbox :v-config="stat" v-if="vIsLocation" ></prior-checkbox>
<tbody v-show="!vIsLocation || stat.isPrior">
<prior-checkbox :v-config="stat" v-if="vIsLocation || vIsGroup" ></prior-checkbox>
<tbody v-show="(!vIsLocation && !vIsGroup) || stat.isPrior">
<tr>
<td class="title">是否开启统计</td>
<td>

View File

@@ -1,5 +1,5 @@
Vue.component("http-web-root-box", {
props: ["v-root-config", "v-is-location"],
props: ["v-root-config", "v-is-location", "v-is-group"],
data: function () {
let rootConfig = this.vRootConfig
if (rootConfig == null) {
@@ -38,14 +38,14 @@ Vue.component("http-web-root-box", {
this.rootConfig.indexes.$remove(i)
},
isOn: function () {
return (!this.vIsLocation || this.rootConfig.isPrior) && this.rootConfig.isOn
return ((!this.vIsLocation && !this.vIsGroup) || this.rootConfig.isPrior) && this.rootConfig.isOn
}
},
template: `<div>
<input type="hidden" name="rootJSON" :value="JSON.stringify(rootConfig)"/>
<table class="ui table selectable definition">
<prior-checkbox :v-config="rootConfig" v-if="vIsLocation"></prior-checkbox>
<tbody v-show="!vIsLocation || rootConfig.isPrior">
<prior-checkbox :v-config="rootConfig" v-if="vIsLocation || vIsGroup"></prior-checkbox>
<tbody v-show="(!vIsLocation && !vIsGroup) || rootConfig.isPrior">
<tr>
<td class="title">是否开启静态资源分发</td>
<td>

View File

@@ -1,5 +1,5 @@
Vue.component("http-webp-config-box", {
props: ["v-webp-config", "v-is-location"],
props: ["v-webp-config", "v-is-location", "v-is-group"],
data: function () {
let config = this.vWebpConfig
if (config == null) {
@@ -43,7 +43,7 @@ Vue.component("http-webp-config-box", {
},
methods: {
isOn: function () {
return (!this.vIsLocation || this.config.isPrior) && this.config.isOn
return ((!this.vIsLocation && !this.vIsGroup) || this.config.isPrior) && this.config.isOn
},
changeExtensions: function (values) {
values.forEach(function (v, k) {
@@ -66,8 +66,8 @@ Vue.component("http-webp-config-box", {
template: `<div>
<input type="hidden" name="webpJSON" :value="JSON.stringify(config)"/>
<table class="ui table definition selectable">
<prior-checkbox :v-config="config" v-if="vIsLocation"></prior-checkbox>
<tbody v-show="!vIsLocation || config.isPrior">
<prior-checkbox :v-config="config" v-if="vIsLocation || vIsGroup"></prior-checkbox>
<tbody v-show="(!vIsLocation && !vIsGroup) || config.isPrior">
<tr>
<td class="title">是否启用</td>
<td>

View File

@@ -1,5 +1,5 @@
Vue.component("http-websocket-box", {
props: ["v-websocket-ref", "v-websocket-config", "v-is-location"],
props: ["v-websocket-ref", "v-websocket-config", "v-is-location", "v-is-group"],
data: function () {
let websocketRef = this.vWebsocketRef
if (websocketRef == null) {
@@ -55,7 +55,7 @@ Vue.component("http-websocket-box", {
},
methods: {
isOn: function () {
return (!this.vIsLocation || this.websocketRef.isPrior) && this.websocketRef.isOn
return ((!this.vIsLocation && !this.vIsGroup) || this.websocketRef.isPrior) && this.websocketRef.isOn
},
changeAdvancedVisible: function (v) {
this.advancedVisible = v
@@ -77,8 +77,8 @@ Vue.component("http-websocket-box", {
<input type="hidden" name="websocketRefJSON" :value="JSON.stringify(websocketRef)"/>
<input type="hidden" name="websocketJSON" :value="JSON.stringify(websocketConfig)"/>
<table class="ui table definition selectable">
<prior-checkbox :v-config="websocketRef" v-if="vIsLocation"></prior-checkbox>
<tbody v-show="(!this.vIsLocation || this.websocketRef.isPrior)">
<prior-checkbox :v-config="websocketRef" v-if="vIsLocation || vIsGroup"></prior-checkbox>
<tbody v-show="((!vIsLocation && !vIsGroup) || websocketRef.isPrior)">
<tr>
<td class="title">是否启用配置</td>
<td>

View File

@@ -18,7 +18,7 @@ Vue.component("prior-checkbox", {
<input type="checkbox" v-model="isPrior"/>
<label class="red"></label>
</div>
<p class="comment"><strong v-if="isPrior">[已打开]</strong> 打开后可以覆盖父级配置。</p>
<p class="comment"><strong v-if="isPrior">[已打开]</strong> 打开后可以覆盖父级或子级配置。</p>
</td>
</tr>
</tbody>`

View File

@@ -187,7 +187,7 @@ p.margin {
margin-top: 1em;
}
.opacity-mask {
opacity: 0.6;
opacity: 0.3;
}
/** 操作按钮容器 **/
.op.one {

View File

@@ -104,7 +104,7 @@ div.margin, p.margin {
}
.opacity-mask {
opacity: 0.6;
opacity: 0.3;
}
/** 操作按钮容器 **/

View File

@@ -0,0 +1,15 @@
{$layout}
{$template "/servers/groups/group/menu"}
{$template "/left_menu_without_menu"}
<div class="right-box without-menu">
<form method="post" class="ui form" data-tea-action="$" data-tea-success="success">
<input type="hidden" name="webId" :value="webId"/>
<http-access-log-config-box
:v-access-log-config="accessLogConfig"
:v-fields="fields"
:v-default-field-codes="defaultFieldCodes"
:v-is-group="true"></http-access-log-config-box>
<submit-btn></submit-btn>
</form>
</div>

View File

@@ -0,0 +1,3 @@
Tea.context(function () {
this.success = NotifyReloadSuccess("保存成功")
})

View File

@@ -0,0 +1,5 @@
<first-menu>
<menu-item :href="'.?serverId=' + serverId" code="index">设置</menu-item>
<menu-item :href="'.purge?serverId=' + serverId" code="purge">清理</menu-item>
<menu-item :href="'.preheat?serverId=' + serverId" code="preheat">预热</menu-item>
</first-menu>

View File

@@ -0,0 +1,11 @@
{$layout "layout_popup"}
<h3 v-if="!isReverse">添加缓存设置</h3>
<h3 v-if="isReverse">添加不缓存设置</h3>
<form method="post" class="ui form" data-tea-action="$" data-tea-success="success">
<table class="ui table definition selectable">
<tbody is="http-cache-ref-box" :v-cache-ref="cacheRef" :v-is-reverse="isReverse"></tbody>
</table>
<p class="comment" v-if="isReverse">如果请求满足当前添加的条件,则不缓存。</p>
<submit-btn>确定</submit-btn>
</form>

View File

@@ -0,0 +1,9 @@
Tea.context(function () {
this.success = NotifyPopup
this.cacheRef = null
if (window.parent.UPDATING_CACHE_REF != null) {
this.cacheRef = window.parent.UPDATING_CACHE_REF
this.isReverse = this.cacheRef.isReverse
}
})

View File

@@ -0,0 +1,16 @@
{$layout}
{$template "/servers/groups/group/menu"}
{$template "/left_menu_without_menu"}
<div class="right-box without-menu">
<form method="post" class="ui form" data-tea-action="$" data-tea-success="success">
<input type="hidden" name="webId" :value="webId"/>
<http-cache-config-box
:v-cache-config="cacheConfig"
:v-cache-policy="cachePolicy"
:v-is-group="true"
></http-cache-config-box>
<submit-btn></submit-btn>
<p class="comment">修改条件设置后请记得保存。</p>
</form>
</div>

View File

@@ -0,0 +1,3 @@
Tea.context(function () {
this.success = NotifyReloadSuccess("保存成功")
})

View File

@@ -0,0 +1,39 @@
{$layout}
{$template "/left_menu"}
<div class="right-box">
{$template "menu"}
<div class="margin"></div>
<div v-show="webConfig.cache == null || !webConfig.cache.isOn">
<p class="comment">没有开启缓存,不需要清理。</p>
</div>
<div v-show="webConfig.cache != null && webConfig.cache.isOn">
<p class="comment">可以在这里批量预热一组Key。</p>
<form method="post" class="ui form" data-tea-action="$" data-tea-before="before" data-tea-success="success" data-tea-fail="fail" data-tea-done="done" data-tea-timeout="3600">
<input type="hidden" name="serverId" :value="serverId"/>
<input type="hidden" name="webId" :value="webId"/>
<table class="ui table definition selectable">
<tr>
<td>Key列表</td>
<td>
<textarea name="keys" rows="10" ref="focus"></textarea>
<p class="comment">每行一个Key。</p>
</td>
</tr>
<tr>
<td class="title">操作结果</td>
<td>
<div v-if="isRequesting">数据发送中...</div>
<span class="red" v-if="!isRequesting && !isOk && message.length > 0">失败:{{message}}</span>
<div v-if="!isRequesting && isOk">
<span v-if="results.length == 0" class="red">此集群下没有任何可用的节点。</span>
<div class="ui label tiny" v-for="one in results" :class="{green:one.isOk, red:!one.isOk}" style="margin-bottom: 0.5em">{{one.nodeName}}{{one.message}}</div>
</div>
</td>
</tr>
</table>
<submit-btn v-if="!isRequesting">提交</submit-btn>
</form>
</div>
</div>

View File

@@ -0,0 +1,26 @@
Tea.context(function () {
this.isRequesting = false
this.isOk = false
this.message = ""
this.results = []
this.before = function () {
this.isRequesting = true
this.isOk = false
this.message = ""
this.results = []
}
this.success = function (resp) {
this.isOk = true
this.results = resp.data.results
}
this.fail = function (resp) {
this.message = resp.message
}
this.done = function () {
this.isRequesting = false
}
});

View File

@@ -0,0 +1,51 @@
{$layout}
{$template "/left_menu"}
<div class="right-box">
{$template "menu"}
<div class="margin"></div>
<div v-show="webConfig.cache == null || !webConfig.cache.isOn">
<p class="comment">没有开启缓存,不需要清理。</p>
</div>
<div v-show="webConfig.cache != null && webConfig.cache.isOn">
<p class="comment">可以在这里批量删除一组Key。</p>
<form method="post" class="ui form" data-tea-action="$" data-tea-before="before" data-tea-success="success" data-tea-fail="fail" data-tea-done="done" data-tea-timeout="300">
<input type="hidden" name="serverId" :value="serverId"/>
<input type="hidden" name="webId" :value="webId"/>
<table class="ui table definition selectable">
<tr>
<td class="title">操作类型</td>
<td>
<radio name="type" :v-value="'key'" v-model="type">根据Key</radio> &nbsp;
<radio name="type" :v-value="'prefix'" v-model="type">根据前缀</radio>
</td>
</tr>
<tr>
<td>
<span v-if="type == 'key'">Key列表</span>
<span v-if="type == 'prefix'">Key前缀列表</span>
</td>
<td>
<textarea name="keys" rows="10" ref="focus"></textarea>
<p class="comment" v-if="type == 'key'">每行一个Key比如是一个完整的URL<code-label>https://example.com/hello/world.html</code-label></p>
<p class="comment" v-if="type == 'prefix'">每行一个Key前缀比如是一个URL前缀<code-label>https://example.com/hello/</code-label></p>
</td>
</tr>
<tr>
<td>操作结果</td>
<td>
<div v-if="isRequesting">数据发送中...</div>
<span class="red" v-if="!isRequesting && !isOk && message.length > 0">失败:{{message}}</span>
<div v-if="!isRequesting && isOk">
<span v-if="results.length == 0" class="red">此集群下没有任何可用的节点。</span>
<div class="ui label tiny" v-for="one in results" :class="{green:one.isOk, red:!one.isOk}" style="margin-bottom: 0.5em">{{one.nodeName}}{{one.message}}</div>
</div>
</td>
</tr>
</table>
<submit-btn v-if="!isRequesting">提交</submit-btn>
</form>
</div>
</div>

View File

@@ -0,0 +1,31 @@
Tea.context(function () {
this.isRequesting = false
this.isOk = false
this.message = ""
this.results = []
this.before = function () {
this.isRequesting = true
this.isOk = false
this.message = ""
this.results = []
}
this.success = function (resp) {
this.isOk = true
this.results = resp.data.results
}
this.fail = function (resp) {
this.message = resp.message
}
this.done = function () {
this.isRequesting = false
}
/**
* 操作类型
*/
this.type = "key" // key | prefix
})

View File

@@ -0,0 +1,11 @@
{$layout}
{$template "/servers/groups/group/menu"}
{$template "/left_menu_without_menu"}
<div class="right-box without-menu">
<form method="post" class="ui form" data-tea-action="$" data-tea-success="success">
<input type="hidden" name="webId" :value="webId"/>
<http-charsets-box :v-usual-charsets="usualCharsets" :v-all-charsets="allCharsets" :v-charset-config="charsetConfig" :v-is-group="true"></http-charsets-box>
<submit-btn></submit-btn>
</form>
</div>

View File

@@ -0,0 +1,3 @@
Tea.context(function () {
this.success = NotifyReloadSuccess("保存成功")
})

View File

@@ -0,0 +1,15 @@
{$layout}
{$template "/left_menu"}
<div class="right-box">
<form method="post" class="ui form" data-tea-success="success" data-tea-action="$">
<input type="hidden" name="webId" :value="webId"/>
<input type="hidden" name="gzipId" :value="gzipConfig.id"/>
<http-gzip-box :v-gzip-ref="gzipRef" :v-gzip-config="gzipConfig"></http-gzip-box>
<div class="margin"></div>
<submit-btn></submit-btn>
</form>
</div>

View File

@@ -0,0 +1,3 @@
Tea.context(function () {
this.success = NotifyReloadSuccess("保存成功")
})

View File

@@ -0,0 +1,13 @@
{$layout}
{$template "/servers/groups/group/menu"}
{$template "/left_menu_without_menu"}
<div class="right-box without-menu">
<form class="ui form" data-tea-action="$" data-tea-success="success">
<csrf-token></csrf-token>
<input type="hidden" name="webId" :value="webId"/>
<http-compression-config-box :v-compression-config="compressionConfig" :v-is-group="true"></http-compression-config-box>
<submit-btn></submit-btn>
</form>
</div>

View File

@@ -0,0 +1,3 @@
Tea.context(function () {
this.success = NotifyReloadSuccess("保存成功")
})

View File

@@ -0,0 +1,16 @@
{$layout}
{$template "/servers/groups/group/menu"}
{$template "/left_menu_without_menu"}
<div class="right-box without-menu">
<form method="post" class="ui form" data-tea-action="$" data-tea-success="success">
<input type="hidden" name="webId" :value="webId"/>
<http-header-policy-box
:v-request-header-policy="requestHeaderPolicy"
:v-request-header-ref="requestHeaderRef"
:v-response-header-policy="responseHeaderPolicy"
:v-response-header-ref="responseHeaderRef"
:v-params="'groupId=' + group.id"
:v-is-group="true"></http-header-policy-box>
</form>
</div>

View File

@@ -0,0 +1,3 @@
Tea.context(function () {
this.success = NotifyReloadSuccess("保存成功")
})

View File

@@ -0,0 +1,16 @@
{$layout}
{$template "/servers/groups/group/menu"}
{$template "/left_menu_without_menu"}
<div class="right-box without-menu">
<form class="ui form" data-tea-action="$" data-tea-success="success">
<csrf-token></csrf-token>
<input type="hidden" name="webId" :value="webId"/>
<http-remote-addr-config-box
:v-remote-addr-config="remoteAddrConfig"
:v-is-group="true"></http-remote-addr-config-box>
<submit-btn></submit-btn>
</form>
</div>

View File

@@ -0,0 +1,3 @@
Tea.context(function () {
this.success = NotifyReloadSuccess("保存成功")
})

View File

@@ -0,0 +1,11 @@
{$layout}
{$template "/servers/groups/group/menu"}
{$template "/left_menu_without_menu"}
<div class="right-box without-menu">
<form method="post" class="ui form" data-tea-action="$" data-tea-success="success">
<input type="hidden" name="webId" :value="webId"/>
<http-stat-config-box :v-stat-config="statConfig" :v-is-group="true"></http-stat-config-box>
<submit-btn></submit-btn>
</form>
</div>

View File

@@ -0,0 +1,3 @@
Tea.context(function () {
this.success = NotifyReloadSuccess("保存成功")
})

View File

@@ -0,0 +1,11 @@
<first-menu>
<menu-item :href="'/servers/server/settings/waf?serverId=' + serverId" code="index">设置</menu-item>
<menu-item :href="'/servers/server/settings/waf/groups?serverId=' + serverId + '&type=inbound&firewallPolicyId='+firewallPolicyId" code="inbound">入站规则</menu-item>
<menu-item :href="'/servers/server/settings/waf/groups?serverId=' + serverId + '&type=outbound&firewallPolicyId='+firewallPolicyId" code="outbound">出站规则</menu-item>
<span class="item disabled">|</span>
<menu-item :href="'/servers/server/settings/waf/ipadmin/countries?serverId=' + serverId + '&firewallPolicyId='+firewallPolicyId" code="country">国家/地区封禁</menu-item>
<menu-item :href="'/servers/server/settings/waf/ipadmin/provinces?serverId=' + serverId + '&firewallPolicyId='+firewallPolicyId" code="province">省份封禁</menu-item>
<menu-item :href="'/servers/server/settings/waf/ipadmin/allowList?serverId=' + serverId + '&firewallPolicyId='+firewallPolicyId" code="allowList">白名单</menu-item>
<menu-item :href="'/servers/server/settings/waf/ipadmin/denyList?serverId=' + serverId + '&firewallPolicyId='+firewallPolicyId" code="denyList">黑名单</menu-item>
<menu-item :href="'/servers/server/settings/waf/ipadmin/test?serverId=' + serverId + '&firewallPolicyId='+firewallPolicyId" code="test">IP检查</menu-item>
</first-menu>

View File

@@ -0,0 +1,70 @@
{$layout}
{$template "/left_menu"}
<div class="right-box">
{$template "menu"}
<h3>分组<a href="" @click.prevent="updateGroup(group.id)">[修改]</a></h3>
<table class="ui table selectable definition">
<tr>
<td class="title">名称</td>
<td>{{group.name}}</td>
</tr>
<tr>
<td>描述</td>
<td>
<span v-if="group.description.length == 0" class="disabled">暂时还没有描述。</span>
<span v-if="group.description.length > 0">{{group.description}}</span>
</td>
</tr>
<tr>
<td>启用状态</td>
<td>
<label-on :v-is-on="group.isOn"></label-on>
</td>
</tr>
</table>
<h3 style="padding-top:0.8em">规则集<a href="" @click.prevent="createSet(group.id)">[添加规则集]</a> </h3>
<p class="comment" v-if="sets == null || sets.length == 0">暂时还没有规则。</p>
<table class="ui table selectable celled" id="sortable-table" v-if="sets != null && sets.length > 0">
<thead>
<tr>
<th style="width:3em"></th>
<th nowrap="">规则集名称</th>
<th nowrap="">规则</th>
<th nowrap="" class="center one wide">关系</th>
<th nowrap="">动作</th>
<th class="three op">操作</th>
</tr>
</thead>
<tbody v-for="set in sets" :data-set-id="set.id">
<tr>
<td style="text-align: center;"><i class="icon bars handle grey"></i> </td>
<td nowrap=""><a href="" @click.prevent="updateSet(set.id)"><span :class="{disabled:!set.isOn}">{{set.name}}</span></a>
<p style="margin-top:0.5em">
<label-on :v-is-on="set.isOn"></label-on>
</p>
</td>
<td class="rules-box">
<div v-for="rule in set.rules" style="margin-top: 0.4em;margin-bottom:0.4em">
<http-firewall-rule-label :v-rule="rule"></http-firewall-rule-label>
</div>
<span class="ui disabled" v-if="set.rules.length == 0">暂时还没有规则</span>
</td>
<td class="center">
<span v-if="set.connector.toUpperCase() == 'OR'"></span><span v-else></span>
<span class="small grey">({{set.connector.toUpperCase()}})</span>
</td>
<td nowrap="">
<http-firewall-actions-view :v-actions="set.actions"></http-firewall-actions-view>
</td>
<td>
<a href="" @click.prevent="updateSet(set.id)">修改</a> &nbsp; <a href="" @click.prevent="updateSetOn(set.id, false)" v-if="set.isOn">停用</a><a href="" @click.prevent="updateSetOn(set.id, true)" v-if="!set.isOn">启用</a> &nbsp; <a href="" @click.prevent="deleteSet(set.id)">删除</a>
</td>
</tr>
</tbody>
</table>
<p class="comment" v-if="group.sets != null && group.sets.length > 1">所有规则匹配顺序为从上到下,可以拖动左侧的<i class="icon bars"></i>排序。</p>
</div>

View File

@@ -0,0 +1,82 @@
Tea.context(function () {
this.$delay(function () {
let that = this
sortTable(function () {
let setIds = []
document
.querySelectorAll("tbody[data-set-id]")
.forEach(function (v) {
setIds.push(v.getAttribute("data-set-id"))
})
that.$post("/servers/components/waf/sortSets")
.params({
groupId: that.group.id,
setIds: setIds
})
.success(function () {
teaweb.successToast("排序保存成功")
})
})
})
// 更改分组
this.updateGroup = function (groupId) {
teaweb.popup("/servers/components/waf/updateGroupPopup?groupId=" + groupId, {
height: "16em",
callback: function () {
teaweb.success("保存成功", function () {
window.location.reload()
})
}
})
}
// 创建规则集
this.createSet = function (groupId) {
teaweb.popup("/servers/components/waf/createSetPopup?firewallPolicyId=" + this.firewallPolicyId + "&groupId=" + groupId + "&type=" + this.type, {
width: "50em",
height: "30em",
callback: function () {
teaweb.success("保存成功", function () {
window.location.reload()
})
}
})
}
// 修改规则集
this.updateSet = function (setId) {
teaweb.popup("/servers/components/waf/updateSetPopup?firewallPolicyId=" + this.firewallPolicyId + "&groupId=" + this.group.id + "&type=" + this.type + "&setId=" + setId, {
width: "50em",
height: "30em",
callback: function () {
teaweb.success("保存成功", function () {
window.location.reload()
})
}
})
}
// 停用|启用规则集
this.updateSetOn = function (setId, isOn) {
this.$post("/servers/components/waf/updateSetOn")
.params({
setId: setId,
isOn: isOn ? 1 : 0
})
.refresh()
}
// 删除规则集
this.deleteSet = function (setId) {
let that = this
teaweb.confirm("确定要删除此规则集吗?", function () {
that.$post("/servers/components/waf/deleteSet")
.params({
groupId: this.group.id,
setId: setId
})
.refresh()
})
}
})

View File

@@ -0,0 +1,50 @@
{$layout}
{$template "/left_menu"}
<div class="right-box">
{$template "menu"}
<second-menu>
<a href="" class="item" @click.prevent="createGroup(type)">[添加分组]</a>
</second-menu>
<warning-message v-if="!wafIsOn">当前WAF未启用设置将在<a :href="'/servers/server/settings/waf?serverId=' + serverId">[启用]</a>后生效。</warning-message>
<p class="comment" v-if="groups.length == 0">暂时还没有规则分组。</p>
<table class="ui table selectable celled" v-if="groups.length > 0" id="sortable-table">
<thead>
<tr>
<th style="width:3em"></th>
<th>规则分组</th>
<th class="center">规则集</th>
<th class="three op">操作</th>
</tr>
</thead>
<tbody v-for="group in groups" :data-group-id="group.id">
<tr>
<td style="text-align: center;"><i class="icon bars handle grey" title="拖动排序"></i> </td>
<td><a :href="'/servers/server/settings/waf/group?serverId=' + serverId + '&firewallPolicyId=' + firewallPolicyId + '&type=' + type + '&groupId=' + group.id"><span :class="{disabled:!group.isOn}">{{group.name}}</span></a>
<p class="comment" v-if="group.description.length > 0" style="padding-bottom:0">{{group.description}}</p>
<p style="margin-top: 0.5em">
<span v-if="group.isOn" class="ui label tiny basic green">启用</span>
<span v-if="!group.isOn" class="ui label tiny basic red">停用</span>
<span v-if="group.code.length > 0" class="ui label basic tiny">预置</span>
<span v-if="group.code.length == 0" class="ui label basic tiny">自定义</span>
</p>
</td>
<td class="center">
<a :href="'/servers/server/settings/waf/group?serverId=' + serverId + '&firewallPolicyId=' + firewallPolicyId + '&type=' + type + '&groupId=' + group.id">{{group.countSets}}</a>
</td>
<td>
<a :href="'/servers/server/settings/waf/group?serverId=' + serverId + '&firewallPolicyId=' + firewallPolicyId + '&type=' + type + '&groupId=' + group.id">详情</a> &nbsp;
<a href="" v-if="!group.isOn" @click.prevent="enableGroup(group.id)">启用</a><a href="" v-if="group.isOn" @click.prevent="disableGroup(group.id)">停用</a> &nbsp;
<a href="" @click.prevent="deleteGroup(group.id)" v-if="group.canDelete">删除</a>
</td>
</tr>
</tbody>
</table>
<p class="comment" v-if="groups.length > 0">所有规则匹配顺序为从上到下,可以拖动左侧的<i class="icon bars"></i>排序。</p>
</div>

View File

@@ -0,0 +1,68 @@
Tea.context(function () {
// 排序
this.$delay(function () {
let that = this
sortTable(function () {
let groupIds = []
document.querySelectorAll("tbody[data-group-id]")
.forEach(function (v) {
groupIds.push(v.getAttribute("data-group-id"))
})
that.$post("/servers/components/waf/sortGroups")
.params({
firewallPolicyId: that.firewallPolicyId,
type: that.type,
groupIds: groupIds
})
.success(function () {
teaweb.successToast("排序保存成功")
})
})
})
// 启用
this.enableGroup = function (groupId) {
this.$post("/servers/components/waf/updateGroupOn")
.params({
groupId: groupId,
isOn: 1
})
.refresh()
}
// 停用
this.disableGroup = function (groupId) {
this.$post("/servers/components/waf/updateGroupOn")
.params({
groupId: groupId,
isOn: 0
})
.refresh()
}
// 删除
this.deleteGroup = function (groupId) {
teaweb.confirm("确定要删除此规则分组吗?", function () {
this.$post("/servers/components/waf/deleteGroup")
.params({
firewallPolicyId: this.firewallPolicyId,
groupId: groupId
})
.refresh()
})
}
// 添加分组
this.createGroup = function (type) {
teaweb.popup("/servers/components/waf/createGroupPopup?firewallPolicyId=" + this.firewallPolicyId + "&type=" + type, {
height: "16em",
callback: function () {
teaweb.success("保存成功", function () {
window.location.reload()
})
}
})
}
})

View File

@@ -0,0 +1,11 @@
{$layout}
{$template "/servers/groups/group/menu"}
{$template "/left_menu_without_menu"}
<div class="right-box without-menu">
<form method="post" class="ui form" data-tea-action="$" data-tea-success="success">
<input type="hidden" name="webId" :value="webId"/>
<http-firewall-config-box :v-firewall-config="firewallConfig" :v-firewall-policy="firewallPolicy" :v-is-group="true"></http-firewall-config-box>
<submit-btn></submit-btn>
</form>
</div>

View File

@@ -0,0 +1,3 @@
Tea.context(function () {
this.success = NotifyReloadSuccess("保存成功")
})

View File

@@ -0,0 +1,25 @@
{$layout}
{$template "/left_menu"}
<div class="right-box">
{$template "../menu"}
<warning-message v-if="!featureIsOn">尚未为当前用户开通此功能。</warning-message>
{$ if .featureIsOn}
<second-menu>
<menu-item @click.prevent="createIP('white')">添加IP</menu-item>
<span class="item">|</span>
<div class="item"><ip-list-bind-box :v-http-firewall-policy-id="firewallPolicyId" :v-type="'white'"></ip-list-bind-box></div>
<span class="item">|</span>
<span class="item">ID: {{listId}} &nbsp; <tip-icon content="ID可以用于使用API操作此IP名单"></tip-icon></span>
</second-menu>
<warning-message v-if="!wafIsOn">当前WAF未启用设置将在<a :href="'/servers/server/settings/waf?serverId=' + serverId">[启用]</a>后生效。</warning-message>
<p class="comment" v-if="items.length == 0">暂时还没有IP。</p>
<ip-list-table v-if="items.length > 0" :v-items="items" @update-item="updateItem" @delete-item="deleteItem"></ip-list-table>
<div class="page" v-html="page"></div>
{$end}
</div>

View File

@@ -0,0 +1,38 @@
Tea.context(function () {
this.updateItem = function (itemId) {
teaweb.popup(Tea.url(".updateIPPopup?listId=" + this.listId, {itemId: itemId}), {
height: "26em",
callback: function () {
teaweb.success("保存成功", function () {
teaweb.reload()
})
}
})
}
this.deleteItem = function (itemId) {
let that = this
teaweb.confirm("确定要删除这个IP吗", function () {
that.$post(".deleteIP")
.params({
"listId": this.listId,
"itemId": itemId
})
.refresh()
})
}
/**
* 添加IP名单菜单
*/
this.createIP = function (type) {
teaweb.popup("/servers/iplists/createIPPopup?listId=" + this.listId + '&type=' + type, {
height: "26em",
callback: function () {
teaweb.success("保存成功", function () {
teaweb.reload()
})
}
})
}
})

View File

@@ -0,0 +1,16 @@
.region-letter-group .item {
padding-left: 1em !important;
padding-right: 1em !important;
}
.country-group {
padding-bottom: 1em;
}
.country-group .country-list .item {
float: left;
width: 12em;
margin-bottom: 0.5em;
}
.country-group .country-list .item .checkbox label {
font-size: 12px !important;
}
/*# sourceMappingURL=countries.css.map */

View File

@@ -0,0 +1 @@
{"version":3,"sources":["countries.less"],"names":[],"mappings":"AAAA,oBACC;EACC,4BAAA;EACA,6BAAA;;AAIF;EAaC,mBAAA;;AAbD,cACC,cACC;EACC,WAAA;EACA,WAAA;EACA,oBAAA;;AALH,cACC,cACC,MAKC,UAAU;EACT,0BAAA","file":"countries.css"}

View File

@@ -0,0 +1,59 @@
{$layout}
{$template "/left_menu"}
<div class="right-box">
{$template "../menu"}
<warning-message v-if="!featureIsOn">尚未为当前用户开通此功能。</warning-message>
{$ if .featureIsOn}
<warning-message v-if="!wafIsOn">当前WAF未启用设置将在<a :href="'/servers/server/settings/waf?serverId=' + serverId">[启用]</a>后生效。</warning-message>
<form method="post" class="ui form" data-tea-action="$" data-tea-success="success">
<input type="hidden" name="firewallPolicyId" :value="firewallPolicyId"/>
<table class="ui table selectable definition">
<tr>
<td class="title">已封禁</td>
<td>
<span v-if="countSelectedCountries == 0" class="disabled">暂时没有选择封禁区域。</span>
<div class="ui label tiny basic" v-for="country in countries" v-if="country.isChecked" style="margin-bottom: 0.5em">
<input type="hidden" name="countryIds" :value="country.id"/>
({{country.letter}}){{country.name}} <a href="" @click.prevent="deselectCountry(country)" title="取消封禁"><i class="icon remove"></i></a>
</div>
</td>
</tr>
<tr>
<td>选择封禁区域</td>
<td>
<more-options-indicator>选择区域</more-options-indicator>
<div class="ui menu tabular tiny region-letter-group" v-show="moreOptionsVisible">
<a href="" v-for="group in letterGroups" class="item" :class="{active: group == selectedGroup}" @click.prevent="selectGroup(group)">{{group}}</a>
<div class="item right">
<div class="ui checkbox" @click.prevent="checkAll">
<input type="checkbox" v-model="isCheckingAll"/>
<label>全选</label>
</div>
</div>
</div>
<div v-for="group in letterGroups" v-show="moreOptionsVisible">
<div v-for="letter in group" v-if="letterCountries[letter] != null && group == selectedGroup" class="country-group">
<h4>{{letter}}</h4>
<div class="country-list">
<div class="item" v-for="country in letterCountries[letter]">
<div class="ui checkbox" @click.prevent="selectCountry(country)">
<input type="checkbox" v-model="country.isChecked"/>
<label>{{country.name}}</label>
</div>
</div>
</div>
<div class="clear"></div>
</div>
</div>
</td>
</tr>
</table>
<submit-btn></submit-btn>
</form>
{$end}
</div>

View File

@@ -0,0 +1,54 @@
Tea.context(function () {
this.letterGroups = [
"ABC", "DEF", "GHI", "JKL", "MNO", "PQR", "STU", "VWX", "YZ"
];
this.selectedGroup = "ABC"
this.letterCountries = {}
let that = this
this.countSelectedCountries = this.countries.$count(function (k, country) {
return country.isChecked
})
this.countries.forEach(function (country) {
if (typeof (that.letterCountries[country.letter]) == "undefined") {
that.letterCountries[country.letter] = []
}
that.letterCountries[country.letter].push(country)
})
this.isCheckingAll = false
this.selectGroup = function (group) {
this.selectedGroup = group
}
this.selectCountry = function (country) {
country.isChecked = !country.isChecked
this.change()
}
this.deselectCountry = function (country) {
country.isChecked = false
this.change()
}
this.checkAll = function () {
this.isCheckingAll = !this.isCheckingAll
this.countries.forEach(function (country) {
country.isChecked = that.isCheckingAll
})
this.change()
}
this.success = function () {
teaweb.success("保存成功", function () {
teaweb.reload()
})
}
this.change = function () {
this.countSelectedCountries = this.countries.$count(function (k, country) {
return country.isChecked
})
}
})

View File

@@ -0,0 +1,22 @@
.region-letter-group {
.item {
padding-left: 1em !important;
padding-right: 1em !important;
}
}
.country-group {
.country-list {
.item {
float: left;
width: 12em;
margin-bottom: 0.5em;
.checkbox label {
font-size: 12px !important;
}
}
}
padding-bottom: 1em;
}

View File

@@ -0,0 +1,25 @@
{$layout}
{$template "/left_menu"}
<div class="right-box">
{$template "../menu"}
<warning-message v-if="!featureIsOn">尚未为当前用户开通此功能。</warning-message>
{$ if .featureIsOn}
<second-menu>
<menu-item @click.prevent="createIP('black')">添加IP</menu-item>
<span class="item">|</span>
<div class="item"><ip-list-bind-box :v-http-firewall-policy-id="firewallPolicyId" :v-type="'black'"></ip-list-bind-box></div>
<span class="item">|</span>
<span class="item">ID: {{listId}} &nbsp; <tip-icon content="ID可以用于使用API操作此IP名单"></tip-icon></span>
</second-menu>
<warning-message v-if="!wafIsOn">当前WAF未启用设置将在<a :href="'/servers/server/settings/waf?serverId=' + serverId">[启用]</a>后生效。</warning-message>
<p class="comment" v-if="items.length == 0">暂时还没有IP。</p>
<ip-list-table v-if="items.length > 0" :v-items="items" @update-item="updateItem" @delete-item="deleteItem"></ip-list-table>
<div class="page" v-html="page"></div>
{$end}
</div>

View File

@@ -0,0 +1,38 @@
Tea.context(function () {
this.updateItem = function (itemId) {
teaweb.popup(Tea.url(".updateIPPopup?listId=" + this.listId, {itemId: itemId}), {
height: "26em",
callback: function () {
teaweb.success("保存成功", function () {
teaweb.reload()
})
}
})
}
this.deleteItem = function (itemId) {
let that = this
teaweb.confirm("确定要删除这个IP吗", function () {
that.$post(".deleteIP")
.params({
"listId": this.listId,
"itemId": itemId
})
.refresh()
})
}
/**
* 添加IP名单菜单
*/
this.createIP = function (type) {
teaweb.popup("/servers/iplists/createIPPopup?listId=" + this.listId + '&type=' + type, {
height: "26em",
callback: function () {
teaweb.success("保存成功", function () {
teaweb.reload()
})
}
})
}
})

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