mirror of
https://github.com/commons-app/apps-android-commons.git
synced 2025-10-27 04:43:54 +01:00
Make login work across sessions
This commit is contained in:
parent
1ea0a1ebeb
commit
9c23a8c34b
7 changed files with 56 additions and 41 deletions
|
|
@ -6,8 +6,6 @@ import javax.inject.Inject;
|
||||||
|
|
||||||
import fr.free.nrw.commons.mwapi.MediaWikiApi;
|
import fr.free.nrw.commons.mwapi.MediaWikiApi;
|
||||||
import fr.free.nrw.commons.theme.NavigationBaseActivity;
|
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;
|
import static fr.free.nrw.commons.auth.AccountUtil.AUTH_COOKIE;
|
||||||
|
|
||||||
|
|
@ -23,13 +21,10 @@ public abstract class AuthenticatedActivity extends NavigationBaseActivity {
|
||||||
onAuthCookieAcquired(authCookie);
|
onAuthCookieAcquired(authCookie);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
sessionManager.getAndSetAuthCookie()
|
authCookie = sessionManager.getAuthCookie();
|
||||||
.subscribeOn(Schedulers.newThread())
|
if (authCookie != null) {
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
onAuthCookieAcquired(authCookie);
|
||||||
.subscribe(cookie -> {
|
}
|
||||||
authCookie = cookie;
|
|
||||||
onAuthCookieAcquired(authCookie);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -3,15 +3,14 @@ package fr.free.nrw.commons.auth;
|
||||||
import android.accounts.Account;
|
import android.accounts.Account;
|
||||||
import android.accounts.AccountManager;
|
import android.accounts.AccountManager;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
|
||||||
import fr.free.nrw.commons.mwapi.MediaWikiApi;
|
import fr.free.nrw.commons.mwapi.MediaWikiApi;
|
||||||
import io.reactivex.Completable;
|
import io.reactivex.Completable;
|
||||||
import io.reactivex.Observable;
|
import io.reactivex.Observable;
|
||||||
import io.reactivex.schedulers.Schedulers;
|
|
||||||
import timber.log.Timber;
|
import timber.log.Timber;
|
||||||
|
|
||||||
import static fr.free.nrw.commons.auth.AccountUtil.ACCOUNT_TYPE;
|
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.
|
* Manage the current logged in user session.
|
||||||
|
|
@ -20,11 +19,13 @@ public class SessionManager {
|
||||||
private final Context context;
|
private final Context context;
|
||||||
private final MediaWikiApi mediaWikiApi;
|
private final MediaWikiApi mediaWikiApi;
|
||||||
private Account currentAccount; // Unlike a savings account... ;-)
|
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.context = context;
|
||||||
this.mediaWikiApi = mediaWikiApi;
|
this.mediaWikiApi = mediaWikiApi;
|
||||||
this.currentAccount = null;
|
this.currentAccount = null;
|
||||||
|
this.sharedPreferences = sharedPreferences;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -50,31 +51,28 @@ public class SessionManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
accountManager.invalidateAuthToken(ACCOUNT_TYPE, mediaWikiApi.getAuthCookie());
|
accountManager.invalidateAuthToken(ACCOUNT_TYPE, mediaWikiApi.getAuthCookie());
|
||||||
getAndSetAuthCookie().subscribeOn(Schedulers.io())
|
String authCookie = getAuthCookie();
|
||||||
.subscribe(authCookie -> {
|
|
||||||
mediaWikiApi.setAuthCookie(authCookie);
|
if (authCookie == null) {
|
||||||
});
|
return false;
|
||||||
|
}
|
||||||
|
mediaWikiApi.setAuthCookie(authCookie);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Observable<String> getAndSetAuthCookie() {
|
public String getAuthCookie() {
|
||||||
AccountManager accountManager = AccountManager.get(context);
|
boolean isLoggedIn = sharedPreferences.getBoolean("isUserLoggedIn", false);
|
||||||
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);
|
|
||||||
|
|
||||||
}
|
if (!isLoggedIn) {
|
||||||
Timber.d("Auth cookie is %s", authCookie);
|
Timber.e("User is not logged in");
|
||||||
return authCookie;
|
|
||||||
}).onErrorReturn(throwable-> {
|
|
||||||
Timber.e(throwable, "Auth cookie is still null :(");
|
|
||||||
return null;
|
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() {
|
public Completable clearAllAccounts() {
|
||||||
|
|
|
||||||
|
|
@ -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;
|
import static fr.free.nrw.commons.auth.AccountUtil.AUTH_TOKEN_TYPE;
|
||||||
|
|
||||||
public class WikiAccountAuthenticator extends AbstractAccountAuthenticator {
|
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
|
@NonNull
|
||||||
private final Context context;
|
private final Context context;
|
||||||
|
|
|
||||||
|
|
@ -96,14 +96,15 @@ public class CommonsApplicationModule {
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
public SessionManager providesSessionManager(Context context,
|
public SessionManager providesSessionManager(Context context,
|
||||||
MediaWikiApi mediaWikiApi) {
|
MediaWikiApi mediaWikiApi,
|
||||||
return new SessionManager(context, mediaWikiApi);
|
@Named("default_preferences") SharedPreferences sharedPreferences) {
|
||||||
|
return new SessionManager(context, mediaWikiApi, sharedPreferences);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
public MediaWikiApi provideMediaWikiApi(Context context) {
|
public MediaWikiApi provideMediaWikiApi(Context context, @Named("default_preferences") SharedPreferences sharedPreferences) {
|
||||||
return new ApacheHttpClientMediaWikiApi(context, BuildConfig.WIKIMEDIA_API_HOST);
|
return new ApacheHttpClientMediaWikiApi(context, BuildConfig.WIKIMEDIA_API_HOST, sharedPreferences);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,7 @@ public class ModificationsSyncAdapter extends AbstractThreadedSyncAdapter {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
String authCookie = sessionManager.getAndSetAuthCookie().blockingSingle();
|
String authCookie = sessionManager.getAuthCookie();
|
||||||
if (isNullOrWhiteSpace(authCookie)) {
|
if (isNullOrWhiteSpace(authCookie)) {
|
||||||
Timber.d("Could not authenticate :(");
|
Timber.d("Could not authenticate :(");
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package fr.free.nrw.commons.mwapi;
|
package fr.free.nrw.commons.mwapi;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
|
|
@ -60,8 +61,9 @@ public class ApacheHttpClientMediaWikiApi implements MediaWikiApi {
|
||||||
private AbstractHttpClient httpClient;
|
private AbstractHttpClient httpClient;
|
||||||
private MWApi api;
|
private MWApi api;
|
||||||
private Context context;
|
private Context context;
|
||||||
|
private SharedPreferences sharedPreferences;
|
||||||
|
|
||||||
public ApacheHttpClientMediaWikiApi(Context context, String apiURL) {
|
public ApacheHttpClientMediaWikiApi(Context context, String apiURL, SharedPreferences sharedPreferences) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
BasicHttpParams params = new BasicHttpParams();
|
BasicHttpParams params = new BasicHttpParams();
|
||||||
SchemeRegistry schemeRegistry = new SchemeRegistry();
|
SchemeRegistry schemeRegistry = new SchemeRegistry();
|
||||||
|
|
@ -72,6 +74,7 @@ public class ApacheHttpClientMediaWikiApi implements MediaWikiApi {
|
||||||
params.setParameter(CoreProtocolPNames.USER_AGENT, getUserAgent());
|
params.setParameter(CoreProtocolPNames.USER_AGENT, getUserAgent());
|
||||||
httpClient = new DefaultHttpClient(cm, params);
|
httpClient = new DefaultHttpClient(cm, params);
|
||||||
api = new MWApi(apiURL, httpClient);
|
api = new MWApi(apiURL, httpClient);
|
||||||
|
this.sharedPreferences = sharedPreferences;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -143,14 +146,17 @@ public class ApacheHttpClientMediaWikiApi implements MediaWikiApi {
|
||||||
String status = loginApiResult.getString("/api/clientlogin/@status");
|
String status = loginApiResult.getString("/api/clientlogin/@status");
|
||||||
if (status.equals("PASS")) {
|
if (status.equals("PASS")) {
|
||||||
api.isLoggedIn = true;
|
api.isLoggedIn = true;
|
||||||
|
setAuthCookieOnLogin(true);
|
||||||
return status;
|
return status;
|
||||||
} else if (status.equals("FAIL")) {
|
} else if (status.equals("FAIL")) {
|
||||||
|
setAuthCookieOnLogin(false);
|
||||||
return loginApiResult.getString("/api/clientlogin/@messagecode");
|
return loginApiResult.getString("/api/clientlogin/@messagecode");
|
||||||
} else if (
|
} else if (
|
||||||
status.equals("UI")
|
status.equals("UI")
|
||||||
&& loginApiResult.getString("/api/clientlogin/requests/_v/@id").equals("TOTPAuthenticationRequest")
|
&& loginApiResult.getString("/api/clientlogin/requests/_v/@id").equals("TOTPAuthenticationRequest")
|
||||||
&& loginApiResult.getString("/api/clientlogin/requests/_v/@provider").equals("Two-factor authentication (OATH).")
|
&& loginApiResult.getString("/api/clientlogin/requests/_v/@provider").equals("Two-factor authentication (OATH).")
|
||||||
) {
|
) {
|
||||||
|
setAuthCookieOnLogin(false);
|
||||||
return "2FA";
|
return "2FA";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -158,6 +164,18 @@ public class ApacheHttpClientMediaWikiApi implements MediaWikiApi {
|
||||||
return "genericerror-" + status;
|
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
|
@Override
|
||||||
public String getAuthCookie() {
|
public String getAuthCookie() {
|
||||||
return api.getAuthCookie();
|
return api.getAuthCookie();
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,13 @@
|
||||||
package fr.free.nrw.commons.mwapi;
|
package fr.free.nrw.commons.mwapi;
|
||||||
|
|
||||||
|
import android.content.SharedPreferences;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
|
import android.preference.PreferenceManager;
|
||||||
|
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
import org.robolectric.Robolectric;
|
|
||||||
import org.robolectric.RobolectricTestRunner;
|
import org.robolectric.RobolectricTestRunner;
|
||||||
import org.robolectric.RuntimeEnvironment;
|
import org.robolectric.RuntimeEnvironment;
|
||||||
import org.robolectric.annotation.Config;
|
import org.robolectric.annotation.Config;
|
||||||
|
|
@ -36,11 +37,13 @@ public class ApacheHttpClientMediaWikiApiTest {
|
||||||
|
|
||||||
private ApacheHttpClientMediaWikiApi testObject;
|
private ApacheHttpClientMediaWikiApi testObject;
|
||||||
private MockWebServer server;
|
private MockWebServer server;
|
||||||
|
private SharedPreferences sharedPreferences;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() throws Exception {
|
public void setUp() throws Exception {
|
||||||
server = new MockWebServer();
|
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() + "/");
|
testObject.setWikiMediaToolforgeUrl("http://" + server.getHostName() + ":" + server.getPort() + "/");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue