Skip to content

Commit

Permalink
Version 7.1.0
Browse files Browse the repository at this point in the history
Version 7.1.0
  • Loading branch information
samtstern authored Nov 20, 2020
2 parents aef1d2f + 94e1005 commit 7f2d6a5
Show file tree
Hide file tree
Showing 14 changed files with 227 additions and 26 deletions.
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,16 +48,16 @@ libraries.
```groovy
dependencies {
// FirebaseUI for Firebase Realtime Database
implementation 'com.firebaseui:firebase-ui-database:7.0.0'
implementation 'com.firebaseui:firebase-ui-database:7.1.0'
// FirebaseUI for Cloud Firestore
implementation 'com.firebaseui:firebase-ui-firestore:7.0.0'
implementation 'com.firebaseui:firebase-ui-firestore:7.1.0'
// FirebaseUI for Firebase Auth
implementation 'com.firebaseui:firebase-ui-auth:7.0.0'
implementation 'com.firebaseui:firebase-ui-auth:7.1.0'
// FirebaseUI for Cloud Storage
implementation 'com.firebaseui:firebase-ui-storage:7.0.0'
implementation 'com.firebaseui:firebase-ui-storage:7.1.0'
}
```

Expand Down Expand Up @@ -244,4 +244,4 @@ accept your pull requests.
1. Submit a pull request targeting the latest dev branch.

