Skip to content

Commit

Permalink
feat: description file for custom theme; use gjson (#433)
Browse files Browse the repository at this point in the history
* feat: description file for custom theme; use gjson

* fix gosec

* remove outdated stuff
  • Loading branch information
uubulb authored Oct 9, 2024
1 parent 937696c commit 55f5c89
Show file tree
Hide file tree
Showing 12 changed files with 214 additions and 159 deletions.
62 changes: 38 additions & 24 deletions cmd/dashboard/controller/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ package controller
import (
"fmt"
"html/template"
"io/fs"
"log"
"net/http"
"os"
"path/filepath"
"strconv"
"strings"
"time"
Expand Down Expand Up @@ -34,28 +34,16 @@ func ServeWeb(port uint) *http.Server {
pprof.Register(r)
}
r.Use(natGateway)
if os.Getenv("NZ_LOCAL_TEMPLATE") == "true" {
r.SetFuncMap(funcMap)
r.Use(mygin.RecordPath)
r.Static("/static", "resource/static")
r.LoadHTMLGlob("resource/template/**/*.html")
} else {
tmpl := template.New("").Funcs(funcMap)
var err error
tmpl, err = tmpl.ParseFS(resource.TemplateFS, "template/**/*.html")
if err != nil {
panic(err)
}
tmpl = loadThirdPartyTemplates(tmpl)
r.SetHTMLTemplate(tmpl)
r.Use(mygin.RecordPath)
staticFs, err := fs.Sub(resource.StaticFS, "static")
if err != nil {
panic(err)
}
r.StaticFS("/static", http.FS(staticFs))
tmpl := template.New("").Funcs(funcMap)
var err error
tmpl, err = tmpl.ParseFS(resource.TemplateFS, "template/**/*.html")
if err != nil {
panic(err)
}
r.Static("/static-custom", "resource/static/custom")
tmpl = loadThirdPartyTemplates(tmpl)
r.SetHTMLTemplate(tmpl)
r.Use(mygin.RecordPath)
r.StaticFS("/static", http.FS(resource.StaticFS))
routers(r)
page404 := func(c *gin.Context) {
mygin.ShowErrorPage(c, mygin.ErrInfo{
Expand Down Expand Up @@ -106,14 +94,40 @@ func loadThirdPartyTemplates(tmpl *template.Template) *template.Template {
if !theme.IsDir() {
continue
}

themeDir := theme.Name()
if !strings.HasPrefix(themeDir, "theme-") {
log.Printf("NEZHA>> Invalid theme name: %s", themeDir)
continue
}

descPath := filepath.Join("resource", "template", themeDir, "theme.json")
desc, err := os.ReadFile(filepath.Clean(descPath))
if err != nil {
log.Printf("NEZHA>> Error opening %s config: %v", themeDir, err)
continue
}

themeName, err := utils.GjsonGet(desc, "name")
if err != nil {
log.Printf("NEZHA>> Error opening %s config: not a valid description file", theme.Name())
continue
}

// load templates
t, err := ret.ParseGlob(fmt.Sprintf("resource/template/%s/*.html", theme.Name()))
templatePath := filepath.Join("resource", "template", themeDir, "*.html")
t, err := ret.ParseGlob(templatePath)
if err != nil {
log.Printf("NEZHA>> Error parsing templates %s error: %v", theme.Name(), err)
log.Printf("NEZHA>> Error parsing templates %s: %v", themeDir, err)
continue
}

themeKey := strings.TrimPrefix(themeDir, "theme-")
model.Themes[themeKey] = themeName.String()

ret = t
}

return ret
}

Expand Down
3 changes: 3 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ require (
github.com/robfig/cron/v3 v3.0.1
github.com/spf13/pflag v1.0.5
github.com/spf13/viper v1.18.2
github.com/tidwall/gjson v1.18.0
github.com/xanzy/go-gitlab v0.103.0
golang.org/x/crypto v0.25.0
golang.org/x/net v0.27.0
Expand Down Expand Up @@ -70,6 +71,8 @@ require (
github.com/spf13/afero v1.11.0 // indirect
github.com/spf13/cast v1.6.0 // indirect
github.com/subosito/gotenv v1.6.0 // indirect
github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.0 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.2.11 // indirect
go.uber.org/atomic v1.9.0 // indirect
Expand Down
6 changes: 6 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,12 @@ github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsT
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY=
github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M=
Expand Down
1 change: 0 additions & 1 deletion model/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ var Themes = map[string]string{
"hotaru": "Hotaru",
"angel-kanade": "AngelKanade",
"server-status": "ServerStatus",
"custom": "Custom(local)",
}

var DashboardThemes = map[string]string{
Expand Down
8 changes: 4 additions & 4 deletions model/notification.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,8 @@ func (ns *NotificationServerBundle) reqBody(message string) (string, error) {
return string(msgBytes)[1 : len(msgBytes)-1]
}), nil
case NotificationRequestTypeForm:
var data map[string]string
if err := utils.Json.Unmarshal([]byte(n.RequestBody), &data); err != nil {
data, err := utils.GjsonParseStringMap(n.RequestBody)
if err != nil {
return "", err
}
params := url.Values{}
Expand All @@ -99,8 +99,8 @@ func (n *Notification) setRequestHeader(req *http.Request) error {
if n.RequestHeader == "" {
return nil
}
var m map[string]string
if err := utils.Json.Unmarshal([]byte(n.RequestHeader), &m); err != nil {
m, err := utils.GjsonParseStringMap(n.RequestHeader)
if err != nil {
return err
}
for k, v := range m {
Expand Down
103 changes: 34 additions & 69 deletions pkg/ddns/cloudflare.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package ddns

import (
"bytes"
"errors"
"fmt"
"io"
"log"
Expand All @@ -14,10 +15,13 @@ import (
const baseEndpoint = "https://api.cloudflare.com/client/v4/zones"

type ProviderCloudflare struct {
isIpv4 bool
domainConfig *DomainConfig
secret string
zoneId string
ipAddr string
recordId string
domainConfig *DomainConfig
recordType string
}

type cfReq struct {
Expand All @@ -28,13 +32,6 @@ type cfReq struct {
Proxied bool `json:"proxied"`
}

type cfResp struct {
Result []struct {
ID string `json:"id"`
Name string `json:"name"`
} `json:"result"`
}

func NewProviderCloudflare(s string) *ProviderCloudflare {
return &ProviderCloudflare{
secret: s,
Expand All @@ -54,33 +51,38 @@ func (provider *ProviderCloudflare) UpdateDomain(domainConfig *DomainConfig) err

// 当IPv4和IPv6同时成功才算作成功
if provider.domainConfig.EnableIPv4 {
if err = provider.addDomainRecord(true); err != nil {
provider.isIpv4 = true
provider.recordType = getRecordString(provider.isIpv4)
provider.ipAddr = provider.domainConfig.Ipv4Addr
if err = provider.addDomainRecord(); err != nil {
return err
}
}

if provider.domainConfig.EnableIpv6 {
if err = provider.addDomainRecord(false); err != nil {
provider.isIpv4 = false
provider.recordType = getRecordString(provider.isIpv4)
provider.ipAddr = provider.domainConfig.Ipv6Addr
if err = provider.addDomainRecord(); err != nil {
return err
}
}

return nil
}

func (provider *ProviderCloudflare) addDomainRecord(isIpv4 bool) error {
err := provider.findDNSRecord(isIpv4)
func (provider *ProviderCloudflare) addDomainRecord() error {
err := provider.findDNSRecord()
if err != nil {
if errors.Is(err, utils.ErrGjsonNotFound) {
// 添加 DNS 记录
return provider.createDNSRecord()
}
return fmt.Errorf("查找 DNS 记录时出错: %s", err)
}

if provider.recordId == "" {
// 添加 DNS 记录
return provider.createDNSRecord(isIpv4)
} else {
// 更新 DNS 记录
return provider.updateDNSRecord(isIpv4)
}
// 更新 DNS 记录
return provider.updateDNSRecord()
}

func (provider *ProviderCloudflare) getZoneID() error {
Expand All @@ -96,72 +98,44 @@ func (provider *ProviderCloudflare) getZoneID() error {
return err
}

res := &cfResp{}
err = utils.Json.Unmarshal(body, res)
result, err := utils.GjsonGet(body, "result.0.id")
if err != nil {
return err
}

result := res.Result
if len(result) > 0 {
provider.zoneId = result[0].ID
return nil
}

return fmt.Errorf("找不到 Zone ID")
provider.zoneId = result.String()
return nil
}

func (provider *ProviderCloudflare) findDNSRecord(isIPv4 bool) error {
var ipType string
if isIPv4 {
ipType = "A"
} else {
ipType = "AAAA"
}

func (provider *ProviderCloudflare) findDNSRecord() error {
de, _ := url.JoinPath(baseEndpoint, provider.zoneId, "dns_records")
du, _ := url.Parse(de)

q := du.Query()
q.Set("name", provider.domainConfig.FullDomain)
q.Set("type", ipType)
q.Set("type", provider.recordType)
du.RawQuery = q.Encode()

body, err := provider.sendRequest("GET", du.String(), nil)
if err != nil {
return err
}

res := &cfResp{}
err = utils.Json.Unmarshal(body, res)
result, err := utils.GjsonGet(body, "result.0.id")
if err != nil {
return err
}

result := res.Result
if len(result) > 0 {
provider.recordId = result[0].ID
return nil
}

provider.recordId = result.String()
return nil
}

func (provider *ProviderCloudflare) createDNSRecord(isIPv4 bool) error {
var ipType, ipAddr string
if isIPv4 {
ipType = "A"
ipAddr = provider.domainConfig.Ipv4Addr
} else {
ipType = "AAAA"
ipAddr = provider.domainConfig.Ipv6Addr
}

func (provider *ProviderCloudflare) createDNSRecord() error {
de, _ := url.JoinPath(baseEndpoint, provider.zoneId, "dns_records")
data := &cfReq{
Name: provider.domainConfig.FullDomain,
Type: ipType,
Content: ipAddr,
Type: provider.recordType,
Content: provider.ipAddr,
TTL: 60,
Proxied: false,
}
Expand All @@ -171,21 +145,12 @@ func (provider *ProviderCloudflare) createDNSRecord(isIPv4 bool) error {
return err
}

func (provider *ProviderCloudflare) updateDNSRecord(isIPv4 bool) error {
var ipType, ipAddr string
if isIPv4 {
ipType = "A"
ipAddr = provider.domainConfig.Ipv4Addr
} else {
ipType = "AAAA"
ipAddr = provider.domainConfig.Ipv6Addr
}

func (provider *ProviderCloudflare) updateDNSRecord() error {
de, _ := url.JoinPath(baseEndpoint, provider.zoneId, "dns_records", provider.recordId)
data := &cfReq{
Name: provider.domainConfig.FullDomain,
Type: ipType,
Content: ipAddr,
Type: provider.recordType,
Content: provider.ipAddr,
TTL: 60,
Proxied: false,
}
Expand Down
7 changes: 7 additions & 0 deletions pkg/ddns/ddns.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,10 @@ func splitDomain(domain string) (prefix string, realDomain string) {
prefix = domain[:len(domain)-len(realDomain)-1]
return prefix, realDomain
}

func getRecordString(isIpv4 bool) string {
if isIpv4 {
return "A"
}
return "AAAA"
}
Loading

0 comments on commit 55f5c89

Please sign in to comment.