Some checks failed
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Has been cancelled
- 七个设置登录密码入口统一 8~12 位、四类字符至少三类(1001/1016),修改密码与建店铺返回字段级提示 - 订单导出末列“操作人”、IoT 卡导出末列“套餐到期时间”、设备导出流量标 MB 并新增“设备合计(GB)” - 历史导出任务按冻结表头识别新旧尾列,行宽不变 - OpenSpec Change fix-august-iteration-export-and-password-hints:10/12,5.3 前端同步与 5.4 测试部署导出验证待完成
175 lines
4.6 KiB
Go
175 lines
4.6 KiB
Go
package auth
|
||
|
||
import (
|
||
"github.com/break/junhong_cmp_fiber/internal/handler/validation"
|
||
"github.com/break/junhong_cmp_fiber/internal/model/dto"
|
||
"github.com/break/junhong_cmp_fiber/internal/service/auth"
|
||
"github.com/break/junhong_cmp_fiber/pkg/errors"
|
||
"github.com/break/junhong_cmp_fiber/pkg/logger"
|
||
"github.com/break/junhong_cmp_fiber/pkg/middleware"
|
||
"github.com/break/junhong_cmp_fiber/pkg/response"
|
||
"github.com/go-playground/validator/v10"
|
||
"github.com/gofiber/fiber/v2"
|
||
"go.uber.org/zap"
|
||
)
|
||
|
||
// changePasswordInvalidPrefix 修改密码参数校验失败提示的统一前缀。
|
||
const changePasswordInvalidPrefix = "修改密码参数不合法"
|
||
|
||
// Handler 统一认证处理器
|
||
// 合并后台和 H5 认证接口
|
||
type Handler struct {
|
||
authService *auth.Service
|
||
validator *validator.Validate
|
||
}
|
||
|
||
// NewHandler 创建统一认证处理器
|
||
func NewHandler(authService *auth.Service, validator *validator.Validate) *Handler {
|
||
return &Handler{
|
||
authService: authService,
|
||
validator: validator,
|
||
}
|
||
}
|
||
|
||
// Login 统一登录(后台+H5)
|
||
// POST /api/auth/login - 统一登录(后台+H5)
|
||
func (h *Handler) Login(c *fiber.Ctx) error {
|
||
var req dto.LoginRequest
|
||
if err := c.BodyParser(&req); err != nil {
|
||
return errors.New(errors.CodeInvalidParam, "请求参数解析失败")
|
||
}
|
||
|
||
if err := h.validator.Struct(&req); err != nil {
|
||
logger.GetAppLogger().Warn("参数验证失败",
|
||
zap.String("path", c.Path()),
|
||
zap.String("method", c.Method()),
|
||
zap.Error(err),
|
||
)
|
||
return errors.New(errors.CodeInvalidParam)
|
||
}
|
||
|
||
clientIP := c.IP()
|
||
ctx := c.UserContext()
|
||
|
||
resp, err := h.authService.Login(ctx, &req, clientIP)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
return response.Success(c, resp)
|
||
}
|
||
|
||
// Logout 统一登出
|
||
// POST /api/auth/logout - 统一登出
|
||
func (h *Handler) Logout(c *fiber.Ctx) error {
|
||
authorization := c.Get("Authorization")
|
||
accessToken := ""
|
||
if len(authorization) > 7 && authorization[:7] == "Bearer " {
|
||
accessToken = authorization[7:]
|
||
}
|
||
|
||
// 尝试从请求体获取 refresh_token(可选)
|
||
refreshToken := ""
|
||
var req dto.RefreshTokenRequest
|
||
if err := c.BodyParser(&req); err == nil {
|
||
refreshToken = req.RefreshToken
|
||
}
|
||
|
||
ctx := c.UserContext()
|
||
|
||
if err := h.authService.Logout(ctx, accessToken, refreshToken); err != nil {
|
||
return err
|
||
}
|
||
|
||
return response.Success(c, nil)
|
||
}
|
||
|
||
// RefreshToken 刷新 Token
|
||
// POST /api/auth/refresh-token - 刷新 Token
|
||
func (h *Handler) RefreshToken(c *fiber.Ctx) error {
|
||
var req dto.RefreshTokenRequest
|
||
if err := c.BodyParser(&req); err != nil {
|
||
return errors.New(errors.CodeInvalidParam, "请求参数解析失败")
|
||
}
|
||
|
||
if err := h.validator.Struct(&req); err != nil {
|
||
logger.GetAppLogger().Warn("参数验证失败",
|
||
zap.String("path", c.Path()),
|
||
zap.String("method", c.Method()),
|
||
zap.Error(err),
|
||
)
|
||
return errors.New(errors.CodeInvalidParam)
|
||
}
|
||
|
||
ctx := c.UserContext()
|
||
|
||
newAccessToken, err := h.authService.RefreshToken(ctx, req.RefreshToken)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
resp := &dto.RefreshTokenResponse{
|
||
AccessToken: newAccessToken,
|
||
ExpiresIn: 86400,
|
||
}
|
||
|
||
return response.Success(c, resp)
|
||
}
|
||
|
||
// GetMe 获取用户信息
|
||
// GET /api/auth/me - 获取用户信息
|
||
func (h *Handler) GetMe(c *fiber.Ctx) error {
|
||
userID := middleware.GetUserIDFromContext(c.UserContext())
|
||
if userID == 0 {
|
||
return errors.New(errors.CodeUnauthorized, "未授权访问")
|
||
}
|
||
|
||
ctx := c.UserContext()
|
||
|
||
userInfo, permissions, err := h.authService.GetCurrentUser(ctx, userID)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
data := map[string]interface{}{
|
||
"user": userInfo,
|
||
"permissions": permissions,
|
||
}
|
||
|
||
return response.Success(c, data)
|
||
}
|
||
|
||
// ChangePassword 修改密码
|
||
// PUT /api/auth/password - 修改密码
|
||
func (h *Handler) ChangePassword(c *fiber.Ctx) error {
|
||
userID := middleware.GetUserIDFromContext(c.UserContext())
|
||
if userID == 0 {
|
||
return errors.New(errors.CodeUnauthorized, "未授权访问")
|
||
}
|
||
|
||
var req dto.ChangePasswordRequest
|
||
if err := c.BodyParser(&req); err != nil {
|
||
return errors.New(errors.CodeInvalidParam, "请求参数解析失败")
|
||
}
|
||
|
||
if err := h.validator.Struct(&req); err != nil {
|
||
logger.GetAppLogger().Warn("参数验证失败",
|
||
zap.String("path", c.Path()),
|
||
zap.String("method", c.Method()),
|
||
zap.Error(err),
|
||
)
|
||
return errors.New(errors.CodeInvalidParam, validation.Message(changePasswordInvalidPrefix, &req, err))
|
||
}
|
||
if err := validation.LoginPassword(changePasswordInvalidPrefix, "新密码", req.NewPassword); err != nil {
|
||
return err
|
||
}
|
||
|
||
ctx := c.UserContext()
|
||
|
||
if err := h.authService.ChangePassword(ctx, userID, req.OldPassword, req.NewPassword); err != nil {
|
||
return err
|
||
}
|
||
|
||
return response.Success(c, nil)
|
||
}
|