mirror of
https://github.com/nextcloud/android.git
synced 2024-11-25 14:45:47 +03:00
Fixed create folder due to new system (write on server is only performed upon unlock)
added test case for remove file Signed-off-by: tobiasKaminsky <tobias@kaminsky.me>
This commit is contained in:
parent
2dfde203c8
commit
121c6c1f23
9 changed files with 237 additions and 39 deletions
|
@ -32,10 +32,13 @@ import com.owncloud.android.lib.common.accounts.AccountUtils;
|
|||
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||
import com.owncloud.android.lib.resources.e2ee.ToggleEncryptionRemoteOperation;
|
||||
import com.owncloud.android.lib.resources.status.OCCapability;
|
||||
import com.owncloud.android.lib.resources.status.OwnCloudVersion;
|
||||
import com.owncloud.android.lib.resources.users.GetPrivateKeyOperation;
|
||||
import com.owncloud.android.lib.resources.users.GetPublicKeyOperation;
|
||||
import com.owncloud.android.lib.resources.users.SendCSROperation;
|
||||
import com.owncloud.android.lib.resources.users.StorePrivateKeyOperation;
|
||||
import com.owncloud.android.operations.GetCapabilitiesOperation;
|
||||
import com.owncloud.android.operations.RemoveFileOperation;
|
||||
import com.owncloud.android.utils.CsrHelper;
|
||||
import com.owncloud.android.utils.EncryptionUtils;
|
||||
|
@ -52,9 +55,11 @@ import java.io.IOException;
|
|||
import java.security.KeyPair;
|
||||
import java.security.PrivateKey;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
import static com.owncloud.android.lib.resources.status.OwnCloudVersion.nextcloud_19;
|
||||
import static junit.framework.TestCase.assertEquals;
|
||||
import static junit.framework.TestCase.assertNotNull;
|
||||
import static junit.framework.TestCase.assertTrue;
|
||||
import static org.junit.Assume.assumeTrue;
|
||||
|
@ -80,6 +85,12 @@ public class EndToEndRandomIT extends AbstractOnServerIT {
|
|||
|
||||
@Before
|
||||
public void before() {
|
||||
OCCapability capability = getStorageManager().getCapability(account.name);
|
||||
|
||||
if (capability.getVersion().equals(new OwnCloudVersion("0.0.0"))) {
|
||||
// fetch new one
|
||||
assertTrue(new GetCapabilitiesOperation().execute(client, getStorageManager()).isSuccess());
|
||||
}
|
||||
// tests only for NC19+
|
||||
assumeTrue(getStorageManager()
|
||||
.getCapability(account.name)
|
||||
|
@ -282,6 +293,7 @@ public class EndToEndRandomIT extends AbstractOnServerIT {
|
|||
}
|
||||
|
||||
OCFile fileToDelete = files.get(new Random().nextInt(files.size()));
|
||||
assertNotNull(fileToDelete.getRemoteId());
|
||||
|
||||
Log_OC.d(this,
|
||||
"[" + i + "/" + actionCount + "] " +
|
||||
|
@ -395,4 +407,58 @@ public class EndToEndRandomIT extends AbstractOnServerIT {
|
|||
private String generateMnemonicString() {
|
||||
return "1 2 3 4 5 6";
|
||||
}
|
||||
|
||||
public void after() {
|
||||
// remove all encrypted files
|
||||
OCFile root = fileDataStorageManager.getFileByDecryptedRemotePath("/");
|
||||
removeFolder(root);
|
||||
|
||||
// List<OCFile> files = fileDataStorageManager.getFolderContent(root, false);
|
||||
//
|
||||
// for (OCFile child : files) {
|
||||
// removeFolder(child);
|
||||
// }
|
||||
|
||||
assertEquals(0, fileDataStorageManager.getFolderContent(root, false).size());
|
||||
|
||||
super.after();
|
||||
}
|
||||
|
||||
private void removeFolder(OCFile folder) {
|
||||
Log_OC.d(this, "Start removing content of folder: " + folder.getDecryptedRemotePath());
|
||||
|
||||
List<OCFile> children = fileDataStorageManager.getFolderContent(folder, false);
|
||||
|
||||
// remove children
|
||||
for (OCFile child : children) {
|
||||
if (child.isFolder()) {
|
||||
removeFolder(child);
|
||||
|
||||
// remove folder
|
||||
Log_OC.d(this, "Remove folder: " + child.getDecryptedRemotePath());
|
||||
if (!folder.isEncrypted() && child.isEncrypted()) {
|
||||
assertTrue(new ToggleEncryptionRemoteOperation(child.getLocalId(),
|
||||
child.getRemotePath(),
|
||||
false)
|
||||
.execute(client)
|
||||
.isSuccess());
|
||||
|
||||
OCFile f = getStorageManager().getFileByEncryptedRemotePath(child.getRemotePath());
|
||||
f.setEncrypted(false);
|
||||
getStorageManager().saveFile(f);
|
||||
|
||||
child.setEncrypted(false);
|
||||
}
|
||||
} else {
|
||||
Log_OC.d(this, "Remove file: " + child.getDecryptedRemotePath());
|
||||
}
|
||||
|
||||
assertTrue(new RemoveFileOperation(child, false, account, false, targetContext)
|
||||
.execute(client, getStorageManager())
|
||||
.isSuccess()
|
||||
);
|
||||
}
|
||||
|
||||
Log_OC.d(this, "Finished removing content of folder: " + folder.getDecryptedRemotePath());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,7 +9,6 @@ import android.content.ActivityNotFoundException;
|
|||
import android.content.Context;
|
||||
|
||||
import com.facebook.testing.screenshot.Screenshot;
|
||||
import com.nextcloud.client.RetryTestRule;
|
||||
import com.nextcloud.client.account.User;
|
||||
import com.nextcloud.client.account.UserAccountManager;
|
||||
import com.nextcloud.client.account.UserAccountManagerImpl;
|
||||
|
@ -35,7 +34,6 @@ import junit.framework.TestCase;
|
|||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Rule;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
|
@ -61,7 +59,7 @@ import static org.junit.Assert.assertTrue;
|
|||
*/
|
||||
|
||||
public abstract class AbstractIT {
|
||||
@Rule public RetryTestRule retryTestRule = new RetryTestRule();
|
||||
//@Rule public RetryTestRule retryTestRule = new RetryTestRule();
|
||||
|
||||
protected static OwnCloudClient client;
|
||||
protected static Account account;
|
||||
|
|
|
@ -16,6 +16,7 @@ import com.nextcloud.client.device.PowerManagementService;
|
|||
import com.nextcloud.client.network.Connectivity;
|
||||
import com.nextcloud.client.network.ConnectivityService;
|
||||
import com.nextcloud.java.util.Optional;
|
||||
import com.owncloud.android.datamodel.OCFile;
|
||||
import com.owncloud.android.datamodel.UploadsStorageManager;
|
||||
import com.owncloud.android.db.OCUpload;
|
||||
import com.owncloud.android.files.services.FileUploader;
|
||||
|
@ -43,6 +44,7 @@ import java.io.IOException;
|
|||
import androidx.annotation.NonNull;
|
||||
import androidx.test.platform.app.InstrumentationRegistry;
|
||||
|
||||
import static junit.framework.TestCase.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
|
||||
|
@ -111,6 +113,9 @@ public abstract class AbstractOnServerIT extends AbstractIT {
|
|||
@After
|
||||
public void after() {
|
||||
deleteAllFiles();
|
||||
|
||||
OCFile root = fileDataStorageManager.getFileByDecryptedRemotePath("/");
|
||||
assertEquals(0, fileDataStorageManager.getFolderContent(root, false).size());
|
||||
}
|
||||
|
||||
public static void deleteAllFiles() {
|
||||
|
@ -236,5 +241,10 @@ public abstract class AbstractOnServerIT extends AbstractIT {
|
|||
|
||||
RemoteOperationResult result = newUpload.execute(client, getStorageManager());
|
||||
assertTrue(result.getLogMessage(), result.isSuccess());
|
||||
//
|
||||
// shortSleep();
|
||||
// shortSleep();
|
||||
//
|
||||
// assertNotNull(getStorageManager().getFileByDecryptedRemotePath(ocUpload.getRemotePath()).getRemoteId());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,5 +26,7 @@ public class FileDataStorageManagerContentResolverTest extends FileDataStorageMa
|
|||
@Override
|
||||
public void before() {
|
||||
sut = new FileDataStorageManager(account, targetContext.getContentResolver());
|
||||
|
||||
super.before();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,7 +55,13 @@ abstract public class FileDataStorageManagerTest extends AbstractOnServerIT {
|
|||
protected FileDataStorageManager sut;
|
||||
|
||||
@Before
|
||||
abstract public void before();
|
||||
public void before() {
|
||||
// make sure everything is removed
|
||||
sut.deleteAllFiles();
|
||||
sut.deleteVirtuals(VirtualFolderType.PHOTOS);
|
||||
|
||||
assertEquals(0, sut.getAllFiles().size());
|
||||
}
|
||||
|
||||
@After
|
||||
public void after() {
|
||||
|
|
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
*
|
||||
* Nextcloud Android client application
|
||||
*
|
||||
* @author Tobias Kaminsky
|
||||
* Copyright (C) 2020 Tobias Kaminsky
|
||||
* Copyright (C) 2020 Nextcloud GmbH
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.owncloud.android.operations;
|
||||
|
||||
import com.owncloud.android.AbstractOnServerIT;
|
||||
import com.owncloud.android.datamodel.OCFile;
|
||||
import com.owncloud.android.db.OCUpload;
|
||||
import com.owncloud.android.utils.FileStorageUtils;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static junit.framework.TestCase.assertNotNull;
|
||||
import static junit.framework.TestCase.assertTrue;
|
||||
|
||||
public class RemoveFileOperationIT extends AbstractOnServerIT {
|
||||
@Test
|
||||
public void deleteFolder() {
|
||||
String parent = "/test/";
|
||||
String path = parent + "folder1/";
|
||||
assertTrue(new CreateFolderOperation(path, user, targetContext).execute(client, getStorageManager())
|
||||
.isSuccess());
|
||||
|
||||
OCFile folder = getStorageManager().getFileByPath(path);
|
||||
|
||||
assertNotNull(folder);
|
||||
|
||||
assertTrue(new RemoveFileOperation(folder,
|
||||
false,
|
||||
account,
|
||||
false,
|
||||
targetContext)
|
||||
.execute(client, getStorageManager())
|
||||
.isSuccess());
|
||||
|
||||
OCFile parentFolder = getStorageManager().getFileByPath(parent);
|
||||
|
||||
assertNotNull(parentFolder);
|
||||
assertTrue(new RemoveFileOperation(parentFolder,
|
||||
false,
|
||||
account,
|
||||
false,
|
||||
targetContext)
|
||||
.execute(client, getStorageManager())
|
||||
.isSuccess());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deleteFile() {
|
||||
String parent = "/test/";
|
||||
String path = parent + "empty.txt";
|
||||
OCUpload ocUpload = new OCUpload(FileStorageUtils.getSavePath(account.name) + "/empty.txt", path, account.name);
|
||||
|
||||
uploadOCUpload(ocUpload);
|
||||
|
||||
OCFile file = getStorageManager().getFileByPath(path);
|
||||
|
||||
assertNotNull(file);
|
||||
|
||||
assertTrue(new RemoveFileOperation(file,
|
||||
false,
|
||||
account,
|
||||
false,
|
||||
targetContext)
|
||||
.execute(client, getStorageManager())
|
||||
.isSuccess());
|
||||
|
||||
OCFile parentFolder = getStorageManager().getFileByPath(parent);
|
||||
|
||||
assertNotNull(parentFolder);
|
||||
assertTrue(new RemoveFileOperation(parentFolder,
|
||||
false,
|
||||
account,
|
||||
false,
|
||||
targetContext)
|
||||
.execute(client, getStorageManager())
|
||||
.isSuccess());
|
||||
}
|
||||
}
|
|
@ -21,7 +21,6 @@
|
|||
|
||||
package com.owncloud.android.operations;
|
||||
|
||||
import android.accounts.Account;
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.util.Pair;
|
||||
|
@ -159,31 +158,6 @@ public class CreateFolderOperation extends SyncOperation implements OnRemoteOper
|
|||
.execute(client);
|
||||
|
||||
if (result.isSuccess()) {
|
||||
RemoteOperationResult remoteFolderOperationResult = new ReadFolderRemoteOperation(encryptedRemotePath)
|
||||
.execute(client);
|
||||
|
||||
createdRemoteFolder = (RemoteFile) remoteFolderOperationResult.getData().get(0);
|
||||
OCFile newDir = new OCFile(createdRemoteFolder.getRemotePath());
|
||||
newDir.setMimeType(MimeType.DIRECTORY);
|
||||
|
||||
newDir.setParentId(parent.getFileId());
|
||||
newDir.setRemoteId(createdRemoteFolder.getRemoteId());
|
||||
newDir.setModificationTimestamp(System.currentTimeMillis());
|
||||
newDir.setEncrypted(true);
|
||||
newDir.setPermissions(createdRemoteFolder.getPermissions());
|
||||
newDir.setDecryptedRemotePath(parent.getDecryptedRemotePath() + filename + "/");
|
||||
getStorageManager().saveFile(newDir);
|
||||
|
||||
RemoteOperationResult encryptionOperationResult = new ToggleEncryptionRemoteOperation(
|
||||
newDir.getLocalId(),
|
||||
newDir.getRemotePath(),
|
||||
true)
|
||||
.execute(client);
|
||||
|
||||
if (!encryptionOperationResult.isSuccess()) {
|
||||
throw new RuntimeException("Error creating encrypted subfolder!");
|
||||
}
|
||||
|
||||
// Key, always generate new one
|
||||
byte[] key = EncryptionUtils.generateKey();
|
||||
|
||||
|
@ -212,6 +186,43 @@ public class CreateFolderOperation extends SyncOperation implements OnRemoteOper
|
|||
token,
|
||||
client,
|
||||
metadataExists);
|
||||
|
||||
// unlock folder
|
||||
if (token != null) {
|
||||
RemoteOperationResult unlockFolderResult = EncryptionUtils.unlockFolder(parent, client, token);
|
||||
|
||||
if (unlockFolderResult.isSuccess()) {
|
||||
token = null;
|
||||
} else {
|
||||
// TODO do better
|
||||
throw new RuntimeException("Could not unlock folder!");
|
||||
}
|
||||
}
|
||||
|
||||
RemoteOperationResult remoteFolderOperationResult = new ReadFolderRemoteOperation(encryptedRemotePath)
|
||||
.execute(client);
|
||||
|
||||
createdRemoteFolder = (RemoteFile) remoteFolderOperationResult.getData().get(0);
|
||||
OCFile newDir = new OCFile(createdRemoteFolder.getRemotePath());
|
||||
newDir.setMimeType(MimeType.DIRECTORY);
|
||||
|
||||
newDir.setParentId(parent.getFileId());
|
||||
newDir.setRemoteId(createdRemoteFolder.getRemoteId());
|
||||
newDir.setModificationTimestamp(System.currentTimeMillis());
|
||||
newDir.setEncrypted(true);
|
||||
newDir.setPermissions(createdRemoteFolder.getPermissions());
|
||||
newDir.setDecryptedRemotePath(parent.getDecryptedRemotePath() + filename + "/");
|
||||
getStorageManager().saveFile(newDir);
|
||||
|
||||
RemoteOperationResult encryptionOperationResult = new ToggleEncryptionRemoteOperation(
|
||||
newDir.getLocalId(),
|
||||
newDir.getRemotePath(),
|
||||
true)
|
||||
.execute(client);
|
||||
|
||||
if (!encryptionOperationResult.isSuccess()) {
|
||||
throw new RuntimeException("Error creating encrypted subfolder!");
|
||||
}
|
||||
} else {
|
||||
// revert to sane state in case of any error
|
||||
Log_OC.e(TAG, remotePath + " hasn't been created");
|
||||
|
@ -249,7 +260,6 @@ public class CreateFolderOperation extends SyncOperation implements OnRemoteOper
|
|||
// TODO do better
|
||||
return new RemoteOperationResult(e);
|
||||
} finally {
|
||||
|
||||
// unlock folder
|
||||
if (token != null) {
|
||||
RemoteOperationResult unlockFolderResult = EncryptionUtils.unlockFolder(parent, client, token);
|
||||
|
|
|
@ -106,7 +106,7 @@ public class RemoveFileOperation extends SyncOperation {
|
|||
context,
|
||||
fileToRemove.getEncryptedFileName());
|
||||
} else {
|
||||
operation = new RemoveFileRemoteOperation(fileToRemove.getDecryptedRemotePath());
|
||||
operation = new RemoveFileRemoteOperation(fileToRemove.getRemotePath());
|
||||
}
|
||||
result = operation.execute(client);
|
||||
if (result.isSuccess() || result.getCode() == ResultCode.FILE_NOT_FOUND) {
|
||||
|
|
|
@ -613,6 +613,13 @@ public class UploadFileOperation extends SyncOperation {
|
|||
token,
|
||||
client,
|
||||
metadataExists);
|
||||
|
||||
// unlock
|
||||
result = EncryptionUtils.unlockFolder(parentFile, client, token);
|
||||
|
||||
if (result.isSuccess()) {
|
||||
token = null;
|
||||
}
|
||||
}
|
||||
} catch (FileNotFoundException e) {
|
||||
Log_OC.d(TAG, mFile.getStoragePath() + " not exists anymore");
|
||||
|
@ -650,7 +657,7 @@ public class UploadFileOperation extends SyncOperation {
|
|||
}
|
||||
|
||||
// unlock must be done always
|
||||
// TODO check if in good state
|
||||
if (token != null) {
|
||||
RemoteOperationResult unlockFolderResult = EncryptionUtils.unlockFolder(parentFile,
|
||||
client,
|
||||
token);
|
||||
|
@ -658,6 +665,7 @@ public class UploadFileOperation extends SyncOperation {
|
|||
if (!unlockFolderResult.isSuccess()) {
|
||||
return unlockFolderResult;
|
||||
}
|
||||
}
|
||||
|
||||
// delete temporal file
|
||||
if (temporalFile != null && temporalFile.exists() && !temporalFile.delete()) {
|
||||
|
|
Loading…
Reference in a new issue