diff --git a/app/src/main/java/fr/free/nrw/commons/auth/AuthenticatedActivity.java b/app/src/main/java/fr/free/nrw/commons/auth/AuthenticatedActivity.java index c3b570784..e39528252 100644 --- a/app/src/main/java/fr/free/nrw/commons/auth/AuthenticatedActivity.java +++ b/app/src/main/java/fr/free/nrw/commons/auth/AuthenticatedActivity.java @@ -6,8 +6,6 @@ import javax.inject.Inject; import fr.free.nrw.commons.mwapi.MediaWikiApi; import fr.free.nrw.commons.theme.NavigationBaseActivity; -import io.reactivex.android.schedulers.AndroidSchedulers; -import io.reactivex.schedulers.Schedulers; import static fr.free.nrw.commons.auth.AccountUtil.AUTH_COOKIE; @@ -23,13 +21,10 @@ public abstract class AuthenticatedActivity extends NavigationBaseActivity { onAuthCookieAcquired(authCookie); return; } - sessionManager.getAndSetAuthCookie() - .subscribeOn(Schedulers.newThread()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(cookie -> { - authCookie = cookie; - onAuthCookieAcquired(authCookie); - }); + authCookie = sessionManager.getAuthCookie(); + if (authCookie != null) { + onAuthCookieAcquired(authCookie); + } } @Override diff --git a/app/src/main/java/fr/free/nrw/commons/auth/SessionManager.java b/app/src/main/java/fr/free/nrw/commons/auth/SessionManager.java index 2c593a23a..a7e62c34e 100644 --- a/app/src/main/java/fr/free/nrw/commons/auth/SessionManager.java +++ b/app/src/main/java/fr/free/nrw/commons/auth/SessionManager.java @@ -3,15 +3,14 @@ package fr.free.nrw.commons.auth; import android.accounts.Account; import android.accounts.AccountManager; import android.content.Context; +import android.content.SharedPreferences; import fr.free.nrw.commons.mwapi.MediaWikiApi; import io.reactivex.Completable; import io.reactivex.Observable; -import io.reactivex.schedulers.Schedulers; import timber.log.Timber; import static fr.free.nrw.commons.auth.AccountUtil.ACCOUNT_TYPE; -import static fr.free.nrw.commons.auth.AccountUtil.AUTH_TOKEN_TYPE; /** * Manage the current logged in user session. @@ -20,11 +19,13 @@ public class SessionManager { private final Context context; private final MediaWikiApi mediaWikiApi; private Account currentAccount; // Unlike a savings account... ;-) + private SharedPreferences sharedPreferences; - public SessionManager(Context context, MediaWikiApi mediaWikiApi) { + public SessionManager(Context context, MediaWikiApi mediaWikiApi, SharedPreferences sharedPreferences) { this.context = context; this.mediaWikiApi = mediaWikiApi; this.currentAccount = null; + this.sharedPreferences = sharedPreferences; } /** @@ -50,31 +51,28 @@ public class SessionManager { } accountManager.invalidateAuthToken(ACCOUNT_TYPE, mediaWikiApi.getAuthCookie()); - getAndSetAuthCookie().subscribeOn(Schedulers.io()) - .subscribe(authCookie -> { - mediaWikiApi.setAuthCookie(authCookie); - }); + String authCookie = getAuthCookie(); + + if (authCookie == null) { + return false; + } + mediaWikiApi.setAuthCookie(authCookie); return true; } - public Observable getAndSetAuthCookie() { - AccountManager accountManager = AccountManager.get(context); - Account curAccount = getCurrentAccount(); - return Observable.fromCallable(() -> { - String authCookie = accountManager.blockingGetAuthToken(curAccount, AUTH_TOKEN_TYPE, false); - if (authCookie == null) { - Timber.d("Media wiki auth cookie is %s", mediaWikiApi.getAuthCookie()); - authCookie = mediaWikiApi.getAuthCookie(); - //authCookie = currentAccount.name + "|" + currentAccount.type + "|" + mediaWikiApi.getUserAgent(); - //mediaWikiApi.setAuthCookie(authCookie); + public String getAuthCookie() { + boolean isLoggedIn = sharedPreferences.getBoolean("isUserLoggedIn", false); - } - Timber.d("Auth cookie is %s", authCookie); - return authCookie; - }).onErrorReturn(throwable-> { - Timber.e(throwable, "Auth cookie is still null :("); + if (!isLoggedIn) { + Timber.e("User is not logged in"); return null; - }); + } else { + String authCookie = sharedPreferences.getString("getAuthCookie", null); + if (authCookie == null) { + Timber.e("Auth cookie is null even after login"); + } + return authCookie; + } } public Completable clearAllAccounts() { diff --git a/app/src/main/java/fr/free/nrw/commons/auth/WikiAccountAuthenticator.java b/app/src/main/java/fr/free/nrw/commons/auth/WikiAccountAuthenticator.java index 42f2c192a..78039f6a9 100644 --- a/app/src/main/java/fr/free/nrw/commons/auth/WikiAccountAuthenticator.java +++ b/app/src/main/java/fr/free/nrw/commons/auth/WikiAccountAuthenticator.java @@ -19,7 +19,7 @@ import static fr.free.nrw.commons.auth.AccountUtil.ACCOUNT_TYPE; import static fr.free.nrw.commons.auth.AccountUtil.AUTH_TOKEN_TYPE; public class WikiAccountAuthenticator extends AbstractAccountAuthenticator { - private static final String[] SYNC_AUTHORITIES = {ContributionsContentProvider.AUTHORITY, ModificationsContentProvider.AUTHORITY}; + private static final String[] SYNC_AUTHORITIES = {ContributionsContentProvider.CONTRIBUTION_AUTHORITY, ModificationsContentProvider.MODIFICATIONS_AUTHORITY}; @NonNull private final Context context; diff --git a/app/src/main/java/fr/free/nrw/commons/di/CommonsApplicationModule.java b/app/src/main/java/fr/free/nrw/commons/di/CommonsApplicationModule.java index f7e11dbf8..efc9c29b6 100644 --- a/app/src/main/java/fr/free/nrw/commons/di/CommonsApplicationModule.java +++ b/app/src/main/java/fr/free/nrw/commons/di/CommonsApplicationModule.java @@ -96,14 +96,15 @@ public class CommonsApplicationModule { @Provides @Singleton public SessionManager providesSessionManager(Context context, - MediaWikiApi mediaWikiApi) { - return new SessionManager(context, mediaWikiApi); + MediaWikiApi mediaWikiApi, + @Named("default_preferences") SharedPreferences sharedPreferences) { + return new SessionManager(context, mediaWikiApi, sharedPreferences); } @Provides @Singleton - public MediaWikiApi provideMediaWikiApi(Context context) { - return new ApacheHttpClientMediaWikiApi(context, BuildConfig.WIKIMEDIA_API_HOST); + public MediaWikiApi provideMediaWikiApi(Context context, @Named("default_preferences") SharedPreferences sharedPreferences) { + return new ApacheHttpClientMediaWikiApi(context, BuildConfig.WIKIMEDIA_API_HOST, sharedPreferences); } @Provides diff --git a/app/src/main/java/fr/free/nrw/commons/modifications/ModificationsSyncAdapter.java b/app/src/main/java/fr/free/nrw/commons/modifications/ModificationsSyncAdapter.java index 3831ce5d2..5d716d738 100644 --- a/app/src/main/java/fr/free/nrw/commons/modifications/ModificationsSyncAdapter.java +++ b/app/src/main/java/fr/free/nrw/commons/modifications/ModificationsSyncAdapter.java @@ -55,7 +55,7 @@ public class ModificationsSyncAdapter extends AbstractThreadedSyncAdapter { return; } - String authCookie = sessionManager.getAndSetAuthCookie().blockingSingle(); + String authCookie = sessionManager.getAuthCookie(); if (isNullOrWhiteSpace(authCookie)) { Timber.d("Could not authenticate :("); return; diff --git a/app/src/main/java/fr/free/nrw/commons/mwapi/ApacheHttpClientMediaWikiApi.java b/app/src/main/java/fr/free/nrw/commons/mwapi/ApacheHttpClientMediaWikiApi.java index a4b5c24fa..fe9700ef5 100644 --- a/app/src/main/java/fr/free/nrw/commons/mwapi/ApacheHttpClientMediaWikiApi.java +++ b/app/src/main/java/fr/free/nrw/commons/mwapi/ApacheHttpClientMediaWikiApi.java @@ -1,6 +1,7 @@ package fr.free.nrw.commons.mwapi; import android.content.Context; +import android.content.SharedPreferences; import android.os.Build; import android.support.annotation.NonNull; import android.support.annotation.Nullable; @@ -60,8 +61,9 @@ public class ApacheHttpClientMediaWikiApi implements MediaWikiApi { private AbstractHttpClient httpClient; private MWApi api; private Context context; + private SharedPreferences sharedPreferences; - public ApacheHttpClientMediaWikiApi(Context context, String apiURL) { + public ApacheHttpClientMediaWikiApi(Context context, String apiURL, SharedPreferences sharedPreferences) { this.context = context; BasicHttpParams params = new BasicHttpParams(); SchemeRegistry schemeRegistry = new SchemeRegistry(); @@ -72,6 +74,7 @@ public class ApacheHttpClientMediaWikiApi implements MediaWikiApi { params.setParameter(CoreProtocolPNames.USER_AGENT, getUserAgent()); httpClient = new DefaultHttpClient(cm, params); api = new MWApi(apiURL, httpClient); + this.sharedPreferences = sharedPreferences; } @Override @@ -143,14 +146,17 @@ public class ApacheHttpClientMediaWikiApi implements MediaWikiApi { String status = loginApiResult.getString("/api/clientlogin/@status"); if (status.equals("PASS")) { api.isLoggedIn = true; + setAuthCookieOnLogin(true); return status; } else if (status.equals("FAIL")) { + setAuthCookieOnLogin(false); return loginApiResult.getString("/api/clientlogin/@messagecode"); } else if ( status.equals("UI") && loginApiResult.getString("/api/clientlogin/requests/_v/@id").equals("TOTPAuthenticationRequest") && loginApiResult.getString("/api/clientlogin/requests/_v/@provider").equals("Two-factor authentication (OATH).") ) { + setAuthCookieOnLogin(false); return "2FA"; } @@ -158,6 +164,18 @@ public class ApacheHttpClientMediaWikiApi implements MediaWikiApi { return "genericerror-" + status; } + private void setAuthCookieOnLogin(boolean isLoggedIn) { + SharedPreferences.Editor editor = sharedPreferences.edit(); + if (isLoggedIn) { + editor.putBoolean("isUserLoggedIn", true); + editor.putString("getAuthCookie", api.getAuthCookie()); + } else { + editor.putBoolean("isUserLoggedIn", false); + editor.remove("getAuthCookie"); + } + editor.apply(); + } + @Override public String getAuthCookie() { return api.getAuthCookie(); diff --git a/app/src/test/java/fr/free/nrw/commons/mwapi/ApacheHttpClientMediaWikiApiTest.java b/app/src/test/java/fr/free/nrw/commons/mwapi/ApacheHttpClientMediaWikiApiTest.java index e6b53d460..2b925535d 100644 --- a/app/src/test/java/fr/free/nrw/commons/mwapi/ApacheHttpClientMediaWikiApiTest.java +++ b/app/src/test/java/fr/free/nrw/commons/mwapi/ApacheHttpClientMediaWikiApiTest.java @@ -1,12 +1,13 @@ package fr.free.nrw.commons.mwapi; +import android.content.SharedPreferences; import android.os.Build; +import android.preference.PreferenceManager; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -import org.robolectric.Robolectric; import org.robolectric.RobolectricTestRunner; import org.robolectric.RuntimeEnvironment; import org.robolectric.annotation.Config; @@ -36,11 +37,13 @@ public class ApacheHttpClientMediaWikiApiTest { private ApacheHttpClientMediaWikiApi testObject; private MockWebServer server; + private SharedPreferences sharedPreferences; @Before public void setUp() throws Exception { server = new MockWebServer(); - testObject = new ApacheHttpClientMediaWikiApi(RuntimeEnvironment.application, "http://" + server.getHostName() + ":" + server.getPort() + "/"); + sharedPreferences = PreferenceManager.getDefaultSharedPreferences(RuntimeEnvironment.application); + testObject = new ApacheHttpClientMediaWikiApi(RuntimeEnvironment.application, "http://" + server.getHostName() + ":" + server.getPort() + "/", sharedPreferences); testObject.setWikiMediaToolforgeUrl("http://" + server.getHostName() + ":" + server.getPort() + "/"); }