Files
hfb_sys/backend/internal/modules/auth/handler.go
T
2026-05-29 12:11:13 +08:00

97 lines
2.6 KiB
Go

package auth
import (
"errors"
"net/http"
"strings"
"hfb_sys/backend/pkg/response"
"github.com/gin-gonic/gin"
)
type Handler struct {
service *Service
}
type SendSMSRequest struct {
Phone string `json:"phone" binding:"required"`
}
type LoginRequest struct {
Phone string `json:"phone" binding:"required"`
Code string `json:"code" binding:"required,len=6"`
}
type RefreshRequest struct {
RefreshToken string `json:"refresh_token" binding:"required"`
}
func NewHandler(service *Service) *Handler {
return &Handler{service: service}
}
func (h *Handler) SendSMS(c *gin.Context) {
var req SendSMSRequest
if err := c.ShouldBindJSON(&req); err != nil {
response.BadRequest(c, "手机号不能为空")
return
}
if err := h.service.SendSMSCode(c.Request.Context(), strings.TrimSpace(req.Phone)); err != nil {
writeAuthError(c, err)
return
}
response.OK(c, gin.H{"phone": PublicPhone(req.Phone), "expires_in": 300})
}
func (h *Handler) Login(c *gin.Context) {
var req LoginRequest
if err := c.ShouldBindJSON(&req); err != nil {
response.BadRequest(c, "手机号和验证码不能为空")
return
}
result, err := h.service.LoginWithSMS(c.Request.Context(), strings.TrimSpace(req.Phone), strings.TrimSpace(req.Code))
if err != nil {
writeAuthError(c, err)
return
}
response.OK(c, result)
}
func (h *Handler) Refresh(c *gin.Context) {
var req RefreshRequest
if err := c.ShouldBindJSON(&req); err != nil {
response.BadRequest(c, "refresh_token 不能为空")
return
}
tokens, err := h.service.RefreshToken(req.RefreshToken)
if err != nil {
response.Unauthorized(c, "刷新令牌无效或已过期")
return
}
response.OK(c, tokens)
}
func (h *Handler) Logout(c *gin.Context) {
response.OK(c, gin.H{"logged_out": true})
}
func writeAuthError(c *gin.Context, err error) {
switch {
case errors.Is(err, ErrDependencyUnavailable):
response.ServiceUnavailable(c, "数据库或 Redis 未连接")
case errors.Is(err, ErrInvalidPhone):
response.BadRequest(c, "手机号格式不正确")
case errors.Is(err, ErrCodeRateLimited):
response.Error(c, http.StatusTooManyRequests, "rate_limited", "验证码发送过于频繁")
case errors.Is(err, ErrSMSSendFailed):
response.Error(c, http.StatusBadGateway, "sms_send_failed", "验证码发送失败,请稍后重试")
case errors.Is(err, ErrCodeInvalid):
response.BadRequest(c, "验证码错误或已过期")
case errors.Is(err, ErrUserDisabled):
response.Error(c, http.StatusForbidden, "user_disabled", "用户已被冻结")
default:
response.Error(c, http.StatusInternalServerError, "internal_error", "服务暂时不可用")
}
}