mengstack-api/internal/modules/auth/interfaces/routes.go
MengStack Dev df809f1045
Some checks failed
CI / Build & Test (push) Failing after 1m31s
feat: user CRUD API + dashboard stats + kernel infrastructure
- Add user management endpoints (list/create/get/update/delete) with pagination and search
- Add dashboard stats endpoint with tenant/user/online counts and growth metrics
- Add tenant resolver middleware for multi-tenant request scoping
- Add i18n kernel with zh/en message files and AcceptLanguage middleware
- Add WebSocket hub/handler for real-time communication
- Add job scheduler kernel with cron support
- Add plugin sandbox for isolated execution
- Add storage kernel (local filesystem)
- Add event bus kernel for pub/sub
- Add cache kernel abstraction
- Add database migration runner and version upgrade checker
- Add rate limiting middleware with Redis backend
- Add SQL migrations for rbac, audit_logs, settings, notifications, examples
- Extend user repository with list/delete/count operations
- Register all module routes with tenant resolver
2026-10-03 03:42:58 +08:00

87 lines
2.1 KiB
Go

package interfaces
import (
"mengstack/internal/app/middleware"
"mengstack/internal/config"
"mengstack/internal/kernel/tenant"
"mengstack/internal/modules/auth/application"
"mengstack/internal/modules/auth/infrastructure"
"github.com/gin-gonic/gin"
"go.uber.org/fx"
)
type AuthMiddleware struct {
fx.In
Service *application.Service
}
func NewAuthMiddleware(in AuthMiddleware) gin.HandlerFunc {
return func(c *gin.Context) {
authHeader := c.GetHeader("Authorization")
if authHeader == "" {
c.AbortWithStatusJSON(401, gin.H{"code": -1, "message": "missing authorization"})
return
}
token := authHeader
if len(authHeader) > 7 && authHeader[:7] == "Bearer " {
token = authHeader[7:]
}
claims, err := application.ParseToken(token, in.Service.JWTSecret())
if err != nil {
c.AbortWithStatusJSON(401, gin.H{"code": -1, "message": "invalid token"})
return
}
c.Set("user_id", claims.UserID)
c.Set("tenant_id", claims.TenantID)
c.Next()
}
}
func SetupRoutes(r *gin.Engine, h *Handler, authMW gin.HandlerFunc, tenantResolver tenant.Resolver) {
auth := r.Group("/api/v1/auth")
auth.Use(middleware.OptionalTenant(tenantResolver))
{
auth.POST("/register", h.Register)
auth.POST("/login", h.Login)
auth.POST("/refresh", h.RefreshToken)
}
protected := r.Group("/api/v1")
protected.Use(authMW, middleware.MultiTenant(tenantResolver))
{
protected.GET("/ping", h.Ping)
protected.GET("/profile", h.GetProfile)
protected.POST("/password", h.ChangePassword)
protected.GET("/users", h.ListUsers)
protected.POST("/users", h.CreateUser)
protected.GET("/users/:id", h.GetUser)
protected.PUT("/users/:id", h.UpdateUser)
protected.DELETE("/users/:id", h.DeleteUser)
}
}
func NewJWTConfig(cfg *config.Config) application.JWTConfig {
return application.JWTConfig{
Secret: cfg.JWT.Secret,
AccessExpiryMinutes: cfg.JWT.AccessExpiryMinutes,
RefreshExpiryDays: cfg.JWT.RefreshExpiryDays,
Issuer: cfg.JWT.Issuer,
}
}
var Module = fx.Module("auth",
fx.Provide(
NewJWTConfig,
infrastructure.NewUserRepository,
application.NewService,
NewHandler,
NewAuthMiddleware,
),
)