前端页面

This commit is contained in:
robin
2026-02-24 11:33:44 +08:00
parent f3af234308
commit 60dc87e0f2
141 changed files with 6845 additions and 133 deletions

View File

@@ -0,0 +1,68 @@
package policies
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/httpdns/httpdnsutils"
"github.com/iwind/TeaGo/actions"
"github.com/iwind/TeaGo/maps"
)
type IndexAction struct {
actionutils.ParentAction
}
func (this *IndexAction) Init() {
this.Nav("httpdns", "policy", "")
}
func (this *IndexAction) RunGet(params struct{}) {
httpdnsutils.AddLeftMenu(this.Parent())
this.Data["policies"] = loadGlobalPolicies()
this.Data["availableClusters"] = loadAvailableDeployClusters()
this.Show()
}
func (this *IndexAction) RunPost(params struct {
DefaultClusterId int64
EnableUserDomainVerify bool
DefaultTTL int
DefaultFallbackMs int
Must *actions.Must
CSRF *actionutils.CSRF
}) {
if params.DefaultClusterId <= 0 || !isValidClusterID(params.DefaultClusterId) {
this.Fail("please select a valid default cluster")
return
}
params.Must.Field("defaultTTL", params.DefaultTTL).Gt(0, "default ttl should be > 0")
params.Must.Field("defaultFallbackMs", params.DefaultFallbackMs).Gt(0, "default fallback should be > 0")
if params.DefaultTTL > 86400 {
this.Fail("default TTL should be <= 86400")
return
}
if params.DefaultFallbackMs > 10000 {
this.Fail("default fallback should be <= 10000 ms")
return
}
saveGlobalPolicies(maps.Map{
"defaultClusterId": params.DefaultClusterId,
"enableUserDomainVerify": params.EnableUserDomainVerify,
"defaultTTL": params.DefaultTTL,
"defaultFallbackMs": params.DefaultFallbackMs,
})
this.Success()
}
func isValidClusterID(clusterID int64) bool {
for _, cluster := range loadAvailableDeployClusters() {
if cluster.GetInt64("id") == clusterID {
return true
}
}
return false
}

View File

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

View File

@@ -0,0 +1,172 @@
package policies
import (
"strings"
"sync"
"github.com/iwind/TeaGo/maps"
)
var globalPoliciesStore = struct {
sync.RWMutex
data maps.Map
publicSniPools []maps.Map
publicSniCertificates []maps.Map
}{
data: maps.Map{
"defaultClusterId": int64(1),
"enableUserDomainVerify": true,
"defaultTTL": 30,
"defaultFallbackMs": 300,
},
publicSniPools: []maps.Map{
{
"domain": "public-sni-a.waf.example.com",
"certId": "cert_public_sni_a",
},
{
"domain": "public-sni-b.waf.example.com",
"certId": "cert_public_sni_b",
},
},
publicSniCertificates: []maps.Map{
{
"id": "cert_public_sni_a",
"name": "public-sni-a.waf.example.com",
"issuer": "Mock CA",
"expiresAt": "2026-12-31 23:59:59",
},
{
"id": "cert_public_sni_b",
"name": "public-sni-b.waf.example.com",
"issuer": "Mock CA",
"expiresAt": "2027-03-31 23:59:59",
},
},
}
func loadGlobalPolicies() maps.Map {
globalPoliciesStore.RLock()
defer globalPoliciesStore.RUnlock()
return maps.Map{
"defaultClusterId": globalPoliciesStore.data.GetInt64("defaultClusterId"),
"enableUserDomainVerify": globalPoliciesStore.data.GetBool("enableUserDomainVerify"),
"defaultTTL": globalPoliciesStore.data.GetInt("defaultTTL"),
"defaultFallbackMs": globalPoliciesStore.data.GetInt("defaultFallbackMs"),
}
}
func saveGlobalPolicies(policies maps.Map) {
globalPoliciesStore.Lock()
globalPoliciesStore.data = maps.Map{
"defaultClusterId": policies.GetInt64("defaultClusterId"),
"enableUserDomainVerify": policies.GetBool("enableUserDomainVerify"),
"defaultTTL": policies.GetInt("defaultTTL"),
"defaultFallbackMs": policies.GetInt("defaultFallbackMs"),
}
globalPoliciesStore.Unlock()
}
func loadPublicSNICertificates() []maps.Map {
globalPoliciesStore.RLock()
defer globalPoliciesStore.RUnlock()
return cloneMapSlice(globalPoliciesStore.publicSniCertificates)
}
// LoadPublicSNICertificates returns global public SNI certificates for other httpdns modules.
func LoadPublicSNICertificates() []maps.Map {
return loadPublicSNICertificates()
}
func loadAvailableDeployClusters() []maps.Map {
return []maps.Map{
{
"id": int64(1),
"name": "gateway-cn-hz",
"region": "cn-hangzhou",
"gatewayDomain": "gw-hz.httpdns.example.com",
},
{
"id": int64(2),
"name": "gateway-cn-bj",
"region": "cn-beijing",
"gatewayDomain": "gw-bj.httpdns.example.com",
},
}
}
// LoadAvailableDeployClusters returns selectable clusters for HTTPDNS user defaults.
func LoadAvailableDeployClusters() []maps.Map {
return loadAvailableDeployClusters()
}
// LoadDefaultClusterID returns current default deploy cluster id for HTTPDNS users.
func LoadDefaultClusterID() int64 {
globalPoliciesStore.RLock()
defer globalPoliciesStore.RUnlock()
return globalPoliciesStore.data.GetInt64("defaultClusterId")
}
// LoadClusterGatewayByID returns gateway domain for the selected cluster.
func LoadClusterGatewayByID(clusterID int64) string {
clusters := loadAvailableDeployClusters()
for _, cluster := range clusters {
if cluster.GetInt64("id") == clusterID {
gatewayDomain := strings.TrimSpace(cluster.GetString("gatewayDomain"))
if len(gatewayDomain) > 0 {
return gatewayDomain
}
}
}
if len(clusters) > 0 {
fallback := strings.TrimSpace(clusters[0].GetString("gatewayDomain"))
if len(fallback) > 0 {
return fallback
}
}
return "gw.httpdns.example.com"
}
// LoadPublicSNIPools returns global public SNI domain pool for other httpdns modules.
func LoadPublicSNIPools() []maps.Map {
globalPoliciesStore.RLock()
defer globalPoliciesStore.RUnlock()
return cloneMapSlice(globalPoliciesStore.publicSniPools)
}
// HasPublicSNIDomain checks if a public SNI domain exists in global pool.
func HasPublicSNIDomain(domain string) bool {
domain = strings.ToLower(strings.TrimSpace(domain))
if len(domain) == 0 {
return false
}
globalPoliciesStore.RLock()
defer globalPoliciesStore.RUnlock()
for _, pool := range globalPoliciesStore.publicSniPools {
if strings.ToLower(strings.TrimSpace(pool.GetString("domain"))) == domain {
return true
}
}
return false
}
func cloneMapSlice(src []maps.Map) []maps.Map {
result := make([]maps.Map, 0, len(src))
for _, item := range src {
cloned := maps.Map{}
for k, v := range item {
cloned[k] = v
}
result = append(result, cloned)
}
return result
}