Initial commit (code only without large binaries)
This commit is contained in:
@@ -0,0 +1,134 @@
|
||||
package log
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/iplibrary"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/userconfigs"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"github.com/iwind/TeaGo/lists"
|
||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type HistoryAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *HistoryAction) Init() {
|
||||
this.Nav("", "log", "")
|
||||
this.SecondMenu("history")
|
||||
}
|
||||
|
||||
func (this *HistoryAction) RunGet(params struct {
|
||||
ServerId int64
|
||||
Day string
|
||||
|
||||
Ip string
|
||||
Domain string
|
||||
ClusterId int64
|
||||
NodeId int64
|
||||
Keyword string
|
||||
RequestId string
|
||||
HasError int
|
||||
|
||||
Partition int32 `default:"-1"`
|
||||
}) {
|
||||
this.Data["featureIsOn"] = true
|
||||
|
||||
if !this.ValidateFeature(userconfigs.UserFeatureCodeServerViewAccessLog, params.ServerId) {
|
||||
this.Data["featureIsOn"] = false
|
||||
this.Show()
|
||||
return
|
||||
}
|
||||
this.Data["ip"] = params.Ip
|
||||
this.Data["domain"] = params.Domain
|
||||
this.Data["keyword"] = params.Keyword
|
||||
this.Data["path"] = this.Request.URL.Path
|
||||
this.Data["clusterId"] = params.ClusterId
|
||||
this.Data["nodeId"] = params.NodeId
|
||||
if len(params.Day) == 0 {
|
||||
params.Day = timeutil.Format("Y-m-d")
|
||||
}
|
||||
|
||||
this.Data["path"] = this.Request.URL.Path
|
||||
this.Data["day"] = params.Day
|
||||
this.Data["accessLogs"] = []interface{}{}
|
||||
this.Data["hasError"] = params.HasError
|
||||
|
||||
day := params.Day
|
||||
ipList := []string{}
|
||||
|
||||
if len(day) > 0 && regexp.MustCompile(`\d{4}-\d{2}-\d{2}`).MatchString(day) {
|
||||
day = strings.ReplaceAll(day, "-", "")
|
||||
var size = int64(20)
|
||||
|
||||
this.Data["hasError"] = params.HasError
|
||||
|
||||
resp, err := this.RPC().HTTPAccessLogRPC().ListHTTPAccessLogs(this.UserContext(), &pb.ListHTTPAccessLogsRequest{
|
||||
Partition: params.Partition,
|
||||
RequestId: params.RequestId,
|
||||
ServerId: params.ServerId,
|
||||
HasError: params.HasError > 0,
|
||||
Day: day,
|
||||
Size: size,
|
||||
Keyword: params.Keyword,
|
||||
Ip: params.Ip,
|
||||
Domain: params.Domain,
|
||||
NodeId: params.NodeId,
|
||||
NodeClusterId: params.ClusterId,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
if len(resp.HttpAccessLogs) == 0 {
|
||||
this.Data["accessLogs"] = []interface{}{}
|
||||
} else {
|
||||
this.Data["accessLogs"] = resp.HttpAccessLogs
|
||||
for _, accessLog := range resp.HttpAccessLogs {
|
||||
if len(accessLog.RemoteAddr) > 0 {
|
||||
if !lists.ContainsString(ipList, accessLog.RemoteAddr) {
|
||||
ipList = append(ipList, accessLog.RemoteAddr)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
this.Data["hasMore"] = resp.HasMore
|
||||
this.Data["nextRequestId"] = resp.RequestId
|
||||
|
||||
// 上一个requestId
|
||||
this.Data["hasPrev"] = false
|
||||
this.Data["lastRequestId"] = ""
|
||||
if len(params.RequestId) > 0 {
|
||||
this.Data["hasPrev"] = true
|
||||
prevResp, err := this.RPC().HTTPAccessLogRPC().ListHTTPAccessLogs(this.UserContext(), &pb.ListHTTPAccessLogsRequest{
|
||||
Partition: params.Partition,
|
||||
RequestId: params.RequestId,
|
||||
ServerId: params.ServerId,
|
||||
HasError: params.HasError > 0,
|
||||
Day: day,
|
||||
Size: size,
|
||||
Reverse: true,
|
||||
Keyword: params.Keyword,
|
||||
Ip: params.Ip,
|
||||
Domain: params.Domain,
|
||||
NodeId: params.NodeId,
|
||||
NodeClusterId: params.ClusterId,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if int64(len(prevResp.HttpAccessLogs)) == size {
|
||||
this.Data["lastRequestId"] = prevResp.RequestId
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 根据IP查询区域
|
||||
this.Data["regions"] = iplibrary.LookupIPSummaries(ipList)
|
||||
|
||||
this.Show()
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
package log
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/iplibrary"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/userconfigs"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/lists"
|
||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
)
|
||||
|
||||
type IndexAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *IndexAction) Init() {
|
||||
this.Nav("", "log", "")
|
||||
this.SecondMenu("index")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct {
|
||||
ServerId int64
|
||||
RequestId string
|
||||
Ip string
|
||||
Domain string
|
||||
ClusterId int64
|
||||
NodeId int64
|
||||
Keyword string
|
||||
}) {
|
||||
this.Data["featureIsOn"] = this.ValidateFeature(userconfigs.UserFeatureCodeServerViewAccessLog, params.ServerId)
|
||||
|
||||
this.Data["serverId"] = params.ServerId
|
||||
this.Data["requestId"] = params.RequestId
|
||||
this.Data["ip"] = params.Ip
|
||||
this.Data["domain"] = params.Domain
|
||||
this.Data["keyword"] = params.Keyword
|
||||
this.Data["path"] = this.Request.URL.Path
|
||||
this.Data["clusterId"] = params.ClusterId
|
||||
this.Data["nodeId"] = params.NodeId
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunPost(params struct {
|
||||
ServerId int64
|
||||
RequestId string
|
||||
Keyword string
|
||||
Ip string
|
||||
Domain string
|
||||
ClusterId int64
|
||||
NodeId int64
|
||||
|
||||
Partition int32 `default:"-1"`
|
||||
|
||||
Must *actions.Must
|
||||
}) {
|
||||
if !this.ValidateFeature(userconfigs.UserFeatureCodeServerViewAccessLog, params.ServerId) {
|
||||
return
|
||||
}
|
||||
|
||||
isReverse := len(params.RequestId) > 0
|
||||
accessLogsResp, err := this.RPC().HTTPAccessLogRPC().ListHTTPAccessLogs(this.UserContext(), &pb.ListHTTPAccessLogsRequest{
|
||||
Partition: params.Partition,
|
||||
ServerId: params.ServerId,
|
||||
RequestId: params.RequestId,
|
||||
Size: 20,
|
||||
Day: timeutil.Format("Ymd"),
|
||||
Keyword: params.Keyword,
|
||||
Ip: params.Ip,
|
||||
Domain: params.Domain,
|
||||
NodeId: params.NodeId,
|
||||
NodeClusterId: params.ClusterId,
|
||||
Reverse: isReverse,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
ipList := []string{}
|
||||
accessLogs := accessLogsResp.HttpAccessLogs
|
||||
if len(accessLogs) == 0 {
|
||||
accessLogs = []*pb.HTTPAccessLog{}
|
||||
} else {
|
||||
for _, accessLog := range accessLogs {
|
||||
if len(accessLog.RemoteAddr) > 0 {
|
||||
if !lists.ContainsString(ipList, accessLog.RemoteAddr) {
|
||||
ipList = append(ipList, accessLog.RemoteAddr)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
this.Data["accessLogs"] = accessLogs
|
||||
if len(accessLogs) > 0 {
|
||||
this.Data["requestId"] = accessLogs[0].RequestId
|
||||
} else {
|
||||
this.Data["requestId"] = params.RequestId
|
||||
}
|
||||
this.Data["hasMore"] = accessLogsResp.HasMore
|
||||
|
||||
// 根据IP查询区域
|
||||
this.Data["regions"] = iplibrary.LookupIPSummaries(ipList)
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package log
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/default/servers/serverutils"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/helpers"
|
||||
"github.com/iwind/TeaGo"
|
||||
)
|
||||
|
||||
func init() {
|
||||
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
||||
server.
|
||||
Helper(helpers.NewUserMustAuth("")).
|
||||
Helper(serverutils.NewServerHelper()).
|
||||
Prefix("/servers/server/log").
|
||||
GetPost("", new(IndexAction)).
|
||||
GetPost("/today", new(TodayAction)).
|
||||
GetPost("/history", new(HistoryAction)).
|
||||
Get("/viewPopup", new(ViewPopupAction)).
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
package log
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/iplibrary"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/userconfigs"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"github.com/iwind/TeaGo/lists"
|
||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
)
|
||||
|
||||
type TodayAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *TodayAction) Init() {
|
||||
this.Nav("", "log", "")
|
||||
this.SecondMenu("today")
|
||||
}
|
||||
|
||||
func (this *TodayAction) RunGet(params struct {
|
||||
RequestId string
|
||||
ServerId int64
|
||||
HasError int
|
||||
|
||||
Ip string
|
||||
Domain string
|
||||
ClusterId int64
|
||||
NodeId int64
|
||||
Keyword string
|
||||
Partition int32 `default:"-1"`
|
||||
}) {
|
||||
this.Data["featureIsOn"] = true
|
||||
|
||||
if !this.ValidateFeature(userconfigs.UserFeatureCodeServerViewAccessLog, params.ServerId) {
|
||||
this.Data["featureIsOn"] = false
|
||||
this.Show()
|
||||
return
|
||||
}
|
||||
this.Data["ip"] = params.Ip
|
||||
this.Data["domain"] = params.Domain
|
||||
this.Data["keyword"] = params.Keyword
|
||||
this.Data["path"] = this.Request.URL.Path
|
||||
this.Data["clusterId"] = params.ClusterId
|
||||
this.Data["nodeId"] = params.NodeId
|
||||
var size = int64(20)
|
||||
|
||||
this.Data["path"] = this.Request.URL.Path
|
||||
this.Data["hasError"] = params.HasError
|
||||
|
||||
resp, err := this.RPC().HTTPAccessLogRPC().ListHTTPAccessLogs(this.UserContext(), &pb.ListHTTPAccessLogsRequest{
|
||||
Partition: params.Partition,
|
||||
RequestId: params.RequestId,
|
||||
ServerId: params.ServerId,
|
||||
HasError: params.HasError > 0,
|
||||
Day: timeutil.Format("Ymd"),
|
||||
Size: size,
|
||||
Keyword: params.Keyword,
|
||||
Ip: params.Ip,
|
||||
Domain: params.Domain,
|
||||
NodeId: params.NodeId,
|
||||
NodeClusterId: params.ClusterId,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
ipList := []string{}
|
||||
if len(resp.HttpAccessLogs) == 0 {
|
||||
this.Data["accessLogs"] = []interface{}{}
|
||||
} else {
|
||||
this.Data["accessLogs"] = resp.HttpAccessLogs
|
||||
for _, accessLog := range resp.HttpAccessLogs {
|
||||
if len(accessLog.RemoteAddr) > 0 {
|
||||
if !lists.ContainsString(ipList, accessLog.RemoteAddr) {
|
||||
ipList = append(ipList, accessLog.RemoteAddr)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
this.Data["hasMore"] = resp.HasMore
|
||||
this.Data["nextRequestId"] = resp.RequestId
|
||||
|
||||
// 上一个requestId
|
||||
this.Data["hasPrev"] = false
|
||||
this.Data["lastRequestId"] = ""
|
||||
if len(params.RequestId) > 0 {
|
||||
this.Data["hasPrev"] = true
|
||||
prevResp, err := this.RPC().HTTPAccessLogRPC().ListHTTPAccessLogs(this.UserContext(), &pb.ListHTTPAccessLogsRequest{
|
||||
Partition: params.Partition,
|
||||
RequestId: params.RequestId,
|
||||
ServerId: params.ServerId,
|
||||
HasError: params.HasError > 0,
|
||||
Day: timeutil.Format("Ymd"),
|
||||
Size: size,
|
||||
Reverse: true,
|
||||
Keyword: params.Keyword,
|
||||
Ip: params.Ip,
|
||||
Domain: params.Domain,
|
||||
NodeId: params.NodeId,
|
||||
NodeClusterId: params.ClusterId,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if int64(len(prevResp.HttpAccessLogs)) == size {
|
||||
this.Data["lastRequestId"] = prevResp.RequestId
|
||||
}
|
||||
}
|
||||
|
||||
// 根据IP查询区域
|
||||
this.Data["regions"] = iplibrary.LookupIPSummaries(ipList)
|
||||
|
||||
this.Show()
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
package log
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/iplibrary"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/userconfigs"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/errors"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"net/http"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type ViewPopupAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *ViewPopupAction) Init() {
|
||||
this.Nav("", "", "")
|
||||
}
|
||||
|
||||
func (this *ViewPopupAction) RunGet(params struct {
|
||||
RequestId string
|
||||
}) {
|
||||
if !this.ValidateFeature(userconfigs.UserFeatureCodeServerViewAccessLog, 0) {
|
||||
return
|
||||
}
|
||||
|
||||
accessLogResp, err := this.RPC().HTTPAccessLogRPC().FindHTTPAccessLog(this.UserContext(), &pb.FindHTTPAccessLogRequest{RequestId: params.RequestId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
accessLog := accessLogResp.HttpAccessLog
|
||||
if accessLog == nil {
|
||||
this.WriteString("not found: " + params.RequestId)
|
||||
return
|
||||
}
|
||||
|
||||
// 状态
|
||||
if len(accessLog.StatusMessage) == 0 {
|
||||
accessLog.StatusMessage = http.StatusText(int(accessLog.Status))
|
||||
}
|
||||
|
||||
this.Data["accessLog"] = accessLog
|
||||
|
||||
// WAF相关
|
||||
var wafMap maps.Map = nil
|
||||
if accessLog.FirewallPolicyId > 0 {
|
||||
policyResp, err := this.RPC().HTTPFirewallPolicyRPC().FindEnabledHTTPFirewallPolicy(this.UserContext(), &pb.FindEnabledHTTPFirewallPolicyRequest{HttpFirewallPolicyId: accessLog.FirewallPolicyId})
|
||||
if err != nil {
|
||||
// 如果没有权限查看,则只显示系统策略
|
||||
if errors.IsResourceNotFound(err) {
|
||||
wafMap = maps.Map{
|
||||
"policy": maps.Map{
|
||||
"id": 0,
|
||||
"name": "系统策略",
|
||||
},
|
||||
"group": maps.Map{
|
||||
"id": 0,
|
||||
"name": "系统策略",
|
||||
},
|
||||
}
|
||||
} else {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
} else if policyResp.HttpFirewallPolicy != nil {
|
||||
wafMap = maps.Map{
|
||||
"policy": maps.Map{
|
||||
"id": policyResp.HttpFirewallPolicy.Id,
|
||||
"name": policyResp.HttpFirewallPolicy.Name,
|
||||
},
|
||||
}
|
||||
if accessLog.FirewallRuleGroupId > 0 {
|
||||
groupResp, err := this.RPC().HTTPFirewallRuleGroupRPC().FindEnabledHTTPFirewallRuleGroup(this.UserContext(), &pb.FindEnabledHTTPFirewallRuleGroupRequest{FirewallRuleGroupId: accessLog.FirewallRuleGroupId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if groupResp.FirewallRuleGroup != nil {
|
||||
wafMap["group"] = maps.Map{
|
||||
"id": groupResp.FirewallRuleGroup.Id,
|
||||
"name": groupResp.FirewallRuleGroup.Name,
|
||||
}
|
||||
|
||||
if accessLog.FirewallRuleSetId > 0 {
|
||||
setResp, err := this.RPC().HTTPFirewallRuleSetRPC().FindEnabledHTTPFirewallRuleSet(this.UserContext(), &pb.FindEnabledHTTPFirewallRuleSetRequest{FirewallRuleSetId: accessLog.FirewallRuleSetId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if setResp.FirewallRuleSet != nil {
|
||||
wafMap["set"] = maps.Map{
|
||||
"id": setResp.FirewallRuleSet.Id,
|
||||
"name": setResp.FirewallRuleSet.Name,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
this.Data["wafInfo"] = wafMap
|
||||
|
||||
// 地域相关
|
||||
var regionMap maps.Map = nil
|
||||
var ipRegion = iplibrary.LookupIP(accessLog.RemoteAddr)
|
||||
if ipRegion != nil && ipRegion.IsOk() {
|
||||
regionMap = maps.Map{
|
||||
"full": ipRegion.RegionSummary(),
|
||||
"isp": ipRegion.ProviderName(),
|
||||
}
|
||||
}
|
||||
this.Data["region"] = regionMap
|
||||
|
||||
// 请求内容
|
||||
this.Data["requestBody"] = string(accessLog.RequestBody)
|
||||
this.Data["requestContentType"] = "text/plain"
|
||||
|
||||
requestContentType, ok := accessLog.Header["Content-Type"]
|
||||
if ok {
|
||||
if len(requestContentType.Values) > 0 {
|
||||
var contentType = requestContentType.Values[0]
|
||||
if strings.HasSuffix(contentType, "/json") || strings.Contains(contentType, "/json;") {
|
||||
this.Data["requestContentType"] = "application/json"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.Show()
|
||||
}
|
||||
@@ -0,0 +1,237 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package access
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
teaconst "github.com/TeaOSLab/EdgeUser/internal/const"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/utils"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type CreatePopupAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *CreatePopupAction) Init() {
|
||||
this.Nav("", "", "")
|
||||
}
|
||||
|
||||
func (this *CreatePopupAction) RunGet(params struct{}) {
|
||||
this.Data["authTypes"] = serverconfigs.FindAllHTTPAuthTypes(teaconst.Role)
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *CreatePopupAction) RunPost(params struct {
|
||||
Name string
|
||||
Type string
|
||||
|
||||
// TypeA
|
||||
TypeASecret string
|
||||
TypeASignParamName string
|
||||
TypeALife int
|
||||
|
||||
// TypeB
|
||||
TypeBSecret string
|
||||
TypeBLife int
|
||||
|
||||
// TypeC
|
||||
TypeCSecret string
|
||||
TypeCLife int
|
||||
|
||||
// TypeD
|
||||
TypeDSecret string
|
||||
TypeDSignParamName string
|
||||
TypeDTimestampParamName string
|
||||
TypeDLife int
|
||||
|
||||
// BasicAuth
|
||||
HttpAuthBasicAuthUsersJSON []byte
|
||||
BasicAuthRealm string
|
||||
BasicAuthCharset string
|
||||
|
||||
// SubRequest
|
||||
SubRequestURL string
|
||||
SubRequestMethod string
|
||||
SubRequestFollowRequest bool
|
||||
|
||||
Exts []string
|
||||
DomainsJSON []byte
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
params.Must.
|
||||
Field("name", params.Name).
|
||||
Require("请输入名称").
|
||||
Field("type", params.Type).
|
||||
Require("请输入鉴权类型")
|
||||
|
||||
var ref = &serverconfigs.HTTPAuthPolicyRef{IsOn: true}
|
||||
var method serverconfigs.HTTPAuthMethodInterface
|
||||
|
||||
// 扩展名
|
||||
var exts = utils.NewStringsStream(params.Exts).
|
||||
Map(strings.TrimSpace, strings.ToLower).
|
||||
Filter(utils.FilterNotEmpty).
|
||||
Map(utils.MapAddPrefixFunc(".")).
|
||||
Unique().
|
||||
Result()
|
||||
|
||||
// 域名
|
||||
var domains = []string{}
|
||||
if len(params.DomainsJSON) > 0 {
|
||||
var rawDomains = []string{}
|
||||
err := json.Unmarshal(params.DomainsJSON, &rawDomains)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
// TODO 如果用户填写了一个网址,应该分析域名并填入
|
||||
|
||||
domains = utils.NewStringsStream(rawDomains).
|
||||
Map(strings.TrimSpace, strings.ToLower).
|
||||
Filter(utils.FilterNotEmpty).
|
||||
Unique().
|
||||
Result()
|
||||
}
|
||||
|
||||
switch params.Type {
|
||||
case serverconfigs.HTTPAuthTypeTypeA:
|
||||
params.Must.
|
||||
Field("typeASecret", params.TypeASecret).
|
||||
Require("请输入鉴权密钥").
|
||||
MaxLength(40, "鉴权密钥不能超过40个字符").
|
||||
Match(`^[a-zA-Z0-9]{1,40}$`, "鉴权密钥中只能包含字母、数字").
|
||||
Field("typeASignParamName", params.TypeASignParamName).
|
||||
Require("请输入签名参数").
|
||||
Match(`^[a-zA-Z0-9_]{1,40}$`, "签名参数中只能包含字母、数字、下划线")
|
||||
|
||||
if params.TypeALife < 0 {
|
||||
params.TypeALife = 0
|
||||
}
|
||||
|
||||
method = &serverconfigs.HTTPAuthTypeAMethod{
|
||||
Secret: params.TypeASecret,
|
||||
SignParamName: params.TypeASignParamName,
|
||||
Life: params.TypeALife,
|
||||
}
|
||||
case serverconfigs.HTTPAuthTypeTypeB:
|
||||
params.Must.
|
||||
Field("typeBSecret", params.TypeBSecret).
|
||||
Require("请输入鉴权密钥").
|
||||
MaxLength(40, "鉴权密钥不能超过40个字符").
|
||||
Match(`^[a-zA-Z0-9]{1,40}$`, "鉴权密钥中只能包含字母、数字")
|
||||
|
||||
method = &serverconfigs.HTTPAuthTypeBMethod{
|
||||
Secret: params.TypeBSecret,
|
||||
Life: params.TypeBLife,
|
||||
}
|
||||
case serverconfigs.HTTPAuthTypeTypeC:
|
||||
params.Must.
|
||||
Field("typeCSecret", params.TypeCSecret).
|
||||
Require("请输入鉴权密钥").
|
||||
MaxLength(40, "鉴权密钥不能超过40个字符").
|
||||
Match(`^[a-zA-Z0-9]{1,40}$`, "鉴权密钥中只能包含字母、数字")
|
||||
|
||||
method = &serverconfigs.HTTPAuthTypeCMethod{
|
||||
Secret: params.TypeCSecret,
|
||||
Life: params.TypeCLife,
|
||||
}
|
||||
case serverconfigs.HTTPAuthTypeTypeD:
|
||||
params.Must.
|
||||
Field("typeDSecret", params.TypeDSecret).
|
||||
Require("请输入鉴权密钥").
|
||||
MaxLength(40, "鉴权密钥不能超过40个字符").
|
||||
Match(`^[a-zA-Z0-9]{1,40}$`, "鉴权密钥中只能包含字母、数字").
|
||||
Field("typeDSignParamName", params.TypeDSignParamName).
|
||||
Require("请输入签名参数").
|
||||
Match(`^[a-zA-Z0-9_]{1,40}$`, "签名参数中只能包含字母、数字、下划线").
|
||||
Field("typeDTimestampParamName", params.TypeDTimestampParamName).
|
||||
Require("请输入时间戳参数").
|
||||
Match(`^[a-zA-Z0-9_]{1,40}$`, "时间戳参数中只能包含字母、数字、下划线")
|
||||
|
||||
method = &serverconfigs.HTTPAuthTypeDMethod{
|
||||
Secret: params.TypeDSecret,
|
||||
SignParamName: params.TypeDSignParamName,
|
||||
TimestampParamName: params.TypeDTimestampParamName,
|
||||
Life: params.TypeDLife,
|
||||
}
|
||||
case serverconfigs.HTTPAuthTypeBasicAuth:
|
||||
var users = []*serverconfigs.HTTPAuthBasicMethodUser{}
|
||||
err := json.Unmarshal(params.HttpAuthBasicAuthUsersJSON, &users)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if len(users) == 0 {
|
||||
this.Fail("请添加至少一个用户")
|
||||
}
|
||||
method = &serverconfigs.HTTPAuthBasicMethod{
|
||||
Users: users,
|
||||
Realm: params.BasicAuthRealm,
|
||||
Charset: params.BasicAuthCharset,
|
||||
}
|
||||
case serverconfigs.HTTPAuthTypeSubRequest:
|
||||
params.Must.Field("subRequestURL", params.SubRequestURL).
|
||||
Require("请输入子请求URL")
|
||||
if params.SubRequestFollowRequest {
|
||||
params.SubRequestMethod = ""
|
||||
}
|
||||
method = &serverconfigs.HTTPAuthSubRequestMethod{
|
||||
URL: params.SubRequestURL,
|
||||
Method: params.SubRequestMethod,
|
||||
}
|
||||
default:
|
||||
this.Fail("不支持的鉴权类型'" + params.Type + "'")
|
||||
}
|
||||
|
||||
if method == nil {
|
||||
this.Fail("找不到对应的鉴权方式")
|
||||
}
|
||||
|
||||
method.SetExts(exts)
|
||||
method.SetDomains(domains)
|
||||
|
||||
methodJSON, err := json.Marshal(method)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
var paramsMap = maps.Map{}
|
||||
err = json.Unmarshal(methodJSON, ¶msMap)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
createResp, err := this.RPC().HTTPAuthPolicyRPC().CreateHTTPAuthPolicy(this.UserContext(), &pb.CreateHTTPAuthPolicyRequest{
|
||||
Name: params.Name,
|
||||
Type: params.Type,
|
||||
ParamsJSON: methodJSON,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
defer this.CreateLogInfo(codes.HTTPAuthPolicy_LogCreateHTTPAuthPolicy, createResp.HttpAuthPolicyId)
|
||||
ref.AuthPolicyId = createResp.HttpAuthPolicyId
|
||||
ref.AuthPolicy = &serverconfigs.HTTPAuthPolicy{
|
||||
Id: createResp.HttpAuthPolicyId,
|
||||
Name: params.Name,
|
||||
IsOn: true,
|
||||
Type: params.Type,
|
||||
Params: paramsMap,
|
||||
}
|
||||
|
||||
this.Data["policyRef"] = ref
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
package access
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/userconfigs"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
)
|
||||
|
||||
type IndexAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *IndexAction) Init() {
|
||||
this.Nav("", "setting", "index")
|
||||
this.SecondMenu("access")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct {
|
||||
ServerId int64
|
||||
}) {
|
||||
this.Data["featureIsOn"] = this.ValidateFeature(userconfigs.UserFeatureCodeServerAuth, params.ServerId)
|
||||
|
||||
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithServerId(this.UserContext(), params.ServerId)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Data["webId"] = webConfig.Id
|
||||
this.Data["authConfig"] = webConfig.Auth
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunPost(params struct {
|
||||
WebId int64
|
||||
AuthJSON []byte
|
||||
|
||||
Must *actions.Must
|
||||
}) {
|
||||
// 获取网站ID
|
||||
serverId, err := this.FindServerIdWithWebId(params.WebId)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
if !this.ValidateFeature(userconfigs.UserFeatureCodeServerAuth, serverId) {
|
||||
this.Fail("permission denied")
|
||||
return
|
||||
}
|
||||
|
||||
defer this.CreateLogInfo(codes.ServerAuth_LogUpdateHTTPAuthSettings, params.WebId)
|
||||
|
||||
var authConfig = &serverconfigs.HTTPAuthConfig{}
|
||||
err = json.Unmarshal(params.AuthJSON, authConfig)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
err = authConfig.Init()
|
||||
if err != nil {
|
||||
this.Fail("配置校验失败:" + err.Error())
|
||||
}
|
||||
|
||||
// 保存之前删除多于的配置信息
|
||||
for _, ref := range authConfig.PolicyRefs {
|
||||
ref.AuthPolicy = nil
|
||||
}
|
||||
|
||||
configJSON, err := json.Marshal(authConfig)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
_, err = this.RPC().HTTPWebRPC().UpdateHTTPWebAuth(this.UserContext(), &pb.UpdateHTTPWebAuthRequest{
|
||||
HttpWebId: params.WebId,
|
||||
AuthJSON: configJSON,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package access
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/default/servers/serverutils"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/helpers"
|
||||
"github.com/iwind/TeaGo"
|
||||
)
|
||||
|
||||
func init() {
|
||||
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
||||
server.
|
||||
Helper(helpers.NewUserMustAuth("")).
|
||||
Helper(serverutils.NewServerHelper()).
|
||||
Prefix("/servers/server/settings/access").
|
||||
GetPost("", new(IndexAction)).
|
||||
GetPost("/createPopup", new(CreatePopupAction)).
|
||||
GetPost("/updatePopup", new(UpdatePopupAction)).
|
||||
Post("/random", new(RandomAction)).
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package access
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"github.com/iwind/TeaGo/rands"
|
||||
)
|
||||
|
||||
type RandomAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *RandomAction) RunPost(params struct{}) {
|
||||
this.Data["random"] = rands.HexString(32)
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,282 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package access
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
teaconst "github.com/TeaOSLab/EdgeUser/internal/const"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/utils"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type UpdatePopupAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *UpdatePopupAction) Init() {
|
||||
this.Nav("", "", "")
|
||||
}
|
||||
|
||||
func (this *UpdatePopupAction) RunGet(params struct {
|
||||
PolicyId int64
|
||||
}) {
|
||||
var authMethods = serverconfigs.FindAllHTTPAuthTypes(teaconst.Role)
|
||||
|
||||
this.Data["authTypes"] = authMethods
|
||||
|
||||
policyResp, err := this.RPC().HTTPAuthPolicyRPC().FindEnabledHTTPAuthPolicy(this.UserContext(), &pb.FindEnabledHTTPAuthPolicyRequest{HttpAuthPolicyId: params.PolicyId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
policy := policyResp.HttpAuthPolicy
|
||||
if policy == nil {
|
||||
this.NotFound("httpAuthPolicy", params.PolicyId)
|
||||
return
|
||||
}
|
||||
|
||||
var authParams = map[string]interface{}{}
|
||||
if len(policy.ParamsJSON) > 0 {
|
||||
err = json.Unmarshal(policy.ParamsJSON, &authParams)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
this.Data["policy"] = maps.Map{
|
||||
"id": policy.Id,
|
||||
"isOn": policy.IsOn,
|
||||
"name": policy.Name,
|
||||
"type": policy.Type,
|
||||
"params": authParams,
|
||||
}
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *UpdatePopupAction) RunPost(params struct {
|
||||
PolicyId int64
|
||||
|
||||
Name string
|
||||
IsOn bool
|
||||
|
||||
// TypeA
|
||||
TypeASecret string
|
||||
TypeASignParamName string
|
||||
TypeALife int
|
||||
|
||||
// TypeB
|
||||
TypeBSecret string
|
||||
TypeBLife int
|
||||
|
||||
// TypeC
|
||||
TypeCSecret string
|
||||
TypeCLife int
|
||||
|
||||
// TypeD
|
||||
TypeDSecret string
|
||||
TypeDSignParamName string
|
||||
TypeDTimestampParamName string
|
||||
TypeDLife int
|
||||
|
||||
// BasicAuth
|
||||
HttpAuthBasicAuthUsersJSON []byte
|
||||
BasicAuthRealm string
|
||||
BasicAuthCharset string
|
||||
|
||||
// SubRequest
|
||||
SubRequestURL string
|
||||
SubRequestMethod string
|
||||
SubRequestFollowRequest bool
|
||||
|
||||
Exts []string
|
||||
DomainsJSON []byte
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.HTTPAuthPolicy_LogUpdateHTTPAuthPolicy, params.PolicyId)
|
||||
|
||||
policyResp, err := this.RPC().HTTPAuthPolicyRPC().FindEnabledHTTPAuthPolicy(this.UserContext(), &pb.FindEnabledHTTPAuthPolicyRequest{HttpAuthPolicyId: params.PolicyId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
policy := policyResp.HttpAuthPolicy
|
||||
if policy == nil {
|
||||
this.NotFound("httpAuthPolicy", params.PolicyId)
|
||||
return
|
||||
}
|
||||
policyType := policy.Type
|
||||
|
||||
params.Must.
|
||||
Field("name", params.Name).
|
||||
Require("请输入名称")
|
||||
|
||||
var ref = &serverconfigs.HTTPAuthPolicyRef{IsOn: true}
|
||||
var method serverconfigs.HTTPAuthMethodInterface
|
||||
|
||||
// 扩展名
|
||||
var exts = utils.NewStringsStream(params.Exts).
|
||||
Map(strings.TrimSpace, strings.ToLower).
|
||||
Filter(utils.FilterNotEmpty).
|
||||
Map(utils.MapAddPrefixFunc(".")).
|
||||
Unique().
|
||||
Result()
|
||||
|
||||
// 域名
|
||||
var domains = []string{}
|
||||
if len(params.DomainsJSON) > 0 {
|
||||
var rawDomains = []string{}
|
||||
err := json.Unmarshal(params.DomainsJSON, &rawDomains)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
// TODO 如果用户填写了一个网址,应该分析域名并填入
|
||||
|
||||
domains = utils.NewStringsStream(rawDomains).
|
||||
Map(strings.TrimSpace, strings.ToLower).
|
||||
Filter(utils.FilterNotEmpty).
|
||||
Unique().
|
||||
Result()
|
||||
}
|
||||
|
||||
switch policyType {
|
||||
case serverconfigs.HTTPAuthTypeTypeA:
|
||||
params.Must.
|
||||
Field("typeASecret", params.TypeASecret).
|
||||
Require("请输入鉴权密钥").
|
||||
MaxLength(40, "鉴权密钥不能超过40个字符").
|
||||
Match(`^[a-zA-Z0-9]{1,40}$`, "鉴权密钥中只能包含字母、数字").
|
||||
Field("typeASignParamName", params.TypeASignParamName).
|
||||
Require("请输入签名参数").
|
||||
Match(`^[a-zA-Z0-9_]{1,40}$`, "签名参数中只能包含字母、数字、下划线")
|
||||
|
||||
if params.TypeALife < 0 {
|
||||
params.TypeALife = 0
|
||||
}
|
||||
|
||||
method = &serverconfigs.HTTPAuthTypeAMethod{
|
||||
Secret: params.TypeASecret,
|
||||
SignParamName: params.TypeASignParamName,
|
||||
Life: params.TypeALife,
|
||||
}
|
||||
case serverconfigs.HTTPAuthTypeTypeB:
|
||||
params.Must.
|
||||
Field("typeBSecret", params.TypeBSecret).
|
||||
Require("请输入鉴权密钥").
|
||||
MaxLength(40, "鉴权密钥不能超过40个字符").
|
||||
Match(`^[a-zA-Z0-9]{1,40}$`, "鉴权密钥中只能包含字母、数字")
|
||||
|
||||
method = &serverconfigs.HTTPAuthTypeBMethod{
|
||||
Secret: params.TypeBSecret,
|
||||
Life: params.TypeBLife,
|
||||
}
|
||||
case serverconfigs.HTTPAuthTypeTypeC:
|
||||
params.Must.
|
||||
Field("typeCSecret", params.TypeCSecret).
|
||||
Require("请输入鉴权密钥").
|
||||
MaxLength(40, "鉴权密钥不能超过40个字符").
|
||||
Match(`^[a-zA-Z0-9]{1,40}$`, "鉴权密钥中只能包含字母、数字")
|
||||
|
||||
method = &serverconfigs.HTTPAuthTypeCMethod{
|
||||
Secret: params.TypeCSecret,
|
||||
Life: params.TypeCLife,
|
||||
}
|
||||
case serverconfigs.HTTPAuthTypeTypeD:
|
||||
params.Must.
|
||||
Field("typeDSecret", params.TypeDSecret).
|
||||
Require("请输入鉴权密钥").
|
||||
MaxLength(40, "鉴权密钥不能超过40个字符").
|
||||
Match(`^[a-zA-Z0-9]{1,40}$`, "鉴权密钥中只能包含字母、数字").
|
||||
Field("typeDSignParamName", params.TypeDSignParamName).
|
||||
Require("请输入签名参数").
|
||||
Match(`^[a-zA-Z0-9_]{1,40}$`, "签名参数中只能包含字母、数字、下划线").
|
||||
Field("typeDTimestampParamName", params.TypeDTimestampParamName).
|
||||
Require("请输入时间戳参数").
|
||||
Match(`^[a-zA-Z0-9_]{1,40}$`, "时间戳参数中只能包含字母、数字、下划线")
|
||||
|
||||
method = &serverconfigs.HTTPAuthTypeDMethod{
|
||||
Secret: params.TypeDSecret,
|
||||
SignParamName: params.TypeDSignParamName,
|
||||
TimestampParamName: params.TypeDTimestampParamName,
|
||||
Life: params.TypeDLife,
|
||||
}
|
||||
case serverconfigs.HTTPAuthTypeBasicAuth:
|
||||
users := []*serverconfigs.HTTPAuthBasicMethodUser{}
|
||||
err := json.Unmarshal(params.HttpAuthBasicAuthUsersJSON, &users)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if len(users) == 0 {
|
||||
this.Fail("请添加至少一个用户")
|
||||
}
|
||||
method = &serverconfigs.HTTPAuthBasicMethod{
|
||||
Users: users,
|
||||
Realm: params.BasicAuthRealm,
|
||||
Charset: params.BasicAuthCharset,
|
||||
}
|
||||
case serverconfigs.HTTPAuthTypeSubRequest:
|
||||
params.Must.Field("subRequestURL", params.SubRequestURL).
|
||||
Require("请输入子请求URL")
|
||||
if params.SubRequestFollowRequest {
|
||||
params.SubRequestMethod = ""
|
||||
}
|
||||
method = &serverconfigs.HTTPAuthSubRequestMethod{
|
||||
URL: params.SubRequestURL,
|
||||
Method: params.SubRequestMethod,
|
||||
}
|
||||
default:
|
||||
this.Fail("不支持的鉴权类型'" + policyType + "'")
|
||||
}
|
||||
|
||||
if method == nil {
|
||||
this.Fail("找不到鉴权方法")
|
||||
}
|
||||
|
||||
method.SetExts(exts)
|
||||
method.SetDomains(domains)
|
||||
|
||||
methodJSON, err := json.Marshal(method)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
var paramsMap map[string]interface{}
|
||||
err = json.Unmarshal(methodJSON, ¶msMap)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
_, err = this.RPC().HTTPAuthPolicyRPC().UpdateHTTPAuthPolicy(this.UserContext(), &pb.UpdateHTTPAuthPolicyRequest{
|
||||
HttpAuthPolicyId: params.PolicyId,
|
||||
Name: params.Name,
|
||||
ParamsJSON: methodJSON,
|
||||
IsOn: params.IsOn,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
ref.AuthPolicy = &serverconfigs.HTTPAuthPolicy{
|
||||
Id: params.PolicyId,
|
||||
Name: params.Name,
|
||||
IsOn: params.IsOn,
|
||||
Type: policyType,
|
||||
Params: paramsMap,
|
||||
}
|
||||
|
||||
this.Data["policyRef"] = ref
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
package accessLog
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/userconfigs"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
type IndexAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *IndexAction) Init() {
|
||||
this.Nav("", "setting", "index")
|
||||
this.SecondMenu("accessLog")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct {
|
||||
ServerId int64
|
||||
}) {
|
||||
this.Data["featureIsOn"] = this.ValidateFeature(userconfigs.UserFeatureCodeServerAccessLog, params.ServerId)
|
||||
|
||||
// 获取配置
|
||||
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithServerId(this.UserContext(), params.ServerId)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
this.Data["webId"] = webConfig.Id
|
||||
this.Data["accessLogConfig"] = webConfig.AccessLogRef
|
||||
|
||||
// 可选的缓存策略
|
||||
this.Data["accessLogPolicies"] = []maps.Map{}
|
||||
|
||||
// 通用变量
|
||||
this.Data["fields"] = serverconfigs.HTTPAccessLogShortFields
|
||||
this.Data["defaultFieldCodes"] = serverconfigs.HTTPAccessLogDefaultFieldsCodes
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunPost(params struct {
|
||||
WebId int64
|
||||
AccessLogJSON []byte
|
||||
|
||||
Must *actions.Must
|
||||
}) {
|
||||
// 获取网站ID
|
||||
serverId, err := this.FindServerIdWithWebId(params.WebId)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
if !this.ValidateFeature(userconfigs.UserFeatureCodeServerAccessLog, serverId) {
|
||||
this.Fail("permission denied")
|
||||
return
|
||||
}
|
||||
|
||||
// 日志
|
||||
defer this.CreateLogInfo(codes.ServerAccessLog_LogUpdateAccessLogSetting, params.WebId)
|
||||
|
||||
// TODO 检查参数
|
||||
|
||||
_, err = this.RPC().HTTPWebRPC().UpdateHTTPWebAccessLog(this.UserContext(), &pb.UpdateHTTPWebAccessLogRequest{
|
||||
HttpWebId: params.WebId,
|
||||
AccessLogJSON: params.AccessLogJSON,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package accessLog
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/default/servers/serverutils"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/helpers"
|
||||
"github.com/iwind/TeaGo"
|
||||
)
|
||||
|
||||
func init() {
|
||||
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
||||
server.
|
||||
Helper(helpers.NewUserMustAuth("")).
|
||||
Helper(serverutils.NewServerHelper()).
|
||||
Prefix("/servers/server/settings/accessLog").
|
||||
GetPost("", new(IndexAction)).
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
95
EdgeUser/internal/web/actions/default/servers/server/settings/cache/createPopup.go
vendored
Normal file
95
EdgeUser/internal/web/actions/default/servers/server/settings/cache/createPopup.go
vendored
Normal file
@@ -0,0 +1,95 @@
|
||||
package cache
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/utils"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type CreatePopupAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *CreatePopupAction) Init() {
|
||||
this.Nav("", "", "")
|
||||
}
|
||||
|
||||
func (this *CreatePopupAction) RunGet(params struct {
|
||||
IsReverse bool
|
||||
}) {
|
||||
this.Data["isReverse"] = params.IsReverse
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *CreatePopupAction) RunPost(params struct {
|
||||
CacheRefJSON []byte
|
||||
|
||||
CondType string
|
||||
CondJSON []byte
|
||||
CondIsCaseInsensitive bool
|
||||
|
||||
Must *actions.Must
|
||||
}) {
|
||||
var cacheRef = &serverconfigs.HTTPCacheRef{}
|
||||
err := json.Unmarshal(params.CacheRefJSON, cacheRef)
|
||||
if err != nil {
|
||||
this.Fail("解析条件出错:" + err.Error() + ", JSON: " + string(params.CacheRefJSON))
|
||||
return
|
||||
}
|
||||
|
||||
if len(params.CondJSON) > 0 {
|
||||
var cond = &shared.HTTPRequestCond{}
|
||||
err = json.Unmarshal(params.CondJSON, cond)
|
||||
if err != nil {
|
||||
this.Fail("解析条件出错:" + err.Error() + ", JSON: " + string(params.CondJSON))
|
||||
return
|
||||
}
|
||||
cond.Type = params.CondType
|
||||
cond.IsCaseInsensitive = params.CondIsCaseInsensitive
|
||||
cacheRef.SimpleCond = cond
|
||||
|
||||
// 将组合条件置为空
|
||||
cacheRef.Conds = &shared.HTTPRequestCondsConfig{}
|
||||
}
|
||||
|
||||
err = cacheRef.Init()
|
||||
if err != nil {
|
||||
this.Fail("解析条件出错:" + err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
if len(cacheRef.Key) == 0 {
|
||||
this.Fail("请输入缓存Key")
|
||||
}
|
||||
|
||||
if !strings.HasPrefix(cacheRef.Key, "${host}") &&
|
||||
!strings.HasPrefix(cacheRef.Key, "${scheme}://${host}") &&
|
||||
!strings.HasPrefix(cacheRef.Key, "//${host}") {
|
||||
this.Fail("缓存Key必须以${host}或${scheme}://${host}开头")
|
||||
}
|
||||
|
||||
if (cacheRef.Conds == nil || len(cacheRef.Conds.Groups) == 0) && cacheRef.SimpleCond == nil {
|
||||
this.Fail("请填写匹配条件分组")
|
||||
}
|
||||
|
||||
this.Data["cacheRef"] = cacheRef
|
||||
|
||||
cacheRefClone, err := utils.JSONClone(cacheRef)
|
||||
if err != nil {
|
||||
this.Fail(err.Error())
|
||||
}
|
||||
err = cacheRefClone.(*serverconfigs.HTTPCacheRef).Init()
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Data["cacheRef"] = cacheRef
|
||||
|
||||
this.Success()
|
||||
}
|
||||
152
EdgeUser/internal/web/actions/default/servers/server/settings/cache/index.go
vendored
Normal file
152
EdgeUser/internal/web/actions/default/servers/server/settings/cache/index.go
vendored
Normal file
@@ -0,0 +1,152 @@
|
||||
package cache
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/utils"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/utils/domainutils"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type IndexAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *IndexAction) Init() {
|
||||
this.Nav("", "setting", "index")
|
||||
this.SecondMenu("cache")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct {
|
||||
ServerId int64
|
||||
}) {
|
||||
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithServerId(this.UserContext(), params.ServerId)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Data["webId"] = webConfig.Id
|
||||
this.Data["cacheConfig"] = webConfig.Cache
|
||||
|
||||
// 当前集群的缓存策略
|
||||
cachePolicy, err := dao.SharedHTTPCachePolicyDAO.FindEnabledHTTPCachePolicyWithServerId(this.UserContext(), params.ServerId)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if cachePolicy != nil {
|
||||
var maxBytes = &shared.SizeCapacity{}
|
||||
if !utils.JSONIsNull(cachePolicy.MaxBytesJSON) {
|
||||
err = json.Unmarshal(cachePolicy.MaxBytesJSON, maxBytes)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
this.Data["cachePolicy"] = maps.Map{
|
||||
"id": cachePolicy.Id,
|
||||
"name": cachePolicy.Name,
|
||||
"isOn": cachePolicy.IsOn,
|
||||
"maxBytes": maxBytes,
|
||||
}
|
||||
} else {
|
||||
this.Data["cachePolicy"] = nil
|
||||
}
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunPost(params struct {
|
||||
WebId int64
|
||||
CacheJSON []byte
|
||||
|
||||
Must *actions.Must
|
||||
}) {
|
||||
// 日志
|
||||
defer this.CreateLogInfo(codes.ServerCache_LogUpdateCacheSettings, params.WebId)
|
||||
|
||||
var cacheConfig = &serverconfigs.HTTPCacheConfig{}
|
||||
err := json.Unmarshal(params.CacheJSON, cacheConfig)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
// 检查Key
|
||||
if cacheConfig.Key != nil && cacheConfig.Key.IsOn {
|
||||
if cacheConfig.Key.Scheme != "http" && cacheConfig.Key.Scheme != "https" {
|
||||
this.Fail("缓存主域名协议只能是http或者https")
|
||||
return
|
||||
}
|
||||
if len(cacheConfig.Key.Host) == 0 {
|
||||
this.Fail("请输入缓存主域名")
|
||||
return
|
||||
}
|
||||
cacheConfig.Key.Host = strings.ToLower(strings.TrimSuffix(cacheConfig.Key.Host, "/"))
|
||||
if !domainutils.ValidateDomainFormat(cacheConfig.Key.Host) {
|
||||
this.Fail("请输入正确的缓存主域名")
|
||||
return
|
||||
}
|
||||
|
||||
// 获取网站ID
|
||||
serverId, err := this.FindServerIdWithWebId(params.WebId)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if serverId <= 0 {
|
||||
this.Fail("找不到要操作的网站")
|
||||
return
|
||||
}
|
||||
|
||||
existServerNameResp, err := this.RPC().ServerRPC().CheckServerNameInServer(this.UserContext(), &pb.CheckServerNameInServerRequest{
|
||||
ServerId: serverId,
|
||||
ServerName: cacheConfig.Key.Host,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if !existServerNameResp.Exists {
|
||||
this.Fail("域名 '" + cacheConfig.Key.Host + "' 在当前网站中并未绑定,不能作为缓存主域名")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// 去除不必要的部分
|
||||
for _, cacheRef := range cacheConfig.CacheRefs {
|
||||
cacheRef.CachePolicy = nil
|
||||
}
|
||||
|
||||
err = cacheConfig.Init()
|
||||
if err != nil {
|
||||
this.Fail("配置校验失败:" + err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
cacheJSON, err := json.Marshal(cacheConfig)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
_, err = this.RPC().HTTPWebRPC().UpdateHTTPWebCache(this.UserContext(), &pb.UpdateHTTPWebCacheRequest{
|
||||
HttpWebId: params.WebId,
|
||||
CacheJSON: cacheJSON,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
20
EdgeUser/internal/web/actions/default/servers/server/settings/cache/init.go
vendored
Normal file
20
EdgeUser/internal/web/actions/default/servers/server/settings/cache/init.go
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
package cache
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/default/servers/serverutils"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/helpers"
|
||||
"github.com/iwind/TeaGo"
|
||||
)
|
||||
|
||||
func init() {
|
||||
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
||||
server.
|
||||
Helper(helpers.NewUserMustAuth("")).
|
||||
Helper(serverutils.NewServerHelper()).
|
||||
Prefix("/servers/server/settings/cache").
|
||||
GetPost("", new(IndexAction)).
|
||||
GetPost("/createPopup", new(CreatePopupAction)).
|
||||
Post("/updateRefs", new(UpdateRefsAction)).
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
84
EdgeUser/internal/web/actions/default/servers/server/settings/cache/updateRefs.go
vendored
Normal file
84
EdgeUser/internal/web/actions/default/servers/server/settings/cache/updateRefs.go
vendored
Normal file
@@ -0,0 +1,84 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package cache
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
)
|
||||
|
||||
type UpdateRefsAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *UpdateRefsAction) RunPost(params struct {
|
||||
WebId int64
|
||||
RefsJSON []byte
|
||||
}) {
|
||||
// 日志
|
||||
defer this.CreateLogInfo(codes.ServerCache_LogUpdateCacheSettings, params.WebId)
|
||||
|
||||
this.Data["isUpdated"] = false
|
||||
|
||||
webConfigResp, err := this.RPC().HTTPWebRPC().FindEnabledHTTPWebConfig(this.UserContext(), &pb.FindEnabledHTTPWebConfigRequest{HttpWebId: params.WebId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var webConfig = &serverconfigs.HTTPWebConfig{}
|
||||
err = json.Unmarshal(webConfigResp.HttpWebJSON, webConfig)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Data["webId"] = webConfig.Id
|
||||
this.Data["cacheConfig"] = webConfig.Cache
|
||||
|
||||
// 校验配置
|
||||
var cacheConfig = webConfig.Cache
|
||||
if cacheConfig == nil {
|
||||
this.Success()
|
||||
return
|
||||
}
|
||||
|
||||
var refs = []*serverconfigs.HTTPCacheRef{}
|
||||
err = json.Unmarshal(params.RefsJSON, &refs)
|
||||
if err != nil {
|
||||
this.ErrorPage(errors.New("decode refs json failed: " + err.Error()))
|
||||
return
|
||||
}
|
||||
cacheConfig.CacheRefs = refs
|
||||
|
||||
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.UserContext(), &pb.UpdateHTTPWebCacheRequest{
|
||||
HttpWebId: params.WebId,
|
||||
CacheJSON: cacheJSON,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Data["isUpdated"] = true
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
//go:build plus
|
||||
|
||||
package cc
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/userconfigs"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
)
|
||||
|
||||
type IndexAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *IndexAction) Init() {
|
||||
this.Nav("", "setting", "index")
|
||||
this.SecondMenu("cc")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct {
|
||||
ServerId int64
|
||||
}) {
|
||||
// 校验权限
|
||||
this.Data["featureIsOn"] = this.ValidateFeature(userconfigs.UserFeatureCodeServerCC, params.ServerId)
|
||||
|
||||
this.Data["serverId"] = params.ServerId
|
||||
|
||||
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithServerId(this.UserContext(), params.ServerId)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Data["webId"] = webConfig.Id
|
||||
|
||||
var ccConfig = serverconfigs.DefaultHTTPCCConfig()
|
||||
resp, err := this.RPC().HTTPWebRPC().FindHTTPWebCC(this.UserContext(), &pb.FindHTTPWebCCRequest{HttpWebId: webConfig.Id})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if len(resp.CcJSON) > 0 {
|
||||
err = json.Unmarshal(resp.CcJSON, ccConfig)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
this.Data["ccConfig"] = ccConfig
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunPost(params struct {
|
||||
WebId int64
|
||||
CcJSON []byte
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
// 获取网站ID
|
||||
serverId, err := this.FindServerIdWithWebId(params.WebId)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
if !this.ValidateFeature(userconfigs.UserFeatureCodeServerCC, serverId) {
|
||||
this.Fail("permission denied")
|
||||
return
|
||||
}
|
||||
|
||||
defer this.CreateLogInfo(codes.ServerCC_LogUpdateCCSettings, params.WebId)
|
||||
|
||||
// 校验配置
|
||||
var ccConfig = serverconfigs.DefaultHTTPCCConfig()
|
||||
err = json.Unmarshal(params.CcJSON, ccConfig)
|
||||
if err != nil {
|
||||
this.Fail("配置解析失败:" + err.Error())
|
||||
return
|
||||
}
|
||||
err = ccConfig.Init()
|
||||
if err != nil {
|
||||
this.Fail("配置校验失败:" + err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
_, err = this.RPC().HTTPWebRPC().UpdateHTTPWebCC(this.UserContext(), &pb.UpdateHTTPWebCCRequest{
|
||||
HttpWebId: params.WebId,
|
||||
CcJSON: params.CcJSON,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
//go:build plus
|
||||
|
||||
package cc
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/default/servers/serverutils"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/helpers"
|
||||
"github.com/iwind/TeaGo"
|
||||
)
|
||||
|
||||
func init() {
|
||||
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
||||
server.
|
||||
Helper(helpers.NewUserMustAuth("")).
|
||||
Helper(serverutils.NewServerHelper()).
|
||||
Prefix("/servers/server/settings/cc").
|
||||
GetPost("", new(IndexAction)).
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
//go:build !plus
|
||||
// +build !plus
|
||||
|
||||
package cc
|
||||
|
||||
// 此文件用于在非 Plus 版本中保持包的完整性
|
||||
// Plus 版本的功能在 init.go 中实现(需要 //go:build plus 标签)
|
||||
@@ -0,0 +1,57 @@
|
||||
package charset
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/configutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"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 {
|
||||
ServerId int64
|
||||
}) {
|
||||
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithServerId(this.UserContext(), params.ServerId)
|
||||
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.CreateLogInfo(codes.ServerCharset_LogUpdateCharsetSetting, params.WebId)
|
||||
|
||||
_, err := this.RPC().HTTPWebRPC().UpdateHTTPWebCharset(this.UserContext(), &pb.UpdateHTTPWebCharsetRequest{
|
||||
HttpWebId: params.WebId,
|
||||
CharsetJSON: params.CharsetJSON,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package charset
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/default/servers/serverutils"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/helpers"
|
||||
"github.com/iwind/TeaGo"
|
||||
)
|
||||
|
||||
func init() {
|
||||
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
||||
server.
|
||||
Helper(helpers.NewUserMustAuth("")).
|
||||
Helper(serverutils.NewServerHelper()).
|
||||
Prefix("/servers/server/settings/charset").
|
||||
GetPost("", new(IndexAction)).
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package compression
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/userconfigs"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
)
|
||||
|
||||
type IndexAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *IndexAction) Init() {
|
||||
this.Nav("", "setting", "index")
|
||||
this.SecondMenu("compression")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct {
|
||||
ServerId int64
|
||||
}) {
|
||||
this.Data["featureIsOn"] = this.ValidateFeature(userconfigs.UserFeatureCodeServerCompression, params.ServerId)
|
||||
|
||||
// 服务分组设置
|
||||
groupResp, err := this.RPC().ServerGroupRPC().FindEnabledServerGroupConfigInfo(this.UserContext(), &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.UserContext(), params.ServerId)
|
||||
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
|
||||
}) {
|
||||
// 获取网站ID
|
||||
serverId, err := this.FindServerIdWithWebId(params.WebId)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
if !this.ValidateFeature(userconfigs.UserFeatureCodeServerCompression, serverId) {
|
||||
this.Fail("permission denied")
|
||||
return
|
||||
}
|
||||
|
||||
defer this.CreateLogInfo(codes.ServerCompression_LogUpdateCompressionSettings, 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.UserContext(), &pb.UpdateHTTPWebCompressionRequest{
|
||||
HttpWebId: params.WebId,
|
||||
CompressionJSON: params.CompressionJSON,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package compression
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/default/servers/serverutils"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/helpers"
|
||||
"github.com/iwind/TeaGo"
|
||||
)
|
||||
|
||||
func init() {
|
||||
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
||||
server.
|
||||
Helper(helpers.NewUserMustAuth("")).
|
||||
Helper(serverutils.NewServerHelper()).
|
||||
Prefix("/servers/server/settings/compression").
|
||||
GetPost("", new(IndexAction)).
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package conds
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/default/servers/server/settings/conds/condutils"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
)
|
||||
|
||||
type AddCondPopupAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *AddCondPopupAction) Init() {
|
||||
}
|
||||
|
||||
func (this *AddCondPopupAction) RunGet(params struct{}) {
|
||||
this.Data["components"] = condutils.ReadAllAvailableCondTypes()
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *AddCondPopupAction) RunPost(params struct {
|
||||
CondType string
|
||||
CondJSON []byte
|
||||
|
||||
Must *actions.Must
|
||||
}) {
|
||||
condConfig := &shared.HTTPRequestCond{}
|
||||
err := json.Unmarshal(params.CondJSON, condConfig)
|
||||
if err != nil {
|
||||
this.Fail("解析条件设置时发生了错误:" + err.Error() + ", JSON: " + string(params.CondJSON))
|
||||
}
|
||||
err = condConfig.Init()
|
||||
if err != nil {
|
||||
this.Fail("校验条件设置时失败:" + err.Error())
|
||||
}
|
||||
condConfig.Type = params.CondType
|
||||
|
||||
this.Data["cond"] = condConfig
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package conds
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/default/servers/server/settings/conds/condutils"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
)
|
||||
|
||||
type AddGroupPopupAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *AddGroupPopupAction) Init() {
|
||||
}
|
||||
|
||||
func (this *AddGroupPopupAction) RunGet(params struct{}) {
|
||||
this.Data["components"] = condutils.ReadAllAvailableCondTypes()
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *AddGroupPopupAction) RunPost(params struct {
|
||||
CondGroupJSON []byte
|
||||
|
||||
Must *actions.Must
|
||||
}) {
|
||||
groupConfig := &shared.HTTPRequestCondGroup{}
|
||||
err := json.Unmarshal(params.CondGroupJSON, groupConfig)
|
||||
if err != nil {
|
||||
this.Fail("解析条件时发生错误:" + err.Error())
|
||||
}
|
||||
|
||||
err = groupConfig.Init()
|
||||
if err != nil {
|
||||
this.Fail("校验条件设置时失败:" + err.Error())
|
||||
}
|
||||
|
||||
this.Data["group"] = groupConfig
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package condutils
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
_ "github.com/iwind/TeaGo/bootstrap"
|
||||
"github.com/iwind/TeaGo/files"
|
||||
"github.com/iwind/TeaGo/logs"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
type CondJSComponent struct {
|
||||
Type string `json:"type"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
Component string `json:"component"`
|
||||
ParamsTitle string `json:"paramsTitle"`
|
||||
IsRequest bool `json:"isRequest"`
|
||||
CaseInsensitive bool `json:"caseInsensitive"`
|
||||
}
|
||||
|
||||
// ReadAllAvailableCondTypes 读取所有可用的条件
|
||||
func ReadAllAvailableCondTypes() []*CondJSComponent {
|
||||
result := []*CondJSComponent{}
|
||||
|
||||
dir := Tea.Root + "/web/"
|
||||
if Tea.IsTesting() {
|
||||
dir = filepath.Dir(Tea.Root) + "/web"
|
||||
}
|
||||
dir += "/public/js/conds/"
|
||||
jsonFiles := files.NewFile(dir).List()
|
||||
for _, file := range jsonFiles {
|
||||
if file.Ext() == ".json" {
|
||||
data, err := file.ReadAll()
|
||||
if err != nil {
|
||||
logs.Println("[COND]read data from json file: " + err.Error())
|
||||
continue
|
||||
}
|
||||
|
||||
c := []*CondJSComponent{}
|
||||
err = json.Unmarshal(data, &c)
|
||||
if err != nil {
|
||||
logs.Println("[COND]decode json failed: " + err.Error())
|
||||
continue
|
||||
}
|
||||
result = append(result, c...)
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package condutils
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestReadAllAvailableCondTypes(t *testing.T) {
|
||||
t.Log(ReadAllAvailableCondTypes())
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package conds
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/helpers"
|
||||
"github.com/iwind/TeaGo"
|
||||
)
|
||||
|
||||
func init() {
|
||||
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
||||
server.
|
||||
Helper(helpers.NewUserMustAuth("")).
|
||||
Prefix("/servers/server/settings/conds").
|
||||
GetPost("/addGroupPopup", new(AddGroupPopupAction)).
|
||||
GetPost("/addCondPopup", new(AddCondPopupAction)).
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
// Copyright 2023 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package copys
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/utils"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// CountServersAction 通过参数读取对应服务数量
|
||||
type CountServersAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *CountServersAction) RunPost(params struct {
|
||||
Targets []string
|
||||
}) {
|
||||
this.Data["countServers"] = -1
|
||||
|
||||
var countServers int64 = 0
|
||||
var hasValidTargets = false
|
||||
|
||||
for _, target := range params.Targets {
|
||||
targetType, targetValue, found := strings.Cut(target, ":")
|
||||
if !found {
|
||||
continue
|
||||
}
|
||||
|
||||
switch targetType {
|
||||
case "servers":
|
||||
var targetServerIds = utils.SplitNumbers(targetValue)
|
||||
if len(targetServerIds) == 0 {
|
||||
continue
|
||||
}
|
||||
countServers += int64(len(targetServerIds))
|
||||
hasValidTargets = true
|
||||
case "groups":
|
||||
var targetGroupIds = utils.SplitNumbers(targetValue)
|
||||
if len(targetGroupIds) == 0 {
|
||||
continue
|
||||
}
|
||||
for _, groupId := range targetGroupIds {
|
||||
countResp, err := this.RPC().ServerRPC().CountAllEnabledServersWithServerGroupId(this.UserContext(), &pb.CountAllEnabledServersWithServerGroupIdRequest{ServerGroupId: groupId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
countServers += countResp.Count
|
||||
}
|
||||
hasValidTargets = true
|
||||
case "user":
|
||||
var targetUserId = types.Int64(targetValue)
|
||||
if targetUserId <= 0 {
|
||||
continue
|
||||
}
|
||||
countResp, err := this.RPC().ServerRPC().CountAllEnabledServersMatch(this.UserContext(), &pb.CountAllEnabledServersMatchRequest{UserId: targetUserId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
countServers += countResp.Count
|
||||
hasValidTargets = true
|
||||
}
|
||||
|
||||
if !hasValidTargets {
|
||||
this.Data["countServers"] = -1
|
||||
} else {
|
||||
this.Data["countServers"] = countServers
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,188 @@
|
||||
// Copyright 2023 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package copys
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/utils"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type IndexAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *IndexAction) Init() {
|
||||
this.Nav("", "", "")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct {
|
||||
ServerId int64
|
||||
ConfigCode string
|
||||
}) {
|
||||
this.Data["serverId"] = params.ServerId
|
||||
this.Data["configCode"] = params.ConfigCode
|
||||
this.Data["userId"] = 0
|
||||
|
||||
var targetOptions = []maps.Map{}
|
||||
|
||||
// 当前分组
|
||||
serverResp, err := this.RPC().ServerRPC().FindEnabledUserServerBasic(this.UserContext(), &pb.FindEnabledUserServerBasicRequest{ServerId: params.ServerId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var server = serverResp.Server
|
||||
if server == nil {
|
||||
this.NotFound("server", params.ServerId)
|
||||
return
|
||||
}
|
||||
|
||||
if len(server.ServerGroups) > 0 {
|
||||
for _, group := range server.ServerGroups {
|
||||
if server.UserId <= 0 || server.UserId == group.UserId { // 确保分组是用户自己的
|
||||
targetOptions = append(targetOptions, maps.Map{
|
||||
"code": "group:" + types.String(group.Id),
|
||||
"name": "当前分组:" + group.Name,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 当前用户
|
||||
this.Data["userGroups"] = []maps.Map{}
|
||||
if server.UserId > 0 {
|
||||
this.Data["userId"] = server.UserId
|
||||
|
||||
userResp, err := this.RPC().UserRPC().FindEnabledUser(this.UserContext(), &pb.FindEnabledUserRequest{UserId: server.UserId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
var user = userResp.User
|
||||
if user != nil {
|
||||
targetOptions = append(targetOptions, maps.Map{
|
||||
"code": "user:" + types.String(user.Id),
|
||||
"name": "当前用户",
|
||||
})
|
||||
}
|
||||
|
||||
// 当前用户的分组
|
||||
groupsResp, err := this.RPC().ServerGroupRPC().FindAllEnabledServerGroups(this.UserContext(), &pb.FindAllEnabledServerGroupsRequest{
|
||||
UserId: server.UserId,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var userGroupMaps = []maps.Map{}
|
||||
for _, group := range groupsResp.ServerGroups {
|
||||
if !group.IsOn {
|
||||
continue
|
||||
}
|
||||
|
||||
userGroupMaps = append(userGroupMaps, maps.Map{
|
||||
"id": group.Id,
|
||||
"name": group.Name,
|
||||
})
|
||||
}
|
||||
this.Data["userGroups"] = userGroupMaps
|
||||
}
|
||||
|
||||
// 其他
|
||||
// TODO 支持选择服务
|
||||
targetOptions = append(targetOptions, maps.Map{
|
||||
"code": "group",
|
||||
"name": "选择分组",
|
||||
}, /**, maps.Map{
|
||||
"code": "server",
|
||||
"name": "选择服务",
|
||||
}**/)
|
||||
|
||||
this.Data["targetOptions"] = targetOptions
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunPost(params struct {
|
||||
ServerId int64
|
||||
ConfigCode string
|
||||
TargetsJSON []byte
|
||||
|
||||
// waf params
|
||||
WafCopyRegions bool
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.Server_LogCopyServerConfigs, params.ServerId, params.ConfigCode)
|
||||
|
||||
var targets = []string{}
|
||||
err := json.Unmarshal(params.TargetsJSON, &targets)
|
||||
if err != nil {
|
||||
this.Fail("解析复制目标失败:" + err.Error())
|
||||
return
|
||||
}
|
||||
if len(targets) == 0 {
|
||||
this.Fail("请选择要复制的目标")
|
||||
return
|
||||
}
|
||||
|
||||
for _, target := range targets {
|
||||
targetType, targetValue, found := strings.Cut(target, ":")
|
||||
if !found {
|
||||
this.Fail("错误的目标格式:" + target)
|
||||
return
|
||||
}
|
||||
|
||||
var targetServerIds = []int64{}
|
||||
var targetGroupIds = []int64{}
|
||||
var targetClusterId int64
|
||||
var targetUserId int64
|
||||
|
||||
switch targetType {
|
||||
case "servers":
|
||||
targetServerIds = utils.SplitNumbers(targetValue)
|
||||
if len(targetServerIds) == 0 {
|
||||
continue
|
||||
}
|
||||
case "groups":
|
||||
targetGroupIds = utils.SplitNumbers(targetValue)
|
||||
if len(targetGroupIds) == 0 {
|
||||
continue
|
||||
}
|
||||
case "user":
|
||||
targetUserId = types.Int64(targetValue)
|
||||
if targetUserId <= 0 {
|
||||
continue
|
||||
}
|
||||
default:
|
||||
this.Fail("错误的目标格式:" + target)
|
||||
return
|
||||
}
|
||||
|
||||
_, err := this.RPC().ServerRPC().CopyServerConfig(this.UserContext(), &pb.CopyServerConfigRequest{
|
||||
ServerId: params.ServerId,
|
||||
ConfigCode: params.ConfigCode,
|
||||
TargetType: targetType,
|
||||
TargetServerIds: targetServerIds,
|
||||
TargetServerGroupIds: targetGroupIds,
|
||||
TargetClusterId: targetClusterId,
|
||||
TargetUserId: targetUserId,
|
||||
WafCopyRegions: params.WafCopyRegions,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package copys
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/default/servers/serverutils"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/helpers"
|
||||
"github.com/iwind/TeaGo"
|
||||
)
|
||||
|
||||
func init() {
|
||||
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
||||
server.
|
||||
Helper(helpers.NewUserMustAuth("")).
|
||||
Helper(serverutils.NewServerHelper()).
|
||||
Prefix("/servers/server/settings/copy").
|
||||
GetPost("", new(IndexAction)).
|
||||
Post("/countServers", new(CountServersAction)).
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package dns
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
)
|
||||
|
||||
type IndexAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *IndexAction) Init() {
|
||||
this.Nav("", "setting", "index")
|
||||
this.SecondMenu("dns")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct {
|
||||
ServerId int64
|
||||
}) {
|
||||
dnsInfoResp, err := this.RPC().ServerRPC().FindEnabledServerDNS(this.UserContext(), &pb.FindEnabledServerDNSRequest{ServerId: params.ServerId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
this.Data["dnsName"] = dnsInfoResp.DnsName
|
||||
if dnsInfoResp.Domain != nil {
|
||||
this.Data["dnsDomain"] = dnsInfoResp.Domain.Name
|
||||
} else {
|
||||
this.Data["dnsDomain"] = ""
|
||||
}
|
||||
|
||||
this.Show()
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package dns
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/default/servers/serverutils"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/helpers"
|
||||
"github.com/iwind/TeaGo"
|
||||
)
|
||||
|
||||
func init() {
|
||||
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
||||
server.
|
||||
Helper(helpers.NewUserMustAuth("")).
|
||||
Helper(serverutils.NewServerHelper()).
|
||||
Prefix("/servers/server/settings/dns").
|
||||
GetPost("", new(IndexAction)).
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package groups
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
type IndexAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *IndexAction) Init() {
|
||||
this.Nav("", "setting", "index")
|
||||
this.SecondMenu("group")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct {
|
||||
ServerId int64
|
||||
}) {
|
||||
this.Data["serverId"] = params.ServerId
|
||||
|
||||
serverResp, err := this.RPC().ServerRPC().FindEnabledServer(this.UserContext(), &pb.FindEnabledServerRequest{
|
||||
ServerId: params.ServerId,
|
||||
IgnoreSSLCerts: true,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var server = serverResp.Server
|
||||
if server == nil {
|
||||
this.NotFound("server", params.ServerId)
|
||||
return
|
||||
}
|
||||
|
||||
var groupMaps = []maps.Map{}
|
||||
for _, group := range server.ServerGroups {
|
||||
if group.UserId != this.UserId() {
|
||||
continue
|
||||
}
|
||||
groupMaps = append(groupMaps, maps.Map{
|
||||
"id": group.Id,
|
||||
"name": group.Name,
|
||||
})
|
||||
}
|
||||
this.Data["groups"] = groupMaps
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunPost(params struct {
|
||||
ServerId int64
|
||||
GroupIds []int64
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.Server_LogUpdateServerGroups, params.ServerId)
|
||||
|
||||
_, err := this.RPC().ServerRPC().UpdateServerGroupIds(this.UserContext(), &pb.UpdateServerGroupIdsRequest{
|
||||
ServerId: params.ServerId,
|
||||
ServerGroupIds: params.GroupIds,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package groups
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/default/servers/serverutils"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/helpers"
|
||||
"github.com/iwind/TeaGo"
|
||||
)
|
||||
|
||||
func init() {
|
||||
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
||||
server.
|
||||
Helper(helpers.NewUserMustAuth("")).
|
||||
Helper(serverutils.NewServerHelper()).
|
||||
Prefix("/servers/server/settings/groups").
|
||||
GetPost("", new(IndexAction)).
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package headers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
)
|
||||
|
||||
type CreateDeletePopupAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *CreateDeletePopupAction) Init() {
|
||||
this.Nav("", "", "")
|
||||
}
|
||||
|
||||
func (this *CreateDeletePopupAction) RunGet(params struct {
|
||||
HeaderPolicyId int64
|
||||
Type string
|
||||
}) {
|
||||
this.Data["headerPolicyId"] = params.HeaderPolicyId
|
||||
this.Data["type"] = params.Type
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *CreateDeletePopupAction) RunPost(params struct {
|
||||
HeaderPolicyId int64
|
||||
Name string
|
||||
|
||||
Must *actions.Must
|
||||
}) {
|
||||
// 日志
|
||||
defer this.CreateLogInfo(codes.ServerHTTPHeader_LogCreateDeletingHeader, params.HeaderPolicyId, params.Name)
|
||||
|
||||
params.Must.
|
||||
Field("name", params.Name).
|
||||
Require("名称不能为空")
|
||||
|
||||
policyConfigResp, err := this.RPC().HTTPHeaderPolicyRPC().FindEnabledHTTPHeaderPolicyConfig(this.UserContext(), &pb.FindEnabledHTTPHeaderPolicyConfigRequest{HttpHeaderPolicyId: params.HeaderPolicyId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var policyConfig = &shared.HTTPHeaderPolicy{}
|
||||
err = json.Unmarshal(policyConfigResp.HttpHeaderPolicyJSON, policyConfig)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
var deleteHeaders = policyConfig.DeleteHeaders
|
||||
deleteHeaders = append(deleteHeaders, params.Name)
|
||||
_, err = this.RPC().HTTPHeaderPolicyRPC().UpdateHTTPHeaderPolicyDeletingHeaders(this.UserContext(), &pb.UpdateHTTPHeaderPolicyDeletingHeadersRequest{
|
||||
HttpHeaderPolicyId: params.HeaderPolicyId,
|
||||
HeaderNames: deleteHeaders,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package headers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
)
|
||||
|
||||
type CreateNonStandardPopupAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *CreateNonStandardPopupAction) Init() {
|
||||
this.Nav("", "", "")
|
||||
}
|
||||
|
||||
func (this *CreateNonStandardPopupAction) RunGet(params struct {
|
||||
HeaderPolicyId int64
|
||||
Type string
|
||||
}) {
|
||||
this.Data["headerPolicyId"] = params.HeaderPolicyId
|
||||
this.Data["type"] = params.Type
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *CreateNonStandardPopupAction) RunPost(params struct {
|
||||
HeaderPolicyId int64
|
||||
Name string
|
||||
|
||||
Must *actions.Must
|
||||
}) {
|
||||
// 日志
|
||||
defer this.CreateLogInfo(codes.ServerHTTPHeader_LogCreateNonStandardHeader, params.HeaderPolicyId, params.Name)
|
||||
|
||||
params.Must.
|
||||
Field("name", params.Name).
|
||||
Require("名称不能为空")
|
||||
|
||||
policyConfigResp, err := this.RPC().HTTPHeaderPolicyRPC().FindEnabledHTTPHeaderPolicyConfig(this.UserContext(), &pb.FindEnabledHTTPHeaderPolicyConfigRequest{HttpHeaderPolicyId: params.HeaderPolicyId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var policyConfig = &shared.HTTPHeaderPolicy{}
|
||||
err = json.Unmarshal(policyConfigResp.HttpHeaderPolicyJSON, policyConfig)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
var nonStandardHeaders = policyConfig.NonStandardHeaders
|
||||
nonStandardHeaders = append(nonStandardHeaders, params.Name)
|
||||
_, err = this.RPC().HTTPHeaderPolicyRPC().UpdateHTTPHeaderPolicyNonStandardHeaders(this.UserContext(), &pb.UpdateHTTPHeaderPolicyNonStandardHeadersRequest{
|
||||
HttpHeaderPolicyId: params.HeaderPolicyId,
|
||||
HeaderNames: nonStandardHeaders,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,149 @@
|
||||
package headers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
)
|
||||
|
||||
type CreateSetPopupAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *CreateSetPopupAction) Init() {
|
||||
this.Nav("", "", "")
|
||||
}
|
||||
|
||||
func (this *CreateSetPopupAction) RunGet(params struct {
|
||||
HeaderPolicyId int64
|
||||
Type string
|
||||
}) {
|
||||
this.Data["headerPolicyId"] = params.HeaderPolicyId
|
||||
this.Data["type"] = params.Type
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *CreateSetPopupAction) RunPost(params struct {
|
||||
Type string
|
||||
HeaderPolicyId int64
|
||||
Name string
|
||||
Value string
|
||||
|
||||
StatusListJSON []byte
|
||||
MethodsJSON []byte
|
||||
DomainsJSON []byte
|
||||
ShouldAppend bool
|
||||
DisableRedirect bool
|
||||
ShouldReplace bool
|
||||
ReplaceValuesJSON []byte
|
||||
|
||||
Must *actions.Must
|
||||
}) {
|
||||
// 日志
|
||||
if params.Type == "request" {
|
||||
defer this.CreateLogInfo(codes.ServerHTTPHeader_LogCreateSettingRequestHeader, params.HeaderPolicyId, params.Name, params.Value)
|
||||
} else {
|
||||
defer this.CreateLogInfo(codes.ServerHTTPHeader_LogCreateSettingResponseHeader, params.HeaderPolicyId, params.Name, params.Value)
|
||||
}
|
||||
|
||||
params.Must.
|
||||
Field("name", params.Name).
|
||||
Require("请输入Header名称")
|
||||
|
||||
configResp, err := this.RPC().HTTPHeaderPolicyRPC().FindEnabledHTTPHeaderPolicyConfig(this.UserContext(), &pb.FindEnabledHTTPHeaderPolicyConfigRequest{HttpHeaderPolicyId: params.HeaderPolicyId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
policyConfig := &shared.HTTPHeaderPolicy{}
|
||||
err = json.Unmarshal(configResp.HttpHeaderPolicyJSON, policyConfig)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
// status list
|
||||
var statusList = []int32{}
|
||||
if len(params.StatusListJSON) > 0 {
|
||||
err = json.Unmarshal(params.StatusListJSON, &statusList)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// methods
|
||||
var methods = []string{}
|
||||
if len(params.MethodsJSON) > 0 {
|
||||
err = json.Unmarshal(params.MethodsJSON, &methods)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// domains
|
||||
var domains = []string{}
|
||||
if len(params.DomainsJSON) > 0 {
|
||||
err = json.Unmarshal(params.DomainsJSON, &domains)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// replace values
|
||||
var replaceValues = []*shared.HTTPHeaderReplaceValue{}
|
||||
if len(params.ReplaceValuesJSON) > 0 {
|
||||
err = json.Unmarshal(params.ReplaceValuesJSON, &replaceValues)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// 创建Header
|
||||
createHeaderResp, err := this.RPC().HTTPHeaderRPC().CreateHTTPHeader(this.UserContext(), &pb.CreateHTTPHeaderRequest{
|
||||
Name: params.Name,
|
||||
Value: params.Value,
|
||||
Status: statusList,
|
||||
Methods: methods,
|
||||
Domains: domains,
|
||||
ShouldAppend: params.ShouldAppend,
|
||||
DisableRedirect: params.DisableRedirect,
|
||||
ShouldReplace: params.ShouldReplace,
|
||||
ReplaceValuesJSON: params.ReplaceValuesJSON,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
headerId := createHeaderResp.HeaderId
|
||||
|
||||
// 保存
|
||||
refs := policyConfig.SetHeaderRefs
|
||||
refs = append(refs, &shared.HTTPHeaderRef{
|
||||
IsOn: true,
|
||||
HeaderId: headerId,
|
||||
})
|
||||
refsJSON, err := json.Marshal(refs)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
_, err = this.RPC().HTTPHeaderPolicyRPC().UpdateHTTPHeaderPolicySettingHeaders(this.UserContext(), &pb.UpdateHTTPHeaderPolicySettingHeadersRequest{
|
||||
HttpHeaderPolicyId: params.HeaderPolicyId,
|
||||
HeadersJSON: refsJSON,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package headers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
)
|
||||
|
||||
// DeleteAction 删除Header
|
||||
type DeleteAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *DeleteAction) RunPost(params struct {
|
||||
HeaderPolicyId int64
|
||||
Type string
|
||||
HeaderId int64
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.ServerHTTPHeader_LogDeleteHeader, params.HeaderPolicyId, params.HeaderId)
|
||||
|
||||
policyConfigResp, err := this.RPC().HTTPHeaderPolicyRPC().FindEnabledHTTPHeaderPolicyConfig(this.UserContext(), &pb.FindEnabledHTTPHeaderPolicyConfigRequest{
|
||||
HttpHeaderPolicyId: params.HeaderPolicyId,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
policyConfig := &shared.HTTPHeaderPolicy{}
|
||||
err = json.Unmarshal(policyConfigResp.HttpHeaderPolicyJSON, policyConfig)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
switch params.Type {
|
||||
case "setHeader":
|
||||
result := []*shared.HTTPHeaderRef{}
|
||||
for _, h := range policyConfig.SetHeaderRefs {
|
||||
if h.HeaderId != params.HeaderId {
|
||||
result = append(result, h)
|
||||
}
|
||||
}
|
||||
resultJSON, err := json.Marshal(result)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
_, err = this.RPC().HTTPHeaderPolicyRPC().UpdateHTTPHeaderPolicySettingHeaders(this.UserContext(), &pb.UpdateHTTPHeaderPolicySettingHeadersRequest{
|
||||
HttpHeaderPolicyId: params.HeaderPolicyId,
|
||||
HeadersJSON: resultJSON,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package headers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
)
|
||||
|
||||
type DeleteDeletingHeaderAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *DeleteDeletingHeaderAction) RunPost(params struct {
|
||||
HeaderPolicyId int64
|
||||
HeaderName string
|
||||
}) {
|
||||
// 日志
|
||||
defer this.CreateLogInfo(codes.ServerHTTPHeader_LogDeleteDeletingHeader, params.HeaderPolicyId, params.HeaderName)
|
||||
|
||||
policyConfigResp, err := this.RPC().HTTPHeaderPolicyRPC().FindEnabledHTTPHeaderPolicyConfig(this.UserContext(), &pb.FindEnabledHTTPHeaderPolicyConfigRequest{HttpHeaderPolicyId: params.HeaderPolicyId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var policyConfigJSON = policyConfigResp.HttpHeaderPolicyJSON
|
||||
var policyConfig = &shared.HTTPHeaderPolicy{}
|
||||
err = json.Unmarshal(policyConfigJSON, policyConfig)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
var headerNames = []string{}
|
||||
for _, h := range policyConfig.DeleteHeaders {
|
||||
if h == params.HeaderName {
|
||||
continue
|
||||
}
|
||||
headerNames = append(headerNames, h)
|
||||
}
|
||||
_, err = this.RPC().HTTPHeaderPolicyRPC().UpdateHTTPHeaderPolicyDeletingHeaders(this.UserContext(), &pb.UpdateHTTPHeaderPolicyDeletingHeadersRequest{
|
||||
HttpHeaderPolicyId: params.HeaderPolicyId,
|
||||
HeaderNames: headerNames,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package headers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
)
|
||||
|
||||
type DeleteNonStandardHeaderAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *DeleteNonStandardHeaderAction) RunPost(params struct {
|
||||
HeaderPolicyId int64
|
||||
HeaderName string
|
||||
}) {
|
||||
// 日志
|
||||
defer this.CreateLogInfo(codes.ServerHTTPHeader_LogDeleteNonStandardHeader, params.HeaderPolicyId, params.HeaderName)
|
||||
|
||||
policyConfigResp, err := this.RPC().HTTPHeaderPolicyRPC().FindEnabledHTTPHeaderPolicyConfig(this.UserContext(), &pb.FindEnabledHTTPHeaderPolicyConfigRequest{HttpHeaderPolicyId: params.HeaderPolicyId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var policyConfigJSON = policyConfigResp.HttpHeaderPolicyJSON
|
||||
var policyConfig = &shared.HTTPHeaderPolicy{}
|
||||
err = json.Unmarshal(policyConfigJSON, policyConfig)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
var headerNames = []string{}
|
||||
for _, h := range policyConfig.NonStandardHeaders {
|
||||
if h == params.HeaderName {
|
||||
continue
|
||||
}
|
||||
headerNames = append(headerNames, h)
|
||||
}
|
||||
_, err = this.RPC().HTTPHeaderPolicyRPC().UpdateHTTPHeaderPolicyNonStandardHeaders(this.UserContext(), &pb.UpdateHTTPHeaderPolicyNonStandardHeadersRequest{
|
||||
HttpHeaderPolicyId: params.HeaderPolicyId,
|
||||
HeaderNames: headerNames,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
package headers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/userconfigs"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
)
|
||||
|
||||
type IndexAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *IndexAction) Init() {
|
||||
this.Nav("", "setting", "index")
|
||||
this.SecondMenu("header")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct {
|
||||
ServerId int64
|
||||
}) {
|
||||
this.Data["featureIsOn"] = this.ValidateFeature(userconfigs.UserFeatureCodeServerHTTPHeaders, params.ServerId)
|
||||
|
||||
// 服务分组设置
|
||||
groupResp, err := this.RPC().ServerGroupRPC().FindEnabledServerGroupConfigInfo(this.UserContext(), &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.UserContext(), params.ServerId)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
webId := webConfig.Id
|
||||
|
||||
isChanged := false
|
||||
if webConfig.RequestHeaderPolicy == nil {
|
||||
createHeaderPolicyResp, err := this.RPC().HTTPHeaderPolicyRPC().CreateHTTPHeaderPolicy(this.UserContext(), &pb.CreateHTTPHeaderPolicyRequest{})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
headerPolicyId := createHeaderPolicyResp.HttpHeaderPolicyId
|
||||
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.UserContext(), &pb.UpdateHTTPWebRequestHeaderRequest{
|
||||
HttpWebId: webId,
|
||||
HeaderJSON: refJSON,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
isChanged = true
|
||||
}
|
||||
if webConfig.ResponseHeaderPolicy == nil {
|
||||
createHeaderPolicyResp, err := this.RPC().HTTPHeaderPolicyRPC().CreateHTTPHeaderPolicy(this.UserContext(), &pb.CreateHTTPHeaderPolicyRequest{})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
headerPolicyId := createHeaderPolicyResp.HttpHeaderPolicyId
|
||||
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.UserContext(), &pb.UpdateHTTPWebResponseHeaderRequest{
|
||||
HttpWebId: webId,
|
||||
HeaderJSON: refJSON,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
isChanged = true
|
||||
}
|
||||
|
||||
// 重新获取配置
|
||||
if isChanged {
|
||||
webConfig, err = dao.SharedHTTPWebDAO.FindWebConfigWithServerId(this.UserContext(), params.ServerId)
|
||||
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()
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package headers
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/default/servers/serverutils"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/helpers"
|
||||
"github.com/iwind/TeaGo"
|
||||
)
|
||||
|
||||
func init() {
|
||||
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
||||
server.
|
||||
Helper(helpers.NewUserMustAuth("")).
|
||||
Helper(serverutils.NewServerHelper()).
|
||||
Prefix("/servers/server/settings/headers").
|
||||
Get("", new(IndexAction)).
|
||||
GetPost("/createSetPopup", new(CreateSetPopupAction)).
|
||||
GetPost("/updateSetPopup", new(UpdateSetPopupAction)).
|
||||
GetPost("/createDeletePopup", new(CreateDeletePopupAction)).
|
||||
Post("/deleteDeletingHeader", new(DeleteDeletingHeaderAction)).
|
||||
GetPost("/createNonStandardPopup", new(CreateNonStandardPopupAction)).
|
||||
Post("/deleteNonStandardHeader", new(DeleteNonStandardHeaderAction)).
|
||||
Post("/delete", new(DeleteAction)).
|
||||
GetPost("/updateCORSPopup", new(UpdateCORSPopupAction)).
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package headers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
)
|
||||
|
||||
type UpdateCORSPopupAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *UpdateCORSPopupAction) Init() {
|
||||
this.Nav("", "", "")
|
||||
}
|
||||
|
||||
func (this *UpdateCORSPopupAction) RunGet(params struct {
|
||||
HeaderPolicyId int64
|
||||
}) {
|
||||
this.Data["headerPolicyId"] = params.HeaderPolicyId
|
||||
|
||||
resp, err := this.RPC().HTTPHeaderPolicyRPC().FindEnabledHTTPHeaderPolicyConfig(this.UserContext(), &pb.FindEnabledHTTPHeaderPolicyConfigRequest{HttpHeaderPolicyId: params.HeaderPolicyId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var headerPolicyJSON = resp.HttpHeaderPolicyJSON
|
||||
var headerPolicy = &shared.HTTPHeaderPolicy{}
|
||||
if len(headerPolicyJSON) > 0 {
|
||||
err = json.Unmarshal(headerPolicyJSON, headerPolicy)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
this.Data["cors"] = headerPolicy.CORS
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *UpdateCORSPopupAction) RunPost(params struct {
|
||||
HeaderPolicyId int64
|
||||
CorsJSON []byte
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
var config = shared.NewHTTPCORSHeaderConfig()
|
||||
err := json.Unmarshal(params.CorsJSON, config)
|
||||
if err != nil {
|
||||
this.Fail("配置校验失败:" + err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
err = config.Init()
|
||||
if err != nil {
|
||||
this.Fail("配置校验失败:" + err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
_, err = this.RPC().HTTPHeaderPolicyRPC().UpdateHTTPHeaderPolicyCORS(this.UserContext(), &pb.UpdateHTTPHeaderPolicyCORSRequest{
|
||||
HttpHeaderPolicyId: params.HeaderPolicyId,
|
||||
CorsJSON: params.CorsJSON,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
package headers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
)
|
||||
|
||||
type UpdateSetPopupAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *UpdateSetPopupAction) Init() {
|
||||
this.Nav("", "", "")
|
||||
}
|
||||
|
||||
func (this *UpdateSetPopupAction) RunGet(params struct {
|
||||
HeaderPolicyId int64
|
||||
HeaderId int64
|
||||
Type string
|
||||
}) {
|
||||
this.Data["headerPolicyId"] = params.HeaderPolicyId
|
||||
this.Data["headerId"] = params.HeaderId
|
||||
this.Data["type"] = params.Type
|
||||
|
||||
headerResp, err := this.RPC().HTTPHeaderRPC().FindEnabledHTTPHeaderConfig(this.UserContext(), &pb.FindEnabledHTTPHeaderConfigRequest{HeaderId: params.HeaderId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
headerConfig := &shared.HTTPHeaderConfig{}
|
||||
err = json.Unmarshal(headerResp.HeaderJSON, headerConfig)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
this.Data["headerConfig"] = headerConfig
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *UpdateSetPopupAction) RunPost(params struct {
|
||||
HeaderId int64
|
||||
Name string
|
||||
Value string
|
||||
|
||||
StatusListJSON []byte
|
||||
MethodsJSON []byte
|
||||
DomainsJSON []byte
|
||||
ShouldAppend bool
|
||||
DisableRedirect bool
|
||||
ShouldReplace bool
|
||||
ReplaceValuesJSON []byte
|
||||
|
||||
Must *actions.Must
|
||||
}) {
|
||||
// 日志
|
||||
defer this.CreateLogInfo(codes.ServerHTTPHeader_LogUpdateSettingHeader, params.HeaderId, params.Name, params.Value)
|
||||
|
||||
params.Must.
|
||||
Field("name", params.Name).
|
||||
Require("请输入Header名称")
|
||||
|
||||
// status list
|
||||
var statusList = []int32{}
|
||||
if len(params.StatusListJSON) > 0 {
|
||||
err := json.Unmarshal(params.StatusListJSON, &statusList)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// methods
|
||||
var methods = []string{}
|
||||
if len(params.MethodsJSON) > 0 {
|
||||
err := json.Unmarshal(params.MethodsJSON, &methods)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// domains
|
||||
var domains = []string{}
|
||||
if len(params.DomainsJSON) > 0 {
|
||||
err := json.Unmarshal(params.DomainsJSON, &domains)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// replace values
|
||||
var replaceValues = []*shared.HTTPHeaderReplaceValue{}
|
||||
if len(params.ReplaceValuesJSON) > 0 {
|
||||
err := json.Unmarshal(params.ReplaceValuesJSON, &replaceValues)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
_, err := this.RPC().HTTPHeaderRPC().UpdateHTTPHeader(this.UserContext(), &pb.UpdateHTTPHeaderRequest{
|
||||
HeaderId: params.HeaderId,
|
||||
Name: params.Name,
|
||||
Value: params.Value,
|
||||
Status: statusList,
|
||||
Methods: methods,
|
||||
Domains: domains,
|
||||
ShouldAppend: params.ShouldAppend,
|
||||
DisableRedirect: params.DisableRedirect,
|
||||
ShouldReplace: params.ShouldReplace,
|
||||
ReplaceValuesJSON: params.ReplaceValuesJSON,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
package http
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
type IndexAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *IndexAction) Init() {
|
||||
this.Nav("", "setting", "index")
|
||||
this.SecondMenu("http")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct {
|
||||
ServerId int64
|
||||
}) {
|
||||
serverConfig, err := dao.SharedServerDAO.FindEnabledServerConfig(this.UserContext(), params.ServerId)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if serverConfig == nil {
|
||||
this.NotFound("server", params.ServerId)
|
||||
return
|
||||
}
|
||||
|
||||
httpConfig := serverConfig.HTTP
|
||||
if httpConfig == nil {
|
||||
httpConfig = &serverconfigs.HTTPProtocolConfig{}
|
||||
httpConfig.IsOn = true
|
||||
}
|
||||
|
||||
this.Data["serverType"] = serverConfig.Type
|
||||
this.Data["httpConfig"] = maps.Map{
|
||||
"isOn": httpConfig.IsOn,
|
||||
"addresses": httpConfig.Listen,
|
||||
}
|
||||
|
||||
// 跳转相关设置
|
||||
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithServerId(this.UserContext(), params.ServerId)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
this.Data["webId"] = webConfig.Id
|
||||
this.Data["redirectToHTTPSConfig"] = webConfig.RedirectToHttps
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunPost(params struct {
|
||||
ServerId int64
|
||||
IsOn bool
|
||||
Addresses string
|
||||
|
||||
WebId int64
|
||||
RedirectToHTTPSJSON []byte
|
||||
|
||||
Must *actions.Must
|
||||
}) {
|
||||
// 记录日志
|
||||
defer this.CreateLogInfo(codes.ServerHTTP_LogUpdateHTTPSettings, params.ServerId)
|
||||
|
||||
serverConfig, err := dao.SharedServerDAO.FindEnabledServerConfig(this.UserContext(), params.ServerId)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if serverConfig == nil {
|
||||
this.NotFound("server", params.ServerId)
|
||||
return
|
||||
}
|
||||
|
||||
var httpConfig = serverConfig.HTTP
|
||||
if httpConfig == nil {
|
||||
httpConfig = &serverconfigs.HTTPProtocolConfig{}
|
||||
}
|
||||
httpConfig.IsOn = params.IsOn
|
||||
|
||||
// 如果启用HTTP时没有填写端口,则默认为80
|
||||
if params.IsOn && len(httpConfig.Listen) == 0 {
|
||||
httpConfig.Listen = []*serverconfigs.NetworkAddressConfig{
|
||||
{
|
||||
Protocol: serverconfigs.ProtocolHTTP,
|
||||
PortRange: "80",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
configData, err := json.Marshal(httpConfig)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
_, err = this.RPC().ServerRPC().UpdateServerHTTP(this.UserContext(), &pb.UpdateServerHTTPRequest{
|
||||
ServerId: params.ServerId,
|
||||
HttpJSON: configData,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
// 设置跳转到HTTPS
|
||||
// TODO 校验设置
|
||||
_, err = this.RPC().HTTPWebRPC().UpdateHTTPWebRedirectToHTTPS(this.UserContext(), &pb.UpdateHTTPWebRedirectToHTTPSRequest{
|
||||
HttpWebId: params.WebId,
|
||||
RedirectToHTTPSJSON: params.RedirectToHTTPSJSON,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package http
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/default/servers/serverutils"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/helpers"
|
||||
"github.com/iwind/TeaGo"
|
||||
)
|
||||
|
||||
func init() {
|
||||
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
||||
server.
|
||||
Helper(helpers.NewUserMustAuth("")).
|
||||
Helper(serverutils.NewServerHelper()).
|
||||
Prefix("/servers/server/settings/http").
|
||||
GetPost("", new(IndexAction)).
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,266 @@
|
||||
package https
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/configutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/sslconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/userconfigs"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/lists"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
)
|
||||
|
||||
type IndexAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *IndexAction) Init() {
|
||||
this.Nav("", "setting", "index")
|
||||
this.SecondMenu("https")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct {
|
||||
ServerId int64
|
||||
}) {
|
||||
this.Data["http3FeatureEnabled"] = this.ValidateFeature(userconfigs.UserFeatureCodeServerHTTP3, params.ServerId)
|
||||
|
||||
serverConfig, err := dao.SharedServerDAO.FindEnabledServerConfig(this.UserContext(), params.ServerId)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if serverConfig == nil {
|
||||
this.NotFound("server", params.ServerId)
|
||||
return
|
||||
}
|
||||
|
||||
var httpsConfig = serverConfig.HTTPS
|
||||
if httpsConfig == nil {
|
||||
httpsConfig = &serverconfigs.HTTPSProtocolConfig{}
|
||||
}
|
||||
|
||||
var sslPolicy *sslconfigs.SSLPolicy
|
||||
var allDNSNames []string
|
||||
if httpsConfig.SSLPolicyRef != nil && httpsConfig.SSLPolicyRef.SSLPolicyId > 0 {
|
||||
sslPolicyConfigResp, err := this.RPC().SSLPolicyRPC().FindEnabledSSLPolicyConfig(this.UserContext(), &pb.FindEnabledSSLPolicyConfigRequest{
|
||||
SslPolicyId: httpsConfig.SSLPolicyRef.SSLPolicyId,
|
||||
IgnoreData: true,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
sslPolicyConfigJSON := sslPolicyConfigResp.SslPolicyJSON
|
||||
if len(sslPolicyConfigJSON) > 0 {
|
||||
sslPolicy = &sslconfigs.SSLPolicy{}
|
||||
err = json.Unmarshal(sslPolicyConfigJSON, sslPolicy)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
for _, cert := range sslPolicy.Certs {
|
||||
for _, dnsName := range cert.DNSNames {
|
||||
if !lists.ContainsString(allDNSNames, dnsName) {
|
||||
allDNSNames = append(allDNSNames, dnsName)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 当前集群是否支持HTTP/3
|
||||
// TODO 检查当前服务所属用户是否支持HTTP/3
|
||||
http3PolicyResp, err := this.RPC().NodeClusterRPC().FindNodeClusterHTTP3Policy(this.UserContext(), &pb.FindNodeClusterHTTP3PolicyRequest{NodeClusterId: serverConfig.ClusterId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var supportsHTTP3 = false
|
||||
if len(http3PolicyResp.Http3PolicyJSON) > 0 {
|
||||
var http3Policy = nodeconfigs.NewHTTP3Policy()
|
||||
err = json.Unmarshal(http3PolicyResp.Http3PolicyJSON, http3Policy)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
supportsHTTP3 = http3Policy.IsOn
|
||||
}
|
||||
|
||||
this.Data["serverType"] = serverConfig.Type
|
||||
this.Data["httpsConfig"] = maps.Map{
|
||||
"isOn": httpsConfig.IsOn,
|
||||
"sslPolicy": sslPolicy,
|
||||
"supportsHTTP3": supportsHTTP3,
|
||||
}
|
||||
|
||||
// 检查域名是否都已经上传了证书
|
||||
serverNamesResp, err := this.RPC().ServerRPC().FindServerNames(this.UserContext(), &pb.FindServerNamesRequest{
|
||||
ServerId: params.ServerId,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var allServerNames []string
|
||||
if len(serverNamesResp.ServerNamesJSON) > 0 {
|
||||
var serverNamesConfigs = []*serverconfigs.ServerNameConfig{}
|
||||
err = json.Unmarshal(serverNamesResp.ServerNamesJSON, &serverNamesConfigs)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
allServerNames = serverconfigs.PlainServerNames(serverNamesConfigs)
|
||||
}
|
||||
|
||||
this.Data["missingCertServerNames"] = []string{}
|
||||
if len(allServerNames) > 0 {
|
||||
var missingServerNames []string
|
||||
for _, serverName := range allServerNames {
|
||||
if !configutils.MatchDomains(allDNSNames, serverName) {
|
||||
missingServerNames = append(missingServerNames, serverName)
|
||||
}
|
||||
}
|
||||
this.Data["missingCertServerNames"] = missingServerNames
|
||||
}
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunPost(params struct {
|
||||
ServerId int64
|
||||
IsOn bool
|
||||
|
||||
SslPolicyJSON []byte
|
||||
|
||||
Must *actions.Must
|
||||
}) {
|
||||
// 记录日志
|
||||
defer this.CreateLogInfo(codes.ServerHTTPS_LogUpdateHTTPSSettings, params.ServerId)
|
||||
|
||||
serverConfig, err := dao.SharedServerDAO.FindEnabledServerConfig(this.UserContext(), params.ServerId)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if serverConfig == nil {
|
||||
this.NotFound("server", params.ServerId)
|
||||
return
|
||||
}
|
||||
|
||||
// 校验SSL
|
||||
var sslPolicyId = int64(0)
|
||||
if params.SslPolicyJSON != nil {
|
||||
sslPolicy := &sslconfigs.SSLPolicy{}
|
||||
err = json.Unmarshal(params.SslPolicyJSON, sslPolicy)
|
||||
if err != nil {
|
||||
this.ErrorPage(errors.New("解析SSL配置时发生了错误:" + err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
sslPolicyId = sslPolicy.Id
|
||||
|
||||
certsJSON, err := json.Marshal(sslPolicy.CertRefs)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
hstsJSON, err := json.Marshal(sslPolicy.HSTS)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
clientCACertsJSON, err := json.Marshal(sslPolicy.ClientCARefs)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
if sslPolicyId > 0 {
|
||||
_, err := this.RPC().SSLPolicyRPC().UpdateSSLPolicy(this.UserContext(), &pb.UpdateSSLPolicyRequest{
|
||||
SslPolicyId: sslPolicyId,
|
||||
Http2Enabled: sslPolicy.HTTP2Enabled,
|
||||
Http3Enabled: sslPolicy.HTTP3Enabled,
|
||||
MinVersion: sslPolicy.MinVersion,
|
||||
SslCertsJSON: certsJSON,
|
||||
HstsJSON: hstsJSON,
|
||||
OcspIsOn: sslPolicy.OCSPIsOn,
|
||||
ClientAuthType: types.Int32(sslPolicy.ClientAuthType),
|
||||
ClientCACertsJSON: clientCACertsJSON,
|
||||
CipherSuitesIsOn: sslPolicy.CipherSuitesIsOn,
|
||||
CipherSuites: sslPolicy.CipherSuites,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
resp, err := this.RPC().SSLPolicyRPC().CreateSSLPolicy(this.UserContext(), &pb.CreateSSLPolicyRequest{
|
||||
Http2Enabled: sslPolicy.HTTP2Enabled,
|
||||
Http3Enabled: sslPolicy.HTTP3Enabled,
|
||||
MinVersion: sslPolicy.MinVersion,
|
||||
SslCertsJSON: certsJSON,
|
||||
HstsJSON: hstsJSON,
|
||||
OcspIsOn: sslPolicy.OCSPIsOn,
|
||||
ClientAuthType: types.Int32(sslPolicy.ClientAuthType),
|
||||
ClientCACertsJSON: clientCACertsJSON,
|
||||
CipherSuitesIsOn: sslPolicy.CipherSuitesIsOn,
|
||||
CipherSuites: sslPolicy.CipherSuites,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
sslPolicyId = resp.SslPolicyId
|
||||
}
|
||||
}
|
||||
|
||||
var httpsConfig = serverConfig.HTTPS
|
||||
if httpsConfig == nil {
|
||||
httpsConfig = &serverconfigs.HTTPSProtocolConfig{}
|
||||
}
|
||||
|
||||
httpsConfig.SSLPolicy = nil
|
||||
httpsConfig.SSLPolicyRef = &sslconfigs.SSLPolicyRef{
|
||||
IsOn: true,
|
||||
SSLPolicyId: sslPolicyId,
|
||||
}
|
||||
httpsConfig.IsOn = params.IsOn
|
||||
|
||||
// 如果启用HTTPS时没有填写端口,则默认为443
|
||||
if params.IsOn && len(httpsConfig.Listen) == 0 {
|
||||
httpsConfig.Listen = []*serverconfigs.NetworkAddressConfig{
|
||||
{
|
||||
Protocol: serverconfigs.ProtocolHTTPS,
|
||||
PortRange: "443",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
configData, err := json.Marshal(httpsConfig)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
_, err = this.RPC().ServerRPC().UpdateServerHTTPS(this.UserContext(), &pb.UpdateServerHTTPSRequest{
|
||||
ServerId: params.ServerId,
|
||||
HttpsJSON: configData,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package https
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/default/servers/serverutils"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/helpers"
|
||||
"github.com/iwind/TeaGo"
|
||||
)
|
||||
|
||||
func init() {
|
||||
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
||||
server.
|
||||
Helper(helpers.NewUserMustAuth("")).
|
||||
Helper(serverutils.NewServerHelper()).
|
||||
Prefix("/servers/server/settings/https").
|
||||
GetPost("", new(IndexAction)).
|
||||
GetPost("/requestCertPopup", new(RequestCertPopupAction)).
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,180 @@
|
||||
package https
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/sslconfigs"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/utils/domainutils"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/lists"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type RequestCertPopupAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *RequestCertPopupAction) Init() {
|
||||
this.Nav("", "", "")
|
||||
}
|
||||
|
||||
func (this *RequestCertPopupAction) RunGet(params struct {
|
||||
ServerId int64
|
||||
ExcludeServerNames string
|
||||
}) {
|
||||
serverNamesResp, err := this.RPC().ServerRPC().FindServerNames(this.UserContext(), &pb.FindServerNamesRequest{ServerId: params.ServerId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
serverNameConfigs := []*serverconfigs.ServerNameConfig{}
|
||||
err = json.Unmarshal(serverNamesResp.ServerNamesJSON, &serverNameConfigs)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
excludeServerNames := []string{}
|
||||
if len(params.ExcludeServerNames) > 0 {
|
||||
excludeServerNames = strings.Split(params.ExcludeServerNames, ",")
|
||||
}
|
||||
serverNames := []string{}
|
||||
for _, c := range serverNameConfigs {
|
||||
if len(c.SubNames) == 0 {
|
||||
if domainutils.ValidateDomainFormat(c.Name) && !lists.ContainsString(excludeServerNames, c.Name) {
|
||||
serverNames = append(serverNames, c.Name)
|
||||
}
|
||||
} else {
|
||||
for _, subName := range c.SubNames {
|
||||
if domainutils.ValidateDomainFormat(subName) && !lists.ContainsString(excludeServerNames, subName) {
|
||||
serverNames = append(serverNames, subName)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
this.Data["serverNames"] = serverNames
|
||||
|
||||
// 用户
|
||||
acmeUsersResp, err := this.RPC().ACMEUserRPC().FindAllACMEUsers(this.UserContext(), &pb.FindAllACMEUsersRequest{
|
||||
UserId: this.UserId(),
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var userMaps = []maps.Map{}
|
||||
for _, user := range acmeUsersResp.AcmeUsers {
|
||||
description := user.Description
|
||||
if len(description) > 0 {
|
||||
description = "(" + description + ")"
|
||||
}
|
||||
|
||||
userMaps = append(userMaps, maps.Map{
|
||||
"id": user.Id,
|
||||
"description": description,
|
||||
"email": user.Email,
|
||||
})
|
||||
}
|
||||
this.Data["users"] = userMaps
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *RequestCertPopupAction) RunPost(params struct {
|
||||
ServerNames []string
|
||||
|
||||
UserId int64
|
||||
UserEmail string
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
// 检查域名
|
||||
if len(params.ServerNames) == 0 {
|
||||
this.Fail("必须包含至少一个或多个域名")
|
||||
}
|
||||
|
||||
// 注册用户
|
||||
var acmeUserId int64
|
||||
if params.UserId > 0 {
|
||||
// TODO 检查当前管理员是否可以使用此用户
|
||||
acmeUserId = params.UserId
|
||||
} else if len(params.UserEmail) > 0 {
|
||||
params.Must.
|
||||
Field("userEmail", params.UserEmail).
|
||||
Email("Email格式错误")
|
||||
|
||||
createUserResp, err := this.RPC().ACMEUserRPC().CreateACMEUser(this.UserContext(), &pb.CreateACMEUserRequest{
|
||||
Email: params.UserEmail,
|
||||
Description: "",
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
defer this.CreateLogInfo(codes.ACMEUser_LogCreateACMEUser, createUserResp.AcmeUserId)
|
||||
acmeUserId = createUserResp.AcmeUserId
|
||||
|
||||
this.Data["acmeUser"] = maps.Map{
|
||||
"id": acmeUserId,
|
||||
"email": params.UserEmail,
|
||||
}
|
||||
} else {
|
||||
this.Fail("请选择或者填写用户")
|
||||
}
|
||||
|
||||
createTaskResp, err := this.RPC().ACMETaskRPC().CreateACMETask(this.UserContext(), &pb.CreateACMETaskRequest{
|
||||
AcmeUserId: acmeUserId,
|
||||
DnsProviderId: 0,
|
||||
DnsDomain: "",
|
||||
Domains: params.ServerNames,
|
||||
AutoRenew: true,
|
||||
AuthType: "http",
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
taskId := createTaskResp.AcmeTaskId
|
||||
|
||||
defer this.CreateLogInfo(codes.ACMETask_LogRunACMETask, taskId)
|
||||
|
||||
runResp, err := this.RPC().ACMETaskRPC().RunACMETask(this.UserContext(), &pb.RunACMETaskRequest{AcmeTaskId: taskId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
if runResp.IsOk {
|
||||
certId := runResp.SslCertId
|
||||
|
||||
configResp, err := this.RPC().SSLCertRPC().FindEnabledSSLCertConfig(this.UserContext(), &pb.FindEnabledSSLCertConfigRequest{SslCertId: certId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
certConfig := &sslconfigs.SSLCertConfig{}
|
||||
err = json.Unmarshal(configResp.SslCertJSON, certConfig)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
certConfig.CertData = nil // 去掉不必要的数据
|
||||
certConfig.KeyData = nil // 去掉不必要的数据
|
||||
this.Data["cert"] = certConfig
|
||||
this.Data["certRef"] = &sslconfigs.SSLCertRef{
|
||||
IsOn: true,
|
||||
CertId: certId,
|
||||
}
|
||||
|
||||
this.Success()
|
||||
} else {
|
||||
this.Fail(runResp.Error)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
// Copyright 2024 GoEdge CDN goedge.cdn@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
//go:build plus
|
||||
|
||||
package referers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
)
|
||||
|
||||
type HlsAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *HlsAction) Init() {
|
||||
this.Nav("", "setting", "hls")
|
||||
this.SecondMenu("multimedia")
|
||||
}
|
||||
|
||||
func (this *HlsAction) RunGet(params struct {
|
||||
ServerId int64
|
||||
}) {
|
||||
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithServerId(this.UserContext(), params.ServerId)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Data["webId"] = webConfig.Id
|
||||
|
||||
hlsResp, err := this.RPC().HTTPWebRPC().FindHTTPWebHLS(this.UserContext(), &pb.FindHTTPWebHLSRequest{HttpWebId: webConfig.Id})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
var hlsConfig = &serverconfigs.HLSConfig{}
|
||||
if len(hlsResp.HlsJSON) > 0 {
|
||||
err = json.Unmarshal(hlsResp.HlsJSON, hlsConfig)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
this.Data["hlsConfig"] = hlsConfig
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *HlsAction) RunPost(params struct {
|
||||
WebId int64
|
||||
HlsJSON []byte
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.ServerHls_LogUpdateHls, params.WebId)
|
||||
|
||||
var hlsConfig = &serverconfigs.HLSConfig{}
|
||||
err := json.Unmarshal(params.HlsJSON, hlsConfig)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
err = hlsConfig.Init()
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
hlsJSON, err := json.Marshal(hlsConfig)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
_, err = this.RPC().HTTPWebRPC().UpdateHTTPWebHLS(this.UserContext(), &pb.UpdateHTTPWebHLSRequest{
|
||||
HttpWebId: params.WebId,
|
||||
HlsJSON: hlsJSON,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
// Copyright 2024 GoEdge CDN goedge.cdn@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
//go:build plus
|
||||
|
||||
package referers
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
)
|
||||
|
||||
type IndexAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *IndexAction) Init() {
|
||||
this.Nav("", "setting", "index")
|
||||
this.SecondMenu("multimedia")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct {
|
||||
ServerId int64
|
||||
}) {
|
||||
this.RedirectURL("./multimedia/hls?serverId=" + types.String(params.ServerId))
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
//go:build plus
|
||||
|
||||
package referers
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/default/servers/serverutils"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/helpers"
|
||||
"github.com/iwind/TeaGo"
|
||||
)
|
||||
|
||||
func init() {
|
||||
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
||||
server.
|
||||
Helper(helpers.NewUserMustAuth("")).
|
||||
Helper(serverutils.NewServerHelper()).
|
||||
Prefix("/servers/server/settings/multimedia").
|
||||
GetPost("", new(IndexAction)).
|
||||
GetPost("/hls", new(HlsAction)).
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
//go:build !plus
|
||||
// +build !plus
|
||||
|
||||
package multimedia
|
||||
|
||||
// 此文件用于在非 Plus 版本中保持包的完整性
|
||||
// Plus 版本的功能在 init.go 中实现(需要 //go:build plus 标签)
|
||||
@@ -0,0 +1,106 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
//go:build plus
|
||||
|
||||
package optimization
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/userconfigs"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
)
|
||||
|
||||
type IndexAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *IndexAction) Init() {
|
||||
this.Nav("", "setting", "index")
|
||||
this.SecondMenu("optimization")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct {
|
||||
ServerId int64
|
||||
}) {
|
||||
this.Data["featureIsOn"] = this.ValidateFeature(userconfigs.UserFeatureCodeServerOptimization, params.ServerId)
|
||||
|
||||
// 服务分组设置
|
||||
groupResp, err := this.RPC().ServerGroupRPC().FindEnabledServerGroupConfigInfo(this.UserContext(), &pb.FindEnabledServerGroupConfigInfoRequest{
|
||||
ServerId: params.ServerId,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
this.Data["hasGroupConfig"] = groupResp.HasOptimizationConfig
|
||||
this.Data["groupSettingURL"] = "/servers/groups/group/settings/optimization?groupId=" + types.String(groupResp.ServerGroupId)
|
||||
|
||||
// WebId
|
||||
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithServerId(this.UserContext(), params.ServerId)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Data["webId"] = webConfig.Id
|
||||
|
||||
if webConfig.Encryption == nil {
|
||||
webConfig.Encryption = serverconfigs.NewHTTPPageEncryptionConfig()
|
||||
}
|
||||
|
||||
this.Data["encryptionConfig"] = webConfig.Encryption
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunPost(params struct {
|
||||
WebId int64
|
||||
EncryptionJSON []byte
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
// 获取网站ID
|
||||
serverId, err := this.FindServerIdWithWebId(params.WebId)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
if !this.ValidateFeature(userconfigs.UserFeatureCodeServerOptimization, serverId) {
|
||||
this.Fail("permission denied")
|
||||
return
|
||||
}
|
||||
|
||||
defer this.CreateLogInfo(codes.ServerOptimization_LogUpdateOptimizationSettings, params.WebId)
|
||||
|
||||
// 校验配置
|
||||
var encryptionConfig = serverconfigs.NewHTTPPageEncryptionConfig()
|
||||
err = json.Unmarshal(params.EncryptionJSON, encryptionConfig)
|
||||
if err != nil {
|
||||
this.Fail("配置校验失败:" + err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
err = encryptionConfig.Init()
|
||||
if err != nil {
|
||||
this.Fail("配置校验失败:" + err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
_, err = this.RPC().HTTPWebRPC().UpdateHTTPWebEncryption(this.UserContext(), &pb.UpdateHTTPWebEncryptionRequest{
|
||||
HttpWebId: params.WebId,
|
||||
EncryptionJSON: params.EncryptionJSON,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
//go:build plus
|
||||
|
||||
package optimization
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/default/servers/serverutils"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/helpers"
|
||||
"github.com/iwind/TeaGo"
|
||||
)
|
||||
|
||||
func init() {
|
||||
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
||||
server.
|
||||
Helper(helpers.NewUserMustAuth("")).
|
||||
Helper(serverutils.NewServerHelper()).
|
||||
Prefix("/servers/server/settings/optimization").
|
||||
GetPost("", new(IndexAction)).
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
//go:build !plus
|
||||
// +build !plus
|
||||
|
||||
package optimization
|
||||
|
||||
// 此文件用于在非 Plus 版本中保持包的完整性
|
||||
// Plus 版本的功能在 init.go 中实现(需要 //go:build plus 标签)
|
||||
@@ -0,0 +1,258 @@
|
||||
package origins
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/sslconfigs"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"net/url"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// AddPopupAction 添加源站
|
||||
type AddPopupAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *AddPopupAction) RunGet(params struct {
|
||||
ServerId int64
|
||||
ReverseProxyId int64
|
||||
OriginType string
|
||||
}) {
|
||||
this.Data["reverseProxyId"] = params.ReverseProxyId
|
||||
this.Data["originType"] = params.OriginType
|
||||
|
||||
serverTypeResp, err := this.RPC().ServerRPC().FindEnabledServerType(this.UserContext(), &pb.FindEnabledServerTypeRequest{ServerId: params.ServerId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
serverType := serverTypeResp.Type
|
||||
this.Data["serverType"] = serverType
|
||||
|
||||
// 是否为HTTP
|
||||
this.Data["isHTTP"] = serverType == "httpProxy" || serverType == "httpWeb"
|
||||
|
||||
// OSS
|
||||
this.getOSSHook()
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *AddPopupAction) RunPost(params struct {
|
||||
OriginType string
|
||||
|
||||
ReverseProxyId int64
|
||||
Weight int32
|
||||
Protocol string
|
||||
Addr string
|
||||
Name string
|
||||
Description string
|
||||
IsOn bool
|
||||
|
||||
CertIdsJSON []byte
|
||||
|
||||
DomainsJSON []byte
|
||||
Host string
|
||||
|
||||
FollowPort bool
|
||||
Http2Enabled bool
|
||||
|
||||
Must *actions.Must
|
||||
}) {
|
||||
ossConfig, goNext, err := this.postOSSHook(params.Protocol)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if !goNext {
|
||||
return
|
||||
}
|
||||
|
||||
// 初始化
|
||||
var pbAddr = &pb.NetworkAddress{
|
||||
Protocol: params.Protocol,
|
||||
}
|
||||
|
||||
var ossJSON []byte = nil
|
||||
var certRefJSON []byte
|
||||
|
||||
if ossConfig != nil { // OSS
|
||||
ossJSON, err = json.Marshal(ossConfig)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
err = ossConfig.Init()
|
||||
if err != nil {
|
||||
this.Fail("校验OSS配置时出错:" + err.Error())
|
||||
return
|
||||
}
|
||||
} else { // 普通源站
|
||||
params.Must.
|
||||
Field("addr", params.Addr).
|
||||
Require("请输入源站地址")
|
||||
|
||||
var addr = params.Addr
|
||||
|
||||
// 是否是完整的地址
|
||||
if (params.Protocol == "http" || params.Protocol == "https") && regexp.MustCompile(`^(http|https)://`).MatchString(addr) {
|
||||
u, err := url.Parse(addr)
|
||||
if err == nil {
|
||||
addr = u.Host
|
||||
}
|
||||
}
|
||||
|
||||
addr = strings.ReplaceAll(addr, ":", ":")
|
||||
addr = regexp.MustCompile(`\s+`).ReplaceAllString(addr, "")
|
||||
portIndex := strings.LastIndex(addr, ":")
|
||||
if portIndex < 0 {
|
||||
if params.Protocol == "http" {
|
||||
addr += ":80"
|
||||
} else if params.Protocol == "https" {
|
||||
addr += ":443"
|
||||
} else {
|
||||
this.FailField("addr", "源站地址中需要带有端口")
|
||||
}
|
||||
portIndex = strings.LastIndex(addr, ":")
|
||||
}
|
||||
|
||||
var host = addr[:portIndex]
|
||||
var port = addr[portIndex+1:]
|
||||
if port == "0" {
|
||||
this.FailField("addr", "源站端口号不能为0")
|
||||
}
|
||||
|
||||
// 证书
|
||||
var certIds = []int64{}
|
||||
if len(params.CertIdsJSON) > 0 {
|
||||
err = json.Unmarshal(params.CertIdsJSON, &certIds)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if len(certIds) > 0 {
|
||||
var certId = certIds[0]
|
||||
if certId > 0 {
|
||||
var certRef = &sslconfigs.SSLCertRef{
|
||||
IsOn: true,
|
||||
CertId: certId,
|
||||
}
|
||||
certRefJSON, err = json.Marshal(certRef)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pbAddr = &pb.NetworkAddress{
|
||||
Protocol: params.Protocol,
|
||||
Host: host,
|
||||
PortRange: port,
|
||||
}
|
||||
}
|
||||
|
||||
// 专属域名
|
||||
var domains = []string{}
|
||||
if len(params.DomainsJSON) > 0 {
|
||||
err = json.Unmarshal(params.DomainsJSON, &domains)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
// 去除可能误加的斜杠
|
||||
for index, domain := range domains {
|
||||
domains[index] = strings.TrimSuffix(domain, "/")
|
||||
}
|
||||
}
|
||||
|
||||
createResp, err := this.RPC().OriginRPC().CreateOrigin(this.UserContext(), &pb.CreateOriginRequest{
|
||||
Name: params.Name,
|
||||
Addr: pbAddr,
|
||||
OssJSON: ossJSON,
|
||||
Description: params.Description,
|
||||
Weight: params.Weight,
|
||||
IsOn: params.IsOn,
|
||||
Domains: domains,
|
||||
CertRefJSON: certRefJSON,
|
||||
Host: params.Host,
|
||||
FollowPort: params.FollowPort,
|
||||
Http2Enabled: params.Http2Enabled,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var originId = createResp.OriginId
|
||||
var originRef = &serverconfigs.OriginRef{
|
||||
IsOn: true,
|
||||
OriginId: originId,
|
||||
}
|
||||
|
||||
reverseProxyResp, err := this.RPC().ReverseProxyRPC().FindEnabledReverseProxy(this.UserContext(), &pb.FindEnabledReverseProxyRequest{ReverseProxyId: params.ReverseProxyId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var reverseProxy = reverseProxyResp.ReverseProxy
|
||||
if reverseProxy == nil {
|
||||
this.ErrorPage(errors.New("reverse proxy should not be nil"))
|
||||
return
|
||||
}
|
||||
|
||||
var origins = []*serverconfigs.OriginRef{}
|
||||
switch params.OriginType {
|
||||
case "primary":
|
||||
if len(reverseProxy.PrimaryOriginsJSON) > 0 {
|
||||
err = json.Unmarshal(reverseProxy.PrimaryOriginsJSON, &origins)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
case "backup":
|
||||
if len(reverseProxy.BackupOriginsJSON) > 0 {
|
||||
err = json.Unmarshal(reverseProxy.BackupOriginsJSON, &origins)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
origins = append(origins, originRef)
|
||||
originsData, err := json.Marshal(origins)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
switch params.OriginType {
|
||||
case "primary":
|
||||
_, err = this.RPC().ReverseProxyRPC().UpdateReverseProxyPrimaryOrigins(this.UserContext(), &pb.UpdateReverseProxyPrimaryOriginsRequest{
|
||||
ReverseProxyId: params.ReverseProxyId,
|
||||
OriginsJSON: originsData,
|
||||
})
|
||||
case "backup":
|
||||
_, err = this.RPC().ReverseProxyRPC().UpdateReverseProxyBackupOrigins(this.UserContext(), &pb.UpdateReverseProxyBackupOriginsRequest{
|
||||
ReverseProxyId: params.ReverseProxyId,
|
||||
OriginsJSON: originsData,
|
||||
})
|
||||
}
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
// 日志
|
||||
defer this.CreateLogInfo(codes.ServerOrigin_LogCreateOrigin, originId)
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
// Copyright 2023 GoEdge CDN goedge.cdn@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
//go:build plus
|
||||
|
||||
package origins
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/ossconfigs"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/default/servers/server/settings/origins/originutils"
|
||||
"os"
|
||||
)
|
||||
|
||||
func (this *AddPopupAction) getOSSHook() {
|
||||
this.Data["ossTypes"] = ossconfigs.FindAllOSSTypes()
|
||||
this.Data["ossBucketParams"] = ossconfigs.FindAllOSSBucketParamDefinitions()
|
||||
|
||||
// 表单
|
||||
var formFile = originutils.OSSTemplateFile("addPopup_oss_plus.html")
|
||||
formData, _ := os.ReadFile(formFile)
|
||||
this.Data["ossForm"] = string(formData)
|
||||
}
|
||||
|
||||
func (this *AddPopupAction) postOSSHook(protocol string) (config *ossconfigs.OSSConfig, goNext bool, err error) {
|
||||
return originutils.ParseOSSFromRequest(protocol, this.Object())
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
package origins
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
)
|
||||
|
||||
type DeleteAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *DeleteAction) RunPost(params struct {
|
||||
ReverseProxyId int64
|
||||
OriginId int64
|
||||
OriginType string
|
||||
}) {
|
||||
reverseProxyResp, err := this.RPC().ReverseProxyRPC().FindEnabledReverseProxy(this.UserContext(), &pb.FindEnabledReverseProxyRequest{ReverseProxyId: params.ReverseProxyId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
reverseProxy := reverseProxyResp.ReverseProxy
|
||||
if reverseProxy == nil {
|
||||
this.ErrorPage(errors.New("reverse proxy is nil"))
|
||||
return
|
||||
}
|
||||
|
||||
origins := []*serverconfigs.OriginRef{}
|
||||
switch params.OriginType {
|
||||
case "primary":
|
||||
err = json.Unmarshal(reverseProxy.PrimaryOriginsJSON, &origins)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
case "backup":
|
||||
err = json.Unmarshal(reverseProxy.BackupOriginsJSON, &origins)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
default:
|
||||
this.ErrorPage(errors.New("invalid origin type '" + params.OriginType + "'"))
|
||||
return
|
||||
}
|
||||
|
||||
result := []*serverconfigs.OriginRef{}
|
||||
for _, origin := range origins {
|
||||
if origin.OriginId == params.OriginId {
|
||||
continue
|
||||
}
|
||||
result = append(result, origin)
|
||||
}
|
||||
resultData, err := json.Marshal(result)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
switch params.OriginType {
|
||||
case "primary":
|
||||
_, err = this.RPC().ReverseProxyRPC().UpdateReverseProxyPrimaryOrigins(this.UserContext(), &pb.UpdateReverseProxyPrimaryOriginsRequest{
|
||||
ReverseProxyId: params.ReverseProxyId,
|
||||
OriginsJSON: resultData,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
case "backup":
|
||||
_, err = this.RPC().ReverseProxyRPC().UpdateReverseProxyBackupOrigins(this.UserContext(), &pb.UpdateReverseProxyBackupOriginsRequest{
|
||||
ReverseProxyId: params.ReverseProxyId,
|
||||
OriginsJSON: resultData,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// 日志
|
||||
defer this.CreateLogInfo(codes.ServerOrigin_LogDeleteOrigin, params.OriginId)
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
// Copyright 2024 GoEdge CDN goedge.cdn@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package origins
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/configutils"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"net"
|
||||
"net/url"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
type DetectHTTPSAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *DetectHTTPSAction) RunPost(params struct {
|
||||
Addr string
|
||||
}) {
|
||||
this.Data["isOk"] = false
|
||||
|
||||
// parse from url
|
||||
if strings.HasPrefix(params.Addr, "http://") || strings.HasPrefix(params.Addr, "https://") {
|
||||
u, err := url.Parse(params.Addr)
|
||||
if err == nil {
|
||||
params.Addr = u.Host
|
||||
}
|
||||
}
|
||||
|
||||
this.Data["addr"] = params.Addr
|
||||
|
||||
if len(params.Addr) == 0 {
|
||||
this.Success()
|
||||
return
|
||||
}
|
||||
|
||||
var realHost = params.Addr
|
||||
host, port, err := net.SplitHostPort(params.Addr)
|
||||
if err == nil {
|
||||
if port != "80" {
|
||||
this.Success()
|
||||
return
|
||||
}
|
||||
realHost = host
|
||||
}
|
||||
|
||||
conn, err := net.DialTimeout("tcp", configutils.QuoteIP(realHost)+":443", 3*time.Second)
|
||||
if err != nil {
|
||||
this.Success()
|
||||
return
|
||||
}
|
||||
_ = conn.Close()
|
||||
|
||||
this.Data["isOk"] = true
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package origins
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/helpers"
|
||||
"github.com/iwind/TeaGo"
|
||||
)
|
||||
|
||||
func init() {
|
||||
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
||||
server.
|
||||
Helper(helpers.NewUserMustAuth("")).
|
||||
Prefix("/servers/server/settings/origins").
|
||||
GetPost("/addPopup", new(AddPopupAction)).
|
||||
Post("/delete", new(DeleteAction)).
|
||||
GetPost("/updatePopup", new(UpdatePopupAction)).
|
||||
Post("/updateIsOn", new(UpdateIsOnAction)).
|
||||
Post("/detectHTTPS", new(DetectHTTPSAction)).
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,384 @@
|
||||
// Copyright 2023 GoEdge CDN goedge.cdn@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
//go:build plus
|
||||
|
||||
package originutils
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/ossconfigs"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/utils/domainutils"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"net/url"
|
||||
"os"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// ParseOSSFromRequest 请Action提交的表单中分析OSS信息
|
||||
func ParseOSSFromRequest(protocol string, action *actions.ActionObject) (config *ossconfigs.OSSConfig, goNext bool, err error) {
|
||||
if !ossconfigs.IsOSSProtocol(protocol) {
|
||||
goNext = true
|
||||
return
|
||||
}
|
||||
|
||||
var ossType = ossconfigs.FindOSSType(protocol)
|
||||
if ossType == nil {
|
||||
action.Fail("无法识别的OSS类型:" + protocol)
|
||||
return
|
||||
}
|
||||
|
||||
switch protocol {
|
||||
case ossconfigs.OSSTypeTencentCOS:
|
||||
var secretId = action.ParamString("tencentCOSSecretId")
|
||||
var secretKey = action.ParamString("tencentCOSSecretKey")
|
||||
var region = action.ParamString("tencentCOSRegion")
|
||||
|
||||
if len(secretId) == 0 {
|
||||
action.FailField("tencentCOSSecretId", "请输入密钥ID")
|
||||
return
|
||||
}
|
||||
if len(secretKey) == 0 {
|
||||
action.FailField("tencentCOSSecretKey", "请输入密钥Key")
|
||||
return
|
||||
}
|
||||
if len(region) == 0 {
|
||||
action.FailField("tencentCOSRegion", "请输入所属区域代号")
|
||||
return
|
||||
}
|
||||
if !regexp.MustCompile(`^[\w-]+$`).MatchString(region) {
|
||||
action.FailField("tencentCOSRegion", "输入的区域代号格式错误")
|
||||
return
|
||||
}
|
||||
|
||||
config = ossconfigs.NewOSSConfig()
|
||||
config.Type = protocol
|
||||
|
||||
if !parseOSSBucketParam(action, config, ossType.BucketOptionName) {
|
||||
return
|
||||
}
|
||||
|
||||
var options = ossconfigs.NewTencentCOSProviderOptions()
|
||||
options.SecretId = secretId
|
||||
options.SecretKey = secretKey
|
||||
options.Region = region
|
||||
config.Options = options
|
||||
|
||||
err = config.Init()
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
case ossconfigs.OSSTypeAliyunOSS:
|
||||
var accessKeyId = action.ParamString("aliyunOSSAccessKeyId")
|
||||
var accessKeySecret = action.ParamString("aliyunOSSAccessKeySecret")
|
||||
var endpoint = action.ParamString("aliyunOSSEndpoint")
|
||||
if len(accessKeyId) == 0 {
|
||||
action.FailField("aliyunOSSAccessKeyId", "请输入密钥ID")
|
||||
return
|
||||
}
|
||||
if len(accessKeySecret) == 0 {
|
||||
action.FailField("aliyunOSSAccessKeySecret", "请输入密钥Key")
|
||||
return
|
||||
}
|
||||
if len(endpoint) == 0 {
|
||||
action.FailField("aliyunOSSEndpoint", "请输入地域节点")
|
||||
return
|
||||
}
|
||||
|
||||
if !domainutils.ValidateDomainFormat(endpoint) {
|
||||
action.FailField("aliyunOSSEndpoint", "地域节点需要是一个域名")
|
||||
return
|
||||
}
|
||||
|
||||
config = ossconfigs.NewOSSConfig()
|
||||
config.Type = protocol
|
||||
|
||||
if !parseOSSBucketParam(action, config, ossType.BucketOptionName) {
|
||||
return
|
||||
}
|
||||
|
||||
var options = ossconfigs.NewAliyunOSSProviderOptions()
|
||||
options.AccessKeyId = accessKeyId
|
||||
options.AccessKeySecret = accessKeySecret
|
||||
options.Endpoint = endpoint
|
||||
config.Options = options
|
||||
|
||||
err = config.Init()
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
case ossconfigs.OSSTypeHuaweiOBS:
|
||||
var accessKeyId = action.ParamString("huaweiOBSAccessKeyId")
|
||||
var accessKeySecret = action.ParamString("huaweiOBSAccessKeySecret")
|
||||
var endpoint = action.ParamString("huaweiOBSEndpoint")
|
||||
if len(accessKeyId) == 0 {
|
||||
action.FailField("huaweiOBSAccessKeyId", "请输入密钥ID")
|
||||
return
|
||||
}
|
||||
if len(accessKeySecret) == 0 {
|
||||
action.FailField("huaweiOBSAccessKeySecret", "请输入密钥Key")
|
||||
return
|
||||
}
|
||||
if len(endpoint) == 0 {
|
||||
action.FailField("huaweiOBSEndpoint", "请输入区域Endpoint")
|
||||
return
|
||||
}
|
||||
|
||||
if !domainutils.ValidateDomainFormat(endpoint) {
|
||||
action.FailField("huaweiOBSEndpoint", "区域Endpoint需要是一个域名")
|
||||
return
|
||||
}
|
||||
|
||||
config = ossconfigs.NewOSSConfig()
|
||||
config.Type = protocol
|
||||
|
||||
if !parseOSSBucketParam(action, config, ossType.BucketOptionName) {
|
||||
return
|
||||
}
|
||||
|
||||
var options = ossconfigs.NewHuaweiOBSProviderOptions()
|
||||
options.AccessKeyId = accessKeyId
|
||||
options.AccessKeySecret = accessKeySecret
|
||||
options.Endpoint = endpoint
|
||||
config.Options = options
|
||||
|
||||
err = config.Init()
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
case ossconfigs.OSSTypeBaiduBOS:
|
||||
var accessKey = action.ParamString("baiduBOSAccessKey")
|
||||
var secretKey = action.ParamString("baiduBOSSecretKey")
|
||||
var endpoint = action.ParamString("baiduBOSEndpoint")
|
||||
if len(accessKey) == 0 {
|
||||
action.FailField("baiduBOSAccessKey", "请输入AccessKey")
|
||||
return
|
||||
}
|
||||
if len(secretKey) == 0 {
|
||||
action.FailField("baiduBOSSecretKey", "请输入SecretKey")
|
||||
return
|
||||
}
|
||||
if len(endpoint) == 0 {
|
||||
action.FailField("baiduBOSEndpoint", "请输入区域Endpoint")
|
||||
return
|
||||
}
|
||||
|
||||
if !domainutils.ValidateDomainFormat(endpoint) {
|
||||
action.FailField("baiduBOSEndpoint", "区域Endpoint需要是一个域名")
|
||||
return
|
||||
}
|
||||
|
||||
config = ossconfigs.NewOSSConfig()
|
||||
config.Type = protocol
|
||||
|
||||
if !parseOSSBucketParam(action, config, ossType.BucketOptionName) {
|
||||
return
|
||||
}
|
||||
|
||||
var options = ossconfigs.NewBaiduBOSProviderOptions()
|
||||
options.AccessKey = accessKey
|
||||
options.SecretKey = secretKey
|
||||
options.Endpoint = endpoint
|
||||
config.Options = options
|
||||
|
||||
err = config.Init()
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
case ossconfigs.OSSTypeQiniuKodo:
|
||||
var accessKey = action.ParamString("qiniuKodoAccessKey")
|
||||
var secretKey = action.ParamString("qiniuKodoSecretKey")
|
||||
var domainProtocol = action.ParamString("qiniuKodoProtocol")
|
||||
var domain = action.ParamString("qiniuKodoDomain")
|
||||
var isPublicString = action.ParamString("qiniuKodoIsPublic")
|
||||
var isPublic = isPublicString == "1" || isPublicString == "true"
|
||||
|
||||
if len(accessKey) == 0 {
|
||||
action.FailField("qiniuKodoAccessKey", "请输入AccessKey")
|
||||
return
|
||||
}
|
||||
if len(secretKey) == 0 {
|
||||
action.FailField("qiniuKodoSecretKey", "请输入SecretKey")
|
||||
}
|
||||
if domainProtocol != "http" && domainProtocol != "https" {
|
||||
action.FailField("qiniuKodoProtocol", "请选择域名访问协议")
|
||||
return
|
||||
}
|
||||
if len(domain) == 0 {
|
||||
action.FailField("qiniuKodoDomain", "请输入访问域名")
|
||||
return
|
||||
}
|
||||
|
||||
domain = strings.ToLower(domain)
|
||||
|
||||
u, parseErr := url.Parse(domain)
|
||||
if parseErr == nil && len(u.Scheme) > 0 {
|
||||
// parse from a full url
|
||||
domain = u.Host
|
||||
domainProtocol = u.Scheme
|
||||
} else {
|
||||
// remove path part
|
||||
var slashIndex = strings.Index(domain, "/")
|
||||
if slashIndex >= 0 {
|
||||
domain = domain[:slashIndex]
|
||||
}
|
||||
}
|
||||
|
||||
// 再次检查
|
||||
if len(domain) == 0 || !domainutils.ValidateDomainFormat(domain) {
|
||||
action.FailField("qiniuKodoDomain", "请输入正确的访问域名")
|
||||
return
|
||||
}
|
||||
|
||||
config = ossconfigs.NewOSSConfig()
|
||||
config.Type = protocol
|
||||
|
||||
if !parseOSSBucketParam(action, config, ossType.BucketOptionName) {
|
||||
return
|
||||
}
|
||||
|
||||
var options = ossconfigs.NewQiniuKodoProviderOptions()
|
||||
options.AccessKey = accessKey
|
||||
options.SecretKey = secretKey
|
||||
options.Protocol = domainProtocol
|
||||
options.Domain = domain
|
||||
options.IsPublic = isPublic
|
||||
config.Options = options
|
||||
|
||||
err = config.Init()
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
case ossconfigs.OSSTypeAmazonS3, ossconfigs.OSSTypeB2:
|
||||
var accessKeyId = action.ParamString("amazonS3AccessKeyId")
|
||||
var accessKeySecret = action.ParamString("amazonS3AccessKeySecret")
|
||||
var region = action.ParamString("amazonS3Region")
|
||||
var endpoint = action.ParamString("amazonS3Endpoint")
|
||||
var bucketAddressStyle = action.ParamString("bucketAddressStyle")
|
||||
if len(accessKeyId) == 0 {
|
||||
action.FailField("amazonS3AccessKeyId", "请输入密钥ID")
|
||||
return
|
||||
}
|
||||
if len(accessKeySecret) == 0 {
|
||||
action.FailField("amazonS3AccessKeySecret", "请输入密钥Key")
|
||||
return
|
||||
}
|
||||
if len(region) == 0 {
|
||||
action.FailField("amazonS3Region", "请输入区域代号")
|
||||
return
|
||||
}
|
||||
|
||||
if !regexp.MustCompile(`^[\w-]+$`).MatchString(region) {
|
||||
action.FailField("amazonS3Region", "输入的区域代号格式错误")
|
||||
return
|
||||
}
|
||||
|
||||
if protocol != ossconfigs.OSSTypeAmazonS3 {
|
||||
if len(endpoint) == 0 {
|
||||
action.FailField("amazonS3Endpoint", "请输入Endpoint")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if len(endpoint) > 0 {
|
||||
if !domainutils.ValidateDomainFormat(endpoint) {
|
||||
u, urlErr := url.Parse(endpoint)
|
||||
if urlErr != nil || len(u.Scheme) == 0 {
|
||||
action.FailField("amazonS3Endpoint", "Endpoint需要是一个域名或者URL")
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
config = ossconfigs.NewOSSConfig()
|
||||
config.Type = protocol
|
||||
|
||||
if !parseOSSBucketParam(action, config, ossType.BucketOptionName) {
|
||||
return
|
||||
}
|
||||
|
||||
var options = ossconfigs.NewAmazonS3ProviderOptions()
|
||||
options.AccessKeyId = accessKeyId
|
||||
options.AccessKeySecret = accessKeySecret
|
||||
options.Region = region
|
||||
options.Endpoint = endpoint
|
||||
options.BucketAddressStyle = bucketAddressStyle
|
||||
config.Options = options
|
||||
|
||||
err = config.Init()
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
default:
|
||||
action.Fail("无法识别的OSS类型:" + protocol)
|
||||
return
|
||||
}
|
||||
|
||||
goNext = true
|
||||
return
|
||||
}
|
||||
|
||||
func parseOSSBucketParam(action *actions.ActionObject, config *ossconfigs.OSSConfig, optionName string) (goNext bool) {
|
||||
var bucketParam = action.ParamString("bucketParam")
|
||||
config.BucketParam = bucketParam
|
||||
|
||||
switch bucketParam {
|
||||
case ossconfigs.OSSBucketParamInput:
|
||||
var bucketName = action.ParamString("bucketName")
|
||||
if len(bucketName) == 0 {
|
||||
action.FailField("bucketName", "请输入"+optionName+"名称")
|
||||
return
|
||||
}
|
||||
if !regexp.MustCompile(`^[\w._-]+$`).MatchString(bucketName) {
|
||||
action.FailField("bucketName", "输入的"+optionName+"名称格式错误")
|
||||
return
|
||||
}
|
||||
config.BucketName = bucketName
|
||||
goNext = true
|
||||
case ossconfigs.OSSBucketParamPrefix:
|
||||
goNext = true
|
||||
case ossconfigs.OSSBucketParamArg:
|
||||
var bucketArgName = action.ParamString("bucketArgName")
|
||||
if len(bucketArgName) == 0 {
|
||||
action.FailField("bucketArgName", "请输入"+optionName+"参数名称")
|
||||
return
|
||||
}
|
||||
if !regexp.MustCompile(`^[\w._-]+$`).MatchString(bucketArgName) {
|
||||
action.FailField("bucketArgName", "输入的"+optionName+"参数名称格式错误")
|
||||
return
|
||||
}
|
||||
config.BucketArgName = bucketArgName
|
||||
goNext = true
|
||||
case ossconfigs.OSSBucketParamSubDomain:
|
||||
goNext = true
|
||||
default:
|
||||
action.Fail("请选择" + optionName + "名称获取方式")
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// OSSTemplateFile 模板文件路径
|
||||
func OSSTemplateFile(filename string) string {
|
||||
var filenames = []string{filename}
|
||||
|
||||
if !Tea.IsTesting() {
|
||||
filenames = append(filenames, strings.Replace(filename, "_plus.html", ".html", -1))
|
||||
}
|
||||
|
||||
for _, name := range filenames {
|
||||
var viewFile = "/views/@default/servers/server/settings/origins/" + name
|
||||
var absPath string
|
||||
if Tea.IsTesting() {
|
||||
absPath = Tea.Root + "/../web" + viewFile
|
||||
} else {
|
||||
absPath = Tea.Root + "/web" + viewFile
|
||||
}
|
||||
|
||||
_, err := os.Stat(absPath)
|
||||
if err == nil {
|
||||
return absPath
|
||||
}
|
||||
}
|
||||
|
||||
return filename
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
// Copyright 2024 GoEdge CDN goedge.cdn@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package origins
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
)
|
||||
|
||||
type UpdateIsOnAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *UpdateIsOnAction) RunPost(params struct {
|
||||
OriginId int64
|
||||
IsOn bool
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.ServerOrigin_LogUpdateOriginIsOn, params.OriginId)
|
||||
|
||||
_, err := this.RPC().OriginRPC().UpdateOriginIsOn(this.UserContext(), &pb.UpdateOriginIsOnRequest{
|
||||
OriginId: params.OriginId,
|
||||
IsOn: params.IsOn,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,250 @@
|
||||
package origins
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/sslconfigs"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"net/url"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// UpdatePopupAction 修改源站
|
||||
type UpdatePopupAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *UpdatePopupAction) Init() {
|
||||
this.Nav("", "", "")
|
||||
}
|
||||
|
||||
func (this *UpdatePopupAction) RunGet(params struct {
|
||||
ServerId int64
|
||||
ReverseProxyId int64
|
||||
OriginType string
|
||||
OriginId int64
|
||||
}) {
|
||||
this.Data["originType"] = params.OriginType
|
||||
this.Data["reverseProxyId"] = params.ReverseProxyId
|
||||
this.Data["originId"] = params.OriginId
|
||||
|
||||
serverTypeResp, err := this.RPC().ServerRPC().FindEnabledServerType(this.UserContext(), &pb.FindEnabledServerTypeRequest{
|
||||
ServerId: params.ServerId,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
this.Data["serverType"] = serverTypeResp.Type
|
||||
|
||||
// 是否为HTTP
|
||||
var serverType = serverTypeResp.Type
|
||||
this.Data["isHTTP"] = serverType == "httpProxy" || serverType == "httpWeb"
|
||||
|
||||
// 源站信息
|
||||
originResp, err := this.RPC().OriginRPC().FindEnabledOriginConfig(this.UserContext(), &pb.FindEnabledOriginConfigRequest{OriginId: params.OriginId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var configData = originResp.OriginJSON
|
||||
var config = &serverconfigs.OriginConfig{}
|
||||
err = json.Unmarshal(configData, config)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
if len(config.Domains) == 0 {
|
||||
config.Domains = []string{}
|
||||
}
|
||||
|
||||
// 重置数据
|
||||
if config.Cert != nil {
|
||||
config.Cert.CertData = nil
|
||||
config.Cert.KeyData = nil
|
||||
}
|
||||
|
||||
this.Data["origin"] = maps.Map{
|
||||
"id": config.Id,
|
||||
"protocol": config.Addr.Protocol,
|
||||
"addr": config.Addr.Host + ":" + config.Addr.PortRange,
|
||||
"weight": config.Weight,
|
||||
"name": config.Name,
|
||||
"description": config.Description,
|
||||
"isOn": config.IsOn,
|
||||
"domains": config.Domains,
|
||||
"cert": config.Cert,
|
||||
"host": config.RequestHost,
|
||||
"followPort": config.FollowPort,
|
||||
"http2Enabled": config.HTTP2Enabled,
|
||||
"oss": config.OSS,
|
||||
}
|
||||
|
||||
// OSS
|
||||
this.getOSSHook()
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *UpdatePopupAction) RunPost(params struct {
|
||||
OriginType string
|
||||
OriginId int64
|
||||
|
||||
ReverseProxyId int64
|
||||
Protocol string
|
||||
Addr string
|
||||
Weight int32
|
||||
Name string
|
||||
Description string
|
||||
IsOn bool
|
||||
|
||||
CertIdsJSON []byte
|
||||
|
||||
DomainsJSON []byte
|
||||
Host string
|
||||
|
||||
FollowPort bool
|
||||
Http2Enabled bool
|
||||
|
||||
Must *actions.Must
|
||||
}) {
|
||||
ossConfig, goNext, err := this.postOSSHook(params.Protocol)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if !goNext {
|
||||
return
|
||||
}
|
||||
|
||||
// 初始化
|
||||
var pbAddr = &pb.NetworkAddress{
|
||||
Protocol: params.Protocol,
|
||||
}
|
||||
var ossJSON []byte
|
||||
var certRefJSON []byte
|
||||
|
||||
if ossConfig != nil { // OSS
|
||||
ossJSON, err = json.Marshal(ossConfig)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
err = ossConfig.Init()
|
||||
if err != nil {
|
||||
this.Fail("校验OSS配置时出错:" + err.Error())
|
||||
return
|
||||
}
|
||||
} else { // 普通源站
|
||||
|
||||
params.Must.
|
||||
Field("addr", params.Addr).
|
||||
Require("请输入源站地址")
|
||||
|
||||
var addr = params.Addr
|
||||
|
||||
// 是否是完整的地址
|
||||
if (params.Protocol == "http" || params.Protocol == "https") && regexp.MustCompile(`^(http|https)://`).MatchString(addr) {
|
||||
u, err := url.Parse(addr)
|
||||
if err == nil {
|
||||
addr = u.Host
|
||||
}
|
||||
}
|
||||
|
||||
addr = strings.ReplaceAll(addr, ":", ":")
|
||||
addr = regexp.MustCompile(`\s+`).ReplaceAllString(addr, "")
|
||||
portIndex := strings.LastIndex(addr, ":")
|
||||
if portIndex < 0 {
|
||||
if params.Protocol == "http" {
|
||||
addr += ":80"
|
||||
} else if params.Protocol == "https" {
|
||||
addr += ":443"
|
||||
} else {
|
||||
this.FailField("addr", "地址中需要带有端口")
|
||||
}
|
||||
portIndex = strings.LastIndex(addr, ":")
|
||||
}
|
||||
host := addr[:portIndex]
|
||||
port := addr[portIndex+1:]
|
||||
if port == "0" {
|
||||
this.FailField("addr", "端口号不能为0")
|
||||
}
|
||||
|
||||
// 证书
|
||||
var certIds = []int64{}
|
||||
var err error
|
||||
if len(params.CertIdsJSON) > 0 {
|
||||
err = json.Unmarshal(params.CertIdsJSON, &certIds)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if len(certIds) > 0 {
|
||||
var certId = certIds[0]
|
||||
if certId > 0 {
|
||||
var certRef = &sslconfigs.SSLCertRef{
|
||||
IsOn: true,
|
||||
CertId: certId,
|
||||
}
|
||||
certRefJSON, err = json.Marshal(certRef)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pbAddr = &pb.NetworkAddress{
|
||||
Protocol: params.Protocol,
|
||||
Host: host,
|
||||
PortRange: port,
|
||||
}
|
||||
}
|
||||
|
||||
// 域名
|
||||
var domains = []string{}
|
||||
if len(params.DomainsJSON) > 0 {
|
||||
err = json.Unmarshal(params.DomainsJSON, &domains)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
// 去除可能误加的斜杠
|
||||
for index, domain := range domains {
|
||||
domains[index] = strings.TrimSuffix(domain, "/")
|
||||
}
|
||||
}
|
||||
|
||||
_, err = this.RPC().OriginRPC().UpdateOrigin(this.UserContext(), &pb.UpdateOriginRequest{
|
||||
OriginId: params.OriginId,
|
||||
Name: params.Name,
|
||||
Addr: pbAddr,
|
||||
OssJSON: ossJSON,
|
||||
Description: params.Description,
|
||||
Weight: params.Weight,
|
||||
IsOn: params.IsOn,
|
||||
Domains: domains,
|
||||
Host: params.Host,
|
||||
CertRefJSON: certRefJSON,
|
||||
FollowPort: params.FollowPort,
|
||||
Http2Enabled: params.Http2Enabled,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
// 日志
|
||||
defer this.CreateLogInfo(codes.ServerOrigin_LogUpdateOrigin, params.OriginId)
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
// Copyright 2023 GoEdge CDN goedge.cdn@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
//go:build plus
|
||||
|
||||
package origins
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/ossconfigs"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/default/servers/server/settings/origins/originutils"
|
||||
"os"
|
||||
)
|
||||
|
||||
func (this *UpdatePopupAction) getOSSHook() {
|
||||
this.Data["ossTypes"] = ossconfigs.FindAllOSSTypes()
|
||||
this.Data["ossBucketParams"] = ossconfigs.FindAllOSSBucketParamDefinitions()
|
||||
|
||||
// 表单
|
||||
var formFile = originutils.OSSTemplateFile("updatePopup_oss_plus.html")
|
||||
formData, _ := os.ReadFile(formFile)
|
||||
this.Data["ossForm"] = string(formData)
|
||||
}
|
||||
|
||||
func (this *UpdatePopupAction) postOSSHook(protocol string) (config *ossconfigs.OSSConfig, goNext bool, err error) {
|
||||
return originutils.ParseOSSFromRequest(protocol, this.Object())
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
package pages
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
)
|
||||
|
||||
type CreatePopupAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *CreatePopupAction) Init() {
|
||||
this.Nav("", "", "")
|
||||
}
|
||||
|
||||
func (this *CreatePopupAction) RunGet(params struct{}) {
|
||||
this.Data["bodyTypes"] = serverconfigs.FindAllHTTPPageBodyTypes()
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *CreatePopupAction) RunPost(params struct {
|
||||
Status string
|
||||
BodyType string
|
||||
|
||||
URL string `alias:"url"`
|
||||
Body string
|
||||
|
||||
ExceptURLPatternsJSON []byte
|
||||
OnlyURLPatternsJSON []byte
|
||||
|
||||
NewStatus int
|
||||
Must *actions.Must
|
||||
}) {
|
||||
params.Must.
|
||||
Field("status", params.Status).
|
||||
Require("请输入响应状态码")
|
||||
|
||||
if len(params.Status) != 3 {
|
||||
this.FailField("status", "状态码长度必须为3位")
|
||||
return
|
||||
}
|
||||
|
||||
switch params.BodyType {
|
||||
case serverconfigs.HTTPPageBodyTypeURL:
|
||||
params.Must.
|
||||
Field("url", params.URL).
|
||||
Require("请输入要显示的URL").
|
||||
Match(`^(?i)(http|https)://`, "请输入正确的URL")
|
||||
case serverconfigs.HTTPPageBodyTypeRedirectURL:
|
||||
params.Must.
|
||||
Field("url", params.URL).
|
||||
Require("请输入要跳转的URL").
|
||||
Match(`^(?i)(http|https)://`, "请输入正确的URL")
|
||||
case serverconfigs.HTTPPageBodyTypeHTML:
|
||||
params.Must.
|
||||
Field("body", params.Body).
|
||||
Require("请输入要显示的HTML内容")
|
||||
|
||||
if len(params.Body) > 32*1024 {
|
||||
this.FailField("body", "自定义页面内容不能超过32K")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
var exceptURLPatterns = []*shared.URLPattern{}
|
||||
if len(params.ExceptURLPatternsJSON) > 0 {
|
||||
err := json.Unmarshal(params.ExceptURLPatternsJSON, &exceptURLPatterns)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
var onlyURLPatterns = []*shared.URLPattern{}
|
||||
if len(params.OnlyURLPatternsJSON) > 0 {
|
||||
err := json.Unmarshal(params.OnlyURLPatternsJSON, &onlyURLPatterns)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
createResp, err := this.RPC().HTTPPageRPC().CreateHTTPPage(this.UserContext(), &pb.CreateHTTPPageRequest{
|
||||
StatusList: []string{params.Status},
|
||||
BodyType: params.BodyType,
|
||||
Url: params.URL,
|
||||
Body: params.Body,
|
||||
NewStatus: types.Int32(params.NewStatus),
|
||||
ExceptURLPatternsJSON: params.ExceptURLPatternsJSON,
|
||||
OnlyURLPatternsJSON: params.OnlyURLPatternsJSON,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var pageId = createResp.HttpPageId
|
||||
|
||||
configResp, err := this.RPC().HTTPPageRPC().FindEnabledHTTPPageConfig(this.UserContext(), &pb.FindEnabledHTTPPageConfigRequest{HttpPageId: pageId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
var pageConfig = &serverconfigs.HTTPPageConfig{}
|
||||
err = json.Unmarshal(configResp.PageJSON, pageConfig)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
err = pageConfig.Init()
|
||||
if err != nil {
|
||||
this.Fail("配置校验失败:" + err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
this.Data["page"] = pageConfig
|
||||
|
||||
// 日志
|
||||
defer this.CreateLogInfo(codes.ServerPage_LogCreatePage, pageId)
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,165 @@
|
||||
package pages
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/userconfigs"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
type IndexAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *IndexAction) Init() {
|
||||
this.Nav("", "setting", "index")
|
||||
this.SecondMenu("pages")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct {
|
||||
ServerId int64
|
||||
}) {
|
||||
this.Data["featureIsOn"] = this.ValidateFeature(userconfigs.UserFeatureCodeServerPages, params.ServerId)
|
||||
|
||||
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithServerId(this.UserContext(), params.ServerId)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Data["webId"] = webConfig.Id
|
||||
this.Data["enableGlobalPages"] = webConfig.EnableGlobalPages
|
||||
this.Data["pages"] = webConfig.Pages
|
||||
this.Data["shutdownConfig"] = webConfig.Shutdown
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunPost(params struct {
|
||||
WebId int64
|
||||
EnableGlobalPages bool
|
||||
PagesJSON []byte
|
||||
ShutdownJSON []byte
|
||||
Must *actions.Must
|
||||
}) {
|
||||
// 获取网站ID
|
||||
serverId, err := this.FindServerIdWithWebId(params.WebId)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if !this.ValidateFeature(userconfigs.UserFeatureCodeServerPages, serverId) {
|
||||
this.Fail("permission denied")
|
||||
return
|
||||
}
|
||||
|
||||
// 日志
|
||||
defer this.CreateLogInfo(codes.ServerPage_LogUpdatePages, params.WebId)
|
||||
|
||||
// 检查配置
|
||||
var urlReg = regexp.MustCompile(`^(?i)(http|https)://`)
|
||||
|
||||
// validate pages
|
||||
if len(params.PagesJSON) > 0 {
|
||||
var pages = []*serverconfigs.HTTPPageConfig{}
|
||||
err := json.Unmarshal(params.PagesJSON, &pages)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
for _, page := range pages {
|
||||
err = page.Init()
|
||||
if err != nil {
|
||||
this.Fail("配置校验失败:" + err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// check url
|
||||
if page.BodyType == serverconfigs.HTTPPageBodyTypeURL && !urlReg.MatchString(page.URL) {
|
||||
this.Fail("自定义页面中 '" + page.URL + "' 不是一个正确的URL,请进行修改")
|
||||
return
|
||||
}
|
||||
if page.BodyType == serverconfigs.HTTPPageBodyTypeRedirectURL && !urlReg.MatchString(page.URL) {
|
||||
this.Fail("自定义页面中 '" + page.URL + "' 不是一个正确的URL,请进行修改")
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// validate shutdown page
|
||||
if len(params.ShutdownJSON) > 0 {
|
||||
var shutdownConfig = &serverconfigs.HTTPShutdownConfig{}
|
||||
err := json.Unmarshal(params.ShutdownJSON, shutdownConfig)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
err = shutdownConfig.Init()
|
||||
if err != nil {
|
||||
this.Fail("配置校验失败:" + err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
if shutdownConfig.BodyType == serverconfigs.HTTPPageBodyTypeURL {
|
||||
if len(shutdownConfig.URL) > 512 {
|
||||
this.Fail("临时关闭页面中URL过长,不能超过512字节")
|
||||
return
|
||||
}
|
||||
|
||||
if shutdownConfig.IsOn /** 只有启用的时候才校验 **/ && !urlReg.MatchString(shutdownConfig.URL) {
|
||||
this.Fail("临时关闭页面中 '" + shutdownConfig.URL + "' 不是一个正确的URL,请进行修改")
|
||||
return
|
||||
}
|
||||
} else if shutdownConfig.BodyType == serverconfigs.HTTPPageBodyTypeRedirectURL {
|
||||
if len(shutdownConfig.URL) > 512 {
|
||||
this.Fail("临时关闭页面中URL过长,不能超过512字节")
|
||||
return
|
||||
}
|
||||
|
||||
if shutdownConfig.IsOn /** 只有启用的时候才校验 **/ && !urlReg.MatchString(shutdownConfig.URL) {
|
||||
this.Fail("临时关闭页面中 '" + shutdownConfig.URL + "' 不是一个正确的URL,请进行修改")
|
||||
return
|
||||
}
|
||||
} else if shutdownConfig.Body == serverconfigs.HTTPPageBodyTypeHTML {
|
||||
if len(shutdownConfig.Body) > 32*1024 {
|
||||
this.Fail("临时关闭页面中HTML内容长度不能超过32K")
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_, err = this.RPC().HTTPWebRPC().UpdateHTTPWebGlobalPagesEnabled(this.UserContext(), &pb.UpdateHTTPWebGlobalPagesEnabledRequest{
|
||||
HttpWebId: params.WebId,
|
||||
IsEnabled: params.EnableGlobalPages,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
_, err = this.RPC().HTTPWebRPC().UpdateHTTPWebPages(this.UserContext(), &pb.UpdateHTTPWebPagesRequest{
|
||||
HttpWebId: params.WebId,
|
||||
PagesJSON: params.PagesJSON,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
_, err = this.RPC().HTTPWebRPC().UpdateHTTPWebShutdown(this.UserContext(), &pb.UpdateHTTPWebShutdownRequest{
|
||||
HttpWebId: params.WebId,
|
||||
ShutdownJSON: params.ShutdownJSON,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package pages
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/default/servers/serverutils"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/helpers"
|
||||
"github.com/iwind/TeaGo"
|
||||
)
|
||||
|
||||
func init() {
|
||||
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
||||
server.
|
||||
Helper(helpers.NewUserMustAuth("")).
|
||||
Helper(serverutils.NewServerHelper()).
|
||||
Prefix("/servers/server/settings/pages").
|
||||
GetPost("", new(IndexAction)).
|
||||
GetPost("/createPopup", new(CreatePopupAction)).
|
||||
GetPost("/updatePopup", new(UpdatePopupAction)).
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,151 @@
|
||||
package pages
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
)
|
||||
|
||||
type UpdatePopupAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *UpdatePopupAction) Init() {
|
||||
this.Nav("", "", "")
|
||||
}
|
||||
|
||||
func (this *UpdatePopupAction) RunGet(params struct {
|
||||
PageId int64
|
||||
}) {
|
||||
this.Data["bodyTypes"] = serverconfigs.FindAllHTTPPageBodyTypes()
|
||||
|
||||
configResp, err := this.RPC().HTTPPageRPC().FindEnabledHTTPPageConfig(this.UserContext(), &pb.FindEnabledHTTPPageConfigRequest{HttpPageId: params.PageId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
var pageConfig = &serverconfigs.HTTPPageConfig{}
|
||||
err = json.Unmarshal(configResp.PageJSON, pageConfig)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if pageConfig.ExceptURLPatterns == nil {
|
||||
pageConfig.ExceptURLPatterns = []*shared.URLPattern{}
|
||||
}
|
||||
if pageConfig.OnlyURLPatterns == nil {
|
||||
pageConfig.OnlyURLPatterns = []*shared.URLPattern{}
|
||||
}
|
||||
this.Data["pageConfig"] = pageConfig
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *UpdatePopupAction) RunPost(params struct {
|
||||
PageId int64
|
||||
|
||||
Status string
|
||||
|
||||
BodyType string
|
||||
URL string `alias:"url"`
|
||||
Body string
|
||||
|
||||
ExceptURLPatternsJSON []byte
|
||||
OnlyURLPatternsJSON []byte
|
||||
|
||||
NewStatus int
|
||||
|
||||
Must *actions.Must
|
||||
}) {
|
||||
// 日志
|
||||
defer this.CreateLogInfo(codes.ServerPage_LogUpdatePage, params.PageId)
|
||||
|
||||
params.Must.
|
||||
Field("status", params.Status).
|
||||
Require("请输入响应状态码")
|
||||
|
||||
switch params.BodyType {
|
||||
case serverconfigs.HTTPPageBodyTypeURL:
|
||||
params.Must.
|
||||
Field("url", params.URL).
|
||||
Require("请输入要显示的URL").
|
||||
Match(`^(?i)(http|https)://`, "请输入正确的URL")
|
||||
case serverconfigs.HTTPPageBodyTypeRedirectURL:
|
||||
params.Must.
|
||||
Field("url", params.URL).
|
||||
Require("请输入要跳转的URL").
|
||||
Match(`^(?i)(http|https)://`, "请输入正确的URL")
|
||||
case serverconfigs.HTTPPageBodyTypeHTML:
|
||||
params.Must.
|
||||
Field("body", params.Body).
|
||||
Require("请输入要显示的HTML内容")
|
||||
|
||||
if len(params.Body) > 32*1024 {
|
||||
this.FailField("body", "自定义页面内容不能超过32K")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
var exceptURLPatterns = []*shared.URLPattern{}
|
||||
if len(params.ExceptURLPatternsJSON) > 0 {
|
||||
err := json.Unmarshal(params.ExceptURLPatternsJSON, &exceptURLPatterns)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
var onlyURLPatterns = []*shared.URLPattern{}
|
||||
if len(params.OnlyURLPatternsJSON) > 0 {
|
||||
err := json.Unmarshal(params.OnlyURLPatternsJSON, &onlyURLPatterns)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
_, err := this.RPC().HTTPPageRPC().UpdateHTTPPage(this.UserContext(), &pb.UpdateHTTPPageRequest{
|
||||
HttpPageId: params.PageId,
|
||||
StatusList: []string{params.Status},
|
||||
BodyType: params.BodyType,
|
||||
Url: params.URL,
|
||||
Body: params.Body,
|
||||
NewStatus: types.Int32(params.NewStatus),
|
||||
ExceptURLPatternsJSON: params.ExceptURLPatternsJSON,
|
||||
OnlyURLPatternsJSON: params.OnlyURLPatternsJSON,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
// 返回修改后的配置
|
||||
configResp, err := this.RPC().HTTPPageRPC().FindEnabledHTTPPageConfig(this.UserContext(), &pb.FindEnabledHTTPPageConfigRequest{HttpPageId: params.PageId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
var pageConfig = &serverconfigs.HTTPPageConfig{}
|
||||
err = json.Unmarshal(configResp.PageJSON, pageConfig)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
err = pageConfig.Init()
|
||||
if err != nil {
|
||||
this.Fail("配置校验失败:" + err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
this.Data["page"] = pageConfig
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
// Copyright 2023 GoEdge CDN goedge.cdn@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package plan
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
// DataAction 套餐相关数据
|
||||
type DataAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *DataAction) RunPost(params struct {
|
||||
ServerId int64
|
||||
UserPlanId int64
|
||||
}) {
|
||||
userPlanResp, err := this.RPC().UserPlanRPC().FindEnabledUserPlan(this.UserContext(), &pb.FindEnabledUserPlanRequest{UserPlanId: params.UserPlanId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var userPlan = userPlanResp.UserPlan
|
||||
if userPlan == nil || userPlan.Plan == nil {
|
||||
this.NotFound("userPlan", params.UserPlanId)
|
||||
return
|
||||
}
|
||||
var plan = userPlan.Plan
|
||||
|
||||
// 网站数
|
||||
countServersResp, err := this.RPC().ServerRPC().CountAllUserServers(this.UserContext(), &pb.CountAllUserServersRequest{
|
||||
UserPlanId: params.UserPlanId,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
this.Data["servers"] = maps.Map{
|
||||
"current": countServersResp.Count,
|
||||
"max": plan.TotalServers,
|
||||
"isValid": plan.TotalServers <= 0 || countServersResp.Count+1 <= int64(plan.TotalServers),
|
||||
}
|
||||
|
||||
// 当前网站域名数
|
||||
countServerNamesResp, err := this.RPC().ServerRPC().CountServerNames(this.UserContext(), &pb.CountServerNamesRequest{ServerId: params.ServerId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
this.Data["serverNames"] = maps.Map{
|
||||
"current": countServerNamesResp.Count,
|
||||
"max": plan.TotalServerNamesPerServer,
|
||||
"isValid": plan.TotalServerNamesPerServer <= 0 || countServerNamesResp.Count <= int64(plan.TotalServerNamesPerServer),
|
||||
}
|
||||
|
||||
// 总域名数
|
||||
countAllServerNamesResp, err := this.RPC().ServerRPC().CountAllServerNamesWithUserId(this.UserContext(), &pb.CountAllServerNamesWithUserIdRequest{
|
||||
UserPlanId: params.UserPlanId,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
this.Data["allServerNames"] = maps.Map{
|
||||
"current": countAllServerNamesResp.Count,
|
||||
"max": plan.TotalServerNames,
|
||||
"isValid": plan.TotalServerNames <= 0 || countAllServerNamesResp.Count+countServerNamesResp.Count <= int64(plan.TotalServerNames),
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,244 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package plan
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/userconfigs"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/utils/numberutils"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
)
|
||||
|
||||
type IndexAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *IndexAction) Init() {
|
||||
this.Nav("", "setting", "index")
|
||||
this.SecondMenu("plan")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct {
|
||||
ServerId int64
|
||||
}) {
|
||||
if !this.ValidateFeature(userconfigs.UserFeatureCodePlan, params.ServerId) {
|
||||
return
|
||||
}
|
||||
|
||||
// 所有可选套餐
|
||||
userPlansResp, err := this.RPC().UserPlanRPC().FindAllEnabledUserPlansForServer(this.UserContext(), &pb.FindAllEnabledUserPlansForServerRequest{
|
||||
UserId: this.UserId(),
|
||||
ServerId: params.ServerId,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var userPlanMaps = []maps.Map{}
|
||||
for _, userPlan := range userPlansResp.UserPlans {
|
||||
if userPlan.Plan == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
var name = userPlan.Plan.Name
|
||||
if len(userPlan.Name) > 0 {
|
||||
name += "-" + userPlan.Name
|
||||
}
|
||||
|
||||
userPlanMaps = append(userPlanMaps, maps.Map{
|
||||
"id": userPlan.Id,
|
||||
"name": name,
|
||||
"dayTo": userPlan.DayTo,
|
||||
"totalServers": userPlan.Plan.TotalServers,
|
||||
"totalServerNames": userPlan.Plan.TotalServerNames,
|
||||
"totalServerNamesPerServer": userPlan.Plan.TotalServerNamesPerServer,
|
||||
})
|
||||
}
|
||||
this.Data["userPlans"] = userPlanMaps
|
||||
|
||||
// 当前使用的套餐
|
||||
userPlanResp, err := this.RPC().ServerRPC().FindServerUserPlan(this.UserContext(), &pb.FindServerUserPlanRequest{ServerId: params.ServerId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
// 用户套餐信息
|
||||
var userPlanMap = maps.Map{"id": 0}
|
||||
var userPlan = userPlanResp.UserPlan
|
||||
this.Data["hasTrafficLimit"] = false
|
||||
if userPlan != nil {
|
||||
userPlanMap = maps.Map{
|
||||
"id": userPlan.Id,
|
||||
"dayTo": userPlan.DayTo,
|
||||
"isExpired": timeutil.Format("Y-m-d") > userPlan.DayTo,
|
||||
"name": userPlan.Name,
|
||||
"plan": nil,
|
||||
}
|
||||
|
||||
var plan = userPlan.Plan
|
||||
if plan != nil {
|
||||
// 流量限制
|
||||
var trafficLimit = &serverconfigs.TrafficLimitConfig{}
|
||||
if len(plan.TrafficLimitJSON) > 0 {
|
||||
err = json.Unmarshal(plan.TrafficLimitJSON, trafficLimit)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
userPlanMap["plan"] = maps.Map{
|
||||
"id": plan.Id,
|
||||
"name": plan.Name,
|
||||
"trafficLimit": trafficLimit,
|
||||
}
|
||||
|
||||
if !trafficLimit.IsEmpty() {
|
||||
this.Data["hasTrafficLimit"] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
this.Data["userPlan"] = userPlanMap
|
||||
|
||||
// 当前网站流量
|
||||
{
|
||||
trafficStatResp, err := this.RPC().ServerDailyRPC().SumServerDailyStats(this.UserContext(), &pb.SumServerDailyStatsRequest{
|
||||
ServerId: params.ServerId,
|
||||
Day: timeutil.Format("Ymd"),
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var trafficDailyBytes int64 = 0
|
||||
if trafficStatResp.ServerDailyStat != nil {
|
||||
trafficDailyBytes = trafficStatResp.ServerDailyStat.Bytes
|
||||
}
|
||||
this.Data["trafficDailyFormat"] = numberutils.FormatBytes(trafficDailyBytes)
|
||||
}
|
||||
|
||||
{
|
||||
trafficStatResp, err := this.RPC().ServerDailyRPC().SumServerMonthlyStats(this.UserContext(), &pb.SumServerMonthlyStatsRequest{
|
||||
ServerId: params.ServerId,
|
||||
Month: timeutil.Format("Ym"),
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var trafficMonthlyBytes int64 = 0
|
||||
if trafficStatResp.ServerMonthlyStat != nil {
|
||||
trafficMonthlyBytes = trafficStatResp.ServerMonthlyStat.Bytes
|
||||
}
|
||||
this.Data["trafficMonthlyFormat"] = numberutils.FormatBytes(trafficMonthlyBytes)
|
||||
}
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunPost(params struct {
|
||||
ServerId int64
|
||||
|
||||
IsChanged bool
|
||||
UserPlanId int64
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
if !params.IsChanged {
|
||||
this.Success()
|
||||
return
|
||||
}
|
||||
|
||||
if params.UserPlanId <= 0 { // 取消绑定
|
||||
defer this.CreateLogInfo(codes.UserPlan_LogCancelUserPlanFromServer, params.ServerId)
|
||||
} else { // 变更绑定
|
||||
defer this.CreateLogInfo(codes.UserPlan_LogBindUserPlanToServer, params.ServerId, params.UserPlanId)
|
||||
}
|
||||
|
||||
// 前后套餐是否一致
|
||||
oldUserPlanResp, err := this.RPC().ServerRPC().FindServerUserPlan(this.UserContext(), &pb.FindServerUserPlanRequest{ServerId: params.ServerId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if oldUserPlanResp.UserPlan != nil && oldUserPlanResp.UserPlan.Id == params.UserPlanId {
|
||||
this.Success()
|
||||
return
|
||||
}
|
||||
|
||||
// 检查套餐
|
||||
if params.UserPlanId > 0 {
|
||||
userPlanResp, err := this.RPC().UserPlanRPC().FindEnabledUserPlan(this.UserContext(), &pb.FindEnabledUserPlanRequest{UserPlanId: params.UserPlanId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var userPlan = userPlanResp.UserPlan
|
||||
if userPlan == nil || userPlan.Plan == nil {
|
||||
this.NotFound("userPlan", params.UserPlanId)
|
||||
return
|
||||
}
|
||||
var plan = userPlan.Plan
|
||||
|
||||
// server
|
||||
if plan.TotalServers > 0 {
|
||||
countServersResp, err := this.RPC().ServerRPC().CountAllUserServers(this.UserContext(), &pb.CountAllUserServersRequest{
|
||||
UserPlanId: params.UserPlanId,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if countServersResp.Count+1 > int64(plan.TotalServers) {
|
||||
this.Fail("已绑定网站数超出当前套餐限制")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
countServerNamesResp, err := this.RPC().ServerRPC().CountServerNames(this.UserContext(), &pb.CountServerNamesRequest{ServerId: params.ServerId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if plan.TotalServerNamesPerServer > 0 {
|
||||
if countServerNamesResp.Count > int64(plan.TotalServerNamesPerServer) {
|
||||
this.Fail("当前网站域名数超出当前套餐限制")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if plan.TotalServerNames > 0 {
|
||||
countAllServerNamesResp, err := this.RPC().ServerRPC().CountAllServerNamesWithUserId(this.UserContext(), &pb.CountAllServerNamesWithUserIdRequest{
|
||||
UserPlanId: params.UserPlanId,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if countAllServerNamesResp.Count+countServerNamesResp.Count > int64(plan.TotalServerNames) {
|
||||
this.Fail("已绑定域名数超出当前套餐限制")
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 提交修改
|
||||
_, err = this.RPC().ServerRPC().UpdateServerUserPlan(this.UserContext(), &pb.UpdateServerUserPlanRequest{
|
||||
ServerId: params.ServerId,
|
||||
UserPlanId: params.UserPlanId,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package plan
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/default/servers/serverutils"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/helpers"
|
||||
"github.com/iwind/TeaGo"
|
||||
)
|
||||
|
||||
func init() {
|
||||
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
||||
server.
|
||||
Helper(helpers.NewUserMustAuth("")).
|
||||
Helper(serverutils.NewServerHelper()).
|
||||
Prefix("/servers/server/settings/plan").
|
||||
GetPost("", new(IndexAction)).
|
||||
Post("/data", new(DataAction)).
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,241 @@
|
||||
package redirects
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/default/dns/domains/domainutils"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"net/url"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type CreatePopupAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *CreatePopupAction) Init() {
|
||||
this.Nav("", "", "")
|
||||
}
|
||||
|
||||
func (this *CreatePopupAction) RunGet(params struct {
|
||||
}) {
|
||||
this.Data["featureIsOn"] = true // MUST BE always true
|
||||
this.Data["statusList"] = serverconfigs.AllHTTPRedirectStatusList()
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *CreatePopupAction) RunPost(params struct {
|
||||
Type string
|
||||
|
||||
// URL
|
||||
Mode string
|
||||
BeforeURL string
|
||||
AfterURL string
|
||||
MatchPrefix bool
|
||||
MatchRegexp bool
|
||||
KeepRequestURI bool
|
||||
KeepArgs bool
|
||||
|
||||
// 域名
|
||||
DomainsAll bool
|
||||
DomainsBeforeJSON []byte
|
||||
DomainBeforeIgnorePorts bool
|
||||
DomainAfter string
|
||||
DomainAfterScheme string
|
||||
|
||||
// 端口
|
||||
PortsAll bool
|
||||
PortsBefore []string
|
||||
PortAfter int
|
||||
PortAfterScheme string
|
||||
|
||||
Status int
|
||||
|
||||
ExceptDomainsJSON []byte
|
||||
OnlyDomainsJSON []byte
|
||||
|
||||
CondsJSON []byte
|
||||
IsOn bool
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
var config = &serverconfigs.HTTPHostRedirectConfig{}
|
||||
config.Type = params.Type
|
||||
config.Status = params.Status
|
||||
config.IsOn = params.IsOn
|
||||
|
||||
switch params.Type {
|
||||
case serverconfigs.HTTPHostRedirectTypeURL:
|
||||
params.Must.
|
||||
Field("beforeURL", params.BeforeURL).
|
||||
Require("请填写跳转前的URL")
|
||||
|
||||
// 校验格式
|
||||
if params.MatchRegexp {
|
||||
_, err := regexp.Compile(params.BeforeURL)
|
||||
if err != nil {
|
||||
this.Fail("跳转前URL正则表达式错误:" + err.Error())
|
||||
}
|
||||
} else {
|
||||
u, err := url.Parse(params.BeforeURL)
|
||||
if err != nil {
|
||||
this.FailField("beforeURL", "请输入正确的跳转前URL")
|
||||
}
|
||||
if (u.Scheme != "http" && u.Scheme != "https") ||
|
||||
len(u.Host) == 0 {
|
||||
this.FailField("beforeURL", "请输入正确的跳转前URL")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
params.Must.
|
||||
Field("afterURL", params.AfterURL).
|
||||
Require("请填写跳转后URL")
|
||||
|
||||
// 校验格式
|
||||
if params.MatchRegexp {
|
||||
// 正则表达式情况下不做校验
|
||||
} else {
|
||||
u, err := url.Parse(params.AfterURL)
|
||||
if err != nil {
|
||||
this.FailField("afterURL", "请输入正确的跳转后URL")
|
||||
}
|
||||
if (u.Scheme != "http" && u.Scheme != "https") ||
|
||||
len(u.Host) == 0 {
|
||||
this.FailField("afterURL", "请输入正确的跳转后URL")
|
||||
}
|
||||
}
|
||||
|
||||
config.Mode = params.Mode
|
||||
config.BeforeURL = params.BeforeURL
|
||||
config.AfterURL = params.AfterURL
|
||||
config.MatchPrefix = params.MatchPrefix
|
||||
config.MatchRegexp = params.MatchRegexp
|
||||
config.KeepRequestURI = params.KeepRequestURI
|
||||
config.KeepArgs = params.KeepArgs
|
||||
case serverconfigs.HTTPHostRedirectTypeDomain:
|
||||
config.DomainsAll = params.DomainsAll
|
||||
var domainsBefore = []string{}
|
||||
if len(params.DomainsBeforeJSON) > 0 {
|
||||
err := json.Unmarshal(params.DomainsBeforeJSON, &domainsBefore)
|
||||
if err != nil {
|
||||
this.Fail("错误的域名格式:" + err.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
config.DomainsBefore = domainsBefore
|
||||
if !params.DomainsAll {
|
||||
if len(domainsBefore) == 0 {
|
||||
this.Fail("请输入跳转前域名")
|
||||
return
|
||||
}
|
||||
}
|
||||
config.DomainBeforeIgnorePorts = params.DomainBeforeIgnorePorts
|
||||
if len(params.DomainAfter) == 0 {
|
||||
this.FailField("domainAfter", "请输入跳转后域名")
|
||||
return
|
||||
}
|
||||
|
||||
// 检查用户输入的是否为域名
|
||||
if !domainutils.ValidateDomainFormat(params.DomainAfter) {
|
||||
// 是否为URL
|
||||
u, err := url.Parse(params.DomainAfter)
|
||||
if err == nil {
|
||||
if len(u.Host) == 0 {
|
||||
this.FailField("domainAfter", "跳转后域名输入不正确")
|
||||
return
|
||||
}
|
||||
params.DomainAfter = u.Host
|
||||
} else {
|
||||
this.FailField("domainAfter", "跳转后域名输入不正确")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
config.DomainAfter = params.DomainAfter
|
||||
config.DomainAfterScheme = params.DomainAfterScheme
|
||||
case serverconfigs.HTTPHostRedirectTypePort:
|
||||
config.PortsAll = params.PortsAll
|
||||
|
||||
config.PortsBefore = params.PortsBefore
|
||||
var portReg = regexp.MustCompile(`^\d+$`)
|
||||
var portRangeReg = regexp.MustCompile(`^\d+-\d+$`)
|
||||
if !config.PortsAll {
|
||||
for _, port := range params.PortsBefore {
|
||||
port = strings.ReplaceAll(port, " ", "")
|
||||
if !portReg.MatchString(port) && !portRangeReg.MatchString(port) {
|
||||
this.Fail("端口号" + port + "填写错误(请输入单个端口号或一个端口范围)")
|
||||
return
|
||||
}
|
||||
}
|
||||
if len(params.PortsBefore) == 0 {
|
||||
this.Fail("请输入跳转前端口")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if params.PortAfter <= 0 {
|
||||
this.FailField("portAfter", "请输入跳转后端口")
|
||||
return
|
||||
}
|
||||
config.PortAfter = params.PortAfter
|
||||
config.PortAfterScheme = params.PortAfterScheme
|
||||
}
|
||||
|
||||
params.Must.
|
||||
Field("status", params.Status).
|
||||
Gte(0, "请选择正确的跳转状态码")
|
||||
|
||||
// 域名
|
||||
if len(params.ExceptDomainsJSON) > 0 {
|
||||
var exceptDomains = []string{}
|
||||
err := json.Unmarshal(params.ExceptDomainsJSON, &exceptDomains)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
config.ExceptDomains = exceptDomains
|
||||
}
|
||||
|
||||
if len(params.OnlyDomainsJSON) > 0 {
|
||||
var onlyDomains = []string{}
|
||||
err := json.Unmarshal(params.OnlyDomainsJSON, &onlyDomains)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
config.OnlyDomains = onlyDomains
|
||||
}
|
||||
|
||||
// 校验匹配条件
|
||||
var conds *shared.HTTPRequestCondsConfig
|
||||
if len(params.CondsJSON) > 0 {
|
||||
conds = &shared.HTTPRequestCondsConfig{}
|
||||
err := json.Unmarshal(params.CondsJSON, conds)
|
||||
if err != nil {
|
||||
this.Fail("匹配条件校验失败:" + err.Error())
|
||||
}
|
||||
|
||||
err = conds.Init()
|
||||
if err != nil {
|
||||
this.Fail("匹配条件校验失败:" + err.Error())
|
||||
}
|
||||
}
|
||||
config.Conds = conds
|
||||
|
||||
// 校验配置
|
||||
err := config.Init()
|
||||
if err != nil {
|
||||
this.Fail("配置校验失败:" + err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
this.Data["redirect"] = config
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package redirects
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/userconfigs"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
)
|
||||
|
||||
type IndexAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *IndexAction) Init() {
|
||||
this.Nav("", "setting", "index")
|
||||
this.SecondMenu("redirects")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct {
|
||||
ServerId int64
|
||||
}) {
|
||||
this.Data["featureIsOn"] = this.ValidateFeature(userconfigs.UserFeatureCodeServerHostRedirects, params.ServerId)
|
||||
|
||||
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithServerId(this.UserContext(), params.ServerId)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Data["webId"] = webConfig.Id
|
||||
|
||||
this.Data["redirects"] = webConfig.HostRedirects
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunPost(params struct {
|
||||
ServerId int64
|
||||
WebId int64
|
||||
HostRedirectsJSON []byte
|
||||
|
||||
Must *actions.Must
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.ServerRedirect_LogUpdateRedirects, params.WebId)
|
||||
|
||||
_, err := this.RPC().HTTPWebRPC().UpdateHTTPWebHostRedirects(this.UserContext(), &pb.UpdateHTTPWebHostRedirectsRequest{
|
||||
HttpWebId: params.WebId,
|
||||
HostRedirectsJSON: params.HostRedirectsJSON,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package redirects
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/default/servers/serverutils"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/helpers"
|
||||
"github.com/iwind/TeaGo"
|
||||
)
|
||||
|
||||
func init() {
|
||||
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
||||
server.
|
||||
Helper(helpers.NewUserMustAuth("")).
|
||||
Helper(serverutils.NewServerHelper()).
|
||||
Prefix("/servers/server/settings/redirects").
|
||||
GetPost("", new(IndexAction)).
|
||||
GetPost("/createPopup", new(CreatePopupAction)).
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package uam
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/userconfigs"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
)
|
||||
|
||||
type IndexAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *IndexAction) Init() {
|
||||
this.Nav("", "setting", "index")
|
||||
this.SecondMenu("referer")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct {
|
||||
ServerId int64
|
||||
}) {
|
||||
this.Data["serverId"] = params.ServerId
|
||||
this.Data["featureIsOn"] = this.ValidateFeature(userconfigs.UserFeatureCodeServerReferers, params.ServerId)
|
||||
|
||||
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithServerId(this.UserContext(), params.ServerId)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Data["webId"] = webConfig.Id
|
||||
|
||||
var referersConfig = webConfig.Referers
|
||||
if referersConfig == nil {
|
||||
referersConfig = &serverconfigs.ReferersConfig{
|
||||
IsPrior: false,
|
||||
IsOn: false,
|
||||
AllowEmpty: true,
|
||||
AllowSameDomain: true,
|
||||
AllowDomains: nil,
|
||||
CheckOrigin: true,
|
||||
}
|
||||
}
|
||||
|
||||
this.Data["referersConfig"] = referersConfig
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunPost(params struct {
|
||||
WebId int64
|
||||
ReferersJSON []byte
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
// 获取网站ID
|
||||
serverId, err := this.FindServerIdWithWebId(params.WebId)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
if !this.ValidateFeature(userconfigs.UserFeatureCodeServerReferers, serverId) {
|
||||
this.Fail("permission denied")
|
||||
return
|
||||
}
|
||||
|
||||
defer this.CreateLogInfo(codes.ServerReferer_LogUpdateReferers, params.WebId)
|
||||
|
||||
_, err = this.RPC().HTTPWebRPC().UpdateHTTPWebReferers(this.UserContext(), &pb.UpdateHTTPWebReferersRequest{
|
||||
HttpWebId: params.WebId,
|
||||
ReferersJSON: params.ReferersJSON,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package uam
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/default/servers/serverutils"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/helpers"
|
||||
"github.com/iwind/TeaGo"
|
||||
)
|
||||
|
||||
func init() {
|
||||
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
||||
server.
|
||||
Helper(helpers.NewUserMustAuth("")).
|
||||
Helper(serverutils.NewServerHelper()).
|
||||
Prefix("/servers/server/settings/referers").
|
||||
GetPost("", new(IndexAction)).
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package remoteAddr
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type IndexAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *IndexAction) Init() {
|
||||
this.Nav("", "setting", "index")
|
||||
this.SecondMenu("remoteAddr")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct {
|
||||
ServerId int64
|
||||
}) {
|
||||
// 服务分组设置
|
||||
groupResp, err := this.RPC().ServerGroupRPC().FindEnabledServerGroupConfigInfo(this.UserContext(), &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.UserContext(), params.ServerId)
|
||||
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())
|
||||
return
|
||||
}
|
||||
|
||||
remoteAddrConfig.Value = strings.TrimSpace(remoteAddrConfig.Value)
|
||||
|
||||
switch remoteAddrConfig.Type {
|
||||
case serverconfigs.HTTPRemoteAddrTypeRequestHeader:
|
||||
if len(remoteAddrConfig.RequestHeaderName) == 0 {
|
||||
this.FailField("requestHeaderName", "请输入请求报头")
|
||||
return
|
||||
}
|
||||
if !regexp.MustCompile(`^[\w-_,]+$`).MatchString(remoteAddrConfig.RequestHeaderName) {
|
||||
this.FailField("requestHeaderName", "请求报头中只能含有数字、英文字母、下划线、中划线")
|
||||
return
|
||||
}
|
||||
remoteAddrConfig.Value = "${header." + remoteAddrConfig.RequestHeaderName + "}"
|
||||
case serverconfigs.HTTPRemoteAddrTypeVariable:
|
||||
if len(remoteAddrConfig.Value) == 0 {
|
||||
this.FailField("value", "请输入自定义变量")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
err = remoteAddrConfig.Init()
|
||||
if err != nil {
|
||||
this.Fail("配置校验失败:" + err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
remoteAddrJSON, err := json.Marshal(remoteAddrConfig)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
_, err = this.RPC().HTTPWebRPC().UpdateHTTPWebRemoteAddr(this.UserContext(), &pb.UpdateHTTPWebRemoteAddrRequest{
|
||||
HttpWebId: params.WebId,
|
||||
RemoteAddrJSON: remoteAddrJSON,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package remoteAddr
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/default/servers/serverutils"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/helpers"
|
||||
"github.com/iwind/TeaGo"
|
||||
)
|
||||
|
||||
func init() {
|
||||
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
||||
server.
|
||||
Helper(helpers.NewUserMustAuth("")).
|
||||
Helper(serverutils.NewServerHelper()).
|
||||
Prefix("/servers/server/settings/remoteAddr").
|
||||
GetPost("", new(IndexAction)).
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package requestlimit
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/userconfigs"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
)
|
||||
|
||||
type IndexAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *IndexAction) Init() {
|
||||
this.Nav("", "setting", "index")
|
||||
this.SecondMenu("requestLimit")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct {
|
||||
ServerId int64
|
||||
}) {
|
||||
this.Data["featureIsOn"] = this.ValidateFeature(userconfigs.UserFeatureCodeServerRequestLimit, params.ServerId)
|
||||
|
||||
// 服务分组设置
|
||||
groupResp, err := this.RPC().ServerGroupRPC().FindEnabledServerGroupConfigInfo(this.UserContext(), &pb.FindEnabledServerGroupConfigInfoRequest{
|
||||
ServerId: params.ServerId,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
this.Data["hasGroupConfig"] = groupResp.HasRequestLimitConfig
|
||||
this.Data["groupSettingURL"] = "/servers/groups/group/settings/requestLimit?groupId=" + types.String(groupResp.ServerGroupId)
|
||||
|
||||
this.Data["serverId"] = params.ServerId
|
||||
|
||||
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithServerId(this.UserContext(), params.ServerId)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Data["webId"] = webConfig.Id
|
||||
this.Data["requestLimitConfig"] = webConfig.RequestLimit
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunPost(params struct {
|
||||
WebId int64
|
||||
RequestLimitJSON []byte
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
// 获取网站ID
|
||||
serverId, err := this.FindServerIdWithWebId(params.WebId)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
if !this.ValidateFeature(userconfigs.UserFeatureCodeServerRequestLimit, serverId) {
|
||||
this.Fail("permission denied")
|
||||
return
|
||||
}
|
||||
|
||||
defer this.CreateLogInfo(codes.ServerRequestLimit_LogUpdateRequestLimitSettings, params.WebId)
|
||||
|
||||
_, err = this.RPC().HTTPWebRPC().UpdateHTTPWebRequestLimit(this.UserContext(), &pb.UpdateHTTPWebRequestLimitRequest{
|
||||
HttpWebId: params.WebId,
|
||||
RequestLimitJSON: params.RequestLimitJSON,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package requestlimit
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/default/servers/serverutils"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/helpers"
|
||||
"github.com/iwind/TeaGo"
|
||||
)
|
||||
|
||||
func init() {
|
||||
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
||||
server.
|
||||
Helper(helpers.NewUserMustAuth("")).
|
||||
Helper(serverutils.NewServerHelper()).
|
||||
Prefix("/servers/server/settings/requestLimit").
|
||||
GetPost("", new(IndexAction)).
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package requestScripts
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/userconfigs"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
)
|
||||
|
||||
type IndexAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *IndexAction) Init() {
|
||||
this.Nav("", "setting", "index")
|
||||
this.SecondMenu("requestScripts")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct {
|
||||
ServerId int64
|
||||
}) {
|
||||
this.Data["featureIsOn"] = this.ValidateFeature(userconfigs.UserFeatureCodeServerScript, params.ServerId)
|
||||
|
||||
// 服务分组设置
|
||||
groupResp, err := this.RPC().ServerGroupRPC().FindEnabledServerGroupConfigInfo(this.UserContext(), &pb.FindEnabledServerGroupConfigInfoRequest{
|
||||
ServerId: params.ServerId,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
this.Data["hasGroupConfig"] = groupResp.HasRequestScriptsConfig
|
||||
this.Data["groupSettingURL"] = "/servers/groups/group/settings/requestScripts?groupId=" + types.String(groupResp.ServerGroupId)
|
||||
|
||||
this.Data["serverId"] = params.ServerId
|
||||
|
||||
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithServerId(this.UserContext(), params.ServerId)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Data["webId"] = webConfig.Id
|
||||
this.Data["requestScriptsConfig"] = webConfig.RequestScripts
|
||||
|
||||
// 审核状态
|
||||
var auditingStatusMaps = []maps.Map{}
|
||||
|
||||
if webConfig.RequestScripts != nil {
|
||||
for _, group := range webConfig.RequestScripts.AllGroups() {
|
||||
for _, script := range group.Scripts {
|
||||
if len(script.AuditingCodeMD5) > 0 {
|
||||
userScriptResp, err := this.RPC().UserScriptRPC().FindUserScriptWithMD5(this.UserContext(), &pb.FindUserScriptWithMD5Request{CodeMD5: script.AuditingCodeMD5})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var userScript = userScriptResp.UserScript
|
||||
if userScript != nil {
|
||||
auditingStatusMaps = append(auditingStatusMaps, maps.Map{
|
||||
"md5": script.AuditingCodeMD5,
|
||||
"isPassed": userScript.IsPassed,
|
||||
"isRejected": userScript.IsRejected,
|
||||
"rejectedReason": userScript.RejectedReason,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
this.Data["auditingStatus"] = auditingStatusMaps
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunPost(params struct {
|
||||
WebId int64
|
||||
RequestScriptsJSON []byte
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
// 获取网站ID
|
||||
serverId, err := this.FindServerIdWithWebId(params.WebId)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
if !this.ValidateFeature(userconfigs.UserFeatureCodeServerScript, serverId) {
|
||||
this.Fail("permission denied")
|
||||
return
|
||||
}
|
||||
|
||||
defer this.CreateLogInfo(codes.ServerScript_LogUpdateScripts, params.WebId)
|
||||
|
||||
var config = &serverconfigs.HTTPRequestScriptsConfig{}
|
||||
err = json.Unmarshal(params.RequestScriptsJSON, config)
|
||||
if err != nil {
|
||||
this.Fail("解析配置发生错误:" + err.Error())
|
||||
}
|
||||
|
||||
err = config.Init()
|
||||
if err != nil {
|
||||
this.Fail("解析配置发生错误:" + err.Error())
|
||||
}
|
||||
|
||||
_, err = this.RPC().HTTPWebRPC().UpdateHTTPWebRequestScripts(this.UserContext(), &pb.UpdateHTTPWebRequestScriptsRequest{
|
||||
HttpWebId: params.WebId,
|
||||
RequestScriptsJSON: params.RequestScriptsJSON,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package requestScripts
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/default/servers/serverutils"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/helpers"
|
||||
"github.com/iwind/TeaGo"
|
||||
)
|
||||
|
||||
func init() {
|
||||
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
||||
server.
|
||||
Helper(helpers.NewUserMustAuth("")).
|
||||
Helper(serverutils.NewServerHelper()).
|
||||
Prefix("/servers/server/settings/requestScripts").
|
||||
GetPost("", new(IndexAction)).
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
package reverseProxy
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
// IndexAction 源站列表
|
||||
type IndexAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *IndexAction) Init() {
|
||||
this.FirstMenu("index")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct {
|
||||
ServerId int64
|
||||
}) {
|
||||
serverTypeResp, err := this.RPC().ServerRPC().FindEnabledServerType(this.UserContext(), &pb.FindEnabledServerTypeRequest{ServerId: params.ServerId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var serverType = serverTypeResp.Type
|
||||
|
||||
reverseProxyResp, err := this.RPC().ServerRPC().FindAndInitServerReverseProxyConfig(this.UserContext(), &pb.FindAndInitServerReverseProxyConfigRequest{ServerId: params.ServerId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var reverseProxyRef = &serverconfigs.ReverseProxyRef{}
|
||||
err = json.Unmarshal(reverseProxyResp.ReverseProxyRefJSON, reverseProxyRef)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
this.Data["reverseProxyRef"] = reverseProxyRef
|
||||
|
||||
var reverseProxy = &serverconfigs.ReverseProxyConfig{}
|
||||
err = json.Unmarshal(reverseProxyResp.ReverseProxyJSON, reverseProxy)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
this.Data["reverseProxyConfig"] = reverseProxy
|
||||
|
||||
this.Data["serverType"] = serverType
|
||||
|
||||
var primaryOriginMaps = []maps.Map{}
|
||||
var backupOriginMaps = []maps.Map{}
|
||||
for _, originConfig := range reverseProxy.PrimaryOrigins {
|
||||
var domains = originConfig.Domains
|
||||
if len(domains) == 0 {
|
||||
domains = []string{}
|
||||
}
|
||||
|
||||
var m = maps.Map{
|
||||
"id": originConfig.Id,
|
||||
"weight": originConfig.Weight,
|
||||
"addr": originConfig.AddrSummary(),
|
||||
"isOSS": originConfig.IsOSS(),
|
||||
"name": originConfig.Name,
|
||||
"isOn": originConfig.IsOn,
|
||||
"domains": domains,
|
||||
"hasCert": originConfig.Cert != nil,
|
||||
"host": originConfig.RequestHost,
|
||||
"followPort": originConfig.FollowPort,
|
||||
"http2Enabled": originConfig.HTTP2Enabled,
|
||||
}
|
||||
primaryOriginMaps = append(primaryOriginMaps, m)
|
||||
}
|
||||
for _, originConfig := range reverseProxy.BackupOrigins {
|
||||
var domains = originConfig.Domains
|
||||
if len(domains) == 0 {
|
||||
domains = []string{}
|
||||
}
|
||||
|
||||
var m = maps.Map{
|
||||
"id": originConfig.Id,
|
||||
"weight": originConfig.Weight,
|
||||
"addr": originConfig.AddrSummary(),
|
||||
"isOSS": originConfig.IsOSS(),
|
||||
"name": originConfig.Name,
|
||||
"isOn": originConfig.IsOn,
|
||||
"domains": domains,
|
||||
"hasCert": originConfig.Cert != nil,
|
||||
"host": originConfig.RequestHost,
|
||||
"followPort": originConfig.FollowPort,
|
||||
"http2Enabled": originConfig.HTTP2Enabled,
|
||||
}
|
||||
backupOriginMaps = append(backupOriginMaps, m)
|
||||
}
|
||||
this.Data["primaryOrigins"] = primaryOriginMaps
|
||||
this.Data["backupOrigins"] = backupOriginMaps
|
||||
|
||||
this.Show()
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package reverseProxy
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/default/servers/serverutils"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/helpers"
|
||||
"github.com/iwind/TeaGo"
|
||||
)
|
||||
|
||||
func init() {
|
||||
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
||||
server.
|
||||
Helper(helpers.NewUserMustAuth("")).
|
||||
Helper(serverutils.NewServerHelper()).
|
||||
Data("mainTab", "setting").
|
||||
Data("secondMenuItem", "reverseProxy").
|
||||
Prefix("/servers/server/settings/reverseProxy").
|
||||
Get("", new(IndexAction)).
|
||||
GetPost("/scheduling", new(SchedulingAction)).
|
||||
GetPost("/updateSchedulingPopup", new(UpdateSchedulingPopupAction)).
|
||||
GetPost("/setting", new(SettingAction)).
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package reverseProxy
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/schedulingconfigs"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
)
|
||||
|
||||
type SchedulingAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *SchedulingAction) Init() {
|
||||
this.FirstMenu("scheduling")
|
||||
}
|
||||
|
||||
func (this *SchedulingAction) RunGet(params struct {
|
||||
ServerId int64
|
||||
}) {
|
||||
reverseProxyResp, err := this.RPC().ServerRPC().FindAndInitServerReverseProxyConfig(this.UserContext(), &pb.FindAndInitServerReverseProxyConfigRequest{ServerId: params.ServerId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
reverseProxy := &serverconfigs.ReverseProxyConfig{}
|
||||
err = json.Unmarshal(reverseProxyResp.ReverseProxyJSON, reverseProxy)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
this.Data["reverseProxyId"] = reverseProxy.Id
|
||||
|
||||
schedulingCode := reverseProxy.FindSchedulingConfig().Code
|
||||
schedulingMap := schedulingconfigs.FindSchedulingType(schedulingCode)
|
||||
if schedulingMap == nil {
|
||||
this.ErrorPage(errors.New("invalid scheduling code '" + schedulingCode + "'"))
|
||||
return
|
||||
}
|
||||
this.Data["scheduling"] = schedulingMap
|
||||
|
||||
this.Show()
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
package reverseProxy
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
)
|
||||
|
||||
type SettingAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *SettingAction) Init() {
|
||||
this.FirstMenu("setting")
|
||||
}
|
||||
|
||||
func (this *SettingAction) RunGet(params struct {
|
||||
ServerId int64
|
||||
}) {
|
||||
reverseProxyResp, err := this.RPC().ServerRPC().FindAndInitServerReverseProxyConfig(this.UserContext(), &pb.FindAndInitServerReverseProxyConfigRequest{ServerId: params.ServerId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var reverseProxyRef = &serverconfigs.ReverseProxyRef{}
|
||||
err = json.Unmarshal(reverseProxyResp.ReverseProxyRefJSON, reverseProxyRef)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
var reverseProxy = &serverconfigs.ReverseProxyConfig{}
|
||||
err = json.Unmarshal(reverseProxyResp.ReverseProxyJSON, reverseProxy)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Data["reverseProxyRef"] = reverseProxyRef
|
||||
this.Data["reverseProxyConfig"] = reverseProxy
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *SettingAction) RunPost(params struct {
|
||||
ServerId int64
|
||||
ReverseProxyRefJSON []byte
|
||||
ReverseProxyJSON []byte
|
||||
|
||||
Must *actions.Must
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.ServerReverseProxy_LogUpdateServerReverseProxySettings, params.ServerId)
|
||||
|
||||
var reverseProxyConfig = &serverconfigs.ReverseProxyConfig{}
|
||||
err := json.Unmarshal(params.ReverseProxyJSON, reverseProxyConfig)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
err = reverseProxyConfig.Init(context.TODO())
|
||||
if err != nil {
|
||||
this.Fail("配置校验失败:" + err.Error())
|
||||
}
|
||||
|
||||
// 设置是否启用
|
||||
_, err = this.RPC().ServerRPC().UpdateServerReverseProxy(this.UserContext(), &pb.UpdateServerReverseProxyRequest{
|
||||
ServerId: params.ServerId,
|
||||
ReverseProxyJSON: params.ReverseProxyRefJSON,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
// PROXY Protocol
|
||||
var proxyProtocolJSON = []byte{}
|
||||
if reverseProxyConfig.ProxyProtocol != nil {
|
||||
proxyProtocolJSON, err = json.Marshal(reverseProxyConfig.ProxyProtocol)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// 设置反向代理相关信息
|
||||
_, err = this.RPC().ReverseProxyRPC().UpdateReverseProxy(this.UserContext(), &pb.UpdateReverseProxyRequest{
|
||||
ReverseProxyId: reverseProxyConfig.Id,
|
||||
RequestHostType: types.Int32(reverseProxyConfig.RequestHostType),
|
||||
RequestHost: reverseProxyConfig.RequestHost,
|
||||
RequestHostExcludingPort: reverseProxyConfig.RequestHostExcludingPort,
|
||||
RequestURI: reverseProxyConfig.RequestURI,
|
||||
StripPrefix: reverseProxyConfig.StripPrefix,
|
||||
AutoFlush: reverseProxyConfig.AutoFlush,
|
||||
AddHeaders: reverseProxyConfig.AddHeaders,
|
||||
FollowRedirects: reverseProxyConfig.FollowRedirects,
|
||||
ProxyProtocolJSON: proxyProtocolJSON,
|
||||
Retry50X: reverseProxyConfig.Retry50X,
|
||||
Retry40X: reverseProxyConfig.Retry40X,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,163 @@
|
||||
package reverseProxy
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/schedulingconfigs"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/lists"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
)
|
||||
|
||||
// 修改调度算法
|
||||
type UpdateSchedulingPopupAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *UpdateSchedulingPopupAction) Init() {
|
||||
}
|
||||
|
||||
func (this *UpdateSchedulingPopupAction) RunGet(params struct {
|
||||
Type string
|
||||
ServerId int64
|
||||
ReverseProxyId int64
|
||||
}) {
|
||||
serverConfig, err := dao.SharedServerDAO.FindEnabledServerConfig(this.UserContext(), params.ServerId)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
if serverConfig == nil {
|
||||
this.NotFound("server", params.ServerId)
|
||||
return
|
||||
}
|
||||
|
||||
this.Data["dataType"] = params.Type
|
||||
this.Data["serverId"] = params.ServerId
|
||||
this.Data["reverseProxyId"] = params.ReverseProxyId
|
||||
|
||||
reverseProxyResp, err := this.RPC().ReverseProxyRPC().FindEnabledReverseProxyConfig(this.UserContext(), &pb.FindEnabledReverseProxyConfigRequest{
|
||||
ReverseProxyId: params.ReverseProxyId,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
configData := reverseProxyResp.ReverseProxyJSON
|
||||
|
||||
reverseProxyConfig := &serverconfigs.ReverseProxyConfig{}
|
||||
err = json.Unmarshal(configData, reverseProxyConfig)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
schedulingObject := &serverconfigs.SchedulingConfig{
|
||||
Code: "random",
|
||||
Options: nil,
|
||||
}
|
||||
if reverseProxyConfig.Scheduling != nil {
|
||||
schedulingObject = reverseProxyConfig.Scheduling
|
||||
}
|
||||
this.Data["scheduling"] = schedulingObject
|
||||
|
||||
// 调度类型
|
||||
schedulingTypes := []maps.Map{}
|
||||
for _, m := range schedulingconfigs.AllSchedulingTypes() {
|
||||
networks, ok := m["networks"]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
if !types.IsSlice(networks) {
|
||||
continue
|
||||
}
|
||||
if (serverConfig.IsHTTPFamily() && lists.Contains(networks, "http")) ||
|
||||
(serverConfig.IsTCPFamily() && lists.Contains(networks, "tcp")) ||
|
||||
(serverConfig.IsUDPFamily() && lists.Contains(networks, "udp")) {
|
||||
schedulingTypes = append(schedulingTypes, m)
|
||||
}
|
||||
}
|
||||
this.Data["schedulingTypes"] = schedulingTypes
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *UpdateSchedulingPopupAction) RunPost(params struct {
|
||||
ServerId int64
|
||||
ReverseProxyId int64
|
||||
|
||||
Type string
|
||||
HashKey string
|
||||
StickyType string
|
||||
StickyParam string
|
||||
|
||||
Must *actions.Must
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.ReverseProxy_LogUpdateReverseProxyScheduling, params.ReverseProxyId)
|
||||
|
||||
reverseProxyResp, err := this.RPC().ReverseProxyRPC().FindEnabledReverseProxyConfig(this.UserContext(), &pb.FindEnabledReverseProxyConfigRequest{ReverseProxyId: params.ReverseProxyId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
configData := reverseProxyResp.ReverseProxyJSON
|
||||
reverseProxy := &serverconfigs.ReverseProxyConfig{}
|
||||
err = json.Unmarshal(configData, reverseProxy)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
if reverseProxy.Scheduling == nil {
|
||||
reverseProxy.FindSchedulingConfig()
|
||||
}
|
||||
|
||||
options := maps.Map{}
|
||||
if params.Type == "hash" {
|
||||
params.Must.
|
||||
Field("hashKey", params.HashKey).
|
||||
Require("请输入Key")
|
||||
|
||||
options["key"] = params.HashKey
|
||||
} else if params.Type == "sticky" {
|
||||
params.Must.
|
||||
Field("stickyType", params.StickyType).
|
||||
Require("请选择参数类型").
|
||||
Field("stickyParam", params.StickyParam).
|
||||
Require("请输入参数名").
|
||||
Match("^[a-zA-Z0-9]+$", "参数名只能是英文字母和数字的组合").
|
||||
MaxCharacters(50, "参数名长度不能超过50位")
|
||||
|
||||
options["type"] = params.StickyType
|
||||
options["param"] = params.StickyParam
|
||||
}
|
||||
|
||||
if schedulingconfigs.FindSchedulingType(params.Type) == nil {
|
||||
this.Fail("不支持此种算法")
|
||||
}
|
||||
|
||||
reverseProxy.Scheduling.Code = params.Type
|
||||
reverseProxy.Scheduling.Options = options
|
||||
|
||||
schedulingData, err := json.Marshal(reverseProxy.Scheduling)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
_, err = this.RPC().ReverseProxyRPC().UpdateReverseProxyScheduling(this.UserContext(), &pb.UpdateReverseProxySchedulingRequest{
|
||||
ReverseProxyId: params.ReverseProxyId,
|
||||
SchedulingJSON: schedulingData,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
package rewrite
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/userconfigs"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
type CreatePopupAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *CreatePopupAction) Init() {
|
||||
}
|
||||
|
||||
func (this *CreatePopupAction) RunGet(params struct {
|
||||
WebId int64
|
||||
}) {
|
||||
// 获取网站ID
|
||||
serverId, err := this.FindServerIdWithWebId(params.WebId)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Data["featureIsOn"] = this.ValidateFeature(userconfigs.UserFeatureCodeServerRewriteRules, serverId)
|
||||
this.Data["webId"] = params.WebId
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *CreatePopupAction) RunPost(params struct {
|
||||
WebId int64
|
||||
Pattern string
|
||||
Replace string
|
||||
Mode string
|
||||
RedirectStatus int
|
||||
ProxyHost string
|
||||
WithQuery bool
|
||||
IsBreak bool
|
||||
IsOn bool
|
||||
|
||||
CondsJSON []byte
|
||||
|
||||
Must *actions.Must
|
||||
}) {
|
||||
params.Must.
|
||||
Field("pattern", params.Pattern).
|
||||
Require("请输入匹配规则").
|
||||
Expect(func() (message string, success bool) {
|
||||
_, err := regexp.Compile(params.Pattern)
|
||||
if err != nil {
|
||||
return "匹配规则错误:" + err.Error(), false
|
||||
}
|
||||
return "", true
|
||||
})
|
||||
|
||||
params.Must.
|
||||
Field("replace", params.Replace).
|
||||
Require("请输入目标URL")
|
||||
|
||||
// 校验匹配条件
|
||||
if len(params.CondsJSON) > 0 {
|
||||
conds := &shared.HTTPRequestCondsConfig{}
|
||||
err := json.Unmarshal(params.CondsJSON, conds)
|
||||
if err != nil {
|
||||
this.Fail("匹配条件校验失败:" + err.Error())
|
||||
}
|
||||
|
||||
err = conds.Init()
|
||||
if err != nil {
|
||||
this.Fail("匹配条件校验失败:" + err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
// web配置
|
||||
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithId(this.UserContext(), params.WebId)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
// 创建
|
||||
createResp, err := this.RPC().HTTPRewriteRuleRPC().CreateHTTPRewriteRule(this.UserContext(), &pb.CreateHTTPRewriteRuleRequest{
|
||||
Pattern: params.Pattern,
|
||||
Replace: params.Replace,
|
||||
Mode: params.Mode,
|
||||
RedirectStatus: types.Int32(params.RedirectStatus),
|
||||
ProxyHost: params.ProxyHost,
|
||||
WithQuery: params.WithQuery,
|
||||
IsBreak: params.IsBreak,
|
||||
IsOn: params.IsOn,
|
||||
CondsJSON: params.CondsJSON,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
ref := &serverconfigs.HTTPRewriteRef{
|
||||
IsOn: true,
|
||||
RewriteRuleId: createResp.RewriteRuleId,
|
||||
}
|
||||
webConfig.RewriteRefs = append(webConfig.RewriteRefs, ref)
|
||||
refsJSON, err := json.Marshal(webConfig.RewriteRefs)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
// 设置Web中的重写规则
|
||||
_, err = this.RPC().HTTPWebRPC().UpdateHTTPWebRewriteRules(this.UserContext(), &pb.UpdateHTTPWebRewriteRulesRequest{
|
||||
HttpWebId: params.WebId,
|
||||
RewriteRulesJSON: refsJSON,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
// 日志
|
||||
defer this.CreateLogInfo(codes.HTTPRewriteRule_LogCreateRewriteRule, params.WebId, createResp.RewriteRuleId)
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package rewrite
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
)
|
||||
|
||||
type DeleteAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *DeleteAction) RunPost(params struct {
|
||||
WebId int64
|
||||
RewriteRuleId int64
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.HTTPRewriteRule_LogDeleteRewriteRule, params.WebId, params.RewriteRuleId)
|
||||
|
||||
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithId(this.UserContext(), params.WebId)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
refs := []*serverconfigs.HTTPRewriteRef{}
|
||||
for _, ref := range webConfig.RewriteRefs {
|
||||
if ref.RewriteRuleId == params.RewriteRuleId {
|
||||
continue
|
||||
}
|
||||
refs = append(refs, ref)
|
||||
}
|
||||
|
||||
refsJSON, err := json.Marshal(refs)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
_, err = this.RPC().HTTPWebRPC().UpdateHTTPWebRewriteRules(this.UserContext(), &pb.UpdateHTTPWebRewriteRulesRequest{
|
||||
HttpWebId: params.WebId,
|
||||
RewriteRulesJSON: refsJSON,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package rewrite
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/userconfigs"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
)
|
||||
|
||||
type IndexAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *IndexAction) Init() {
|
||||
this.Nav("", "setting", "index")
|
||||
this.SecondMenu("rewrite")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct {
|
||||
ServerId int64
|
||||
}) {
|
||||
this.Data["featureIsOn"] = this.ValidateFeature(userconfigs.UserFeatureCodeServerRewriteRules, params.ServerId)
|
||||
|
||||
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithServerId(this.UserContext(), params.ServerId)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
this.Data["webId"] = webConfig.Id
|
||||
|
||||
if len(webConfig.RewriteRules) == 0 {
|
||||
this.Data["rewriteRules"] = []interface{}{}
|
||||
} else {
|
||||
this.Data["rewriteRules"] = webConfig.RewriteRules
|
||||
}
|
||||
|
||||
this.Show()
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package rewrite
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/default/servers/serverutils"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/helpers"
|
||||
"github.com/iwind/TeaGo"
|
||||
)
|
||||
|
||||
func init() {
|
||||
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
||||
server.
|
||||
Helper(helpers.NewUserMustAuth("")).
|
||||
Helper(serverutils.NewServerHelper()).
|
||||
Prefix("/servers/server/settings/rewrite").
|
||||
Get("", new(IndexAction)).
|
||||
GetPost("/createPopup", new(CreatePopupAction)).
|
||||
GetPost("/updatePopup", new(UpdatePopupAction)).
|
||||
Post("/delete", new(DeleteAction)).
|
||||
Post("/sort", new(SortAction)).
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package rewrite
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
)
|
||||
|
||||
type SortAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *SortAction) RunPost(params struct {
|
||||
WebId int64
|
||||
RewriteRuleIds []int64
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.HTTPRewriteRule_LogSortRewriteRules, params.WebId)
|
||||
|
||||
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithId(this.UserContext(), params.WebId)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
refsMap := map[int64]*serverconfigs.HTTPRewriteRef{}
|
||||
for _, ref := range webConfig.RewriteRefs {
|
||||
refsMap[ref.RewriteRuleId] = ref
|
||||
}
|
||||
newRefs := []*serverconfigs.HTTPRewriteRef{}
|
||||
for _, rewriteRuleId := range params.RewriteRuleIds {
|
||||
ref, ok := refsMap[rewriteRuleId]
|
||||
if ok {
|
||||
newRefs = append(newRefs, ref)
|
||||
}
|
||||
}
|
||||
refsJSON, err := json.Marshal(newRefs)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
_, err = this.RPC().HTTPWebRPC().UpdateHTTPWebRewriteRules(this.UserContext(), &pb.UpdateHTTPWebRewriteRulesRequest{
|
||||
HttpWebId: params.WebId,
|
||||
RewriteRulesJSON: refsJSON,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
package rewrite
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
type UpdatePopupAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *UpdatePopupAction) Init() {
|
||||
}
|
||||
|
||||
func (this *UpdatePopupAction) RunGet(params struct {
|
||||
WebId int64
|
||||
RewriteRuleId int64
|
||||
}) {
|
||||
this.Data["webId"] = params.WebId
|
||||
|
||||
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithId(this.UserContext(), params.WebId)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
isFound := false
|
||||
for _, rewriteRule := range webConfig.RewriteRules {
|
||||
if rewriteRule.Id == params.RewriteRuleId {
|
||||
this.Data["rewriteRule"] = rewriteRule
|
||||
isFound = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !isFound {
|
||||
this.WriteString("找不到要修改的重写规则")
|
||||
return
|
||||
}
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *UpdatePopupAction) RunPost(params struct {
|
||||
WebId int64
|
||||
RewriteRuleId int64
|
||||
Pattern string
|
||||
Replace string
|
||||
Mode string
|
||||
RedirectStatus int
|
||||
ProxyHost string
|
||||
WithQuery bool
|
||||
IsBreak bool
|
||||
IsOn bool
|
||||
CondsJSON []byte
|
||||
|
||||
Must *actions.Must
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.HTTPRewriteRule_LogUpdateRewriteRule, params.WebId, params.RewriteRuleId)
|
||||
|
||||
params.Must.
|
||||
Field("pattern", params.Pattern).
|
||||
Require("请输入匹配规则").
|
||||
Expect(func() (message string, success bool) {
|
||||
_, err := regexp.Compile(params.Pattern)
|
||||
if err != nil {
|
||||
return "匹配规则错误:" + err.Error(), false
|
||||
}
|
||||
return "", true
|
||||
})
|
||||
|
||||
params.Must.
|
||||
Field("replace", params.Replace).
|
||||
Require("请输入目标URL")
|
||||
|
||||
// 校验匹配条件
|
||||
if len(params.CondsJSON) > 0 {
|
||||
conds := &shared.HTTPRequestCondsConfig{}
|
||||
err := json.Unmarshal(params.CondsJSON, conds)
|
||||
if err != nil {
|
||||
this.Fail("匹配条件校验失败:" + err.Error())
|
||||
}
|
||||
|
||||
err = conds.Init()
|
||||
if err != nil {
|
||||
this.Fail("匹配条件校验失败:" + err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
// 修改
|
||||
_, err := this.RPC().HTTPRewriteRuleRPC().UpdateHTTPRewriteRule(this.UserContext(), &pb.UpdateHTTPRewriteRuleRequest{
|
||||
RewriteRuleId: params.RewriteRuleId,
|
||||
Pattern: params.Pattern,
|
||||
Replace: params.Replace,
|
||||
Mode: params.Mode,
|
||||
RedirectStatus: types.Int32(params.RedirectStatus),
|
||||
ProxyHost: params.ProxyHost,
|
||||
WithQuery: params.WithQuery,
|
||||
IsBreak: params.IsBreak,
|
||||
IsOn: params.IsOn,
|
||||
CondsJSON: params.CondsJSON,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package serverNames
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
)
|
||||
|
||||
// 审核域名
|
||||
type AuditAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *AuditAction) RunPost(params struct {
|
||||
ServerId int64
|
||||
AuditingOK bool
|
||||
AuditingReason string
|
||||
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.Server_LogSubmitAuditingServer, params.ServerId)
|
||||
|
||||
if !params.AuditingOK && len(params.AuditingReason) == 0 {
|
||||
this.FailField("auditingReason", "请输入审核不通过原因")
|
||||
}
|
||||
|
||||
_, err := this.RPC().ServerRPC().UpdateServerNamesAuditing(this.UserContext(), &pb.UpdateServerNamesAuditingRequest{
|
||||
ServerId: params.ServerId,
|
||||
AuditingResult: &pb.ServerNameAuditingResult{
|
||||
IsOk: params.AuditingOK,
|
||||
Reason: params.AuditingReason,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,161 @@
|
||||
package serverNames
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// IndexAction 域名管理
|
||||
type IndexAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *IndexAction) Init() {
|
||||
this.FirstMenu("index")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct {
|
||||
ServerId int64
|
||||
}) {
|
||||
serverNamesResp, err := this.RPC().ServerRPC().FindServerNames(this.UserContext(), &pb.FindServerNamesRequest{ServerId: params.ServerId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
var serverNamesConfig = []*serverconfigs.ServerNameConfig{}
|
||||
this.Data["isAuditing"] = serverNamesResp.IsAuditing
|
||||
this.Data["auditingResult"] = maps.Map{
|
||||
"isOk": true,
|
||||
}
|
||||
if serverNamesResp.IsAuditing {
|
||||
serverNamesResp.ServerNamesJSON = serverNamesResp.AuditingServerNamesJSON
|
||||
} else if serverNamesResp.AuditingResult != nil {
|
||||
if !serverNamesResp.AuditingResult.IsOk {
|
||||
serverNamesResp.ServerNamesJSON = serverNamesResp.AuditingServerNamesJSON
|
||||
}
|
||||
|
||||
this.Data["auditingResult"] = maps.Map{
|
||||
"isOk": serverNamesResp.AuditingResult.IsOk,
|
||||
"reason": serverNamesResp.AuditingResult.Reason,
|
||||
"createdTime": timeutil.FormatTime("Y-m-d H:i:s", serverNamesResp.AuditingResult.CreatedAt),
|
||||
}
|
||||
}
|
||||
if len(serverNamesResp.ServerNamesJSON) > 0 {
|
||||
err := json.Unmarshal(serverNamesResp.ServerNamesJSON, &serverNamesConfig)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
this.Data["serverNames"] = serverNamesConfig
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunPost(params struct {
|
||||
ServerId int64
|
||||
ServerNames string
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
// 记录日志
|
||||
defer this.CreateLogInfo(codes.Server_ServerNamesLogUpdateServerNames, params.ServerId)
|
||||
|
||||
// 检查用户所在集群
|
||||
clusterIdResp, err := this.RPC().UserRPC().FindUserNodeClusterId(this.UserContext(), &pb.FindUserNodeClusterIdRequest{UserId: this.UserId()})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var clusterId = clusterIdResp.NodeClusterId
|
||||
|
||||
var serverNames = []*serverconfigs.ServerNameConfig{}
|
||||
err = json.Unmarshal([]byte(params.ServerNames), &serverNames)
|
||||
if err != nil {
|
||||
this.Fail("域名解析失败:" + err.Error())
|
||||
}
|
||||
serverconfigs.NormalizeServerNames(serverNames)
|
||||
|
||||
// 检查域名是否已经存在
|
||||
var allServerNames = serverconfigs.PlainServerNames(serverNames)
|
||||
if len(allServerNames) > 0 {
|
||||
dupResp, err := this.RPC().ServerRPC().CheckServerNameDuplicationInNodeCluster(this.UserContext(), &pb.CheckServerNameDuplicationInNodeClusterRequest{
|
||||
ServerNames: allServerNames,
|
||||
NodeClusterId: clusterId,
|
||||
ExcludeServerId: params.ServerId,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if len(dupResp.DuplicatedServerNames) > 0 {
|
||||
this.Fail("域名 " + strings.Join(dupResp.DuplicatedServerNames, ", ") + " 已经被其他网站所占用,不能重复使用")
|
||||
}
|
||||
}
|
||||
|
||||
// 检查套餐限制
|
||||
userPlanResp, err := this.RPC().ServerRPC().FindServerUserPlan(this.UserContext(), &pb.FindServerUserPlanRequest{ServerId: params.ServerId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var userPlan = userPlanResp.UserPlan
|
||||
if userPlan != nil && userPlan.Id > 0 {
|
||||
if userPlan.DayTo < timeutil.Format("Y-m-d") {
|
||||
this.Fail("当前网站绑定的套餐已过期,请续费或更换套餐后再操作")
|
||||
return
|
||||
}
|
||||
|
||||
var plan = userPlan.Plan
|
||||
if plan == nil {
|
||||
this.Fail("当前网站绑定的套餐已失效,请续费或更换套餐后再操作")
|
||||
return
|
||||
}
|
||||
|
||||
var countServerNames = len(serverconfigs.PlainServerNames(serverNames))
|
||||
if countServerNames > 0 {
|
||||
if plan.TotalServerNames > 0 {
|
||||
totalServerNamesResp, err := this.RPC().ServerRPC().CountAllServerNamesWithUserId(this.UserContext(), &pb.CountAllServerNamesWithUserIdRequest{
|
||||
UserId: this.UserId(),
|
||||
UserPlanId: userPlan.Id,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var totalServerNames = totalServerNamesResp.Count
|
||||
if totalServerNames+int64(countServerNames) > int64(plan.TotalServerNames) {
|
||||
this.Fail("当前域名数量超出当前套餐可以绑定的域名数量(" + types.String(plan.TotalServerNames) + ")")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if plan.TotalServerNamesPerServer > 0 {
|
||||
if countServerNames > types.Int(plan.TotalServerNamesPerServer) {
|
||||
this.Fail("当前网站域名数量超出套餐限制(" + types.String(plan.TotalServerNamesPerServer) + ")")
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_, err = this.RPC().ServerRPC().UpdateServerNames(this.UserContext(), &pb.UpdateServerNamesRequest{
|
||||
ServerId: params.ServerId,
|
||||
ServerNamesJSON: []byte(params.ServerNames),
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package serverNames
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/default/servers/serverutils"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/helpers"
|
||||
"github.com/iwind/TeaGo"
|
||||
)
|
||||
|
||||
func init() {
|
||||
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
||||
server.
|
||||
Helper(helpers.NewUserMustAuth("")).
|
||||
Helper(serverutils.NewServerHelper()).
|
||||
Data("mainTab", "setting").
|
||||
Data("secondMenuItem", "serverName").
|
||||
Prefix("/servers/server/settings/serverNames").
|
||||
GetPost("", new(IndexAction)).
|
||||
Post("/audit", new(AuditAction)).
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package stat
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
|
||||
"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 {
|
||||
ServerId int64
|
||||
}) {
|
||||
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithServerId(this.UserContext(), params.ServerId)
|
||||
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(codes.ServerStat_LogUpdateStatSettings, params.WebId)
|
||||
|
||||
// TODO 校验配置
|
||||
|
||||
_, err := this.RPC().HTTPWebRPC().UpdateHTTPWebStat(this.UserContext(), &pb.UpdateHTTPWebStatRequest{
|
||||
HttpWebId: params.WebId,
|
||||
StatJSON: params.StatJSON,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package stat
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/actions/default/servers/serverutils"
|
||||
"github.com/TeaOSLab/EdgeUser/internal/web/helpers"
|
||||
"github.com/iwind/TeaGo"
|
||||
)
|
||||
|
||||
func init() {
|
||||
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
||||
server.
|
||||
Helper(helpers.NewUserMustAuth("")).
|
||||
Helper(serverutils.NewServerHelper()).
|
||||
Prefix("/servers/server/settings/stat").
|
||||
GetPost("", new(IndexAction)).
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user