mirror of
https://github.com/owncloud/android-library.git
synced 2025-06-07 16:06:08 +00:00
Invalidate the client token when access token expires and try the last operation [WIP]
This commit is contained in:
parent
fe947194c5
commit
a1b1c2f9ed
@ -1,5 +1,5 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2016 ownCloud GmbH.
|
||||
* Copyright (C) 2017 ownCloud GmbH.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@ -45,58 +45,75 @@ import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Operation which execution involves one or several interactions with an ownCloud server.
|
||||
*
|
||||
*
|
||||
* Provides methods to execute the operation both synchronously or asynchronously.
|
||||
*
|
||||
* @author David A. Velasco
|
||||
*
|
||||
* @author David A. Velasco
|
||||
* @author David González Verdugo
|
||||
*/
|
||||
public abstract class RemoteOperation implements Runnable {
|
||||
|
||||
|
||||
private static final String TAG = RemoteOperation.class.getSimpleName();
|
||||
|
||||
/** OCS API header name */
|
||||
/**
|
||||
* OCS API header name
|
||||
*/
|
||||
public static final String OCS_API_HEADER = "OCS-APIREQUEST";
|
||||
|
||||
/** OCS API header value */
|
||||
/**
|
||||
* OCS API header value
|
||||
*/
|
||||
public static final String OCS_API_HEADER_VALUE = "true";
|
||||
|
||||
/** ownCloud account in the remote ownCloud server to operate */
|
||||
/**
|
||||
* ownCloud account in the remote ownCloud server to operate
|
||||
*/
|
||||
private Account mAccount = null;
|
||||
|
||||
/** Android Application context */
|
||||
private Context mContext = null;
|
||||
|
||||
/** Object to interact with the remote server */
|
||||
private OwnCloudClient mClient = null;
|
||||
|
||||
/** Callback object to notify about the execution of the remote operation */
|
||||
private OnRemoteOperationListener mListener = null;
|
||||
|
||||
/** Handler to the thread where mListener methods will be called */
|
||||
private Handler mListenerHandler = null;
|
||||
|
||||
/** Activity */
|
||||
/**
|
||||
* Android Application context
|
||||
*/
|
||||
private Context mContext = null;
|
||||
|
||||
/**
|
||||
* Object to interact with the remote server
|
||||
*/
|
||||
private OwnCloudClient mClient = null;
|
||||
|
||||
/**
|
||||
* Callback object to notify about the execution of the remote operation
|
||||
*/
|
||||
private OnRemoteOperationListener mListener = null;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
protected abstract RemoteOperationResult run(OwnCloudClient client);
|
||||
|
||||
|
||||
/**
|
||||
* Abstract method to implement the operation in derived classes.
|
||||
*/
|
||||
protected abstract RemoteOperationResult run(OwnCloudClient client);
|
||||
|
||||
|
||||
/**
|
||||
* Synchronously executes the remote operation on the received ownCloud account.
|
||||
*
|
||||
*
|
||||
* Do not call this method from the main thread.
|
||||
*
|
||||
*
|
||||
* This method should be used whenever an ownCloud account is available, instead of
|
||||
* {@link #execute(OwnCloudClient)}.
|
||||
*
|
||||
* @param account ownCloud account in remote ownCloud server to reach during the
|
||||
* execution of the operation.
|
||||
* @param context Android context for the component calling the method.
|
||||
* @return Result of the operation.
|
||||
*
|
||||
* @param account ownCloud account in remote ownCloud server to reach during the
|
||||
* execution of the operation.
|
||||
* @param context Android context for the component calling the method.
|
||||
* @return Result of the operation.
|
||||
*/
|
||||
public RemoteOperationResult execute(Account account, Context context) {
|
||||
if (account == null)
|
||||
@ -108,54 +125,53 @@ public abstract class RemoteOperation implements Runnable {
|
||||
mAccount = account;
|
||||
mContext = context.getApplicationContext();
|
||||
try {
|
||||
OwnCloudAccount ocAccount = new OwnCloudAccount(mAccount, mContext);
|
||||
OwnCloudAccount ocAccount = new OwnCloudAccount(mAccount, mContext);
|
||||
mClient = OwnCloudClientManagerFactory.getDefaultSingleton().
|
||||
getClientFor(ocAccount, mContext);
|
||||
getClientFor(ocAccount, mContext);
|
||||
} catch (Exception e) {
|
||||
Log_OC.e(TAG, "Error while trying to access to " + mAccount.name, e);
|
||||
return new RemoteOperationResult(e);
|
||||
}
|
||||
return run(mClient);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Synchronously executes the remote operation
|
||||
*
|
||||
* Do not call this method from the main thread.
|
||||
*
|
||||
* @param client Client object to reach an ownCloud server during the execution of
|
||||
* the operation.
|
||||
* @return Result of the operation.
|
||||
*/
|
||||
public RemoteOperationResult execute(OwnCloudClient client) {
|
||||
if (client == null)
|
||||
throw new IllegalArgumentException("Trying to execute a remote operation with a NULL " +
|
||||
"OwnCloudClient");
|
||||
mClient = client;
|
||||
return run(client);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Synchronously executes the remote operation
|
||||
*
|
||||
* Do not call this method from the main thread.
|
||||
*
|
||||
* @param client Client object to reach an ownCloud server during the execution of
|
||||
* the operation.
|
||||
* @return Result of the operation.
|
||||
*/
|
||||
public RemoteOperationResult execute(OwnCloudClient client) {
|
||||
if (client == null)
|
||||
throw new IllegalArgumentException("Trying to execute a remote operation with a NULL " +
|
||||
"OwnCloudClient");
|
||||
mClient = client;
|
||||
return run(client);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Asynchronously executes the remote operation
|
||||
*
|
||||
*
|
||||
* This method should be used whenever an ownCloud account is available, instead of
|
||||
* {@link #execute(OwnCloudClient)}.
|
||||
*
|
||||
* @deprecated This method will be removed in version 1.0.
|
||||
* Use {@link #execute(Account, Context, OnRemoteOperationListener,
|
||||
* Handler)} instead.
|
||||
*
|
||||
* @param account ownCloud account in remote ownCloud server to reach during
|
||||
* the execution of the operation.
|
||||
* @param context Android context for the component calling the method.
|
||||
* @param listener Listener to be notified about the execution of the operation.
|
||||
* @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.
|
||||
*
|
||||
* @param account ownCloud account in remote ownCloud server to reach during
|
||||
* the execution of the operation.
|
||||
* @param context Android context for the component calling the method.
|
||||
* @param listener Listener to be notified about the execution of the operation.
|
||||
* @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.
|
||||
* @deprecated This method will be removed in version 1.0.
|
||||
* Use {@link #execute(Account, Context, OnRemoteOperationListener,
|
||||
* Handler)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
@Deprecated
|
||||
public Thread execute(Account account, Context context, OnRemoteOperationListener listener,
|
||||
Handler listenerHandler, Activity callerActivity) {
|
||||
if (account == null)
|
||||
@ -168,34 +184,34 @@ public abstract class RemoteOperation implements Runnable {
|
||||
mContext = context.getApplicationContext();
|
||||
mCallerActivity = callerActivity;
|
||||
mClient = null; // the client instance will be created from mAccount
|
||||
// and mContext in the runnerThread to create below
|
||||
// and mContext in the runnerThread to create below
|
||||
mListener = listener;
|
||||
|
||||
|
||||
mListenerHandler = listenerHandler;
|
||||
|
||||
|
||||
Thread runnerThread = new Thread(this);
|
||||
runnerThread.start();
|
||||
return runnerThread;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Asynchronously executes the remote operation
|
||||
*
|
||||
* This method should be used whenever an ownCloud account is available,
|
||||
*
|
||||
* This method should be used whenever an ownCloud account is available,
|
||||
* instead of {@link #execute(OwnCloudClient, OnRemoteOperationListener, Handler))}.
|
||||
*
|
||||
* @param account ownCloud account in remote ownCloud server to reach during the
|
||||
* execution of the operation.
|
||||
* @param context Android context for the component calling the method.
|
||||
* @param listener Listener to be notified about the execution of the operation.
|
||||
* @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.
|
||||
*
|
||||
* @param account ownCloud account in remote ownCloud server to reach during the
|
||||
* execution of the operation.
|
||||
* @param context Android context for the component calling the method.
|
||||
* @param listener Listener to be notified about the execution of the operation.
|
||||
* @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 Thread execute(Account account, Context context,
|
||||
OnRemoteOperationListener listener, Handler listenerHandler) {
|
||||
|
||||
|
||||
if (account == null)
|
||||
throw new IllegalArgumentException
|
||||
("Trying to execute a remote operation with a NULL Account");
|
||||
@ -206,147 +222,185 @@ public abstract class RemoteOperation implements Runnable {
|
||||
mContext = context.getApplicationContext();
|
||||
mCallerActivity = null;
|
||||
mClient = null; // the client instance will be created from
|
||||
// mAccount and mContext in the runnerThread to create below
|
||||
|
||||
// mAccount and mContext in the runnerThread to create below
|
||||
|
||||
mListener = listener;
|
||||
|
||||
|
||||
mListenerHandler = listenerHandler;
|
||||
|
||||
|
||||
Thread runnerThread = new Thread(this);
|
||||
runnerThread.start();
|
||||
return runnerThread;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Asynchronously executes the remote operation
|
||||
*
|
||||
* @param client Client object to reach an ownCloud server
|
||||
* during the execution of the operation.
|
||||
* @param listener Listener to be notified about the execution of the operation.
|
||||
* @param listenerHandler Handler, if passed in, associated to the thread where the methods of
|
||||
* the listener objects must be called.
|
||||
* @return Thread were the remote operation is executed.
|
||||
*/
|
||||
public Thread execute(OwnCloudClient client,
|
||||
|
||||
/**
|
||||
* Asynchronously executes the remote operation
|
||||
*
|
||||
* @param client Client object to reach an ownCloud server
|
||||
* during the execution of the operation.
|
||||
* @param listener Listener to be notified about the execution of the operation.
|
||||
* @param listenerHandler Handler, if passed in, associated to the thread where the methods of
|
||||
* the listener objects must be called.
|
||||
* @return Thread were the remote operation is executed.
|
||||
*/
|
||||
public Thread execute(OwnCloudClient client,
|
||||
OnRemoteOperationListener listener, Handler listenerHandler) {
|
||||
if (client == null) {
|
||||
throw new IllegalArgumentException
|
||||
if (client == null) {
|
||||
throw new IllegalArgumentException
|
||||
("Trying to execute a remote operation with a NULL OwnCloudClient");
|
||||
}
|
||||
mClient = client;
|
||||
|
||||
if (listener == null) {
|
||||
throw new IllegalArgumentException
|
||||
}
|
||||
mClient = client;
|
||||
|
||||
if (listener == null) {
|
||||
throw new IllegalArgumentException
|
||||
("Trying to execute a remote operation asynchronously " +
|
||||
"without a listener to notiy the result");
|
||||
}
|
||||
mListener = listener;
|
||||
|
||||
if (listenerHandler != null) {
|
||||
}
|
||||
mListener = listener;
|
||||
|
||||
if (listenerHandler != null) {
|
||||
mListenerHandler = listenerHandler;
|
||||
}
|
||||
|
||||
|
||||
Thread runnerThread = new Thread(this);
|
||||
runnerThread.start();
|
||||
return runnerThread;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Asynchronous execution of the operation
|
||||
* started by {@link RemoteOperation#execute(OwnCloudClient,
|
||||
* OnRemoteOperationListener, Handler)},
|
||||
* and result posting.
|
||||
*
|
||||
* TODO refactor && clean the code; now it's a mess
|
||||
*/
|
||||
Thread runnerThread = new Thread(this);
|
||||
runnerThread.start();
|
||||
return runnerThread;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Asynchronous execution of the operation
|
||||
* started by {@link RemoteOperation#execute(OwnCloudClient,
|
||||
* OnRemoteOperationListener, Handler)},
|
||||
* and result posting.
|
||||
*
|
||||
* TODO refactor && clean the code; now it's a mess
|
||||
*/
|
||||
@Override
|
||||
public final void run() {
|
||||
RemoteOperationResult result = null;
|
||||
boolean repeat = false;
|
||||
do {
|
||||
try{
|
||||
try {
|
||||
if (mClient == null) {
|
||||
if (mAccount != null && mContext != null) {
|
||||
/** DEPRECATED BLOCK - will be removed at version 1.0 */
|
||||
/** DEPRECATED BLOCK - will be removed at version 1.0 */
|
||||
if (mCallerActivity != null) {
|
||||
mClient = OwnCloudClientFactory.createOwnCloudClient(
|
||||
mAccount, mContext, mCallerActivity);
|
||||
mAccount, mContext, mCallerActivity);
|
||||
} else {
|
||||
/** EOF DEPRECATED */
|
||||
OwnCloudAccount ocAccount = new OwnCloudAccount(mAccount, mContext);
|
||||
/** EOF DEPRECATED */
|
||||
OwnCloudAccount ocAccount = new OwnCloudAccount(mAccount, mContext);
|
||||
mClient = OwnCloudClientManagerFactory.getDefaultSingleton().
|
||||
getClientFor(ocAccount, mContext);
|
||||
getClientFor(ocAccount, mContext);
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
throw new IllegalStateException("Trying to run a remote operation " +
|
||||
"asynchronously with no client instance or account");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} catch (IOException e) {
|
||||
Log_OC.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) {
|
||||
Log_OC.e(TAG, "Error while trying to access to " + mAccount.name, e);
|
||||
result = new RemoteOperationResult(e);
|
||||
}
|
||||
|
||||
|
||||
if (result == null)
|
||||
result = run(mClient);
|
||||
|
||||
|
||||
repeat = false;
|
||||
/** DEPRECATED BLOCK - will be removed at version 1.0 ; don't trust in this code
|
||||
* to trigger authentication update */
|
||||
if (mCallerActivity != null && mAccount != null && mContext != null &&
|
||||
|
||||
|
||||
AccountManager mAccountManager = AccountManager.get(mContext);
|
||||
|
||||
String isOAuthStr = mAccountManager.getUserData(mAccount,
|
||||
AccountUtils.Constants.KEY_SUPPORTS_OAUTH2);
|
||||
|
||||
Boolean isOAuth = Boolean.valueOf(isOAuthStr);
|
||||
|
||||
/** DEPRECATED BLOCK - will be removed at version 1.0 ; don't trust in this code
|
||||
* to trigger authentication update */
|
||||
if (mAccount != null && mContext != null &&
|
||||
!result.isSuccess() &&
|
||||
ResultCode.UNAUTHORIZED.equals(result.getCode())
|
||||
) {
|
||||
) {
|
||||
/// possible fail due to lack of authorization
|
||||
// in an operation performed in foreground
|
||||
OwnCloudCredentials cred = mClient.getCredentials();
|
||||
if (cred != null) {
|
||||
/// confirmed : unauthorized operation
|
||||
AccountManager am = AccountManager.get(mContext);
|
||||
if (cred.authTokenExpires()) {
|
||||
am.invalidateAuthToken(
|
||||
mAccount.type,
|
||||
cred.getAuthToken()
|
||||
);
|
||||
} else {
|
||||
am.clearPassword(mAccount);
|
||||
|
||||
OwnCloudClient client;
|
||||
OwnCloudAccount ocAccount;
|
||||
|
||||
try {
|
||||
/// Step 1: Invalidate credentials of current account
|
||||
ocAccount = new OwnCloudAccount(mAccount, mContext);
|
||||
client = (OwnCloudClientManagerFactory.getDefaultSingleton().
|
||||
removeClientFor(ocAccount));
|
||||
if (client != null) {
|
||||
AccountManager am = AccountManager.get(mContext);
|
||||
if (cred.authTokenExpires()) {
|
||||
am.invalidateAuthToken( // SAML & OAuth
|
||||
mAccount.type,
|
||||
cred.getAuthToken()
|
||||
);
|
||||
} else { //Basic
|
||||
am.clearPassword(mAccount);
|
||||
}
|
||||
}
|
||||
|
||||
/// Step 2: Get new access token using refresh token
|
||||
// Params needed: clientId, clientSecret (switch credentials), grantype and
|
||||
// refresh token
|
||||
String refreshToken = mAccountManager.getUserData(mAccount,
|
||||
AccountUtils.Constants.KEY_OAUTH2_REFRESH_TOKEN);
|
||||
|
||||
// mClient.executeMethod(postMethod);
|
||||
|
||||
/// Step 3: Save access token in account manager
|
||||
|
||||
} catch (AccountUtils.AccountNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
mClient = null;
|
||||
|
||||
// when repeated, the creation of a new OwnCloudClient after erasing the saved
|
||||
// credentials will trigger the login activity
|
||||
repeat = true;
|
||||
if (isOAuth) {
|
||||
repeat = true;
|
||||
}
|
||||
|
||||
result = null;
|
||||
}
|
||||
}
|
||||
/** EOF DEPRECATED BLOCK **/
|
||||
} while (repeat);
|
||||
|
||||
|
||||
if (mAccount != null && mContext != null) {
|
||||
// Save Client Cookies
|
||||
// Save Client Cookies
|
||||
AccountUtils.saveClient(mClient, mAccount, mContext);
|
||||
}
|
||||
|
||||
|
||||
final RemoteOperationResult resultToSend = result;
|
||||
if (mListenerHandler != null && mListener != null) {
|
||||
mListenerHandler.post(new Runnable() {
|
||||
mListenerHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mListener.onRemoteOperationFinish(RemoteOperation.this, resultToSend);
|
||||
}
|
||||
});
|
||||
}
|
||||
else if(mListener != null) {
|
||||
} else if (mListener != null) {
|
||||
mListener.onRemoteOperationFinish(RemoteOperation.this, resultToSend);
|
||||
}
|
||||
}
|
||||
@ -354,11 +408,10 @@ 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.
|
||||
*
|
||||
* @return Current client instance to access the remote server.
|
||||
*/
|
||||
public final OwnCloudClient getClient() {
|
||||
return mClient;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user