Merge 2.8 release with master (#1887)

* Add Traceur for getting meaningful RxJava stack traces (#1832)

* Hotfix for overwrite issue in 2.8.0  (#1838)

* This solution is an hotfix for overrite issue came back on 2.8.0 version. What I did is checking the extension, and if it is null, adding .jpg suffix. Because commons files always have suffixes, and we should compare file names after adding suffixes. Othervise overrides are possible.

* Check if file title includes an extension already, by checking if is there any dot in it.

* Fix logic error

* Add uncovered tests

* Remove unecessary line breaks

* Make Javadocs more explicit

* Versioning and changelog for v2.8.2 (#1842)

* Versioning for v2.8.2

* Changelog for v2.8.2

* Add logs in wiki data edit and session refresh flow (#1874)

* Fix logout (#1875)

* [WIP] Refactor feedback and quiz to reduce possibility of NPE (#1881)

* Refactor feedback and quiz to reduce possibility of NPE

* Handle throwables in quiz checker

* Minor refactoring

* Set Traceur to only work in DEBUG mode (#1884)

* Bug fix for uploaded images count in achievements activity (#1885)

* Versioning and changelog for v2.8.3 (#1886)

* Update changelog.md

* Versioning for v2.8.3
This commit is contained in:
Vivek Maskara 2018-09-07 05:50:41 +05:30 committed by GitHub
parent 13c377aa17
commit a63b9f88bb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 284 additions and 252 deletions

View file

@ -24,7 +24,6 @@ import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.CoreProtocolPNames;
import org.apache.http.util.EntityUtils;
import org.json.JSONObject;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
@ -45,6 +44,7 @@ import java.util.concurrent.Callable;
import fr.free.nrw.commons.BuildConfig;
import fr.free.nrw.commons.Media;
import fr.free.nrw.commons.PageTitle;
import fr.free.nrw.commons.achievements.FeedbackResponse;
import fr.free.nrw.commons.auth.AccountUtil;
import fr.free.nrw.commons.category.CategoryImageUtils;
import fr.free.nrw.commons.category.QueryContinue;
@ -76,14 +76,17 @@ public class ApacheHttpClientMediaWikiApi implements MediaWikiApi {
private SharedPreferences defaultPreferences;
private SharedPreferences categoryPreferences;
private Gson gson;
private final OkHttpClient okHttpClient;
public ApacheHttpClientMediaWikiApi(Context context,
String apiURL,
String wikidatApiURL,
SharedPreferences defaultPreferences,
SharedPreferences categoryPreferences,
Gson gson) {
Gson gson,
OkHttpClient okHttpClient) {
this.context = context;
this.okHttpClient = okHttpClient;
BasicHttpParams params = new BasicHttpParams();
SchemeRegistry schemeRegistry = new SchemeRegistry();
schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
@ -233,17 +236,27 @@ public class ApacheHttpClientMediaWikiApi implements MediaWikiApi {
@Override
public String getCentralAuthToken() throws IOException {
String centralAuthToken = api.action("centralauthtoken")
.get()
.getString("/api/centralauthtoken/@centralauthtoken");
CustomApiResult result = api.action("centralauthtoken").get();
String centralAuthToken = result.getString("/api/centralauthtoken/@centralauthtoken");
Timber.d("MediaWiki Central auth token is %s", centralAuthToken);
if(centralAuthToken == null || centralAuthToken.isEmpty()) {
if ((centralAuthToken == null || centralAuthToken.isEmpty())
&& "notLoggedIn".equals(result.getString("api/error/@code"))) {
Timber.d("Central auth token isn't valid. Trying to fetch a fresh token");
api.removeAllCookies();
String login = login(AccountUtil.getUserName(context), AccountUtil.getPassword(context));
if(login.equals("PASS")) {
String loginResultCode = login(AccountUtil.getUserName(context), AccountUtil.getPassword(context));
if(loginResultCode.equals("PASS")) {
return getCentralAuthToken();
} else if(loginResultCode.equals("2FA")) {
Timber.e("Cannot refresh session for 2FA enabled user. Login required");
} else {
Timber.e("Error occurred in refreshing session. Error code is %s", loginResultCode);
}
} else {
Timber.e("Error occurred while fetching auth token. Error code is %s and message is %s",
result.getString("api/error/@code"),
result.getString("api/error/@info"));
}
return centralAuthToken;
}
@ -467,13 +480,12 @@ public class ApacheHttpClientMediaWikiApi implements MediaWikiApi {
return false;
}
Node node = result.getNode("api").getDocument();
Element element = (Element) node;
if (element != null && element.getAttribute("status").equals("success")) {
if ("success".equals(result.getString("api/tag/result/@status"))) {
return true;
} else {
Timber.e(result.getString("api/error/@code") + " " + result.getString("api/error/@info"));
Timber.e("Error occurred in creating claim. Error code is: %s and message is %s",
result.getString("api/error/@code"),
result.getString("api/error/@info"));
}
return false;
}
@ -954,12 +966,11 @@ public class ApacheHttpClientMediaWikiApi implements MediaWikiApi {
/**
* This takes userName as input, which is then used to fetch the feedback/achievements
* statistics using OkHttp and JavaRx. This function return JSONObject
* @param userName
* @param userName MediaWiki user name
* @return
*/
@NonNull
@Override
public Single<JSONObject> getAchievements(String userName) {
public Single<FeedbackResponse> getAchievements(String userName) {
final String fetchAchievementUrlTemplate =
wikiMediaToolforgeUrl + "urbanecmbot/commonsmisc/feedback.py";
return Single.fromCallable(() -> {
@ -973,46 +984,19 @@ public class ApacheHttpClientMediaWikiApi implements MediaWikiApi {
Request request = new Request.Builder()
.url(urlBuilder.toString())
.build();
OkHttpClient client = new OkHttpClient();
Response response = client.newCall(request).execute();
String jsonData = response.body().string();
JSONObject jsonObject = new JSONObject(jsonData);
return jsonObject;
Response response = okHttpClient.newCall(request).execute();
if (response != null && response.body() != null && response.isSuccessful()) {
String json = response.body().string();
if (json == null) {
return null;
}
return gson.fromJson(json, FeedbackResponse.class);
}
return null;
});
}
/**
* This takes userName as input, which is then used to fetch the no of images deleted
* using OkHttp and JavaRx. This function return JSONObject
* @param userName
* @return
*/
@NonNull
@Override
public Single<JSONObject> getRevertRespObjectSingle(String userName){
final String fetchRevertCountUrlTemplate =
wikiMediaToolforgeUrl + "urbanecmbot/commonsmisc/feedback.py";
return Single.fromCallable(() -> {
String url = String.format(
Locale.ENGLISH,
fetchRevertCountUrlTemplate,
new PageTitle(userName).getText());
HttpUrl.Builder urlBuilder = HttpUrl.parse(url).newBuilder();
urlBuilder.addQueryParameter("user", userName);
urlBuilder.addQueryParameter("fetch","deletedUploads");
Log.i("url", urlBuilder.toString());
Request request = new Request.Builder()
.url(urlBuilder.toString())
.build();
OkHttpClient client = new OkHttpClient();
Response response = client.newCall(request).execute();
String jsonData = response.body().string();
JSONObject jsonRevertObject = new JSONObject(jsonData);
return jsonRevertObject;
});
}
private Date parseMWDate(String mwDate) {
SimpleDateFormat isoFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.ENGLISH); // Assuming MW always gives me UTC
isoFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
@ -1023,4 +1007,15 @@ public class ApacheHttpClientMediaWikiApi implements MediaWikiApi {
}
}
/**
* Calls media wiki's logout API
*/
public void logout() {
try {
api.logout();
} catch (IOException e) {
Timber.e(e, "Error occurred while logging out");
}
}
}

View file

@ -167,6 +167,8 @@ public class CustomMwApi {
// I should be doing more validation here, but meh
isLoggedIn = false;
this.action("logout").post();
removeAllCookies();
authCookie = null;
}
private CustomApiResult makeRequest(String method, HashMap<String, Object> params) throws IOException {

View file

@ -4,13 +4,12 @@ import android.net.Uri;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import org.json.JSONObject;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import fr.free.nrw.commons.Media;
import fr.free.nrw.commons.achievements.FeedbackResponse;
import fr.free.nrw.commons.notification.Notification;
import io.reactivex.Observable;
import io.reactivex.Single;
@ -98,13 +97,11 @@ public interface MediaWikiApi {
@NonNull
Single<Integer> getUploadCount(String userName);
@NonNull
Single<JSONObject> getRevertRespObjectSingle(String userName);
boolean isUserBlockedFromCommons();
@NonNull
Single<JSONObject> getAchievements(String userName);
Single<FeedbackResponse> getAchievements(String userName);
void logout();
interface ProgressListener {
void onProgress(long transferred, long total);