Make login work across sessions

This commit is contained in:
maskara 2018-01-21 03:29:07 +05:30
parent 1ea0a1ebeb
commit 9c23a8c34b
7 changed files with 56 additions and 41 deletions

View file

@ -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

View file

@ -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<String> 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() {

View file

@ -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;

View file

@ -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

View file

@ -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;

View file

@ -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();

View file

@ -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() + "/");
}