This commit is contained in:
unknown
2026-02-04 20:27:13 +08:00
commit 3b042d1dad
9410 changed files with 1488147 additions and 0 deletions

View File

@@ -0,0 +1,158 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
//go:build !plus
package access
import (
"encoding/json"
teaconst "github.com/TeaOSLab/EdgeAdmin/internal/const"
"github.com/TeaOSLab/EdgeAdmin/internal/utils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
"github.com/iwind/TeaGo/actions"
"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
// 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 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()
}
var method serverconfigs.HTTPAuthMethodInterface
switch params.Type {
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)
paramsJSON, err := json.Marshal(method)
if err != nil {
this.ErrorPage(err)
return
}
var paramsMap map[string]interface{}
err = json.Unmarshal(paramsJSON, &paramsMap)
if err != nil {
this.ErrorPage(err)
return
}
createResp, err := this.RPC().HTTPAuthPolicyRPC().CreateHTTPAuthPolicy(this.AdminContext(), &pb.CreateHTTPAuthPolicyRequest{
Name: params.Name,
Type: params.Type,
ParamsJSON: paramsJSON,
})
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()
}

View File

@@ -0,0 +1,245 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
//go:build plus
package access
import (
"encoding/json"
teaconst "github.com/TeaOSLab/EdgeAdmin/internal/const"
"github.com/TeaOSLab/EdgeAdmin/internal/utils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
"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{}) {
var authMethods = []*serverconfigs.HTTPAuthTypeDefinition{}
for _, method := range serverconfigs.FindAllHTTPAuthTypes(teaconst.Role) {
if !method.IsPlus || (method.IsPlus && teaconst.IsPlus) {
authMethods = append(authMethods, method)
}
}
this.Data["authTypes"] = authMethods
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, &paramsMap)
if err != nil {
this.ErrorPage(err)
return
}
createResp, err := this.RPC().HTTPAuthPolicyRPC().CreateHTTPAuthPolicy(this.AdminContext(), &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()
}

View File

@@ -0,0 +1,105 @@
package access
import (
"encoding/json"
teaconst "github.com/TeaOSLab/EdgeAdmin/internal/const"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"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/iwind/TeaGo/actions"
"github.com/iwind/TeaGo/lists"
)
type IndexAction struct {
actionutils.ParentAction
}
func (this *IndexAction) Init() {
this.Nav("", "setting", "index")
this.SecondMenu("access")
}
func (this *IndexAction) RunGet(params struct {
ServerId int64
}) {
// 只有HTTP服务才支持
if this.FilterHTTPFamily() {
return
}
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithServerId(this.AdminContext(), params.ServerId)
if err != nil {
this.ErrorPage(err)
return
}
this.Data["webId"] = webConfig.Id
// 移除不存在的鉴权方法
var allTypes = []string{}
for _, def := range serverconfigs.FindAllHTTPAuthTypes(teaconst.Role) {
allTypes = append(allTypes, def.Code)
}
if webConfig.Auth != nil {
var refs = webConfig.Auth.PolicyRefs
var realRefs = []*serverconfigs.HTTPAuthPolicyRef{}
for _, ref := range refs {
if ref.AuthPolicy == nil {
continue
}
if !lists.ContainsString(allTypes, ref.AuthPolicy.Type) {
continue
}
realRefs = append(realRefs, ref)
}
webConfig.Auth.PolicyRefs = realRefs
}
this.Data["authConfig"] = webConfig.Auth
this.Show()
}
func (this *IndexAction) RunPost(params struct {
WebId int64
AuthJSON []byte
Must *actions.Must
}) {
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.AdminContext(), &pb.UpdateHTTPWebAuthRequest{
HttpWebId: params.WebId,
AuthJSON: configJSON,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -0,0 +1,22 @@
package access
import (
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/serverutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
"github.com/iwind/TeaGo"
)
func init() {
TeaGo.BeforeStart(func(server *TeaGo.Server) {
server.
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeServer)).
Helper(serverutils.NewServerHelper()).
Prefix("/servers/server/settings/access").
GetPost("", new(IndexAction)).
GetPost("/createPopup", new(CreatePopupAction)).
GetPost("/updatePopup", new(UpdatePopupAction)).
Post("/random", new(RandomAction)).
EndAll()
})
}

View File

@@ -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/EdgeAdmin/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()
}

View File

