Skip to content

Commit 2ada82a

Browse files
Implemented custom password reset link (#1850)
1 parent c3badea commit 2ada82a

File tree

7 files changed

+92
-6
lines changed

7 files changed

+92
-6
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
- Add ability to always skip provider choice (#1825) (contributed by @ubragg)
22
- Fix a bug with `isNewUser` for some providers (#1737) (contributed by @laurentiu-git)
33
- Add ability to lock the Orientation (#1834) (contributed by @laurentiu-git)
4+
- Add ability to customize password reset (#1747) (contributed by @laurentiu-git)

auth/src/main/java/com/firebase/ui/auth/AuthUI.java

+13
Original file line numberDiff line numberDiff line change
@@ -1211,6 +1211,7 @@ private abstract class AuthIntentBuilder<T extends AuthIntentBuilder> {
12111211
boolean mEnableCredentials = true;
12121212
boolean mEnableHints = true;
12131213
AuthMethodPickerLayout mAuthMethodPickerLayout = null;
1214+
ActionCodeSettings mPasswordSettings = null;
12141215

12151216
/**
12161217
* Specifies the theme to use for the application flow. If no theme is specified, a
@@ -1406,6 +1407,17 @@ public T setLockOrientation(boolean lockOrientation) {
14061407
return (T) this;
14071408
}
14081409

1410+
/**
1411+
* Set custom settings for the RecoverPasswordActivity.
1412+
*
1413+
* @param passwordSettings to allow additional state via a continue URL.
1414+
*/
1415+
@NonNull
1416+
public T setResetPasswordSettings(ActionCodeSettings passwordSettings) {
1417+
mPasswordSettings = passwordSettings;
1418+
return (T) this;
1419+
}
1420+
14091421
@CallSuper
14101422
@NonNull
14111423
public Intent build() {
@@ -1485,6 +1497,7 @@ protected FlowParameters getFlowParams() {
14851497
mAlwaysShowProviderChoice,
14861498
mLockOrientation,
14871499
mEmailLink,
1500+
mPasswordSettings,
14881501
mAuthMethodPickerLayout);
14891502
}
14901503
}

auth/src/main/java/com/firebase/ui/auth/data/model/FlowParameters.java

+9
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import com.firebase.ui.auth.AuthUI.IdpConfig;
2323
import com.firebase.ui.auth.util.ExtraConstants;
2424
import com.firebase.ui.auth.util.Preconditions;
25+
import com.google.firebase.auth.ActionCodeSettings;
2526

2627
import java.util.Collections;
2728
import java.util.List;
@@ -55,6 +56,7 @@ public FlowParameters createFromParcel(Parcel in) {
5556
boolean alwaysShowProviderChoice = in.readInt() != 0;
5657
boolean lockOrientation = in.readInt() != 0;
5758
String emailLink = in.readString();
59+
ActionCodeSettings passwordResetSettings = in.readParcelable(ActionCodeSettings.class.getClassLoader());
5860
AuthMethodPickerLayout customLayout = in.readParcelable(AuthMethodPickerLayout.class.getClassLoader());
5961

6062
return new FlowParameters(
@@ -71,6 +73,7 @@ public FlowParameters createFromParcel(Parcel in) {
7173
alwaysShowProviderChoice,
7274
lockOrientation,
7375
emailLink,
76+
passwordResetSettings,
7477
customLayout);
7578
}
7679

@@ -104,6 +107,9 @@ public FlowParameters[] newArray(int size) {
104107
@Nullable
105108
public String emailLink;
106109

110+
@Nullable
111+
public final ActionCodeSettings passwordResetSettings;
112+
107113
public final boolean enableCredentials;
108114
public final boolean enableHints;
109115
public final boolean enableAnonymousUpgrade;
@@ -127,6 +133,7 @@ public FlowParameters(
127133
boolean alwaysShowProviderChoice,
128134
boolean lockOrientation,
129135
@Nullable String emailLink,
136+
@Nullable ActionCodeSettings passwordResetSettings,
130137
@Nullable AuthMethodPickerLayout authMethodPickerLayout) {
131138
this.appName = Preconditions.checkNotNull(appName, "appName cannot be null");
132139
this.providers = Collections.unmodifiableList(
@@ -142,6 +149,7 @@ public FlowParameters(
142149
this.alwaysShowProviderChoice = alwaysShowProviderChoice;
143150
this.lockOrientation = lockOrientation;
144151
this.emailLink = emailLink;
152+
this.passwordResetSettings = passwordResetSettings;
145153
this.authMethodPickerLayout = authMethodPickerLayout;
146154
}
147155

@@ -167,6 +175,7 @@ public void writeToParcel(Parcel dest, int flags) {
167175
dest.writeInt(alwaysShowProviderChoice ? 1 : 0);
168176
dest.writeInt(lockOrientation ? 1 : 0);
169177
dest.writeString(emailLink);
178+
dest.writeParcelable(passwordResetSettings, flags);
170179
dest.writeParcelable(authMethodPickerLayout, flags);
171180
}
172181

auth/src/main/java/com/firebase/ui/auth/ui/email/RecoverPasswordActivity.java

+10-1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import com.firebase.ui.auth.viewmodel.ResourceObserver;
3535
import com.firebase.ui.auth.viewmodel.email.RecoverPasswordHandler;
3636
import com.google.android.material.textfield.TextInputLayout;
37+
import com.google.firebase.auth.ActionCodeSettings;
3738
import com.google.firebase.auth.FirebaseAuthInvalidCredentialsException;
3839
import com.google.firebase.auth.FirebaseAuthInvalidUserException;
3940

@@ -118,10 +119,18 @@ public void onClick(View view) {
118119
@Override
119120
public void onDonePressed() {
120121
if (mEmailFieldValidator.validate(mEmailEditText.getText())) {
121-
mHandler.startReset(mEmailEditText.getText().toString());
122+
if (getFlowParams().passwordResetSettings != null) {
123+
resetPassword(mEmailEditText.getText().toString(), getFlowParams().passwordResetSettings);
124+
}
125+
else {
126+
resetPassword(mEmailEditText.getText().toString(), null);
127+
}
122128
}
123129
}
124130

131+
private void resetPassword(String email, @Nullable ActionCodeSettings passwordResetSettings) {
132+
mHandler.startReset(email, passwordResetSettings);
133+
}
125134
private void showEmailSentDialog(String email) {
126135
new AlertDialog.Builder(this)
127136
.setTitle(R.string.fui_title_confirm_recover_password)

auth/src/main/java/com/firebase/ui/auth/viewmodel/email/RecoverPasswordHandler.java

+8-3
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@
66
import com.firebase.ui.auth.viewmodel.AuthViewModelBase;
77
import com.google.android.gms.tasks.OnCompleteListener;
88
import com.google.android.gms.tasks.Task;
9+
import com.google.firebase.auth.ActionCodeSettings;
910

1011
import androidx.annotation.NonNull;
12+
import androidx.annotation.Nullable;
1113
import androidx.annotation.RestrictTo;
1214

1315
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
@@ -16,10 +18,13 @@ public RecoverPasswordHandler(Application application) {
1618
super(application);
1719
}
1820

19-
public void startReset(@NonNull final String email) {
21+
public void startReset(@NonNull final String email, @Nullable ActionCodeSettings actionCodeSettings) {
2022
setResult(Resource.<String>forLoading());
21-
getAuth().sendPasswordResetEmail(email)
22-
.addOnCompleteListener(new OnCompleteListener<Void>() {
23+
Task<Void> reset = actionCodeSettings != null
24+
? getAuth().sendPasswordResetEmail(email, actionCodeSettings)
25+
: getAuth().sendPasswordResetEmail(email);
26+
27+
reset.addOnCompleteListener(new OnCompleteListener<Void>() {
2328
@Override
2429
public void onComplete(@NonNull Task<Void> task) {
2530
Resource<String> resource = task.isSuccessful()

auth/src/test/java/com/firebase/ui/auth/testhelpers/TestHelper.java

+1
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,7 @@ public static FlowParameters getFlowParameters(Collection<String> providerIds,
168168
false,
169169
true,
170170
null,
171+
null,
171172
customLayout);
172173
}
173174

auth/src/test/java/com/firebase/ui/auth/viewmodel/RecoverPasswordHandlerTest.java

+50-2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import com.firebase.ui.auth.testhelpers.TestConstants;
1010
import com.firebase.ui.auth.testhelpers.TestHelper;
1111
import com.firebase.ui.auth.viewmodel.email.RecoverPasswordHandler;
12+
import com.google.firebase.auth.ActionCodeSettings;
1213
import com.google.firebase.auth.EmailAuthProvider;
1314
import com.google.firebase.auth.FirebaseAuth;
1415

@@ -39,6 +40,8 @@ public class RecoverPasswordHandlerTest {
3940

4041
private RecoverPasswordHandler mHandler;
4142

43+
private ActionCodeSettings mPasswordResetSettings;
44+
4245
@Before
4346
public void setUp() {
4447
TestHelper.initialize();
@@ -49,6 +52,12 @@ public void setUp() {
4952
FlowParameters testParams = TestHelper.getFlowParameters(Collections.singletonList(
5053
EmailAuthProvider.PROVIDER_ID));
5154
mHandler.initializeForTesting(testParams, mMockAuth, null, null);
55+
56+
mPasswordResetSettings = ActionCodeSettings.newBuilder()
57+
.setAndroidPackageName("com.firebase.uidemo", true, null)
58+
.setHandleCodeInApp(true)
59+
.setUrl("https://google.com")
60+
.build();
5261
}
5362

5463
@Test
@@ -59,7 +68,7 @@ public void testReset_sendsRecoverEmail() {
5968

6069
// Begin observation, then send the email
6170
mHandler.getOperation().observeForever(mObserver);
62-
mHandler.startReset(TestConstants.EMAIL);
71+
mHandler.startReset(TestConstants.EMAIL, null);
6372

6473
// Should get in-progress resource
6574
verify(mObserver).onChanged(argThat(ResourceMatchers.<String>isLoading()));
@@ -79,7 +88,7 @@ public void testReset_propagatesFailure() {
7988

8089
// Begin observation, then send the email
8190
mHandler.getOperation().observeForever(mObserver);
82-
mHandler.startReset(TestConstants.EMAIL);
91+
mHandler.startReset(TestConstants.EMAIL, null);
8392

8493
// Should get in-progress resource
8594
verify(mObserver).onChanged(argThat(ResourceMatchers.<String>isLoading()));
@@ -91,4 +100,43 @@ public void testReset_propagatesFailure() {
91100
verify(mObserver).onChanged(argThat(ResourceMatchers.<String>isFailure()));
92101
}
93102

103+
@Test
104+
public void testReset_sendsCustomRecoverEmail() {
105+
// Send password email succeeds
106+
when(mMockAuth.sendPasswordResetEmail(TestConstants.EMAIL, mPasswordResetSettings ))
107+
.thenReturn(AutoCompleteTask.<Void>forSuccess(null));
108+
109+
// Begin observation, then send the email
110+
mHandler.getOperation().observeForever(mObserver);
111+
mHandler.startReset(TestConstants.EMAIL, mPasswordResetSettings);
112+
113+
// Should get in-progress resource
114+
verify(mObserver).onChanged(argThat(ResourceMatchers.<String>isLoading()));
115+
116+
// Firebase auth should be called
117+
verify(mMockAuth).sendPasswordResetEmail(TestConstants.EMAIL, mPasswordResetSettings);
118+
119+
// Should get the success resource
120+
verify(mObserver).onChanged(argThat(ResourceMatchers.<String>isSuccess()));
121+
}
122+
123+
@Test
124+
public void testCustomReset_propagatesFailure() {
125+
// Send password email fails
126+
when(mMockAuth.sendPasswordResetEmail(TestConstants.EMAIL, mPasswordResetSettings))
127+
.thenReturn(AutoCompleteTask.<Void>forFailure(new Exception("FAILED")));
128+
129+
// Begin observation, then send the email
130+
mHandler.getOperation().observeForever(mObserver);
131+
mHandler.startReset(TestConstants.EMAIL, mPasswordResetSettings);
132+
133+
// Should get in-progress resource
134+
verify(mObserver).onChanged(argThat(ResourceMatchers.<String>isLoading()));
135+
136+
// Firebase auth should be called
137+
verify(mMockAuth).sendPasswordResetEmail(TestConstants.EMAIL, mPasswordResetSettings);
138+
139+
// Should get the success resource
140+
verify(mObserver).onChanged(argThat(ResourceMatchers.<String>isFailure()));
141+
}
94142
}

0 commit comments

Comments
 (0)