mirror of
https://github.com/Rain-kl/OpenFlare.git
synced 2026-09-29 14:06:36 +08:00
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:
@@ -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"}}
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -5,11 +5,10 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"Wavelet/core"
|
||||
"log"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"Wavelet/core"
|
||||
)
|
||||
|
||||
var allCmd = &cobra.Command{
|
||||
|
||||
+1
-2
@@ -4,11 +4,10 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"Wavelet/core"
|
||||
"log"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"Wavelet/core"
|
||||
)
|
||||
|
||||
var apiCmd = &cobra.Command{
|
||||
|
||||
+12
-12
@@ -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.
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -4,11 +4,10 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"Wavelet/pkg/buildinfo"
|
||||
"Wavelet/pkg/config"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestFormatStartupBanner(t *testing.T) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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 (
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -4,11 +4,10 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"Wavelet/core"
|
||||
"log"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"Wavelet/core"
|
||||
)
|
||||
|
||||
var schedulerCmd = &cobra.Command{
|
||||
|
||||
@@ -4,11 +4,10 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"Wavelet/core"
|
||||
"log"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"Wavelet/core"
|
||||
)
|
||||
|
||||
var workerCmd = &cobra.Command{
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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...)
|
||||
}
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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...)
|
||||
}
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
Vendored
+2
-2
@@ -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()
|
||||
|
||||
|
||||
Vendored
+5
-5
@@ -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")
|
||||
}
|
||||
|
||||
@@ -118,8 +118,7 @@ type logConfig struct {
|
||||
}
|
||||
|
||||
// schedulerConfig 定时任务配置
|
||||
type schedulerConfig struct {
|
||||
}
|
||||
type schedulerConfig struct{}
|
||||
|
||||
// workerConfig 工作配置
|
||||
type workerConfig struct {
|
||||
|
||||
@@ -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())
|
||||
},
|
||||
|
||||
@@ -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 的毫秒时间戳
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ import (
|
||||
)
|
||||
|
||||
// logDirPerm 日志目录权限
|
||||
const logDirPerm = 0750
|
||||
const logDirPerm = 0o750
|
||||
|
||||
func getLogWriterForConfig(cfg Config) (zapcore.WriteSyncer, error) {
|
||||
if cfg.Output == "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...))
|
||||
}
|
||||
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
package testhelper
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"Wavelet/pkg/response"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// NewTestGinEngine 创建带 ErrorHandlerMiddleware 的 Gin 引擎,与生产环境错误响应行为一致。
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -4,14 +4,13 @@
|
||||
package util
|
||||
|
||||
import (
|
||||
"Wavelet/pkg/httppool"
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
"Wavelet/pkg/httppool"
|
||||
)
|
||||
|
||||
// IsLocalhost 检查 URL 是否为 localhost
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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), ¤tCfg); err != nil {
|
||||
return "", fmt.Errorf("解析当前存储配置失败: %w", err)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 返回管理员权限校验中间件
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 (
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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,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 {
|
||||
|
||||
@@ -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}$`)
|
||||
|
||||
@@ -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,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,
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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{}
|
||||
|
||||
@@ -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 选项
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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 (
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user