chore(lint): unify formatting on golangci-lint fmt (gofumpt), uncap issue reporting, fix gofumpt drift

- make format 现在与 code-check 使用同一格式化器(golangci-lint fmt),消除 goimports -local 与 gofumpt 的格式拉锯
- .golangci.yml 关闭默认 50/3 截断,完整上报所有问题(只增强不弱化)
- 全库 gofumpt 规范化(203 files, 纯格式无行为变更)
This commit is contained in:
ryan
2026-08-28 16:31:53 +08:00
parent 078ad9b2f3
commit 528240026d
204 changed files with 572 additions and 718 deletions
+1
View File
@@ -0,0 +1 @@
{"ts":"2026-08-28T00:00:00Z","iter":0,"type":"baseline","metrics":{"lint_issues":45,"dup_issues":15,"tests_passed":44},"description":"baseline: 45 golangci issues (15 dupl), all tests pass","asi":{"note":"quick wins queue: gofumpt(4)+revive(8); then goconst/mnd; gosec; nilerr bug; contextcheck; dupl batches; nestif"}}
+7
View File
@@ -37,6 +37,7 @@ linters:
dupl:
threshold: 80
cyclop:
max-complexity: 20
package-average: 10
@@ -54,6 +55,12 @@ linters:
- condition
- return
# 完整上报所有问题(取消 golangci 默认 50/3 截断,保证 code-check 与度量真实)
issues:
max-issues-per-linter: 0
max-same-issues: 0
formatters:
enable:
- gofumpt
+2 -3
View File
@@ -14,9 +14,8 @@ license-check:
scripts/update_go_license.sh --check
format:
@echo "==> Formatting backend Go source with goimports..."
@command -v goimports >/dev/null 2>&1 || { echo 'error: goimports is required. Run: go install golang.org/x/tools/cmd/goimports@latest' >&2; exit 1; }
goimports -w -local $(MODULE) $$(find backend -type f -name '*.go' -not -path './.git/*')
@echo "==> Formatting backend Go source with golangci-lint fmt (gofumpt, same gate as code-check)..."
cd backend && golangci-lint fmt
@echo "==> Formatting frontend source..."
cd frontend && pnpm format
+1 -2
View File
@@ -5,11 +5,10 @@
package cmd
import (
"Wavelet/core"
"log"
"github.com/spf13/cobra"
"Wavelet/core"
)
var allCmd = &cobra.Command{
+1 -2
View File
@@ -4,11 +4,10 @@
package cmd
import (
"Wavelet/core"
"log"
"github.com/spf13/cobra"
"Wavelet/core"
)
var apiCmd = &cobra.Command{
+12 -12
View File
@@ -4,17 +4,6 @@
package cmd
import (
"context"
"database/sql"
"fmt"
"io/fs"
"log"
"path/filepath"
"time"
"github.com/pressly/goose/v3"
goosedb "github.com/pressly/goose/v3/database"
"Wavelet/core"
"Wavelet/core/contracts"
"Wavelet/pkg/config"
@@ -33,9 +22,20 @@ import (
"Wavelet/plugins/drivers/driver_inproc_worker"
"Wavelet/plugins/infra/cache"
"Wavelet/plugins/infra/cache_memory"
infradb "Wavelet/plugins/infra/database"
"Wavelet/plugins/infra/logger"
"Wavelet/plugins/infra/storage"
"context"
"database/sql"
"fmt"
"io/fs"
"log"
"path/filepath"
"time"
"github.com/pressly/goose/v3"
goosedb "github.com/pressly/goose/v3/database"
infradb "Wavelet/plugins/infra/database"
)
// newWaveletApp creates a core.App wired with Wavelet platform infrastructure, domain plugins, and profile drivers.
+2 -3
View File
@@ -4,13 +4,12 @@
package cmd
import (
"Wavelet/core"
"Wavelet/pkg/config"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"Wavelet/core"
"Wavelet/pkg/config"
)
func TestNewWaveletAppProfiles(t *testing.T) {
+2 -3
View File
@@ -7,12 +7,11 @@
package cmd
import (
"Wavelet/pkg/buildinfo"
"Wavelet/pkg/config"
"fmt"
"runtime"
"strings"
"Wavelet/pkg/buildinfo"
"Wavelet/pkg/config"
)
//nolint:unused // startup banner formatting utilities
+2 -3
View File
@@ -4,11 +4,10 @@
package cmd
import (
"strings"
"testing"
"Wavelet/pkg/buildinfo"
"Wavelet/pkg/config"
"strings"
"testing"
)
func TestFormatStartupBanner(t *testing.T) {
+4 -5
View File
@@ -4,6 +4,10 @@
package cmd
import (
"Wavelet/core"
"Wavelet/core/contracts"
"Wavelet/core/extpoints"
"Wavelet/pkg/config"
"context"
"fmt"
"sync/atomic"
@@ -12,11 +16,6 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"Wavelet/core"
"Wavelet/core/contracts"
"Wavelet/core/extpoints"
"Wavelet/pkg/config"
)
func TestRedisPluggability_Simulation(t *testing.T) {
+2 -3
View File
@@ -4,6 +4,8 @@
package cmd
import (
"Wavelet/plugins/domain/auth"
"Wavelet/plugins/infra/database"
"bufio"
"context"
"crypto/rand"
@@ -14,12 +16,9 @@ import (
"strings"
userdomain "Wavelet/plugins/domain/user"
"Wavelet/plugins/infra/database"
"github.com/spf13/cobra"
"gorm.io/gorm"
"Wavelet/plugins/domain/auth"
)
var (
+1 -1
View File
@@ -4,13 +4,13 @@
package cmd
import (
"Wavelet/pkg/testhelper"
"bytes"
"io"
"os"
"testing"
"time"
"Wavelet/pkg/testhelper"
userdomain "Wavelet/plugins/domain/user"
)
+4 -5
View File
@@ -4,16 +4,15 @@
package cmd
import (
"Wavelet/pkg/buildinfo"
"Wavelet/pkg/config"
"Wavelet/pkg/logger"
"Wavelet/pkg/trace"
"context"
"log"
"time"
"github.com/spf13/cobra"
"Wavelet/pkg/buildinfo"
"Wavelet/pkg/config"
"Wavelet/pkg/logger"
"Wavelet/pkg/trace"
)
const traceShutdownTimeout = 10 * time.Second
+1 -2
View File
@@ -4,11 +4,10 @@
package cmd
import (
"Wavelet/core"
"log"
"github.com/spf13/cobra"
"Wavelet/core"
)
var schedulerCmd = &cobra.Command{
+1 -2
View File
@@ -4,11 +4,10 @@
package cmd
import (
"Wavelet/core"
"log"
"github.com/spf13/cobra"
"Wavelet/core"
)
var workerCmd = &cobra.Command{
+2 -3
View File
@@ -4,6 +4,8 @@
package core_test
import (
"Wavelet/core"
"Wavelet/core/extpoints"
"context"
"errors"
"sync"
@@ -13,9 +15,6 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"Wavelet/core"
"Wavelet/core/extpoints"
)
// appMockDriver is a test driver tracking its start/stop lifecycle.
+2 -3
View File
@@ -4,13 +4,12 @@
package core
import (
"Wavelet/core/extpoints"
"context"
"errors"
"fmt"
"sync"
"time"
"Wavelet/core/extpoints"
)
// Context is the central micro-kernel service bus and runtime lifecycle container.
@@ -103,7 +102,7 @@ func (c *Context) GoContext() context.Context {
}
// Set stores an arbitrary key-value pair in this Context's local storage.
func (c *Context) Set(key any, val any) {
func (c *Context) Set(key, val any) {
c.mu.Lock()
defer c.mu.Unlock()
if c.values == nil {
+1 -2
View File
@@ -4,6 +4,7 @@
package core_test
import (
"Wavelet/core"
"context"
"errors"
"fmt"
@@ -14,8 +15,6 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"Wavelet/core"
)
// Sample services for testing
+1 -1
View File
@@ -68,6 +68,6 @@ type TaskService interface {
ValidatePayload(taskType string, payload []byte) ([]byte, error)
ReloadScheduler() error
AppendLog(ctx context.Context, format string, args ...any)
ListExecutions(ctx context.Context, taskType string, status string, page, pageSize int) ([]TaskExecutionDTO, int64, error)
ListExecutions(ctx context.Context, taskType, status string, page, pageSize int) ([]TaskExecutionDTO, int64, error)
GetExecution(ctx context.Context, id uint64) (*TaskExecutionDTO, error)
}
+4 -3
View File
@@ -14,8 +14,10 @@ import (
const maxHandlerParams = 2
var ctxInterfaceType = reflect.TypeFor[context.Context]()
var errInterfaceType = reflect.TypeFor[error]()
var (
ctxInterfaceType = reflect.TypeFor[context.Context]()
errInterfaceType = reflect.TypeFor[error]()
)
type eventListener struct {
id uint64
@@ -213,7 +215,6 @@ func (b *EventBus) Emit(ctx context.Context, topic string, payload any) error {
}
return resErr
}()
if err != nil {
errs = append(errs, err)
}
+1 -2
View File
@@ -4,6 +4,7 @@
package core_test
import (
"Wavelet/core"
"context"
"errors"
"fmt"
@@ -13,8 +14,6 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"Wavelet/core"
)
type UserRegisteredEvent struct {
+2 -3
View File
@@ -4,6 +4,8 @@
package extpoints_test
import (
"Wavelet/core"
"Wavelet/core/extpoints"
"context"
"testing"
"testing/fstest"
@@ -11,9 +13,6 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"Wavelet/core"
"Wavelet/core/extpoints"
)
func TestRouterExtension(t *testing.T) {
+1 -1
View File
@@ -21,7 +21,7 @@ type RouteDefinition struct {
type RouterExtension interface {
Use(middlewares ...any)
Group(prefix string, middlewares ...any) RouterExtension
Handle(method string, path string, handlers ...any) RouteDefinition
Handle(method, path string, handlers ...any) RouteDefinition
GET(path string, handlers ...any) RouteDefinition
POST(path string, handlers ...any) RouteDefinition
PUT(path string, handlers ...any) RouteDefinition
+4 -4
View File
@@ -28,8 +28,8 @@ func WithScheduleOption(key string, val any) ScheduleOption {
// ScheduleExtension defines the interface for registering and querying cron/scheduled tasks.
type ScheduleExtension interface {
Register(spec string, taskType string, payload any, opts ...ScheduleOption)
RegisterCron(spec string, taskType string, payload any, opts ...ScheduleOption)
Register(spec, taskType string, payload any, opts ...ScheduleOption)
RegisterCron(spec, taskType string, payload any, opts ...ScheduleOption)
Schedules() []ScheduleDefinition
Get(taskType string) (ScheduleDefinition, bool)
Unregister(taskType string) bool
@@ -50,7 +50,7 @@ func NewScheduleRegistry() *ScheduleRegistry {
}
// Register adds a schedule definition.
func (s *ScheduleRegistry) Register(spec string, taskType string, payload any, opts ...ScheduleOption) {
func (s *ScheduleRegistry) Register(spec, taskType string, payload any, opts ...ScheduleOption) {
s.mu.Lock()
defer s.mu.Unlock()
@@ -82,7 +82,7 @@ func (s *ScheduleRegistry) Register(spec string, taskType string, payload any, o
}
// RegisterCron is an alias for Register.
func (s *ScheduleRegistry) RegisterCron(spec string, taskType string, payload any, opts ...ScheduleOption) {
func (s *ScheduleRegistry) RegisterCron(spec, taskType string, payload any, opts ...ScheduleOption) {
s.Register(spec, taskType, payload, opts...)
}
+1 -2
View File
@@ -4,14 +4,13 @@
package core_test
import (
"Wavelet/core"
"context"
"reflect"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"Wavelet/core"
)
type MockServiceA interface {
+3 -3
View File
@@ -30,7 +30,7 @@ func (s *scopedRouterExtension) Group(prefix string, middlewares ...any) extpoin
return newScopedRouterExtension(s.ctx, subGroup)
}
func (s *scopedRouterExtension) Handle(method string, path string, handlers ...any) extpoints.RouteDefinition {
func (s *scopedRouterExtension) Handle(method, path string, handlers ...any) extpoints.RouteDefinition {
rd := s.underlying.Handle(method, path, handlers...)
routeID := rd.ID
s.ctx.OnDispose(func() error {
@@ -141,7 +141,7 @@ func newScopedScheduleExtension(ctx *Context, underlying extpoints.ScheduleExten
}
}
func (s *scopedScheduleExtension) Register(spec string, taskType string, payload any, opts ...extpoints.ScheduleOption) {
func (s *scopedScheduleExtension) Register(spec, taskType string, payload any, opts ...extpoints.ScheduleOption) {
s.underlying.Register(spec, taskType, payload, opts...)
s.ctx.OnDispose(func() error {
s.underlying.Unregister(taskType)
@@ -149,7 +149,7 @@ func (s *scopedScheduleExtension) Register(spec string, taskType string, payload
})
}
func (s *scopedScheduleExtension) RegisterCron(spec string, taskType string, payload any, opts ...extpoints.ScheduleOption) {
func (s *scopedScheduleExtension) RegisterCron(spec, taskType string, payload any, opts ...extpoints.ScheduleOption) {
s.Register(spec, taskType, payload, opts...)
}
+1 -2
View File
@@ -4,11 +4,10 @@
package core
import (
"Wavelet/core/extpoints"
"context"
"errors"
"reflect"
"Wavelet/core/extpoints"
)
// Standard sentinel errors returned by core operations.
@@ -6,12 +6,11 @@
package custom_example
import (
"Wavelet/core"
"Wavelet/core/contracts"
"net/http"
"github.com/gin-gonic/gin"
"Wavelet/core"
"Wavelet/core/contracts"
)
// Plugin implements core.Plugin for the custom_example downstream plugin.
+1 -1
View File
@@ -242,7 +242,7 @@ func (w *Writer[T]) run() {
}
}
func (w *Writer[T]) shouldFlushOnInterval(batchLen int, batchStartedAt time.Time, now time.Time) bool {
func (w *Writer[T]) shouldFlushOnInterval(batchLen int, batchStartedAt, now time.Time) bool {
if batchLen == 0 {
return false
}
+2 -2
View File
@@ -26,7 +26,7 @@ const (
headerSize = 8 // 8 bytes metadata prefix for expiration UnixNano timestamp
defaultMaxSizeMB = 100
defaultTTLMinutes = 60
cacheDirPerm = 0750
cacheDirPerm = 0o750
// DefaultExpiration applies the cache-wide default TTL.
DefaultExpiration time.Duration = 0
@@ -284,7 +284,7 @@ func (c *Cache) Status() Status {
}
// UpdatePolicy dynamically updates policies.
func (c *Cache) UpdatePolicy(maxSizeMB int64, ttlMinutes int64, lruEnabled bool) {
func (c *Cache) UpdatePolicy(maxSizeMB, ttlMinutes int64, lruEnabled bool) {
c.mu.Lock()
defer c.mu.Unlock()
+5 -5
View File
@@ -31,7 +31,7 @@ type CacheItem struct {
// Loader is an interface that the cache client must implement to handle database retrieval.
type Loader interface {
LoadAll(ctx context.Context, configType string) ([]CacheItem, error)
LoadOne(ctx context.Context, configType string, key string) (CacheItem, error)
LoadOne(ctx context.Context, configType, key string) (CacheItem, error)
}
type cacheEntry struct {
@@ -59,7 +59,7 @@ func getWriteLock(configType string) *sync.Mutex {
// Get retrieves a cache item from the local cache store, checking for expiration.
// Reads are completely lock-free because maps stored in Otter are immutable.
func Get(configType string, key string) (CacheItem, bool) {
func Get(configType, key string) (CacheItem, bool) {
m, ok := managerCache.GetIfPresent(configType)
if !ok {
return CacheItem{}, false
@@ -80,7 +80,7 @@ func Get(configType string, key string) (CacheItem, bool) {
return entry.item, true
}
func deleteKeyIfExpired(configType string, key string, expireAt time.Time) {
func deleteKeyIfExpired(configType, key string, expireAt time.Time) {
lock := getWriteLock(configType)
lock.Lock()
defer lock.Unlock()
@@ -138,7 +138,7 @@ func Set(item CacheItem) {
// Delete removes a single item from the local cache store.
// Writes are protected by a fine-grained lock per configType.
func Delete(configType string, key string) {
func Delete(configType, key string) {
lock := getWriteLock(configType)
lock.Lock()
defer lock.Unlock()
@@ -196,7 +196,7 @@ func GetTypeItems(configType string) []CacheItem {
}
// Refresh reloads configuration cache from database via the Loader.
func Refresh(ctx context.Context, configType string, key string, loader Loader) error {
func Refresh(ctx context.Context, configType, key string, loader Loader) error {
if configType == "" {
return errors.New("type is required")
}
+1 -2
View File
@@ -118,8 +118,7 @@ type logConfig struct {
}
// schedulerConfig 定时任务配置
type schedulerConfig struct {
}
type schedulerConfig struct{}
// workerConfig 工作配置
type workerConfig struct {
+1 -1
View File
@@ -52,7 +52,7 @@ func TestNewTransportUsesConfiguredDirectDialer(t *testing.T) {
dialer := &net.Dialer{}
transport := NewTransport(TransportOptions{
Proxy: nil,
DialContext: func(ctx context.Context, network string, address string) (net.Conn, error) {
DialContext: func(ctx context.Context, network, address string) (net.Conn, error) {
dialedAddress = address
return dialer.DialContext(ctx, network, server.Listener.Addr().String())
},
+1 -2
View File
@@ -5,12 +5,11 @@
package idgen
import (
"Wavelet/pkg/config"
"fmt"
"log"
"github.com/bwmarrin/snowflake"
"Wavelet/pkg/config"
)
// 2025-12-01 00:00:00 UTC 的毫秒时间戳
+1 -1
View File
@@ -99,7 +99,7 @@ func (r *LogRingBuffer) appendLine(line string) {
// cursor=0 表示查询最新日志,cursor>0 表示查询 index < cursor 的更早日志
// limit 为返回条数上限
// 返回日志条目(按 index 升序)和是否有更早的日志
func (r *LogRingBuffer) Query(cursor int, limit int) ([]LogEntry, bool) {
func (r *LogRingBuffer) Query(cursor, limit int) ([]LogEntry, bool) {
r.mu.RLock()
defer r.mu.RUnlock()
+1 -1
View File
@@ -17,7 +17,7 @@ import (
)
// logDirPerm 日志目录权限
const logDirPerm = 0750
const logDirPerm = 0o750
func getLogWriterForConfig(cfg Config) (zapcore.WriteSyncer, error) {
if cfg.Output == "file" {
+4 -4
View File
@@ -38,12 +38,12 @@ func sanitizeHeaderValue(v string) string {
}
// SendMail sends an HTML email using the provided config and message details
func SendMail(ctx context.Context, cfg Config, to string, subject, body string) error {
func SendMail(ctx context.Context, cfg Config, to, subject, body string) error {
return SendMailHTML(ctx, cfg, to, subject, body)
}
// SendMailHTML sends an HTML format email
func SendMailHTML(ctx context.Context, cfg Config, to string, subject, body string) error {
func SendMailHTML(ctx context.Context, cfg Config, to, subject, body string) error {
addr := net.JoinHostPort(cfg.Host, strconv.Itoa(cfg.Port))
// Header & MIME settings for HTML email
@@ -124,9 +124,9 @@ func sendMailViaSSL(ctx context.Context, addr string, auth smtp.Auth, cfg Config
}
// SendMailWithLog sends a test email and records a detailed SMTP connection log
func SendMailWithLog(ctx context.Context, cfg Config, to string, subject, body string) (string, error) {
func SendMailWithLog(ctx context.Context, cfg Config, to, subject, body string) (string, error) {
var logBuf bytes.Buffer
logLine := func(dir string, format string, args ...interface{}) {
logLine := func(dir, format string, args ...interface{}) {
fmt.Fprintf(&logBuf, "[%s] %s\n", dir, fmt.Sprintf(format, args...))
}
+2 -2
View File
@@ -4,9 +4,9 @@
package testhelper
import (
"github.com/gin-gonic/gin"
"Wavelet/pkg/response"
"github.com/gin-gonic/gin"
)
// NewTestGinEngine 创建带 ErrorHandlerMiddleware 的 Gin 引擎,与生产环境错误响应行为一致。
+4 -2
View File
@@ -12,8 +12,10 @@ import (
)
// Tracer 全局 OpenTelemetry Tracer 实例
var Tracer trace.Tracer
var shutdownFuncs []func(context.Context) error
var (
Tracer trace.Tracer
shutdownFuncs []func(context.Context) error
)
func init() {
// 初始化 Propagator
+3 -3
View File
@@ -33,7 +33,7 @@ const (
// signKey: 64 字符 hex 编码的密钥(对应 32 字节,用于 AES-256)
// plaintext: 要加密的明文字符串
// return: base64 编码的密文
func Encrypt(signKey string, plaintext string) (string, error) {
func Encrypt(signKey, plaintext string) (string, error) {
return encryptBytes(signKey, []byte(plaintext))
}
@@ -41,7 +41,7 @@ func Encrypt(signKey string, plaintext string) (string, error) {
// signKey: 64 字符 hex 编码的密钥(对应 32 字节,用于 AES-256)
// ciphertext: base64 编码的密文
// return: 解密后的明文字符串
func Decrypt(signKey string, ciphertext string) (string, error) {
func Decrypt(signKey, ciphertext string) (string, error) {
plaintext, err := decryptBytes(signKey, ciphertext)
if err != nil {
return "", err
@@ -86,7 +86,7 @@ func encryptBytes(signKey string, plaintext []byte) (string, error) {
}
// decryptBytes 解密函数,处理字节数据
func decryptBytes(signKey string, ciphertext string) ([]byte, error) {
func decryptBytes(signKey, ciphertext string) ([]byte, error) {
// 将 hex 编码的密钥转换为字节
key, err := hex.DecodeString(signKey)
if err != nil {
+1 -2
View File
@@ -4,14 +4,13 @@
package util
import (
"Wavelet/pkg/httppool"
"context"
"fmt"
"io"
"net/http"
"net/url"
"time"
"Wavelet/pkg/httppool"
)
// IsLocalhost 检查 URL 是否为 localhost
+4 -2
View File
@@ -18,8 +18,10 @@ func HashPassword(password string) (string, error) {
return string(hash), nil
}
var dummyPasswordHashOnce sync.Once
var dummyPasswordHash string
var (
dummyPasswordHashOnce sync.Once
dummyPasswordHash string
)
func dummyHash() string {
dummyPasswordHashOnce.Do(func() {
+1 -2
View File
@@ -4,12 +4,11 @@
package admin
import (
"Wavelet/core/contracts"
"context"
"sync"
"gorm.io/gorm"
"Wavelet/core/contracts"
)
var (
@@ -4,13 +4,12 @@
package admin
import (
"Wavelet/core/contracts"
"Wavelet/pkg/response"
"net/http"
"strconv"
"github.com/gin-gonic/gin"
"Wavelet/core/contracts"
"Wavelet/pkg/response"
)
// ListAuthSources lists all configured authentication sources.
@@ -4,6 +4,7 @@
package admin
import (
"Wavelet/pkg/response"
"context"
"net/http"
"strconv"
@@ -11,7 +12,6 @@ import (
"github.com/gin-gonic/gin"
pkgcache "Wavelet/pkg/cache/disk"
"Wavelet/pkg/response"
)
type updateCacheConfigRequest struct {
@@ -4,6 +4,9 @@
package admin
import (
"Wavelet/core/contracts"
"Wavelet/pkg/logger"
"Wavelet/pkg/response"
"context"
"encoding/json"
"errors"
@@ -15,10 +18,7 @@ import (
"github.com/gin-gonic/gin"
"gorm.io/gorm"
"Wavelet/core/contracts"
"Wavelet/pkg/logger"
mail "Wavelet/pkg/mail"
"Wavelet/pkg/response"
)
const maskedConfigValue = "******"
@@ -465,7 +465,7 @@ func maskSensitiveConfig(key, value string) string {
// validateAndMergeStorageConfig parses, merges unmasked secrets, validates parameter values,
// and tests connectivity of the new storage configuration.
func validateAndMergeStorageConfig(ctx context.Context, value string, currentConfig string) (string, error) {
func validateAndMergeStorageConfig(ctx context.Context, value, currentConfig string) (string, error) {
var currentCfg contracts.StorageConfigDTO
if err := json.Unmarshal([]byte(currentConfig), &currentCfg); err != nil {
return "", fmt.Errorf("解析当前存储配置失败: %w", err)
+2 -3
View File
@@ -4,6 +4,8 @@
package admin
import (
"Wavelet/pkg/config"
"Wavelet/pkg/response"
"context"
"database/sql"
"fmt"
@@ -17,9 +19,6 @@ import (
"github.com/gin-gonic/gin"
"gorm.io/gorm"
"Wavelet/pkg/config"
"Wavelet/pkg/response"
)
const (
@@ -4,6 +4,11 @@
package admin
import (
"Wavelet/core/contracts"
"Wavelet/pkg/config"
"Wavelet/pkg/logger"
"Wavelet/pkg/response"
"Wavelet/pkg/util"
"context"
"encoding/json"
"errors"
@@ -16,12 +21,6 @@ import (
"github.com/gin-gonic/gin"
"github.com/gorilla/websocket"
"Wavelet/core/contracts"
"Wavelet/pkg/config"
"Wavelet/pkg/logger"
"Wavelet/pkg/response"
"Wavelet/pkg/util"
)
const (
@@ -4,6 +4,9 @@
package admin
import (
"Wavelet/pkg/config"
"Wavelet/pkg/logger"
"Wavelet/pkg/response"
"context"
"errors"
"fmt"
@@ -14,10 +17,6 @@ import (
"github.com/gin-gonic/gin"
"gorm.io/gorm"
"Wavelet/pkg/config"
"Wavelet/pkg/logger"
"Wavelet/pkg/response"
)
var startTime = time.Now()
@@ -4,6 +4,9 @@
package admin
import (
"Wavelet/core/contracts"
"Wavelet/pkg/logger"
"Wavelet/pkg/response"
"fmt"
"net/http"
"strconv"
@@ -12,10 +15,6 @@ import (
"github.com/gin-gonic/gin"
"github.com/robfig/cron/v3"
"Wavelet/core/contracts"
"Wavelet/pkg/logger"
"Wavelet/pkg/response"
)
// ListTaskTypes 获取支持的任务类型列表
@@ -4,14 +4,13 @@
package admin
import (
"Wavelet/pkg/response"
"context"
"errors"
"net/http"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
"Wavelet/pkg/response"
)
// CreateTemplateRequest 创建模板请求
@@ -4,6 +4,10 @@
package admin
import (
"Wavelet/pkg/buildinfo"
"Wavelet/pkg/logger"
"Wavelet/pkg/response"
"Wavelet/pkg/util"
"archive/tar"
"archive/zip"
"compress/gzip"
@@ -23,11 +27,6 @@ import (
"github.com/gin-gonic/gin"
"golang.org/x/mod/semver"
"Wavelet/pkg/buildinfo"
"Wavelet/pkg/logger"
"Wavelet/pkg/response"
"Wavelet/pkg/util"
)
const (
@@ -391,7 +390,7 @@ func matchBinaryName(name string, candidates []string) bool {
return false
}
func getCandidateBinaryNames(executable string, repository string) []string {
func getCandidateBinaryNames(executable, repository string) []string {
execName := filepath.Base(executable)
names := []string{execName}
@@ -435,7 +434,7 @@ func isLikelyBinary(name string, isDir bool, mode os.FileMode) bool {
return filepath.Ext(base) == ".exe"
}
return (mode.Perm()&0111 != 0) || (filepath.Ext(base) == "")
return (mode.Perm()&0o111 != 0) || (filepath.Ext(base) == "")
}
func findBinaryInTarGz(archivePath string, candidates []string) (string, error) {
@@ -4,6 +4,10 @@
package admin
import (
"Wavelet/core/contracts"
"Wavelet/pkg/logger"
"Wavelet/pkg/response"
"Wavelet/pkg/util"
"errors"
"net/http"
"strconv"
@@ -11,11 +15,6 @@ import (
"github.com/gin-gonic/gin"
"gorm.io/gorm"
"Wavelet/core/contracts"
"Wavelet/pkg/logger"
"Wavelet/pkg/response"
"Wavelet/pkg/util"
)
// listUsersRequest 用户列表查询请求
@@ -393,7 +392,6 @@ func UpdateUser(c *gin.Context) {
IsAdmin: req.IsAdmin,
Password: req.Password,
})
if err != nil {
if abortUserLogicError(c, err, userNotFound, []string{cannotRevokeSelfAdmin}, []string{emailRequired, emailExists, passwordTooShort}) {
return
+2 -2
View File
@@ -4,13 +4,13 @@
package admin
import (
"github.com/gin-gonic/gin"
"Wavelet/core/contracts"
"Wavelet/pkg/logger"
"Wavelet/pkg/response"
"Wavelet/pkg/trace"
"Wavelet/pkg/util"
"github.com/gin-gonic/gin"
)
// LoginAdminRequired 返回管理员权限校验中间件
+3 -4
View File
@@ -5,16 +5,15 @@
package admin
import (
"Wavelet/core"
"Wavelet/core/contracts"
"Wavelet/core/extpoints"
"context"
"embed"
"reflect"
"github.com/gin-gonic/gin"
"github.com/hibiken/asynq"
"Wavelet/core"
"Wavelet/core/contracts"
"Wavelet/core/extpoints"
)
//go:embed migrations/*/*.sql
+2 -3
View File
@@ -4,14 +4,13 @@
package admin_test
import (
"Wavelet/core"
"Wavelet/plugins/domain/admin"
"context"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"Wavelet/core"
"Wavelet/plugins/domain/admin"
)
func TestAdminPluginUnit(t *testing.T) {
+5 -6
View File
@@ -4,6 +4,9 @@
package admin
import (
"Wavelet/pkg/cache/ram"
"Wavelet/pkg/idgen"
"Wavelet/pkg/util"
"context"
"encoding/json"
"errors"
@@ -14,10 +17,6 @@ import (
"github.com/shopspring/decimal"
"gorm.io/gorm"
"Wavelet/pkg/cache/ram"
"Wavelet/pkg/idgen"
"Wavelet/pkg/util"
)
const (
@@ -62,7 +61,7 @@ func PreheatSystemConfigByKey(ctx context.Context, key string) (SystemConfig, er
}
// GetSystemConfigByGroup queries a configuration by Type and Key.
func GetSystemConfigByGroup(ctx context.Context, configType string, key string) (SystemConfig, error) {
func GetSystemConfigByGroup(ctx context.Context, configType, key string) (SystemConfig, error) {
ensureSystemConfigCacheListener()
if item, ok := ram.Get(configType, key); ok {
@@ -479,7 +478,7 @@ func GetLatestTaskExecutionByTaskType(ctx context.Context, taskType string) (*Ta
}
// AppendTaskExecutionLog 将日志追加到缓冲,任务完成后再持久化到数据库。
func AppendTaskExecutionLog(ctx context.Context, taskID string, logLine string) error {
func AppendTaskExecutionLog(ctx context.Context, taskID, logLine string) error {
cacheSvc := GetCache(ctx)
if cacheSvc == nil {
return errors.New("cache service is not initialized")
+1 -2
View File
@@ -6,13 +6,12 @@
package admin
import (
"Wavelet/pkg/logger"
"context"
"fmt"
"os"
"path/filepath"
"syscall"
"Wavelet/pkg/logger"
)
const installedBinaryMode = 0o755
@@ -4,14 +4,13 @@
package admin
import (
"Wavelet/pkg/cache/ram"
"context"
"encoding/json"
"errors"
"time"
"gorm.io/gorm"
"Wavelet/pkg/cache/ram"
)
const (
@@ -57,7 +56,7 @@ func (ConfigLoader) LoadAll(ctx context.Context, configType string) ([]ram.Cache
}
// LoadOne loads a single system config from database as CacheItem.
func (ConfigLoader) LoadOne(ctx context.Context, configType string, key string) (ram.CacheItem, error) {
func (ConfigLoader) LoadOne(ctx context.Context, configType, key string) (ram.CacheItem, error) {
cfg, err := GetSystemConfigByKey(ctx, key)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
+2 -3
View File
@@ -4,13 +4,12 @@
package auth
import (
"Wavelet/core/contracts"
"Wavelet/pkg/logger"
"context"
"encoding/json"
"github.com/gin-gonic/gin"
"Wavelet/core/contracts"
"Wavelet/pkg/logger"
)
// LogForAudit 将登录鉴权审计日志写入 Logger
@@ -4,14 +4,13 @@
package auth
import (
"Wavelet/core/contracts"
"context"
"errors"
"fmt"
"strconv"
"strings"
"Wavelet/core/contracts"
"github.com/coreos/go-oidc/v3/oidc"
"golang.org/x/oauth2"
)
@@ -128,7 +127,7 @@ func containsScope(scopes []string, scope string) bool {
return false
}
func buildOAuthUserInfo(ctx context.Context, source *AuthSource, code string, nonce string, redirectURL string) (*contracts.OAuthUserInfoDTO, error) {
func buildOAuthUserInfo(ctx context.Context, source *AuthSource, code, nonce, redirectURL string) (*contracts.OAuthUserInfoDTO, error) {
authConfig, verifier, err := buildOAuthConfig(ctx, source, redirectURL)
if err != nil {
return nil, err
+2 -3
View File
@@ -4,12 +4,11 @@
package auth
import (
"Wavelet/core/contracts"
"Wavelet/pkg/cache/ram"
"context"
"fmt"
"time"
"Wavelet/core/contracts"
"Wavelet/pkg/cache/ram"
)
const (
+3 -4
View File
@@ -4,14 +4,13 @@
package auth_test
import (
"Wavelet/core"
"Wavelet/core/contracts"
"Wavelet/plugins/domain/auth"
"context"
"encoding/json"
"testing"
"time"
"Wavelet/core"
"Wavelet/core/contracts"
"Wavelet/plugins/domain/auth"
)
type mockCacheService struct {
+5 -7
View File
@@ -4,6 +4,11 @@
package auth
import (
"Wavelet/core/contracts"
"Wavelet/pkg/idgen"
"Wavelet/pkg/logger"
"Wavelet/pkg/response"
"Wavelet/pkg/util"
"context"
"errors"
"fmt"
@@ -12,18 +17,11 @@ import (
"strings"
"time"
"Wavelet/core/contracts"
"github.com/coreos/go-oidc/v3/oidc"
"github.com/gin-contrib/sessions"
"github.com/gin-gonic/gin"
"github.com/google/uuid"
"gorm.io/gorm"
"Wavelet/pkg/idgen"
"Wavelet/pkg/logger"
"Wavelet/pkg/response"
"Wavelet/pkg/util"
)
// GetLoginSources 获取可用登录源列表
+4 -5
View File
@@ -4,17 +4,16 @@
package auth
import (
"Wavelet/core/contracts"
"Wavelet/pkg/response"
"Wavelet/pkg/trace"
"Wavelet/pkg/util"
"context"
"crypto/sha256"
"encoding/hex"
"errors"
"github.com/gin-gonic/gin"
"Wavelet/core/contracts"
"Wavelet/pkg/response"
"Wavelet/pkg/trace"
"Wavelet/pkg/util"
)
func hashToken(token string) string {
+1 -2
View File
@@ -4,14 +4,13 @@
package auth
import (
"Wavelet/core/contracts"
"encoding/json"
"errors"
"regexp"
"strconv"
"strings"
"time"
"Wavelet/core/contracts"
)
var authSourceNamePattern = regexp.MustCompile(`^[A-Za-z0-9][A-Za-z0-9_-]{0,79}$`)
+3 -4
View File
@@ -5,13 +5,12 @@
package auth
import (
"context"
"embed"
"reflect"
"Wavelet/core"
"Wavelet/core/contracts"
"Wavelet/core/extpoints"
"context"
"embed"
"reflect"
)
//go:embed migrations/*/*.sql
+4 -4
View File
@@ -4,6 +4,9 @@
package auth_test
import (
"Wavelet/core"
"Wavelet/core/contracts"
"Wavelet/plugins/domain/auth"
"context"
"crypto/sha256"
"encoding/hex"
@@ -15,10 +18,6 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"gorm.io/gorm"
"Wavelet/core"
"Wavelet/core/contracts"
"Wavelet/plugins/domain/auth"
)
type mockDBService struct {
@@ -84,6 +83,7 @@ func (m *mockProvider) Name() string { return "custom" }
func (m *mockProvider) GetAuthURL(state string) string {
return "https://custom.com/auth?state=" + state
}
func (m *mockProvider) ExchangeCode(ctx context.Context, code string) (*contracts.OAuthUserInfoDTO, error) {
return &contracts.OAuthUserInfoDTO{
ID: 555,
+3 -4
View File
@@ -4,13 +4,12 @@
package auth
import (
"Wavelet/core"
"Wavelet/core/contracts"
"context"
"sync"
"gorm.io/gorm"
"Wavelet/core"
"Wavelet/core/contracts"
)
var (
@@ -120,6 +119,6 @@ func ListExternalAccountsByUserID(ctx context.Context, userID uint64) ([]Externa
}
// UnbindExternalAccount 解绑外部账号
func UnbindExternalAccount(ctx context.Context, id uint64, userID uint64) error {
func UnbindExternalAccount(ctx context.Context, id, userID uint64) error {
return getDB(ctx).Where("id = ? AND user_id = ?", id, userID).Delete(&ExternalAccount{}).Error
}
+2 -3
View File
@@ -4,14 +4,13 @@
package auth
import (
"Wavelet/core/contracts"
"Wavelet/pkg/util"
"context"
"errors"
"sync"
"github.com/gin-gonic/gin"
"Wavelet/core/contracts"
"Wavelet/pkg/util"
)
type authServiceImpl struct{}
+2 -3
View File
@@ -4,6 +4,8 @@
package auth
import (
"Wavelet/core/contracts"
"Wavelet/pkg/config"
"context"
"crypto/sha256"
"encoding/hex"
@@ -15,9 +17,6 @@ import (
"github.com/gin-gonic/gin"
"github.com/google/uuid"
gsessions "github.com/gorilla/sessions"
"Wavelet/core/contracts"
"Wavelet/pkg/config"
)
// GetSessionOptions 根据配置构建 Session 选项
+3 -4
View File
@@ -4,13 +4,12 @@
package cap
import (
"net/http"
"github.com/gin-gonic/gin"
"Wavelet/pkg/logger"
"Wavelet/pkg/response"
"Wavelet/plugins/domain/cap/pow"
"net/http"
"github.com/gin-gonic/gin"
)
// ChallengeResponse is a local type alias for the pow.ChallengeResponse struct
+3 -4
View File
@@ -5,6 +5,8 @@
package cap
import (
"Wavelet/pkg/config"
"Wavelet/plugins/domain/cap/pow"
"context"
"crypto/sha256"
"encoding/hex"
@@ -12,9 +14,6 @@ import (
"strings"
"sync"
"time"
"Wavelet/pkg/config"
"Wavelet/plugins/domain/cap/pow"
)
const (
@@ -116,7 +115,7 @@ func (m *Manager) Redeem(ctx context.Context, token string, solutions []int, sco
}
// VerifyToken validates and consumes the redeem token (single-use).
func (m *Manager) VerifyToken(ctx context.Context, token string, expectedScope string) (bool, error) {
func (m *Manager) VerifyToken(ctx context.Context, token, expectedScope string) (bool, error) {
if token == "" {
return false, nil
}
+2 -2
View File
@@ -4,9 +4,9 @@
package cap
import (
"github.com/gin-gonic/gin"
"Wavelet/pkg/response"
"github.com/gin-gonic/gin"
)
// VerifyMiddleware returns a Gin middleware that checks and consumes the X-Cap-Token header.
+1 -2
View File
@@ -5,11 +5,10 @@
package cap
import (
"reflect"
"Wavelet/core"
"Wavelet/core/contracts"
"Wavelet/core/extpoints"
"reflect"
)
// Plugin implements core.Plugin to provide CAPTCHA generation, validation, and route protection.
+1 -1
View File
@@ -88,7 +88,7 @@ func RandomHex(byteLen int) string {
return hex.EncodeToString(bytes)
}
func jwtSign(payload []byte, secret []byte) string {
func jwtSign(payload, secret []byte) string {
body := b64urlEncode(payload)
sigInput := jwtHeaderB64 + "." + body
+6 -6
View File
@@ -14,12 +14,12 @@ import (
// Store defines the storage interface for challenge nonces and verification tokens
type Store interface {
Get(ctx context.Context, key string) (string, bool, error)
Set(ctx context.Context, key string, val string, ttl time.Duration) error
Set(ctx context.Context, key, val string, ttl time.Duration) error
Delete(ctx context.Context, key string) error
// SetNX atomically sets key=val with the given TTL only when the key does not
// exist yet. It returns true when the key was actually written (i.e. this
// caller "won" the race), and false when the key already existed.
SetNX(ctx context.Context, key string, val string, ttl time.Duration) (bool, error)
SetNX(ctx context.Context, key, val string, ttl time.Duration) (bool, error)
// GetAndDelete atomically retrieves the value of key and removes it in a
// single operation. Returns ("", false, nil) when the key does not exist.
GetAndDelete(ctx context.Context, key string) (string, bool, error)
@@ -68,7 +68,7 @@ func (s *MemoryStore) getLocked(key string) (string, bool, error) {
}
// Set 向 MemoryStore 写入指定 key 的值
func (s *MemoryStore) Set(_ context.Context, key string, val string, ttl time.Duration) error {
func (s *MemoryStore) Set(_ context.Context, key, val string, ttl time.Duration) error {
s.mu.Lock()
defer s.mu.Unlock()
s.items[key] = memoryItem{
@@ -88,7 +88,7 @@ func (s *MemoryStore) Delete(_ context.Context, key string) error {
// SetNX atomically sets key only when it is absent (or expired).
// Returns true if the key was written by this call.
func (s *MemoryStore) SetNX(_ context.Context, key string, val string, ttl time.Duration) (bool, error) {
func (s *MemoryStore) SetNX(_ context.Context, key, val string, ttl time.Duration) (bool, error) {
s.mu.Lock()
defer s.mu.Unlock()
@@ -159,7 +159,7 @@ func (s *RedisStore) Get(ctx context.Context, key string) (string, bool, error)
}
// Set 向 RedisStore 写入指定 key 的值
func (s *RedisStore) Set(ctx context.Context, key string, val string, ttl time.Duration) error {
func (s *RedisStore) Set(ctx context.Context, key, val string, ttl time.Duration) error {
return s.client.Set(ctx, key, val, ttl).Err()
}
@@ -169,7 +169,7 @@ func (s *RedisStore) Delete(ctx context.Context, key string) error {
}
// SetNX wraps Redis SET NX – returns true only when the key was newly created.
func (s *RedisStore) SetNX(ctx context.Context, key string, val string, ttl time.Duration) (bool, error) {
func (s *RedisStore) SetNX(ctx context.Context, key, val string, ttl time.Duration) (bool, error) {
return s.client.SetNX(ctx, key, val, ttl).Result()
}
@@ -4,6 +4,8 @@
package cap
import (
"Wavelet/core"
"Wavelet/core/contracts"
"context"
"errors"
"strconv"
@@ -13,9 +15,6 @@ import (
"golang.org/x/sync/singleflight"
"gorm.io/gorm"
"Wavelet/core"
"Wavelet/core/contracts"
)
var (
+10 -10
View File
@@ -4,6 +4,16 @@
package domain_test
import (
"Wavelet/core"
"Wavelet/core/contracts"
"Wavelet/plugins/domain/admin"
"Wavelet/plugins/domain/auth"
"Wavelet/plugins/domain/message_gateway"
"Wavelet/plugins/domain/risk_control"
"Wavelet/plugins/domain/user"
"Wavelet/plugins/infra/cache"
"Wavelet/plugins/infra/logger"
"Wavelet/plugins/infra/storage"
"context"
"io/fs"
"path/filepath"
@@ -16,17 +26,7 @@ import (
"github.com/stretchr/testify/require"
"gorm.io/gorm"
"Wavelet/core"
"Wavelet/core/contracts"
"Wavelet/plugins/domain/admin"
"Wavelet/plugins/domain/auth"
"Wavelet/plugins/domain/message_gateway"
"Wavelet/plugins/domain/risk_control"
"Wavelet/plugins/domain/user"
"Wavelet/plugins/infra/cache"
db "Wavelet/plugins/infra/database"
"Wavelet/plugins/infra/logger"
"Wavelet/plugins/infra/storage"
)
func setupTestDB(t *testing.T) *gorm.DB {
@@ -4,12 +4,11 @@
package message_gateway
import (
"Wavelet/pkg/response"
"net/http"
"strconv"
"github.com/gin-gonic/gin"
"Wavelet/pkg/response"
)
// ListAdminChannelDefinitions returns form schemas for supported channel types.
@@ -5,17 +5,15 @@
package qq
import (
"Wavelet/pkg/logger"
"Wavelet/pkg/util"
"Wavelet/plugins/domain/message_gateway"
"context"
"fmt"
"strings"
"sync"
"time"
"Wavelet/pkg/util"
"Wavelet/pkg/logger"
"Wavelet/plugins/domain/message_gateway"
"github.com/tencent-connect/botgo"
"github.com/tencent-connect/botgo/dto"
"github.com/tencent-connect/botgo/event"
@@ -4,10 +4,9 @@
package qq
import (
"Wavelet/plugins/domain/message_gateway"
"context"
"testing"
"Wavelet/plugins/domain/message_gateway"
)
func TestHandleEvent_DropsNonC2C(t *testing.T) {
@@ -5,6 +5,8 @@
package telegram
import (
"Wavelet/pkg/util"
"Wavelet/plugins/domain/message_gateway"
"context"
"fmt"
"os"
@@ -13,9 +15,6 @@ import (
"strings"
tele "gopkg.in/telebot.v4"
"Wavelet/pkg/util"
"Wavelet/plugins/domain/message_gateway"
)
// Adapter is a Telegram private-chat channel.
@@ -4,12 +4,11 @@
package telegram
import (
"Wavelet/plugins/domain/message_gateway"
"context"
"testing"
tele "gopkg.in/telebot.v4"
"Wavelet/plugins/domain/message_gateway"
)
func TestHandleUpdate_DropsGroups(t *testing.T) {
@@ -4,10 +4,9 @@
package message_gateway
import (
"Wavelet/core/contracts"
"context"
"time"
"Wavelet/core/contracts"
)
// AdminLogin is the metadata definition for the admin login event.
@@ -4,13 +4,12 @@
package message_gateway
import (
"Wavelet/core"
"Wavelet/core/contracts"
"context"
"sync"
"gorm.io/gorm"
"Wavelet/core"
"Wavelet/core/contracts"
)
var (
@@ -4,15 +4,14 @@
package message_gateway
import (
"Wavelet/core/contracts"
"Wavelet/pkg/response"
"Wavelet/pkg/util"
"errors"
"net/http"
"strconv"
"github.com/gin-gonic/gin"
"Wavelet/core/contracts"
"Wavelet/pkg/response"
"Wavelet/pkg/util"
)
func currentUser(c *gin.Context) (*contracts.UserDTO, bool) {
@@ -4,14 +4,13 @@
package message_gateway_test
import (
"Wavelet/pkg/testhelper"
"Wavelet/plugins/domain/message_gateway"
"context"
"testing"
"time"
"gorm.io/gorm"
"Wavelet/pkg/testhelper"
"Wavelet/plugins/domain/message_gateway"
)
type mockDBService struct {
@@ -5,16 +5,15 @@
package message_gateway
import (
"Wavelet/core"
"Wavelet/core/contracts"
"Wavelet/core/extpoints"
"Wavelet/pkg/util"
"context"
"embed"
"reflect"
"github.com/gin-gonic/gin"
"Wavelet/core"
"Wavelet/core/contracts"
"Wavelet/core/extpoints"
"Wavelet/pkg/util"
)
//go:embed migrations/*/*.sql
@@ -4,15 +4,14 @@
package message_gateway_test
import (
"Wavelet/core"
"Wavelet/plugins/domain/message_gateway"
"context"
"io/fs"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"Wavelet/core"
"Wavelet/plugins/domain/message_gateway"
)
func TestMessageGatewayPluginUnit(t *testing.T) {
@@ -4,6 +4,7 @@
package push
import (
"Wavelet/pkg/httppool"
"bytes"
"context"
"encoding/json"
@@ -12,8 +13,6 @@ import (
"io"
"net/http"
"strings"
"Wavelet/pkg/httppool"
)
func init() {
@@ -4,14 +4,13 @@
package push
import (
"Wavelet/pkg/util"
"context"
"errors"
"fmt"
"net"
"net/smtp"
"strings"
"Wavelet/pkg/util"
)
func init() {
@@ -4,6 +4,7 @@
package push
import (
"Wavelet/pkg/httppool"
"bytes"
"context"
"crypto/hmac"
@@ -16,8 +17,6 @@ import (
"strconv"
"strings"
"time"
"Wavelet/pkg/httppool"
)
func init() {
@@ -4,6 +4,7 @@
package push
import (
"Wavelet/pkg/httppool"
"bytes"
"context"
"encoding/json"
@@ -11,8 +12,6 @@ import (
"fmt"
"net/http"
"strings"
"Wavelet/pkg/httppool"
)
func init() {
@@ -4,6 +4,7 @@
package message_gateway
import (
"Wavelet/pkg/response"
"encoding/json"
"errors"
"net/http"
@@ -14,7 +15,6 @@ import (
"github.com/gin-gonic/gin"
"gorm.io/gorm"
"Wavelet/pkg/response"
pkgpush "Wavelet/plugins/domain/message_gateway/push"
)
@@ -4,18 +4,16 @@
package message_gateway
import (
"Wavelet/pkg/logger"
"Wavelet/pkg/util"
"context"
"encoding/json"
"errors"
"sync"
"Wavelet/pkg/logger"
pkgpush "Wavelet/plugins/domain/message_gateway/push"
"gorm.io/gorm"
"Wavelet/pkg/util"
)
// NotificationMessage represents the structured notification message payload.
@@ -122,7 +120,7 @@ func (t *EventTrigger) Trigger(ctx context.Context, meta EventMetadata, body map
})
}
func (t *EventTrigger) buildMessage(event *PushEvent, meta EventMetadata, flatBody map[string]any, body map[string]any) (NotificationMessage, string) {
func (t *EventTrigger) buildMessage(event *PushEvent, meta EventMetadata, flatBody, body map[string]any) (NotificationMessage, string) {
var msg NotificationMessage
renderedTemplate := ""
@@ -4,6 +4,7 @@
package message_gateway
import (
"Wavelet/pkg/response"
"errors"
"fmt"
"net/http"
@@ -13,8 +14,6 @@ import (
"github.com/gin-gonic/gin"
"gorm.io/gorm"
"Wavelet/pkg/response"
)
// UpdatePushEventRequest is the request body for updating a push event.
@@ -4,6 +4,7 @@
package message_gateway
import (
"Wavelet/core/contracts"
"context"
"encoding/json"
"errors"
@@ -13,7 +14,6 @@ import (
"gorm.io/gorm"
"Wavelet/core/contracts"
pkgpush "Wavelet/plugins/domain/message_gateway/push"
)
@@ -368,7 +368,7 @@ func resolveDynamicKeyword(target string, flatBody map[string]any) string {
return target
}
func resolveTargetUser(ctx context.Context, resolved string, _ string) (contracts.UserDTO, bool) {
func resolveTargetUser(ctx context.Context, resolved, _ string) (contracts.UserDTO, bool) {
var user contracts.UserDTO
if id, err := strconv.ParseUint(resolved, 10, 64); err == nil {
if err := getDB(ctx).Table("w_users").Where("id = ?", id).First(&user).Error; err == nil {
@@ -381,7 +381,7 @@ func resolveTargetUser(ctx context.Context, resolved string, _ string) (contract
return user, false
}
func resolveSystemTarget(ctx context.Context, resolved string, channel string) (string, bool) {
func resolveSystemTarget(ctx context.Context, resolved, channel string) (string, bool) {
if resolved != "系统" && resolved != "system" && resolved != "0" {
return "", false
}
@@ -507,7 +507,7 @@ func getFlatBody(body map[string]any) map[string]any {
return flatResult
}
func flattenMap(prefix string, m map[string]any, result map[string]any) {
func flattenMap(prefix string, m, result map[string]any) {
for k, v := range m {
key := k
if prefix != "" {
@@ -4,13 +4,12 @@
package message_gateway
import (
"Wavelet/core/contracts"
"Wavelet/pkg/logger"
"context"
"encoding/json"
"strconv"
"time"
"Wavelet/core/contracts"
"Wavelet/pkg/logger"
)
func handleTaskCompleted(ctx context.Context, e contracts.TaskCompletedEvent) {
@@ -59,7 +58,7 @@ func handleTaskCompleted(ctx context.Context, e contracts.TaskCompletedEvent) {
}
}
func extractUserFromMap(ctx context.Context, data map[string]any, body map[string]any) {
func extractUserFromMap(ctx context.Context, data, body map[string]any) {
if u, exists := body["user"]; exists && u != nil {
return
}
@@ -4,14 +4,13 @@
package message_gateway
import (
"Wavelet/core/contracts"
"Wavelet/pkg/logger"
"Wavelet/plugins/domain/message_gateway/push"
"context"
"encoding/json"
"errors"
"fmt"
"Wavelet/core/contracts"
"Wavelet/pkg/logger"
"Wavelet/plugins/domain/message_gateway/push"
)
const (
@@ -101,7 +100,7 @@ func (h *PushHandler) Execute(ctx context.Context, payload []byte) error {
return nil
}
func (h *PushHandler) recordHistory(ctx context.Context, req SendPayload, status string, errMsg string) {
func (h *PushHandler) recordHistory(ctx context.Context, req SendPayload, status, errMsg string) {
if dbErr := recordPushHistory(ctx, req, status, errMsg); dbErr != nil {
logger.ErrorF(ctx, "[Push] 写入推送历史审计记录失败: %v", dbErr)
}

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