@@ -0,0 +1,202 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
//go:build !plus
package access
import (
"encoding/json"
teaconst "github.com/TeaOSLab/EdgeAdmin/internal/const"
"github.com/TeaOSLab/EdgeAdmin/internal/utils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
"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
}) {
this.Data["authTypes"] = serverconfigs.FindAllHTTPAuthTypes(teaconst.Role)
policyResp, err := this.RPC().HTTPAuthPolicyRPC().FindEnabledHTTPAuthPolicy(this.AdminContext(), &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
// 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.AdminContext(), &pb.FindEnabledHTTPAuthPolicyRequest{HttpAuthPolicyId: params.PolicyId})
if err != nil {
this.ErrorPage(err)
return
}
var policy = policyResp.HttpAuthPolicy
if policy == nil {
this.NotFound("httpAuthPolicy", params.PolicyId)
return
}
policyType := policy.Type
params.Must.
Field("name", params.Name).
Require("请输入名称")
// 扩展名
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()
}
var ref = &serverconfigs.HTTPAuthPolicyRef{IsOn: true}
var method serverconfigs.HTTPAuthMethodInterface
switch policyType {
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("不支持的鉴权类型'" + policyType + "'")
}
if method == nil {
this.Fail("无法找到对应的鉴权方式")
}
method.SetExts(exts)
method.SetDomains(domains)
paramsJSON, err := json.Marshal(method)
if err != nil {
this.ErrorPage(err)
return
}
var paramsMap map[string]interface{}
err = json.Unmarshal(paramsJSON, &paramsMap)
if err != nil {
this.ErrorPage(err)
return
}
_, err = this.RPC().HTTPAuthPolicyRPC().UpdateHTTPAuthPolicy(this.AdminContext(), &pb.UpdateHTTPAuthPolicyRequest{
HttpAuthPolicyId: params.PolicyId,
Name: params.Name,
ParamsJSON: paramsJSON,
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()
}

View File

@@ -0,0 +1,288 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
//go:build plus
package access
import (
"encoding/json"
teaconst "github.com/TeaOSLab/EdgeAdmin/internal/const"
"github.com/TeaOSLab/EdgeAdmin/internal/utils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
"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.HTTPAuthTypeDefinition{}
for _, method := range serverconfigs.FindAllHTTPAuthTypes(teaconst.Role) {
if !method.IsPlus || (method.IsPlus && teaconst.IsPlus) {
authMethods = append(authMethods, method)
}
}
this.Data["authTypes"] = authMethods
policyResp, err := this.RPC().HTTPAuthPolicyRPC().FindEnabledHTTPAuthPolicy(this.AdminContext(), &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.AdminContext(), &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, &paramsMap)
if err != nil {
this.ErrorPage(err)
return
}
_, err = this.RPC().HTTPAuthPolicyRPC().UpdateHTTPAuthPolicy(this.AdminContext(), &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()
}

View File

@@ -0,0 +1,78 @@
package accessLog
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"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/iwind/TeaGo/actions"
"github.com/iwind/TeaGo/types"
)
type IndexAction struct {
actionutils.ParentAction
}
func (this *IndexAction) Init() {
this.Nav("", "setting", "index")
this.SecondMenu("accessLog")
}
func (this *IndexAction) RunGet(params struct {
ServerId int64
}) {
// 只有HTTP服务才支持
if this.FilterHTTPFamily() {
return
}
// 网站分组设置
groupResp, err := this.RPC().ServerGroupRPC().FindEnabledServerGroupConfigInfo(this.AdminContext(), &pb.FindEnabledServerGroupConfigInfoRequest{
ServerId: params.ServerId,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Data["hasGroupConfig"] = groupResp.HasAccessLogConfig
this.Data["groupSettingURL"] = "/servers/groups/group/settings/accessLog?groupId=" + types.String(groupResp.ServerGroupId)
// 获取配置
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithServerId(this.AdminContext(), params.ServerId)
if err != nil {
this.ErrorPage(err)
return
}
this.Data["webId"] = webConfig.Id
this.Data["accessLogConfig"] = webConfig.AccessLogRef
// 通用变量
this.Data["fields"] = serverconfigs.HTTPAccessLogFields
this.Data["defaultFieldCodes"] = serverconfigs.HTTPAccessLogDefaultFieldsCodes
this.Show()
}
func (this *IndexAction) RunPost(params struct {
WebId int64
AccessLogJSON []byte
Must *actions.Must
}) {
// 日志
defer this.CreateLogInfo(codes.ServerAccessLog_LogUpdateAccessLogSetting, params.WebId)
// TODO 检查参数
_, err := this.RPC().HTTPWebRPC().UpdateHTTPWebAccessLog(this.AdminContext(), &pb.UpdateHTTPWebAccessLogRequest{
HttpWebId: params.WebId,
AccessLogJSON: params.AccessLogJSON,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

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

View File

@@ -0,0 +1,88 @@
package cache
import (
"encoding/json"
"github.com/TeaOSLab/EdgeAdmin/internal/utils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
"github.com/iwind/TeaGo/actions"
)
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 (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()
}

View File

@@ -0,0 +1,154 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package cache
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/components/cache/cacheutils"
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/actions"
"github.com/iwind/TeaGo/lists"
"github.com/iwind/TeaGo/maps"
"github.com/iwind/TeaGo/types"
"strings"
)
type FetchAction struct {
actionutils.ParentAction
}
func (this *FetchAction) Init() {
this.Nav("", "setting", "fetch")
this.SecondMenu("cache")
}
func (this *FetchAction) RunGet(params struct {
ServerId int64
}) {
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithServerId(this.AdminContext(), params.ServerId)
if err != nil {
this.ErrorPage(err)
return
}
this.Data["webId"] = webConfig.Id
this.Data["webConfig"] = webConfig
this.Show()
}
func (this *FetchAction) RunPost(params struct {
ServerId int64
WebId int64
Keys string
Must *actions.Must
}) {
// 创建日志
defer this.CreateLogInfo(codes.ServerCache_LogFetchCaches, params.ServerId)
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithId(this.AdminContext(), params.WebId)
if err != nil {
this.ErrorPage(err)
return
}
if webConfig == nil {
this.NotFound("httpWeb", params.WebId)
return
}
var cache = webConfig.Cache
if cache == nil || !cache.IsOn {
this.Fail("当前没有开启缓存")
}
serverResp, err := this.RPC().ServerRPC().FindEnabledUserServerBasic(this.AdminContext(), &pb.FindEnabledUserServerBasicRequest{ServerId: params.ServerId})
if err != nil {
this.ErrorPage(err)
return
}
var server = serverResp.Server
if server == nil || server.NodeCluster == nil {
this.NotFound("server", params.ServerId)
return
}
var clusterId = server.NodeCluster.Id
clusterResp, err := this.RPC().NodeClusterRPC().FindEnabledNodeCluster(this.AdminContext(), &pb.FindEnabledNodeClusterRequest{NodeClusterId: clusterId})
if err != nil {
this.ErrorPage(err)
return
}
var cluster = clusterResp.NodeCluster
if cluster == nil {
this.NotFound("nodeCluster", clusterId)
return
}
var cachePolicyId = cluster.HttpCachePolicyId
if cachePolicyId == 0 {
this.Fail("当前集群没有设置缓存策略")
}
cachePolicyResp, err := this.RPC().HTTPCachePolicyRPC().FindEnabledHTTPCachePolicyConfig(this.AdminContext(), &pb.FindEnabledHTTPCachePolicyConfigRequest{HttpCachePolicyId: cachePolicyId})
if err != nil {
this.ErrorPage(err)
return
}
cachePolicyJSON := cachePolicyResp.HttpCachePolicyJSON
if len(cachePolicyJSON) == 0 {
this.Fail("找不到要操作的缓存策略")
}
if len(params.Keys) == 0 {
this.Fail("请输入要预热的Key列表")
}
realKeys := []string{}
for _, key := range strings.Split(params.Keys, "\n") {
key = strings.TrimSpace(key)
if len(key) == 0 {
continue
}
if lists.ContainsString(realKeys, key) {
continue
}
realKeys = append(realKeys, key)
}
// 校验Key
validateResp, err := this.RPC().HTTPCacheTaskKeyRPC().ValidateHTTPCacheTaskKeys(this.AdminContext(), &pb.ValidateHTTPCacheTaskKeysRequest{Keys: realKeys})
if err != nil {
this.ErrorPage(err)
return
}
var failKeyMaps = []maps.Map{}
if len(validateResp.FailKeys) > 0 {
for _, key := range validateResp.FailKeys {
failKeyMaps = append(failKeyMaps, maps.Map{
"key": key.Key,
"reason": cacheutils.KeyFailReason(key.ReasonCode),
})
}
}
this.Data["failKeys"] = failKeyMaps
if len(failKeyMaps) > 0 {
this.Fail("有" + types.String(len(failKeyMaps)) + "个Key无法完成操作请删除后重试")
}
// 提交任务
_, err = this.RPC().HTTPCacheTaskRPC().CreateHTTPCacheTask(this.AdminContext(), &pb.CreateHTTPCacheTaskRequest{
Type: "fetch",
KeyType: "key",
Keys: realKeys,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -0,0 +1,170 @@
package cache
import (
"encoding/json"
"github.com/TeaOSLab/EdgeAdmin/internal/utils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/dns/domains/domainutils"
"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/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("", "setting", "index")
this.SecondMenu("cache")
}
func (this *IndexAction) RunGet(params struct {
ServerId int64
}) {
// 只有HTTP服务才支持
if this.FilterHTTPFamily() {
return
}
// 服务分组设置
groupResp, err := this.RPC().ServerGroupRPC().FindEnabledServerGroupConfigInfo(this.AdminContext(), &pb.FindEnabledServerGroupConfigInfoRequest{
ServerId: params.ServerId,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Data["hasGroupConfig"] = groupResp.HasCacheConfig
this.Data["groupSettingURL"] = "/servers/groups/group/settings/cache?groupId=" + types.String(groupResp.ServerGroupId)
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithServerId(this.AdminContext(), params.ServerId)
if err != nil {
this.ErrorPage(err)
return
}
this.Data["webId"] = webConfig.Id
this.Data["cacheConfig"] = webConfig.Cache
// 当前集群的缓存策略
cachePolicy, err := dao.SharedHTTPCachePolicyDAO.FindEnabledHTTPCachePolicyWithServerId(this.AdminContext(), 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
}
// 检查域名所属
serverIdResp, err := this.RPC().HTTPWebRPC().FindServerIdWithHTTPWebId(this.AdminContext(), &pb.FindServerIdWithHTTPWebIdRequest{HttpWebId: params.WebId})
if err != nil {
this.ErrorPage(err)
return
}
var serverId = serverIdResp.ServerId
if serverId <= 0 {
this.Fail("找不到要操作的网站")
return
}
existServerNameResp, err := this.RPC().ServerRPC().CheckServerNameInServer(this.AdminContext(), &pb.CheckServerNameInServerRequest{
ServerId: serverId,
ServerName: cacheConfig.Key.Host,
})
if err != nil {
this.ErrorPage(err)
return
}
if !existServerNameResp.Exists {
this.Fail("域名 '" + cacheConfig.Key.Host + "' 在当前网站中并未绑定,不能作为缓存主域名")
return
}
}
err = cacheConfig.Init()
if err != nil {
this.Fail("检查配置失败:" + err.Error())
}
// 去除不必要的部分
for _, cacheRef := range cacheConfig.CacheRefs {
cacheRef.CachePolicy = nil
}
cacheJSON, err := json.Marshal(cacheConfig)
if err != nil {
this.ErrorPage(err)
return
}
_, err = this.RPC().HTTPWebRPC().UpdateHTTPWebCache(this.AdminContext(), &pb.UpdateHTTPWebCacheRequest{
HttpWebId: params.WebId,
CacheJSON: cacheJSON,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -0,0 +1,23 @@
package cache
import (
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/serverutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
"github.com/iwind/TeaGo"
)
func init() {
TeaGo.BeforeStart(func(server *TeaGo.Server) {
server.
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeServer)).
Helper(serverutils.NewServerHelper()).
Prefix("/servers/server/settings/cache").
GetPost("", new(IndexAction)).
GetPost("/createPopup", new(CreatePopupAction)).
GetPost("/purge", new(PurgeAction)).
GetPost("/fetch", new(FetchAction)).
Post("/updateRefs", new(UpdateRefsAction)).
EndAll()
})
}

View File

@@ -0,0 +1,155 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package cache
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/components/cache/cacheutils"
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/actions"
"github.com/iwind/TeaGo/lists"
"github.com/iwind/TeaGo/maps"
"github.com/iwind/TeaGo/types"
"strings"
)
type PurgeAction struct {
actionutils.ParentAction
}
func (this *PurgeAction) Init() {
this.Nav("", "setting", "purge")
this.SecondMenu("cache")
}
func (this *PurgeAction) RunGet(params struct {
ServerId int64
}) {
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithServerId(this.AdminContext(), params.ServerId)
if err != nil {
this.ErrorPage(err)
return
}
this.Data["webId"] = webConfig.Id
this.Data["webConfig"] = webConfig
this.Show()
}
func (this *PurgeAction) RunPost(params struct {
ServerId int64
WebId int64
KeyType string
Keys string
Must *actions.Must
}) {
// 创建日志
defer this.CreateLogInfo(codes.ServerCache_LogPurgeCaches, params.ServerId)
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithId(this.AdminContext(), params.WebId)
if err != nil {
this.ErrorPage(err)
return
}
if webConfig == nil {
this.NotFound("httpWeb", params.WebId)
return
}
var cache = webConfig.Cache
if cache == nil || !cache.IsOn {
this.Fail("当前没有开启缓存")
}
serverResp, err := this.RPC().ServerRPC().FindEnabledUserServerBasic(this.AdminContext(), &pb.FindEnabledUserServerBasicRequest{ServerId: params.ServerId})
if err != nil {
this.ErrorPage(err)
return
}
var server = serverResp.Server
if server == nil || server.NodeCluster == nil {
this.NotFound("server", params.ServerId)
return
}
var clusterId = server.NodeCluster.Id
clusterResp, err := this.RPC().NodeClusterRPC().FindEnabledNodeCluster(this.AdminContext(), &pb.FindEnabledNodeClusterRequest{NodeClusterId: clusterId})
if err != nil {
this.ErrorPage(err)
return
}
var cluster = clusterResp.NodeCluster
if cluster == nil {
this.NotFound("nodeCluster", clusterId)
return
}
var cachePolicyId = cluster.HttpCachePolicyId
if cachePolicyId == 0 {
this.Fail("当前集群没有设置缓存策略")
}
cachePolicyResp, err := this.RPC().HTTPCachePolicyRPC().FindEnabledHTTPCachePolicyConfig(this.AdminContext(), &pb.FindEnabledHTTPCachePolicyConfigRequest{HttpCachePolicyId: cachePolicyId})
if err != nil {
this.ErrorPage(err)
return
}
cachePolicyJSON := cachePolicyResp.HttpCachePolicyJSON
if len(cachePolicyJSON) == 0 {
this.Fail("找不到要操作的缓存策略")
}
if len(params.Keys) == 0 {
this.Fail("请输入要删除的Key列表")
}
realKeys := []string{}
for _, key := range strings.Split(params.Keys, "\n") {
key = strings.TrimSpace(key)
if len(key) == 0 {
continue
}
if lists.ContainsString(realKeys, key) {
continue
}
realKeys = append(realKeys, key)
}
// 校验Key
validateResp, err := this.RPC().HTTPCacheTaskKeyRPC().ValidateHTTPCacheTaskKeys(this.AdminContext(), &pb.ValidateHTTPCacheTaskKeysRequest{Keys: realKeys})
if err != nil {
this.ErrorPage(err)
return
}
var failKeyMaps = []maps.Map{}
if len(validateResp.FailKeys) > 0 {
for _, key := range validateResp.FailKeys {
failKeyMaps = append(failKeyMaps, maps.Map{
"key": key.Key,
"reason": cacheutils.KeyFailReason(key.ReasonCode),
})
}
}
this.Data["failKeys"] = failKeyMaps
if len(failKeyMaps) > 0 {
this.Fail("有" + types.String(len(failKeyMaps)) + "个Key无法完成操作请删除后重试")
}
// 提交任务
_, err = this.RPC().HTTPCacheTaskRPC().CreateHTTPCacheTask(this.AdminContext(), &pb.CreateHTTPCacheTaskRequest{
Type: "purge",
KeyType: params.KeyType,
Keys: realKeys,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -0,0 +1,84 @@
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package cache
import (
"encoding/json"
"errors"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
)
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.AdminContext(), &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.AdminContext(), &pb.UpdateHTTPWebCacheRequest{
HttpWebId: params.WebId,
CacheJSON: cacheJSON,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Data["isUpdated"] = true
this.Success()
}

View File

@@ -0,0 +1,99 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
//go:build plus
package cc
import (
"encoding/json"
teaconst "github.com/TeaOSLab/EdgeAdmin/internal/const"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"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/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
}) {
if !teaconst.IsPlus {
return
}
// 只有HTTP服务才支持
if this.FilterHTTPFamily() {
return
}
this.Data["serverId"] = params.ServerId
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithServerId(this.AdminContext(), 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.AdminContext(), &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
}) {
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.AdminContext(), &pb.UpdateHTTPWebCCRequest{
HttpWebId: params.WebId,
CcJSON: params.CcJSON,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -0,0 +1,21 @@
//go:build plus
package cc
import (
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/serverutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
"github.com/iwind/TeaGo"
)
func init() {
TeaGo.BeforeStart(func(server *TeaGo.Server) {
server.
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeServer)).
Helper(serverutils.NewServerHelper()).
Prefix("/servers/server/settings/cc").
GetPost("", new(IndexAction)).
EndAll()
})
}

View File

@@ -0,0 +1,74 @@
package charset
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"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/iwind/TeaGo/actions"
"github.com/iwind/TeaGo/types"
)
type IndexAction struct {
actionutils.ParentAction
}
func (this *IndexAction) Init() {
this.Nav("", "setting", "index")
this.SecondMenu("charset")
}
func (this *IndexAction) RunGet(params struct {
ServerId int64
}) {
// 只有HTTP服务才支持
if this.FilterHTTPFamily() {
return
}
// 服务分组设置
groupResp, err := this.RPC().ServerGroupRPC().FindEnabledServerGroupConfigInfo(this.AdminContext(), &pb.FindEnabledServerGroupConfigInfoRequest{
ServerId: params.ServerId,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Data["hasGroupConfig"] = groupResp.HasCharsetConfig
this.Data["groupSettingURL"] = "/servers/groups/group/settings/charset?groupId=" + types.String(groupResp.ServerGroupId)
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithServerId(this.AdminContext(), params.ServerId)
if err != nil {
this.ErrorPage(err)
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.AdminContext(), &pb.UpdateHTTPWebCharsetRequest{
HttpWebId: params.WebId,
CharsetJSON: params.CharsetJSON,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

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

View File

@@ -0,0 +1,67 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package common
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"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("common")
}
func (this *IndexAction) RunGet(params struct {
ServerId int64
}) {
// 只有HTTP服务才支持
if this.FilterHTTPFamily() {
return
}
this.Data["hasGroupConfig"] = false
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithServerId(this.AdminContext(), params.ServerId)
if err != nil {
this.ErrorPage(err)
return
}
this.Data["webId"] = webConfig.Id
this.Data["commonConfig"] = maps.Map{
"mergeSlashes": webConfig.MergeSlashes,
}
this.Show()
}
func (this *IndexAction) RunPost(params struct {
WebId int64
MergeSlashes bool
Must *actions.Must
CSRF *actionutils.CSRF
}) {
defer this.CreateLogInfo(codes.ServerCommon_LogUpdateCommonSettings, params.WebId)
_, err := this.RPC().HTTPWebRPC().UpdateHTTPWebCommon(this.AdminContext(), &pb.UpdateHTTPWebCommonRequest{
HttpWebId: params.WebId,
MergeSlashes: params.MergeSlashes,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

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

View File

@@ -0,0 +1,89 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package compression
import (
"encoding/json"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/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/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
}) {
// 只有HTTP服务才支持
if this.FilterHTTPFamily() {
return
}
// 服务分组设置
groupResp, err := this.RPC().ServerGroupRPC().FindEnabledServerGroupConfigInfo(this.AdminContext(), &pb.FindEnabledServerGroupConfigInfoRequest{
ServerId: params.ServerId,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Data["hasGroupConfig"] = groupResp.HasCompressionConfig
this.Data["groupSettingURL"] = "/servers/groups/group/settings/compression?groupId=" + types.String(groupResp.ServerGroupId)
// WebId
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithServerId(this.AdminContext(), params.ServerId)
if err != nil {
this.ErrorPage(err)
return
}
this.Data["webId"] = webConfig.Id
this.Data["compressionConfig"] = webConfig.Compression
this.Show()
}
func (this *IndexAction) RunPost(params struct {
WebId int64
CompressionJSON []byte
Must *actions.Must
CSRF *actionutils.CSRF
}) {
defer this.CreateLogInfo(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.AdminContext(), &pb.UpdateHTTPWebCompressionRequest{
HttpWebId: params.WebId,
CompressionJSON: params.CompressionJSON,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

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

View File

@@ -0,0 +1,43 @@
package conds
import (
"encoding/json"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/server/settings/conds/condutils"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
"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()
}

View File

@@ -0,0 +1,42 @@
package conds
import (
"encoding/json"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/server/settings/conds/condutils"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
"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()
}

View File

@@ -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
}

View File

@@ -0,0 +1,7 @@
package condutils
import "testing"
func TestReadAllAvailableCondTypes(t *testing.T) {
t.Log(ReadAllAvailableCondTypes())
}

View File

@@ -0,0 +1,18 @@
package conds
import (
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
"github.com/iwind/TeaGo"
)
func init() {
TeaGo.BeforeStart(func(server *TeaGo.Server) {
server.
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeServer)).
Prefix("/servers/server/settings/conds").
GetPost("/addGroupPopup", new(AddGroupPopupAction)).
GetPost("/addCondPopup", new(AddCondPopupAction)).
EndAll()
})
}

View File

@@ -0,0 +1,88 @@
// Copyright 2023 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
package copys
import (
"github.com/TeaOSLab/EdgeAdmin/internal/utils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/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.AdminContext(), &pb.CountAllEnabledServersWithServerGroupIdRequest{ServerGroupId: groupId})
if err != nil {
this.ErrorPage(err)
return
}
countServers += countResp.Count
}
hasValidTargets = true
case "cluster":
var targetClusterId = types.Int64(targetValue)
if targetClusterId <= 0 {
continue
}
countResp, err := this.RPC().ServerRPC().CountAllEnabledServersWithNodeClusterId(this.AdminContext(), &pb.CountAllEnabledServersWithNodeClusterIdRequest{NodeClusterId: targetClusterId})
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.AdminContext(), &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()
}
}

View File

@@ -0,0 +1,239 @@
// Copyright 2023 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
package copys
import (
"encoding/json"
teaconst "github.com/TeaOSLab/EdgeAdmin/internal/const"
"github.com/TeaOSLab/EdgeAdmin/internal/utils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/actions"
"github.com/iwind/TeaGo/maps"
"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
}) {
if !teaconst.IsPlus {
return
}
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.AdminContext(), &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": this.Lang(codes.Server_CopySettingCurrentGroup, group.Name),
})
}
}
}
// 当前用户
this.Data["userGroups"] = []maps.Map{}
if server.UserId > 0 {
this.Data["userId"] = server.UserId
userResp, err := this.RPC().UserRPC().FindEnabledUser(this.AdminContext(), &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": this.Lang(codes.Server_CopySettingCurrentUser, user.Fullname+" - "+user.Username),
})
}
// 当前用户的分组
groupsResp, err := this.RPC().ServerGroupRPC().FindAllEnabledServerGroups(this.AdminContext(), &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
}
// 管理员分组
var adminGroupMaps = []maps.Map{}
{
groupsResp, err := this.RPC().ServerGroupRPC().FindAllEnabledServerGroups(this.AdminContext(), &pb.FindAllEnabledServerGroupsRequest{
UserId: 0,
})
if err != nil {
this.ErrorPage(err)
return
}
for _, group := range groupsResp.ServerGroups {
if !group.IsOn {
continue
}
adminGroupMaps = append(adminGroupMaps, maps.Map{
"id": group.Id,
"name": group.Name,
})
}
}
this.Data["adminGroups"] = adminGroupMaps
// 当前集群
if server.NodeCluster != nil && server.NodeCluster.Id > 0 {
targetOptions = append(targetOptions, maps.Map{
"code": "cluster:" + types.String(server.NodeCluster.Id),
"name": this.Lang(codes.Server_CopySettingCurrentCluster, server.NodeCluster.Name),
})
}
// 其他
// TODO 支持选择服务
targetOptions = append(targetOptions, maps.Map{
"code": "group",
"name": this.Lang(codes.Server_CopySettingSelectGroup),
}, maps.Map{
"code": "user",
"name": this.Lang(codes.Server_CopySettingSelectUser),
}, maps.Map{
"code": "cluster",
"name": this.Lang(codes.Server_CopySettingSelectCluster),
}, /**, maps.Map{
"code": "server",
"name": this.Lang(codes.ServerCopySettingSelectServer),
}**/)
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
}) {
if !teaconst.IsPlus {
return
}
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 "cluster":
targetClusterId = types.Int64(targetValue)
if targetClusterId <= 0 {
continue
}
case "user":
targetUserId = types.Int64(targetValue)
if targetUserId <= 0 {
continue
}
default:
this.Fail("错误的目标格式:" + target)
return
}
_, err := this.RPC().ServerRPC().CopyServerConfig(this.AdminContext(), &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()
}

View File

@@ -0,0 +1,20 @@
package copys
import (
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/serverutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
"github.com/iwind/TeaGo"
)
func init() {
TeaGo.BeforeStart(func(server *TeaGo.Server) {
server.
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeServer)).
Helper(serverutils.NewServerHelper()).
Prefix("/servers/server/settings/copy").
GetPost("", new(IndexAction)).
Post("/countServers", new(CountServersAction)).
EndAll()
})
}

View File

@@ -0,0 +1,57 @@
package dns
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/actions"
)
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.AdminContext(), &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.Data["supportCNAME"] = dnsInfoResp.SupportCNAME
this.Show()
}
func (this *IndexAction) RunPost(params struct {
ServerId int64
SupportCNAME bool
Must *actions.Must
CSRF *actionutils.CSRF
}) {
defer this.CreateLogInfo(codes.ServerDNS_LogUpdateDNSSettings, params.ServerId)
_, err := this.RPC().ServerRPC().UpdateServerDNS(this.AdminContext(), &pb.UpdateServerDNSRequest{
ServerId: params.ServerId,
SupportCNAME: params.SupportCNAME,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -0,0 +1,21 @@
package dns
import (
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/serverutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
"github.com/iwind/TeaGo"
)
func init() {
TeaGo.BeforeStart(func(server *TeaGo.Server) {
server.
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeServer)).
Helper(serverutils.NewServerHelper()).
Prefix("/servers/server/settings/dns").
GetPost("", new(IndexAction)).
Post("/regenerateCNAME", new(RegenerateCNAMEAction)).
GetPost("/updateCNAMEPopup", new(UpdateCNAMEPopupAction)).
EndAll()
})
}

View File

@@ -0,0 +1,27 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package dns
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
)
type RegenerateCNAMEAction struct {
actionutils.ParentAction
}
func (this *RegenerateCNAMEAction) RunPost(params struct {
ServerId int64
}) {
defer this.CreateLogInfo(codes.ServerDNS_LogRegenerateDNSName, params.ServerId)
_, err := this.RPC().ServerRPC().RegenerateServerDNSName(this.AdminContext(), &pb.RegenerateServerDNSNameRequest{ServerId: params.ServerId})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -0,0 +1,98 @@
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
package dns
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/types"
"regexp"
"strings"
)
type UpdateCNAMEPopupAction struct {
actionutils.ParentAction
}
func (this *UpdateCNAMEPopupAction) RunGet(params struct {
ServerId int64
}) {
this.Data["serverId"] = params.ServerId
dnsInfoResp, err := this.RPC().ServerRPC().FindEnabledServerDNS(this.AdminContext(), &pb.FindEnabledServerDNSRequest{ServerId: params.ServerId})
if err != nil {
this.ErrorPage(err)
return
}
this.Data["dnsName"] = dnsInfoResp.DnsName
this.Show()
}
func (this *UpdateCNAMEPopupAction) RunPost(params struct {
ServerId int64
DnsName string
}) {
defer this.CreateLogInfo(codes.ServerDNS_LogUpdateDNSName, params.ServerId, params.DnsName)
var dnsName = strings.ToLower(params.DnsName)
if len(dnsName) == 0 {
this.FailField("dnsName", "CNAME不能为空")
}
const maxLen = 30
if len(dnsName) > maxLen {
this.FailField("dnsName", "CNAME长度不能超过"+types.String(maxLen)+"个字符")
}
if !regexp.MustCompile(`^[a-z0-9]{1,` + types.String(maxLen) + `}$`).MatchString(dnsName) {
this.FailField("dnsName", "CNAME中只能包含数字、英文字母")
}
serverResp, err := this.RPC().ServerRPC().FindEnabledServer(this.AdminContext(), &pb.FindEnabledServerRequest{
ServerId: params.ServerId,
IgnoreSSLCerts: true,
})
if err != nil {
this.ErrorPage(err)
return
}
var server = serverResp.Server
if server == nil {
this.Fail("找不到要修改的服务")
}
if server.NodeCluster == nil {
this.Fail("服务必须先分配到一个集群才能修改")
}
var clusterId = server.NodeCluster.Id
if server.DnsName == params.DnsName {
// 没有修改则直接返回
this.Success()
}
serverIdResp, err := this.RPC().ServerRPC().FindServerIdWithDNSName(this.AdminContext(), &pb.FindServerIdWithDNSNameRequest{
NodeClusterId: clusterId,
DnsName: dnsName,
})
if err != nil {
this.ErrorPage(err)
return
}
if serverIdResp.ServerId > 0 && serverIdResp.ServerId != params.ServerId {
this.FailField("dnsName", "当前CNAME已被别的服务占用请换一个")
}
_, err = this.RPC().ServerRPC().UpdateServerDNSName(this.AdminContext(), &pb.UpdateServerDNSNameRequest{
ServerId: params.ServerId,
DnsName: dnsName,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -0,0 +1,93 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package fastcgi
import (
"encoding/json"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
"github.com/iwind/TeaGo/actions"
"net"
)
type CreatePopupAction struct {
actionutils.ParentAction
}
func (this *CreatePopupAction) Init() {
this.Nav("", "", "")
}
func (this *CreatePopupAction) RunGet(params struct{}) {
this.Show()
}
func (this *CreatePopupAction) RunPost(params struct {
Address string
ParamsJSON []byte
ReadTimeout int64
PoolSize int32
PathInfoPattern string
IsOn bool
Must *actions.Must
CSRF *actionutils.CSRF
}) {
var fastcgiId = int64(0)
defer func() {
this.CreateLogInfo(codes.HTTPFastcgi_LogCreateHTTPFastcgi, fastcgiId)
}()
params.Must.
Field("address", params.Address).
Require("请输入Fastcgi地址")
_, _, err := net.SplitHostPort(params.Address)
if err != nil {
this.FailField("address", "请输入正确的Fastcgi地址")
}
readTimeoutJSON, err := json.Marshal(&shared.TimeDuration{
Count: params.ReadTimeout,
Unit: "second",
})
if err != nil {
this.ErrorPage(err)
return
}
createResp, err := this.RPC().HTTPFastcgiRPC().CreateHTTPFastcgi(this.AdminContext(), &pb.CreateHTTPFastcgiRequest{
IsOn: params.IsOn,
Address: params.Address,
ParamsJSON: params.ParamsJSON,
ReadTimeoutJSON: readTimeoutJSON,
ConnTimeoutJSON: nil, // TODO 将来支持
PoolSize: params.PoolSize,
PathInfoPattern: params.PathInfoPattern,
})
if err != nil {
this.ErrorPage(err)
return
}
fastcgiId = createResp.HttpFastcgiId
configResp, err := this.RPC().HTTPFastcgiRPC().FindEnabledHTTPFastcgiConfig(this.AdminContext(), &pb.FindEnabledHTTPFastcgiConfigRequest{HttpFastcgiId: fastcgiId})
if err != nil {
this.ErrorPage(err)
return
}
configJSON := configResp.HttpFastcgiJSON
config := &serverconfigs.HTTPFastcgiConfig{}
err = json.Unmarshal(configJSON, config)
if err != nil {
this.ErrorPage(err)
return
}
this.Data["fastcgi"] = config
this.Success()
}

View File

@@ -0,0 +1,76 @@
package fastcgi
import (
"encoding/json"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"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/iwind/TeaGo/actions"
)
type IndexAction struct {
actionutils.ParentAction
}
func (this *IndexAction) Init() {
this.Nav("", "setting", "index")
this.SecondMenu("fastcgi")
}
func (this *IndexAction) RunGet(params struct {
ServerId int64
}) {
// 只有HTTP服务才支持
if this.FilterHTTPFamily() {
return
}
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithServerId(this.AdminContext(), params.ServerId)
if err != nil {
this.ErrorPage(err)
return
}
this.Data["webId"] = webConfig.Id
this.Data["fastcgiRef"] = webConfig.FastcgiRef
this.Data["fastcgiConfigs"] = webConfig.FastcgiList
this.Show()
}
func (this *IndexAction) RunPost(params struct {
WebId int64
FastcgiRefJSON []byte
FastcgiJSON []byte
Must *actions.Must
}) {
defer this.CreateLogInfo(codes.ServerFastcgi_LogUpdateHTTPFastcgi, params.WebId)
// TODO 检查配置
fastcgiRef := &serverconfigs.HTTPFastcgiRef{}
err := json.Unmarshal(params.FastcgiRefJSON, fastcgiRef)
if err != nil {
this.ErrorPage(err)
return
}
fastcgiRefJSON, err := json.Marshal(fastcgiRef)
if err != nil {
this.ErrorPage(err)
return
}
_, err = this.RPC().HTTPWebRPC().UpdateHTTPWebFastcgi(this.AdminContext(), &pb.UpdateHTTPWebFastcgiRequest{
HttpWebId: params.WebId,
FastcgiJSON: fastcgiRefJSON,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -0,0 +1,21 @@
package fastcgi
import (
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/serverutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
"github.com/iwind/TeaGo"
)
func init() {
TeaGo.BeforeStart(func(server *TeaGo.Server) {
server.
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeServer)).
Helper(serverutils.NewServerHelper()).
Prefix("/servers/server/settings/fastcgi").
GetPost("", new(IndexAction)).
GetPost("/createPopup", new(CreatePopupAction)).
GetPost("/updatePopup", new(UpdatePopupAction)).
EndAll()
})
}

View File

@@ -0,0 +1,107 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package fastcgi
import (
"encoding/json"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
"github.com/iwind/TeaGo/actions"
"net"
)
type UpdatePopupAction struct {
actionutils.ParentAction
}
func (this *UpdatePopupAction) Init() {
this.Nav("", "", "")
}
func (this *UpdatePopupAction) RunGet(params struct {
FastcgiId int64
}) {
configResp, err := this.RPC().HTTPFastcgiRPC().FindEnabledHTTPFastcgiConfig(this.AdminContext(), &pb.FindEnabledHTTPFastcgiConfigRequest{HttpFastcgiId: params.FastcgiId})
if err != nil {
this.ErrorPage(err)
return
}
configJSON := configResp.HttpFastcgiJSON
config := &serverconfigs.HTTPFastcgiConfig{}
err = json.Unmarshal(configJSON, config)
if err != nil {
this.ErrorPage(err)
return
}
this.Data["fastcgi"] = config
this.Show()
}
func (this *UpdatePopupAction) RunPost(params struct {
FastcgiId int64
Address string
ParamsJSON []byte
ReadTimeout int64
PoolSize int32
PathInfoPattern string
IsOn bool
Must *actions.Must
CSRF *actionutils.CSRF
}) {
defer this.CreateLogInfo(codes.HTTPFastcgi_LogUpdateHTTPFastcgi, params.FastcgiId)
params.Must.
Field("address", params.Address).
Require("请输入Fastcgi地址")
_, _, err := net.SplitHostPort(params.Address)
if err != nil {
this.FailField("address", "请输入正确的Fastcgi地址")
}
readTimeoutJSON, err := json.Marshal(&shared.TimeDuration{
Count: params.ReadTimeout,
Unit: "second",
})
if err != nil {
this.ErrorPage(err)
return
}
_, err = this.RPC().HTTPFastcgiRPC().UpdateHTTPFastcgi(this.AdminContext(), &pb.UpdateHTTPFastcgiRequest{
HttpFastcgiId: params.FastcgiId,
IsOn: params.IsOn,
Address: params.Address,
ParamsJSON: params.ParamsJSON,
ReadTimeoutJSON: readTimeoutJSON,
ConnTimeoutJSON: nil, // TODO 将来支持
PoolSize: params.PoolSize,
PathInfoPattern: params.PathInfoPattern,
})
if err != nil {
this.ErrorPage(err)
return
}
configResp, err := this.RPC().HTTPFastcgiRPC().FindEnabledHTTPFastcgiConfig(this.AdminContext(), &pb.FindEnabledHTTPFastcgiConfigRequest{HttpFastcgiId: params.FastcgiId})
if err != nil {
this.ErrorPage(err)
return
}
configJSON := configResp.HttpFastcgiJSON
config := &serverconfigs.HTTPFastcgiConfig{}
err = json.Unmarshal(configJSON, config)
if err != nil {
this.ErrorPage(err)
return
}
this.Data["fastcgi"] = config
this.Success()
}

View File

@@ -0,0 +1,67 @@
package headers
import (
"encoding/json"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
"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.AdminContext(), &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.AdminContext(), &pb.UpdateHTTPHeaderPolicyDeletingHeadersRequest{
HttpHeaderPolicyId: params.HeaderPolicyId,
HeaderNames: deleteHeaders,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -0,0 +1,67 @@
package headers
import (
"encoding/json"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
"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.AdminContext(), &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.AdminContext(), &pb.UpdateHTTPHeaderPolicyNonStandardHeadersRequest{
HttpHeaderPolicyId: params.HeaderPolicyId,
HeaderNames: nonStandardHeaders,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -0,0 +1,153 @@
package headers
import (
"encoding/json"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
"github.com/iwind/TeaGo/actions"
"strings"
)
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.Name = strings.TrimSuffix(params.Name, ":")
params.Must.
Field("name", params.Name).
Require("请输入Header名称")
configResp, err := this.RPC().HTTPHeaderPolicyRPC().FindEnabledHTTPHeaderPolicyConfig(this.AdminContext(), &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.AdminContext(), &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.AdminContext(), &pb.UpdateHTTPHeaderPolicySettingHeadersRequest{
HttpHeaderPolicyId: params.HeaderPolicyId,
HeadersJSON: refsJSON,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -0,0 +1,61 @@
package headers
import (
"encoding/json"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
)
// 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.AdminContext(), &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.AdminContext(), &pb.UpdateHTTPHeaderPolicySettingHeadersRequest{
HttpHeaderPolicyId: params.HeaderPolicyId,
HeadersJSON: resultJSON,
})
if err != nil {
this.ErrorPage(err)
return
}
}
this.Success()
}

View File

@@ -0,0 +1,52 @@
package headers
import (
"encoding/json"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
)
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.AdminContext(), &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.AdminContext(), &pb.UpdateHTTPHeaderPolicyDeletingHeadersRequest{
HttpHeaderPolicyId: params.HeaderPolicyId,
HeaderNames: headerNames,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -0,0 +1,52 @@
package headers
import (
"encoding/json"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
)
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.AdminContext(), &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.AdminContext(), &pb.UpdateHTTPHeaderPolicyNonStandardHeadersRequest{
HttpHeaderPolicyId: params.HeaderPolicyId,
HeaderNames: headerNames,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -0,0 +1,119 @@
package headers
import (
"encoding/json"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
"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
}) {
// 只有HTTP服务才支持
if this.FilterHTTPFamily() {
return
}
// 服务分组设置
groupResp, err := this.RPC().ServerGroupRPC().FindEnabledServerGroupConfigInfo(this.AdminContext(), &pb.FindEnabledServerGroupConfigInfoRequest{
ServerId: params.ServerId,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Data["hasGroupRequestConfig"] = groupResp.HasRequestHeadersConfig
this.Data["hasGroupResponseConfig"] = groupResp.HasResponseHeadersConfig
this.Data["groupSettingURL"] = "/servers/groups/group/settings/headers?groupId=" + types.String(groupResp.ServerGroupId)
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithServerId(this.AdminContext(), params.ServerId)
if err != nil {
this.ErrorPage(err)
return
}
webId := webConfig.Id
isChanged := false
if webConfig.RequestHeaderPolicy == nil {
createHeaderPolicyResp, err := this.RPC().HTTPHeaderPolicyRPC().CreateHTTPHeaderPolicy(this.AdminContext(), &pb.CreateHTTPHeaderPolicyRequest{})
if err != nil {
this.ErrorPage(err)
return
}
var 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.AdminContext(), &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.AdminContext(), &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.AdminContext(), &pb.UpdateHTTPWebResponseHeaderRequest{
HttpWebId: webId,
HeaderJSON: refJSON,
})
if err != nil {
this.ErrorPage(err)
return
}
isChanged = true
}
// 重新获取配置
if isChanged {
webConfig, err = dao.SharedHTTPWebDAO.FindWebConfigWithServerId(this.AdminContext(), 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()
}

View File

@@ -0,0 +1,27 @@
package headers
import (
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/serverutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
"github.com/iwind/TeaGo"
)
func init() {
TeaGo.BeforeStart(func(server *TeaGo.Server) {
server.
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeServer)).
Helper(serverutils.NewServerHelper()).
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()
})
}

View File

@@ -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/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
"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.AdminContext(), &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.AdminContext(), &pb.UpdateHTTPHeaderPolicyCORSRequest{
HttpHeaderPolicyId: params.HeaderPolicyId,
CorsJSON: params.CorsJSON,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -0,0 +1,127 @@
package headers
import (
"encoding/json"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
"github.com/iwind/TeaGo/actions"
"strings"
)
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.AdminContext(), &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.Name = strings.TrimSuffix(params.Name, ":")
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.AdminContext(), &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()
}

View File

@@ -0,0 +1,178 @@
package http
import (
"context"
"encoding/json"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/serverutils"
"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/iwind/TeaGo/actions"
"github.com/iwind/TeaGo/lists"
"github.com/iwind/TeaGo/maps"
"github.com/iwind/TeaGo/types"
"regexp"
)
type IndexAction struct {
actionutils.ParentAction
}
func (this *IndexAction) Init() {
this.Nav("", "setting", "index")
this.SecondMenu("http")
}
func (this *IndexAction) RunGet(params struct {
ServerId int64
}) {
// 只有HTTP服务才支持
if this.FilterHTTPFamily() {
return
}
server, _, isOk := serverutils.FindServer(this.Parent(), params.ServerId)
if !isOk {
return
}
var httpConfig = &serverconfigs.HTTPProtocolConfig{}
if len(server.HttpJSON) > 0 {
err := json.Unmarshal(server.HttpJSON, httpConfig)
if err != nil {
this.ErrorPage(err)
return
}
} else {
httpConfig.IsOn = true
}
_ = httpConfig.Init()
var httpPorts = httpConfig.AllPorts()
// 检查http和https端口冲突
var conflictingPorts = []int{}
if len(server.HttpsJSON) > 0 {
var httpsConfig = &serverconfigs.HTTPSProtocolConfig{}
err := json.Unmarshal(server.HttpsJSON, httpsConfig)
if err != nil {
this.ErrorPage(err)
return
}
_ = httpsConfig.Init(context.TODO())
for _, port := range httpsConfig.AllPorts() {
if lists.ContainsInt(httpPorts, port) {
conflictingPorts = append(conflictingPorts, port)
}
}
}
this.Data["conflictingPorts"] = conflictingPorts
this.Data["serverType"] = server.Type
this.Data["httpConfig"] = maps.Map{
"isOn": httpConfig.IsOn,
"addresses": httpConfig.Listen,
}
// 跳转相关设置
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithServerId(this.AdminContext(), 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)
var addresses = []*serverconfigs.NetworkAddressConfig{}
err := json.Unmarshal([]byte(params.Addresses), &addresses)
if err != nil {
this.Fail("端口地址解析失败:" + err.Error())
}
// 如果启用HTTP时没有填写端口则默认为80
if params.IsOn && len(addresses) == 0 {
addresses = []*serverconfigs.NetworkAddressConfig{
{
Protocol: serverconfigs.ProtocolHTTP,
PortRange: "80",
},
}
}
// 检查端口地址是否正确
for _, addr := range addresses {
err = addr.Init()
if err != nil {
this.Fail("绑定端口校验失败:" + err.Error())
}
if regexp.MustCompile(`^\d+$`).MatchString(addr.PortRange) {
port := types.Int(addr.PortRange)
if port > 65535 {
this.Fail("绑定的端口地址不能大于65535")
}
if port == 443 {
this.Fail("端口443通常是HTTPS的端口不能用在HTTP上")
}
}
}
server, _, isOk := serverutils.FindServer(this.Parent(), params.ServerId)
if !isOk {
return
}
var httpConfig = &serverconfigs.HTTPProtocolConfig{}
if len(server.HttpJSON) > 0 {
err = json.Unmarshal(server.HttpJSON, httpConfig)
if err != nil {
this.ErrorPage(err)
return
}
}
httpConfig.IsOn = params.IsOn
httpConfig.Listen = addresses
configData, err := json.Marshal(httpConfig)
if err != nil {
this.ErrorPage(err)
return
}
_, err = this.RPC().ServerRPC().UpdateServerHTTP(this.AdminContext(), &pb.UpdateServerHTTPRequest{
ServerId: params.ServerId,
HttpJSON: configData,
})
if err != nil {
this.ErrorPage(err)
return
}
// 设置跳转到HTTPS
// TODO 校验设置
_, err = this.RPC().HTTPWebRPC().UpdateHTTPWebRedirectToHTTPS(this.AdminContext(), &pb.UpdateHTTPWebRedirectToHTTPSRequest{
HttpWebId: params.WebId,
RedirectToHTTPSJSON: params.RedirectToHTTPSJSON,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

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

View File

@@ -0,0 +1,307 @@
package https
import (
"context"
"encoding/json"
"errors"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/serverutils"
"github.com/TeaOSLab/EdgeCommon/pkg/configutils"
"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/iwind/TeaGo/actions"
"github.com/iwind/TeaGo/lists"
"github.com/iwind/TeaGo/maps"
"github.com/iwind/TeaGo/types"
"regexp"
)
type IndexAction struct {
actionutils.ParentAction
}
func (this *IndexAction) Init() {
this.Nav("", "setting", "index")
this.SecondMenu("https")
}
func (this *IndexAction) RunGet(params struct {
ServerId int64
}) {
// 只有HTTP服务才支持
if this.FilterHTTPFamily() {
return
}
server, _, isOk := serverutils.FindServer(this.Parent(), params.ServerId)
if !isOk {
return
}
var httpsConfig = &serverconfigs.HTTPSProtocolConfig{}
if len(server.HttpsJSON) > 0 {
err := json.Unmarshal(server.HttpsJSON, httpsConfig)
if err != nil {
this.ErrorPage(err)
return
}
} else {
httpsConfig.IsOn = true
}
_ = httpsConfig.Init(context.TODO())
var httpsPorts = httpsConfig.AllPorts()
// 检查http和https端口冲突
var conflictingPorts = []int{}
if len(server.HttpJSON) > 0 {
var httpConfig = &serverconfigs.HTTPProtocolConfig{}
err := json.Unmarshal(server.HttpJSON, httpConfig)
if err != nil {
this.ErrorPage(err)
return
}
_ = httpConfig.Init()
for _, port := range httpConfig.AllPorts() {
if lists.ContainsInt(httpsPorts, port) {
conflictingPorts = append(conflictingPorts, port)
}
}
}
this.Data["conflictingPorts"] = conflictingPorts
var sslPolicy *sslconfigs.SSLPolicy
var allDNSNames []string
if httpsConfig.SSLPolicyRef != nil && httpsConfig.SSLPolicyRef.SSLPolicyId > 0 {
sslPolicyConfigResp, err := this.RPC().SSLPolicyRPC().FindEnabledSSLPolicyConfig(this.AdminContext(), &pb.FindEnabledSSLPolicyConfigRequest{
SslPolicyId: httpsConfig.SSLPolicyRef.SSLPolicyId,
IgnoreData: true,
})
if err != nil {
this.ErrorPage(err)
return
}
var 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
if server.NodeCluster == nil {
this.ErrorPage(errors.New("no node cluster for the server"))
return
}
supportsHTTP3, err := this.checkSupportsHTTP3(server.NodeCluster.Id)
if err != nil {
this.ErrorPage(err)
return
}
this.Data["serverType"] = server.Type
this.Data["httpsConfig"] = maps.Map{
"isOn": httpsConfig.IsOn,
"addresses": httpsConfig.Listen,
"sslPolicy": sslPolicy,
"supportsHTTP3": supportsHTTP3,
}
// 检查域名是否都已经上传了证书
serverNamesResp, err := this.RPC().ServerRPC().FindServerNames(this.AdminContext(), &pb.FindServerNamesRequest{
ServerId: server.Id,
})
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
Addresses string
SslPolicyJSON []byte
Must *actions.Must
}) {
// 记录日志
defer this.CreateLogInfo(codes.ServerHTTPS_LogUpdateHTTPSSettings, params.ServerId)
var addresses = []*serverconfigs.NetworkAddressConfig{}
err := json.Unmarshal([]byte(params.Addresses), &addresses)
if err != nil {
this.Fail("端口地址解析失败:" + err.Error())
}
// 如果启用HTTPS时没有填写端口则默认为443
if params.IsOn && len(addresses) == 0 {
addresses = []*serverconfigs.NetworkAddressConfig{
{
Protocol: serverconfigs.ProtocolHTTPS,
PortRange: "443",
},
}
}
// 检查端口地址是否正确
for _, addr := range addresses {
err = addr.Init()
if err != nil {
this.Fail("绑定端口校验失败:" + err.Error())
}
if regexp.MustCompile(`^\d+$`).MatchString(addr.PortRange) {
port := types.Int(addr.PortRange)
if port > 65535 {
this.Fail("绑定的端口地址不能大于65535")
}
if port == 80 {
this.Fail("端口80通常是HTTP的端口不能用在HTTPS上")
}
}
}
// 校验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.AdminContext(), &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.AdminContext(), &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
}
}
server, _, isOk := serverutils.FindServer(this.Parent(), params.ServerId)
if !isOk {
return
}
var httpsConfig = &serverconfigs.HTTPSProtocolConfig{}
if len(server.HttpsJSON) > 0 {
err = json.Unmarshal(server.HttpsJSON, httpsConfig)
if err != nil {
this.ErrorPage(err)
return
}
}
httpsConfig.SSLPolicy = nil
httpsConfig.SSLPolicyRef = &sslconfigs.SSLPolicyRef{
IsOn: true,
SSLPolicyId: sslPolicyId,
}
httpsConfig.IsOn = params.IsOn
httpsConfig.Listen = addresses
configData, err := json.Marshal(httpsConfig)
if err != nil {
this.ErrorPage(err)
return
}
_, err = this.RPC().ServerRPC().UpdateServerHTTPS(this.AdminContext(), &pb.UpdateServerHTTPSRequest{
ServerId: params.ServerId,
HttpsJSON: configData,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -0,0 +1,8 @@
// Copyright 2023 GoEdge CDN goedge.cdn@gmail.com. All rights reserved. Official site: https://goedge.cn .
//go:build !plus
package https
func (this *IndexAction) checkSupportsHTTP3(clusterId int64) (bool, error) {
return false, nil
}

View File

@@ -0,0 +1,40 @@
// Copyright 2023 GoEdge CDN goedge.cdn@gmail.com. All rights reserved. Official site: https://goedge.cn .
//go:build plus
package https
import (
"encoding/json"
teaconst "github.com/TeaOSLab/EdgeAdmin/internal/const"
"github.com/TeaOSLab/EdgeAdmin/internal/rpc"
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
)
func (this *IndexAction) checkSupportsHTTP3(clusterId int64) (bool, error) {
if !teaconst.IsPlus {
return false, nil
}
// TODO 检查当前网站所属用户是否支持HTTP/3
http3PolicyResp, err := this.RPC().NodeClusterRPC().FindNodeClusterHTTP3Policy(this.AdminContext(), &pb.FindNodeClusterHTTP3PolicyRequest{NodeClusterId: clusterId})
if err != nil {
if rpc.IsUnimplementedError(err) {
err = nil
}
return false, err
}
var supportsHTTP3 = false
if len(http3PolicyResp.Http3PolicyJSON) > 0 {
var http3Policy = nodeconfigs.NewHTTP3Policy()
err = json.Unmarshal(http3PolicyResp.Http3PolicyJSON, http3Policy)
if err != nil {
return false, err
}
supportsHTTP3 = http3Policy.IsOn
}
return supportsHTTP3, nil
}

View File

@@ -0,0 +1,20 @@
package https
import (
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/serverutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
"github.com/iwind/TeaGo"
)
func init() {
TeaGo.BeforeStart(func(server *TeaGo.Server) {
server.
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeServer)).
Helper(serverutils.NewServerHelper()).
Prefix("/servers/server/settings/https").
GetPost("", new(IndexAction)).
GetPost("/requestCertPopup", new(RequestCertPopupAction)).
EndAll()
})
}

View File

@@ -0,0 +1,182 @@
package https
import (
"encoding/json"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/dns/domains/domainutils"
"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/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.AdminContext(), &pb.FindServerNamesRequest{ServerId: params.ServerId})
if err != nil {
this.ErrorPage(err)
return
}
var serverNameConfigs = []*serverconfigs.ServerNameConfig{}
err = json.Unmarshal(serverNamesResp.ServerNamesJSON, &serverNameConfigs)
if err != nil {
this.ErrorPage(err)
return
}
var excludeServerNames = []string{}
if len(params.ExcludeServerNames) > 0 {
excludeServerNames = strings.Split(params.ExcludeServerNames, ",")
}
var 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.AdminContext(), &pb.FindAllACMEUsersRequest{
AdminId: this.AdminId(),
UserId: 0,
})
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.AdminContext(), &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.AdminContext(), &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.AdminContext(), &pb.RunACMETaskRequest{AcmeTaskId: taskId})
if err != nil {
this.ErrorPage(err)
return
}
if runResp.IsOk {
certId := runResp.SslCertId
configResp, err := this.RPC().SSLCertRPC().FindEnabledSSLCertConfig(this.AdminContext(), &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)
}
}

View File

@@ -0,0 +1,203 @@
package settings
import (
"encoding/json"
"errors"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
"github.com/iwind/TeaGo/actions"
"github.com/iwind/TeaGo/maps"
)
// IndexAction 服务基本信息设置
type IndexAction struct {
actionutils.ParentAction
}
func (this *IndexAction) Init() {
this.Nav("", "setting", "")
this.SecondMenu("basic")
}
func (this *IndexAction) RunGet(params struct {
ServerId int64
}) {
// 所有集群
resp, err := this.RPC().NodeClusterRPC().FindAllEnabledNodeClusters(this.AdminContext(), &pb.FindAllEnabledNodeClustersRequest{})
if err != nil {
this.ErrorPage(err)
}
if err != nil {
this.ErrorPage(err)
return
}
var clusterMaps = []maps.Map{}
for _, cluster := range resp.NodeClusters {
clusterMaps = append(clusterMaps, maps.Map{
"id": cluster.Id,
"name": cluster.Name,
})
}
this.Data["clusters"] = clusterMaps
// 当前服务信息
serverResp, err := this.RPC().ServerRPC().FindEnabledServer(this.AdminContext(), &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
}
// 用户
if server.User != nil {
this.Data["user"] = maps.Map{
"id": server.User.Id,
"fullname": server.User.Fullname,
"username": server.User.Username,
}
} else {
this.Data["user"] = nil
}
// 套餐
this.initUserPlan(server)
// 集群
var clusterId = int64(0)
this.Data["clusterName"] = ""
if server.NodeCluster != nil {
clusterId = server.NodeCluster.Id
this.Data["clusterName"] = server.NodeCluster.Name
}
// 分组
var groupMaps = []maps.Map{}
if len(server.ServerGroups) > 0 {
for _, group := range server.ServerGroups {
groupMaps = append(groupMaps, maps.Map{
"id": group.Id,
"name": group.Name,
})
}
}
// 域名和限流状态
var trafficLimitStatus *serverconfigs.TrafficLimitStatus
if len(server.Config) > 0 {
var serverConfig = &serverconfigs.ServerConfig{}
err = json.Unmarshal(server.Config, serverConfig)
if err == nil {
if serverConfig.TrafficLimitStatus != nil && serverConfig.TrafficLimitStatus.IsValid() {
trafficLimitStatus = serverConfig.TrafficLimitStatus
}
}
}
this.Data["server"] = maps.Map{
"id": server.Id,
"clusterId": clusterId,
"type": server.Type,
"name": server.Name,
"description": server.Description,
"isOn": server.IsOn,
"groups": groupMaps,
"trafficLimitStatus": trafficLimitStatus,
}
var serverType = serverconfigs.FindServerType(server.Type)
if serverType == nil {
this.ErrorPage(errors.New("invalid server type '" + server.Type + "'"))
return
}
var typeName = serverType.GetString("name")
this.Data["typeName"] = typeName
// 记录最近使用
_, err = this.RPC().LatestItemRPC().IncreaseLatestItem(this.AdminContext(), &pb.IncreaseLatestItemRequest{
ItemType: "server",
ItemId: params.ServerId,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Show()
}
// RunPost 保存
func (this *IndexAction) RunPost(params struct {
ServerId int64
UserId int64
Name string
Description string
ClusterId int64
KeepOldConfigs bool
GroupIds []int64
IsOn bool
UserPlanId int64
Must *actions.Must
}) {
// 记录日志
defer this.CreateLogInfo(codes.Server_LogUpdateServerBasic, params.ServerId)
params.Must.
Field("name", params.Name).
Require("请输入服务名称")
if params.ClusterId <= 0 {
this.Fail("请选择部署的集群")
}
// 修改基本信息
_, err := this.RPC().ServerRPC().UpdateServerBasic(this.AdminContext(), &pb.UpdateServerBasicRequest{
ServerId: params.ServerId,
Name: params.Name,
Description: params.Description,
NodeClusterId: params.ClusterId,
KeepOldConfigs: params.KeepOldConfigs,
IsOn: params.IsOn,
ServerGroupIds: params.GroupIds,
})
if err != nil {
this.ErrorPage(err)
return
}
// 修改用户
if params.UserId > 0 {
_, err = this.RPC().ServerRPC().UpdateServerUser(this.AdminContext(), &pb.UpdateServerUserRequest{
ServerId: params.ServerId,
UserId: params.UserId,
})
if err != nil {
this.ErrorPage(err)
return
}
} else {
// 修改套餐
if params.UserPlanId > 0 {
_, err = this.RPC().ServerRPC().UpdateServerUserPlan(this.AdminContext(), &pb.UpdateServerUserPlanRequest{
ServerId: params.ServerId,
UserPlanId: params.UserPlanId,
})
if err != nil {
this.ErrorPage(err)
return
}
}
}
this.Success()
}

View File

@@ -0,0 +1,14 @@
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
//go:build !plus
package settings
import (
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/maps"
)
func (this *IndexAction) initUserPlan(server *pb.Server) {
var userPlanMap = maps.Map{"id": server.UserPlanId, "dayTo": "", "plan": maps.Map{}}
this.Data["userPlan"] = userPlanMap
}

View File

@@ -0,0 +1,40 @@
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
//go:build plus
package settings
import (
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/maps"
)
func (this *IndexAction) initUserPlan(server *pb.Server) {
var userPlanMap = maps.Map{"id": server.UserPlanId, "dayTo": "", "plan": maps.Map{}}
if server.UserPlanId > 0 {
userPlanResp, err := this.RPC().UserPlanRPC().FindEnabledUserPlan(this.AdminContext(), &pb.FindEnabledUserPlanRequest{UserPlanId: server.UserPlanId})
if err != nil {
this.ErrorPage(err)
return
}
var userPlan = userPlanResp.UserPlan
if userPlan != nil {
planResp, err := this.RPC().PlanRPC().FindEnabledPlan(this.AdminContext(), &pb.FindEnabledPlanRequest{PlanId: userPlan.PlanId})
if err != nil {
this.ErrorPage(err)
return
}
var plan = planResp.Plan
if plan != nil {
userPlanMap = maps.Map{
"id": userPlan.Id,
"dayTo": userPlan.DayTo,
"plan": maps.Map{
"id": plan.Id,
"name": plan.Name,
},
}
}
}
}
this.Data["userPlan"] = userPlanMap
}

View File

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

View File

@@ -0,0 +1,100 @@
package access
import (
"encoding/json"
teaconst "github.com/TeaOSLab/EdgeAdmin/internal/const"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"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/iwind/TeaGo/actions"
"github.com/iwind/TeaGo/lists"
)
type IndexAction struct {
actionutils.ParentAction
}
func (this *IndexAction) Init() {
this.Nav("", "setting", "index")
this.SecondMenu("access")
}
func (this *IndexAction) RunGet(params struct {
LocationId int64
}) {
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithLocationId(this.AdminContext(), params.LocationId)
if err != nil {
this.ErrorPage(err)
return
}
this.Data["webId"] = webConfig.Id
// 移除不存在的鉴权方法
var allTypes = []string{}
for _, def := range serverconfigs.FindAllHTTPAuthTypes(teaconst.Role) {
allTypes = append(allTypes, def.Code)
}
if webConfig.Auth != nil {
var refs = webConfig.Auth.PolicyRefs
var realRefs = []*serverconfigs.HTTPAuthPolicyRef{}
for _, ref := range refs {
if ref.AuthPolicy == nil {
continue
}
if !lists.ContainsString(allTypes, ref.AuthPolicy.Type) {
continue
}
realRefs = append(realRefs, ref)
}
webConfig.Auth.PolicyRefs = realRefs
}
this.Data["authConfig"] = webConfig.Auth
this.Show()
}
func (this *IndexAction) RunPost(params struct {
WebId int64
AuthJSON []byte
Must *actions.Must
}) {
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.AdminContext(), &pb.UpdateHTTPWebAuthRequest{
HttpWebId: params.WebId,
AuthJSON: configJSON,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -0,0 +1,22 @@
package access
import (
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/server/settings/locations/locationutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/serverutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
"github.com/iwind/TeaGo"
)
func init() {
TeaGo.BeforeStart(func(server *TeaGo.Server) {
server.
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeServer)).
Helper(locationutils.NewLocationHelper()).
Helper(serverutils.NewServerHelper()).
Data("tinyMenuItem", "access").
Prefix("/servers/server/settings/locations/access").
GetPost("", new(IndexAction)).
EndAll()
})
}

View File

@@ -0,0 +1,58 @@
package accessLog
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"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/iwind/TeaGo/actions"
)
type IndexAction struct {
actionutils.ParentAction
}
func (this *IndexAction) Init() {
}
func (this *IndexAction) RunGet(params struct {
LocationId int64
}) {
// 获取配置
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithLocationId(this.AdminContext(), params.LocationId)
if err != nil {
this.ErrorPage(err)
return
}
this.Data["webId"] = webConfig.Id
this.Data["accessLogConfig"] = webConfig.AccessLogRef
// 通用变量
this.Data["fields"] = serverconfigs.HTTPAccessLogFields
this.Data["defaultFieldCodes"] = serverconfigs.HTTPAccessLogDefaultFieldsCodes
this.Show()
}
func (this *IndexAction) RunPost(params struct {
WebId int64
AccessLogJSON []byte
Must *actions.Must
}) {
defer this.CreateLogInfo(codes.ServerAccessLog_LogUpdateAccessLogSetting, params.WebId)
// TODO 检查参数
_, err := this.RPC().HTTPWebRPC().UpdateHTTPWebAccessLog(this.AdminContext(), &pb.UpdateHTTPWebAccessLogRequest{
HttpWebId: params.WebId,
AccessLogJSON: params.AccessLogJSON,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -0,0 +1,22 @@
package accessLog
import (
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/server/settings/locations/locationutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/serverutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
"github.com/iwind/TeaGo"
)
func init() {
TeaGo.BeforeStart(func(server *TeaGo.Server) {
server.
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeServer)).
Helper(locationutils.NewLocationHelper()).
Helper(serverutils.NewServerHelper()).
Data("tinyMenuItem", "accessLog").
Prefix("/servers/server/settings/locations/accessLog").
GetPost("", new(IndexAction)).
EndAll()
})
}

View File

@@ -0,0 +1,151 @@
package cache
import (
"encoding/json"
"github.com/TeaOSLab/EdgeAdmin/internal/utils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/dns/domains/domainutils"
"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/iwind/TeaGo/actions"
"github.com/iwind/TeaGo/maps"
"strings"
)
type IndexAction struct {
actionutils.ParentAction
}
func (this *IndexAction) Init() {
}
func (this *IndexAction) RunGet(params struct {
ServerId int64
LocationId int64
}) {
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithLocationId(this.AdminContext(), params.LocationId)
if err != nil {
this.ErrorPage(err)
return
}
this.Data["webId"] = webConfig.Id
this.Data["cacheConfig"] = webConfig.Cache
// 当前集群的缓存策略
cachePolicy, err := dao.SharedHTTPCachePolicyDAO.FindEnabledHTTPCachePolicyWithServerId(this.AdminContext(), 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
}
// 检查域名所属
serverIdResp, err := this.RPC().HTTPWebRPC().FindServerIdWithHTTPWebId(this.AdminContext(), &pb.FindServerIdWithHTTPWebIdRequest{HttpWebId: params.WebId})
if err != nil {
this.ErrorPage(err)
return
}
var serverId = serverIdResp.ServerId
if serverId <= 0 {
this.Fail("找不到要操作的网站")
return
}
existServerNameResp, err := this.RPC().ServerRPC().CheckServerNameInServer(this.AdminContext(), &pb.CheckServerNameInServerRequest{
ServerId: serverId,
ServerName: cacheConfig.Key.Host,
})
if err != nil {
this.ErrorPage(err)
return
}
if !existServerNameResp.Exists {
this.Fail("域名 '" + cacheConfig.Key.Host + "' 在当前网站中并未绑定,不能作为缓存主域名")
return
}
}
err = cacheConfig.Init()
if err != nil {
this.Fail("检查配置失败:" + err.Error())
}
// 去除不必要的部分
for _, cacheRef := range cacheConfig.CacheRefs {
cacheRef.CachePolicy = nil
}
cacheJSON, err := json.Marshal(cacheConfig)
if err != nil {
this.ErrorPage(err)
return
}
_, err = this.RPC().HTTPWebRPC().UpdateHTTPWebCache(this.AdminContext(), &pb.UpdateHTTPWebCacheRequest{
HttpWebId: params.WebId,
CacheJSON: cacheJSON,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -0,0 +1,22 @@
package cache
import (
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/server/settings/locations/locationutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/serverutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
"github.com/iwind/TeaGo"
)
func init() {
TeaGo.BeforeStart(func(server *TeaGo.Server) {
server.
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeServer)).
Helper(locationutils.NewLocationHelper()).
Helper(serverutils.NewServerHelper()).
Data("tinyMenuItem", "cache").
Prefix("/servers/server/settings/locations/cache").
GetPost("", new(IndexAction)).
EndAll()
})
}

View File

@@ -0,0 +1,89 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package cc
import (
"encoding/json"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"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/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
LocationId int64
}) {
this.Data["serverId"] = params.ServerId
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithLocationId(this.AdminContext(), params.LocationId)
if err != nil {
this.ErrorPage(err)
return
}
this.Data["webId"] = webConfig.Id
var ccConfig = serverconfigs.DefaultHTTPCCConfig()
resp, err := this.RPC().HTTPWebRPC().FindHTTPWebCC(this.AdminContext(), &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
}) {
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.AdminContext(), &pb.UpdateHTTPWebCCRequest{
HttpWebId: params.WebId,
CcJSON: params.CcJSON,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -0,0 +1,22 @@
package cc
import (
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/server/settings/locations/locationutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/serverutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
"github.com/iwind/TeaGo"
)
func init() {
TeaGo.BeforeStart(func(server *TeaGo.Server) {
server.
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeServer)).
Helper(locationutils.NewLocationHelper()).
Helper(serverutils.NewServerHelper()).
Data("tinyMenuItem", "cc").
Prefix("/servers/server/settings/locations/cc").
GetPost("", new(IndexAction)).
EndAll()
})
}

View File

@@ -0,0 +1,55 @@
package charset
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"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/iwind/TeaGo/actions"
)
type IndexAction struct {
actionutils.ParentAction
}
func (this *IndexAction) Init() {
}
func (this *IndexAction) RunGet(params struct {
LocationId int64
}) {
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithLocationId(this.AdminContext(), params.LocationId)
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.AdminContext(), &pb.UpdateHTTPWebCharsetRequest{
HttpWebId: params.WebId,
CharsetJSON: params.CharsetJSON,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -0,0 +1,22 @@
package charset
import (
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/server/settings/locations/locationutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/serverutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
"github.com/iwind/TeaGo"
)
func init() {
TeaGo.BeforeStart(func(server *TeaGo.Server) {
server.
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeServer)).
Helper(locationutils.NewLocationHelper()).
Helper(serverutils.NewServerHelper()).
Data("tinyMenuItem", "charset").
Prefix("/servers/server/settings/locations/charset").
GetPost("", new(IndexAction)).
EndAll()
})
}

View File

@@ -0,0 +1,70 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package compression
import (
"encoding/json"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/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/iwind/TeaGo/actions"
)
type IndexAction struct {
actionutils.ParentAction
}
func (this *IndexAction) Init() {
this.Nav("", "", "")
}
func (this *IndexAction) RunGet(params struct {
ServerId int64
LocationId int64
}) {
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithLocationId(this.AdminContext(), params.LocationId)
if err != nil {
this.ErrorPage(err)
return
}
this.Data["webId"] = webConfig.Id
this.Data["compressionConfig"] = webConfig.Compression
this.Show()
}
func (this *IndexAction) RunPost(params struct {
WebId int64
CompressionJSON []byte
Must *actions.Must
CSRF *actionutils.CSRF
}) {
defer this.CreateLogInfo(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.AdminContext(), &pb.UpdateHTTPWebCompressionRequest{
HttpWebId: params.WebId,
CompressionJSON: params.CompressionJSON,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -0,0 +1,22 @@
package compression
import (
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/server/settings/locations/locationutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/serverutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
"github.com/iwind/TeaGo"
)
func init() {
TeaGo.BeforeStart(func(server *TeaGo.Server) {
server.
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeServer)).
Helper(locationutils.NewLocationHelper()).
Helper(serverutils.NewServerHelper()).
Data("tinyMenuItem", "compression").
Prefix("/servers/server/settings/locations/compression").
GetPost("", new(IndexAction)).
EndAll()
})
}

View File

@@ -0,0 +1,156 @@
package locations
import (
"encoding/json"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"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/iwind/TeaGo/actions"
"regexp"
"strings"
)
// CreateAction 创建路由规则
type CreateAction struct {
actionutils.ParentAction
}
func (this *CreateAction) Init() {
this.Nav("", "setting", "create")
this.SecondMenu("locations")
}
func (this *CreateAction) RunGet(params struct {
ServerId int64
ParentId int64 // 父节点
}) {
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithServerId(this.AdminContext(), params.ServerId)
if err != nil {
this.ErrorPage(err)
return
}
this.Data["webId"] = webConfig.Id
this.Data["patternTypes"] = serverconfigs.AllLocationPatternTypes()
this.Show()
}
func (this *CreateAction) RunPost(params struct {
WebId int64
Name string
Pattern string
PatternType int
Description string
IsBreak bool
IsCaseInsensitive bool
IsReverse bool
CondsJSON []byte
DomainsJSON []byte
Must *actions.Must
}) {
defer this.CreateLogInfo(codes.HTTPLocation_LogCreateHTTPLocation, params.Pattern)
params.Must.
Field("pattern", params.Pattern).
Require("请输入路径匹配规则")
// 校验正则
if params.PatternType == serverconfigs.HTTPLocationPatternTypeRegexp {
_, err := regexp.Compile(params.Pattern)
if err != nil {
this.Fail("正则表达式校验失败:" + err.Error())
}
}
// 校验匹配条件
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())
}
}
// 自动加上前缀斜杠
if params.PatternType == serverconfigs.HTTPLocationPatternTypePrefix ||
params.PatternType == serverconfigs.HTTPLocationPatternTypeExact {
params.Pattern = "/" + strings.TrimLeft(params.Pattern, "/")
}
// 域名
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, "/")
}
}
location := &serverconfigs.HTTPLocationConfig{}
location.SetPattern(params.Pattern, params.PatternType, params.IsCaseInsensitive, params.IsReverse)
resultPattern := location.Pattern
locationResp, err := this.RPC().HTTPLocationRPC().CreateHTTPLocation(this.AdminContext(), &pb.CreateHTTPLocationRequest{
ParentId: 0, // TODO 需要实现
Name: params.Name,
Description: params.Description,
Pattern: resultPattern,
IsBreak: params.IsBreak,
CondsJSON: params.CondsJSON,
Domains: domains,
})
if err != nil {
this.ErrorPage(err)
return
}
locationId := locationResp.LocationId
// Web中Location
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithId(this.AdminContext(), params.WebId)
if err != nil {
this.ErrorPage(err)
return
}
// TODO 支持Location嵌套
webConfig.LocationRefs = append(webConfig.LocationRefs, &serverconfigs.HTTPLocationRef{
IsOn: true,
LocationId: locationId,
Children: nil,
})
refJSON, err := json.Marshal(webConfig.LocationRefs)
if err != nil {
this.ErrorPage(err)
return
}
_, err = this.RPC().HTTPWebRPC().UpdateHTTPWebLocations(this.AdminContext(), &pb.UpdateHTTPWebLocationsRequest{
HttpWebId: params.WebId,
LocationsJSON: refJSON,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -0,0 +1,40 @@
package locations
import (
"encoding/json"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
)
type DeleteAction struct {
actionutils.ParentAction
}
func (this *DeleteAction) RunPost(params struct {
WebId int64
LocationId int64
}) {
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithId(this.AdminContext(), params.WebId)
if err != nil {
this.ErrorPage(err)
return
}
webConfig.RemoveLocationRef(params.LocationId)
refJSON, err := json.Marshal(webConfig.LocationRefs)
if err != nil {
this.ErrorPage(err)
return
}
_, err = this.RPC().HTTPWebRPC().UpdateHTTPWebLocations(this.AdminContext(), &pb.UpdateHTTPWebLocationsRequest{
HttpWebId: params.WebId,
LocationsJSON: refJSON,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -0,0 +1,70 @@
package fastcgi
import (
"encoding/json"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"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/iwind/TeaGo/actions"
)
type IndexAction struct {
actionutils.ParentAction
}
func (this *IndexAction) Init() {
}
func (this *IndexAction) RunGet(params struct {
LocationId int64
}) {
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithLocationId(this.AdminContext(), params.LocationId)
if err != nil {
this.ErrorPage(err)
return
}
this.Data["webId"] = webConfig.Id
this.Data["fastcgiRef"] = webConfig.FastcgiRef
this.Data["fastcgiConfigs"] = webConfig.FastcgiList
this.Show()
}
func (this *IndexAction) RunPost(params struct {
WebId int64
FastcgiRefJSON []byte
FastcgiJSON []byte
Must *actions.Must
}) {
defer this.CreateLogInfo(codes.ServerFastcgi_LogUpdateHTTPFastcgi, params.WebId)
// TODO 检查配置
fastcgiRef := &serverconfigs.HTTPFastcgiRef{}
err := json.Unmarshal(params.FastcgiRefJSON, fastcgiRef)
if err != nil {
this.ErrorPage(err)
return
}
fastcgiRefJSON, err := json.Marshal(fastcgiRef)
if err != nil {
this.ErrorPage(err)
return
}
_, err = this.RPC().HTTPWebRPC().UpdateHTTPWebFastcgi(this.AdminContext(), &pb.UpdateHTTPWebFastcgiRequest{
HttpWebId: params.WebId,
FastcgiJSON: fastcgiRefJSON,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -0,0 +1,22 @@
package fastcgi
import (
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/server/settings/locations/locationutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/serverutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
"github.com/iwind/TeaGo"
)
func init() {
TeaGo.BeforeStart(func(server *TeaGo.Server) {
server.
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeServer)).
Helper(locationutils.NewLocationHelper()).
Helper(serverutils.NewServerHelper()).
Data("tinyMenuItem", "fastcgi").
Prefix("/servers/server/settings/locations/fastcgi").
GetPost("", new(IndexAction)).
EndAll()
})
}

View File

@@ -0,0 +1,140 @@
package headers
import (
"encoding/json"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"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/iwind/TeaGo/actions"
)
type IndexAction struct {
actionutils.ParentAction
}
func (this *IndexAction) Init() {
}
func (this *IndexAction) RunGet(params struct {
LocationId int64
}) {
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithLocationId(this.AdminContext(), params.LocationId)
if err != nil {
this.ErrorPage(err)
return
}
webId := webConfig.Id
this.Data["webId"] = webId
isChanged := false
if webConfig.RequestHeaderPolicy == nil {
createHeaderPolicyResp, err := this.RPC().HTTPHeaderPolicyRPC().CreateHTTPHeaderPolicy(this.AdminContext(), &pb.CreateHTTPHeaderPolicyRequest{})
if err != nil {
this.ErrorPage(err)
return
}
headerPolicyId := createHeaderPolicyResp.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.AdminContext(), &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.AdminContext(), &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.AdminContext(), &pb.UpdateHTTPWebResponseHeaderRequest{
HttpWebId: webId,
HeaderJSON: refJSON,
})
if err != nil {
this.ErrorPage(err)
return
}
isChanged = true
}
// 重新获取配置
if isChanged {
webConfig, err = dao.SharedHTTPWebDAO.FindWebConfigWithLocationId(this.AdminContext(), params.LocationId)
if err != nil {
this.ErrorPage(err)
return
}
}
this.Data["requestHeaderRef"] = webConfig.RequestHeaderPolicyRef
this.Data["requestHeaderPolicy"] = webConfig.RequestHeaderPolicy
this.Data["responseHeaderRef"] = webConfig.ResponseHeaderPolicyRef
this.Data["responseHeaderPolicy"] = webConfig.ResponseHeaderPolicy
this.Show()
}
func (this *IndexAction) RunPost(params struct {
WebId int64
Type string
RequestHeaderJSON []byte
ResponseHeaderJSON []byte
Must *actions.Must
}) {
defer this.CreateLogInfo(codes.ServerHTTPHeader_LogUpdateHTTPHeaders, params.WebId)
// TODO 检查配置
switch params.Type {
case "request":
_, err := this.RPC().HTTPWebRPC().UpdateHTTPWebRequestHeader(this.AdminContext(), &pb.UpdateHTTPWebRequestHeaderRequest{
HttpWebId: params.WebId,
HeaderJSON: params.RequestHeaderJSON,
})
if err != nil {
this.ErrorPage(err)
return
}
case "response":
_, err := this.RPC().HTTPWebRPC().UpdateHTTPWebResponseHeader(this.AdminContext(), &pb.UpdateHTTPWebResponseHeaderRequest{
HttpWebId: params.WebId,
HeaderJSON: params.ResponseHeaderJSON,
})
if err != nil {
this.ErrorPage(err)
return
}
}
this.Success()
}

View File

@@ -0,0 +1,22 @@
package headers
import (
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/server/settings/locations/locationutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/serverutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
"github.com/iwind/TeaGo"
)
func init() {
TeaGo.BeforeStart(func(server *TeaGo.Server) {
server.
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeServer)).
Helper(locationutils.NewLocationHelper()).
Helper(serverutils.NewServerHelper()).
Data("tinyMenuItem", "header").
Prefix("/servers/server/settings/locations/headers").
GetPost("", new(IndexAction)).
EndAll()
})
}

View File

@@ -0,0 +1,53 @@
package http
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/actions"
)
type IndexAction struct {
actionutils.ParentAction
}
func (this *IndexAction) Init() {
}
func (this *IndexAction) RunGet(params struct {
LocationId int64
}) {
// 跳转相关设置
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithLocationId(this.AdminContext(), params.LocationId)
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 {
WebId int64
RedirectToHTTPSJSON []byte
Must *actions.Must
}) {
defer this.CreateLogInfo(codes.ServerRedirect_LogUpdateRedirects, params.WebId)
// 设置跳转到HTTPS
// TODO 校验设置
_, err := this.RPC().HTTPWebRPC().UpdateHTTPWebRedirectToHTTPS(this.AdminContext(), &pb.UpdateHTTPWebRedirectToHTTPSRequest{
HttpWebId: params.WebId,
RedirectToHTTPSJSON: params.RedirectToHTTPSJSON,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -0,0 +1,22 @@
package http
import (
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/server/settings/locations/locationutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/serverutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
"github.com/iwind/TeaGo"
)
func init() {
TeaGo.BeforeStart(func(server *TeaGo.Server) {
server.
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeServer)).
Helper(locationutils.NewLocationHelper()).
Helper(serverutils.NewServerHelper()).
Data("tinyMenuItem", "http").
Prefix("/servers/server/settings/locations/http").
GetPost("", new(IndexAction)).
EndAll()
})
}

View File

@@ -0,0 +1,68 @@
package locations
import (
"encoding/json"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
"github.com/iwind/TeaGo/maps"
"strings"
)
type IndexAction struct {
actionutils.ParentAction
}
func (this *IndexAction) Init() {
this.Nav("", "setting", "index")
this.SecondMenu("locations")
}
func (this *IndexAction) RunGet(params struct {
ServerId int64
}) {
// 只有HTTP服务才支持
if this.FilterHTTPFamily() {
return
}
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithServerId(this.AdminContext(), params.ServerId)
if err != nil {
this.ErrorPage(err)
return
}
this.Data["webId"] = webConfig.Id
var locationMaps = []maps.Map{}
if webConfig.Locations != nil {
for _, location := range webConfig.Locations {
err := location.ExtractPattern()
if err != nil {
continue
}
jsonData, err := json.Marshal(location)
if err != nil {
this.ErrorPage(err)
return
}
m := maps.Map{}
err = json.Unmarshal(jsonData, &m)
if err != nil {
this.ErrorPage(err)
return
}
var pieces = strings.Split(location.Pattern, " ")
if len(pieces) == 2 {
m["pattern"] = pieces[1]
m["patternTypeName"] = serverconfigs.FindLocationPatternTypeName(location.PatternType())
} else {
m["pattern"] = location.Pattern
m["patternTypeName"] = serverconfigs.FindLocationPatternTypeName(serverconfigs.HTTPLocationPatternTypePrefix)
}
locationMaps = append(locationMaps, m)
}
}
this.Data["locations"] = locationMaps
this.Show()
}

View File

@@ -0,0 +1,22 @@
package locations
import (
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/serverutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
"github.com/iwind/TeaGo"
)
func init() {
TeaGo.BeforeStart(func(server *TeaGo.Server) {
server.
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeServer)).
Helper(serverutils.NewServerHelper()).
Prefix("/servers/server/settings/locations").
Get("", new(IndexAction)).
GetPost("/create", new(CreateAction)).
Post("/delete", new(DeleteAction)).
Post("/sort", new(SortAction)).
EndAll()
})
}

View File

@@ -0,0 +1,133 @@
package location
import (
"encoding/json"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
"github.com/iwind/TeaGo/actions"
"regexp"
"strings"
)
// IndexAction 路由规则详情
type IndexAction struct {
actionutils.ParentAction
}
func (this *IndexAction) Init() {
}
func (this *IndexAction) RunGet(params struct {
LocationId int64
}) {
var location = this.Data.Get("locationConfig")
if location == nil {
this.NotFound("location", params.LocationId)
return
}
var locationConfig = location.(*serverconfigs.HTTPLocationConfig)
this.Data["patternTypes"] = serverconfigs.AllLocationPatternTypes()
this.Data["pattern"] = locationConfig.PatternString()
this.Data["type"] = locationConfig.PatternType()
this.Data["isReverse"] = locationConfig.IsReverse()
this.Data["isCaseInsensitive"] = locationConfig.IsCaseInsensitive()
this.Data["conds"] = locationConfig.Conds
this.Data["domains"] = locationConfig.Domains
this.Show()
}
func (this *IndexAction) RunPost(params struct {
LocationId int64
Name string
Pattern string
PatternType int
Description string
IsBreak bool
IsCaseInsensitive bool
IsReverse bool
IsOn bool
CondsJSON []byte
DomainsJSON []byte
Must *actions.Must
}) {
defer this.CreateLogInfo(codes.HTTPLocation_LogUpdateHTTPLocation, params.LocationId)
params.Must.
Field("pattern", params.Pattern).
Require("请输入路由匹配规则")
// 校验正则
if params.PatternType == serverconfigs.HTTPLocationPatternTypeRegexp {
_, err := regexp.Compile(params.Pattern)
if err != nil {
this.Fail("正则表达式校验失败:" + err.Error())
}
}
// 自动加上前缀斜杠
if params.PatternType == serverconfigs.HTTPLocationPatternTypePrefix ||
params.PatternType == serverconfigs.HTTPLocationPatternTypeExact {
params.Pattern = "/" + strings.TrimLeft(params.Pattern, "/")
}
// 校验匹配条件
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())
}
}
// 域名
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, "/")
}
}
location := &serverconfigs.HTTPLocationConfig{}
location.SetPattern(params.Pattern, params.PatternType, params.IsCaseInsensitive, params.IsReverse)
resultPattern := location.Pattern
_, err := this.RPC().HTTPLocationRPC().UpdateHTTPLocation(this.AdminContext(), &pb.UpdateHTTPLocationRequest{
LocationId: params.LocationId,
Name: params.Name,
Description: params.Description,
Pattern: resultPattern,
IsBreak: params.IsBreak,
IsOn: params.IsOn,
CondsJSON: params.CondsJSON,
Domains: domains,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -0,0 +1,22 @@
package location
import (
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/server/settings/locations/locationutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/serverutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
"github.com/iwind/TeaGo"
)
func init() {
TeaGo.BeforeStart(func(server *TeaGo.Server) {
server.
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeServer)).
Helper(locationutils.NewLocationHelper()).
Helper(serverutils.NewServerHelper()).
Data("tinyMenuItem", "basic").
Prefix("/servers/server/settings/locations/location").
GetPost("", new(IndexAction)).
EndAll()
})
}

View File

@@ -0,0 +1,226 @@
package locationutils
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
"github.com/iwind/TeaGo/actions"
"github.com/iwind/TeaGo/maps"
"net/http"
)
type LocationHelper struct {
helpers.LangHelper
}
func NewLocationHelper() *LocationHelper {
return &LocationHelper{}
}
func (this *LocationHelper) BeforeAction(actionPtr actions.ActionWrapper) {
var action = actionPtr.Object()
if action.Request.Method != http.MethodGet {
return
}
var serverIdString = action.ParamString("serverId")
var locationIdString = action.ParamString("locationId")
action.Data["leftMenuItemIsDisabled"] = true
action.Data["mainMenu"] = "server"
action.Data["mainTab"] = "setting"
action.Data["secondMenuItem"] = "locations"
// 路径信息
var currentLocationConfig *serverconfigs.HTTPLocationConfig = nil
parentActionValue, ok := actionPtr.(interface {
Parent() *actionutils.ParentAction
})
if ok {
var parentAction = parentActionValue.Parent()
var locationId = action.ParamInt64("locationId")
locationConfig, isOk := FindLocationConfig(parentAction, locationId)
if !isOk {
return
}
action.Data["locationId"] = locationId
action.Data["locationConfig"] = locationConfig
currentLocationConfig = locationConfig
}
// 左侧菜单
action.Data["tinyLeftMenuItems"] = this.createMenus(serverIdString, locationIdString, action.Data.GetString("tinyMenuItem"), currentLocationConfig, actionPtr)
}
func (this *LocationHelper) createMenus(serverIdString string, locationIdString string, secondMenuItem string, locationConfig *serverconfigs.HTTPLocationConfig, actionPtr actions.ActionWrapper) []maps.Map {
menuItems := []maps.Map{}
menuItems = append(menuItems, maps.Map{
"name": this.Lang(actionPtr, codes.Server_MenuSettingBasic),
"url": "/servers/server/settings/locations/location?serverId=" + serverIdString + "&locationId=" + locationIdString,
"isActive": secondMenuItem == "basic",
"isOff": locationConfig != nil && !locationConfig.IsOn,
})
menuItems = append(menuItems, maps.Map{
"name": this.Lang(actionPtr, codes.Server_MenuSettingHTTP),
"url": "/servers/server/settings/locations/http?serverId=" + serverIdString + "&locationId=" + locationIdString,
"isActive": secondMenuItem == "http",
"isOn": locationConfig != nil && locationConfig.Web != nil && locationConfig.Web.RedirectToHttps != nil && locationConfig.Web.RedirectToHttps.IsPrior,
})
menuItems = append(menuItems, maps.Map{
"name": this.Lang(actionPtr, codes.Server_MenuSettingOrigins),
"url": "/servers/server/settings/locations/reverseProxy?serverId=" + serverIdString + "&locationId=" + locationIdString,
"isActive": secondMenuItem == "reverseProxy",
"isOn": locationConfig != nil && locationConfig.ReverseProxyRef != nil && locationConfig.ReverseProxyRef.IsPrior,
})
menuItems = this.filterMenuItems1(locationConfig, menuItems, serverIdString, locationIdString, secondMenuItem, actionPtr)
menuItems = append(menuItems, maps.Map{
"name": "-",
"url": "",
"isActive": false,
})
menuItems = append(menuItems, maps.Map{
"name": this.Lang(actionPtr, codes.Server_MenuSettingRewriteRules),
"url": "/servers/server/settings/locations/rewrite?serverId=" + serverIdString + "&locationId=" + locationIdString,
"isActive": secondMenuItem == "rewrite",
"isOn": locationConfig != nil && locationConfig.Web != nil && len(locationConfig.Web.RewriteRefs) > 0,
})
menuItems = append(menuItems, maps.Map{
"name": this.Lang(actionPtr, codes.Server_MenuSettingWAF),
"url": "/servers/server/settings/locations/waf?serverId=" + serverIdString + "&locationId=" + locationIdString,
"isActive": secondMenuItem == "waf",
"isOn": locationConfig != nil && locationConfig.Web != nil && locationConfig.Web.FirewallRef != nil && locationConfig.Web.FirewallRef.IsPrior,
})
menuItems = append(menuItems, maps.Map{
"name": this.Lang(actionPtr, codes.Server_MenuSettingCache),
"url": "/servers/server/settings/locations/cache?serverId=" + serverIdString + "&locationId=" + locationIdString,
"isActive": secondMenuItem == "cache",
"isOn": locationConfig != nil && locationConfig.Web != nil && locationConfig.Web.Cache != nil && locationConfig.Web.Cache.IsPrior && locationConfig.Web.Cache.IsOn,
})
menuItems = append(menuItems, maps.Map{
"name": this.Lang(actionPtr, codes.Server_MenuSettingAuth),
"url": "/servers/server/settings/locations/access?serverId=" + serverIdString + "&locationId=" + locationIdString,
"isActive": secondMenuItem == "access",
"isOn": locationConfig != nil && locationConfig.Web != nil && locationConfig.Web.Auth != nil && locationConfig.Web.Auth.IsPrior,
})
menuItems = append(menuItems, maps.Map{
"name": this.Lang(actionPtr, codes.Server_MenuSettingReferers),
"url": "/servers/server/settings/locations/referers?serverId=" + serverIdString + "&locationId=" + locationIdString,
"isActive": secondMenuItem == "referer",
"isOn": locationConfig.Web != nil && locationConfig.Web.Referers != nil && locationConfig.Web.Referers.IsPrior,
})
menuItems = append(menuItems, maps.Map{
"name": this.Lang(actionPtr, codes.Server_MenuSettingUserAgents),
"url": "/servers/server/settings/locations/userAgent?serverId=" + serverIdString + "&locationId=" + locationIdString,
"isActive": secondMenuItem == "userAgent",
"isOn": locationConfig.Web != nil && locationConfig.Web.UserAgent != nil && locationConfig.Web.UserAgent.IsPrior,
})
menuItems = append(menuItems, maps.Map{
"name": this.Lang(actionPtr, codes.Server_MenuSettingAccessLog),
"url": "/servers/server/settings/locations/accessLog?serverId=" + serverIdString + "&locationId=" + locationIdString,
"isActive": secondMenuItem == "accessLog",
"isOn": locationConfig != nil && locationConfig.Web != nil && locationConfig.Web.AccessLogRef != nil && locationConfig.Web.AccessLogRef.IsPrior,
})
menuItems = append(menuItems, maps.Map{
"name": this.Lang(actionPtr, codes.Server_MenuSettingCompression),
"url": "/servers/server/settings/locations/compression?serverId=" + serverIdString + "&locationId=" + locationIdString,
"isActive": secondMenuItem == "compression",
"isOn": locationConfig != nil && locationConfig.Web != nil && locationConfig.Web.Compression != nil && locationConfig.Web.Compression.IsPrior,
})
menuItems = append(menuItems, maps.Map{
"name": this.Lang(actionPtr, codes.Server_MenuSettingPages),
"url": "/servers/server/settings/locations/pages?serverId=" + serverIdString + "&locationId=" + locationIdString,
"isActive": secondMenuItem == "pages",
"isOn": locationConfig != nil && locationConfig.Web != nil && (len(locationConfig.Web.Pages) > 0 || (locationConfig.Web.Shutdown != nil && locationConfig.Web.Shutdown.IsPrior)),
})
menuItems = append(menuItems, maps.Map{
"name": this.Lang(actionPtr, codes.Server_MenuSettingHTTPHeaders),
"url": "/servers/server/settings/locations/headers?serverId=" + serverIdString + "&locationId=" + locationIdString,
"isActive": secondMenuItem == "header",
"isOn": locationConfig != nil && this.hasHTTPHeaders(locationConfig.Web),
})
menuItems = append(menuItems, maps.Map{
"name": this.Lang(actionPtr, codes.Server_MenuSettingWebsocket),
"url": "/servers/server/settings/locations/websocket?serverId=" + serverIdString + "&locationId=" + locationIdString,
"isActive": secondMenuItem == "websocket",
"isOn": locationConfig != nil && locationConfig.Web != nil && locationConfig.Web.WebsocketRef != nil && locationConfig.Web.WebsocketRef.IsPrior,
})
menuItems = append(menuItems, maps.Map{
"name": this.Lang(actionPtr, codes.Server_MenuSettingWebP),
"url": "/servers/server/settings/locations/webp?serverId=" + serverIdString + "&locationId=" + locationIdString,
"isActive": secondMenuItem == "webp",
"isOn": locationConfig != nil && locationConfig.Web != nil && locationConfig.Web.WebP != nil && locationConfig.Web.WebP.IsPrior,
})
menuItems = this.filterMenuItems3(locationConfig, menuItems, serverIdString, locationIdString, secondMenuItem, actionPtr)
menuItems = append(menuItems, maps.Map{
"name": this.Lang(actionPtr, codes.Server_MenuSettingStat),
"url": "/servers/server/settings/locations/stat?serverId=" + serverIdString + "&locationId=" + locationIdString,
"isActive": secondMenuItem == "stat",
"isOn": locationConfig != nil && locationConfig.Web != nil && locationConfig.Web.StatRef != nil && locationConfig.Web.StatRef.IsPrior,
})
menuItems = append(menuItems, maps.Map{
"name": this.Lang(actionPtr, codes.Server_MenuSettingCharset),
"url": "/servers/server/settings/locations/charset?serverId=" + serverIdString + "&locationId=" + locationIdString,
"isActive": secondMenuItem == "charset",
"isOn": locationConfig != nil && locationConfig.Web != nil && locationConfig.Web.Charset != nil && locationConfig.Web.Charset.IsPrior,
})
menuItems = append(menuItems, maps.Map{
"name": this.Lang(actionPtr, codes.Server_MenuSettingRoot),
"url": "/servers/server/settings/locations/web?serverId=" + serverIdString + "&locationId=" + locationIdString,
"isActive": secondMenuItem == "web",
"isOn": locationConfig != nil && locationConfig.Web != nil && locationConfig.Web.Root != nil && locationConfig.Web.Root.IsPrior,
})
menuItems = append(menuItems, maps.Map{
"name": this.Lang(actionPtr, codes.Server_MenuSettingFastcgi),
"url": "/servers/server/settings/locations/fastcgi?serverId=" + serverIdString + "&locationId=" + locationIdString,
"isActive": secondMenuItem == "fastcgi",
"isOn": locationConfig != nil && locationConfig.Web != nil && locationConfig.Web.FastcgiRef != nil && locationConfig.Web.FastcgiRef.IsPrior,
})
menuItems = this.filterMenuItems2(locationConfig, menuItems, serverIdString, locationIdString, secondMenuItem, actionPtr)
menuItems = append(menuItems, maps.Map{
"name": "-",
"url": "",
"isActive": false,
})
menuItems = append(menuItems, maps.Map{
"name": this.Lang(actionPtr, codes.Server_MenuSettingClientIP),
"url": "/servers/server/settings/locations/remoteAddr?serverId=" + serverIdString + "&locationId=" + locationIdString,
"isActive": secondMenuItem == "remoteAddr",
"isOn": locationConfig != nil && locationConfig.Web != nil && locationConfig.Web.RemoteAddr != nil && locationConfig.Web.RemoteAddr.IsOn,
})
menuItems = append(menuItems, maps.Map{
"name": this.Lang(actionPtr, codes.Server_MenuSettingRequestLimit),
"url": "/servers/server/settings/locations/requestLimit?serverId=" + serverIdString + "&locationId=" + locationIdString,
"isActive": secondMenuItem == "requestLimit",
"isOn": locationConfig != nil && locationConfig.Web != nil && locationConfig.Web.RequestLimit != nil && locationConfig.Web.RequestLimit.IsOn,
})
return menuItems
}
// 检查是否已设置Header
func (this *LocationHelper) hasHTTPHeaders(web *serverconfigs.HTTPWebConfig) bool {
if web == nil {
return false
}
if web.RequestHeaderPolicyRef != nil && web.RequestHeaderPolicyRef.IsPrior {
if web.RequestHeaderPolicyRef.IsOn && web.RequestHeaderPolicy != nil && !web.RequestHeaderPolicy.IsEmpty() {
return true
}
}
if web.ResponseHeaderPolicyRef != nil && web.ResponseHeaderPolicyRef.IsPrior {
if web.ResponseHeaderPolicyRef.IsOn && web.ResponseHeaderPolicy != nil && !web.ResponseHeaderPolicy.IsEmpty() {
return true
}
}
return false
}

View File

@@ -0,0 +1,22 @@
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
//go:build !plus
package locationutils
import (
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
"github.com/iwind/TeaGo/actions"
"github.com/iwind/TeaGo/maps"
)
func (this *LocationHelper) filterMenuItems1(locationConfig *serverconfigs.HTTPLocationConfig, menuItems []maps.Map, serverIdString string, locationIdString string, secondMenuItem string, actionPtr actions.ActionWrapper) []maps.Map {
return menuItems
}
func (this *LocationHelper) filterMenuItems2(locationConfig *serverconfigs.HTTPLocationConfig, menuItems []maps.Map, serverIdString string, locationIdString string, secondMenuItem string, actionPtr actions.ActionWrapper) []maps.Map {
return menuItems
}
func (this *LocationHelper) filterMenuItems3(locationConfig *serverconfigs.HTTPLocationConfig, menuItems []maps.Map, serverIdString string, locationIdString string, secondMenuItem string, actionPtr actions.ActionWrapper) []maps.Map {
return menuItems
}

View File

@@ -0,0 +1,82 @@
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
//go:build plus
package locationutils
import (
teaconst "github.com/TeaOSLab/EdgeAdmin/internal/const"
"github.com/TeaOSLab/EdgeAdmin/internal/plus"
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
plusutils "github.com/TeaOSLab/EdgePlus/pkg/utils"
"github.com/iwind/TeaGo/actions"
"github.com/iwind/TeaGo/maps"
)
func (this *LocationHelper) filterMenuItems1(locationConfig *serverconfigs.HTTPLocationConfig, menuItems []maps.Map, serverIdString string, locationIdString string, secondMenuItem string, actionPtr actions.ActionWrapper) []maps.Map {
if teaconst.IsPlus {
menuItems = append(menuItems, maps.Map{
"name": "-",
"url": "",
"isActive": false,
})
menuItems = append(menuItems, maps.Map{
"name": this.Lang(actionPtr, codes.Server_MenuSettingUAM),
"url": "/servers/server/settings/locations/uam?serverId=" + serverIdString + "&locationId=" + locationIdString,
"isActive": secondMenuItem == "uam",
"isOn": locationConfig.Web != nil && locationConfig.Web.UAM != nil && locationConfig.Web.UAM.IsPrior && locationConfig.Web.UAM.IsOn,
"isOff": locationConfig.Web != nil && locationConfig.Web.UAM != nil && locationConfig.Web.UAM.IsPrior && !locationConfig.Web.UAM.IsOn,
"isImportant": locationConfig.Web != nil && locationConfig.Web.UAM != nil && locationConfig.Web.UAM.IsPrior && locationConfig.Web.UAM.IsOn,
})
menuItems = append(menuItems, maps.Map{
"name": this.Lang(actionPtr, codes.Server_MenuSettingCC),
"url": "/servers/server/settings/locations/cc?serverId=" + serverIdString + "&locationId=" + locationIdString,
"isActive": secondMenuItem == "cc",
"isOn": locationConfig.Web != nil && locationConfig.Web.CC != nil && locationConfig.Web.CC.IsPrior && locationConfig.Web.CC.IsOn,
"isOff": locationConfig.Web != nil && locationConfig.Web.CC != nil && locationConfig.Web.CC.IsPrior && !locationConfig.Web.CC.IsOn,
"isImportant": locationConfig.Web != nil && locationConfig.Web.CC != nil && locationConfig.Web.CC.IsPrior && locationConfig.Web.CC.IsOn,
})
}
return menuItems
}
func (this *LocationHelper) filterMenuItems2(locationConfig *serverconfigs.HTTPLocationConfig, menuItems []maps.Map, serverIdString string, locationIdString string, secondMenuItem string, actionPtr actions.ActionWrapper) []maps.Map {
if teaconst.IsPlus {
if plus.AllowComponent(plus.ComponentCodeComputing) {
if locationConfig.Web != nil && locationConfig.Web.RequestScripts != nil {
_ = locationConfig.Web.RequestScripts.Init()
}
menuItems = append(menuItems, maps.Map{
"name": this.Lang(actionPtr, codes.Server_MenuSettingScripts),
"url": "/servers/server/settings/locations/requestScripts?serverId=" + serverIdString + "&locationId=" + locationIdString,
"isActive": secondMenuItem == "requestScripts",
"isOn": locationConfig.Web != nil && locationConfig.Web.RequestScripts != nil && !locationConfig.Web.RequestScripts.IsEmpty(),
})
}
}
return menuItems
}
func (this *LocationHelper) filterMenuItems3(locationConfig *serverconfigs.HTTPLocationConfig, menuItems []maps.Map, serverIdString string, locationIdString string, secondMenuItem string, actionPtr actions.ActionWrapper) []maps.Map {
if teaconst.IsPlus {
menuItems = append(menuItems, maps.Map{
"name": this.Lang(actionPtr, codes.Server_MenuSettingOptimization),
"url": "/servers/server/settings/locations/optimization?serverId=" + serverIdString + "&locationId=" + locationIdString,
"isActive": secondMenuItem == "optimization",
"isOn": locationConfig.Web != nil && locationConfig.Web.Optimization != nil && locationConfig.Web.Optimization.IsPrior,
})
if plusutils.CompareEdition(plus.PlusEdition, plusutils.EditionPro) >= 0 {
menuItems = append(menuItems, maps.Map{
"name": this.Lang(actionPtr, codes.Server_MenuSettingMultimedia),
"url": "/servers/server/settings/locations/multimedia?serverId=" + serverIdString + "&locationId=" + locationIdString,
"isActive": secondMenuItem == "multimedia",
"isOn": locationConfig.Web != nil && locationConfig.Web.HLS != nil && locationConfig.Web.HLS.IsPrior,
"configCode": "",
})
}
}
return menuItems
}

View File

@@ -0,0 +1,42 @@
package locationutils
import (
"context"
"encoding/json"
"errors"
"github.com/TeaOSLab/EdgeAdmin/internal/utils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
"github.com/iwind/TeaGo/types"
)
// FindLocationConfig 查找路由规则配置
func FindLocationConfig(parentAction *actionutils.ParentAction, locationId int64) (locationConfig *serverconfigs.HTTPLocationConfig, isOk bool) {
locationConfigResp, err := parentAction.RPC().HTTPLocationRPC().FindEnabledHTTPLocationConfig(parentAction.AdminContext(), &pb.FindEnabledHTTPLocationConfigRequest{LocationId: locationId})
if err != nil {
parentAction.ErrorPage(err)
return
}
if utils.JSONIsNull(locationConfigResp.LocationJSON) {
parentAction.ErrorPage(errors.New("location '" + types.String(locationId) + "' not found"))
return
}
locationConfig = &serverconfigs.HTTPLocationConfig{}
err = json.Unmarshal(locationConfigResp.LocationJSON, locationConfig)
if err != nil {
parentAction.ErrorPage(err)
return
}
err = locationConfig.Init(context.TODO())
if err != nil {
parentAction.ErrorPage(err)
return
}
isOk = true
return
}

View File

@@ -0,0 +1,107 @@
// Copyright 2024 GoEdge CDN goedge.cdn@gmail.com. All rights reserved. Official site: https://goedge.cn .
//go:build plus
package referers
import (
"encoding/json"
teaconst "github.com/TeaOSLab/EdgeAdmin/internal/const"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"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/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
LocationId int64
}) {
// 只有商业版才支持此功能
if !teaconst.IsPlus {
return
}
this.Data["serverId"] = params.ServerId
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithLocationId(this.AdminContext(), params.LocationId)
if err != nil {
this.ErrorPage(err)
return
}
this.Data["webId"] = webConfig.Id
hlsResp, err := this.RPC().HTTPWebRPC().FindHTTPWebHLS(this.AdminContext(), &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
}) {
// 只有商业版才支持此功能
if !teaconst.IsPlus {
return
}
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.AdminContext(), &pb.UpdateHTTPWebHLSRequest{
HttpWebId: params.WebId,
HlsJSON: hlsJSON,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -0,0 +1,31 @@
// Copyright 2024 GoEdge CDN goedge.cdn@gmail.com. All rights reserved. Official site: https://goedge.cn .
//go:build plus
package referers
import (
teaconst "github.com/TeaOSLab/EdgeAdmin/internal/const"
"github.com/TeaOSLab/EdgeAdmin/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
LocationId int64
}) {
// 只有商业版才支持此功能
if !teaconst.IsPlus {
return
}
this.RedirectURL("./multimedia/hls?serverId=" + types.String(params.ServerId) + "&locationId=" + types.String(params.LocationId))
}

View File

@@ -0,0 +1,25 @@
//go:build plus
package referers
import (
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/server/settings/locations/locationutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/serverutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
"github.com/iwind/TeaGo"
)
func init() {
TeaGo.BeforeStart(func(server *TeaGo.Server) {
server.
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeServer)).
Helper(locationutils.NewLocationHelper()).
Helper(serverutils.NewServerHelper()).
Data("tinyMenuItem", "multimedia").
Prefix("/servers/server/settings/locations/multimedia").
GetPost("", new(IndexAction)).
GetPost("/hls", new(HlsAction)).
EndAll()
})
}

