refactor(core): fix cross-domain auth imports, unify migration, add downstream scaffold

Architecture:
- Move GetFromContext/SetToContext from plugins/domain/auth to pkg/util
- Move auth context key constants to core/contracts (AuthUserObjKey, AuthTokenAuthKey, etc.)
- Add AuthUserIDKey, AuthUserNameKey, GetCurrentUserID, RevokeToken to contracts.AuthService
- All 4 domain plugin Apply() methods now resolve AuthService via core.Using IoC
- Plugin route middleware uses authSvc.RequireAuthMiddleware() cast to gin.HandlerFunc
- DisallowTokenAuth added to AuthService contract

Migration:
- Replace cmd/app.go SetMigrationRunner bridge with gooseEngine implementing core.MigrationEngine
- Remove cmd/root.go PreRun migration hooks and runMigrations() function
- Migrations now run via core.App.Start() → RunMigrations()

Events:
- Add complete domain event topic catalog and payload DTOs to core/contracts/events.go
- 15 event topics across auth, user, admin, upload, message_gateway, risk_control

Downstream:
- Create downstream/ directory with README and custom_example plugin scaffold

CI:
- Update Makefile code-check architecture guards for Cordis layering
- Enforce: core no gin/gorm/asynq, contracts no plugins/, pkg no plugins/, domain no cross-domain
This commit is contained in:
ryan
2026-08-28 11:51:48 +08:00
parent 416603b616
commit c9b702d234
26 changed files with 460 additions and 123 deletions
+16 -31
View File
@@ -12,27 +12,12 @@ import (
"github.com/Rain-kl/Wavelet/core/contracts"
"github.com/Rain-kl/Wavelet/pkg/response"
otel_trace "github.com/Rain-kl/Wavelet/pkg/trace"
"github.com/Rain-kl/Wavelet/pkg/trace"
"github.com/Rain-kl/Wavelet/pkg/util"
db "github.com/Rain-kl/Wavelet/plugins/infra/database"
"github.com/gin-gonic/gin"
)
// GetFromContext 从 Gin 请求上下文获取指定类型的值。
func GetFromContext[T any](c *gin.Context, key string) (T, bool) {
value, exists := c.Get(key)
if !exists {
var zero T
return zero, false
}
typed, ok := value.(T)
return typed, ok
}
// SetToContext 设置值到 Gin 请求上下文。
func SetToContext[T any](c *gin.Context, key string, value T) {
c.Set(key, value)
}
func hashToken(token string) string {
h := sha256.New()
h.Write([]byte(token))
@@ -91,8 +76,8 @@ func GetUserFromRequest(c *gin.Context) (*contracts.UserDTO, error) {
if user.Username == SystemUsername {
return nil, errors.New("system user is not allowed to login")
}
SetToContext(c, TokenAuthKey, true)
SetToContext(c, TokenAdminKey, tokenRecord.IsAdmin)
util.SetToContext(c, contracts.AuthTokenAuthKey, true)
util.SetToContext(c, contracts.AuthTokenAdminKey, tokenRecord.IsAdmin)
return user, nil
}
}
@@ -113,8 +98,8 @@ func GetUserFromRequest(c *gin.Context) (*contracts.UserDTO, error) {
SetCachedUser(ctx, userID, user)
}
SetToContext(c, TokenAuthKey, false)
SetToContext(c, TokenAdminKey, false)
util.SetToContext(c, contracts.AuthTokenAuthKey, false)
util.SetToContext(c, contracts.AuthTokenAdminKey, false)
if user.Username == "system" {
return nil, errors.New("system user is not allowed to login")
@@ -126,7 +111,7 @@ func GetUserFromRequest(c *gin.Context) (*contracts.UserDTO, error) {
// LoginRequired 返回登录鉴权中间件,校验 Access Token 或 Session
func LoginRequired() gin.HandlerFunc {
return func(c *gin.Context) {
ctx, span := otel_trace.Start(c.Request.Context(), "LoginRequired")
_, span := trace.Start(c.Request.Context(), "LoginRequired")
defer span.End()
user, err := GetUserFromRequest(c)
@@ -135,8 +120,8 @@ func LoginRequired() gin.HandlerFunc {
return
}
LogForAudit(ctx, user, c)
SetToContext(c, UserObjKey, user)
LogForAudit(c.Request.Context(), user, c)
util.SetToContext(c, contracts.AuthUserObjKey, user)
c.Next()
}
}
@@ -144,7 +129,7 @@ func LoginRequired() gin.HandlerFunc {
// AdminRequired 校验管理员权限(支持 Session 和 Token 鉴权)
func AdminRequired() gin.HandlerFunc {
return func(c *gin.Context) {
ctx, span := otel_trace.Start(c.Request.Context(), "AdminRequired")
_, span := trace.Start(c.Request.Context(), "AdminRequired")
defer span.End()
user, err := GetUserFromRequest(c)
@@ -153,8 +138,8 @@ func AdminRequired() gin.HandlerFunc {
return
}
isTokenAuth, _ := GetFromContext[bool](c, TokenAuthKey)
isTokenAdmin, _ := GetFromContext[bool](c, TokenAdminKey)
isTokenAuth, _ := util.GetFromContext[bool](c, contracts.AuthTokenAuthKey)
isTokenAdmin, _ := util.GetFromContext[bool](c, contracts.AuthTokenAdminKey)
// 如果是通过 Token 鉴权,要求该 Token 具备管理员权限或者用户本身为管理员
if isTokenAuth && !isTokenAdmin && !user.IsAdmin {
@@ -168,8 +153,8 @@ func AdminRequired() gin.HandlerFunc {
return
}
LogForAudit(ctx, user, c)
SetToContext(c, UserObjKey, user)
LogForAudit(c.Request.Context(), user, c)
util.SetToContext(c, contracts.AuthUserObjKey, user)
c.Next()
}
}
@@ -182,10 +167,10 @@ func LoginAdminRequired() gin.HandlerFunc {
// DisallowTokenAuth 拒绝使用 Access Token 进行身份验证的请求访问该端点
func DisallowTokenAuth() gin.HandlerFunc {
return func(c *gin.Context) {
if tokenAuth, _ := GetFromContext[bool](c, TokenAuthKey); tokenAuth {
if tokenAuth, _ := util.GetFromContext[bool](c, contracts.AuthTokenAuthKey); tokenAuth {
response.AbortForbidden(c, ErrTokenAuthNotAllowed)
return
}
c.Next()
}
}
}