diff --git a/res/values/oauth.xml b/res/values/oauth.xml index b12b648c7c..66bb225593 100644 --- a/res/values/oauth.xml +++ b/res/values/oauth.xml @@ -1,5 +1,7 @@ - https://frko.surfnetlabs.nl/workshop/php-oauth/authorize.php - https://frko.surfnetlabs.nl/workshop/php-oauth/token.php + + http://owncloud.tuxed.net/oauth/php-oauth/authorize.php + http://owncloud.tuxed.net/oauth/php-oauth/token.php diff --git a/res/values/strings.xml b/res/values/strings.xml index bc35032e3f..21938f09d5 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -111,6 +111,7 @@ Contacts Synchronization failed Synchronization of %1$s could not be completed + Invalid credentials for %1$s Conflicts found %1$d kept-in-sync files could not be sync\'ed Kept-in-sync files failed diff --git a/src/com/owncloud/android/operations/RemoteOperation.java b/src/com/owncloud/android/operations/RemoteOperation.java index bf635a8da9..06a70f703c 100644 --- a/src/com/owncloud/android/operations/RemoteOperation.java +++ b/src/com/owncloud/android/operations/RemoteOperation.java @@ -244,6 +244,7 @@ public abstract class RemoteOperation implements Runnable { repeat = false; if (mCallerActivity != null && mAccount != null && mContext != null && !result.isSuccess() && result.getCode() == ResultCode.UNAUTHORIZED) { + /// fail due to lack of authorization in an operation performed in foreground AccountManager am = AccountManager.get(mContext); Credentials cred = mClient.getCredentials(); if (cred instanceof BearerCredentials) { @@ -252,7 +253,7 @@ public abstract class RemoteOperation implements Runnable { am.clearPassword(mAccount); } mClient = null; - repeat = true; + repeat = true; // when repeated, the creation of a new OwnCloudClient after erasing the saved credentials will trigger the login activity result = null; } } while (repeat); diff --git a/src/com/owncloud/android/syncadapter/FileSyncAdapter.java b/src/com/owncloud/android/syncadapter/FileSyncAdapter.java index 46c088b45d..4eafeac56d 100644 --- a/src/com/owncloud/android/syncadapter/FileSyncAdapter.java +++ b/src/com/owncloud/android/syncadapter/FileSyncAdapter.java @@ -19,7 +19,6 @@ package com.owncloud.android.syncadapter; import java.io.IOException; -import java.net.UnknownHostException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -35,11 +34,11 @@ import com.owncloud.android.operations.RemoteOperationResult; import com.owncloud.android.operations.SynchronizeFolderOperation; import com.owncloud.android.operations.UpdateOCVersionOperation; import com.owncloud.android.operations.RemoteOperationResult.ResultCode; +import com.owncloud.android.ui.activity.AuthenticatorActivity; import com.owncloud.android.ui.activity.ErrorsWhileCopyingHandlerActivity; + import android.accounts.Account; import android.accounts.AccountsException; -import android.accounts.AuthenticatorException; -import android.accounts.OperationCanceledException; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; @@ -249,6 +248,7 @@ public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter { RemoteOperationResult.ResultCode code = failedResult.getCode(); return (code.equals(RemoteOperationResult.ResultCode.SSL_ERROR) || code.equals(RemoteOperationResult.ResultCode.SSL_RECOVERABLE_PEER_UNVERIFIED) || + code.equals(RemoteOperationResult.ResultCode.UNAUTHORIZED) || code.equals(RemoteOperationResult.ResultCode.BAD_OC_VERSION) || code.equals(RemoteOperationResult.ResultCode.INSTANCE_NOT_CONFIGURED)); } @@ -299,12 +299,29 @@ public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter { private void notifyFailedSynchronization() { Notification notification = new Notification(R.drawable.icon, getContext().getString(R.string.sync_fail_ticker), System.currentTimeMillis()); notification.flags |= Notification.FLAG_AUTO_CANCEL; - // TODO put something smart in the contentIntent below + boolean needsToUpdateCredentials = (mLastFailedResult != null && mLastFailedResult.getCode() == ResultCode.UNAUTHORIZED); + // TODO put something smart in the contentIntent below for all the possible errors notification.contentIntent = PendingIntent.getActivity(getContext().getApplicationContext(), (int)System.currentTimeMillis(), new Intent(), 0); - notification.setLatestEventInfo(getContext().getApplicationContext(), - getContext().getString(R.string.sync_fail_ticker), - String.format(getContext().getString(R.string.sync_fail_content), getAccount().name), - notification.contentIntent); + if (needsToUpdateCredentials) { + // let the user update credentials with one click + Intent updateAccountCredentials = new Intent(getContext(), AuthenticatorActivity.class); + updateAccountCredentials.putExtra(AuthenticatorActivity.EXTRA_ACCOUNT, getAccount()); + updateAccountCredentials.putExtra(AuthenticatorActivity.EXTRA_ACTION, AuthenticatorActivity.ACTION_UPDATE_TOKEN); + updateAccountCredentials.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + updateAccountCredentials.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); + updateAccountCredentials.addFlags(Intent.FLAG_FROM_BACKGROUND); + notification.contentIntent = PendingIntent.getActivity(getContext(), (int)System.currentTimeMillis(), updateAccountCredentials, PendingIntent.FLAG_ONE_SHOT); + notification.setLatestEventInfo(getContext().getApplicationContext(), + getContext().getString(R.string.sync_fail_ticker), + String.format(getContext().getString(R.string.sync_fail_content_unauthorized), getAccount().name), + notification.contentIntent); + Log.e(TAG, "NEEDS TO UPDATE CREDENTIALS"); + } else { + notification.setLatestEventInfo(getContext().getApplicationContext(), + getContext().getString(R.string.sync_fail_ticker), + String.format(getContext().getString(R.string.sync_fail_content), getAccount().name), + notification.contentIntent); + } ((NotificationManager) getContext().getSystemService(Context.NOTIFICATION_SERVICE)).notify(R.string.sync_fail_ticker, notification); } diff --git a/src/com/owncloud/android/ui/activity/AuthenticatorActivity.java b/src/com/owncloud/android/ui/activity/AuthenticatorActivity.java index 8c8798c596..8dce3bc2f5 100644 --- a/src/com/owncloud/android/ui/activity/AuthenticatorActivity.java +++ b/src/com/owncloud/android/ui/activity/AuthenticatorActivity.java @@ -186,8 +186,6 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity /// retrieve extras from intent String tokenType = getIntent().getExtras().getString(AccountAuthenticator.KEY_AUTH_TOKEN_TYPE); boolean oAuthRequired = AccountAuthenticator.AUTH_TOKEN_TYPE_ACCESS_TOKEN.equals(tokenType); - mOAuth2Check.setChecked(oAuthRequired); - changeViewByOAuth2Check(oAuthRequired); mAccount = getIntent().getExtras().getParcelable(EXTRA_ACCOUNT); if (mAccount != null) { @@ -199,7 +197,11 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity mHostUrlInput.setText(mHostBaseUrl); String userName = mAccount.name.substring(0, mAccount.name.lastIndexOf('@')); mUsernameInput.setText(userName); + oAuthRequired = (mAccountMgr.getUserData(mAccount, AccountAuthenticator.KEY_SUPPORTS_OAUTH2) != null); } + mOAuth2Check.setChecked(oAuthRequired); + changeViewByOAuth2Check(oAuthRequired); + } else { loadSavedInstanceState(savedInstanceState); @@ -826,11 +828,10 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity boolean isOAuth = mOAuth2Check.isChecked(); if (isOAuth) { response.putString(AccountManager.KEY_AUTHTOKEN, mOAuthAccessToken); - // the next line is unnecessary; the AccountManager does it when receives the response Bundle - // mAccountMgr.setAuthToken(mAccount, AccountAuthenticator.AUTH_TOKEN_TYPE_ACCESS_TOKEN, mOAuthAccessToken); + // the next line is necessary; by now, notifications are calling directly to the AuthenticatorActivity to update, without AccountManager intervention + mAccountMgr.setAuthToken(mAccount, AccountAuthenticator.AUTH_TOKEN_TYPE_ACCESS_TOKEN, mOAuthAccessToken); } else { response.putString(AccountManager.KEY_AUTHTOKEN, mPasswordInput.getText().toString()); - // the next line is not really necessary, because we are using the password as if it was an auth token; but let's keep it there by now mAccountMgr.setPassword(mAccount, mPasswordInput.getText().toString()); } setAccountAuthenticatorResult(response);