Files
smartmate/backend/gateway/api/userauth/handler.go
Losita cc98b62ad8 Version: 0.9.83.dev.260508
后端:
1.关闭了注册接口

前端:
1.改造了主页

仓库:
1.对部署做了一些改善
2026-05-08 18:29:49 +08:00

155 lines
4.5 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package userauthapi
import (
"context"
"net/http"
"strings"
"time"
gatewaymiddleware "github.com/LoveLosita/smartflow/backend/gateway/middleware"
"github.com/LoveLosita/smartflow/backend/gateway/shared/respond"
contracts "github.com/LoveLosita/smartflow/backend/shared/contracts/userauth"
"github.com/LoveLosita/smartflow/backend/shared/ports"
"github.com/gin-gonic/gin"
)
type UserHandler struct {
client ports.UserCommandClient
captcha *GeeTestService
allowRegister bool
}
// NewUserHandler 只接收 user/auth 客户端与验证码服务,不再直接依赖本地 user service。
func NewUserHandler(client ports.UserCommandClient, captcha *GeeTestService, allowRegister bool) *UserHandler {
return &UserHandler{
client: client,
captcha: captcha,
allowRegister: allowRegister,
}
}
func (api *UserHandler) CaptchaRegister(c *gin.Context) {
captchaCtx, cancel := context.WithTimeout(c.Request.Context(), 3*time.Second)
defer cancel()
registerData, err := api.captcha.Register(captchaCtx, c.ClientIP())
if err != nil {
respond.DealWithError(c, err)
return
}
c.JSON(http.StatusOK, respond.RespWithData(respond.Ok, registerData))
}
func (api *UserHandler) UserRegister(c *gin.Context) {
if !api.ensureRegisterEnabled(c) {
return
}
var req registerRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, respond.WrongParamType)
return
}
// 1. 先用独立超时完成极验二次校验,避免第三方接口抖动侵入内部 RPC 超时预算。
// 2. 只有验证码通过后才继续调 user/auth 注册服务,防止无效流量进入内部链路。
// 3. 内部 RPC 仍保留原先 2 秒超时边界,不改变现有 user/auth 服务 SLA。
captchaCtx, cancelCaptcha := context.WithTimeout(c.Request.Context(), 3*time.Second)
defer cancelCaptcha()
if err := api.captcha.Verify(captchaCtx, req.captchaPayload(), c.ClientIP()); err != nil {
respond.DealWithError(c, err)
return
}
ctx, cancel := context.WithTimeout(c.Request.Context(), 2*time.Second)
defer cancel()
retUser, err := api.client.Register(ctx, req.toContract())
if err != nil {
respond.DealWithError(c, err)
return
}
c.JSON(http.StatusOK, respond.RespWithData(respond.Ok, retUser))
}
func (api *UserHandler) UserLogin(c *gin.Context) {
var req loginRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, respond.WrongParamType)
return
}
captchaCtx, cancelCaptcha := context.WithTimeout(c.Request.Context(), 3*time.Second)
defer cancelCaptcha()
if err := api.captcha.Verify(captchaCtx, req.captchaPayload(), c.ClientIP()); err != nil {
respond.DealWithError(c, err)
return
}
ctx, cancel := context.WithTimeout(c.Request.Context(), 2*time.Second)
defer cancel()
tokens, err := api.client.Login(ctx, req.toContract())
if err != nil {
respond.DealWithError(c, err)
return
}
c.JSON(http.StatusOK, respond.RespWithData(respond.Ok, tokens))
}
func (api *UserHandler) RefreshTokenHandler(c *gin.Context) {
var req contracts.RefreshTokenRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, respond.WrongParamType)
return
}
if strings.TrimSpace(req.RefreshToken) == "" {
c.JSON(http.StatusBadRequest, respond.MissingParam)
return
}
ctx, cancel := context.WithTimeout(c.Request.Context(), 2*time.Second)
defer cancel()
tokens, err := api.client.RefreshToken(ctx, req)
if err != nil {
respond.DealWithError(c, err)
return
}
c.JSON(http.StatusOK, respond.RespWithData(respond.Ok, tokens))
}
func (api *UserHandler) UserLogout(c *gin.Context) {
token := gatewaymiddleware.ExtractTokenFromAuthorization(c.GetHeader("Authorization"))
if token == "" {
c.JSON(http.StatusUnauthorized, respond.MissingToken)
return
}
ctx, cancel := context.WithTimeout(c.Request.Context(), 2*time.Second)
defer cancel()
if err := api.client.Logout(ctx, token); err != nil {
respond.DealWithError(c, err)
return
}
c.JSON(http.StatusOK, respond.Ok)
}
// ensureRegisterEnabled 负责统一收口“注册相关入口”的开关判断。
// 职责边界:
// 1. 只判断当前环境是否允许注册,并向前端返回明确的 403
// 2. 不负责登录、刷新 token、登出等其它 user/auth 能力;
// 3. 不触发验证码或 RPC 调用,避免“已关闭注册”时仍向下游产生无效流量。
func (api *UserHandler) ensureRegisterEnabled(c *gin.Context) bool {
if api.allowRegister {
return true
}
c.JSON(http.StatusForbidden, respond.Response{
Status: "40301",
Info: "registration is disabled",
})
return false
}