mirror of
https://github.com/certimate-go/certimate.git
synced 2026-07-20 21:01:41 +08:00
refactor: add maps utility for json value replacements
This commit is contained in:
parent
d1a8e93f43
commit
9f614e67b6
@ -17,6 +17,7 @@ import (
|
||||
"github.com/certimate-go/certimate/pkg/core"
|
||||
xcert "github.com/certimate-go/certimate/pkg/utils/cert"
|
||||
xcertx509 "github.com/certimate-go/certimate/pkg/utils/cert/x509"
|
||||
xmaps "github.com/certimate-go/certimate/pkg/utils/maps"
|
||||
)
|
||||
|
||||
type (
|
||||
@ -148,7 +149,7 @@ func (d *Deployer) Deploy(ctx context.Context, certPEM, privkeyPEM string) (*Dep
|
||||
}
|
||||
|
||||
// 处理 Webhook 请求数据
|
||||
var webhookData interface{}
|
||||
var webhookData any
|
||||
if d.config.WebhookData == "" {
|
||||
webhookData = map[string]string{
|
||||
"name": strings.Join(xcertx509.GetSubjectAltNames(certX509), ";"),
|
||||
@ -176,21 +177,22 @@ func (d *Deployer) Deploy(ctx context.Context, certPEM, privkeyPEM string) (*Dep
|
||||
|
||||
// 替换变量值
|
||||
webhookUrl.Path = strings.ReplaceAll(webhookUrl.Path, "${CERTIMATE_DEPLOYER_COMMONNAME}", url.PathEscape(xcertx509.GetSubjectCommonName(certX509)))
|
||||
replaceJsonValueRecursively(webhookData, "${CERTIMATE_DEPLOYER_COMMONNAME}", xcertx509.GetSubjectCommonName(certX509))
|
||||
replaceJsonValueRecursively(webhookData, "${CERTIMATE_DEPLOYER_SUBJECTALTNAMES}", strings.Join(xcertx509.GetSubjectAltNames(certX509), ";"))
|
||||
replaceJsonValueRecursively(webhookData, "${CERTIMATE_DEPLOYER_CERTIFICATE}", certPEM)
|
||||
replaceJsonValueRecursively(webhookData, "${CERTIMATE_DEPLOYER_CERTIFICATE_SERVER}", serverCertPEM)
|
||||
replaceJsonValueRecursively(webhookData, "${CERTIMATE_DEPLOYER_CERTIFICATE_INTERMEDIA}", issuerCertPEM)
|
||||
replaceJsonValueRecursively(webhookData, "${CERTIMATE_DEPLOYER_PRIVATEKEY}", privkeyPEM)
|
||||
xmaps.DeepReplaceValueUnsafe(webhookData, "${CERTIMATE_DEPLOYER_COMMONNAME}", xcertx509.GetSubjectCommonName(certX509))
|
||||
xmaps.DeepReplaceValueUnsafe(webhookData, "${CERTIMATE_DEPLOYER_SUBJECTALTNAMES}", strings.Join(xcertx509.GetSubjectAltNames(certX509), ";"))
|
||||
xmaps.DeepReplaceValueUnsafe(webhookData, "${CERTIMATE_DEPLOYER_CERTIFICATE}", certPEM)
|
||||
xmaps.DeepReplaceValueUnsafe(webhookData, "${CERTIMATE_DEPLOYER_CERTIFICATE_SERVER}", serverCertPEM)
|
||||
xmaps.DeepReplaceValueUnsafe(webhookData, "${CERTIMATE_DEPLOYER_CERTIFICATE_INTERMEDIA}", issuerCertPEM)
|
||||
xmaps.DeepReplaceValueUnsafe(webhookData, "${CERTIMATE_DEPLOYER_PRIVATEKEY}", privkeyPEM)
|
||||
|
||||
// 兼容旧版变量
|
||||
// TODO: remove in future version
|
||||
webhookUrl.Path = strings.ReplaceAll(webhookUrl.Path, "${DOMAIN}", url.PathEscape(certX509.Subject.CommonName))
|
||||
replaceJsonValueRecursively(webhookData, "${DOMAIN}", certX509.Subject.CommonName)
|
||||
replaceJsonValueRecursively(webhookData, "${DOMAINS}", strings.Join(certX509.DNSNames, ";"))
|
||||
replaceJsonValueRecursively(webhookData, "${CERTIFICATE}", certPEM)
|
||||
replaceJsonValueRecursively(webhookData, "${SERVER_CERTIFICATE}", serverCertPEM)
|
||||
replaceJsonValueRecursively(webhookData, "${INTERMEDIA_CERTIFICATE}", issuerCertPEM)
|
||||
replaceJsonValueRecursively(webhookData, "${PRIVATE_KEY}", privkeyPEM)
|
||||
xmaps.DeepReplaceValueUnsafe(webhookData, "${DOMAIN}", certX509.Subject.CommonName)
|
||||
xmaps.DeepReplaceValueUnsafe(webhookData, "${DOMAINS}", strings.Join(certX509.DNSNames, ";"))
|
||||
xmaps.DeepReplaceValueUnsafe(webhookData, "${CERTIFICATE}", certPEM)
|
||||
xmaps.DeepReplaceValueUnsafe(webhookData, "${SERVER_CERTIFICATE}", serverCertPEM)
|
||||
xmaps.DeepReplaceValueUnsafe(webhookData, "${INTERMEDIA_CERTIFICATE}", issuerCertPEM)
|
||||
xmaps.DeepReplaceValueUnsafe(webhookData, "${PRIVATE_KEY}", privkeyPEM)
|
||||
|
||||
// 生成请求
|
||||
// 其中 GET 请求需转换为查询参数
|
||||
@ -222,19 +224,3 @@ func (d *Deployer) Deploy(ctx context.Context, certPEM, privkeyPEM string) (*Dep
|
||||
|
||||
return &DeployResult{}, nil
|
||||
}
|
||||
|
||||
func replaceJsonValueRecursively(data interface{}, oldStr, newStr string) interface{} {
|
||||
switch v := data.(type) {
|
||||
case map[string]any:
|
||||
for k, val := range v {
|
||||
v[k] = replaceJsonValueRecursively(val, oldStr, newStr)
|
||||
}
|
||||
case []any:
|
||||
for i, val := range v {
|
||||
v[i] = replaceJsonValueRecursively(val, oldStr, newStr)
|
||||
}
|
||||
case string:
|
||||
return strings.ReplaceAll(v, oldStr, newStr)
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
@ -10,13 +10,13 @@ import (
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/go-resty/resty/v2"
|
||||
|
||||
"github.com/certimate-go/certimate/internal/app"
|
||||
"github.com/certimate-go/certimate/pkg/core"
|
||||
xmaps "github.com/certimate-go/certimate/pkg/utils/maps"
|
||||
)
|
||||
|
||||
type (
|
||||
@ -107,11 +107,13 @@ func (n *Notifier) Notify(ctx context.Context, subject string, message string) (
|
||||
return nil, fmt.Errorf("failed to unmarshal custom payload: %w", err)
|
||||
}
|
||||
|
||||
replaceJsonValueRecursively(webhookData, "${CERTIMATE_NOTIFIER_SUBJECT}", subject)
|
||||
replaceJsonValueRecursively(webhookData, "${CERTIMATE_NOTIFIER_MESSAGE}", message)
|
||||
xmaps.DeepReplaceValue(webhookData, "${CERTIMATE_NOTIFIER_SUBJECT}", subject)
|
||||
xmaps.DeepReplaceValue(webhookData, "${CERTIMATE_NOTIFIER_MESSAGE}", message)
|
||||
|
||||
replaceJsonValueRecursively(webhookData, "${SUBJECT}", subject)
|
||||
replaceJsonValueRecursively(webhookData, "${MESSAGE}", message)
|
||||
// 兼容旧版变量
|
||||
// TODO: remove in future version
|
||||
xmaps.DeepReplaceValue(webhookData, "${SUBJECT}", subject)
|
||||
xmaps.DeepReplaceValue(webhookData, "${MESSAGE}", message)
|
||||
}
|
||||
|
||||
// REF: https://open.dingtalk.com/document/development/custom-robots-send-group-messages
|
||||
@ -135,25 +137,3 @@ func (n *Notifier) Notify(ctx context.Context, subject string, message string) (
|
||||
|
||||
return &NotifyResult{}, nil
|
||||
}
|
||||
|
||||
func replaceJsonValueRecursively(data interface{}, oldStr, newStr string) interface{} {
|
||||
switch v := data.(type) {
|
||||
case map[string]any:
|
||||
for k, val := range v {
|
||||
v[k] = replaceJsonValueRecursively(val, oldStr, newStr)
|
||||
}
|
||||
case []any:
|
||||
for i, val := range v {
|
||||
v[i] = replaceJsonValueRecursively(val, oldStr, newStr)
|
||||
}
|
||||
case []string:
|
||||
for i, s := range v {
|
||||
var val interface{} = s
|
||||
var newVal interface{} = replaceJsonValueRecursively(val, oldStr, newStr)
|
||||
v[i] = newVal.(string)
|
||||
}
|
||||
case string:
|
||||
return strings.ReplaceAll(v, oldStr, newStr)
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
@ -9,13 +9,13 @@ import (
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"net/url"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/go-resty/resty/v2"
|
||||
|
||||
"github.com/certimate-go/certimate/internal/app"
|
||||
"github.com/certimate-go/certimate/pkg/core"
|
||||
xmaps "github.com/certimate-go/certimate/pkg/utils/maps"
|
||||
)
|
||||
|
||||
type (
|
||||
@ -91,11 +91,13 @@ func (n *Notifier) Notify(ctx context.Context, subject string, message string) (
|
||||
return nil, fmt.Errorf("failed to unmarshal custom payload: %w", err)
|
||||
}
|
||||
|
||||
replaceJsonValueRecursively(webhookData, "${CERTIMATE_NOTIFIER_SUBJECT}", subject)
|
||||
replaceJsonValueRecursively(webhookData, "${CERTIMATE_NOTIFIER_MESSAGE}", message)
|
||||
xmaps.DeepReplaceValue(webhookData, "${CERTIMATE_NOTIFIER_SUBJECT}", subject)
|
||||
xmaps.DeepReplaceValue(webhookData, "${CERTIMATE_NOTIFIER_MESSAGE}", message)
|
||||
|
||||
replaceJsonValueRecursively(webhookData, "${SUBJECT}", subject)
|
||||
replaceJsonValueRecursively(webhookData, "${MESSAGE}", message)
|
||||
// 兼容旧版变量
|
||||
// TODO: remove in future version
|
||||
xmaps.DeepReplaceValue(webhookData, "${SUBJECT}", subject)
|
||||
xmaps.DeepReplaceValue(webhookData, "${MESSAGE}", message)
|
||||
}
|
||||
|
||||
if n.config.Secret != "" {
|
||||
@ -137,25 +139,3 @@ func (n *Notifier) Notify(ctx context.Context, subject string, message string) (
|
||||
|
||||
return &NotifyResult{}, nil
|
||||
}
|
||||
|
||||
func replaceJsonValueRecursively(data interface{}, oldStr, newStr string) interface{} {
|
||||
switch v := data.(type) {
|
||||
case map[string]any:
|
||||
for k, val := range v {
|
||||
v[k] = replaceJsonValueRecursively(val, oldStr, newStr)
|
||||
}
|
||||
case []any:
|
||||
for i, val := range v {
|
||||
v[i] = replaceJsonValueRecursively(val, oldStr, newStr)
|
||||
}
|
||||
case []string:
|
||||
for i, s := range v {
|
||||
var val interface{} = s
|
||||
var newVal interface{} = replaceJsonValueRecursively(val, oldStr, newStr)
|
||||
v[i] = newVal.(string)
|
||||
}
|
||||
case string:
|
||||
return strings.ReplaceAll(v, oldStr, newStr)
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
@ -15,6 +15,7 @@ import (
|
||||
"github.com/go-resty/resty/v2"
|
||||
|
||||
"github.com/certimate-go/certimate/pkg/core"
|
||||
xmaps "github.com/certimate-go/certimate/pkg/utils/maps"
|
||||
)
|
||||
|
||||
type (
|
||||
@ -134,7 +135,7 @@ func (n *Notifier) Notify(ctx context.Context, subject string, message string) (
|
||||
}
|
||||
|
||||
// 处理 Webhook 请求数据
|
||||
var webhookData interface{}
|
||||
var webhookData any
|
||||
if n.config.WebhookData == "" {
|
||||
webhookData = map[string]string{
|
||||
"subject": subject,
|
||||
@ -160,12 +161,13 @@ func (n *Notifier) Notify(ctx context.Context, subject string, message string) (
|
||||
}
|
||||
|
||||
// 替换变量值
|
||||
replaceJsonValueRecursively(webhookData, "${CERTIMATE_NOTIFIER_SUBJECT}", subject)
|
||||
replaceJsonValueRecursively(webhookData, "${CERTIMATE_NOTIFIER_MESSAGE}", message)
|
||||
xmaps.DeepReplaceValueUnsafe(webhookData, "${CERTIMATE_NOTIFIER_SUBJECT}", subject)
|
||||
xmaps.DeepReplaceValueUnsafe(webhookData, "${CERTIMATE_NOTIFIER_MESSAGE}", message)
|
||||
|
||||
// 兼容旧版变量
|
||||
replaceJsonValueRecursively(webhookData, "${SUBJECT}", subject)
|
||||
replaceJsonValueRecursively(webhookData, "${MESSAGE}", message)
|
||||
// TODO: remove in future version
|
||||
xmaps.DeepReplaceValueUnsafe(webhookData, "${SUBJECT}", subject)
|
||||
xmaps.DeepReplaceValueUnsafe(webhookData, "${MESSAGE}", message)
|
||||
|
||||
// 生成请求
|
||||
// 其中 GET 请求需转换为查询参数
|
||||
@ -197,25 +199,3 @@ func (n *Notifier) Notify(ctx context.Context, subject string, message string) (
|
||||
|
||||
return &NotifyResult{}, nil
|
||||
}
|
||||
|
||||
func replaceJsonValueRecursively(data interface{}, oldStr, newStr string) interface{} {
|
||||
switch v := data.(type) {
|
||||
case map[string]any:
|
||||
for k, val := range v {
|
||||
v[k] = replaceJsonValueRecursively(val, oldStr, newStr)
|
||||
}
|
||||
case []any:
|
||||
for i, val := range v {
|
||||
v[i] = replaceJsonValueRecursively(val, oldStr, newStr)
|
||||
}
|
||||
case []string:
|
||||
for i, s := range v {
|
||||
var val interface{} = s
|
||||
var newVal interface{} = replaceJsonValueRecursively(val, oldStr, newStr)
|
||||
v[i] = newVal.(string)
|
||||
}
|
||||
case string:
|
||||
return strings.ReplaceAll(v, oldStr, newStr)
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
@ -6,12 +6,12 @@ import (
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/go-resty/resty/v2"
|
||||
|
||||
"github.com/certimate-go/certimate/internal/app"
|
||||
"github.com/certimate-go/certimate/pkg/core"
|
||||
xmaps "github.com/certimate-go/certimate/pkg/utils/maps"
|
||||
)
|
||||
|
||||
type (
|
||||
@ -84,11 +84,13 @@ func (n *Notifier) Notify(ctx context.Context, subject string, message string) (
|
||||
return nil, fmt.Errorf("failed to unmarshal custom payload: %w", err)
|
||||
}
|
||||
|
||||
replaceJsonValueRecursively(webhookData, "${CERTIMATE_NOTIFIER_SUBJECT}", subject)
|
||||
replaceJsonValueRecursively(webhookData, "${CERTIMATE_NOTIFIER_MESSAGE}", message)
|
||||
xmaps.DeepReplaceValue(webhookData, "${CERTIMATE_NOTIFIER_SUBJECT}", subject)
|
||||
xmaps.DeepReplaceValue(webhookData, "${CERTIMATE_NOTIFIER_MESSAGE}", message)
|
||||
|
||||
replaceJsonValueRecursively(webhookData, "${SUBJECT}", subject)
|
||||
replaceJsonValueRecursively(webhookData, "${MESSAGE}", message)
|
||||
// 兼容旧版变量
|
||||
// TODO: remove in future version
|
||||
xmaps.DeepReplaceValue(webhookData, "${SUBJECT}", subject)
|
||||
xmaps.DeepReplaceValue(webhookData, "${MESSAGE}", message)
|
||||
}
|
||||
|
||||
// REF: https://developer.work.weixin.qq.com/document/path/91770
|
||||
@ -112,25 +114,3 @@ func (n *Notifier) Notify(ctx context.Context, subject string, message string) (
|
||||
|
||||
return &NotifyResult{}, nil
|
||||
}
|
||||
|
||||
func replaceJsonValueRecursively(data interface{}, oldStr, newStr string) interface{} {
|
||||
switch v := data.(type) {
|
||||
case map[string]any:
|
||||
for k, val := range v {
|
||||
v[k] = replaceJsonValueRecursively(val, oldStr, newStr)
|
||||
}
|
||||
case []any:
|
||||
for i, val := range v {
|
||||
v[i] = replaceJsonValueRecursively(val, oldStr, newStr)
|
||||
}
|
||||
case []string:
|
||||
for i, s := range v {
|
||||
var val interface{} = s
|
||||
var newVal interface{} = replaceJsonValueRecursively(val, oldStr, newStr)
|
||||
v[i] = newVal.(string)
|
||||
}
|
||||
case string:
|
||||
return strings.ReplaceAll(v, oldStr, newStr)
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
92
pkg/utils/loop/for.go
Normal file
92
pkg/utils/loop/for.go
Normal file
@ -0,0 +1,92 @@
|
||||
package loop
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
)
|
||||
|
||||
// 遍历集合并执行迭代函数。
|
||||
//
|
||||
// 入参:
|
||||
// - collection: 集合。
|
||||
// - iter: 迭代函数,接收集合中的元素和索引作为参数,返回错误。
|
||||
//
|
||||
// 出参:
|
||||
// - err: 错误。
|
||||
func ForRange[T any](collection []T, iter func(item T, index int) error) error {
|
||||
iterWithContext := func(_ context.Context, item T, index int) error {
|
||||
return iter(item, index)
|
||||
}
|
||||
return ForRangeWithContext(context.Background(), collection, iterWithContext)
|
||||
}
|
||||
|
||||
// 遍历集合并执行迭代函数,或上下文被取消。
|
||||
//
|
||||
// 入参:
|
||||
// - ctx: 上下文。
|
||||
// - collection: 集合。
|
||||
// - iter: 迭代函数,接收上下文、集合中的元素和索引作为参数,返回错误。
|
||||
//
|
||||
// 出参:
|
||||
// - err: 错误。
|
||||
func ForRangeWithContext[T any](ctx context.Context, collection []T, iter func(ctx context.Context, item T, index int) error) error {
|
||||
for i, item := range collection {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
|
||||
default:
|
||||
if err := iter(ctx, item, i); err != nil {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// 与 [ForRange] 类似,但在迭代时遇到错误不会中止、并在收集所有错误后返回。
|
||||
//
|
||||
// 入参:
|
||||
// - collection: 集合。
|
||||
// - iter: 迭代函数,接收集合中的元素和索引作为参数,返回错误。
|
||||
//
|
||||
// 出参:
|
||||
// - err: 错误。
|
||||
func ForRangeAll[T any](collection []T, iter func(item T, index int) error) error {
|
||||
iterWithContext := func(_ context.Context, item T, index int) error {
|
||||
return iter(item, index)
|
||||
}
|
||||
return ForRangeAllWithContext(context.Background(), collection, iterWithContext)
|
||||
}
|
||||
|
||||
// 与 [ForRangeAllWithContext] 类似,但在迭代时遇到错误不会中止、并在收集所有错误后返回。
|
||||
//
|
||||
// 入参:
|
||||
// - ctx: 上下文。
|
||||
// - collection: 集合。
|
||||
// - iter: 迭代函数,接收上下文、集合中的元素和索引作为参数,返回错误。
|
||||
//
|
||||
// 出参:
|
||||
// - err: 错误。
|
||||
func ForRangeAllWithContext[T any](ctx context.Context, collection []T, iter func(ctx context.Context, item T, index int) error) error {
|
||||
var errs []error
|
||||
|
||||
for i, item := range collection {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
|
||||
default:
|
||||
if err := iter(ctx, item, i); err != nil {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(errs) > 0 {
|
||||
return errors.Join(errs...)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
44
pkg/utils/maps/replace.go
Normal file
44
pkg/utils/maps/replace.go
Normal file
@ -0,0 +1,44 @@
|
||||
package maps
|
||||
|
||||
import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
// 在字典中递归地替换指定的字符串的值。
|
||||
// 注意该函数会修改原始的字典。
|
||||
//
|
||||
// 入参:
|
||||
// - dict: 字典。
|
||||
// - oldStr:需要替换的字符串。
|
||||
// - newStr:替换后的字符串。
|
||||
//
|
||||
// 出参:
|
||||
// - dict: 替换后的字典。
|
||||
func DeepReplaceValue(dict map[string]any, oldStr, newStr string) map[string]any {
|
||||
return deepReplaceMapValue(dict, oldStr, newStr).(map[string]any)
|
||||
}
|
||||
|
||||
// 与 [DeepReplaceValue] 类似,但入参类型为 `any`。
|
||||
func DeepReplaceValueUnsafe(dict any, oldStr, newStr string) any {
|
||||
return deepReplaceMapValue(dict, oldStr, newStr)
|
||||
}
|
||||
|
||||
func deepReplaceMapValue(data any, oldStr, newStr string) any {
|
||||
switch v := data.(type) {
|
||||
case map[string]any:
|
||||
for k, va := range v {
|
||||
v[k] = deepReplaceMapValue(va, oldStr, newStr)
|
||||
}
|
||||
case []any:
|
||||
for i, va := range v {
|
||||
v[i] = deepReplaceMapValue(va, oldStr, newStr)
|
||||
}
|
||||
case []string:
|
||||
for i, vs := range v {
|
||||
v[i] = deepReplaceMapValue(vs, oldStr, newStr).(string)
|
||||
}
|
||||
case string:
|
||||
return strings.ReplaceAll(v, oldStr, newStr)
|
||||
}
|
||||
return data
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user