[gh-actions]: https://github.com/firebase/FirebaseUI-Android/actions
[gh-actions-badge]: https://github.com/firebase/FirebaseUI-Android/workflows/Android%20CI/badge.svg
[gh-actions-badge]: https://github.com/firebase/FirebaseUI-Android/workflows/Android%20CI/badge.svg
2 changes: 1 addition & 1 deletion auth/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ Gradle, add the dependency:
```groovy
dependencies {
// ...
implementation 'com.firebaseui:firebase-ui-auth:7.0.0'
implementation 'com.firebaseui:firebase-ui-auth:7.1.0'
// Required only if Facebook login support is required
// Find the latest Facebook SDK releases here: https://github.com/facebook/facebook-android-sdk/blob/master/CHANGELOG.md
Expand Down
47 changes: 42 additions & 5 deletions auth/src/main/java/com/firebase/ui/auth/AuthUI.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,11 @@
import com.google.android.gms.auth.api.signin.GoogleSignIn;
import com.google.android.gms.auth.api.signin.GoogleSignInAccount;
import com.google.android.gms.auth.api.signin.GoogleSignInOptions;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GoogleApiAvailability;
import com.google.android.gms.common.api.ApiException;
import com.google.android.gms.common.api.CommonStatusCodes;
import com.google.android.gms.common.api.GoogleApi;
import com.google.android.gms.common.api.Scope;
import com.google.android.gms.tasks.Continuation;
import com.google.android.gms.tasks.Task;
Expand Down Expand Up @@ -340,6 +343,12 @@ public Task<AuthResult> silentSignIn(@NonNull Context context,
.getParcelable(ExtraConstants.GOOGLE_SIGN_IN_OPTIONS);
}

// If Play services are not available we can't attempt to use the credentials client.
if (!GoogleApiUtils.isPlayServicesAvailable(context)) {
return Tasks.forException(
new FirebaseUiException(ErrorCodes.PLAY_SERVICES_UPDATE_CANCELLED));
}

return GoogleApiUtils.getCredentialsClient(context)
.request(new CredentialRequest.Builder()
// We can support both email and Google at the same time here because they
Expand Down Expand Up @@ -392,8 +401,16 @@ public Task<AuthResult> then(
*/
@NonNull
public Task<Void> signOut(@NonNull Context context) {
Task<Void> maybeDisableAutoSignIn = GoogleApiUtils.getCredentialsClient(context)
.disableAutoSignIn()
boolean playServicesAvailable = GoogleApiUtils.isPlayServicesAvailable(context);
if (!playServicesAvailable) {
Log.w(TAG, "Google Play services not available during signOut");
}

Task<Void> maybeDisableAutoSignIn = playServicesAvailable
? GoogleApiUtils.getCredentialsClient(context).disableAutoSignIn()
: Tasks.forResult((Void) null);

maybeDisableAutoSignIn
.continueWith(new Continuation<Void, Void>() {
@Override
public Void then(@NonNull Task<Void> task) {
Expand Down Expand Up @@ -434,7 +451,7 @@ public Void then(@NonNull Task<Void> task) {
* @param context the calling {@link Context}.
*/
@NonNull
public Task<Void> delete(@NonNull Context context) {
public Task<Void> delete(@NonNull final Context context) {
final FirebaseUser currentUser = mAuth.getCurrentUser();
if (currentUser == null) {
return Tasks.forException(new FirebaseAuthInvalidUserException(
Expand All @@ -443,14 +460,19 @@ public Task<Void> delete(@NonNull Context context) {
}

final List<Credential> credentials = getCredentialsFromFirebaseUser(currentUser);
final CredentialsClient client = GoogleApiUtils.getCredentialsClient(context);

// Ensure the order in which tasks are executed properly destructures the user.
return signOutIdps(context).continueWithTask(new Continuation<Void, Task<Void>>() {
@Override
public Task<Void> then(@NonNull Task<Void> task) {
task.getResult(); // Propagate exception if there was one

if (!GoogleApiUtils.isPlayServicesAvailable(context)) {
Log.w(TAG, "Google Play services not available during delete");
return Tasks.forResult((Void) null);
}

final CredentialsClient client = GoogleApiUtils.getCredentialsClient(context);
List<Task<?>> credentialTasks = new ArrayList<>();
for (Credential credential : credentials) {
credentialTasks.add(client.delete(credential));
Expand Down Expand Up @@ -516,7 +538,11 @@ private Task<Void> signOutIdps(@NonNull Context context) {
if (ProviderAvailability.IS_FACEBOOK_AVAILABLE) {
LoginManager.getInstance().logOut();
}
return GoogleSignIn.getClient(context, GoogleSignInOptions.DEFAULT_SIGN_IN).signOut();
if (GoogleApiUtils.isPlayServicesAvailable(context)) {
return GoogleSignIn.getClient(context, GoogleSignInOptions.DEFAULT_SIGN_IN).signOut();
} else {
return Tasks.forResult((Void) null);
}
}

/**
Expand Down Expand Up @@ -732,6 +758,17 @@ public EmailBuilder setForceSameDevice() {
return this;
}

/**
* Sets a default sign in email, if the given email has been registered before, then
* it will ask the user for password, if the given email it's not registered, then
* it starts signing up the default email.
*/
@NonNull
public EmailBuilder setDefaultEmail(String email) {
getParams().putString(ExtraConstants.DEFAULT_EMAIL, email);
return this;
}

@Override
public IdpConfig build() {
if (super.mProviderId.equals(EMAIL_LINK_PROVIDER)) {
Expand Down
10 changes: 8 additions & 2 deletions auth/src/main/java/com/firebase/ui/auth/KickoffActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@
import com.google.android.gms.common.GoogleApiAvailability;
import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.android.gms.tasks.Task;
import com.google.android.gms.tasks.Tasks;
import com.google.firebase.auth.GoogleAuthProvider;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
Expand Down Expand Up @@ -53,8 +56,11 @@ protected void onFailure(@NonNull Exception e) {
}
});

GoogleApiAvailability.getInstance()
.makeGooglePlayServicesAvailable(this)
Task<Void> checkPlayServicesTask = getFlowParams().isPlayServicesRequired()
? GoogleApiAvailability.getInstance().makeGooglePlayServicesAvailable(this)
: Tasks.forResult((Void) null);

checkPlayServicesTask
.addOnSuccessListener(this, new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void aVoid) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,12 @@
import android.text.TextUtils;

import com.firebase.ui.auth.AuthMethodPickerLayout;
import com.firebase.ui.auth.AuthUI;
import com.firebase.ui.auth.AuthUI.IdpConfig;
import com.firebase.ui.auth.util.ExtraConstants;
import com.firebase.ui.auth.util.Preconditions;
import com.google.firebase.auth.ActionCodeSettings;
import com.google.firebase.auth.GoogleAuthProvider;

import java.util.Collections;
import java.util.List;
Expand Down Expand Up @@ -200,6 +202,23 @@ public boolean isAnonymousUpgradeEnabled() {
return enableAnonymousUpgrade;
}

public boolean isPlayServicesRequired() {
// Play services only required for Google Sign In and the Credentials API
return isProviderEnabled(GoogleAuthProvider.PROVIDER_ID)
|| enableHints
|| enableCredentials;
}

public boolean isProviderEnabled(@AuthUI.SupportedProvider String provider) {
for (AuthUI.IdpConfig idp : providers) {
if (idp.getProviderId().equals(provider)) {
return true;
}
}

return false;
}

public boolean shouldShowProviderChoice() {
return defaultProvider == null && (!isSingleProviderFlow() || alwaysShowProviderChoice);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,12 @@ protected void onCreate(@Nullable Bundle savedInstanceState) {
responseForLinking, forceSameDevice);
switchFragment(fragment, R.id.fragment_register_email, EmailLinkFragment.TAG);
} else {
AuthUI.IdpConfig emailConfig = ProviderUtils.getConfigFromIdps(
getFlowParams().providers, EmailAuthProvider.PROVIDER_ID);

if (emailConfig != null) {
email = emailConfig.getParams().getString(ExtraConstants.DEFAULT_EMAIL);;
}
// Start with check email
CheckEmailFragment fragment = CheckEmailFragment.newInstance(email);
switchFragment(fragment, R.id.fragment_register_email, CheckEmailFragment.TAG);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ public final class ExtraConstants {
public static final String CREDENTIAL = "extra_credential";

public static final String EMAIL = "extra_email";
public static final String DEFAULT_EMAIL = "extra_default_email";
public static final String ALLOW_NEW_EMAILS = "extra_allow_new_emails";
public static final String REQUIRE_NAME = "extra_require_name";
public static final String GOOGLE_SIGN_IN_OPTIONS = "extra_google_sign_in_options";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
import com.google.android.gms.auth.api.credentials.Credentials;
import com.google.android.gms.auth.api.credentials.CredentialsClient;
import com.google.android.gms.auth.api.credentials.CredentialsOptions;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GoogleApiAvailability;

import androidx.annotation.NonNull;
import androidx.annotation.RestrictTo;
Expand All @@ -16,6 +18,12 @@ private GoogleApiUtils() {
throw new AssertionError("No instance for you!");
}

public static boolean isPlayServicesAvailable(@NonNull Context context) {
return GoogleApiAvailability
.getInstance()
.isGooglePlayServicesAvailable(context) == ConnectionResult.SUCCESS;
}

@NonNull
public static CredentialsClient getCredentialsClient(@NonNull Context context) {
CredentialsOptions options = new CredentialsOptions.Builder()
Expand Down
15 changes: 14 additions & 1 deletion auth/src/test/java/com/firebase/ui/auth/AuthUITest.java
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ public void testPhoneBuilder_withValidDefaultNumberCode_expectSuccess() {
}

@Test
public void testPhoneBuilder_withBlacklistedCountryWithSameCountryCode_expectSucess() {
public void testPhoneBuilder_withBlacklistedCountryWithSameCountryCode_expectSuccess() {
new IdpConfig.PhoneBuilder()
.setDefaultNumber("+1123456789")
.setBlacklistedCountries(Arrays.asList("ca"))
Expand Down Expand Up @@ -333,6 +333,19 @@ public void testEmailBuilder_withAnonymousUpgradeAndNotForcingSameDevice_expectT
(actionCodeSettings).build();
}

@Test
public void testEmailBuilder_withSetDefaultEmail_expectSuccess() {
ActionCodeSettings actionCodeSettings = ActionCodeSettings.newBuilder().setUrl(URL).build();

IdpConfig config = new IdpConfig.EmailBuilder()
.setDefaultEmail(TestConstants.EMAIL)
.setActionCodeSettings(actionCodeSettings)
.build();

assertThat(config.getParams().getString(ExtraConstants.DEFAULT_EMAIL))
.isEqualTo(TestConstants.EMAIL);
}

@Test(expected = IllegalStateException.class)
public void testSignInIntentBuilder_anonymousUpgradeWithEmailLinkCrossDevice_expectThrows() {
ActionCodeSettings actionCodeSettings = ActionCodeSettings.newBuilder().setUrl(URL).build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,12 +126,13 @@ public static FlowParameters getFlowParameters(Collection<String> providerIds) {

public static FlowParameters getFlowParameters(Collection<String> providerIds,
boolean enableAnonymousUpgrade) {
return getFlowParameters(providerIds, enableAnonymousUpgrade, null);
return getFlowParameters(providerIds, enableAnonymousUpgrade, null, false);
}

public static FlowParameters getFlowParameters(Collection<String> providerIds,
boolean enableAnonymousUpgrade,
AuthMethodPickerLayout customLayout) {
AuthMethodPickerLayout customLayout,
boolean hasDefaultEmail) {
List<IdpConfig> idpConfigs = new ArrayList<>();
for (String providerId : providerIds) {
switch (providerId) {
Expand All @@ -153,7 +154,13 @@ public static FlowParameters getFlowParameters(Collection<String> providerIds,
.setHandleCodeInApp(true).build()).build());
break;
case EmailAuthProvider.PROVIDER_ID:
idpConfigs.add(new IdpConfig.EmailBuilder().build());
if (hasDefaultEmail) { idpConfigs.add(new IdpConfig.EmailBuilder()
.setDefaultEmail(TestConstants.EMAIL)
.build());
} else
{
idpConfigs.add(new IdpConfig.EmailBuilder().build());
}
break;
case PhoneAuthProvider.PROVIDER_ID:
idpConfigs.add(new IdpConfig.PhoneBuilder().build());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import com.firebase.ui.auth.testhelpers.TestHelper;
import com.firebase.ui.auth.util.ExtraConstants;
import com.firebase.ui.auth.util.data.EmailLinkPersistenceManager;
import com.google.android.material.textfield.TextInputEditText;
import com.google.android.material.textfield.TextInputLayout;
import com.google.firebase.auth.EmailAuthProvider;
import com.google.firebase.auth.GoogleAuthProvider;
Expand All @@ -34,6 +35,8 @@
import org.junit.runner.RunWith;
import org.robolectric.Robolectric;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.Shadows;
import org.robolectric.shadows.ShadowActivity;

import java.util.Collections;

Expand Down Expand Up @@ -73,7 +76,7 @@ public void testOnCreate_emailLinkLinkingFlow_expectSendEmailLinkFlowStarted() {
EmailLinkPersistenceManager.getInstance().saveEmail(ApplicationProvider.getApplicationContext(),
EMAIL, TestConstants.SESSION_ID, TestConstants.UID);

EmailActivity emailActivity = createActivity(AuthUI.EMAIL_LINK_PROVIDER, true);
EmailActivity emailActivity = createActivity(AuthUI.EMAIL_LINK_PROVIDER, true, false);

EmailLinkFragment fragment = (EmailLinkFragment) emailActivity
.getSupportFragmentManager().findFragmentByTag(EmailLinkFragment.TAG);
Expand Down Expand Up @@ -141,16 +144,59 @@ public void testSignUpButton_validatesFields() {
passwordLayout.getError().toString());
}

@Test
public void testSetDefaultEmail_validField() {
EmailActivity emailActivity = createActivity(EmailAuthProvider.PROVIDER_ID, false, true);

CheckEmailFragment fragment = (CheckEmailFragment) emailActivity
.getSupportFragmentManager().findFragmentByTag(CheckEmailFragment.TAG);
assertThat(fragment).isNotNull();

TextInputEditText email = emailActivity.findViewById(R.id.email);
assertEquals(TestConstants.EMAIL, email.getText().toString());

}

@Test
public void testSetDefaultEmail_expectWelcomeBackPasswordPrompt() {
EmailActivity emailActivity = createActivity(EmailAuthProvider.PROVIDER_ID, false, true);

emailActivity.onExistingEmailUser(new User.Builder(EmailAuthProvider.PROVIDER_ID, TestConstants.EMAIL).build());

ShadowActivity.IntentForResult nextIntent =
Shadows.shadowOf(emailActivity).getNextStartedActivityForResult();
assertEquals(WelcomeBackPasswordPrompt.class.getName(),
nextIntent.intent.getComponent().getClassName());

}

@Test
public void testSetDefaultEmail_expectRegisterEmailFragment() {
EmailActivity emailActivity = createActivity(EmailAuthProvider.PROVIDER_ID, false, true);

emailActivity.onNewUser(new User.Builder(EmailAuthProvider.PROVIDER_ID, TestConstants.EMAIL).build());

RegisterEmailFragment registerEmailFragment = (RegisterEmailFragment) emailActivity
.getSupportFragmentManager().findFragmentByTag(RegisterEmailFragment.TAG);
assertThat(registerEmailFragment).isNotNull();
}


private EmailActivity createActivity(String providerId) {
return createActivity(providerId, false);
return createActivity(providerId, false, false);
}

private EmailActivity createActivity(String providerId, boolean emailLinkLinkingFlow) {
private EmailActivity createActivity(String providerId, boolean emailLinkLinkingFlow, boolean hasDefaultEmail) {
Intent startIntent = EmailActivity.createIntent(
ApplicationProvider.getApplicationContext(),
TestHelper.getFlowParameters(Collections.singletonList(providerId)));

if (hasDefaultEmail) {
startIntent = EmailActivity.createIntent(
ApplicationProvider.getApplicationContext(),
TestHelper.getFlowParameters(Collections.singletonList(providerId), false, null, true));
}

if (emailLinkLinkingFlow) {
startIntent.putExtra(ExtraConstants.EMAIL, EMAIL);
startIntent.putExtra(ExtraConstants.IDP_RESPONSE, buildGoogleIdpResponse());
Expand Down
Loading

0 comments on commit 7f2d6a5

Please sign in to comment.