Clean public release with: - Go/Gin/PostgreSQL/Redis architecture - Multi-tenant support - JWT authentication - Docker Compose deployment - Environment-based configuration
167 lines
4.8 KiB
Go
167 lines
4.8 KiB
Go
package interfaces
|
||
|
||
import (
|
||
"mengstack/internal/kernel/response"
|
||
"mengstack/internal/modules/auth/application"
|
||
"mengstack/internal/modules/auth/domain"
|
||
|
||
"github.com/gin-gonic/gin"
|
||
)
|
||
|
||
type Handler struct {
|
||
svc *application.Service
|
||
}
|
||
|
||
func NewHandler(svc *application.Service) *Handler {
|
||
return &Handler{svc: svc}
|
||
}
|
||
|
||
// Register godoc
|
||
// @Summary 用户注册
|
||
// @Description 使用邮箱、用户名和密码注册新用户,返回 JWT token
|
||
// @Tags Auth
|
||
// @Accept json
|
||
// @Produce json
|
||
// @Param request body domain.RegisterRequest true "注册信息"
|
||
// @Success 200 {object} response.Response{data=domain.TokenPair}
|
||
// @Failure 400 {object} response.Response
|
||
// @Failure 409 {object} response.Response
|
||
// @Router /auth/register [post]
|
||
func (h *Handler) Register(c *gin.Context) {
|
||
var req domain.RegisterRequest
|
||
if err := c.ShouldBindJSON(&req); err != nil {
|
||
response.Fail(c, response.NewBadRequest("invalid request body"))
|
||
return
|
||
}
|
||
|
||
tokens, err := h.svc.Register(c.Request.Context(), req)
|
||
if err != nil {
|
||
response.HandleError(c, err)
|
||
return
|
||
}
|
||
|
||
response.Success(c, tokens)
|
||
}
|
||
|
||
// Login godoc
|
||
// @Summary 用户登录
|
||
// @Description 使用邮箱和密码登录,返回 JWT token
|
||
// @Tags Auth
|
||
// @Accept json
|
||
// @Produce json
|
||
// @Param request body domain.LoginRequest true "登录信息"
|
||
// @Success 200 {object} response.Response{data=domain.TokenPair}
|
||
// @Failure 400 {object} response.Response
|
||
// @Failure 401 {object} response.Response
|
||
// @Router /auth/login [post]
|
||
func (h *Handler) Login(c *gin.Context) {
|
||
var req domain.LoginRequest
|
||
if err := c.ShouldBindJSON(&req); err != nil {
|
||
response.Fail(c, response.NewBadRequest("invalid request body"))
|
||
return
|
||
}
|
||
|
||
tokens, err := h.svc.Login(c.Request.Context(), req)
|
||
if err != nil {
|
||
response.HandleError(c, err)
|
||
return
|
||
}
|
||
|
||
response.Success(c, tokens)
|
||
}
|
||
|
||
// RefreshToken godoc
|
||
// @Summary 刷新 Token
|
||
// @Description 使用 refresh_token 获取新的 token 对
|
||
// @Tags Auth
|
||
// @Accept json
|
||
// @Produce json
|
||
// @Param request body object true "{ \"refresh_token\": \"...\" }"
|
||
// @Success 200 {object} response.Response{data=domain.TokenPair}
|
||
// @Failure 400 {object} response.Response
|
||
// @Failure 401 {object} response.Response
|
||
// @Router /auth/refresh [post]
|
||
func (h *Handler) RefreshToken(c *gin.Context) {
|
||
var req struct {
|
||
RefreshToken string `json:"refresh_token" binding:"required"`
|
||
}
|
||
if err := c.ShouldBindJSON(&req); err != nil {
|
||
response.Fail(c, response.NewBadRequest("invalid request body"))
|
||
return
|
||
}
|
||
|
||
tokens, err := h.svc.RefreshToken(c.Request.Context(), req.RefreshToken)
|
||
if err != nil {
|
||
response.HandleError(c, err)
|
||
return
|
||
}
|
||
|
||
response.Success(c, tokens)
|
||
}
|
||
|
||
// ChangePassword godoc
|
||
// @Summary 修改密码
|
||
// @Description 使用旧密码验证后设置新密码
|
||
// @Tags Auth
|
||
// @Accept json
|
||
// @Produce json
|
||
// @Param request body domain.ChangePasswordRequest true "密码修改请求"
|
||
// @Success 200 {object} response.Response
|
||
// @Failure 400 {object} response.Response
|
||
// @Failure 401 {object} response.Response
|
||
// @Security Bearer
|
||
// @Security TenantID
|
||
// @Router /password [post]
|
||
func (h *Handler) ChangePassword(c *gin.Context) {
|
||
userID := c.GetUint("user_id")
|
||
|
||
var req domain.ChangePasswordRequest
|
||
if err := c.ShouldBindJSON(&req); err != nil {
|
||
response.Fail(c, response.NewBadRequest("invalid request body"))
|
||
return
|
||
}
|
||
|
||
if err := h.svc.ChangePassword(c.Request.Context(), userID, req); err != nil {
|
||
response.HandleError(c, err)
|
||
return
|
||
}
|
||
|
||
response.Success(c, nil)
|
||
}
|
||
|
||
// GetProfile godoc
|
||
// @Summary 获取当前用户信息
|
||
// @Description 返回当前认证用户的个人资料
|
||
// @Tags Auth
|
||
// @Produce json
|
||
// @Success 200 {object} response.Response{data=domain.UserDTO}
|
||
// @Failure 401 {object} response.Response
|
||
// @Failure 404 {object} response.Response
|
||
// @Security Bearer
|
||
// @Security TenantID
|
||
// @Router /profile [get]
|
||
func (h *Handler) GetProfile(c *gin.Context) {
|
||
userID := c.GetUint("user_id")
|
||
|
||
dto, err := h.svc.GetProfile(c.Request.Context(), userID)
|
||
if err != nil {
|
||
response.HandleError(c, err)
|
||
return
|
||
}
|
||
|
||
response.Success(c, dto)
|
||
}
|
||
|
||
// Ping godoc
|
||
// @Summary 健康探测
|
||
// @Description 返回 pong,用于验证认证和多租户中间件是否正常
|
||
// @Tags System
|
||
// @Produce json
|
||
// @Success 200 {object} response.Response
|
||
// @Security Bearer
|
||
// @Security TenantID
|
||
// @Router /ping [get]
|
||
func (h *Handler) Ping(c *gin.Context) {
|
||
response.Success(c, gin.H{"message": "pong"})
|
||
}
|