View File

@@ -0,0 +1,87 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
//go:build plus
package optimization
import (
"encoding/json"
teaconst "github.com/TeaOSLab/EdgeAdmin/internal/const"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"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/iwind/TeaGo/actions"
)
type IndexAction struct {
actionutils.ParentAction
}
func (this *IndexAction) Init() {
this.Nav("", "setting", "index")
this.SecondMenu("optimization")
}
func (this *IndexAction) RunGet(params struct {
ServerId int64
LocationId int64
}) {
// 只有商业版才支持此功能
if !teaconst.IsPlus {
return
}
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithLocationId(this.AdminContext(), params.LocationId)
if err != nil {
this.ErrorPage(err)
return
}
if webConfig.Optimization == nil {
webConfig.Optimization = serverconfigs.NewHTTPPageOptimizationConfig()
}
this.Data["webId"] = webConfig.Id
this.Data["optimizationConfig"] = webConfig.Optimization
this.Show()
}
func (this *IndexAction) RunPost(params struct {
WebId int64
OptimizationJSON []byte
Must *actions.Must
CSRF *actionutils.CSRF
}) {
// 只有商业版才支持此功能
if !teaconst.IsPlus {
return
}
defer this.CreateLogInfo(codes.ServerOptimization_LogUpdateOptimizationSettings, params.WebId)
// 校验配置
var optimizationConfig = serverconfigs.NewHTTPPageOptimizationConfig()
err := json.Unmarshal(params.OptimizationJSON, optimizationConfig)
if err != nil {
this.Fail("配置校验失败:" + err.Error())
}
err = optimizationConfig.Init()
if err != nil {
this.Fail("配置校验失败:" + err.Error())
}
_, err = this.RPC().HTTPWebRPC().UpdateHTTPWebOptimization(this.AdminContext(), &pb.UpdateHTTPWebOptimizationRequest{
HttpWebId: params.WebId,
OptimizationJSON: params.OptimizationJSON,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -0,0 +1,24 @@
//go:build plus
package optimization
import (
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/server/settings/locations/locationutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/serverutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
"github.com/iwind/TeaGo"
)
func init() {
TeaGo.BeforeStart(func(server *TeaGo.Server) {
server.
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeServer)).
Helper(locationutils.NewLocationHelper()).
Helper(serverutils.NewServerHelper()).
Data("tinyMenuItem", "optimization").
Prefix("/servers/server/settings/locations/optimization").
GetPost("", new(IndexAction)).
EndAll()
})
}

View File

@@ -0,0 +1,74 @@
package pages
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/actions"
)
type IndexAction struct {
actionutils.ParentAction
}
func (this *IndexAction) Init() {
}
func (this *IndexAction) RunGet(params struct {
LocationId int64
}) {
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithLocationId(this.AdminContext(), params.LocationId)
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 string
ShutdownJSON string
Must *actions.Must
}) {
defer this.CreateLogInfo(codes.ServerPage_LogUpdatePages, params.WebId)
// TODO 检查配置
_, err := this.RPC().HTTPWebRPC().UpdateHTTPWebGlobalPagesEnabled(this.AdminContext(), &pb.UpdateHTTPWebGlobalPagesEnabledRequest{
HttpWebId: params.WebId,
IsEnabled: params.EnableGlobalPages,
})
if err != nil {
this.ErrorPage(err)
return
}
_, err = this.RPC().HTTPWebRPC().UpdateHTTPWebPages(this.AdminContext(), &pb.UpdateHTTPWebPagesRequest{
HttpWebId: params.WebId,
PagesJSON: []byte(params.PagesJSON),
})
if err != nil {
this.ErrorPage(err)
return
}
_, err = this.RPC().HTTPWebRPC().UpdateHTTPWebShutdown(this.AdminContext(), &pb.UpdateHTTPWebShutdownRequest{
HttpWebId: params.WebId,
ShutdownJSON: []byte(params.ShutdownJSON),
})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -0,0 +1,22 @@
package pages
import (
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/server/settings/locations/locationutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/serverutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
"github.com/iwind/TeaGo"
)
func init() {
TeaGo.BeforeStart(func(server *TeaGo.Server) {
server.
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeServer)).
Helper(locationutils.NewLocationHelper()).
Helper(serverutils.NewServerHelper()).
Data("tinyMenuItem", "pages").
Prefix("/servers/server/settings/locations/pages").
GetPost("", new(IndexAction)).
EndAll()
})
}

