feat: backend core - auth, user, role, permission, device, webhook, monitoring, cache, repository, service, middleware, API handlers
This commit is contained in:
153
internal/api/handler/password_reset_handler.go
Normal file
153
internal/api/handler/password_reset_handler.go
Normal file
@@ -0,0 +1,153 @@
|
||||
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"})
|
||||
}
|
||||
Reference in New Issue
Block a user