package handler import ( "net/http" "github.com/gin-gonic/gin" "github.com/user-management-system/internal/service" ) // PasswordResetHandler handles password reset requests type PasswordResetHandler struct { passwordResetService *service.PasswordResetService smsService *service.SMSCodeService } // NewPasswordResetHandler creates a new PasswordResetHandler func NewPasswordResetHandler(passwordResetService *service.PasswordResetService) *PasswordResetHandler { return &PasswordResetHandler{passwordResetService: passwordResetService} } // NewPasswordResetHandlerWithSMS creates a new PasswordResetHandler with SMS support func NewPasswordResetHandlerWithSMS(passwordResetService *service.PasswordResetService, smsService *service.SMSCodeService) *PasswordResetHandler { return &PasswordResetHandler{ passwordResetService: passwordResetService, smsService: smsService, } } func (h *PasswordResetHandler) ForgotPassword(c *gin.Context) { var req struct { Email string `json:"email" binding:"required"` } if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } if err := h.passwordResetService.ForgotPassword(c.Request.Context(), req.Email); err != nil { handleError(c, err) return } c.JSON(http.StatusOK, gin.H{"message": "password reset email sent"}) } func (h *PasswordResetHandler) ValidateResetToken(c *gin.Context) { token := c.Query("token") if token == "" { c.JSON(http.StatusBadRequest, gin.H{"error": "token is required"}) return } valid, err := h.passwordResetService.ValidateResetToken(c.Request.Context(), token) if err != nil { handleError(c, err) return } c.JSON(http.StatusOK, gin.H{"valid": valid}) } func (h *PasswordResetHandler) ResetPassword(c *gin.Context) { var req struct { Token string `json:"token" binding:"required"` NewPassword string `json:"new_password" binding:"required"` } if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } if err := h.passwordResetService.ResetPassword(c.Request.Context(), req.Token, req.NewPassword); err != nil { handleError(c, err) return } c.JSON(http.StatusOK, gin.H{"message": "password reset successful"}) } // ForgotPasswordByPhoneRequest 短信密码重置请求 type ForgotPasswordByPhoneRequest struct { Phone string `json:"phone" binding:"required"` } // ForgotPasswordByPhone 发送短信验证码 func (h *PasswordResetHandler) ForgotPasswordByPhone(c *gin.Context) { if h.smsService == nil { c.JSON(http.StatusServiceUnavailable, gin.H{"error": "SMS service not configured"}) return } var req ForgotPasswordByPhoneRequest if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } // 获取验证码(不发送,由调用方通过其他渠道发送) code, err := h.passwordResetService.ForgotPasswordByPhone(c.Request.Context(), req.Phone) if err != nil { handleError(c, err) return } if code == "" { // 用户不存在,不提示 c.JSON(http.StatusOK, gin.H{"message": "verification code sent"}) return } // 通过SMS服务发送验证码 sendReq := &service.SendCodeRequest{ Phone: req.Phone, Purpose: "password_reset", } _, err = h.smsService.SendCode(c.Request.Context(), sendReq) if err != nil { handleError(c, err) return } c.JSON(http.StatusOK, gin.H{"message": "verification code sent"}) } // ResetPasswordByPhoneRequest 短信验证码重置密码请求 type ResetPasswordByPhoneRequest struct { Phone string `json:"phone" binding:"required"` Code string `json:"code" binding:"required"` NewPassword string `json:"new_password" binding:"required"` } // ResetPasswordByPhone 通过短信验证码重置密码 func (h *PasswordResetHandler) ResetPasswordByPhone(c *gin.Context) { var req ResetPasswordByPhoneRequest if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } err := h.passwordResetService.ResetPasswordByPhone(c.Request.Context(), &service.ResetPasswordByPhoneRequest{ Phone: req.Phone, Code: req.Code, NewPassword: req.NewPassword, }) if err != nil { handleError(c, err) return } c.JSON(http.StatusOK, gin.H{"message": "password reset successful"}) }