View File

@@ -0,0 +1,70 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package referers
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"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/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 {
LocationId int64
}) {
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithLocationId(this.AdminContext(), params.LocationId)
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
}) {
defer this.CreateLogInfo(codes.ServerReferer_LogUpdateReferers, params.WebId)
_, err := this.RPC().HTTPWebRPC().UpdateHTTPWebReferers(this.AdminContext(), &pb.UpdateHTTPWebReferersRequest{
HttpWebId: params.WebId,
ReferersJSON: params.ReferersJSON,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -0,0 +1,22 @@
package referers
import (
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/server/settings/locations/locationutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/serverutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
"github.com/iwind/TeaGo"
)
func init() {
TeaGo.BeforeStart(func(server *TeaGo.Server) {
server.
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeServer)).
Helper(locationutils.NewLocationHelper()).
Helper(serverutils.NewServerHelper()).
Data("tinyMenuItem", "referer").
Prefix("/servers/server/settings/locations/referers").
GetPost("", new(IndexAction)).
EndAll()
})
}

View File

@@ -0,0 +1,95 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package remoteAddr
import (
"encoding/json"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
"github.com/iwind/TeaGo/actions"
"regexp"
"strings"
)
type IndexAction struct {
actionutils.ParentAction
}
func (this *IndexAction) Init() {
}
func (this *IndexAction) RunGet(params struct {
LocationId int64
}) {
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithLocationId(this.AdminContext(), params.LocationId)
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.AdminContext(), &pb.UpdateHTTPWebRemoteAddrRequest{
HttpWebId: params.WebId,
RemoteAddrJSON: remoteAddrJSON,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -0,0 +1,22 @@
package remoteAddr
import (
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/server/settings/locations/locationutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/serverutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
"github.com/iwind/TeaGo"
)
func init() {
TeaGo.BeforeStart(func(server *TeaGo.Server) {
server.
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeServer)).
Helper(locationutils.NewLocationHelper()).
Helper(serverutils.NewServerHelper()).
Data("tinyMenuItem", "remoteAddr").
Prefix("/servers/server/settings/locations/remoteAddr").
GetPost("", new(IndexAction)).
EndAll()
})
}

View File

@@ -0,0 +1,56 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package requestlimit
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/actions"
)
type IndexAction struct {
actionutils.ParentAction
}
func (this *IndexAction) Init() {
}
func (this *IndexAction) RunGet(params struct {
ServerId int64
LocationId int64
}) {
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithLocationId(this.AdminContext(), params.LocationId)
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
}) {
defer this.CreateLogInfo(codes.ServerRequestLimit_LogUpdateRequestLimitSettings, params.WebId)
_, err := this.RPC().HTTPWebRPC().UpdateHTTPWebRequestLimit(this.AdminContext(), &pb.UpdateHTTPWebRequestLimitRequest{
HttpWebId: params.WebId,
RequestLimitJSON: params.RequestLimitJSON,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

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