package user import ( "context" "encoding/json" "fmt" "net/http" "github.com/gin-gonic/gin" "github.com/perfect-panel/server/internal/logic/public/user" "github.com/perfect-panel/server/internal/svc" "github.com/perfect-panel/server/pkg/constant" "github.com/pkg/errors" ) // DeleteAccountHandler 注销账号处理器 // 根据当前token删除所有关联设备,然后根据各自设备ID重新新建账号 // 新增:需携带邮箱验证码,验证通过后执行注销 type deleteAccountReq struct { EmailCode string `json:"email_code" binding:"required"` // 邮箱验证码 } func DeleteAccountHandler(serverCtx *svc.ServiceContext) gin.HandlerFunc { return func(c *gin.Context) { var req deleteAccountReq if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "invalid request: " + err.Error()}) return } // 校验邮箱验证码 if err := verifyEmailCode(c.Request.Context(), serverCtx, req.EmailCode); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } l := user.NewDeleteAccountLogic(c.Request.Context(), serverCtx) resp, err := l.DeleteAccount() if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, resp) } } type CacheKeyPayload struct { Code string `json:"code"` LastAt int64 `json:"lastAt"` } func verifyEmailCode(ctx context.Context, serverCtx *svc.ServiceContext, code string) error { userEmail := ctx.Value("user_email").(string) cacheKey := fmt.Sprintf("auth_code:%s:%s", constant.Security, userEmail) val, err := serverCtx.Redis.Get(ctx, cacheKey).Result() if err != nil { return errors.Wrap(err, "failed to get cached code") } var payload CacheKeyPayload if err := json.Unmarshal([]byte(val), &payload); err != nil { return errors.Wrap(err, "invalid cached payload") } if payload.Code != code { return errors.New("invalid email code") } // 验证通过,立即删除缓存,防止重复使用 _ = serverCtx.Redis.Del(ctx, cacheKey) return nil }