Skip to content

Commit

Permalink
Remote wipe
Browse files Browse the repository at this point in the history
Signed-off-by: tobiasKaminsky <tobias@kaminsky.me>
  • Loading branch information
tobiasKaminsky committed Sep 4, 2019
1 parent 53ab465 commit 83b139d
Show file tree
Hide file tree
Showing 8 changed files with 220 additions and 106 deletions.
2 changes: 1 addition & 1 deletion .idea/codeStyles/Project.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -2268,15 +2268,15 @@ public List<OCFile> getVirtualFolderContent(VirtualFolderType type, boolean only
}

public void deleteAllFiles() {
String where = ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?";
String[] whereArgs = new String[]{account.name};
String where = ProviderTableMeta.FILE_ACCOUNT_OWNER + "= ? AND " +
ProviderTableMeta.FILE_PATH + "= ?";
String[] whereArgs = new String[]{account.name, OCFile.ROOT_PATH};

if (getContentResolver() != null) {
getContentResolver().delete(ProviderTableMeta.CONTENT_URI_FILE, where, whereArgs);

getContentResolver().delete(ProviderTableMeta.CONTENT_URI_DIR, where, whereArgs);
} else {
try {
getContentProviderClient().delete(ProviderTableMeta.CONTENT_URI_FILE, where, whereArgs);
getContentProviderClient().delete(ProviderTableMeta.CONTENT_URI_DIR, where, whereArgs);
} catch (RemoteException e) {
Log_OC.e(TAG, "Exception in deleteAllFiles for account " + account.name + ": " + e.getMessage(), e);
}
Expand Down
81 changes: 72 additions & 9 deletions src/main/java/com/owncloud/android/jobs/AccountRemovalJob.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,26 +28,38 @@
import android.accounts.AccountManager;
import android.accounts.AccountManagerCallback;
import android.accounts.AccountManagerFuture;
import android.content.ContentResolver;
import android.content.Context;
import android.text.TextUtils;

import com.evernote.android.job.Job;
import com.evernote.android.job.util.support.PersistableBundleCompat;
import com.google.gson.Gson;
import com.nextcloud.client.account.UserAccountManager;
import com.nextcloud.client.preferences.AppPreferencesImpl;
import com.owncloud.android.MainApp;
import com.owncloud.android.R;
import com.owncloud.android.datamodel.ArbitraryDataProvider;
import com.owncloud.android.datamodel.FileDataStorageManager;
import com.owncloud.android.datamodel.FilesystemDataProvider;
import com.owncloud.android.datamodel.PushConfigurationState;
import com.owncloud.android.datamodel.SyncedFolder;
import com.owncloud.android.datamodel.SyncedFolderProvider;
import com.owncloud.android.datamodel.UploadsStorageManager;
import com.owncloud.android.lib.common.OwnCloudAccount;
import com.owncloud.android.lib.common.OwnCloudClient;
import com.owncloud.android.lib.common.OwnCloudClientManagerFactory;
import com.owncloud.android.lib.common.utils.Log_OC;
import com.owncloud.android.lib.resources.users.RemoteWipeSuccessRemoteOperation;
import com.owncloud.android.ui.activity.ContactsPreferenceActivity;
import com.owncloud.android.ui.events.AccountRemovedEvent;
import com.owncloud.android.utils.EncryptionUtils;
import com.owncloud.android.utils.FileStorageUtils;
import com.owncloud.android.utils.FilesSyncHelper;
import com.owncloud.android.utils.PushUtils;

import org.greenrobot.eventbus.EventBus;
import org.jetbrains.annotations.NotNull;

import java.io.File;
import java.util.ArrayList;
Expand All @@ -65,28 +77,48 @@
public class AccountRemovalJob extends Job implements AccountManagerCallback<Boolean> {
public static final String TAG = "AccountRemovalJob";
public static final String ACCOUNT = "account";
public static final String REMOTE_WIPE = "remote_wipe";

private UploadsStorageManager uploadsStorageManager;
private UserAccountManager accountManager;
private UserAccountManager userAccountManager;

public AccountRemovalJob(UploadsStorageManager uploadStorageManager, UserAccountManager accountManager) {
this.uploadsStorageManager = uploadStorageManager;
this.accountManager = accountManager;
this.userAccountManager = accountManager;
}

@NonNull
@Override
protected Result onRunJob(Params params) {
protected Result onRunJob(@NotNull Params params) {
Context context = MainApp.getAppContext();
PersistableBundleCompat bundle = params.getExtras();
Account account = accountManager.getAccountByName(bundle.getString(ACCOUNT, ""));
AccountManager am = (AccountManager) context.getSystemService(ACCOUNT_SERVICE);
Account account = userAccountManager.getAccountByName(bundle.getString(ACCOUNT, ""));
AccountManager accountManager = (AccountManager) context.getSystemService(ACCOUNT_SERVICE);
boolean remoteWipe = bundle.getBoolean(REMOTE_WIPE, false);

if (account != null && am != null) {
if (account != null && accountManager != null) {
// disable contact backup job
ContactsPreferenceActivity.cancelContactBackupJobForAccount(context, account);

am.removeAccount(account, this, null);
OwnCloudClient client = null;
try {
OwnCloudAccount ocAccount = new OwnCloudAccount(account, MainApp.getAppContext());
client = OwnCloudClientManagerFactory.getDefaultSingleton().getClientFor(ocAccount,
MainApp.getAppContext());
} catch (Exception e) {
Log_OC.e(this, "Could not create client", e);
}

try {
AccountManagerFuture<Boolean> accountRemoval = accountManager.removeAccount(account, this, null);
boolean removal = accountRemoval.getResult();

if (!removal) {
Log_OC.e(this, "Account removal of " + account.name + " failed!");
}
} catch (Exception e) {
Log_OC.e(this, "Account removal of " + account.name + " failed!", e);
}

FileDataStorageManager storageManager = new FileDataStorageManager(account, context.getContentResolver());

Expand All @@ -99,8 +131,34 @@ protected Result onRunJob(Params params) {
// delete all database entries
storageManager.deleteAllFiles();

// remove contact backup job
ContactsPreferenceActivity.cancelContactBackupJobForAccount(context, account);

ContentResolver contentResolver = context.getContentResolver();

// disable daily backup
ArbitraryDataProvider arbitraryDataProvider = new ArbitraryDataProvider(contentResolver);

arbitraryDataProvider.storeOrUpdateKeyValue(account.name,
ContactsPreferenceActivity.PREFERENCE_CONTACTS_AUTOMATIC_BACKUP,
"false");

String arbitraryDataPushString;

if (!TextUtils.isEmpty(arbitraryDataPushString = arbitraryDataProvider.getValue(
account, PushUtils.KEY_PUSH)) &&
!TextUtils.isEmpty(context.getResources().getString(R.string.push_server_url))) {
Gson gson = new Gson();
PushConfigurationState pushArbitraryData = gson.fromJson(arbitraryDataPushString,
PushConfigurationState.class);
pushArbitraryData.setShouldBeDeleted(true);
arbitraryDataProvider.storeOrUpdateKeyValue(account.name, PushUtils.KEY_PUSH,
gson.toJson(pushArbitraryData));

PushUtils.pushRegistrationToServer(userAccountManager, pushArbitraryData.getPushToken());
}

// remove pending account removal
ArbitraryDataProvider arbitraryDataProvider = new ArbitraryDataProvider(context.getContentResolver());
arbitraryDataProvider.deleteKeyForAccount(account.name, PENDING_FOR_REMOVAL);

// remove synced folders set for account
Expand All @@ -113,7 +171,7 @@ protected Result onRunJob(Params params) {
for (SyncedFolder syncedFolder : syncedFolders) {
if (syncedFolder.getAccount().equals(account.name)) {
arbitraryDataProvider.deleteKeyForAccount(FilesSyncHelper.GLOBAL,
FilesSyncHelper.SYNCEDFOLDERINITIATED + syncedFolder.getId());
FilesSyncHelper.SYNCEDFOLDERINITIATED + syncedFolder.getId());
syncedFolderIds.add(syncedFolder.getId());
}
}
Expand All @@ -132,6 +190,11 @@ protected Result onRunJob(Params params) {
arbitraryDataProvider.deleteKeyForAccount(account.name, EncryptionUtils.PRIVATE_KEY);
arbitraryDataProvider.deleteKeyForAccount(account.name, EncryptionUtils.PUBLIC_KEY);

if (remoteWipe && client != null) {
String authToken = client.getCredentials().getAuthToken();
new RemoteWipeSuccessRemoteOperation(authToken).execute(client);
}

return Result.SUCCESS;
} else {
return Result.FAILURE;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -186,9 +186,11 @@ private int deleteDirectory(SQLiteDatabase db, Uri uri, String where, String...
children.close();
}

count += db.delete(ProviderTableMeta.FILE_TABLE_NAME,
ProviderTableMeta._ID + "=" + uri.getPathSegments().get(1)
+ (!TextUtils.isEmpty(where) ? " AND (" + where + ")" : ""), whereArgs);
if (uri.getPathSegments().size() > 1) {
count += db.delete(ProviderTableMeta.FILE_TABLE_NAME,
ProviderTableMeta._ID + "=" + uri.getPathSegments().get(1)
+ (!TextUtils.isEmpty(where) ? " AND (" + where + ")" : ""), whereArgs);
}

return count;
}
Expand All @@ -203,9 +205,13 @@ private int deleteSingleFile(SQLiteDatabase db, Uri uri, String where, String...
}
Log_OC.d(TAG, "Removing FILE " + remoteId);

count = db.delete(ProviderTableMeta.FILE_TABLE_NAME,
ProviderTableMeta._ID + "=" + uri.getPathSegments().get(1)
+ (!TextUtils.isEmpty(where) ? " AND (" + where + ")" : ""), whereArgs);
if (remoteId == null) {
return 0;
} else {
count = db.delete(ProviderTableMeta.FILE_TABLE_NAME,
ProviderTableMeta._ID + "=" + uri.getPathSegments().get(1)
+ (!TextUtils.isEmpty(where) ? " AND (" + where + ")" : ""), whereArgs);
}
} catch (Exception e) {
Log_OC.d(TAG, "DB-Error removing file!", e);
} finally {
Expand Down Expand Up @@ -476,7 +482,9 @@ private Cursor query(SQLiteDatabase db, Uri uri, String[] projectionArray, Strin
case ROOT_DIRECTORY:
break;
case DIRECTORY:
sqlQuery.appendWhere(ProviderTableMeta.FILE_PARENT + "=" + uri.getPathSegments().get(1));
if (uri.getPathSegments().size() > SINGLE_PATH_SEGMENT) {
sqlQuery.appendWhere(ProviderTableMeta.FILE_PARENT + "=" + uri.getPathSegments().get(1));
}
break;
case SINGLE_FILE:
if (uri.getPathSegments().size() > SINGLE_PATH_SEGMENT) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -496,7 +496,7 @@ private void selectNavigationItem(final MenuItem menuItem) {
case R.id.nav_logout:
mCheckedMenuItem = -1;
menuItem.setChecked(false);
UserInfoActivity.openAccountRemovalConfirmationDialog(getAccount(), getSupportFragmentManager(), true);
UserInfoActivity.openAccountRemovalConfirmationDialog(getAccount(), getSupportFragmentManager());
break;
case R.id.nav_shared:
handleSearchEvents(new SearchEvent("",
Expand Down Expand Up @@ -1427,6 +1427,8 @@ protected void onStop() {
@Subscribe(threadMode = ThreadMode.MAIN)
public void onAccountRemovedEvent(AccountRemovedEvent event) {
updateAccountList();

restart();
}

/**
Expand Down
46 changes: 27 additions & 19 deletions src/main/java/com/owncloud/android/ui/activity/FileActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@
import com.owncloud.android.operations.UpdateShareViaLinkOperation;
import com.owncloud.android.services.OperationsService;
import com.owncloud.android.services.OperationsService.OperationsServiceBinder;
import com.owncloud.android.ui.asynctasks.CheckRemoteWipeTask;
import com.owncloud.android.ui.asynctasks.LoadingVersionNumberTask;
import com.owncloud.android.ui.dialog.ConfirmationDialogFragment;
import com.owncloud.android.ui.dialog.LoadingDialog;
Expand All @@ -81,6 +82,8 @@
import com.owncloud.android.utils.FilesSyncHelper;
import com.owncloud.android.utils.ThemeUtils;

import java.lang.ref.WeakReference;

import javax.inject.Inject;

import androidx.fragment.app.DialogFragment;
Expand Down Expand Up @@ -394,43 +397,48 @@ protected void requestCredentialsUpdate(Context context) {
* be used.
*/
protected void requestCredentialsUpdate(Context context, Account account) {
if (account == null) {
account = getAccount();
}

boolean remoteWipeSupported = accountManager.getServerVersion(account).isRemoteWipeSupported();

if (remoteWipeSupported) {
new CheckRemoteWipeTask(account, new WeakReference<>(this)).execute();
} else {
performCredentialsUpdate(account, context);
}
}

public void performCredentialsUpdate(Account account, Context context) {
try {
/// step 1 - invalidate credentials of current account
if (account == null) {
account = getAccount();
}
OwnCloudClient client;
OwnCloudAccount ocAccount = new OwnCloudAccount(account, context);
client = OwnCloudClientManagerFactory.getDefaultSingleton().removeClientFor(ocAccount);
OwnCloudClient client = OwnCloudClientManagerFactory.getDefaultSingleton().removeClientFor(ocAccount);

if (client != null) {
OwnCloudCredentials cred = client.getCredentials();
if (cred != null) {
AccountManager am = AccountManager.get(context);
if (cred.authTokenExpires()) {
am.invalidateAuthToken(
account.type,
cred.getAuthToken()
);
OwnCloudCredentials credentials = client.getCredentials();
if (credentials != null) {
AccountManager accountManager = AccountManager.get(context);
if (credentials.authTokenExpires()) {
accountManager.invalidateAuthToken(account.type, credentials.getAuthToken());
} else {
am.clearPassword(account);
accountManager.clearPassword(account);
}
}
}

/// step 2 - request credentials to user
Intent updateAccountCredentials = new Intent(this, AuthenticatorActivity.class);
Intent updateAccountCredentials = new Intent(context, AuthenticatorActivity.class);
updateAccountCredentials.putExtra(AuthenticatorActivity.EXTRA_ACCOUNT, account);
updateAccountCredentials.putExtra(
AuthenticatorActivity.EXTRA_ACTION,
AuthenticatorActivity.ACTION_UPDATE_EXPIRED_TOKEN);
AuthenticatorActivity.EXTRA_ACTION,
AuthenticatorActivity.ACTION_UPDATE_EXPIRED_TOKEN);
updateAccountCredentials.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
startActivityForResult(updateAccountCredentials, REQUEST_CODE__UPDATE_CREDENTIALS);

} catch (com.owncloud.android.lib.common.accounts.AccountUtils.AccountNotFoundException e) {
DisplayUtils.showSnackMessage(this, R.string.auth_account_does_not_exist);
}

}

/**
Expand Down
Loading

0 comments on commit 83b139d

Please sign in to comment.