Skip to content

fix: resolve bounty issue #5 - save user data before sign out on email collision#16

Open
bomlinux92-byte wants to merge 2 commits into
allknowledge34:mainfrom
bomlinux92-byte:bounty-fix-5-0519
Open

fix: resolve bounty issue #5 - save user data before sign out on email collision#16
bomlinux92-byte wants to merge 2 commits into
allknowledge34:mainfrom
bomlinux92-byte:bounty-fix-5-0519

Conversation

@bomlinux92-byte
Copy link
Copy Markdown

@bomlinux92-byte bomlinux92-byte commented May 19, 2026

Summary

Fix for [BOUNTY /usr/bin/bash.40] Login fails with "Invalid Email" after successful signup and OTP verification — Issue #5

Root cause

When a user signs up with phone+email and the email already exists in Firebase Auth (FirebaseAuthUserCollisionException), the original code would:

  1. Sign out the phone-only account immediately
  2. Redirect to login with prefilled email

The problem: user data (name, phone, etc.) was never saved to Firestore, so when the user logs in with the existing email account, their profile data is missing and the login fails with "Invalid Email" error.

Fix

Create a new saveUserToFirestoreOnCollision() method that:

  1. Saves user data to Firestore FIRST (using the phone auth UID)
  2. Then signs out the phone-only account
  3. Then redirects to login with prefilled email

This ensures the user's profile data is preserved even when the email linking fails due to an existing account.

Changes

  • Added saveUserToFirestoreOnCollision() method in OTPActivity.java
  • When FirebaseAuthUserCollisionException occurs, user data is saved to Firestore BEFORE sign out
  • Original saveUserToFirestoreAndContinue() method is unchanged for normal flow

Closes #5

Summary by CodeRabbit

  • New Features
    • Enhanced email conflict handling during phone-based authentication. When an email collision occurs, user registration data is automatically preserved and users are redirected to the login screen with their email address pre-filled. This streamlines the account recovery process and reduces the need for manual re-entry of credentials.

Review Change Stack

hermes@bounty.hunter added 2 commits May 15, 2026 00:20
…ollisionException properly

When email linking fails with FirebaseAuthUserCollisionException, the user
was left with a phone-only account that cannot login with email/password.

Fix: sign out the orphaned phone-only account and redirect to login screen
with the email pre-filled, so the user can login with the existing account.
…gn out on email collision

When a user signs up with phone+email and the email already exists
in Firebase Auth (FirebaseAuthUserCollisionException), the original
code would:
1. Sign out the phone-only account immediately
2. Redirect to login with prefilled email

The problem: user data (name, phone, etc.) was never saved to
Firestore, so when the user logs in with the existing email account,
their profile data is missing.

Fix: Create a new saveUserToFirestoreOnCollision() method that:
1. Saves user data to Firestore FIRST (using the phone auth UID)
2. Then signs out the phone-only account
3. Then redirects to login with prefilled email

This ensures the user's profile data is preserved even when the
email linking fails due to an existing account.
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 19, 2026

📝 Walkthrough

Walkthrough

OTPActivity now handles email-linking collisions by persisting user data to Firestore before signing out and redirecting to LoginActivity with the conflicting email prefilled. LoginActivity receives and pre-populates that email field on open.

Changes

Email Collision Redirect with Prefill

Layer / File(s) Summary
OTPActivity email collision and Firestore persistence
app/src/main/java/com/example/updateapp/views/activites/OTPActivity.java
FirebaseAuthUserCollisionException handler now invokes saveUserToFirestoreOnCollision(...), which normalizes user fields, writes a UserModel to Firestore, dismisses the loading dialog, signs out, and starts LoginActivity with prefilled_email; success/failure outcomes emit different toast messages.
LoginActivity prefilled email population
app/src/main/java/com/example/updateapp/views/activites/LoginActivity.java
onCreate extracts the optional prefilled_email intent extra and pre-populates binding.edtEmail if the value is non-null and non-empty.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 A collision once sparked, now gently resolved,
User data to Firestore, smoothly involved!
LoginActivity waits with email in hand,
A prefilled embrace, as planned and as planned.
hops

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically describes the main change: adding data persistence before sign-out when email collision occurs, which is the core fix in both OTPActivity and LoginActivity modifications.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
app/src/main/java/com/example/updateapp/views/activites/OTPActivity.java (1)

224-226: 💤 Low value

Hardcoded English strings break i18n.

