Skip to content

Specify additonal scopes through code rather than config.xml #342

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Oct 17, 2016

Conversation

amandle
Copy link
Contributor

@amandle amandle commented Oct 6, 2016

No description provided.

@samtstern
Copy link
Contributor

For scopes-only this approach LGTM, but I think we can give ourselves more breathing room if we instead have SignInIntentBuilder take some sort of IDPConfig<> object which has fields, one of which is a List<String> of scopes.

Then instead of calls to setProviders() and setAdditionalGoogleScopes() you could do something like enableProvider(GOOGLE_PROVIDER, mGoogleIdpConfig) or even have one method for each IDP like enableGoogleProvider(mGoogleIdpConfig).

This way if we want to add more customization in the future (IDPs can change underneath us) we don't need a breaking API change, we just add a new field to IDPConfig. It also makes the availability of the options clearer if you pass them at the time of enabling the IDP. This is like how in GmsCore with GoogleApiClient you do .addApi(mApi, mApiOptions).

@amandle
Copy link
Contributor Author

amandle commented Oct 8, 2016

I refactored quite heavily. There is now an IdpConfig class as you suggested, and setProviders takes a list of them. So as not to have two classes doing pretty much the same thing, and since the new IdpConfig class needs to be publicly available I removed IDPProviderParcel and replaced it with the IdpConfig class. This cleans things up a bit. This is kind of a large change now, apologies about that.

Copy link
Contributor

@samtstern samtstern left a comment

Choose a reason for hiding this comment

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

This refactor looks really good, thanks! A few comments about how we can go even further.


