From d38dde0ec4a4113b3dcc6a1c1c689295b90d01e5 Mon Sep 17 00:00:00 2001 From: addshore Date: Fri, 12 May 2017 13:04:22 +0200 Subject: [PATCH] Use clientlogin API module This is the first step to allowing 2 factor authentication #328. This uses the new API module clientlogin instead of the login module. We still report the same set of errors in a 'nice' way with real error messages, how ever there are lots more that can probably be handled, for example #507. --- .../free/nrw/commons/CommonsApplication.java | 1 - .../main/java/fr/free/nrw/commons/MWApi.java | 58 +++++++++++++++++++ .../free/nrw/commons/MediaDataExtractor.java | 1 - .../free/nrw/commons/auth/LoginActivity.java | 19 ++++-- .../auth/WikiAccountAuthenticator.java | 5 +- .../nrw/commons/category/MethodAUpdater.java | 2 +- .../nrw/commons/category/PrefixUpdater.java | 2 +- .../nrw/commons/category/TitleCategories.java | 2 +- .../ContributionsSyncAdapter.java | 2 +- .../ModificationsSyncAdapter.java | 2 +- .../nrw/commons/upload/ExistingFileAsync.java | 2 +- .../nrw/commons/upload/UploadService.java | 7 +-- 12 files changed, 80 insertions(+), 23 deletions(-) create mode 100644 app/src/main/java/fr/free/nrw/commons/MWApi.java diff --git a/app/src/main/java/fr/free/nrw/commons/CommonsApplication.java b/app/src/main/java/fr/free/nrw/commons/CommonsApplication.java index 5ba33a7e2..5e45d97df 100644 --- a/app/src/main/java/fr/free/nrw/commons/CommonsApplication.java +++ b/app/src/main/java/fr/free/nrw/commons/CommonsApplication.java @@ -32,7 +32,6 @@ import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager; import org.apache.http.params.BasicHttpParams; import org.apache.http.params.CoreProtocolPNames; -import org.mediawiki.api.MWApi; import java.io.IOException; diff --git a/app/src/main/java/fr/free/nrw/commons/MWApi.java b/app/src/main/java/fr/free/nrw/commons/MWApi.java new file mode 100644 index 000000000..37a4d02e7 --- /dev/null +++ b/app/src/main/java/fr/free/nrw/commons/MWApi.java @@ -0,0 +1,58 @@ +package fr.free.nrw.commons; + +import java.io.IOException; + +import org.apache.http.impl.client.AbstractHttpClient; +import org.mediawiki.api.ApiResult; + +/** + * @author Addshore + */ +public class MWApi extends org.mediawiki.api.MWApi { + + public MWApi(String apiURL, AbstractHttpClient client) { + super(apiURL, client); + } + + /** + * @param username String + * @param password String + * @return String On success: "PASS" + * failure: A failure message code (deifned by mediawiki) + * misc: genericerror-UI, genericerror-REDIRECT, genericerror-RESTART + * @throws IOException On api request IO issue + */ + public String login(String username, String password) throws IOException { + + /** Request a login token to be used later to log in. */ + ApiResult tokenData = this.action("query") + .param("action", "query") + .param("meta", "tokens") + .param("type", "login") + .post(); + String token = tokenData.getString("/api/query/tokens/@logintoken"); + + /** Actually log in. */ + ApiResult loginData = this.action("clientlogin") + .param("rememberMe", "1") + .param("username", username) + .param("password", password) + .param("logintoken", token) + .param("loginreturnurl", "http://example.com/")//TODO return to url? + .post(); + String status = loginData.getString("/api/clientlogin/@status"); + + if (status.equals("PASS")) { + this.isLoggedIn = true; + return status; + + } else if (status.equals("FAIL")) { + return loginData.getString("/api/clientlogin/@messagecode"); + } + + // UI, REDIRECT, RESTART + return "genericerror-" + status; + } + + +} diff --git a/app/src/main/java/fr/free/nrw/commons/MediaDataExtractor.java b/app/src/main/java/fr/free/nrw/commons/MediaDataExtractor.java index b09ec1b76..df9d5a4de 100644 --- a/app/src/main/java/fr/free/nrw/commons/MediaDataExtractor.java +++ b/app/src/main/java/fr/free/nrw/commons/MediaDataExtractor.java @@ -1,7 +1,6 @@ package fr.free.nrw.commons; import org.mediawiki.api.ApiResult; -import org.mediawiki.api.MWApi; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; diff --git a/app/src/main/java/fr/free/nrw/commons/auth/LoginActivity.java b/app/src/main/java/fr/free/nrw/commons/auth/LoginActivity.java index b86294e7e..b104eb2e2 100644 --- a/app/src/main/java/fr/free/nrw/commons/auth/LoginActivity.java +++ b/app/src/main/java/fr/free/nrw/commons/auth/LoginActivity.java @@ -66,7 +66,7 @@ public class LoginActivity extends AccountAuthenticatorActivity { .param("result", result) .log(); - if (result.equals("Success")) { + if (result.equals("PASS")) { if (dialog != null && dialog.isShowing()) { dialog.dismiss(); } @@ -100,20 +100,27 @@ public class LoginActivity extends AccountAuthenticatorActivity { } else { int response; + // Match known failure message codes and provide messages if(result.equals("NetworkFailure")) { + // Matches NetworkFailure which is created by the doInBackground method response = R.string.login_failed_network; - } else if(result.equals("NotExists") || result.equals("Illegal") || result.equals("NotExists")) { + } else if (result.toLowerCase().contains("nosuchuser".toLowerCase()) || result.toLowerCase().contains("noname".toLowerCase())) { + // Matches nosuchuser, nosuchusershort, noname response = R.string.login_failed_username; passwordEdit.setText(""); - } else if(result.equals("EmptyPass") || result.equals("WrongPass") || result.equals("WrongPluginPass")) { + + } else if (result.toLowerCase().contains("wrongpassword".toLowerCase())) { + // Matches wrongpassword, wrongpasswordempty response = R.string.login_failed_password; passwordEdit.setText(""); - } else if(result.equals("Throttled")) { + } else if (result.toLowerCase().contains("throttle".toLowerCase())) { + // Matches unknown throttle error codes response = R.string.login_failed_throttled; - } else if(result.equals("Blocked")) { + } else if (result.toLowerCase().contains("userblocked".toLowerCase())) { + // Matches login-userblocked response = R.string.login_failed_blocked; } else { - // Should never really happen + // Occurs with unhandled login failure codes Timber.d("Login failed with reason: %s", result); response = R.string.login_failed_generic; } 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 9194fa316..42448ace0 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 @@ -9,11 +9,10 @@ import android.content.Context; import android.content.Intent; import android.os.Bundle; -import org.mediawiki.api.MWApi; - import java.io.IOException; import fr.free.nrw.commons.CommonsApplication; +import fr.free.nrw.commons.MWApi; public class WikiAccountAuthenticator extends AbstractAccountAuthenticator { @@ -46,7 +45,7 @@ public class WikiAccountAuthenticator extends AbstractAccountAuthenticator { private String getAuthCookie(String username, String password) throws IOException { MWApi api = CommonsApplication.createMWApi(); String result = api.login(username, password); - if(result.equals("Success")) { + if(result.equals("PASS")) { return api.getAuthCookie(); } else { return null; diff --git a/app/src/main/java/fr/free/nrw/commons/category/MethodAUpdater.java b/app/src/main/java/fr/free/nrw/commons/category/MethodAUpdater.java index 74e379b37..35ab0ef17 100644 --- a/app/src/main/java/fr/free/nrw/commons/category/MethodAUpdater.java +++ b/app/src/main/java/fr/free/nrw/commons/category/MethodAUpdater.java @@ -3,8 +3,8 @@ package fr.free.nrw.commons.category; import android.os.AsyncTask; import android.view.View; +import fr.free.nrw.commons.MWApi; import org.mediawiki.api.ApiResult; -import org.mediawiki.api.MWApi; import java.io.IOException; import java.util.ArrayList; diff --git a/app/src/main/java/fr/free/nrw/commons/category/PrefixUpdater.java b/app/src/main/java/fr/free/nrw/commons/category/PrefixUpdater.java index 17d7ab801..10499acbd 100644 --- a/app/src/main/java/fr/free/nrw/commons/category/PrefixUpdater.java +++ b/app/src/main/java/fr/free/nrw/commons/category/PrefixUpdater.java @@ -4,8 +4,8 @@ import android.os.AsyncTask; import android.text.TextUtils; import android.view.View; +import fr.free.nrw.commons.MWApi; import org.mediawiki.api.ApiResult; -import org.mediawiki.api.MWApi; import java.io.IOException; import java.util.ArrayList; diff --git a/app/src/main/java/fr/free/nrw/commons/category/TitleCategories.java b/app/src/main/java/fr/free/nrw/commons/category/TitleCategories.java index 9622d4d3b..a372b353d 100644 --- a/app/src/main/java/fr/free/nrw/commons/category/TitleCategories.java +++ b/app/src/main/java/fr/free/nrw/commons/category/TitleCategories.java @@ -2,8 +2,8 @@ package fr.free.nrw.commons.category; import android.os.AsyncTask; +import fr.free.nrw.commons.MWApi; import org.mediawiki.api.ApiResult; -import org.mediawiki.api.MWApi; import java.io.IOException; import java.util.ArrayList; diff --git a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsSyncAdapter.java b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsSyncAdapter.java index 59f34d1da..b3d1e8fda 100644 --- a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsSyncAdapter.java +++ b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsSyncAdapter.java @@ -12,8 +12,8 @@ import android.os.Bundle; import android.os.RemoteException; import android.text.TextUtils; +import fr.free.nrw.commons.MWApi; import org.mediawiki.api.ApiResult; -import org.mediawiki.api.MWApi; import java.io.IOException; import java.util.ArrayList; 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 228b01a80..fdc9e28a5 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 @@ -12,8 +12,8 @@ import android.database.Cursor; import android.os.Bundle; import android.os.RemoteException; +import fr.free.nrw.commons.MWApi; import org.mediawiki.api.ApiResult; -import org.mediawiki.api.MWApi; import java.io.IOException; diff --git a/app/src/main/java/fr/free/nrw/commons/upload/ExistingFileAsync.java b/app/src/main/java/fr/free/nrw/commons/upload/ExistingFileAsync.java index 6d7b08025..14988c60c 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/ExistingFileAsync.java +++ b/app/src/main/java/fr/free/nrw/commons/upload/ExistingFileAsync.java @@ -6,8 +6,8 @@ import android.content.Intent; import android.os.AsyncTask; import android.support.v7.app.AlertDialog; +import fr.free.nrw.commons.MWApi; import org.mediawiki.api.ApiResult; -import org.mediawiki.api.MWApi; import java.io.IOException; import java.util.ArrayList; diff --git a/app/src/main/java/fr/free/nrw/commons/upload/UploadService.java b/app/src/main/java/fr/free/nrw/commons/upload/UploadService.java index dea134ac3..523b6a479 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/UploadService.java +++ b/app/src/main/java/fr/free/nrw/commons/upload/UploadService.java @@ -13,8 +13,8 @@ import android.support.v4.app.NotificationCompat; import android.webkit.MimeTypeMap; import android.widget.Toast; +import fr.free.nrw.commons.*; import org.mediawiki.api.ApiResult; -import org.mediawiki.api.MWApi; import java.io.FileNotFoundException; import java.io.IOException; @@ -25,11 +25,6 @@ import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; -import fr.free.nrw.commons.CommonsApplication; -import fr.free.nrw.commons.EventLog; -import fr.free.nrw.commons.HandlerService; -import fr.free.nrw.commons.R; -import fr.free.nrw.commons.Utils; import fr.free.nrw.commons.contributions.Contribution; import fr.free.nrw.commons.contributions.ContributionsActivity; import fr.free.nrw.commons.contributions.ContributionsContentProvider;