The toast messages on lines 225-226 and 235-236 use hardcoded English strings while the rest of the codebase uses string resources (e.g., getString(R.string.xxx)). Consider extracting these to strings.xml for consistency with the existing localization pattern.

Also applies to: 235-237

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/src/main/java/com/example/updateapp/views/activites/OTPActivity.java`
around lines 224 - 226, The two Toasts in OTPActivity (the Toast.makeText calls
in OTPActivity.java that show "An account with this email already exists..." and
the other hardcoded message around lines 235-237) use hardcoded English strings;
extract both messages into string resources in strings.xml and replace the
literals with getString(R.string.<name>) calls in OTPActivity (e.g.,
R.string.email_exists_message and R.string.other_toast_message) so they follow
the app's i18n pattern and can be translated.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@app/src/main/java/com/example/updateapp/views/activites/OTPActivity.java`:
- Around line 202-243: In saveUserToFirestoreOnCollision, the method parameters
(name, email, number, password) are reassigned and then captured by lambdas
causing a compile error because they are not effectively final; fix by replacing
the conditional reassignments with new final local variables (e.g., final String
safeName = (name == null ? "" : name), final String safeEmail = (email == null ?
"" : email), etc.) and use these final locals in the UserModel constructor and
inside the addOnSuccessListener/addOnFailureListener callbacks so the lambdas
capture effectively final variables.
- Line 213: Replace the hardcoded invalid profile URL that contains "token=***"
with the real token used elsewhere (or extract to a shared constant) so both
usages reference the same value; create a private static final String (e.g.,
DEFAULT_PROFILE_URL) and use that constant in OTPActivity where the placeholder
string appears and in the other location that currently uses the actual token to
prevent broken profile images and duplication.

---

Nitpick comments:
In `@app/src/main/java/com/example/updateapp/views/activites/OTPActivity.java`:
- Around line 224-226: The two Toasts in OTPActivity (the Toast.makeText calls
in OTPActivity.java that show "An account with this email already exists..." and
the other hardcoded message around lines 235-237) use hardcoded English strings;
extract both messages into string resources in strings.xml and replace the
literals with getString(R.string.<name>) calls in OTPActivity (e.g.,
R.string.email_exists_message and R.string.other_toast_message) so they follow
the app's i18n pattern and can be translated.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: d7987af6-d0d4-4192-a56a-62939eb611d6

📥 Commits

Reviewing files that changed from the base of the PR and between 2f5069d and d0f7126.

📒 Files selected for processing (2)
  • app/src/main/java/com/example/updateapp/views/activites/LoginActivity.java
  • app/src/main/java/com/example/updateapp/views/activites/OTPActivity.java

