(Bug 41703) Validate user tokens & re-login if necessary

Now we send out a request before every upload to check if
the user is logged in. If not, we re-login.

Need to study this more - this adds a little bit of extra latency
to every upload. But if the upload fails because of a login failure,
it will mean we'll have to re-upload the entire thing. Choices.

Also added a debug method to convert XML object to a String. Was
amazed at the power of Java being able to make such a complex task
accomplishable by a single line </s>
This commit is contained in:
YuviPanda 2012-11-02 23:22:29 +05:30
parent 496413da22
commit 11685e5ec1
2 changed files with 73 additions and 1 deletions

View file

@ -1,7 +1,15 @@
package org.wikimedia.commons; package org.wikimedia.commons;
import java.io.IOException;
import java.io.StringWriter;
import javax.xml.transform.*;
import android.accounts.*;
import android.app.Application; import android.app.Application;
import org.mediawiki.api.*; import org.mediawiki.api.*;
import org.w3c.dom.Node;
import org.wikimedia.commons.auth.WikiAccountAuthenticator;
import org.apache.http.HttpVersion; import org.apache.http.HttpVersion;
import org.apache.http.conn.ConnectionKeepAliveStrategy; import org.apache.http.conn.ConnectionKeepAliveStrategy;
import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.impl.client.DefaultHttpClient;
@ -34,4 +42,50 @@ public class CommonsApplication extends Application {
return api; return api;
} }
public Boolean revalidateAuthToken() {
AccountManager accountManager = AccountManager.get(this);
Account[] allAccounts =accountManager.getAccountsByType(WikiAccountAuthenticator.COMMONS_ACCOUNT_TYPE);
Account curAccount = allAccounts[0];
accountManager.invalidateAuthToken(WikiAccountAuthenticator.COMMONS_ACCOUNT_TYPE, api.getAuthCookie());
try {
String authCookie = accountManager.blockingGetAuthToken(curAccount, "", false);
api.setAuthCookie(authCookie);
return true;
} catch (OperationCanceledException e) {
e.printStackTrace();
return false;
} catch (AuthenticatorException e) {
e.printStackTrace();
return false;
} catch (IOException e) {
e.printStackTrace();
return false;
}
}
public static String getStringFromDOM(Node dom) {
javax.xml.transform.Transformer transformer = null;
try {
transformer = TransformerFactory.newInstance().newTransformer();
} catch (TransformerConfigurationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (TransformerFactoryConfigurationError e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
StringWriter outputStream = new StringWriter();
javax.xml.transform.dom.DOMSource domSource = new javax.xml.transform.dom.DOMSource(dom);
javax.xml.transform.stream.StreamResult strResult = new javax.xml.transform.stream.StreamResult(outputStream);
try {
transformer.transform(domSource, strResult);
} catch (TransformerException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return outputStream.toString();
}
} }

View file

@ -25,6 +25,8 @@ public class UploadService extends IntentService {
public static final String EXTRA_EDIT_SUMMARY = EXTRA_PREFIX + ".summary"; public static final String EXTRA_EDIT_SUMMARY = EXTRA_PREFIX + ".summary";
private NotificationManager notificationManager; private NotificationManager notificationManager;
private CommonsApplication app;
public UploadService(String name) { public UploadService(String name) {
super(name); super(name);
} }
@ -84,12 +86,13 @@ public class UploadService extends IntentService {
public void onCreate() { public void onCreate() {
super.onCreate(); super.onCreate();
notificationManager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE); notificationManager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
app = (CommonsApplication)this.getApplicationContext();
} }
@Override @Override
protected void onHandleIntent(Intent intent) { protected void onHandleIntent(Intent intent) {
MWApi api = ((CommonsApplication)this.getApplicationContext()).getApi(); MWApi api = app.getApi();
InputStream file; InputStream file;
long length; long length;
ApiResult result; ApiResult result;
@ -124,12 +127,26 @@ public class UploadService extends IntentService {
notificationManager.notify(notificationTag, NOTIFICATION_DOWNLOAD_IN_PROGRESS, progressNotification); notificationManager.notify(notificationTag, NOTIFICATION_DOWNLOAD_IN_PROGRESS, progressNotification);
Log.d("Commons", "Just before"); Log.d("Commons", "Just before");
NotificationUpdateProgressListener notificationUpdater = new NotificationUpdateProgressListener(progressNotification, notificationTag, NotificationUpdateProgressListener notificationUpdater = new NotificationUpdateProgressListener(progressNotification, notificationTag,
String.format(getString(R.string.upload_progress_notification_title_in_progress), filename), String.format(getString(R.string.upload_progress_notification_title_in_progress), filename),
String.format(getString(R.string.upload_progress_notification_title_finishing), filename) String.format(getString(R.string.upload_progress_notification_title_finishing), filename)
); );
try { try {
if(!api.validateLogin()) {
// Need to revalidate!
if(app.revalidateAuthToken()) {
Log.d("Commons", "Successfully revalidated token!");
} else {
Log.d("Commons", "Unable to revalidate :(");
// TODO: Put up a new notification, ask them to re-login
notificationManager.cancel(notificationTag, NOTIFICATION_DOWNLOAD_IN_PROGRESS);
Toast failureToast = Toast.makeText(this, R.string.authentication_failed, Toast.LENGTH_LONG);
failureToast.show();
return;
}
}
result = api.upload(filename, file, length, pageContents, editSummary, notificationUpdater); result = api.upload(filename, file, length, pageContents, editSummary, notificationUpdater);
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
@ -142,6 +159,7 @@ public class UploadService extends IntentService {
Intent openUploadedPageIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(descUrl)); Intent openUploadedPageIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(descUrl));
Notification doneNotification = new NotificationCompat.Builder(this) Notification doneNotification = new NotificationCompat.Builder(this)
.setAutoCancel(true)
.setSmallIcon(R.drawable.ic_launcher) .setSmallIcon(R.drawable.ic_launcher)
.setContentTitle(String.format(getString(R.string.upload_completed_notification_title), filename)) .setContentTitle(String.format(getString(R.string.upload_completed_notification_title), filename))
.setContentText(getString(R.string.upload_completed_notification_text)) .setContentText(getString(R.string.upload_completed_notification_text))