Compare commits
60 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0d02e3f15a | ||
|
|
bf82f22d0f | ||
|
|
e18f182ce6 | ||
|
|
761c26b587 | ||
|
|
5e62769dcf | ||
|
|
86b8a718a0 | ||
|
|
a729cfc31d | ||
|
|
96cfda852a | ||
|
|
0423d9246c | ||
|
|
985798757f | ||
|
|
72876f6749 | ||
|
|
03d6e223d8 | ||
|
|
62d9f2ed97 | ||
|
|
a550a44a52 | ||
|
|
b19d586949 | ||
|
|
bbfa3ee57f | ||
|
|
af409dd3b8 | ||
|
|
3db79ca149 | ||
|
|
e880420494 | ||
|
|
28ec17b8fe | ||
|
|
8026a40807 | ||
|
|
068c6d406a | ||
|
|
57470e4ef0 | ||
|
|
ca8e1537f5 | ||
|
|
d67b818398 | ||
|
|
f5f46424bb | ||
|
|
1e259717ce | ||
|
|
91ece99a9c | ||
|
|
d30ebdb369 | ||
|
|
ade8522b69 | ||
|
|
159b308f31 | ||
|
|
837bf25f7b | ||
|
|
8301d3669b | ||
|
|
cc752e8d80 | ||
|
|
d20e6bd42f | ||
|
|
bfee9fe233 | ||
|
|
9c962b09f1 | ||
|
|
46edefead7 | ||
|
|
725cfc8a2b | ||
|
|
1ce48b9ef4 | ||
|
|
37cc28f225 | ||
|
|
5ebe3bb8e0 | ||
|
|
aa01512f89 | ||
|
|
37ff2b886a | ||
|
|
ce18212756 | ||
|
|
08f50a274a | ||
|
|
892ee0013a | ||
|
|
e9a47041fd | ||
|
|
d419fa06e8 | ||
|
|
8b961a890c | ||
|
|
db32915114 | ||
|
|
2ffdb10cce | ||
|
|
507fd7e5d4 | ||
|
|
7df599b5a9 | ||
|
|
9987334f55 | ||
|
|
d8c3365384 | ||
|
|
2e284b5af9 | ||
|
|
89ddd4e6a3 | ||
|
|
36524ea481 | ||
|
|
35cf693610 |
@@ -1,10 +1,11 @@
|
||||
FROM alpine:latest
|
||||
LABEL maintainer="iwind.liu@gmail.com"
|
||||
ENV TZ "Asia/Shanghai"
|
||||
ENV VERSION 0.5.7
|
||||
ENV VERSION 0.6.2
|
||||
ENV ROOT_DIR /usr/local/goedge
|
||||
ENV TAR_FILE edge-admin-linux-amd64-plus-v${VERSION}.zip
|
||||
ENV TAR_URL "https://dl.goedge.cn/edge/v${VERSION}/edge-admin-linux-amd64-plus-v${VERSION}.zip"
|
||||
#ENV TAR_URL "http://192.168.2.60:8080/edge-admin-linux-amd64-plus-v${VERSION}.zip" # your local repository
|
||||
|
||||
RUN apk add --no-cache tzdata
|
||||
|
||||
|
||||
8
go.mod
8
go.mod
@@ -15,9 +15,9 @@ require (
|
||||
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
|
||||
github.com/tealeg/xlsx/v3 v3.2.3
|
||||
github.com/xlzd/gotp v0.0.0-20181030022105-c8557ba2c119
|
||||
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad
|
||||
golang.org/x/sys v0.2.0
|
||||
google.golang.org/grpc v1.45.0
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
)
|
||||
|
||||
require (
|
||||
@@ -36,8 +36,8 @@ require (
|
||||
github.com/rogpeppe/fastuuid v1.2.0 // indirect
|
||||
github.com/shabbyrobe/xmlwriter v0.0.0-20200208144257-9fca06d00ffa // indirect
|
||||
github.com/yusufpapurcu/wmi v1.2.2 // indirect
|
||||
golang.org/x/net v0.0.0-20220225172249-27dd8689420f // indirect
|
||||
golang.org/x/text v0.3.7 // indirect
|
||||
golang.org/x/net v0.2.0 // indirect
|
||||
golang.org/x/text v0.4.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20220317150908-0efb43f6373e // indirect
|
||||
google.golang.org/protobuf v1.27.1 // indirect
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
|
||||
|
||||
20
go.sum
20
go.sum
@@ -74,6 +74,7 @@ github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/
|
||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/iwind/TeaGo v0.0.0-20210411134150-ddf57e240c2f/go.mod h1:KU4mS7QNiZ7QWEuDBk1zw0/Q2LrAPZv3tycEFBsuUwc=
|
||||
github.com/iwind/TeaGo v0.0.0-20220304043459-0dd944a5b475 h1:EseyfFaQOjWanGiby9KMw7PjDBMg/95tLDgIw/ns0Cw=
|
||||
github.com/iwind/TeaGo v0.0.0-20220304043459-0dd944a5b475/go.mod h1:HRHK0zoC/og3c9/hKosD9yYVMTnnzm3PgXUdhRYHaLc=
|
||||
github.com/iwind/gosock v0.0.0-20211103081026-ee4652210ca4 h1:VWGsCqTzObdlbf7UUE3oceIpcEKi4C/YBUszQXk118A=
|
||||
@@ -170,8 +171,8 @@ golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/
|
||||
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||
golang.org/x/net v0.0.0-20220225172249-27dd8689420f h1:oA4XRj0qtSt8Yo1Zms0CUlsT3KG69V2UGQWPBxujDmc=
|
||||
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/net v0.2.0 h1:sZfSu1wtKLGlWI4ZZayP0ck9Y73K1ynO6gqzTdBVdPU=
|
||||
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
@@ -198,20 +199,16 @@ golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad h1:ntjMns5wyP/fN65tdBD4g8J5w8n015+iIIs9rtjXkY0=
|
||||
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.2.0 h1:ljd4t30dBnAvMZaQCevtY0xLLD0A+bRZXbgLMLU1F/A=
|
||||
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg=
|
||||
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
@@ -266,7 +263,8 @@ gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package teaconst
|
||||
|
||||
const (
|
||||
Version = "0.5.8"
|
||||
Version = "0.6.3"
|
||||
|
||||
APINodeVersion = "0.5.8"
|
||||
APINodeVersion = "0.6.3"
|
||||
|
||||
ProductName = "Edge Admin"
|
||||
ProcessName = "edge-admin"
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/server/settings/conds/condutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/files"
|
||||
@@ -115,6 +116,16 @@ func generateComponentsJSFile() error {
|
||||
buffer.Write([]byte{'\n', '\n'})
|
||||
}
|
||||
|
||||
// WAF操作符
|
||||
wafOperatorsJSON, err := json.Marshal(firewallconfigs.AllRuleOperators)
|
||||
if err != nil {
|
||||
logs.Println("ComponentsAction marshal waf rule operators failed: " + err.Error())
|
||||
} else {
|
||||
buffer.WriteString("window.WAF_RULE_OPERATORS = ")
|
||||
buffer.Write(wafOperatorsJSON)
|
||||
buffer.Write([]byte{'\n', '\n'})
|
||||
}
|
||||
|
||||
fp, err := os.OpenFile(filepath.Clean(Tea.PublicFile("/js/components.src.js")), os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0777)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
package utils_test
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/utils"
|
||||
"github.com/iwind/TeaGo/assert"
|
||||
"testing"
|
||||
)
|
||||
|
||||
@@ -85,6 +85,10 @@ func (this *IndexAction) RunPost(params struct {
|
||||
|
||||
LogRecordServerError bool
|
||||
|
||||
PerformanceAutoReadTimeout bool
|
||||
PerformanceAutoWriteTimeout bool
|
||||
PerformanceDebug bool
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
@@ -124,17 +128,25 @@ func (this *IndexAction) RunPost(params struct {
|
||||
}
|
||||
}
|
||||
|
||||
// 域名
|
||||
config.HTTPAll.AllowMismatchDomains = allowMismatchDomains
|
||||
config.HTTPAll.AllowNodeIP = params.HttpAllAllowNodeIP
|
||||
config.HTTPAll.DefaultDomain = params.HttpAllDefaultDomain
|
||||
|
||||
// 访问日志
|
||||
config.HTTPAccessLog.EnableRequestHeaders = params.HttpAccessLogEnableRequestHeaders
|
||||
config.HTTPAccessLog.EnableResponseHeaders = params.HttpAccessLogEnableResponseHeaders
|
||||
config.HTTPAccessLog.CommonRequestHeadersOnly = params.HttpAccessLogCommonRequestHeadersOnly
|
||||
config.HTTPAccessLog.EnableCookies = params.HttpAccessLogEnableCookies
|
||||
|
||||
// 日志
|
||||
config.Log.RecordServerError = params.LogRecordServerError
|
||||
|
||||
// 性能
|
||||
config.Performance.AutoReadTimeout = params.PerformanceAutoReadTimeout
|
||||
config.Performance.AutoWriteTimeout = params.PerformanceAutoWriteTimeout
|
||||
config.Performance.Debug = params.PerformanceDebug
|
||||
|
||||
err = config.Init()
|
||||
if err != nil {
|
||||
this.Fail("配置校验失败:" + err.Error())
|
||||
|
||||
@@ -89,6 +89,19 @@ func (this *IndexAction) RunGet(params struct {
|
||||
}
|
||||
}
|
||||
|
||||
// DNS信息
|
||||
var fullDomainName = ""
|
||||
if len(cluster.DnsName) > 0 && cluster.DnsDomainId > 0 {
|
||||
domainResp, err := this.RPC().DNSDomainRPC().FindBasicDNSDomain(this.AdminContext(), &pb.FindBasicDNSDomainRequest{DnsDomainId: cluster.DnsDomainId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if domainResp.DnsDomain != nil {
|
||||
fullDomainName = cluster.DnsName + "." + domainResp.DnsDomain.Name
|
||||
}
|
||||
}
|
||||
|
||||
this.Data["cluster"] = maps.Map{
|
||||
"id": cluster.Id,
|
||||
"name": cluster.Name,
|
||||
@@ -100,6 +113,7 @@ func (this *IndexAction) RunGet(params struct {
|
||||
"autoRemoteStart": cluster.AutoRemoteStart,
|
||||
"autoInstallNftables": cluster.AutoInstallNftables,
|
||||
"sshParams": sshParams,
|
||||
"domainName": fullDomainName,
|
||||
}
|
||||
|
||||
// 默认值
|
||||
|
||||
@@ -3,23 +3,38 @@ package tasks
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"time"
|
||||
)
|
||||
|
||||
type CheckAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *CheckAction) RunPost(params struct{}) {
|
||||
resp, err := this.RPC().NodeTaskRPC().ExistsNodeTasks(this.AdminContext(), &pb.ExistsNodeTasksRequest{
|
||||
ExcludeTypes: []string{"ipItemChanged"},
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
func (this *CheckAction) RunPost(params struct {
|
||||
IsDoing bool
|
||||
HasError bool
|
||||
IsUpdated bool
|
||||
}) {
|
||||
var maxTries = 10
|
||||
for i := 0; i < maxTries; i++ {
|
||||
resp, err := this.RPC().NodeTaskRPC().ExistsNodeTasks(this.AdminContext(), &pb.ExistsNodeTasksRequest{
|
||||
ExcludeTypes: []string{"ipItemChanged"},
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Data["isDoing"] = resp.ExistTasks
|
||||
this.Data["hasError"] = resp.ExistError
|
||||
// 如果没有数据变化,继续查询
|
||||
if i < maxTries-1 && params.IsUpdated && resp.ExistTasks == params.IsDoing && resp.ExistError == params.HasError {
|
||||
time.Sleep(3 * time.Second)
|
||||
continue
|
||||
}
|
||||
|
||||
this.Data["isDoing"] = resp.ExistTasks
|
||||
this.Data["hasError"] = resp.ExistError
|
||||
break
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
|
||||
@@ -133,6 +133,11 @@ func ValidateRecordValue(recordType dnsconfigs.RecordType, value string) (messag
|
||||
message = "请输入正确的邮件服务器域名"
|
||||
return
|
||||
}
|
||||
case dnsconfigs.RecordTypeSRV:
|
||||
if len(value) == 0 {
|
||||
message = "请输入主机名"
|
||||
return
|
||||
}
|
||||
case dnsconfigs.RecordTypeTXT:
|
||||
if len(value) > 512 {
|
||||
message = "文本长度不能超出512字节"
|
||||
|
||||
@@ -64,6 +64,7 @@ func (this *CreatePopupAction) RunPost(params struct {
|
||||
// HuaweiDNS
|
||||
ParamHuaweiAccessKeyId string
|
||||
ParamHuaweiAccessKeySecret string
|
||||
ParamHuaweiEndpoint string
|
||||
|
||||
// CloudFlare
|
||||
ParamCloudFlareAPIKey string
|
||||
@@ -119,6 +120,7 @@ func (this *CreatePopupAction) RunPost(params struct {
|
||||
|
||||
apiParams["accessKeyId"] = params.ParamHuaweiAccessKeyId
|
||||
apiParams["accessKeySecret"] = params.ParamHuaweiAccessKeySecret
|
||||
apiParams["endpoint"] = params.ParamHuaweiEndpoint
|
||||
case "cloudFlare":
|
||||
params.Must.
|
||||
Field("paramCloudFlareAPIKey", params.ParamCloudFlareAPIKey).
|
||||
|
||||
@@ -91,6 +91,7 @@ func (this *UpdatePopupAction) RunPost(params struct {
|
||||
// HuaweiDNS
|
||||
ParamHuaweiAccessKeyId string
|
||||
ParamHuaweiAccessKeySecret string
|
||||
ParamHuaweiEndpoint string
|
||||
|
||||
// CloudFlare
|
||||
ParamCloudFlareAPIKey string
|
||||
@@ -148,6 +149,7 @@ func (this *UpdatePopupAction) RunPost(params struct {
|
||||
|
||||
apiParams["accessKeyId"] = params.ParamHuaweiAccessKeyId
|
||||
apiParams["accessKeySecret"] = params.ParamHuaweiAccessKeySecret
|
||||
apiParams["endpoint"] = params.ParamHuaweiEndpoint
|
||||
case "cloudFlare":
|
||||
params.Must.
|
||||
Field("paramCloudFlareAPIKey", params.ParamCloudFlareAPIKey).
|
||||
|
||||
@@ -3,21 +3,36 @@ package tasks
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"time"
|
||||
)
|
||||
|
||||
type CheckAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *CheckAction) RunPost(params struct{}) {
|
||||
resp, err := this.RPC().DNSTaskRPC().ExistsDNSTasks(this.AdminContext(), &pb.ExistsDNSTasksRequest{})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
func (this *CheckAction) RunPost(params struct {
|
||||
IsDoing bool
|
||||
HasError bool
|
||||
IsUpdated bool
|
||||
}) {
|
||||
var maxTries = 10
|
||||
for i := 0; i < maxTries; i++ {
|
||||
resp, err := this.RPC().DNSTaskRPC().ExistsDNSTasks(this.AdminContext(), &pb.ExistsDNSTasksRequest{})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Data["isDoing"] = resp.ExistTasks
|
||||
this.Data["hasError"] = resp.ExistError
|
||||
// 如果没有数据变化,继续查询
|
||||
if i < maxTries-1 && params.IsUpdated && resp.ExistTasks == params.IsDoing && resp.ExistError == params.HasError {
|
||||
time.Sleep(3 * time.Second)
|
||||
continue
|
||||
}
|
||||
|
||||
this.Data["isDoing"] = resp.ExistTasks
|
||||
this.Data["hasError"] = resp.ExistError
|
||||
break
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
|
||||
@@ -55,10 +55,11 @@ func (this *IndexAction) RunGet(params struct {
|
||||
|
||||
// 服务列表
|
||||
serversResp, err := this.RPC().ServerRPC().ListEnabledServersMatch(this.AdminContext(), &pb.ListEnabledServersMatchRequest{
|
||||
Offset: page.Offset,
|
||||
Size: page.Size,
|
||||
ServerGroupId: params.GroupId,
|
||||
Keyword: params.Keyword,
|
||||
Offset: page.Offset,
|
||||
Size: page.Size,
|
||||
ServerGroupId: params.GroupId,
|
||||
Keyword: params.Keyword,
|
||||
IgnoreSSLCerts: true,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
|
||||
@@ -43,7 +43,7 @@ func (this *IndexAction) RunGet(params struct {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
headerPolicyId := createHeaderPolicyResp.HeaderPolicyId
|
||||
headerPolicyId := createHeaderPolicyResp.HttpHeaderPolicyId
|
||||
ref := &shared.HTTPHeaderPolicyRef{
|
||||
IsPrior: false,
|
||||
IsOn: true,
|
||||
@@ -70,7 +70,7 @@ func (this *IndexAction) RunGet(params struct {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
headerPolicyId := createHeaderPolicyResp.HeaderPolicyId
|
||||
headerPolicyId := createHeaderPolicyResp.HttpHeaderPolicyId
|
||||
ref := &shared.HTTPHeaderPolicyRef{
|
||||
IsPrior: false,
|
||||
IsOn: true,
|
||||
|
||||
@@ -99,6 +99,7 @@ func (this *IndexAction) RunGet(params struct {
|
||||
TrafficOutAsc: params.TrafficOutOrder == "asc",
|
||||
UserId: params.UserId,
|
||||
IgnoreServerNames: true,
|
||||
IgnoreSSLCerts: true,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
|
||||
@@ -48,7 +48,10 @@ func (this *UpdateCNAMEPopupAction) RunPost(params struct {
|
||||
this.FailField("dnsName", "CNAME中只能包含数字、英文字母")
|
||||
}
|
||||
|
||||
serverResp, err := this.RPC().ServerRPC().FindEnabledServer(this.AdminContext(), &pb.FindEnabledServerRequest{ServerId: params.ServerId})
|
||||
serverResp, err := this.RPC().ServerRPC().FindEnabledServer(this.AdminContext(), &pb.FindEnabledServerRequest{
|
||||
ServerId: params.ServerId,
|
||||
IgnoreSSLCerts: true,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
|
||||
@@ -40,13 +40,13 @@ func (this *CreateDeletePopupAction) RunPost(params struct {
|
||||
Field("name", params.Name).
|
||||
Require("名称不能为空")
|
||||
|
||||
policyConfigResp, err := this.RPC().HTTPHeaderPolicyRPC().FindEnabledHTTPHeaderPolicyConfig(this.AdminContext(), &pb.FindEnabledHTTPHeaderPolicyConfigRequest{HeaderPolicyId: params.HeaderPolicyId})
|
||||
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.HeaderPolicyJSON, policyConfig)
|
||||
err = json.Unmarshal(policyConfigResp.HttpHeaderPolicyJSON, policyConfig)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
@@ -55,8 +55,8 @@ func (this *CreateDeletePopupAction) RunPost(params struct {
|
||||
deleteHeaders := policyConfig.DeleteHeaders
|
||||
deleteHeaders = append(deleteHeaders, params.Name)
|
||||
_, err = this.RPC().HTTPHeaderPolicyRPC().UpdateHTTPHeaderPolicyDeletingHeaders(this.AdminContext(), &pb.UpdateHTTPHeaderPolicyDeletingHeadersRequest{
|
||||
HeaderPolicyId: params.HeaderPolicyId,
|
||||
HeaderNames: deleteHeaders,
|
||||
HttpHeaderPolicyId: params.HeaderPolicyId,
|
||||
HeaderNames: deleteHeaders,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
|
||||
@@ -52,13 +52,13 @@ func (this *CreateSetPopupAction) RunPost(params struct {
|
||||
Field("name", params.Name).
|
||||
Require("请输入Header名称")
|
||||
|
||||
configResp, err := this.RPC().HTTPHeaderPolicyRPC().FindEnabledHTTPHeaderPolicyConfig(this.AdminContext(), &pb.FindEnabledHTTPHeaderPolicyConfigRequest{HeaderPolicyId: params.HeaderPolicyId})
|
||||
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.HeaderPolicyJSON, policyConfig)
|
||||
err = json.Unmarshal(configResp.HttpHeaderPolicyJSON, policyConfig)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
@@ -135,8 +135,8 @@ func (this *CreateSetPopupAction) RunPost(params struct {
|
||||
}
|
||||
|
||||
_, err = this.RPC().HTTPHeaderPolicyRPC().UpdateHTTPHeaderPolicySettingHeaders(this.AdminContext(), &pb.UpdateHTTPHeaderPolicySettingHeadersRequest{
|
||||
HeaderPolicyId: params.HeaderPolicyId,
|
||||
HeadersJSON: refsJSON,
|
||||
HttpHeaderPolicyId: params.HeaderPolicyId,
|
||||
HeadersJSON: refsJSON,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
|
||||
@@ -21,14 +21,14 @@ func (this *DeleteAction) RunPost(params struct {
|
||||
defer this.CreateLog(oplogs.LevelInfo, "删除请求Header,HeaderPolicyId:%d, HeaderId:%d", params.HeaderPolicyId, params.HeaderId)
|
||||
|
||||
policyConfigResp, err := this.RPC().HTTPHeaderPolicyRPC().FindEnabledHTTPHeaderPolicyConfig(this.AdminContext(), &pb.FindEnabledHTTPHeaderPolicyConfigRequest{
|
||||
HeaderPolicyId: params.HeaderPolicyId,
|
||||
HttpHeaderPolicyId: params.HeaderPolicyId,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
policyConfig := &shared.HTTPHeaderPolicy{}
|
||||
err = json.Unmarshal(policyConfigResp.HeaderPolicyJSON, policyConfig)
|
||||
err = json.Unmarshal(policyConfigResp.HttpHeaderPolicyJSON, policyConfig)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
@@ -48,8 +48,8 @@ func (this *DeleteAction) RunPost(params struct {
|
||||
return
|
||||
}
|
||||
_, err = this.RPC().HTTPHeaderPolicyRPC().UpdateHTTPHeaderPolicySettingHeaders(this.AdminContext(), &pb.UpdateHTTPHeaderPolicySettingHeadersRequest{
|
||||
HeaderPolicyId: params.HeaderPolicyId,
|
||||
HeadersJSON: resultJSON,
|
||||
HttpHeaderPolicyId: params.HeaderPolicyId,
|
||||
HeadersJSON: resultJSON,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
|
||||
@@ -19,12 +19,12 @@ func (this *DeleteDeletingHeaderAction) RunPost(params struct {
|
||||
// 日志
|
||||
defer this.CreateLog(oplogs.LevelInfo, "删除需要删除的请求Header,HeaderPolicyId:%d, HeaderName:%s", params.HeaderPolicyId, params.HeaderName)
|
||||
|
||||
policyConfigResp, err := this.RPC().HTTPHeaderPolicyRPC().FindEnabledHTTPHeaderPolicyConfig(this.AdminContext(), &pb.FindEnabledHTTPHeaderPolicyConfigRequest{HeaderPolicyId: params.HeaderPolicyId})
|
||||
policyConfigResp, err := this.RPC().HTTPHeaderPolicyRPC().FindEnabledHTTPHeaderPolicyConfig(this.AdminContext(), &pb.FindEnabledHTTPHeaderPolicyConfigRequest{HttpHeaderPolicyId: params.HeaderPolicyId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
policyConfigJSON := policyConfigResp.HeaderPolicyJSON
|
||||
policyConfigJSON := policyConfigResp.HttpHeaderPolicyJSON
|
||||
policyConfig := &shared.HTTPHeaderPolicy{}
|
||||
err = json.Unmarshal(policyConfigJSON, policyConfig)
|
||||
if err != nil {
|
||||
@@ -40,8 +40,8 @@ func (this *DeleteDeletingHeaderAction) RunPost(params struct {
|
||||
headerNames = append(headerNames, h)
|
||||
}
|
||||
_, err = this.RPC().HTTPHeaderPolicyRPC().UpdateHTTPHeaderPolicyDeletingHeaders(this.AdminContext(), &pb.UpdateHTTPHeaderPolicyDeletingHeadersRequest{
|
||||
HeaderPolicyId: params.HeaderPolicyId,
|
||||
HeaderNames: headerNames,
|
||||
HttpHeaderPolicyId: params.HeaderPolicyId,
|
||||
HeaderNames: headerNames,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
|
||||
@@ -47,7 +47,7 @@ func (this *IndexAction) RunGet(params struct {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
headerPolicyId := createHeaderPolicyResp.HeaderPolicyId
|
||||
var headerPolicyId = createHeaderPolicyResp.HttpHeaderPolicyId
|
||||
ref := &shared.HTTPHeaderPolicyRef{
|
||||
IsPrior: false,
|
||||
IsOn: true,
|
||||
@@ -74,7 +74,7 @@ func (this *IndexAction) RunGet(params struct {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
headerPolicyId := createHeaderPolicyResp.HeaderPolicyId
|
||||
headerPolicyId := createHeaderPolicyResp.HttpHeaderPolicyId
|
||||
ref := &shared.HTTPHeaderPolicyRef{
|
||||
IsPrior: false,
|
||||
IsOn: true,
|
||||
|
||||
@@ -19,6 +19,7 @@ func init() {
|
||||
GetPost("/createDeletePopup", new(CreateDeletePopupAction)).
|
||||
Post("/deleteDeletingHeader", new(DeleteDeletingHeaderAction)).
|
||||
Post("/delete", new(DeleteAction)).
|
||||
GetPost("/updateCORSPopup", new(UpdateCORSPopupAction)).
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package headers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/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.HTTPCORSHeaderConfig{}
|
||||
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()
|
||||
}
|
||||
@@ -31,7 +31,7 @@ func (this *IndexAction) RunGet(params struct {
|
||||
if !isOk {
|
||||
return
|
||||
}
|
||||
httpsConfig := &serverconfigs.HTTPSProtocolConfig{}
|
||||
var httpsConfig = &serverconfigs.HTTPSProtocolConfig{}
|
||||
if len(server.HttpsJSON) > 0 {
|
||||
err := json.Unmarshal(server.HttpsJSON, httpsConfig)
|
||||
if err != nil {
|
||||
@@ -44,12 +44,15 @@ func (this *IndexAction) RunGet(params struct {
|
||||
|
||||
var sslPolicy *sslconfigs.SSLPolicy
|
||||
if httpsConfig.SSLPolicyRef != nil && httpsConfig.SSLPolicyRef.SSLPolicyId > 0 {
|
||||
sslPolicyConfigResp, err := this.RPC().SSLPolicyRPC().FindEnabledSSLPolicyConfig(this.AdminContext(), &pb.FindEnabledSSLPolicyConfigRequest{SslPolicyId: httpsConfig.SSLPolicyRef.SSLPolicyId})
|
||||
sslPolicyConfigResp, err := this.RPC().SSLPolicyRPC().FindEnabledSSLPolicyConfig(this.AdminContext(), &pb.FindEnabledSSLPolicyConfigRequest{
|
||||
SslPolicyId: httpsConfig.SSLPolicyRef.SSLPolicyId,
|
||||
IgnoreData: true,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
sslPolicyConfigJSON := sslPolicyConfigResp.SslPolicyJSON
|
||||
var sslPolicyConfigJSON = sslPolicyConfigResp.SslPolicyJSON
|
||||
if len(sslPolicyConfigJSON) > 0 {
|
||||
sslPolicy = &sslconfigs.SSLPolicy{}
|
||||
err = json.Unmarshal(sslPolicyConfigJSON, sslPolicy)
|
||||
|
||||
@@ -42,7 +42,10 @@ func (this *IndexAction) RunGet(params struct {
|
||||
this.Data["clusters"] = clusterMaps
|
||||
|
||||
// 当前服务信息
|
||||
serverResp, err := this.RPC().ServerRPC().FindEnabledServer(this.AdminContext(), &pb.FindEnabledServerRequest{ServerId: params.ServerId})
|
||||
serverResp, err := this.RPC().ServerRPC().FindEnabledServer(this.AdminContext(), &pb.FindEnabledServerRequest{
|
||||
ServerId: params.ServerId,
|
||||
IgnoreSSLCerts: true,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
@@ -121,6 +124,7 @@ func (this *IndexAction) RunGet(params struct {
|
||||
// RunPost 保存
|
||||
func (this *IndexAction) RunPost(params struct {
|
||||
ServerId int64
|
||||
UserId int64
|
||||
Name string
|
||||
Description string
|
||||
ClusterId int64
|
||||
@@ -157,16 +161,28 @@ func (this *IndexAction) RunPost(params struct {
|
||||
return
|
||||
}
|
||||
|
||||
// 修改套餐
|
||||
if params.UserPlanId > 0 {
|
||||
_, err = this.RPC().ServerRPC().UpdateServerUserPlan(this.AdminContext(), &pb.UpdateServerUserPlanRequest{
|
||||
ServerId: params.ServerId,
|
||||
UserPlanId: params.UserPlanId,
|
||||
// 修改用户
|
||||
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()
|
||||
|
||||
@@ -36,7 +36,7 @@ func (this *IndexAction) RunGet(params struct {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
headerPolicyId := createHeaderPolicyResp.HeaderPolicyId
|
||||
headerPolicyId := createHeaderPolicyResp.HttpHeaderPolicyId
|
||||
ref := &shared.HTTPHeaderPolicyRef{
|
||||
IsPrior: false,
|
||||
IsOn: true,
|
||||
@@ -59,7 +59,7 @@ func (this *IndexAction) RunGet(params struct {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
headerPolicyId := createHeaderPolicyResp.HeaderPolicyId
|
||||
headerPolicyId := createHeaderPolicyResp.HttpHeaderPolicyId
|
||||
ref := &shared.HTTPHeaderPolicyRef{
|
||||
IsPrior: false,
|
||||
IsOn: true,
|
||||
|
||||
@@ -109,6 +109,12 @@ func (this *LocationHelper) createMenus(serverIdString string, locationIdString
|
||||
"isActive": secondMenuItem == "referer",
|
||||
"isOn": locationConfig.Web != nil && locationConfig.Web.Referers != nil && locationConfig.Web.Referers.IsPrior,
|
||||
})
|
||||
menuItems = append(menuItems, maps.Map{
|
||||
"name": "UA名单",
|
||||
"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": "字符编码",
|
||||
"url": "/servers/server/settings/locations/charset?serverId=" + serverIdString + "&locationId=" + locationIdString,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package uam
|
||||
package referers
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package uam
|
||||
package referers
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package userAgent
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
)
|
||||
|
||||
type IndexAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *IndexAction) Init() {
|
||||
this.Nav("", "setting", "index")
|
||||
this.SecondMenu("userAgent")
|
||||
}
|
||||
|
||||
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 userAgentConfig = webConfig.UserAgent
|
||||
if userAgentConfig == nil {
|
||||
userAgentConfig = serverconfigs.NewUserAgentConfig()
|
||||
}
|
||||
|
||||
this.Data["userAgentConfig"] = userAgentConfig
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunPost(params struct {
|
||||
WebId int64
|
||||
UserAgentJSON []byte
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
defer this.CreateLogInfo("修改Web %d User-Agent设置", params.WebId)
|
||||
|
||||
_, err := this.RPC().HTTPWebRPC().UpdateHTTPWebUserAgent(this.AdminContext(), &pb.UpdateHTTPWebUserAgentRequest{
|
||||
HttpWebId: params.WebId,
|
||||
UserAgentJSON: params.UserAgentJSON,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package userAgent
|
||||
|
||||
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", "userAgent").
|
||||
Prefix("/servers/server/settings/locations/userAgent").
|
||||
GetPost("", new(IndexAction)).
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package uam
|
||||
package referers
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package uam
|
||||
package referers
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package userAgent
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
)
|
||||
|
||||
type IndexAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *IndexAction) Init() {
|
||||
this.Nav("", "setting", "index")
|
||||
this.SecondMenu("userAgent")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct {
|
||||
ServerId int64
|
||||
}) {
|
||||
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 userAgentConfig = webConfig.UserAgent
|
||||
if userAgentConfig == nil {
|
||||
userAgentConfig = serverconfigs.NewUserAgentConfig()
|
||||
}
|
||||
|
||||
this.Data["userAgentConfig"] = userAgentConfig
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunPost(params struct {
|
||||
WebId int64
|
||||
UserAgentJSON []byte
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
defer this.CreateLogInfo("修改Web %d User-Agent设置", params.WebId)
|
||||
|
||||
_, err := this.RPC().HTTPWebRPC().UpdateHTTPWebUserAgent(this.AdminContext(), &pb.UpdateHTTPWebUserAgentRequest{
|
||||
HttpWebId: params.WebId,
|
||||
UserAgentJSON: params.UserAgentJSON,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package userAgent
|
||||
|
||||
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/userAgent").
|
||||
GetPost("", new(IndexAction)).
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
@@ -57,7 +57,10 @@ func (this *ServerHelper) createLeftMenu(action *actions.ActionObject) {
|
||||
return
|
||||
}
|
||||
|
||||
serverResp, err := rpcClient.ServerRPC().FindEnabledServer(rpcClient.Context(action.Context.GetInt64("adminId")), &pb.FindEnabledServerRequest{ServerId: serverId})
|
||||
serverResp, err := rpcClient.ServerRPC().FindEnabledServer(rpcClient.Context(action.Context.GetInt64("adminId")), &pb.FindEnabledServerRequest{
|
||||
ServerId: serverId,
|
||||
IgnoreSSLCerts: true,
|
||||
})
|
||||
if err != nil {
|
||||
logs.Error(err)
|
||||
return
|
||||
@@ -315,6 +318,12 @@ func (this *ServerHelper) createSettingsMenu(secondMenuItem string, serverIdStri
|
||||
"isActive": secondMenuItem == "referer",
|
||||
"isOn": serverConfig.Web != nil && serverConfig.Web.Referers != nil && serverConfig.Web.Referers.IsOn,
|
||||
})
|
||||
menuItems = append(menuItems, maps.Map{
|
||||
"name": "UA名单",
|
||||
"url": "/servers/server/settings/userAgent?serverId=" + serverIdString,
|
||||
"isActive": secondMenuItem == "userAgent",
|
||||
"isOn": serverConfig.Web != nil && serverConfig.Web.UserAgent != nil && serverConfig.Web.UserAgent.IsOn,
|
||||
})
|
||||
menuItems = append(menuItems, maps.Map{
|
||||
"name": "字符编码",
|
||||
"url": "/servers/server/settings/charset?serverId=" + serverIdString,
|
||||
|
||||
@@ -8,14 +8,17 @@ import (
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// 查找Server
|
||||
// FindServer 查找服务信息
|
||||
func FindServer(p *actionutils.ParentAction, serverId int64) (*pb.Server, *serverconfigs.ServerConfig, bool) {
|
||||
serverResp, err := p.RPC().ServerRPC().FindEnabledServer(p.AdminContext(), &pb.FindEnabledServerRequest{ServerId: serverId})
|
||||
serverResp, err := p.RPC().ServerRPC().FindEnabledServer(p.AdminContext(), &pb.FindEnabledServerRequest{
|
||||
ServerId: serverId,
|
||||
IgnoreSSLCerts: true,
|
||||
})
|
||||
if err != nil {
|
||||
p.ErrorPage(err)
|
||||
return nil, nil, false
|
||||
}
|
||||
server := serverResp.Server
|
||||
var server = serverResp.Server
|
||||
if server == nil {
|
||||
p.ErrorPage(errors.New("not found server with id '" + strconv.FormatInt(serverId, 10) + "'"))
|
||||
return nil, nil, false
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/server/settings/conds/condutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
@@ -123,6 +124,16 @@ func (this *ComponentsAction) RunGet(params struct{}) {
|
||||
buffer.Write([]byte{'\n', '\n'})
|
||||
}
|
||||
|
||||
// WAF操作符
|
||||
wafOperatorsJSON, err := json.Marshal(firewallconfigs.AllRuleOperators)
|
||||
if err != nil {
|
||||
logs.Println("ComponentsAction marshal waf rule operators failed: " + err.Error())
|
||||
} else {
|
||||
buffer.WriteString("window.WAF_RULE_OPERATORS = ")
|
||||
buffer.Write(wafOperatorsJSON)
|
||||
buffer.Write([]byte{'\n', '\n'})
|
||||
}
|
||||
|
||||
componentsData = buffer.Bytes()
|
||||
|
||||
// ETag
|
||||
|
||||
@@ -97,6 +97,7 @@ func (this *UserAction) RunGet(params struct {
|
||||
"username": user.Username,
|
||||
"fullname": user.Fullname,
|
||||
"email": user.Email,
|
||||
"verifiedEmail": user.VerifiedEmail,
|
||||
"tel": user.Tel,
|
||||
"remark": user.Remark,
|
||||
"mobile": user.Mobile,
|
||||
|
||||
@@ -118,16 +118,16 @@ func FindAllMenuMaps(nodeLogsType string, countUnreadNodeLogs int64, countUnread
|
||||
"subtitle": "集群列表",
|
||||
"icon": "globe",
|
||||
"subItems": []maps.Map{
|
||||
{
|
||||
"name": "问题修复",
|
||||
"url": "/dns/issues",
|
||||
"code": "issue",
|
||||
},
|
||||
{
|
||||
"name": "DNS服务商",
|
||||
"url": "/dns/providers",
|
||||
"code": "provider",
|
||||
},
|
||||
{
|
||||
"name": "问题修复",
|
||||
"url": "/dns/issues",
|
||||
"code": "issue",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
@@ -112,8 +112,8 @@ func checkIPWithoutCache(config *systemconfigs.SecurityConfig, ipAddr string) bo
|
||||
}
|
||||
|
||||
// 请求检查相关正则
|
||||
var searchEngineRegex = regexp.MustCompile(`60spider|adldxbot|adsbot-google|applebot|admantx|alexa|baidu|bingbot|bingpreview|facebookexternalhit|googlebot|proximic|slurp|sogou|twitterbot|yandex`)
|
||||
var spiderRegexp = regexp.MustCompile(`python|pycurl|http-client|httpclient|apachebench|nethttp|http_request|java|perl|ruby|scrapy|php|rust|curl|wget`) // 其中增加了curl和wget
|
||||
var searchEngineRegex = regexp.MustCompile(`(?i)(60spider|adldxbot|adsbot-google|applebot|admantx|alexa|baidu|bingbot|bingpreview|facebookexternalhit|googlebot|proximic|slurp|sogou|twitterbot|yandex)`)
|
||||
var spiderRegexp = regexp.MustCompile(`(?i)(python|pycurl|http-client|httpclient|apachebench|nethttp|http_request|java|perl|ruby|scrapy|php|rust|curl|wget)`) // 其中增加了curl和wget
|
||||
|
||||
// 检查请求
|
||||
func checkRequestSecurity(securityConfig *systemconfigs.SecurityConfig, req *http.Request) bool {
|
||||
|
||||
@@ -84,6 +84,7 @@ import (
|
||||
_ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/server/settings/locations/reverseProxy"
|
||||
_ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/server/settings/locations/rewrite"
|
||||
_ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/server/settings/locations/stat"
|
||||
_ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/server/settings/locations/userAgent"
|
||||
_ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/server/settings/locations/waf"
|
||||
_ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/server/settings/locations/web"
|
||||
_ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/server/settings/locations/webp"
|
||||
@@ -102,6 +103,7 @@ import (
|
||||
_ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/server/settings/tls"
|
||||
_ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/server/settings/udp"
|
||||
_ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/server/settings/unix"
|
||||
_ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/server/settings/userAgent"
|
||||
_ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/server/settings/waf"
|
||||
_ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/server/settings/web"
|
||||
_ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/server/settings/webp"
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -2,6 +2,7 @@
|
||||
* 更多选项
|
||||
*/
|
||||
Vue.component("more-options-indicator", {
|
||||
props:[],
|
||||
data: function () {
|
||||
return {
|
||||
visible: false
|
||||
@@ -14,6 +15,7 @@ Vue.component("more-options-indicator", {
|
||||
Tea.Vue.moreOptionsVisible = this.visible
|
||||
}
|
||||
this.$emit("change", this.visible)
|
||||
this.$emit("input", this.visible)
|
||||
}
|
||||
},
|
||||
template: '<a href="" style="font-weight: normal" @click.prevent="changeVisible()"><slot><span v-if="!visible">更多选项</span><span v-if="visible">收起选项</span></slot> <i class="icon angle" :class="{down:!visible, up:visible}"></i> </a>'
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
Vue.component("values-box", {
|
||||
props: ["values", "v-values", "size", "maxlength", "name", "placeholder"],
|
||||
props: ["values", "v-values", "size", "maxlength", "name", "placeholder", "v-allow-empty"],
|
||||
data: function () {
|
||||
let values = this.values;
|
||||
if (values == null) {
|
||||
@@ -39,7 +39,9 @@ Vue.component("values-box", {
|
||||
},
|
||||
confirm: function () {
|
||||
if (this.value.length == 0) {
|
||||
return
|
||||
if (typeof(this.vAllowEmpty) != "boolean" || !this.vAllowEmpty) {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if (this.isUpdating) {
|
||||
@@ -75,12 +77,17 @@ Vue.component("values-box", {
|
||||
},
|
||||
template: `<div>
|
||||
<div v-show="!isEditing && realValues.length > 0">
|
||||
<div class="ui label tiny basic" v-for="(value, index) in realValues" style="margin-top:0.4em;margin-bottom:0.4em">{{value}}</div>
|
||||
<div class="ui label tiny basic" v-for="(value, index) in realValues" style="margin-top:0.4em;margin-bottom:0.4em">
|
||||
<span v-if="value.toString().length > 0">{{value}}</span>
|
||||
<span v-if="value.toString().length == 0" class="disabled">[空]</span>
|
||||
</div>
|
||||
<a href="" @click.prevent="startEditing" style="font-size: 0.8em; margin-left: 0.2em">[修改]</a>
|
||||
</div>
|
||||
<div v-show="isEditing || realValues.length == 0">
|
||||
<div style="margin-bottom: 1em" v-if="realValues.length > 0">
|
||||
<div class="ui label tiny basic" v-for="(value, index) in realValues" style="margin-top:0.4em;margin-bottom:0.4em">{{value}}
|
||||
<div class="ui label tiny basic" v-for="(value, index) in realValues" style="margin-top:0.4em;margin-bottom:0.4em">
|
||||
<span v-if="value.toString().length > 0">{{value}}</span>
|
||||
<span v-if="value.toString().length == 0" class="disabled">[空]</span>
|
||||
<input type="hidden" :name="name" :value="value"/>
|
||||
<a href="" @click.prevent="update(index)" title="修改"><i class="icon pencil small" ></i></a>
|
||||
<a href="" @click.prevent="remove(index)" title="删除"><i class="icon remove"></i></a>
|
||||
|
||||
@@ -80,7 +80,7 @@ Vue.component("dns-route-selector", {
|
||||
return
|
||||
}
|
||||
this.searchingRoutes = this.vAllRoutes.filter(function (route) {
|
||||
return teaweb.match(route.name, keyword) || teaweb.match(route.domainName, keyword)
|
||||
return teaweb.match(route.name, keyword) || teaweb.match(route.code, keyword) || teaweb.match(route.domainName, keyword)
|
||||
})
|
||||
if (this.searchingRoutes.length > 0) {
|
||||
this.routeCode = this.searchingRoutes[0].code + "@" + this.searchingRoutes[0].domainId
|
||||
@@ -99,24 +99,25 @@ Vue.component("dns-route-selector", {
|
||||
</div>
|
||||
<button type="button" class="ui button small" @click.prevent="add" v-if="!isAdding">+</button>
|
||||
<div v-if="isAdding">
|
||||
<div class="ui fields inline">
|
||||
<div class="ui field">
|
||||
<select class="ui dropdown" style="width: 18em" v-model="routeCode">
|
||||
<option value="" v-if="keyword.length == 0">[请选择]</option>
|
||||
<option v-for="route in searchingRoutes" :value="route.code + '@' + route.domainId">{{route.name}}({{route.domainName}})</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="ui field">
|
||||
<input type="text" placeholder="搜索..." size="10" v-model="keyword" ref="keywordRef" @keyup.enter="confirm" @keypress.enter.prevent="1"/>
|
||||
</div>
|
||||
|
||||
<div class="ui field">
|
||||
<button class="ui button tiny" type="button" @click.prevent="confirm">确定</button>
|
||||
</div>
|
||||
<div class="ui field">
|
||||
<a href="" @click.prevent="cancel()"><i class="icon remove small"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
<table class="ui table">
|
||||
<tr>
|
||||
<td class="title">所有线路</td>
|
||||
<td>
|
||||
<select class="ui dropdown auto-width" v-model="routeCode">
|
||||
<option value="" v-if="keyword.length == 0">[请选择]</option>
|
||||
<option v-for="route in searchingRoutes" :value="route.code + '@' + route.domainId">{{route.name}}({{route.code}}/{{route.domainName}})</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>搜索</td>
|
||||
<td>
|
||||
<input type="text" placeholder="搜索..." size="10" style="width: 10em" v-model="keyword" ref="keywordRef" @keyup.enter="confirm" @keypress.enter.prevent="1"/>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<button class="ui button tiny" type="button" @click.prevent="confirm">确定</button> <a href="" @click.prevent="cancel()"><i class="icon remove small"></i></a>
|
||||
</div>
|
||||
</div>`
|
||||
})
|
||||
@@ -26,7 +26,8 @@ Vue.component("ns-route-ranges-box", {
|
||||
|
||||
// region
|
||||
regions: [],
|
||||
regionType: "country"
|
||||
regionType: "country",
|
||||
regionConnector: "OR"
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
@@ -68,6 +69,7 @@ Vue.component("ns-route-ranges-box", {
|
||||
this.isAdding = false
|
||||
this.regions = []
|
||||
this.regionType = "country"
|
||||
this.regionConnector = "OR"
|
||||
this.isReverse = false
|
||||
},
|
||||
confirmIPRange: function () {
|
||||
@@ -131,6 +133,7 @@ Vue.component("ns-route-ranges-box", {
|
||||
}
|
||||
this.ranges.push({
|
||||
type: "region",
|
||||
connector: this.regionConnector,
|
||||
params: {
|
||||
regions: this.regions,
|
||||
isReverse: this.isReverse
|
||||
@@ -362,10 +365,24 @@ Vue.component("ns-route-ranges-box", {
|
||||
<span class="red" v-if="range.params.isReverse">[排除]</span>
|
||||
<span v-if="range.type == 'ipRange'">IP范围:</span>
|
||||
<span v-if="range.type == 'cidr'">CIDR:</span>
|
||||
<span v-if="range.type == 'region'">区域:</span>
|
||||
<span v-if="range.type == 'region'"></span>
|
||||
<span v-if="range.type == 'ipRange'">{{range.params.ipFrom}} - {{range.params.ipTo}}</span>
|
||||
<span v-if="range.type == 'cidr'">{{range.params.cidr}}</span>
|
||||
<span v-if="range.type == 'region'"><span v-for="(region, index) in range.params.regions">{{region.name}}<span v-if="index < range.params.regions.length - 1">,</span></span></span>
|
||||
<span v-if="range.type == 'region'">
|
||||
<span v-for="(region, index) in range.params.regions">
|
||||
<span v-if="region.type == 'country'">国家/地区</span>
|
||||
<span v-if="region.type == 'province'">省份</span>
|
||||
<span v-if="region.type == 'city'">城市</span>
|
||||
<span v-if="region.type == 'provider'">ISP</span>
|
||||
:{{region.name}}
|
||||
<span v-if="index < range.params.regions.length - 1" class="grey">
|
||||
|
||||
<span v-if="range.connector == 'OR' || range.connector == '' || range.connector == null">或</span>
|
||||
<span v-if="range.connector == 'AND'">且</span>
|
||||
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
<a href="" title="删除" @click.prevent="remove(index)"><i class="icon remove small"></i></a>
|
||||
</div>
|
||||
<div class="ui divider"></div>
|
||||
@@ -488,9 +505,21 @@ Vue.component("ns-route-ranges-box", {
|
||||
<tr>
|
||||
<td>已添加</td>
|
||||
<td>
|
||||
<div v-for="(region, index) in regions" class="ui label small basic">
|
||||
{{region.name}} <a href="" title="删除" @click.prevent="removeRegion(index)"><i class="icon remove small"></i></a>
|
||||
</div>
|
||||
<span v-for="(region, index) in regions">
|
||||
<span class="ui label small basic">
|
||||
<span v-if="region.type == 'country'">国家/地区</span>
|
||||
<span v-if="region.type == 'province'">省份</span>
|
||||
<span v-if="region.type == 'city'">城市</span>
|
||||
<span v-if="region.type == 'provider'">ISP</span>
|
||||
:{{region.name}} <a href="" title="删除" @click.prevent="removeRegion(index)"><i class="icon remove small"></i></a>
|
||||
</span>
|
||||
<span v-if="index < regions.length - 1" class="grey">
|
||||
|
||||
<span v-if="regionConnector == 'OR' || regionConnector == ''">或</span>
|
||||
<span v-if="regionConnector == 'AND'">且</span>
|
||||
|
||||
</span>
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
@@ -526,6 +555,17 @@ Vue.component("ns-route-ranges-box", {
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>区域之间关系</td>
|
||||
<td>
|
||||
<select class="ui dropdown auto-width" v-model="regionConnector">
|
||||
<option value="OR">或</option>
|
||||
<option value="AND">且</option>
|
||||
</select>
|
||||
<p class="comment" v-if="regionConnector == 'OR'">匹配所选任一区域即认为匹配成功。</p>
|
||||
<p class="comment" v-if="regionConnector == 'AND'">匹配所有所选区域才认为匹配成功。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>排除</td>
|
||||
<td>
|
||||
|
||||
@@ -88,6 +88,7 @@ Vue.component("ns-routes-selector", {
|
||||
<option value="isp">运营商</option>
|
||||
<option value="china">中国省市</option>
|
||||
<option value="world">全球国家地区</option>
|
||||
<option value="agent">搜索引擎</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
|
||||
102
web/public/js/components/senders/email-sender.js
Normal file
102
web/public/js/components/senders/email-sender.js
Normal file
@@ -0,0 +1,102 @@
|
||||
Vue.component("email-sender", {
|
||||
props: ["value", "name"],
|
||||
data: function () {
|
||||
let value = this.value
|
||||
if (value == null) {
|
||||
value = {
|
||||
isOn: false,
|
||||
smtpHost: "",
|
||||
smtpPort: 0,
|
||||
username: "",
|
||||
password: "",
|
||||
fromEmail: "",
|
||||
fromName: ""
|
||||
}
|
||||
}
|
||||
let smtpPortString = value.smtpPort.toString()
|
||||
if (smtpPortString == "0") {
|
||||
smtpPortString = ""
|
||||
}
|
||||
|
||||
return {
|
||||
config: value,
|
||||
smtpPortString: smtpPortString
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
smtpPortString: function (v) {
|
||||
let port = parseInt(v)
|
||||
if (!isNaN(port)) {
|
||||
this.config.smtpPort = port
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
test: function () {
|
||||
window.TESTING_EMAIL_CONFIG = this.config
|
||||
teaweb.popup("/users/setting/emailTest", {
|
||||
height: "36em"
|
||||
})
|
||||
}
|
||||
},
|
||||
template: `<div>
|
||||
<input type="hidden" :name="name" :value="JSON.stringify(config)"/>
|
||||
<table class="ui table selectable definition">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="title">启用</td>
|
||||
<td><checkbox v-model="config.isOn"></checkbox></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
<tbody v-show="config.isOn">
|
||||
<tr>
|
||||
<td>SMTP地址 *</td>
|
||||
<td>
|
||||
<input type="text" :name="name + 'SmtpHost'" v-model="config.smtpHost"/>
|
||||
<p class="comment">SMTP主机地址,比如<code-label>smtp.qq.com</code-label>,目前仅支持TLS协议,如不清楚,请查询对应邮件服务商文档。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>SMTP端口 *</td>
|
||||
<td>
|
||||
<input type="text" :name="name + 'SmtpPort'" v-model="smtpPortString" style="width: 5em" maxlength="5"/>
|
||||
<p class="comment">SMTP主机端口,比如<code-label>587</code-label>、<code-label>465</code-label>,如不清楚,请查询对应邮件服务商文档。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>用户名 *</td>
|
||||
<td>
|
||||
<input type="text" :name="name + 'Username'" v-model="config.username"/>
|
||||
<p class="comment">通常为发件人邮箱地址。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>密码 *</td>
|
||||
<td>
|
||||
<input type="password" :name="name + 'Password'" v-model="config.password"/>
|
||||
<p class="comment">邮箱登录密码或授权码,如不清楚,请查询对应邮件服务商文档。。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>发件人Email *</td>
|
||||
<td>
|
||||
<input type="text" :name="name + 'FromEmail'" v-model="config.fromEmail" maxlength="128"/>
|
||||
<p class="comment">使用的发件人邮箱地址,通常和发件用户名一致。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>发件人名称</td>
|
||||
<td>
|
||||
<input type="text" :name="name + 'FromName'" v-model="config.fromName" maxlength="30"/>
|
||||
<p class="comment">使用的发件人名称,默认使用系统设置的<a href="/settings/ui" target="_blank">产品名称</a>。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>发送测试</td>
|
||||
<td><a href="" @click.prevent="test">[点此测试]</a></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="margin"></div>
|
||||
</div>`
|
||||
})
|
||||
@@ -20,11 +20,13 @@ Vue.component("http-compression-config-box", {
|
||||
gzipRef: null,
|
||||
deflateRef: null,
|
||||
brotliRef: null,
|
||||
minLength: {count: 0, "unit": "kb"},
|
||||
maxLength: {count: 0, "unit": "kb"},
|
||||
minLength: {count: 1, "unit": "kb"},
|
||||
maxLength: {count: 32, "unit": "mb"},
|
||||
mimeTypes: ["text/*", "application/javascript", "application/json", "application/atom+xml", "application/rss+xml", "application/xhtml+xml", "font/*", "image/svg+xml"],
|
||||
extensions: [".js", ".json", ".html", ".htm", ".xml", ".css", ".woff2", ".txt"],
|
||||
conds: null
|
||||
exceptExtensions: [".apk", ".ipa"],
|
||||
conds: null,
|
||||
enablePartialContent: false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -108,6 +110,14 @@ Vue.component("http-compression-config-box", {
|
||||
})
|
||||
this.config.extensions = values
|
||||
},
|
||||
changeExceptExtensions: function (values) {
|
||||
values.forEach(function (v, k) {
|
||||
if (v.length > 0 && v[0] != ".") {
|
||||
values[k] = "." + v
|
||||
}
|
||||
})
|
||||
this.config.exceptExtensions = values
|
||||
},
|
||||
changeMimeTypes: function (values) {
|
||||
this.config.mimeTypes = values
|
||||
},
|
||||
@@ -179,6 +189,13 @@ Vue.component("http-compression-config-box", {
|
||||
<p class="comment">含有这些扩展名的URL将会被压缩,不区分大小写。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>例外扩展名</td>
|
||||
<td>
|
||||
<values-box :values="config.exceptExtensions" @change="changeExceptExtensions" placeholder="比如 .html"></values-box>
|
||||
<p class="comment">含有这些扩展名的URL将<strong>不会</strong>被压缩,不区分大小写。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>支持的MimeType</td>
|
||||
<td>
|
||||
@@ -231,6 +248,13 @@ Vue.component("http-compression-config-box", {
|
||||
<p class="comment">0表示不限制,内容长度从文件尺寸或Content-Length中获取。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>支持Partial<br/>Content</td>
|
||||
<td>
|
||||
<checkbox v-model="config.enablePartialContent"></checkbox>
|
||||
<p class="comment">支持对分区内容(PartialContent)的压缩;除非客户端有特殊要求,一般不需要启用。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>匹配条件</td>
|
||||
<td>
|
||||
|
||||
@@ -744,7 +744,7 @@ Vue.component("http-cond-params", {
|
||||
<select class="ui dropdown auto-width" v-model="operator" @change="changeOperator">
|
||||
<option v-for="operator in operators" :value="operator.op">{{operator.name}}</option>
|
||||
</select>
|
||||
<p class="comment">{{operatorDescription}}</p>
|
||||
<p class="comment" v-html="operatorDescription"></p>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
Vue.component("http-cors-header-config-box", {
|
||||
props: ["value"],
|
||||
data: function () {
|
||||
let config = this.value
|
||||
if (config == null) {
|
||||
config = {
|
||||
isOn: false,
|
||||
allowMethods: [],
|
||||
allowOrigin: "",
|
||||
allowCredentials: true,
|
||||
exposeHeaders: [],
|
||||
maxAge: 0,
|
||||
requestHeaders: [],
|
||||
requestMethod: ""
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
config: config
|
||||
}
|
||||
},
|
||||
template: `<div>
|
||||
<input type="hidden" name="corsJSON" :value="JSON.stringify(config)"/>
|
||||
<table class="ui table definition selectable">
|
||||
<tr>
|
||||
<td class="title">启用CORS自适应跨域</td>
|
||||
<td>
|
||||
<checkbox v-model="config.isOn"></checkbox>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<div class="margin"></div>
|
||||
</div>`
|
||||
})
|
||||
@@ -10,7 +10,21 @@ Vue.component("http-firewall-rule-label", {
|
||||
showErr: function (err) {
|
||||
teaweb.popupTip("规则校验错误,请修正:<span class=\"red\">" + teaweb.encodeHTML(err) + "</span>")
|
||||
},
|
||||
operatorName: function (operatorCode) {
|
||||
var operatorName = operatorCode
|
||||
if (typeof (window.WAF_RULE_OPERATORS) != null) {
|
||||
window.WAF_RULE_OPERATORS.forEach(function (v) {
|
||||
if (v.code == operatorCode) {
|
||||
operatorName = v.name
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return operatorName
|
||||
},
|
||||
isEmptyString: function (v) {
|
||||
return typeof v == "string" && v.length == 0
|
||||
}
|
||||
},
|
||||
template: `<div>
|
||||
<div class="ui label tiny basic" style="line-height: 1.5">
|
||||
@@ -29,8 +43,9 @@ Vue.component("http-firewall-rule-label", {
|
||||
|
||||
<span v-else>
|
||||
<span v-if="rule.paramFilters != null && rule.paramFilters.length > 0" v-for="paramFilter in rule.paramFilters"> | {{paramFilter.code}}</span>
|
||||
<var :class="{dash:rule.isCaseInsensitive}" :title="rule.isCaseInsensitive ? '大小写不敏感':''" v-if="!rule.isComposed">{{rule.operator}}</var>
|
||||
{{rule.value}}
|
||||
<span :class="{dash:rule.isCaseInsensitive}" :title="rule.isCaseInsensitive ? '大小写不敏感':''" v-if="!rule.isComposed">{{operatorName(rule.operator)}}</span>
|
||||
<span v-if="!isEmptyString(rule.value)">{{rule.value}}</span>
|
||||
<span v-else class="disabled" style="font-weight: normal" title="空字符串">[空]</span>
|
||||
</span>
|
||||
|
||||
<!-- description -->
|
||||
|
||||
@@ -21,7 +21,7 @@ Vue.component("http-firewall-rules-box", {
|
||||
})
|
||||
},
|
||||
updateRule: function (index, rule) {
|
||||
window.UPDATING_RULE = rule
|
||||
window.UPDATING_RULE = teaweb.clone(rule)
|
||||
let that = this
|
||||
teaweb.popup("/servers/components/waf/createRulePopup?type=" + this.vType, {
|
||||
height: "30em",
|
||||
@@ -35,12 +35,27 @@ Vue.component("http-firewall-rules-box", {
|
||||
teaweb.confirm("确定要删除此规则吗?", function () {
|
||||
that.rules.$remove(index)
|
||||
})
|
||||
},
|
||||
operatorName: function (operatorCode) {
|
||||
var operatorName = operatorCode
|
||||
if (typeof (window.WAF_RULE_OPERATORS) != null) {
|
||||
window.WAF_RULE_OPERATORS.forEach(function (v) {
|
||||
if (v.code == operatorCode) {
|
||||
operatorName = v.name
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return operatorName
|
||||
},
|
||||
isEmptyString: function (v) {
|
||||
return typeof v == "string" && v.length == 0
|
||||
}
|
||||
},
|
||||
template: `<div>
|
||||
<input type="hidden" name="rulesJSON" :value="JSON.stringify(rules)"/>
|
||||
<div v-if="rules.length > 0">
|
||||
<div v-for="(rule, index) in rules" class="ui label small basic" style="margin-bottom: 0.5em">
|
||||
<div v-for="(rule, index) in rules" class="ui label small basic" style="margin-bottom: 0.5em; line-height: 1.5">
|
||||
{{rule.name}}[{{rule.param}}]
|
||||
|
||||
<!-- cc2 -->
|
||||
@@ -55,7 +70,9 @@ Vue.component("http-firewall-rules-box", {
|
||||
</span>
|
||||
|
||||
<span v-else>
|
||||
<span v-if="rule.paramFilters != null && rule.paramFilters.length > 0" v-for="paramFilter in rule.paramFilters"> | {{paramFilter.code}}</span> <var>{{rule.operator}}</var> {{rule.value}}
|
||||
<span v-if="rule.paramFilters != null && rule.paramFilters.length > 0" v-for="paramFilter in rule.paramFilters"> | {{paramFilter.code}}</span> <span :class="{dash:rule.isCaseInsensitive}" :title="rule.isCaseInsensitive ? '大小写不敏感':''">{{operatorName(rule.operator)}}</span>
|
||||
<span v-if="!isEmptyString(rule.value)">{{rule.value}}</span>
|
||||
<span v-else class="disabled" style="font-weight: normal" title="空字符串">[空]</span>
|
||||
</span>
|
||||
|
||||
<!-- description -->
|
||||
|
||||
@@ -28,7 +28,7 @@ Vue.component("http-header-assistant", {
|
||||
}
|
||||
this.matchedHeaders = this.allHeaders.filter(function (header) {
|
||||
return teaweb.match(header, v)
|
||||
}).slice(0, 5)
|
||||
}).slice(0, 10)
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
@@ -38,7 +38,7 @@ Vue.component("http-header-assistant", {
|
||||
}
|
||||
},
|
||||
template: `<span v-if="selectedHeaderName.length == 0">
|
||||
<a href="" v-for="header in matchedHeaders" class="ui label basic tiny blue" style="font-weight: normal" @click.prevent="select(header)">{{header}}</a>
|
||||
<a href="" v-for="header in matchedHeaders" class="ui label basic tiny blue" style="font-weight: normal; margin-bottom: 0.3em" @click.prevent="select(header)">{{header}}</a>
|
||||
<span v-if="matchedHeaders.length > 0"> </span>
|
||||
</span>`
|
||||
})
|
||||
@@ -54,6 +54,13 @@ Vue.component("http-header-policy-box", {
|
||||
}
|
||||
}
|
||||
|
||||
let responseCORS = {
|
||||
isOn: false
|
||||
}
|
||||
if (responsePolicy.cors != null) {
|
||||
responseCORS = responsePolicy.cors
|
||||
}
|
||||
|
||||
return {
|
||||
type: type,
|
||||
typeName: (type == "request") ? "请求" : "响应",
|
||||
@@ -62,7 +69,8 @@ Vue.component("http-header-policy-box", {
|
||||
requestSettingHeaders: requestSettingHeaders,
|
||||
requestDeletingHeaders: requestDeletingHeaders,
|
||||
responseSettingHeaders: responseSettingHeaders,
|
||||
responseDeletingHeaders: responseDeletingHeaders
|
||||
responseDeletingHeaders: responseDeletingHeaders,
|
||||
responseCORS: responseCORS
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
@@ -114,6 +122,13 @@ Vue.component("http-header-policy-box", {
|
||||
.refresh()
|
||||
}
|
||||
)
|
||||
},
|
||||
updateCORS: function (policyId) {
|
||||
teaweb.popup("/servers/server/settings/headers/updateCORSPopup?" + this.vParams + "&headerPolicyId=" + policyId + "&type=" + this.type, {
|
||||
callback: function () {
|
||||
teaweb.successRefresh("保存成功")
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
template: `<div>
|
||||
@@ -141,7 +156,7 @@ Vue.component("http-header-policy-box", {
|
||||
<warning-message>由于已经在当前<a :href="vGroupSettingUrl + '#request'">服务分组</a>中进行了对应的配置,在这里的配置将不会生效。</warning-message>
|
||||
</div>
|
||||
<div :class="{'opacity-mask': vHasGroupRequestConfig}">
|
||||
<h3>设置请求Header <a href="" @click.prevent="addSettingHeader(vRequestHeaderPolicy.id)">[添加新Header]</a></h3>
|
||||
<h4>设置请求Header <a href="" @click.prevent="addSettingHeader(vRequestHeaderPolicy.id)">[添加新Header]</a></h4>
|
||||
<p class="comment" v-if="requestSettingHeaders.length == 0">暂时还没有Header。</p>
|
||||
<table class="ui table selectable celled" v-if="requestSettingHeaders.length > 0">
|
||||
<thead>
|
||||
@@ -151,35 +166,39 @@ Vue.component("http-header-policy-box", {
|
||||
<th class="two op">操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr v-for="header in requestSettingHeaders">
|
||||
<td class="five wide">
|
||||
{{header.name}}
|
||||
<div>
|
||||
<span v-if="header.status != null && header.status.codes != null && !header.status.always"><grey-label v-for="code in header.status.codes" :key="code">{{code}}</grey-label></span>
|
||||
<span v-if="header.methods != null && header.methods.length > 0"><grey-label v-for="method in header.methods" :key="method">{{method}}</grey-label></span>
|
||||
<span v-if="header.domains != null && header.domains.length > 0"><grey-label v-for="domain in header.domains" :key="domain">{{domain}}</grey-label></span>
|
||||
<grey-label v-if="header.shouldAppend">附加</grey-label>
|
||||
<grey-label v-if="header.disableRedirect">跳转禁用</grey-label>
|
||||
<grey-label v-if="header.shouldReplace && header.replaceValues != null && header.replaceValues.length > 0">替换</grey-label>
|
||||
</div>
|
||||
</td>
|
||||
<td>{{header.value}}</td>
|
||||
<td><a href="" @click.prevent="updateSettingPopup(vRequestHeaderPolicy.id, header.id)">修改</a> <a href="" @click.prevent="deleteHeader(vRequestHeaderPolicy.id, 'setHeader', header.id)">删除</a> </td>
|
||||
</tr>
|
||||
<tbody v-for="header in requestSettingHeaders">
|
||||
<tr>
|
||||
<td class="five wide">
|
||||
{{header.name}}
|
||||
<div>
|
||||
<span v-if="header.status != null && header.status.codes != null && !header.status.always"><grey-label v-for="code in header.status.codes" :key="code">{{code}}</grey-label></span>
|
||||
<span v-if="header.methods != null && header.methods.length > 0"><grey-label v-for="method in header.methods" :key="method">{{method}}</grey-label></span>
|
||||
<span v-if="header.domains != null && header.domains.length > 0"><grey-label v-for="domain in header.domains" :key="domain">{{domain}}</grey-label></span>
|
||||
<grey-label v-if="header.shouldAppend">附加</grey-label>
|
||||
<grey-label v-if="header.disableRedirect">跳转禁用</grey-label>
|
||||
<grey-label v-if="header.shouldReplace && header.replaceValues != null && header.replaceValues.length > 0">替换</grey-label>
|
||||
</div>
|
||||
</td>
|
||||
<td>{{header.value}}</td>
|
||||
<td><a href="" @click.prevent="updateSettingPopup(vRequestHeaderPolicy.id, header.id)">修改</a> <a href="" @click.prevent="deleteHeader(vRequestHeaderPolicy.id, 'setHeader', header.id)">删除</a> </td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<h3>删除请求Header</h3>
|
||||
<h4>删除请求Header</h4>
|
||||
<p class="comment">这里可以设置需要从请求中删除的Header。</p>
|
||||
|
||||
<table class="ui table definition selectable">
|
||||
<td class="title">需要删除的Header</td>
|
||||
<td>
|
||||
<div v-if="requestDeletingHeaders.length > 0">
|
||||
<div class="ui label small basic" v-for="headerName in requestDeletingHeaders">{{headerName}} <a href=""><i class="icon remove" title="删除" @click.prevent="deleteDeletingHeader(vRequestHeaderPolicy.id, headerName)"></i></a> </div>
|
||||
<div class="ui divider" ></div>
|
||||
</div>
|
||||
<button class="ui button small" type="button" @click.prevent="addDeletingHeader(vRequestHeaderPolicy.id, 'request')">+</button>
|
||||
</td>
|
||||
<tr>
|
||||
<td class="title">需要删除的Header</td>
|
||||
<td>
|
||||
<div v-if="requestDeletingHeaders.length > 0">
|
||||
<div class="ui label small basic" v-for="headerName in requestDeletingHeaders">{{headerName}} <a href=""><i class="icon remove" title="删除" @click.prevent="deleteDeletingHeader(vRequestHeaderPolicy.id, headerName)"></i></a> </div>
|
||||
<div class="ui divider" ></div>
|
||||
</div>
|
||||
<button class="ui button small" type="button" @click.prevent="addDeletingHeader(vRequestHeaderPolicy.id, 'request')">+</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
@@ -199,7 +218,7 @@ Vue.component("http-header-policy-box", {
|
||||
<warning-message>由于已经在当前<a :href="vGroupSettingUrl + '#response'">服务分组</a>中进行了对应的配置,在这里的配置将不会生效。</warning-message>
|
||||
</div>
|
||||
<div :class="{'opacity-mask': vHasGroupResponseConfig}">
|
||||
<h3>设置响应Header <a href="" @click.prevent="addSettingHeader(vResponseHeaderPolicy.id)">[添加新Header]</a></h3>
|
||||
<h4>设置响应Header <a href="" @click.prevent="addSettingHeader(vResponseHeaderPolicy.id)">[添加新Header]</a></h4>
|
||||
<p class="comment" style="margin-top: 0; padding-top: 0">将会覆盖已有的同名Header。</p>
|
||||
<p class="comment" v-if="responseSettingHeaders.length == 0">暂时还没有Header。</p>
|
||||
<table class="ui table selectable celled" v-if="responseSettingHeaders.length > 0">
|
||||
@@ -210,37 +229,52 @@ Vue.component("http-header-policy-box", {
|
||||
<th class="two op">操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr v-for="header in responseSettingHeaders">
|
||||
<td class="five wide">
|
||||
{{header.name}}
|
||||
<div>
|
||||
<span v-if="header.status != null && header.status.codes != null && !header.status.always"><grey-label v-for="code in header.status.codes" :key="code">{{code}}</grey-label></span>
|
||||
<span v-if="header.methods != null && header.methods.length > 0"><grey-label v-for="method in header.methods" :key="method">{{method}}</grey-label></span>
|
||||
<span v-if="header.domains != null && header.domains.length > 0"><grey-label v-for="domain in header.domains" :key="domain">{{domain}}</grey-label></span>
|
||||
<grey-label v-if="header.shouldAppend">附加</grey-label>
|
||||
<grey-label v-if="header.disableRedirect">跳转禁用</grey-label>
|
||||
<grey-label v-if="header.shouldReplace && header.replaceValues != null && header.replaceValues.length > 0">替换</grey-label>
|
||||
</div>
|
||||
</td>
|
||||
<td>{{header.value}}</td>
|
||||
<td><a href="" @click.prevent="updateSettingPopup(vResponseHeaderPolicy.id, header.id)">修改</a> <a href="" @click.prevent="deleteHeader(vResponseHeaderPolicy.id, 'setHeader', header.id)">删除</a> </td>
|
||||
</tr>
|
||||
<tbody v-for="header in responseSettingHeaders">
|
||||
<tr>
|
||||
<td class="five wide">
|
||||
{{header.name}}
|
||||
<div>
|
||||
<span v-if="header.status != null && header.status.codes != null && !header.status.always"><grey-label v-for="code in header.status.codes" :key="code">{{code}}</grey-label></span>
|
||||
<span v-if="header.methods != null && header.methods.length > 0"><grey-label v-for="method in header.methods" :key="method">{{method}}</grey-label></span>
|
||||
<span v-if="header.domains != null && header.domains.length > 0"><grey-label v-for="domain in header.domains" :key="domain">{{domain}}</grey-label></span>
|
||||
<grey-label v-if="header.shouldAppend">附加</grey-label>
|
||||
<grey-label v-if="header.disableRedirect">跳转禁用</grey-label>
|
||||
<grey-label v-if="header.shouldReplace && header.replaceValues != null && header.replaceValues.length > 0">替换</grey-label>
|
||||
</div>
|
||||
</td>
|
||||
<td>{{header.value}}</td>
|
||||
<td><a href="" @click.prevent="updateSettingPopup(vResponseHeaderPolicy.id, header.id)">修改</a> <a href="" @click.prevent="deleteHeader(vResponseHeaderPolicy.id, 'setHeader', header.id)">删除</a> </td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<h3>删除响应Header</h3>
|
||||
<h4>删除响应Header</h4>
|
||||
<p class="comment">这里可以设置需要从响应中删除的Header。</p>
|
||||
|
||||
<table class="ui table definition selectable">
|
||||
<td class="title">需要删除的Header</td>
|
||||
<td>
|
||||
<div v-if="responseDeletingHeaders.length > 0">
|
||||
<div class="ui label small basic" v-for="headerName in responseDeletingHeaders">{{headerName}} <a href=""><i class="icon remove" title="删除" @click.prevent="deleteDeletingHeader(vResponseHeaderPolicy.id, headerName)"></i></a> </div>
|
||||
<div class="ui divider" ></div>
|
||||
</div>
|
||||
<button class="ui button small" type="button" @click.prevent="addDeletingHeader(vResponseHeaderPolicy.id, 'response')">+</button>
|
||||
</td>
|
||||
<tr>
|
||||
<td class="title">需要删除的Header</td>
|
||||
<td>
|
||||
<div v-if="responseDeletingHeaders.length > 0">
|
||||
<div class="ui label small basic" v-for="headerName in responseDeletingHeaders">{{headerName}} <a href=""><i class="icon remove" title="删除" @click.prevent="deleteDeletingHeader(vResponseHeaderPolicy.id, headerName)"></i></a> </div>
|
||||
<div class="ui divider" ></div>
|
||||
</div>
|
||||
<button class="ui button small" type="button" @click.prevent="addDeletingHeader(vResponseHeaderPolicy.id, 'response')">+</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<h4>其他设置</h4>
|
||||
|
||||
<table class="ui table definition selectable">
|
||||
<tr>
|
||||
<td class="title">CORS自适应跨域</td>
|
||||
<td>
|
||||
<span v-if="responseCORS.isOn" class="green">已启用</span><span class="disabled" v-else="">未启用</span> <a href="" @click.prevent="updateCORS(vResponseHeaderPolicy.id)">[修改]</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="margin"></div>
|
||||
</div>`
|
||||
|
||||
@@ -57,7 +57,7 @@ Vue.component("http-remote-addr-config-box", {
|
||||
<prior-checkbox :v-config="config" v-if="vIsLocation || vIsGroup"></prior-checkbox>
|
||||
<tbody v-show="(!vIsLocation && !vIsGroup) || config.isPrior">
|
||||
<tr>
|
||||
<td class="title">是否启用</td>
|
||||
<td class="title">启用访客IP设置</td>
|
||||
<td>
|
||||
<div class="ui checkbox">
|
||||
<input type="checkbox" value="1" v-model="config.isOn"/>
|
||||
|
||||
@@ -62,7 +62,7 @@ Vue.component("http-request-limit-config-box", {
|
||||
<prior-checkbox :v-config="config" v-if="vIsLocation || vIsGroup"></prior-checkbox>
|
||||
<tbody v-show="(!vIsLocation && !vIsGroup) || config.isPrior">
|
||||
<tr>
|
||||
<td class="title">启用</td>
|
||||
<td class="title">启用请求限制</td>
|
||||
<td>
|
||||
<checkbox v-model="config.isOn"></checkbox>
|
||||
</td>
|
||||
|
||||
@@ -36,7 +36,7 @@ Vue.component("script-config-box", {
|
||||
<table class="ui table definition selectable">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="title">是否启用</td>
|
||||
<td class="title">启用脚本设置</td>
|
||||
<td><checkbox v-model="config.isOn"></checkbox></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
@@ -43,6 +43,7 @@ Vue.component("ssl-config-box", {
|
||||
}
|
||||
|
||||
let hsts = policy.hsts
|
||||
let hstsMaxAgeString = "31536000"
|
||||
if (hsts == null) {
|
||||
hsts = {
|
||||
isOn: false,
|
||||
@@ -52,6 +53,9 @@ Vue.component("ssl-config-box", {
|
||||
domains: []
|
||||
}
|
||||
}
|
||||
if (hsts.maxAge != null) {
|
||||
hstsMaxAgeString = hsts.maxAge.toString()
|
||||
}
|
||||
|
||||
return {
|
||||
policy: policy,
|
||||
@@ -60,6 +64,7 @@ Vue.component("ssl-config-box", {
|
||||
hsts: hsts,
|
||||
hstsOptionsVisible: false,
|
||||
hstsDomainAdding: false,
|
||||
hstsMaxAgeString: hstsMaxAgeString,
|
||||
addingHstsDomain: "",
|
||||
hstsDomainEditingIndex: -1,
|
||||
|
||||
@@ -233,22 +238,22 @@ Vue.component("ssl-config-box", {
|
||||
|
||||
// 监控HSTS有效期修改
|
||||
changeHSTSMaxAge: function () {
|
||||
var v = this.hsts.maxAge
|
||||
if (isNaN(v)) {
|
||||
var v = parseInt(this.hstsMaxAgeString)
|
||||
if (isNaN(v) || v < 0) {
|
||||
this.hsts.maxAge = 0
|
||||
this.hsts.days = "-"
|
||||
return
|
||||
}
|
||||
this.hsts.days = parseInt(v / 86400)
|
||||
if (isNaN(this.hsts.days)) {
|
||||
this.hsts.days = "-"
|
||||
} else if (this.hsts.days < 0) {
|
||||
this.hsts.maxAge = v
|
||||
this.hsts.days = v / 86400
|
||||
if (this.hsts.days == 0) {
|
||||
this.hsts.days = "-"
|
||||
}
|
||||
},
|
||||
|
||||
// 设置HSTS有效期
|
||||
setHSTSMaxAge: function (maxAge) {
|
||||
this.hsts.maxAge = maxAge
|
||||
this.hstsMaxAgeString = maxAge.toString()
|
||||
this.changeHSTSMaxAge()
|
||||
},
|
||||
|
||||
@@ -441,7 +446,7 @@ Vue.component("ssl-config-box", {
|
||||
<td>
|
||||
<div class="ui fields inline">
|
||||
<div class="ui field">
|
||||
<input type="text" name="hstsMaxAge" v-model="hsts.maxAge" maxlength="10" size="10" @input="changeHSTSMaxAge()"/>
|
||||
<input type="text" name="hstsMaxAge" v-model="hstsMaxAgeString" maxlength="10" size="10" @input="changeHSTSMaxAge()"/>
|
||||
</div>
|
||||
<div class="ui field">
|
||||
秒
|
||||
|
||||
@@ -63,7 +63,7 @@ Vue.component("traffic-limit-config-box", {
|
||||
<table class="ui table selectable definition">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="title">是否启用</td>
|
||||
<td class="title">启用流量限制</td>
|
||||
<td>
|
||||
<checkbox v-model="config.isOn"></checkbox>
|
||||
<p class="comment">注意:由于流量统计是每5分钟统计一次,所以超出流量限制后,对用户的提醒也会有所延迟。</p>
|
||||
|
||||
142
web/public/js/components/server/user-agent-config-box.js
Normal file
142
web/public/js/components/server/user-agent-config-box.js
Normal file
@@ -0,0 +1,142 @@
|
||||
Vue.component("user-agent-config-box", {
|
||||
props: ["v-is-location", "v-is-group", "value"],
|
||||
data: function () {
|
||||
let config = this.value
|
||||
if (config == null) {
|
||||
config = {
|
||||
isPrior: false,
|
||||
isOn: false,
|
||||
filters: []
|
||||
}
|
||||
}
|
||||
if (config.filters == null) {
|
||||
config.filters = []
|
||||
}
|
||||
return {
|
||||
config: config,
|
||||
isAdding: false,
|
||||
addingFilter: {
|
||||
keywords: [],
|
||||
action: "deny"
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
isOn: function () {
|
||||
return ((!this.vIsLocation && !this.vIsGroup) || this.config.isPrior) && this.config.isOn
|
||||
},
|
||||
remove: function (index) {
|
||||
let that = this
|
||||
teaweb.confirm("确定要删除此名单吗?", function () {
|
||||
that.config.filters.$remove(index)
|
||||
})
|
||||
},
|
||||
add: function () {
|
||||
this.isAdding = true
|
||||
},
|
||||
confirm: function () {
|
||||
if (this.addingFilter.action == "deny") {
|
||||
this.config.filters.push(this.addingFilter)
|
||||
} else {
|
||||
let index = -1
|
||||
this.config.filters.forEach(function (filter, filterIndex) {
|
||||
if (filter.action == "allow") {
|
||||
index = filterIndex
|
||||
}
|
||||
})
|
||||
|
||||
if (index < 0) {
|
||||
this.config.filters.unshift(this.addingFilter)
|
||||
} else {
|
||||
this.config.filters.$insert(index + 1, this.addingFilter)
|
||||
}
|
||||
}
|
||||
|
||||
this.cancel()
|
||||
},
|
||||
cancel: function () {
|
||||
this.isAdding = false
|
||||
this.addingFilter = {
|
||||
keywords: [],
|
||||
action: "deny"
|
||||
}
|
||||
},
|
||||
changeKeywords: function (keywords) {
|
||||
this.addingFilter.keywords = keywords
|
||||
}
|
||||
},
|
||||
template: `<div>
|
||||
<input type="hidden" name="userAgentJSON" :value="JSON.stringify(config)"/>
|
||||
<table class="ui table definition selectable">
|
||||
<prior-checkbox :v-config="config" v-if="vIsLocation || vIsGroup"></prior-checkbox>
|
||||
<tbody v-show="(!vIsLocation && !vIsGroup) || config.isPrior">
|
||||
<tr>
|
||||
<td class="title">启用UA名单</td>
|
||||
<td>
|
||||
<div class="ui checkbox">
|
||||
<input type="checkbox" value="1" v-model="config.isOn"/>
|
||||
<label></label>
|
||||
</div>
|
||||
<p class="comment">选中后表示开启UserAgent名单。</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
<tbody v-show="isOn()">
|
||||
<tr>
|
||||
<td>UA名单</td>
|
||||
<td>
|
||||
<div v-if="config.filters.length > 0">
|
||||
<table class="ui table celled">
|
||||
<thead class="full-width">
|
||||
<tr>
|
||||
<th>UA关键词</th>
|
||||
<th class="two wide">动作</th>
|
||||
<th class="one op">操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody v-for="(filter, index) in config.filters">
|
||||
<tr>
|
||||
<td style="background: white">
|
||||
<span v-for="keyword in filter.keywords" class="ui label basic tiny">
|
||||
<span v-if="keyword.length > 0">{{keyword}}</span>
|
||||
<span v-if="keyword.length == 0" class="disabled">[空]</span>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<span v-if="filter.action == 'allow'" class="green">允许</span><span v-if="filter.action == 'deny'" class="red">不允许</span>
|
||||
</td>
|
||||
<td><a href="" @click.prevent="remove(index)">删除</a></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div v-if="isAdding" style="margin-top: 0.5em">
|
||||
<table class="ui table definition">
|
||||
<tr>
|
||||
<td class="title">UA关键词</td>
|
||||
<td>
|
||||
<values-box :v-values="addingFilter.keywords" :v-allow-empty="true" @change="changeKeywords"></values-box>
|
||||
<p class="comment">不区分大小写,比如<code-label>Chrome</code-label>;支持<code-label>*</code-label>通配符,比如<code-label>*Firefox*</code-label>;也支持空的关键词,表示空UserAgent。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>动作</td>
|
||||
<td><select class="ui dropdown auto-width" v-model="addingFilter.action">
|
||||
<option value="deny">不允许</option>
|
||||
<option value="allow">允许</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<button type="button" class="ui button tiny" @click.prevent="confirm">保存</button> <a href="" @click.prevent="cancel" title="取消"><i class="icon remove small"></i></a>
|
||||
</div>
|
||||
<div v-show="!isAdding" style="margin-top: 0.5em">
|
||||
<button class="ui button tiny" type="button" @click.prevent="add">+</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="margin"></div>
|
||||
</div>`
|
||||
})
|
||||
@@ -49,6 +49,10 @@ window.teaweb = {
|
||||
}
|
||||
return true;
|
||||
},
|
||||
clone: function (source) {
|
||||
let s = JSON.stringify(source)
|
||||
return JSON.parse(s)
|
||||
},
|
||||
|
||||
loadJS: function (file, callback) {
|
||||
let element = document.createElement("script")
|
||||
@@ -349,6 +353,9 @@ window.teaweb = {
|
||||
Swal: function () {
|
||||
return this.isPopup() ? window.parent.Swal : window.Swal;
|
||||
},
|
||||
hasPopup: function () {
|
||||
return document.getElementsByClassName("swal2-container").length > 0
|
||||
},
|
||||
success: function (message, callback) {
|
||||
var width = "20em";
|
||||
if (message.length > 30) {
|
||||
@@ -940,7 +947,7 @@ window.teaweb = {
|
||||
},
|
||||
chartMap: {}, // dom id => chart
|
||||
initChart: function (dom, cache) {
|
||||
if (typeof(cache) != "boolean") {
|
||||
if (typeof (cache) != "boolean") {
|
||||
cache = true
|
||||
}
|
||||
|
||||
|
||||
@@ -728,7 +728,7 @@ span.olive,
|
||||
var.olive {
|
||||
color: #b5cc18 !important;
|
||||
}
|
||||
var.dash {
|
||||
span.dash {
|
||||
border-bottom: 1px dashed grey;
|
||||
}
|
||||
var.normal {
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -118,6 +118,12 @@ Tea.context(function () {
|
||||
return
|
||||
}
|
||||
this.$post("/clusters/tasks/check")
|
||||
.params({
|
||||
isDoing: this.doingNodeTasks.isDoing ? 1 : 0,
|
||||
hasError: this.doingNodeTasks.hasError ? 1 : 0,
|
||||
isUpdated: this.doingNodeTasks.isUpdated ? 1 : 0
|
||||
})
|
||||
.timeout(60)
|
||||
.success(function (resp) {
|
||||
this.doingNodeTasks.isDoing = resp.data.isDoing
|
||||
this.doingNodeTasks.hasError = resp.data.hasError
|
||||
@@ -151,6 +157,12 @@ Tea.context(function () {
|
||||
return
|
||||
}
|
||||
this.$post("/dns/tasks/check")
|
||||
.params({
|
||||
isDoing: this.doingDNSTasks.isDoing ? 1 : 0,
|
||||
hasError: this.doingDNSTasks.hasError ? 1 : 0,
|
||||
isUpdated: this.doingDNSTasks.isUpdated ? 1 : 0
|
||||
})
|
||||
.timeout(60)
|
||||
.success(function (resp) {
|
||||
this.doingDNSTasks.isDoing = resp.data.isDoing
|
||||
this.doingDNSTasks.hasError = resp.data.hasError
|
||||
|
||||
@@ -748,7 +748,7 @@ span.olive, var.olive {
|
||||
color: #b5cc18 !important;
|
||||
}
|
||||
|
||||
var.dash {
|
||||
span.dash {
|
||||
border-bottom: 1px dashed grey;
|
||||
}
|
||||
|
||||
|
||||
@@ -239,7 +239,7 @@ span.olive,
|
||||
var.olive {
|
||||
color: #b5cc18 !important;
|
||||
}
|
||||
var.dash {
|
||||
span.dash {
|
||||
border-bottom: 1px dashed grey;
|
||||
}
|
||||
/** Message **/
|
||||
@@ -312,4 +312,17 @@ textarea.wide-code {
|
||||
.combo-box .menu::-webkit-scrollbar {
|
||||
width: 4px;
|
||||
}
|
||||
code-label {
|
||||
background: #fff;
|
||||
border: 1px solid rgba(34, 36, 38, 0.15);
|
||||
color: rgba(0, 0, 0, 0.87);
|
||||
font-size: 0.71428571rem;
|
||||
padding: 3px;
|
||||
margin-left: 2px;
|
||||
margin-right: 2px;
|
||||
line-height: 1;
|
||||
display: inline-block;
|
||||
font-weight: 700;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
/*# sourceMappingURL=@layout_popup.css.map */
|
||||
@@ -1 +1 @@
|
||||
{"version":3,"sources":["@layout_popup.less"],"names":[],"mappings":"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","file":"@layout_popup.css"}
|
||||
{"version":3,"sources":["@layout_popup.less"],"names":[],"mappings":"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","file":"@layout_popup.css"}
|
||||
@@ -292,7 +292,7 @@ span.olive, var.olive {
|
||||
color: #b5cc18 !important;
|
||||
}
|
||||
|
||||
var.dash {
|
||||
span.dash {
|
||||
border-bottom: 1px dashed grey;
|
||||
}
|
||||
|
||||
@@ -379,4 +379,19 @@ textarea.wide-code {
|
||||
|
||||
.combo-box .menu::-webkit-scrollbar {
|
||||
width: 4px;
|
||||
}
|
||||
|
||||
// code-label
|
||||
code-label {
|
||||
background: #fff;
|
||||
border: 1px solid rgba(34, 36, 38, .15);
|
||||
color: rgba(0, 0, 0, .87);
|
||||
font-size: .71428571rem;
|
||||
padding: 3px;
|
||||
margin-left: 2px;
|
||||
margin-right: 2px;
|
||||
line-height: 1;
|
||||
display: inline-block;
|
||||
font-weight: 700;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
@@ -64,7 +64,7 @@
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>是否启用</td>
|
||||
<td>启用当前管理员</td>
|
||||
<td>
|
||||
<checkbox name="isOn" v-model="admin.isOn"></checkbox>
|
||||
</td>
|
||||
|
||||
@@ -256,7 +256,7 @@
|
||||
<td>上次更新时间</td>
|
||||
<td>
|
||||
{{nodeDatetime}}
|
||||
<p class="comment" v-if="nodeTimeDiff > 3"><span class="red">当前节点时间与API节点时间相差 {{nodeTimeDiff}} 秒,请同步节点时间。</span></p>
|
||||
<p class="comment" v-if="nodeTimeDiff > 30"><span class="red">当前节点时间与API节点时间相差 {{nodeTimeDiff}} 秒,请同步节点时间。</span></p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
<div>
|
||||
<second-menu>
|
||||
<menu-item @click.prevent="createThreshold">添加阈值</menu-item>
|
||||
<menu-item @click.prevent="createThreshold">[添加阈值]</menu-item>
|
||||
</second-menu>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -9,11 +9,16 @@
|
||||
<csrf-token></csrf-token>
|
||||
|
||||
<table class="ui table selectable definition">
|
||||
<tr v-if="hasDomains">
|
||||
<tr>
|
||||
<td>选择主域名 *</td>
|
||||
<td>
|
||||
<dns-domain-selector :v-domain-id="domainId" :v-domain-name="domainName" :v-provider-name="domainProvider.name" @change="changeDomain"></dns-domain-selector>
|
||||
<p class="comment">用于生成集群节点和网站服务的DNS解析记录<span v-if="domainId > 0">,修改后将自动删除旧域名中的相关记录</span>。</p>
|
||||
<div v-if="hasDomains">
|
||||
<dns-domain-selector :v-domain-id="domainId" :v-domain-name="domainName" :v-provider-name="domainProvider.name" @change="changeDomain"></dns-domain-selector>
|
||||
<p class="comment">用于生成集群节点和网站服务的DNS解析记录<span v-if="domainId > 0">,修改后将自动删除旧域名中的相关记录</span>。</p>
|
||||
</div>
|
||||
<div v-else>
|
||||
没有可用的域名,请在 <a href="/dns/providers" target="_blank">[域名解析]</a> 中添加。
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-if="oldDomain.id > 0 && domain.id == 0">
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
<td class="color-border">允许使用节点IP访问</td>
|
||||
<td>
|
||||
<checkbox name="httpAllAllowNodeIP" v-model="config.httpAll.allowNodeIP"></checkbox>
|
||||
<p class="comment">选中后,表示允许使用节点IP访问网站。</p>
|
||||
<p class="comment">选中后,表示允许直接使用节点IP访问网站。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-show="config.httpAll.matchDomainStrictly">
|
||||
@@ -90,6 +90,31 @@
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h4>性能</h4>
|
||||
<table class="ui table definition selectable">
|
||||
<tr>
|
||||
<td class="title">自动读数据超时</td>
|
||||
<td>
|
||||
<checkbox name="performanceAutoReadTimeout" v-model="config.performance.autoReadTimeout"></checkbox>
|
||||
<p class="comment">从客户端读取数据时自动设置超时时间,如果超时,则自动视为慢连接,并关闭网络连接;此为专业选项,请在专家指导下进行修改。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="title">自动写数据超时</td>
|
||||
<td>
|
||||
<checkbox name="performanceAutoWriteTimeout" v-model="config.performance.autoWriteTimeout"></checkbox>
|
||||
<p class="comment">向客户端发送数据时自动设置超时时间,如果超时,则自动视为慢连接,并关闭网络连接;此为专业选项,请在专家指导下进行修改。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>调试模式</td>
|
||||
<td>
|
||||
<checkbox name="performanceDebug" v-model="config.performance.debug"></checkbox>
|
||||
<p class="comment">开启调试模式后,将在某些信息中包含调试信息。</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<submit-btn></submit-btn>
|
||||
</form>
|
||||
</div>
|
||||
@@ -10,6 +10,12 @@
|
||||
<td class="title">集群名称 *</td>
|
||||
<td><input type="text" name="name" maxlength="50" ref="focus" v-model="cluster.name"/></td>
|
||||
</tr>
|
||||
<tr v-if="cluster.domainName.length > 0">
|
||||
<td>域名</td>
|
||||
<td>
|
||||
{{cluster.domainName}}<link-icon :href="'/clusters/cluster/settings/dns?clusterId=' + cluster.id"></link-icon>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>默认SSH认证</td>
|
||||
<td>
|
||||
|
||||
@@ -21,6 +21,7 @@ Tea.context(function () {
|
||||
that.itemDescription = v.description
|
||||
that.itemParams = v.params
|
||||
that.threshold.param = v.params[0].code
|
||||
that.paramDescription = v.params[0].description
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
<div class="right-box with-menu">
|
||||
<first-menu>
|
||||
<menu-item @click.prevent="createThreshold">添加阈值</menu-item>
|
||||
<menu-item @click.prevent="createThreshold">[添加阈值]</menu-item>
|
||||
</first-menu>
|
||||
|
||||
<p class="comment" v-if="thresholds.length == 0">暂时还没有设置阈值。</p>
|
||||
|
||||
@@ -26,6 +26,7 @@ Tea.context(function () {
|
||||
that.itemDescription = v.description
|
||||
that.itemParams = v.params
|
||||
that.threshold.param = v.params[0].code
|
||||
that.paramDescription = v.params[0].description
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -93,6 +93,13 @@
|
||||
<p class="comment">登录华为云控制台 -- 在"我的凭证 -- 访问密钥"中创建和获取。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>终端节点</td>
|
||||
<td>
|
||||
<input type="text" name="paramHuaweiEndpoint" maxlength="100"/>
|
||||
<p class="comment">选填项。可以填写终端节点(Endpoint)区域代号或者域名,参考 <a href="https://developer.huaweicloud.com/endpoint?DNS" target="_blank">https://developer.huaweicloud.com/endpoint?DNS</a>(如果此链接失效,请到华为云开发者中心自行查找)。</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
<!-- CloudFlare -->
|
||||
|
||||
@@ -67,6 +67,13 @@
|
||||
<td>AccessKeySecret</td>
|
||||
<td>{{provider.apiParams.accessKeySecret}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>终端节点</td>
|
||||
<td>
|
||||
<span v-if="provider.apiParams.endpoint != null && provider.apiParams.endpoint.length > 0">{{provider.apiParams.endpoint}}</span>
|
||||
<span v-else class="disabled">默认</span>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
<!-- CloudFlare -->
|
||||
|
||||
@@ -92,6 +92,13 @@
|
||||
<p class="comment">登录华为云控制台 -- 在"我的凭证 -- 访问密钥"中创建和获取。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>终端节点</td>
|
||||
<td>
|
||||
<input type="text" name="paramHuaweiEndpoint" maxlength="100" v-model="provider.params.endpoint"/>
|
||||
<p class="comment">选填项。可以填写终端节点(Endpoint)区域代号或者域名,参考 <a href="https://developer.huaweicloud.com/endpoint?DNS" target="_blank">https://developer.huaweicloud.com/endpoint?DNS</a>(如果此链接失效,请到华为云开发者中心自行查找)。</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
{$layout}
|
||||
{$template "menu"}
|
||||
|
||||
<div class="margin"></div>
|
||||
<div><span class="grey">预热缓存指的是预先从源站读取最新内容,当用户访问预热后的URL时直接从缓存中返回内容,不需要再次回源。</span></div>
|
||||
|
||||
<form method="post" class="ui form" data-tea-action="$" data-tea-before="before" data-tea-success="success" data-tea-fail="fail" data-tea-done="done" data-tea-timeout="3600">
|
||||
<csrf-token></csrf-token>
|
||||
<table class="ui table definition selectable">
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
|
||||
<div class="margin"></div>
|
||||
|
||||
<div><span class="grey">刷新缓存指的是标记URL列表或目录为失效状态,当有新的用户请求这些URL时,会再次从源站读取最新的内容。</span></div>
|
||||
|
||||
<form method="post" class="ui form" data-tea-action="$" data-tea-before="before" data-tea-success="success" data-tea-fail="fail" data-tea-done="done" data-tea-timeout="300">
|
||||
<csrf-token></csrf-token>
|
||||
<table class="ui table definition selectable">
|
||||
|
||||
@@ -13,9 +13,9 @@
|
||||
<select name="prefix" class="ui dropdown auto-width" @change="changeCheckpoint()" v-model="rule.checkpointPrefix">
|
||||
<option value="">[选择参数]</option>
|
||||
<optgroup label="特殊参数"></optgroup>
|
||||
<option v-for="cp in checkpoints" v-if="cp.isComposed" :value="cp.prefix">{{cp.name}} - [ {{cp.prefix}}]</option>
|
||||
<option v-for="cp in checkpoints" v-if="cp.isComposed" :value="cp.prefix">{{cp.name}} - [{{cp.prefix}}]</option>
|
||||
<optgroup label="通用参数"></optgroup>
|
||||
<option v-for="cp in checkpoints" v-if="!cp.isComposed" :value="cp.prefix">{{cp.name}} - [ {{cp.prefix}}]</option>
|
||||
<option v-for="cp in checkpoints" v-if="!cp.isComposed" :value="cp.prefix">{{cp.name}} - [{{cp.prefix}}]</option>
|
||||
</select>
|
||||
<p class="comment" v-if="checkpoint != null"><span class="ui label tiny">${<em style="font-style: normal;">{{checkpoint.prefix}}</em>}</span>{{checkpoint.description}}</p>
|
||||
</td>
|
||||
|
||||
@@ -27,7 +27,7 @@ Tea.context(function () {
|
||||
this.rule.checkpointPrefix = param
|
||||
}
|
||||
this.$delay(function () {
|
||||
this.changeCheckpoint()
|
||||
this.loadCheckpoint()
|
||||
if (this.rule.checkpointOptions != null && this.checkpoint != null && this.checkpoint.options != null) {
|
||||
let that = this
|
||||
this.checkpoint.options.forEach(function (option) {
|
||||
@@ -43,6 +43,18 @@ Tea.context(function () {
|
||||
* checkpoint
|
||||
*/
|
||||
this.checkpoint = null
|
||||
|
||||
this.loadCheckpoint = function () {
|
||||
if (this.rule.checkpointPrefix.length == 0) {
|
||||
this.checkpoint = null
|
||||
return
|
||||
}
|
||||
let that = this
|
||||
this.checkpoint = this.checkpoints.$find(function (k, v) {
|
||||
return v.prefix == that.rule.checkpointPrefix
|
||||
})
|
||||
}
|
||||
|
||||
this.changeCheckpoint = function () {
|
||||
if (this.rule.checkpointPrefix.length == 0) {
|
||||
this.checkpoint = null
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<input type="hidden" name="firewallPolicyId" :value="firewallPolicyId"/>
|
||||
<table class="ui table definition selectable">
|
||||
<tr>
|
||||
<td class="title">选择要倒入的规则文件</td>
|
||||
<td class="title">选择要导入的规则文件</td>
|
||||
<td>
|
||||
<input type="file" name="file" accept=".json"/>
|
||||
</td>
|
||||
|
||||
@@ -57,7 +57,6 @@ Tea.context(function () {
|
||||
// 添加分组
|
||||
this.createGroup = function (type) {
|
||||
teaweb.popup("/servers/components/waf/createGroupPopup?firewallPolicyId=" + this.firewallPolicyId + "&type=" + type, {
|
||||
height: "16em",
|
||||
callback: function () {
|
||||
teaweb.success("保存成功", function () {
|
||||
window.location.reload()
|
||||
|
||||
@@ -8,6 +8,14 @@ Tea.context(function () {
|
||||
this.isLoaded = false
|
||||
|
||||
this.load = function () {
|
||||
// 如果有弹窗时,暂时不更新
|
||||
if (teaweb.hasPopup()) {
|
||||
this.$delay(function () {
|
||||
this.load()
|
||||
}, 5000)
|
||||
return
|
||||
}
|
||||
|
||||
this.$post("$")
|
||||
.params({
|
||||
serverId: this.serverId,
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
{$layout "layout_popup"}
|
||||
|
||||
<h3>CORS跨域设置</h3>
|
||||
<form class="ui form" data-tea-action="$" data-tea-success="success">
|
||||
<csrf-token></csrf-token>
|
||||
<input type="hidden" name="headerPolicyId" :value="headerPolicyId"/>
|
||||
<http-cors-header-config-box v-model="cors"></http-cors-header-config-box>
|
||||
<submit-btn></submit-btn>
|
||||
</form>
|
||||
@@ -10,7 +10,15 @@
|
||||
<td>所属用户</td>
|
||||
<td>
|
||||
<span v-if="user != null">{{user.fullname}} <span class="small">({{user.username}})</span><link-icon :href="'/users/user?userId=' + user.id"></link-icon></span>
|
||||
<span v-else class="disabled">-</span>
|
||||
<div v-if="user == null">
|
||||
<div v-show="!userSelectorVisible">
|
||||
<span class="disabled">没有指定用户</span> <a href="" @click.prevent="showUserSelector">[指定用户]</a>
|
||||
</div>
|
||||
<div v-show="userSelectorVisible">
|
||||
<user-selector style="display:inline-block"></user-selector>
|
||||
<p class="comment"><span class="red">此操作同时会将与当前服务相关联的证书等数据自动修改为此用户所属。</span></p>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
@@ -66,7 +74,7 @@
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>是否启用</td>
|
||||
<td>启用当前服务</td>
|
||||
<td>
|
||||
<div class="ui checkbox">
|
||||
<input type="checkbox" name="isOn" value="1" v-model="server.isOn"/>
|
||||
|
||||
@@ -4,6 +4,12 @@ Tea.context(function () {
|
||||
/**
|
||||
* 用户相关
|
||||
*/
|
||||
this.userSelectorVisible = false
|
||||
|
||||
this.showUserSelector = function () {
|
||||
this.userSelectorVisible = !this.userSelectorVisible
|
||||
}
|
||||
|
||||
this.userId = 0
|
||||
this.plans = []
|
||||
this.userPlanId = 0
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
{$layout}
|
||||
{$template "/left_menu"}
|
||||
|
||||
<div class="right-box">
|
||||
{$template "../location_menu"}
|
||||
{$template "../left_menu"}
|
||||
|
||||
<div class="right-box tiny">
|
||||
<form class="ui form" data-tea-action="$" data-tea-success="success">
|
||||
<csrf-token></csrf-token>
|
||||
<input type="hidden" name="webId" :value="webId"/>
|
||||
|
||||
<user-agent-config-box v-model="userAgentConfig" :v-is-location="true"></user-agent-config-box>
|
||||
|
||||
<submit-btn></submit-btn>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,3 @@
|
||||
Tea.context(function () {
|
||||
this.success = NotifyReloadSuccess("保存成功")
|
||||
})
|
||||
@@ -0,0 +1,13 @@
|
||||
{$layout}
|
||||
{$template "../settings_menu"}
|
||||
{$template "/left_menu_with_menu"}
|
||||
|
||||
<div class="right-box with-menu">
|
||||
<form class="ui form" data-tea-action="$" data-tea-success="success">
|
||||
<csrf-token></csrf-token>
|
||||
<input type="hidden" name="webId" :value="webId"/>
|
||||
|
||||
<user-agent-config-box v-model="userAgentConfig"></user-agent-config-box>
|
||||
<submit-btn></submit-btn>
|
||||
</form>
|
||||
</div>
|
||||
@@ -0,0 +1,3 @@
|
||||
Tea.context(function () {
|
||||
this.success = NotifyReloadSuccess("保存成功")
|
||||
})
|
||||
@@ -57,7 +57,6 @@ Tea.context(function () {
|
||||
// 添加分组
|
||||
this.createGroup = function (type) {
|
||||
teaweb.popup("/servers/components/waf/createGroupPopup?firewallPolicyId=" + this.firewallPolicyId + "&type=" + type, {
|
||||
height: "16em",
|
||||
callback: function () {
|
||||
teaweb.success("保存成功", function () {
|
||||
window.location.reload()
|
||||
|
||||
@@ -33,35 +33,42 @@
|
||||
<td>关联集群</td>
|
||||
<td>
|
||||
<span v-if="user.cluster != null">{{user.cluster.name}} <link-icon :href="'/clusters/cluster?clusterId=' + user.cluster.id"></link-icon></span>
|
||||
<span v-else class="disabled">-</span>
|
||||
<span v-else class="disabled">没有设置。</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>手机号</td>
|
||||
<td>
|
||||
<span v-if="user.mobile.length > 0">{{user.mobile}}</span>
|
||||
<span v-else class="disabled">-</span>
|
||||
<span v-else class="disabled">没有设置。</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>联系电话</td>
|
||||
<td>
|
||||
<span v-if="user.tel.length > 0">{{user.tel}}</span>
|
||||
<span v-else class="disabled">-</span>
|
||||
<span v-else class="disabled">没有设置。</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>电子邮箱</td>
|
||||
<td>常用电子邮箱</td>
|
||||
<td>
|
||||
<span v-if="user.email.length > 0">{{user.email}}</span>
|
||||
<span v-else class="disabled">-</span>
|
||||
<span v-else class="disabled">没有设置。</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>已绑定电子邮箱</td>
|
||||
<td>
|
||||
<span v-if="user.verifiedEmail.length > 0">{{user.verifiedEmail}}</span>
|
||||
<span v-else class="disabled">没有设置。</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>备注</td>
|
||||
<td>
|
||||
<span v-if="user.remark.length > 0">{{user.remark}}</span>
|
||||
<span v-else class="disabled">-</span>
|
||||
<span v-else class="disabled">没有设置。</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
||||
Reference in New Issue
Block a user