Redirect app to login screen when operations in file details view fail due to bad credentials

This commit is contained in:
David A. Velasco 2013-01-17 13:01:51 +01:00
parent 11b88e0fcc
commit 73f8797b75
7 changed files with 99 additions and 32 deletions

View file

@ -44,10 +44,13 @@ import eu.alefzero.webdav.WebdavClient;
import android.accounts.Account;
import android.accounts.AccountManager;
import android.accounts.AccountManagerFuture;
import android.accounts.AuthenticatorException;
import android.accounts.OperationCanceledException;
import android.app.Activity;
import android.content.Context;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
public class OwnCloudClientUtils {
@ -103,6 +106,31 @@ public class OwnCloudClientUtils {
}
public static WebdavClient createOwnCloudClient (Account account, Context appContext, Activity currentActivity) throws OperationCanceledException, AuthenticatorException, IOException {
Uri uri = Uri.parse(AccountUtils.constructFullURLForAccount(appContext, account));
WebdavClient client = createOwnCloudClient(uri, appContext);
AccountManager am = AccountManager.get(appContext);
if (am.getUserData(account, AccountAuthenticator.KEY_SUPPORTS_OAUTH2) != null) { // TODO avoid a call to getUserData here
AccountManagerFuture<Bundle> future = am.getAuthToken(account, AccountAuthenticator.AUTH_TOKEN_TYPE_ACCESS_TOKEN, null, currentActivity, null, null);
Bundle result = future.getResult();
String accessToken = result.getString(AccountManager.KEY_AUTHTOKEN);
//String accessToken = am.blockingGetAuthToken(account, AccountAuthenticator.AUTH_TOKEN_TYPE_ACCESS_TOKEN, false);
if (accessToken == null) throw new AuthenticatorException("WTF!");
client.setBearerCredentials(accessToken); // TODO not assume that the access token is a bearer token
} else {
String username = account.name.substring(0, account.name.lastIndexOf('@'));
//String password = am.getPassword(account);
//String password = am.blockingGetAuthToken(account, AccountAuthenticator.AUTH_TOKEN_TYPE_PASSWORD, false);
AccountManagerFuture<Bundle> future = am.getAuthToken(account, AccountAuthenticator.AUTH_TOKEN_TYPE_PASSWORD, null, currentActivity, null, null);
Bundle result = future.getResult();
String password = result.getString(AccountManager.KEY_AUTHTOKEN);
client.setBasicCredentials(username, password);
}
return client;
}
/**
* Creates a WebdavClient to try a new account before saving it
*

View file

@ -23,8 +23,7 @@ import com.owncloud.android.network.OwnCloudClientUtils;
import android.accounts.Account;
import android.accounts.AccountsException;
import android.accounts.AuthenticatorException;
import android.accounts.OperationCanceledException;
import android.app.Activity;
import android.content.Context;
import android.os.Handler;
import android.util.Log;
@ -57,6 +56,9 @@ public abstract class RemoteOperation implements Runnable {
/** Handler to the thread where mListener methods will be called */
private Handler mListenerHandler = null;
/** Activity */
private Activity mCallerActivity;
/**
* Abstract method to implement the operation in derived classes.
@ -119,13 +121,14 @@ public abstract class RemoteOperation implements Runnable {
* @param listenerHandler Handler associated to the thread where the methods of the listener objects must be called.
* @return Thread were the remote operation is executed.
*/
public final Thread execute(Account account, Context context, OnRemoteOperationListener listener, Handler listenerHandler) {
public final Thread execute(Account account, Context context, OnRemoteOperationListener listener, Handler listenerHandler, Activity callerActivity) {
if (account == null)
throw new IllegalArgumentException("Trying to execute a remote operation with a NULL Account");
if (context == null)
throw new IllegalArgumentException("Trying to execute a remote operation with a NULL Context");
mAccount = account;
mContext = context.getApplicationContext();
mCallerActivity = callerActivity;
mClient = null; // the client instance will be created from mAccount and mContext in the runnerThread to create below
if (listener == null) {
@ -207,15 +210,18 @@ public abstract class RemoteOperation implements Runnable {
try{
if (mClient == null) {
if (mAccount != null && mContext != null) {
mClient = OwnCloudClientUtils.createOwnCloudClient(mAccount, mContext);
if (mCallerActivity != null) {
mClient = OwnCloudClientUtils.createOwnCloudClient(mAccount, mContext, mCallerActivity);
} else {
mClient = OwnCloudClientUtils.createOwnCloudClient(mAccount, mContext);
}
} else {
throw new IllegalStateException("Trying to run a remote operation asynchronously with no client instance or account");
}
}
result = run(mClient);
} catch (IOException e) {
Log.e(TAG, "Error while trying to access to " + mAccount.name, e);
Log.e(TAG, "Error while trying to access to " + mAccount.name, new AccountsException("I/O exception while trying to authorize the account", e));
result = new RemoteOperationResult(e);
} catch (AccountsException e) {
@ -223,6 +229,9 @@ public abstract class RemoteOperation implements Runnable {
result = new RemoteOperationResult(e);
}
if (result == null)
result = run(mClient);
final RemoteOperationResult resultToSend = result;
if (mListenerHandler != null && mListener != null) {
mListenerHandler.post(new Runnable() {
@ -233,6 +242,15 @@ public abstract class RemoteOperation implements Runnable {
});
}
}
/**
* Returns the current client instance to access the remote server.
*
* @return Current client instance to access the remote server.
*/
public final WebdavClient getClient() {
return mClient;
}
}

View file

@ -112,6 +112,8 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
private boolean mStatusCorrect, mIsSslConn;
private RemoteOperationResult mLastSslUntrustedServerResult;
public static final String PARAM_ACCOUNTNAME = "param_Accountname";
public static final String PARAM_USERNAME = "param_Username";
public static final String PARAM_HOSTNAME = "param_Hostname";
@ -196,6 +198,19 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
mStatusText = mStatusIcon = 0;
mStatusCorrect = false;
mIsSslConn = false;
String accountName = getIntent().getExtras().getString(PARAM_ACCOUNTNAME);
String tokenType = getIntent().getExtras().getString(AccountAuthenticator.KEY_AUTH_TOKEN_TYPE);
if (AccountAuthenticator.AUTH_TOKEN_TYPE_ACCESS_TOKEN.equals(tokenType)) {
CheckBox oAuth2Check = (CheckBox) findViewById(R.id.oauth_onOff_check);
oAuth2Check.setChecked(true);
changeViewByOAuth2Check(true);
}
if (accountName != null) {
((TextView) findViewById(R.id.account_username)).setText(accountName.substring(0, accountName.lastIndexOf('@')));
tv.setText(accountName.substring(accountName.lastIndexOf('@') + 1));
}
}
iv.setOnClickListener(this);
iv2.setOnClickListener(this);

View file

@ -658,7 +658,8 @@ public class FileDisplayActivity extends SherlockFragmentActivity implements
operation.execute( AccountUtils.getCurrentOwnCloudAccount(FileDisplayActivity.this),
FileDisplayActivity.this,
FileDisplayActivity.this,
mHandler);
mHandler,
FileDisplayActivity.this);
dialog.dismiss();

View file

@ -18,20 +18,9 @@
package com.owncloud.android.ui.fragment;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.StringRequestEntity;
import org.apache.commons.httpclient.params.HttpConnectionManagerParams;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;
import org.apache.jackrabbit.webdav.client.methods.PropFindMethod;
import org.json.JSONObject;
import org.apache.commons.httpclient.Credentials;
import org.apache.commons.httpclient.UsernamePasswordCredentials;
import android.accounts.Account;
import android.accounts.AccountManager;
@ -66,7 +55,6 @@ import android.widget.TextView;
import android.widget.Toast;
import com.actionbarsherlock.app.SherlockFragment;
import com.owncloud.android.AccountUtils;
import com.owncloud.android.DisplayUtils;
import com.owncloud.android.authenticator.AccountAuthenticator;
import com.owncloud.android.datamodel.FileDataStorageManager;
@ -76,6 +64,7 @@ import com.owncloud.android.files.services.FileObserverService;
import com.owncloud.android.files.services.FileUploader;
import com.owncloud.android.files.services.FileDownloader.FileDownloaderBinder;
import com.owncloud.android.files.services.FileUploader.FileUploaderBinder;
import com.owncloud.android.network.BearerCredentials;
import com.owncloud.android.network.OwnCloudClientUtils;
import com.owncloud.android.operations.OnRemoteOperationListener;
import com.owncloud.android.operations.RemoteOperation;
@ -90,10 +79,8 @@ import com.owncloud.android.ui.activity.FileDisplayActivity;
import com.owncloud.android.ui.activity.TransferServiceGetter;
import com.owncloud.android.ui.dialog.EditNameDialog;
import com.owncloud.android.ui.dialog.EditNameDialog.EditNameDialogListener;
import com.owncloud.android.utils.OwnCloudVersion;
import com.owncloud.android.R;
import eu.alefzero.webdav.WebdavClient;
import eu.alefzero.webdav.WebdavUtils;
/**
@ -308,7 +295,7 @@ public class FileDetailFragment extends SherlockFragment implements
} else {
mLastRemoteOperation = new SynchronizeFileOperation(mFile, null, mStorageManager, mAccount, true, false, getActivity());
mLastRemoteOperation.execute(mAccount, getSherlockActivity(), this, mHandler);
mLastRemoteOperation.execute(mAccount, getSherlockActivity(), this, mHandler, getSherlockActivity());
// update ui
boolean inDisplayActivity = getActivity() instanceof FileDisplayActivity;
@ -422,7 +409,7 @@ public class FileDetailFragment extends SherlockFragment implements
mLastRemoteOperation = new RemoveFileOperation( mFile,
true,
mStorageManager);
mLastRemoteOperation.execute(mAccount, getSherlockActivity(), this, mHandler);
mLastRemoteOperation.execute(mAccount, getSherlockActivity(), this, mHandler, getSherlockActivity());
boolean inDisplayActivity = getActivity() instanceof FileDisplayActivity;
getActivity().showDialog((inDisplayActivity)? FileDisplayActivity.DIALOG_SHORT_WAIT : FileDetailActivity.DIALOG_SHORT_WAIT);
@ -863,7 +850,7 @@ public class FileDetailFragment extends SherlockFragment implements
mAccount,
newFilename,
new FileDataStorageManager(mAccount, getActivity().getContentResolver()));
mLastRemoteOperation.execute(mAccount, getSherlockActivity(), this, mHandler);
mLastRemoteOperation.execute(mAccount, getSherlockActivity(), this, mHandler, getSherlockActivity());
boolean inDisplayActivity = getActivity() instanceof FileDisplayActivity;
getActivity().showDialog((inDisplayActivity)? FileDisplayActivity.DIALOG_SHORT_WAIT : FileDetailActivity.DIALOG_SHORT_WAIT);
}
@ -949,7 +936,19 @@ public class FileDetailFragment extends SherlockFragment implements
*/
@Override
public void onRemoteOperationFinish(RemoteOperation operation, RemoteOperationResult result) {
if (operation.equals(mLastRemoteOperation)) {
if (!result.isSuccess() && result.getCode() == ResultCode.UNAUTHORIZED) {
AccountManager am = AccountManager.get(getSherlockActivity());
//am.invalidateAuthToken(AccountAuthenticator.ACCOUNT_TYPE, OwnCloudClientUtils.getAuthorizationTokenType(operation.getClient().getCredentials()));
Credentials cred = operation.getClient().getCredentials();
if (cred instanceof BearerCredentials) {
am.invalidateAuthToken(AccountAuthenticator.ACCOUNT_TYPE, ((BearerCredentials)cred).getAccessToken());
} else {
am.clearPassword(mAccount);
}
operation.execute(mAccount, getSherlockActivity(), this, mHandler, getSherlockActivity()); // need a new client instance, so avoid retry()
// TODO si el usuario no se autoriza de nuevo, esto genera un bucle infinito; o un error en la creación del objecto cliente
} else {
if (operation instanceof RemoveFileOperation) {
onRemoveFileOperationFinish((RemoveFileOperation)operation, result);

View file

@ -316,7 +316,7 @@ public class OCFileListFragment extends FragmentListView implements EditNameDial
case R.id.download_file_item: {
Account account = AccountUtils.getCurrentOwnCloudAccount(getSherlockActivity());
RemoteOperation operation = new SynchronizeFileOperation(mTargetFile, null, mContainerActivity.getStorageManager(), account, true, false, getSherlockActivity());
operation.execute(account, getSherlockActivity(), mContainerActivity, mHandler);
operation.execute(account, getSherlockActivity(), mContainerActivity, mHandler, getSherlockActivity());
getSherlockActivity().showDialog(FileDisplayActivity.DIALOG_SHORT_WAIT);
return true;
}
@ -478,7 +478,7 @@ public class OCFileListFragment extends FragmentListView implements EditNameDial
AccountUtils.getCurrentOwnCloudAccount(getActivity()),
newFilename,
mContainerActivity.getStorageManager());
operation.execute(AccountUtils.getCurrentOwnCloudAccount(getSherlockActivity()), getSherlockActivity(), mContainerActivity, mHandler);
operation.execute(AccountUtils.getCurrentOwnCloudAccount(getSherlockActivity()), getSherlockActivity(), mContainerActivity, mHandler, getSherlockActivity());
getActivity().showDialog(FileDisplayActivity.DIALOG_SHORT_WAIT);
}
}
@ -491,7 +491,7 @@ public class OCFileListFragment extends FragmentListView implements EditNameDial
RemoteOperation operation = new RemoveFileOperation( mTargetFile,
true,
mContainerActivity.getStorageManager());
operation.execute(AccountUtils.getCurrentOwnCloudAccount(getSherlockActivity()), getSherlockActivity(), mContainerActivity, mHandler);
operation.execute(AccountUtils.getCurrentOwnCloudAccount(getSherlockActivity()), getSherlockActivity(), mContainerActivity, mHandler, getSherlockActivity());
getActivity().showDialog(FileDisplayActivity.DIALOG_SHORT_WAIT);
}

View file

@ -335,4 +335,10 @@ public class WebdavClient extends HttpClient {
}
return super.executeMethod(hostconfig, method, state);
}
public final Credentials getCredentials() {
return mCredentials;
}
}