Files
nofx/api
0xYYBB | ZYY | Bobo dca1a16e2f fix(auth): allow re-fetching OTP for unverified users (#653)
* fix(auth): allow re-fetching OTP for unverified users

**Problem:**
- User registers but interrupts OTP setup
- Re-registration returns "邮箱已被注册" error
- User stuck, cannot retrieve QR code to complete setup

**Root Cause:**
- handleRegister rejects all existing emails without checking OTPVerified status
- No way for users to recover from interrupted registration

**Fix:**
- Check if existing user has OTPVerified=false
- If unverified, return original OTP QR code instead of error
- User can continue completing registration with same user_id
- If verified, still reject with "邮箱已被注册" (existing behavior)

**Code Changes:**
```go
// Before:
_, err := s.database.GetUserByEmail(req.Email)
if err == nil {
    c.JSON(http.StatusConflict, gin.H{"error": "邮箱已被注册"})
    return
}

// After:
existingUser, err := s.database.GetUserByEmail(req.Email)
if err == nil {
    if !existingUser.OTPVerified {
        // Return OTP to complete registration
        qrCodeURL := auth.GetOTPQRCodeURL(existingUser.OTPSecret, req.Email)
        c.JSON(http.StatusOK, gin.H{
            "user_id": existingUser.ID,
            "otp_secret": existingUser.OTPSecret,
            "qr_code_url": qrCodeURL,
            "message": "检测到未完成的注册,请继续完成OTP设置",
        })
        return
    }
    c.JSON(http.StatusConflict, gin.H{"error": "邮箱已被注册"})
    return
}
```

**Testing Scenario:**
1. User POST /api/register with email + password
2. User receives OTP QR code but closes browser (interrupts)
3. User POST /api/register again with same email + password
4.  Now returns original OTP instead of error
5. User can complete registration via /api/complete-registration

**Security:**
 No security issue - still requires OTP verification
 Only returns OTP for unverified accounts
 Password not validated on re-fetch (same as initial registration)

**Impact:**
 Users can recover from interrupted registration
 Better UX for registration flow
 No breaking changes to existing verified users

**API Changes:**
- POST /api/register response for unverified users:
  - Status: 200 OK (was: 409 Conflict)
  - Body includes: user_id, otp_secret, qr_code_url, message

Fixes #615

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* test(api): add comprehensive unit tests for OTP re-fetch logic

- Test OTP re-fetch logic for unverified users
- Test OTP verification state handling
- Test complete registration flow scenarios
- Test edge cases (ID=0, empty OTPSecret, verified users)

All 11 test cases passed, covering:
1. OTPRefetchLogic (3 cases): new user, unverified refetch, verified rejection
2. OTPVerificationStates (2 cases): verified/unverified states
3. RegistrationFlow (3 cases): first registration, interrupted resume, duplicate attempt
4. EdgeCases (3 cases): validates behavior with edge conditions

Related to PR #653 - ensures proper OTP re-fetch behavior for unverified users.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* style: apply go fmt after rebase

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

---------

Co-authored-by: ZhouYongyou <128128010+zhouyongyou@users.noreply.github.com>
Co-authored-by: Claude <noreply@anthropic.com>
2025-11-10 20:29:02 -05:00
..
2025-11-08 02:03:09 +08:00