feat: complete production readiness improvements
- Fix DIP violations in service layer (device, stats, auth middleware) - Add ReplaceUserRoles interface method for transaction safety - Implement Magic Bytes validation for avatar uploads - Standardize OAuth error handling with ErrOAuthProviderNotSupported - Use crypto/rand for JWT secret generation instead of weak fixed key - Apply code formatting with gofumpt and goimports - Fix staticcheck issues (S1024, S1008, ST1005) - Add comprehensive quality and functional test reports - Achieve 36.3% test coverage (up from 16.3%) - All E2E, integration, and business logic tests passing
This commit is contained in:
@@ -14,38 +14,37 @@ import (
|
||||
"github.com/user-management-system/internal/cache"
|
||||
"github.com/user-management-system/internal/domain"
|
||||
apierrors "github.com/user-management-system/internal/pkg/errors"
|
||||
"github.com/user-management-system/internal/repository"
|
||||
)
|
||||
|
||||
// Interfaces for dependency inversion (DIP) — middleware depends on these abstractions, not concrete types.
|
||||
type authUserRepository interface {
|
||||
GetByID(ctx context.Context, id int64) (*domain.User, error)
|
||||
}
|
||||
|
||||
type authUserRoleRepository interface {
|
||||
GetUserRolesAndPermissions(ctx context.Context, userID int64) ([]*domain.Role, []*domain.Permission, error)
|
||||
}
|
||||
|
||||
type AuthMiddleware struct {
|
||||
jwt *auth.JWT
|
||||
userRepo *repository.UserRepository
|
||||
userRoleRepo *repository.UserRoleRepository
|
||||
roleRepo *repository.RoleRepository
|
||||
rolePermissionRepo *repository.RolePermissionRepository
|
||||
permissionRepo *repository.PermissionRepository
|
||||
l1Cache *cache.L1Cache
|
||||
cacheManager *cache.CacheManager
|
||||
sfGroup singleflight.Group
|
||||
jwt *auth.JWT
|
||||
userRepo authUserRepository
|
||||
userRoleRepo authUserRoleRepository
|
||||
l1Cache *cache.L1Cache
|
||||
cacheManager *cache.CacheManager
|
||||
sfGroup singleflight.Group
|
||||
}
|
||||
|
||||
func NewAuthMiddleware(
|
||||
jwt *auth.JWT,
|
||||
userRepo *repository.UserRepository,
|
||||
userRoleRepo *repository.UserRoleRepository,
|
||||
roleRepo *repository.RoleRepository,
|
||||
rolePermissionRepo *repository.RolePermissionRepository,
|
||||
permissionRepo *repository.PermissionRepository,
|
||||
userRepo authUserRepository,
|
||||
userRoleRepo authUserRoleRepository,
|
||||
l1Cache *cache.L1Cache,
|
||||
) *AuthMiddleware {
|
||||
return &AuthMiddleware{
|
||||
jwt: jwt,
|
||||
userRepo: userRepo,
|
||||
userRoleRepo: userRoleRepo,
|
||||
roleRepo: roleRepo,
|
||||
rolePermissionRepo: rolePermissionRepo,
|
||||
permissionRepo: permissionRepo,
|
||||
l1Cache: l1Cache,
|
||||
jwt: jwt,
|
||||
userRepo: userRepo,
|
||||
userRoleRepo: userRoleRepo,
|
||||
l1Cache: l1Cache,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,7 +68,7 @@ func (m *AuthMiddleware) Required() gin.HandlerFunc {
|
||||
return
|
||||
}
|
||||
|
||||
if m.isJTIBlacklisted(claims.JTI) {
|
||||
if m.isJTIBlacklisted(c.Request.Context(), claims.JTI) {
|
||||
c.JSON(http.StatusUnauthorized, apierrors.New(http.StatusUnauthorized, "UNAUTHORIZED", "令牌已失效,请重新登录"))
|
||||
c.Abort()
|
||||
return
|
||||
@@ -98,7 +97,7 @@ func (m *AuthMiddleware) Optional() gin.HandlerFunc {
|
||||
token := m.extractToken(c)
|
||||
if token != "" {
|
||||
claims, err := m.jwt.ValidateAccessToken(token)
|
||||
if err == nil && !m.isJTIBlacklisted(claims.JTI) && m.isUserActive(c.Request.Context(), claims.UserID) {
|
||||
if err == nil && !m.isJTIBlacklisted(c.Request.Context(), claims.JTI) && m.isUserActive(c.Request.Context(), claims.UserID) {
|
||||
c.Set("user_id", claims.UserID)
|
||||
c.Set("username", claims.Username)
|
||||
c.Set("token_jti", claims.JTI)
|
||||
@@ -112,7 +111,7 @@ func (m *AuthMiddleware) Optional() gin.HandlerFunc {
|
||||
}
|
||||
}
|
||||
|
||||
func (m *AuthMiddleware) isJTIBlacklisted(jti string) bool {
|
||||
func (m *AuthMiddleware) isJTIBlacklisted(ctx context.Context, jti string) bool {
|
||||
if jti == "" {
|
||||
return false
|
||||
}
|
||||
@@ -128,7 +127,7 @@ func (m *AuthMiddleware) isJTIBlacklisted(jti string) bool {
|
||||
// 多个并发请求只会触发一次 L2 查询
|
||||
if m.cacheManager != nil {
|
||||
val, err, _ := m.sfGroup.Do(key, func() (interface{}, error) {
|
||||
found, _ := m.cacheManager.Get(context.Background(), key)
|
||||
found, _ := m.cacheManager.Get(ctx, key)
|
||||
return found, nil
|
||||
})
|
||||
if err == nil && val != nil {
|
||||
|
||||
Reference in New Issue
Block a user