protected IdpConfig(Parcel in) {
mProviderId = in.readString();
mScopes = in.createStringArrayList();
Copy link
Contributor

Choose a reason for hiding this comment

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

This creates a new one, but it should read the value instead.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

createStringArrayList actually does read the list, it just handles the creation of the list for you: https://developer.android.com/reference/android/os/Parcel.html#createStringArrayList()

Copy link
Contributor

Choose a reason for hiding this comment

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

Whoops, TIL!

* https://developers.facebook.com/docs/facebook-login/android
* https://developers.facebook.com/docs/facebook-login/permissions
*
* For Google permissions see:
Copy link
Contributor

Choose a reason for hiding this comment

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

What about twitter?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Twitter scopes are configured only through the developer console. I will add that to the comment.

/**
* Builder for the intent to start the user authentication flow.
*/
public final class SignInIntentBuilder {
private int mLogo = NO_LOGO;
private int mTheme = getDefaultTheme();
private List<String> mProviders = Collections.singletonList(EMAIL_PROVIDER);
private List<IdpConfig> mProviders = new ArrayList<>();
Copy link
Contributor

@samtstern samtstern Oct 10, 2016

Choose a reason for hiding this comment

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

Should this be a set? Seems like you want set-like properties in subsequent logic.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We do need set like properties, but we also need to retain the order. It looks like LinkedHashSet will do what we want.

public FacebookProvider (Context appContext, IDPProviderParcel facebookParcel) {
public FacebookProvider (
Context appContext,
List<String> scopes) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Why not just pass through the IDPConfig here? That way you only have to change this once.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

public GoogleProvider(FragmentActivity activity, IDPProviderParcel parcel, @Nullable String email) {
public GoogleProvider(
FragmentActivity activity,
@Nullable String email,
Copy link
Contributor

Choose a reason for hiding this comment

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

Same question here about just passing IDPConfig (and elsewhere, I'll stop repeating myself)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

mActivity = activity;
String mClientId = parcel.getProviderExtra().getString(CLIENT_ID_KEY);
String mClientId = activity.getString(R.string.default_web_client_id);
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this equivalent behavior before? What if they want to pass another client ID?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The behavior is the same, the clientId is still read from config.xml if they want to change it (same as before) but we are not sticking in a parcel and then reading it back, we're just using it directly.

* In the simplest case, you can supply the provider ID and build the config like this:
* {@code new IdpConfig.Builder(AuthUI.GOOGLE_PROVIDER).build()}
*/
public static class IdpConfig implements Parcelable {
Copy link
Contributor

Choose a reason for hiding this comment

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

Would it be better if each provider had a subclass of this? so new GoogleIdpConfig.Builder().build(), etc. This way you have more control over provider differences. For example doesn't look like you're supporting Twitter scopes so that builder would not have setScopes(). It would also hide the GOOGLE_PROVIDER and other Strings from the dev.

This one is up to you, I can see arguments both ways.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I tried this, but it makes parceling and passing a list of providers around much uglier. I would prefer to keep it this way.

Copy link
Contributor

Choose a reason for hiding this comment

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

Ok that's a good reason, keeping it as it is SGTM.

} else {
mScopes = scopes;
}
String applicationId = appContext.getString(R.string.facebook_application_id);
Copy link
Contributor

Choose a reason for hiding this comment

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

If you took my suggestion of IdpConfig subclasses, these strings could be part of the builders and we could eliminate the resource-based config entirely.

@@ -62,8 +65,7 @@ public GoogleProvider(FragmentActivity activity, IDPProviderParcel parcel, @Null
.requestIdToken(mClientId);

// Add additional scopes
String[] extraScopes = mActivity.getResources().getStringArray(R.array.google_permissions);
Copy link
Contributor

Choose a reason for hiding this comment

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

Bonus points: since we're removing these scopes as resources, maybe we could log a big warning message if we see them defined and they're non empty. Something like "DEVELOPER_WARNING: you have defined R.array.google_permissions but that is no longer respected as of FirebaseUI 1.0.0. See README"

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good idea, added.

@samtstern
Copy link
Contributor

Also I merged master into version-1.0.0-dev today, I forgot this PR was outstanding so I apologize if there are conflicts for you (they should be simple if there are any)

Copy link
Contributor

@samtstern samtstern left a comment

Choose a reason for hiding this comment

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

One last comment but LGTM!


if (appContext.getResources().getIdentifier(
"google_permissions", "array", appContext.getPackageName()) != 0) {
Log.w(TAG, "DEVELOPER WARNING: You have defined R.array.facebook_permissions but that"
Copy link
Contributor

Choose a reason for hiding this comment

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

This says facebook_permissions in one place and google_permissions in another.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oops, good catch.

@@ -229,22 +234,22 @@
* Provider identifier for email and password credentials, for use with
* {@link SignInIntentBuilder#setProviders}.
*/
public static final String EMAIL_PROVIDER = "email";
public static final String EMAIL_PROVIDER = EmailAuthProvider.PROVIDER_ID;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

We had discussed this change previously and I was against it then, but since we are now exposing IdpConfig to the user of the library, the mapping is necessarily one to one, so I think this change makes sense now.

Copy link
Contributor

Choose a reason for hiding this comment

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

Agreed, seems like a sensible change.

@samtstern
Copy link
Contributor

@amandle FYI you can carry my approval through from before. Merge when ready and the tests are green.

@SUPERCILEX
Copy link
Collaborator

@amandle Travis failed with exit code 137. I've been having that issue too, just restart the build or push some whitespace to get it going again. It's really random, but apparently it has something to do with the Travis sandbox only having 3GB of RAM available and us exceeding that.

@amandle
Copy link
Contributor Author

amandle commented Oct 16, 2016

@SUPERCILEX Thanks, I'll give that a try!

@SUPERCILEX
Copy link
Collaborator

@amandle I did some more Googling: see this issue travis-ci/travis-ci#5582 and this solution srsudar/MamasDelRioAndroid@ec64465.

@SUPERCILEX
Copy link
Collaborator

See #358

@googlebot
Copy link

We found a Contributor License Agreement for you (the sender of this pull request) and all commit authors, but as best as we can tell these commits were authored by someone else. If that's the case, please add them to this pull request and have them confirm that they're okay with these commits being contributed to Google. If we're mistaken and you did author these commits, just reply here to confirm.

@googlebot
Copy link

CLAs look good, thanks!

@SUPERCILEX
Copy link
Collaborator

Maybe undo f40ce5a to force a rerun?

@samtstern
Copy link
Contributor

Note: when a build fails there is a Restart Build button on the page you can use:
screen shot 2016-10-17 at 11 21 47 am

@amandle
Copy link
Contributor Author

amandle commented Oct 17, 2016

@samtstern I still don't see that button :-(

@SUPERCILEX
Copy link
Collaborator

SUPERCILEX commented Oct 17, 2016

@samtstern unfortunately, that button is only available to repository admins (the person who set up Travis).

@SUPERCILEX
Copy link
Collaborator

@amandle Looks like a compile error:

/home/travis/build/firebase/FirebaseUI-Android/auth/src/main/java/com/firebase/ui/auth/ui/idp/IDPSignInContainerActivity.java:67: error: incompatible types: String cannot be converted to IdpConfig
            mIDPProvider = new GoogleProvider(this, mEmail, providerConfig);

@SUPERCILEX
Copy link
Collaborator

SUPERCILEX commented Oct 17, 2016

I'm sorry, I just realized that I merged the Travis fix into master instead of 1.0.0. @samtstern could you merge master into dev or @amandle you could just merge master into this PR directly since I think the Travis fix is the only difference between master and dev?

@samtstern
Copy link
Contributor

@SUPERCILEX @amandle I merged master into 1.0.0-dev, the only changes were travis.yml and your small change to SaveCredentialsActivity

@SUPERCILEX
Copy link
Collaborator

Yes! Thanks @samtstern it worked! Also, look at that build time!!! 4mins vs the usual ~10mins!

@amandle amandle changed the title Specify additonal scopes thorugh code rather than config.xml Specify additonal scopes through code rather than config.xml Oct 17, 2016
@amandle amandle merged commit 897b455 into firebase:version-1.0.0-dev Oct 17, 2016
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.

4 participants