Skip to content

Commit

Permalink
Split GitHub provider out into its own module (#1421)
Browse files Browse the repository at this point in the history
  • Loading branch information
SUPERCILEX authored and samtstern committed Aug 29, 2018
1 parent 0da111b commit 68be249
Show file tree
Hide file tree
Showing 24 changed files with 162 additions and 103 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ dependencies {
// FirebaseUI for Firebase Auth
implementation 'com.firebaseui:firebase-ui-auth:4.1.0'
// FirebaseUI for Firebase Auth GitHub provider
implementation 'com.firebaseui:firebase-ui-auth-github:4.1.0'
// FirebaseUI for Cloud Storage
implementation 'com.firebaseui:firebase-ui-storage:4.1.0'
Expand Down
1 change: 1 addition & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ dependencies {
implementation(Config.Libs.Support.multidex)

implementation(project(":auth"))
implementation(project(":auth-github"))
implementation(project(":firestore"))
implementation(project(":database"))
implementation(project(":storage"))
Expand Down
40 changes: 4 additions & 36 deletions app/src/main/res/values/config.xml
Original file line number Diff line number Diff line change
@@ -1,46 +1,14 @@
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Example: project-id.firebaseapp.com. Used for OAuth redirects -->
<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="UnusedResources">
<!-- See auth/src/main/res/values/config.xml for documentation -->

<string name="firebase_web_host" translatable="false">CHANGE-ME</string>

<!--
The Facebook Application ID associated with this Android application. To
use Facebook accounts with the demo application, register an application
and provide your value here.
-->
<string name="facebook_application_id" translatable="false">CHANGE-ME</string>
<string name="facebook_login_protocol_scheme" translatable="false">fbYOUR_APP_ID</string>

<!-- Facebook Application ID, prefixed by 'fb'. Enables Chrome Custom tabs. -->
<string name="facebook_login_protocol_scheme" translatable="false" tools:ignore="UnusedResources">fbYOUR_APP_ID</string>


<!--
Your Twitter Consumer Key. To use Twitter accounts with the demo application, register an
application with Twitter and provide the following two values.
-->
<string name="twitter_consumer_key" translatable="false">CHANGE-ME</string>

<!--
Your Twitter Consumer Secret.
WARNING: By obtaining your Consumer Key and Consumer Secret other programs can perform API
operations as your app. Embedding the Consumer Key and Consumer Secret in your app, no matter
how obfuscated, makes it vulnerable to being stolen.
-->
<string name="twitter_consumer_secret" translatable="false">CHANGE-ME</string>


<!--
Your GitHub Client ID. To use GitHub accounts with the demo application, register an
application with GitHub and provide the following two values.
-->
<string name="github_client_id" translatable="false">CHANGE-ME</string>

<!--
Your GitHub Client Secret.
WARNING: By obtaining your Client ID and Client Secret other programs can perform API
operations as your app. Embedding the Client ID and Client Secret in your app, no matter
how obfuscated, makes it vulnerable to being stolen.
-->
<string name="github_client_secret" translatable="false">CHANGE-ME</string>
</resources>
10 changes: 10 additions & 0 deletions auth-github/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
dependencies {
compileOnly(project(":auth")) { isTransitive = false }
compileOnly(Config.Libs.Firebase.auth) { isTransitive = false }

implementation(Config.Libs.Support.appCompat)
implementation(Config.Libs.Support.customTabs)

implementation(Config.Libs.Misc.retrofit)
implementation(Config.Libs.Misc.retrofitGson)
}
35 changes: 35 additions & 0 deletions auth-github/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.firebase.ui.auth.ui.github">

<application>

<activity
android:name=".GitHubLoginActivity"
android:label=""
android:configChanges="keyboard|keyboardHidden|screenLayout|screenSize|orientation"
android:launchMode="singleTop"
android:theme="@style/FirebaseUI.Transparent">

<intent-filter
android:autoVerify="true"
tools:ignore="UnusedAttribute">
<action android:name="android.intent.action.VIEW" />

<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />

<data
android:host="@string/firebase_web_host"
android:path="/__/auth/handler"
android:scheme="https"
tools:ignore="AppLinksAutoVerifyWarning" />
</intent-filter>

</activity>

</application>

</manifest>
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,14 @@
import com.firebase.ui.auth.ErrorCodes;
import com.firebase.ui.auth.FirebaseUiException;
import com.firebase.ui.auth.IdpResponse;
import com.firebase.ui.auth.R;
import com.firebase.ui.auth.data.model.GitHubProfile;
import com.firebase.ui.auth.data.model.GitHubTokenResponse;
import com.firebase.ui.auth.data.model.Resource;
import com.firebase.ui.auth.data.model.User;
import com.firebase.ui.auth.data.model.UserCancellationException;
import com.firebase.ui.auth.ui.HelperActivityBase;
import com.firebase.ui.auth.ui.provider.GitHubLoginActivity;
import com.firebase.ui.auth.ui.github.GitHubLoginActivity;
import com.firebase.ui.auth.ui.github.R;
import com.firebase.ui.auth.util.ExtraConstants;
import com.firebase.ui.auth.viewmodel.ProviderSignInBase;
import com.firebase.ui.auth.viewmodel.RequestCodes;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.firebase.ui.auth.ui.provider;
package com.firebase.ui.auth.ui.github;

import android.annotation.SuppressLint;
import android.content.Context;
Expand All @@ -10,7 +10,6 @@
import android.support.customtabs.CustomTabsIntent;
import android.support.v4.content.ContextCompat;

import com.firebase.ui.auth.R;
import com.firebase.ui.auth.data.remote.GitHubSignInHandler;
import com.firebase.ui.auth.ui.HelperActivityBase;
import com.firebase.ui.auth.util.ExtraConstants;
Expand Down
10 changes: 10 additions & 0 deletions auth-github/src/main/res/values/ids.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Expect auth resources -->
<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="ResourceName">
<item name="colorPrimary" type="color" />
<item name="FirebaseUI.Transparent" type="style" />

<item name="firebase_web_host" type="string" />
<item name="github_client_id" type="string" />
<item name="github_client_secret" type="string" />
</resources>
25 changes: 14 additions & 11 deletions auth/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@ dependencies {
// ...
implementation 'com.firebaseui:firebase-ui-auth:4.1.0'
// Required only if GitHub OAuth support is required
implementation 'com.firebaseui:firebase-ui-auth-github:4.1.0'
// Required only if Facebook login support is required
// Find the latest Facebook SDK releases here: https://goo.gl/Ce5L94
implementation 'com.facebook.android:facebook-login:4.x'
Expand Down Expand Up @@ -664,7 +667,7 @@ To support this behavior, FirebaseUI makes it easy to "upgrade" an anonymous
account to a permanent account. To do so, simply call `enableAnonymousUsersAutoUpgrade()`
when you configure the sign-in UI (this option is disabled by default).

For example:
For example:
```java
startActivityForResult(
AuthUI.getInstance()
Expand All @@ -676,26 +679,26 @@ startActivityForResult(
```

With this enabled, FirebaseUI will link the credential on sign-in with the anonymous account
using Firebase Auth's `linkWithCredential` method:
using Firebase Auth's `linkWithCredential` method:
```java
FirebaseAuth.getInstance().getCurrentUser().linkWithCredential(permanentCredential);
```

#### Handling anonymous user upgrade merge conflicts

There is an issue when an anonymous user tries to upgrade to an existing Firebase user.
There is an issue when an anonymous user tries to upgrade to an existing Firebase user.

For example, a user may have previously signed up with a Google credential on a different device.
If they are signed in anonymously and they attempt to upgrade with the existing Google account,
For example, a user may have previously signed up with a Google credential on a different device.
If they are signed in anonymously and they attempt to upgrade with the existing Google account,
a `FirebaseAuthUserCollisionException` will be thrown by Firebase Auth as an existing user
cannot be linked to another existing user. No two users can share the same credential. In this case,
cannot be linked to another existing user. No two users can share the same credential. In this case,
we need to merge the data from both users before we can upgrade the anonymous user.

The process of storing the anonymous users data, signing in with the credential, and copying the
data over to the existing account is left to the developer.
data over to the existing account is left to the developer.

When linking is unsuccessful due to user collision, an error with code
`ErrorCodes.ANONYMOUS_UPGRADE_MERGE_CONFLICT` will be returned to `onActivityResult()`. A valid
When linking is unsuccessful due to user collision, an error with code
`ErrorCodes.ANONYMOUS_UPGRADE_MERGE_CONFLICT` will be returned to `onActivityResult()`. A valid
non-anonymous credential can be obtained from the `IdpResponse` via `getCredentialForLinking()`.

**Example:**
Expand All @@ -714,7 +717,7 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
...
// Get the non-anoymous credential from the response
AuthCredential nonAnonymousCredential = response.getCredentialForLinking();
// Sign in with credential
// Sign in with credential
FirebaseAuth.getInstance().signInWithCredential(nonAnonymousCredential);
.addOnSuccessListener(new OnSuccessListener<AuthResult>() {
@Override
Expand Down
2 changes: 1 addition & 1 deletion auth/auth-proguard.pro
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Twitter and Facebook are optional
# 3P providers are optional
-dontwarn com.facebook.**
-dontwarn com.twitter.**
# Keep the class names used to check for availablility
Expand Down
7 changes: 1 addition & 6 deletions auth/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,9 @@ dependencies {
api(Config.Libs.PlayServices.auth)

compileOnly(Config.Libs.Provider.facebook)
// Needed to override Facebook
implementation(Config.Libs.Support.cardView)
implementation(Config.Libs.Support.customTabs)
implementation(Config.Libs.Support.cardView) // Needed to override Facebook
compileOnly(Config.Libs.Provider.twitter) { isTransitive = true }

implementation(Config.Libs.Misc.retrofit)
implementation(Config.Libs.Misc.retrofitGson)

testImplementation(Config.Libs.Test.junit)
testImplementation(Config.Libs.Test.truth)
testImplementation(Config.Libs.Test.mockito)
Expand Down
24 changes: 0 additions & 24 deletions auth/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -35,30 +35,6 @@
android:exported="false"
android:theme="@style/FirebaseUI.Transparent" />

<activity
android:name=".ui.provider.GitHubLoginActivity"
android:label=""
android:configChanges="keyboard|keyboardHidden|screenLayout|screenSize|orientation"
android:launchMode="singleTop"
android:theme="@style/FirebaseUI.Transparent">

<intent-filter
android:autoVerify="true"
tools:ignore="UnusedAttribute">
<action android:name="android.intent.action.VIEW" />

<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />

<data
android:host="@string/firebase_web_host"
android:path="/__/auth/handler"
android:scheme="https"
tools:ignore="AppLinksAutoVerifyWarning" />
</intent-filter>

</activity>

<activity
android:name=".ui.email.RecoverPasswordActivity"
android:label="@string/fui_title_recover_password_activity"
Expand Down
6 changes: 6 additions & 0 deletions auth/src/main/java/com/firebase/ui/auth/AuthUI.java
Original file line number Diff line number Diff line change
Expand Up @@ -978,6 +978,12 @@ public static final class GitHubBuilder extends Builder {
public GitHubBuilder() {
//noinspection deprecation taking a hit for the backcompat team
super(GithubAuthProvider.PROVIDER_ID);
if (!ProviderAvailability.IS_GITHUB_AVAILABLE) {
throw new RuntimeException(
"GitHub provider cannot be configured " +
"without dependency. Did you forget to add " +
"'com.firebaseui:firebase-ui-auth-github:VERSION' dependency?");
}
Preconditions.checkConfigured(getApplicationContext(),
"GitHub provider unconfigured. Make sure to add your client id and secret." +
" See the docs for more info:" +
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.firebase.ui.auth.data.remote;

import android.support.annotation.RestrictTo;

import com.firebase.ui.auth.AuthUI;
import com.firebase.ui.auth.viewmodel.ProviderSignInBase;

@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
public final class GitHubSignInHandlerBridge {
public static final Class<ProviderSignInBase<AuthUI.IdpConfig>> HANDLER_CLASS;

static {
try {
//noinspection unchecked
HANDLER_CLASS = (Class<ProviderSignInBase<AuthUI.IdpConfig>>)
Class.forName("com.firebase.ui.auth.data.remote.GitHubSignInHandler");
} catch (ClassNotFoundException e) {
throw new IllegalStateException(
"Check for availability with ProviderAvailability first.", e);
}
}

private GitHubSignInHandlerBridge() {
throw new AssertionError("No instance for you!");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
import com.firebase.ui.auth.data.remote.AnonymousSignInHandler;
import com.firebase.ui.auth.data.remote.EmailSignInHandler;
import com.firebase.ui.auth.data.remote.FacebookSignInHandler;
import com.firebase.ui.auth.data.remote.GitHubSignInHandler;
import com.firebase.ui.auth.data.remote.GitHubSignInHandlerBridge;
import com.firebase.ui.auth.data.remote.GoogleSignInHandler;
import com.firebase.ui.auth.data.remote.PhoneSignInHandler;
import com.firebase.ui.auth.data.remote.TwitterSignInHandler;
Expand Down Expand Up @@ -167,7 +167,8 @@ private void populateIdpList(List<IdpConfig> providerConfigs,
buttonLayout = R.layout.fui_idp_button_twitter;
break;
case GithubAuthProvider.PROVIDER_ID:
GitHubSignInHandler github = supplier.get(GitHubSignInHandler.class);
ProviderSignInBase<IdpConfig> github =
supplier.get(GitHubSignInHandlerBridge.HANDLER_CLASS);
github.init(idpConfig);
provider = github;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
import com.firebase.ui.auth.data.model.FlowParameters;
import com.firebase.ui.auth.data.model.User;
import com.firebase.ui.auth.data.remote.FacebookSignInHandler;
import com.firebase.ui.auth.data.remote.GitHubSignInHandler;
import com.firebase.ui.auth.data.remote.GitHubSignInHandlerBridge;
import com.firebase.ui.auth.data.remote.GoogleSignInHandler;
import com.firebase.ui.auth.data.remote.TwitterSignInHandler;
import com.firebase.ui.auth.ui.InvisibleActivityBase;
Expand Down Expand Up @@ -77,7 +77,8 @@ protected void onCreate(@Nullable Bundle savedInstanceState) {
mProvider = twitter;
break;
case GithubAuthProvider.PROVIDER_ID:
GitHubSignInHandler github = supplier.get(GitHubSignInHandler.class);
ProviderSignInBase<AuthUI.IdpConfig> github =
supplier.get(GitHubSignInHandlerBridge.HANDLER_CLASS);
github.init(providerConfig);
mProvider = github;
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
import com.firebase.ui.auth.data.model.FlowParameters;
import com.firebase.ui.auth.data.model.User;
import com.firebase.ui.auth.data.remote.FacebookSignInHandler;
import com.firebase.ui.auth.data.remote.GitHubSignInHandler;
import com.firebase.ui.auth.data.remote.GitHubSignInHandlerBridge;
import com.firebase.ui.auth.data.remote.GoogleSignInHandler;
import com.firebase.ui.auth.data.remote.TwitterSignInHandler;
import com.firebase.ui.auth.ui.AppCompatBase;
Expand Down Expand Up @@ -132,7 +132,8 @@ protected void onCreate(@Nullable Bundle savedInstanceState) {
providerName = R.string.fui_idp_name_twitter;
break;
case GithubAuthProvider.PROVIDER_ID:
GitHubSignInHandler github = supplier.get(GitHubSignInHandler.class);
ProviderSignInBase<AuthUI.IdpConfig> github =
supplier.get(GitHubSignInHandlerBridge.HANDLER_CLASS);
github.init(config);
mProvider = github;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
public final class ProviderAvailability {
public static final boolean IS_GITHUB_AVAILABLE =
exists("com.firebase.ui.auth.data.remote.GitHubSignInHandler");
public static final boolean IS_FACEBOOK_AVAILABLE =
exists("com.facebook.login.LoginManager");
public static final boolean IS_TWITTER_AVAILABLE =
Expand Down
Loading

0 comments on commit 68be249

Please sign in to comment.