mirror of
https://github.com/NoFxAiOS/nofx.git
synced 2026-06-06 05:51:19 +08:00
fix: use completeRegistration for incomplete OTP setup in login flow
- LoginPage: call completeRegistration instead of verifyOTP when qrCodeURL exists - This ensures otp_verified is set to true for users completing OTP setup - Backend: reorder maxUsers check to allow existing incomplete users to continue - Backend: return OTP info when login with incomplete OTP setup
This commit is contained in:
@@ -2989,7 +2989,44 @@ func (s *Server) handleRegister(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
// Check max users limit
|
||||
var req struct {
|
||||
Email string `json:"email" binding:"required,email"`
|
||||
Password string `json:"password" binding:"required,min=6"`
|
||||
}
|
||||
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
SafeBadRequest(c, "Invalid request parameters")
|
||||
return
|
||||
}
|
||||
|
||||
// Check if email already exists (must check before maxUsers to allow incomplete OTP users)
|
||||
existingUser, err := s.store.User().GetByEmail(req.Email)
|
||||
if err == nil {
|
||||
// User exists, check OTP verification status
|
||||
if !existingUser.OTPVerified {
|
||||
// OTP not verified, verify password first for security
|
||||
if !auth.CheckPassword(req.Password, existingUser.PasswordHash) {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "Email or password incorrect"})
|
||||
return
|
||||
}
|
||||
// Password correct, allow user to continue OTP setup
|
||||
// Return existing OTP information
|
||||
qrCodeURL := auth.GetOTPQRCodeURL(existingUser.OTPSecret, req.Email)
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"user_id": existingUser.ID,
|
||||
"email": existingUser.Email,
|
||||
"otp_secret": existingUser.OTPSecret,
|
||||
"qr_code_url": qrCodeURL,
|
||||
"message": "Incomplete registration detected, please continue OTP setup",
|
||||
})
|
||||
return
|
||||
}
|
||||
// OTP already verified, reject duplicate registration
|
||||
c.JSON(http.StatusConflict, gin.H{"error": "Email already registered"})
|
||||
return
|
||||
}
|
||||
|
||||
// Check max users limit (only for new users)
|
||||
maxUsers := config.Get().MaxUsers
|
||||
if maxUsers > 0 {
|
||||
userCount, err := s.store.User().Count()
|
||||
@@ -3003,23 +3040,6 @@ func (s *Server) handleRegister(c *gin.Context) {
|
||||
}
|
||||
}
|
||||
|
||||
var req struct {
|
||||
Email string `json:"email" binding:"required,email"`
|
||||
Password string `json:"password" binding:"required,min=6"`
|
||||
}
|
||||
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
SafeBadRequest(c, "Invalid request parameters")
|
||||
return
|
||||
}
|
||||
|
||||
// Check if email already exists
|
||||
_, err := s.store.User().GetByEmail(req.Email)
|
||||
if err == nil {
|
||||
c.JSON(http.StatusConflict, gin.H{"error": "Email already registered"})
|
||||
return
|
||||
}
|
||||
|
||||
// Generate password hash
|
||||
passwordHash, err := auth.HashPassword(req.Password)
|
||||
if err != nil {
|
||||
@@ -3141,10 +3161,15 @@ func (s *Server) handleLogin(c *gin.Context) {
|
||||
|
||||
// Check if OTP is verified
|
||||
if !user.OTPVerified {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{
|
||||
"error": "Account has not completed OTP setup",
|
||||
// Return OTP info so user can complete setup
|
||||
qrCodeURL := auth.GetOTPQRCodeURL(user.OTPSecret, user.Email)
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"user_id": user.ID,
|
||||
"email": user.Email,
|
||||
"otp_secret": user.OTPSecret,
|
||||
"qr_code_url": qrCodeURL,
|
||||
"requires_otp_setup": true,
|
||||
"message": "Please complete OTP setup first",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user