Comment on lines +202 to +243
private void saveUserToFirestoreOnCollision(String uid, String name, String email, String number, String password) {
if (name == null) name = "";
if (email == null) email = "";
if (number == null) number = "";
if (password == null) password = "";

UserModel user = new UserModel(
name,
email,
number,
password,
"https://firebasestorage.googleapis.com/v0/b/earning-b8942.firebasestorage.app/o/account.png?alt=media&token=***"
);

if (dialog.isShowing()) dialog.dismiss();

firestore.collection("users")
.document(uid)
.set(user)
.addOnSuccessListener(unused -> {
// User data saved successfully. Now sign out and redirect to login.
auth.signOut();
Toast.makeText(OTPActivity.this,
"An account with this email already exists. Please login with your email and password.",
Toast.LENGTH_LONG).show();
Intent intent = new Intent(OTPActivity.this, LoginActivity.class);
intent.putExtra("prefilled_email", email);
startActivity(intent);
finish();
})
.addOnFailureListener(e -> {
// Failed to save - still redirect to login with email prefilled.
auth.signOut();
Toast.makeText(OTPActivity.this,
"Failed to link email: " + e.getMessage() + ". Please login with your existing account.",
Toast.LENGTH_LONG).show();
Intent intent = new Intent(OTPActivity.this, LoginActivity.class);
intent.putExtra("prefilled_email", email);
startActivity(intent);
finish();
});
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Compile error: email is not effectively final.

The parameters name, email, number, and password are conditionally reassigned (lines 203-206), then email is captured in lambda callbacks (lines 228, 239). Java requires variables used in lambdas to be effectively final. This code will fail to compile.

🐛 Proposed fix using final local variables
 private void saveUserToFirestoreOnCollision(String uid, String name, String email, String number, String password) {
-    if (name == null) name = "";
-    if (email == null) email = "";
-    if (number == null) number = "";
-    if (password == null) password = "";
+    final String safeName = (name == null) ? "" : name;
+    final String safeEmail = (email == null) ? "" : email;
+    final String safeNumber = (number == null) ? "" : number;
+    final String safePassword = (password == null) ? "" : password;

     UserModel user = new UserModel(
-            name,
-            email,
-            number,
-            password,
+            safeName,
+            safeEmail,
+            safeNumber,
+            safePassword,
             "https://firebasestorage.googleapis.com/v0/b/earning-b8942.firebasestorage.app/o/account.png?alt=media&token=***"
     );

     if (dialog.isShowing()) dialog.dismiss();

     firestore.collection("users")
             .document(uid)
             .set(user)
             .addOnSuccessListener(unused -> {
                 // User data saved successfully. Now sign out and redirect to login.
                 auth.signOut();
                 Toast.makeText(OTPActivity.this,
                         "An account with this email already exists. Please login with your email and password.",
                         Toast.LENGTH_LONG).show();
                 Intent intent = new Intent(OTPActivity.this, LoginActivity.class);
-                intent.putExtra("prefilled_email", email);
+                intent.putExtra("prefilled_email", safeEmail);
                 startActivity(intent);
                 finish();
             })
             .addOnFailureListener(e -> {
                 // Failed to save - still redirect to login with email prefilled.
                 auth.signOut();
                 Toast.makeText(OTPActivity.this,
                         "Failed to link email: " + e.getMessage() + ". Please login with your existing account.",
                         Toast.LENGTH_LONG).show();
                 Intent intent = new Intent(OTPActivity.this, LoginActivity.class);
-                intent.putExtra("prefilled_email", email);
+                intent.putExtra("prefilled_email", safeEmail);
                 startActivity(intent);
                 finish();
             });
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/src/main/java/com/example/updateapp/views/activites/OTPActivity.java`
around lines 202 - 243, In saveUserToFirestoreOnCollision, the method parameters
(name, email, number, password) are reassigned and then captured by lambdas
causing a compile error because they are not effectively final; fix by replacing
the conditional reassignments with new final local variables (e.g., final String
safeName = (name == null ? "" : name), final String safeEmail = (email == null ?
"" : email), etc.) and use these final locals in the UserModel constructor and
inside the addOnSuccessListener/addOnFailureListener callbacks so the lambdas
capture effectively final variables.

email,
number,
password,
"https://firebasestorage.googleapis.com/v0/b/earning-b8942.firebasestorage.app/o/account.png?alt=media&token=***"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Placeholder token will produce broken profile images.

The image URL uses token=*** while the existing method at line 257 uses the actual token. Users created through the collision flow will have invalid profile image URLs. Use the same token or extract the URL to a constant.

🐛 Proposed fix
-            "https://firebasestorage.googleapis.com/v0/b/earning-b8942.firebasestorage.app/o/account.png?alt=media&token=***"
+            "https://firebasestorage.googleapis.com/v0/b/earning-b8942.firebasestorage.app/o/account.png?alt=media&token=0ef08dd9-6b13-4da2-a39f-500cff3cf4f0"

Consider extracting this URL to a constant to avoid duplication:

private static final String DEFAULT_PROFILE_URL = 
    "https://firebasestorage.googleapis.com/v0/b/earning-b8942.firebasestorage.app/o/account.png?alt=media&token=0ef08dd9-6b13-4da2-a39f-500cff3cf4f0";
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"https://firebasestorage.googleapis.com/v0/b/earning-b8942.firebasestorage.app/o/account.png?alt=media&token=***"
"https://firebasestorage.googleapis.com/v0/b/earning-b8942.firebasestorage.app/o/account.png?alt=media&token=0ef08dd9-6b13-4da2-a39f-500cff3cf4f0"
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/src/main/java/com/example/updateapp/views/activites/OTPActivity.java` at
line 213, Replace the hardcoded invalid profile URL that contains "token=***"
with the real token used elsewhere (or extract to a shared constant) so both
usages reference the same value; create a private static final String (e.g.,
DEFAULT_PROFILE_URL) and use that constant in OTPActivity where the placeholder
string appears and in the other location that currently uses the actual token to
prevent broken profile images and duplication.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

$0.4 Bounty : Login fails with "Invalid Email" after successful signup and OTP verification

1 participant