diff options
Diffstat (limited to 'build/integration/files_features')
-rw-r--r-- | build/integration/files_features/checksums.feature | 63 | ||||
-rw-r--r-- | build/integration/files_features/download.feature | 296 | ||||
-rw-r--r-- | build/integration/files_features/external-storage.feature | 127 | ||||
-rw-r--r-- | build/integration/files_features/favorites.feature | 152 | ||||
-rw-r--r-- | build/integration/files_features/metadata.feature | 16 | ||||
-rw-r--r-- | build/integration/files_features/tags.feature | 465 | ||||
-rw-r--r-- | build/integration/files_features/transfer-ownership.feature | 576 | ||||
-rw-r--r-- | build/integration/files_features/trashbin.feature | 84 | ||||
-rw-r--r-- | build/integration/files_features/windows_compatibility.feature | 68 |
9 files changed, 1847 insertions, 0 deletions
diff --git a/build/integration/files_features/checksums.feature b/build/integration/files_features/checksums.feature new file mode 100644 index 00000000000..d797c7a503e --- /dev/null +++ b/build/integration/files_features/checksums.feature @@ -0,0 +1,63 @@ +# SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors +# SPDX-FileCopyrightText: 2016 ownCloud, Inc. +# SPDX-License-Identifier: AGPL-3.0-only +Feature: checksums + + Scenario: Uploading a file with checksum should work + Given user "user0" exists + When user "user0" uploads file "data/textfile.txt" to "/myChecksumFile.txt" with checksum "MD5:d70b40f177b14b470d1756a3c12b963a" + Then The webdav response should have a status code "201" + + Scenario: Uploading a file with checksum should return the checksum in the propfind + Given user "user0" exists + And user "user0" uploads file "data/textfile.txt" to "/myChecksumFile.txt" with checksum "MD5:d70b40f177b14b470d1756a3c12b963a" + When user "user0" request the checksum of "/myChecksumFile.txt" via propfind + Then The webdav checksum should match "MD5:d70b40f177b14b470d1756a3c12b963a" + + Scenario: Uploading a file with checksum should return the checksum in the download header + Given user "user0" exists + And user "user0" uploads file "data/textfile.txt" to "/myChecksumFile.txt" with checksum "MD5:d70b40f177b14b470d1756a3c12b963a" + When user "user0" downloads the file "/myChecksumFile.txt" + Then The header checksum should match "MD5:d70b40f177b14b470d1756a3c12b963a" + + Scenario: Moving a file with checksum should return the checksum in the propfind + Given user "user0" exists + And user "user0" uploads file "data/textfile.txt" to "/myChecksumFile.txt" with checksum "MD5:d70b40f177b14b470d1756a3c12b963a" + When User "user0" moved file "/myChecksumFile.txt" to "/myMovedChecksumFile.txt" + And user "user0" request the checksum of "/myMovedChecksumFile.txt" via propfind + Then The webdav checksum should match "MD5:d70b40f177b14b470d1756a3c12b963a" + + Scenario: Moving file with checksum should return the checksum in the download header + Given user "user0" exists + And user "user0" uploads file "data/textfile.txt" to "/myChecksumFile.txt" with checksum "MD5:d70b40f177b14b470d1756a3c12b963a" + When User "user0" moved file "/myChecksumFile.txt" to "/myMovedChecksumFile.txt" + And user "user0" downloads the file "/myMovedChecksumFile.txt" + Then The header checksum should match "MD5:d70b40f177b14b470d1756a3c12b963a" + + Scenario: Copying a file with checksum should return the checksum in the propfind + Given user "user0" exists + And user "user0" uploads file "data/textfile.txt" to "/myChecksumFile.txt" with checksum "MD5:d70b40f177b14b470d1756a3c12b963a" + When User "user0" copied file "/myChecksumFile.txt" to "/myChecksumFileCopy.txt" + And user "user0" request the checksum of "/myChecksumFileCopy.txt" via propfind + Then The webdav checksum should match "MD5:d70b40f177b14b470d1756a3c12b963a" + + Scenario: Copying file with checksum should return the checksum in the download header + Given user "user0" exists + And user "user0" uploads file "data/textfile.txt" to "/myChecksumFile.txt" with checksum "MD5:d70b40f177b14b470d1756a3c12b963a" + When User "user0" copied file "/myChecksumFile.txt" to "/myChecksumFileCopy.txt" + And user "user0" downloads the file "/myChecksumFileCopy.txt" + Then The header checksum should match "MD5:d70b40f177b14b470d1756a3c12b963a" + + Scenario: Overwriting a file with checksum should remove the checksum and not return it in the propfind + Given user "user0" exists + And user "user0" uploads file "data/textfile.txt" to "/myChecksumFile.txt" with checksum "MD5:d70b40f177b14b470d1756a3c12b963a" + When user "user0" uploads file "data/textfile.txt" to "/myChecksumFile.txt" + And user "user0" request the checksum of "/myChecksumFile.txt" via propfind + Then The webdav checksum should be empty + + Scenario: Overwriting a file with checksum should remove the checksum and not return it in the download header + Given user "user0" exists + And user "user0" uploads file "data/textfile.txt" to "/myChecksumFile.txt" with checksum "MD5:d70b40f177b14b470d1756a3c12b963a" + When user "user0" uploads file "data/textfile.txt" to "/myChecksumFile.txt" + And user "user0" downloads the file "/myChecksumFile.txt" + Then The OC-Checksum header should not be there diff --git a/build/integration/files_features/download.feature b/build/integration/files_features/download.feature new file mode 100644 index 00000000000..f9d4e7e95b9 --- /dev/null +++ b/build/integration/files_features/download.feature @@ -0,0 +1,296 @@ +# SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors +# SPDX-License-Identifier: AGPL-3.0-or-later +Feature: download + + Scenario: downloading 2 small files + Given using new dav path + And user "user0" exists + And User "user0" copies file "/welcome.txt" to "/welcome2.txt" + When user "user0" downloads zip file for entries '"welcome.txt","welcome2.txt"' in folder "/" + Then the downloaded file is a zip file + And the downloaded zip file contains a file named "welcome.txt" with the contents of "/welcome.txt" from "user0" data + And the downloaded zip file contains a file named "welcome2.txt" with the contents of "/welcome2.txt" from "user0" data + + Scenario: downloading a small file and a directory + Given using new dav path + And user "user0" exists + And user "user0" created a folder "/emptySubFolder" + When user "user0" downloads zip file for entries '"welcome.txt","emptySubFolder"' in folder "/" + Then the downloaded file is a zip file + And the downloaded zip file contains a file named "welcome.txt" with the contents of "/welcome.txt" from "user0" data + And the downloaded zip file contains a folder named "emptySubFolder/" + + Scenario: downloading a small file and 2 nested directories + Given using new dav path + And user "user0" exists + And user "user0" created a folder "/subFolder" + And user "user0" created a folder "/subFolder/emptySubSubFolder" + When user "user0" downloads zip file for entries '"welcome.txt","subFolder"' in folder "/" + Then the downloaded file is a zip file + And the downloaded zip file contains a file named "welcome.txt" with the contents of "/welcome.txt" from "user0" data + And the downloaded zip file contains a folder named "subFolder/" + And the downloaded zip file contains a folder named "subFolder/emptySubSubFolder/" + + Scenario: downloading dir with 2 small files + Given using new dav path + And user "user0" exists + And user "user0" created a folder "/sparseFolder" + And User "user0" copies file "/welcome.txt" to "/sparseFolder/welcome.txt" + And User "user0" copies file "/welcome.txt" to "/sparseFolder/welcome2.txt" + When user "user0" downloads zip file for entries '"sparseFolder"' in folder "/" + Then the downloaded file is a zip file + And the downloaded zip file contains a folder named "sparseFolder/" + And the downloaded zip file contains a file named "sparseFolder/welcome.txt" with the contents of "/sparseFolder/welcome.txt" from "user0" data + And the downloaded zip file contains a file named "sparseFolder/welcome2.txt" with the contents of "/sparseFolder/welcome2.txt" from "user0" data + + Scenario: downloading dir with a small file and a directory + Given using new dav path + And user "user0" exists + And user "user0" created a folder "/sparseFolder" + And User "user0" copies file "/welcome.txt" to "/sparseFolder/welcome.txt" + And user "user0" created a folder "/sparseFolder/emptySubFolder" + When user "user0" downloads zip file for entries '"sparseFolder"' in folder "/" + Then the downloaded file is a zip file + And the downloaded zip file contains a folder named "sparseFolder/" + And the downloaded zip file contains a file named "sparseFolder/welcome.txt" with the contents of "/sparseFolder/welcome.txt" from "user0" data + And the downloaded zip file contains a folder named "sparseFolder/emptySubFolder/" + + Scenario: downloading dir with a small file and 2 nested directories + Given using new dav path + And user "user0" exists + And user "user0" created a folder "/sparseFolder" + And User "user0" copies file "/welcome.txt" to "/sparseFolder/welcome.txt" + And user "user0" created a folder "/sparseFolder/subFolder" + And user "user0" created a folder "/sparseFolder/subFolder/emptySubSubFolder" + When user "user0" downloads zip file for entries '"sparseFolder"' in folder "/" + Then the downloaded file is a zip file + And the downloaded zip file contains a folder named "sparseFolder/" + And the downloaded zip file contains a file named "sparseFolder/welcome.txt" with the contents of "/sparseFolder/welcome.txt" from "user0" data + And the downloaded zip file contains a folder named "sparseFolder/subFolder/" + And the downloaded zip file contains a folder named "sparseFolder/subFolder/emptySubSubFolder/" + + Scenario: downloading (from folder) 2 small files + Given using new dav path + And user "user0" exists + And user "user0" created a folder "/baseFolder" + And User "user0" copies file "/welcome.txt" to "/baseFolder/welcome.txt" + And User "user0" copies file "/welcome.txt" to "/baseFolder/welcome2.txt" + When user "user0" downloads zip file for entries '"welcome.txt","welcome2.txt"' in folder "/baseFolder/" + Then the downloaded file is a zip file + And the downloaded zip file contains a file named "welcome.txt" with the contents of "/baseFolder/welcome.txt" from "user0" data + And the downloaded zip file contains a file named "welcome2.txt" with the contents of "/baseFolder/welcome2.txt" from "user0" data + + Scenario: downloading (from folder) a small file and a directory + Given using new dav path + And user "user0" exists + And user "user0" created a folder "/baseFolder" + And User "user0" copies file "/welcome.txt" to "/baseFolder/welcome.txt" + And user "user0" created a folder "/baseFolder/emptySubFolder" + When user "user0" downloads zip file for entries '"welcome.txt","emptySubFolder"' in folder "/baseFolder/" + Then the downloaded file is a zip file + And the downloaded zip file contains a file named "welcome.txt" with the contents of "/baseFolder/welcome.txt" from "user0" data + And the downloaded zip file contains a folder named "emptySubFolder/" + + Scenario: downloading (from folder) a small file and 2 nested directories + Given using new dav path + And user "user0" exists + And user "user0" created a folder "/baseFolder" + And User "user0" copies file "/welcome.txt" to "/baseFolder/welcome.txt" + And user "user0" created a folder "/baseFolder/subFolder" + And user "user0" created a folder "/baseFolder/subFolder/emptySubSubFolder" + When user "user0" downloads zip file for entries '"welcome.txt","subFolder"' in folder "/baseFolder/" + Then the downloaded file is a zip file + And the downloaded zip file contains a file named "welcome.txt" with the contents of "/baseFolder/welcome.txt" from "user0" data + And the downloaded zip file contains a folder named "subFolder/" + And the downloaded zip file contains a folder named "subFolder/emptySubSubFolder/" + + Scenario: downloading (from folder) dir with 2 small files + Given using new dav path + And user "user0" exists + And user "user0" created a folder "/baseFolder" + And user "user0" created a folder "/baseFolder/sparseFolder" + And User "user0" copies file "/welcome.txt" to "/baseFolder/sparseFolder/welcome.txt" + And User "user0" copies file "/welcome.txt" to "/baseFolder/sparseFolder/welcome2.txt" + When user "user0" downloads zip file for entries '"sparseFolder"' in folder "/baseFolder/" + Then the downloaded file is a zip file + And the downloaded zip file contains a folder named "sparseFolder/" + And the downloaded zip file contains a file named "sparseFolder/welcome.txt" with the contents of "/baseFolder/sparseFolder/welcome.txt" from "user0" data + And the downloaded zip file contains a file named "sparseFolder/welcome2.txt" with the contents of "/baseFolder/sparseFolder/welcome2.txt" from "user0" data + + Scenario: downloading (from folder) dir with a small file and a directory + Given using new dav path + And user "user0" exists + And user "user0" created a folder "/baseFolder" + And user "user0" created a folder "/baseFolder/sparseFolder" + And User "user0" copies file "/welcome.txt" to "/baseFolder/sparseFolder/welcome.txt" + And user "user0" created a folder "/baseFolder/sparseFolder/emptySubFolder" + When user "user0" downloads zip file for entries '"sparseFolder"' in folder "/baseFolder/" + Then the downloaded file is a zip file + And the downloaded zip file contains a folder named "sparseFolder/" + And the downloaded zip file contains a file named "sparseFolder/welcome.txt" with the contents of "/baseFolder/sparseFolder/welcome.txt" from "user0" data + And the downloaded zip file contains a folder named "sparseFolder/emptySubFolder/" + + Scenario: downloading (from folder) dir with a small file and 2 nested directories + Given using new dav path + And user "user0" exists + And user "user0" created a folder "/baseFolder" + And user "user0" created a folder "/baseFolder/sparseFolder" + And User "user0" copies file "/welcome.txt" to "/baseFolder/sparseFolder/welcome.txt" + And user "user0" created a folder "/baseFolder/sparseFolder/subFolder" + And user "user0" created a folder "/baseFolder/sparseFolder/subFolder/emptySubSubFolder" + When user "user0" downloads zip file for entries '"sparseFolder"' in folder "/baseFolder/" + Then the downloaded file is a zip file + And the downloaded zip file contains a folder named "sparseFolder/" + And the downloaded zip file contains a file named "sparseFolder/welcome.txt" with the contents of "/baseFolder/sparseFolder/welcome.txt" from "user0" data + And the downloaded zip file contains a folder named "sparseFolder/subFolder/" + And the downloaded zip file contains a folder named "sparseFolder/subFolder/emptySubSubFolder/" + + @large + Scenario: downloading small file and dir with 65524 small files and 9 nested directories + Given using new dav path + And user "user0" exists + And user "user0" created a folder "/crowdedFolder" + And user "user0" created a folder "/crowdedFolder/subFolder1" + And file "/crowdedFolder/subFolder1/test.txt" is created "10000" times in "user0" user data + And invoking occ with "files:scan --path /user0/files/crowdedFolder/subFolder1" + And user "user0" created a folder "/crowdedFolder/subFolder2" + And file "/crowdedFolder/subFolder2/test.txt" is created "10000" times in "user0" user data + And invoking occ with "files:scan --path /user0/files/crowdedFolder/subFolder2" + And user "user0" created a folder "/crowdedFolder/subFolder3" + And file "/crowdedFolder/subFolder3/test.txt" is created "10000" times in "user0" user data + And invoking occ with "files:scan --path /user0/files/crowdedFolder/subFolder3" + And user "user0" created a folder "/crowdedFolder/subFolder4" + And file "/crowdedFolder/subFolder4/test.txt" is created "10000" times in "user0" user data + And invoking occ with "files:scan --path /user0/files/crowdedFolder/subFolder4" + And user "user0" created a folder "/crowdedFolder/subFolder5" + And file "/crowdedFolder/subFolder5/test.txt" is created "10000" times in "user0" user data + And invoking occ with "files:scan --path /user0/files/crowdedFolder/subFolder5" + And user "user0" created a folder "/crowdedFolder/subFolder6" + And file "/crowdedFolder/subFolder6/test.txt" is created "10000" times in "user0" user data + And invoking occ with "files:scan --path /user0/files/crowdedFolder/subFolder6" + And user "user0" created a folder "/crowdedFolder/subFolder7" + And file "/crowdedFolder/subFolder7/test.txt" is created "5524" times in "user0" user data + And invoking occ with "files:scan --path /user0/files/crowdedFolder/subFolder7" + And user "user0" created a folder "/crowdedFolder/subFolder7/subSubFolder" + And user "user0" created a folder "/crowdedFolder/subFolder7/subSubFolder/emptySubSubSubFolder" + When user "user0" downloads zip file for entries '"welcome.txt","crowdedFolder"' in folder "/" + Then the downloaded file is a zip file + And the downloaded zip file contains a file named "welcome.txt" with the contents of "/welcome.txt" from "user0" data + And the downloaded zip file contains a folder named "crowdedFolder/" + And the downloaded zip file contains a folder named "crowdedFolder/subFolder1/" + And the downloaded zip file contains a file named "crowdedFolder/subFolder1/test.txt-0" with the contents of "/crowdedFolder/subFolder1/test.txt-0" from "user0" data + And the downloaded zip file contains a file named "crowdedFolder/subFolder7/test.txt-5523" with the contents of "/crowdedFolder/subFolder7/test.txt-5523" from "user0" data + And the downloaded zip file contains a folder named "crowdedFolder/subFolder7/subSubFolder/emptySubSubSubFolder/" + + @large + Scenario: downloading dir with 65525 small files and 9 nested directories + Given using new dav path + And user "user0" exists + And user "user0" created a folder "/crowdedFolder" + And user "user0" created a folder "/crowdedFolder/subFolder1" + And file "/crowdedFolder/subFolder1/test.txt" is created "10000" times in "user0" user data + And invoking occ with "files:scan --path /user0/files/crowdedFolder/subFolder1" + And user "user0" created a folder "/crowdedFolder/subFolder2" + And file "/crowdedFolder/subFolder2/test.txt" is created "10000" times in "user0" user data + And invoking occ with "files:scan --path /user0/files/crowdedFolder/subFolder2" + And user "user0" created a folder "/crowdedFolder/subFolder3" + And file "/crowdedFolder/subFolder3/test.txt" is created "10000" times in "user0" user data + And invoking occ with "files:scan --path /user0/files/crowdedFolder/subFolder3" + And user "user0" created a folder "/crowdedFolder/subFolder4" + And file "/crowdedFolder/subFolder4/test.txt" is created "10000" times in "user0" user data + And invoking occ with "files:scan --path /user0/files/crowdedFolder/subFolder4" + And user "user0" created a folder "/crowdedFolder/subFolder5" + And file "/crowdedFolder/subFolder5/test.txt" is created "10000" times in "user0" user data + And invoking occ with "files:scan --path /user0/files/crowdedFolder/subFolder5" + And user "user0" created a folder "/crowdedFolder/subFolder6" + And file "/crowdedFolder/subFolder6/test.txt" is created "10000" times in "user0" user data + And invoking occ with "files:scan --path /user0/files/crowdedFolder/subFolder6" + And user "user0" created a folder "/crowdedFolder/subFolder7" + And file "/crowdedFolder/subFolder7/test.txt" is created "5525" times in "user0" user data + And invoking occ with "files:scan --path /user0/files/crowdedFolder/subFolder7" + And user "user0" created a folder "/crowdedFolder/subFolder7/subSubFolder" + And user "user0" created a folder "/crowdedFolder/subFolder7/subSubFolder/emptySubSubSubFolder" + When user "user0" downloads zip file for entries '"crowdedFolder"' in folder "/" + Then the downloaded file is a zip file + And the downloaded zip file contains a folder named "crowdedFolder/" + And the downloaded zip file contains a folder named "crowdedFolder/subFolder1/" + And the downloaded zip file contains a file named "crowdedFolder/subFolder1/test.txt-0" with the contents of "/crowdedFolder/subFolder1/test.txt-0" from "user0" data + And the downloaded zip file contains a file named "crowdedFolder/subFolder7/test.txt-5524" with the contents of "/crowdedFolder/subFolder7/test.txt-5524" from "user0" data + And the downloaded zip file contains a folder named "crowdedFolder/subFolder7/subSubFolder/emptySubSubSubFolder/" + + @large + Scenario: downloading small file and dir with 65524 small files and 10 nested directories returns a zip64 + Given using new dav path + And user "user0" exists + And user "user0" created a folder "/crowdedFolder" + And user "user0" created a folder "/crowdedFolder/subFolder1" + And file "/crowdedFolder/subFolder1/test.txt" is created "10000" times in "user0" user data + And invoking occ with "files:scan --path /user0/files/crowdedFolder/subFolder1" + And user "user0" created a folder "/crowdedFolder/subFolder2" + And file "/crowdedFolder/subFolder2/test.txt" is created "10000" times in "user0" user data + And invoking occ with "files:scan --path /user0/files/crowdedFolder/subFolder2" + And user "user0" created a folder "/crowdedFolder/subFolder3" + And file "/crowdedFolder/subFolder3/test.txt" is created "10000" times in "user0" user data + And invoking occ with "files:scan --path /user0/files/crowdedFolder/subFolder3" + And user "user0" created a folder "/crowdedFolder/subFolder4" + And file "/crowdedFolder/subFolder4/test.txt" is created "10000" times in "user0" user data + And invoking occ with "files:scan --path /user0/files/crowdedFolder/subFolder4" + And user "user0" created a folder "/crowdedFolder/subFolder5" + And file "/crowdedFolder/subFolder5/test.txt" is created "10000" times in "user0" user data + And invoking occ with "files:scan --path /user0/files/crowdedFolder/subFolder5" + And user "user0" created a folder "/crowdedFolder/subFolder6" + And file "/crowdedFolder/subFolder6/test.txt" is created "10000" times in "user0" user data + And invoking occ with "files:scan --path /user0/files/crowdedFolder/subFolder6" + And user "user0" created a folder "/crowdedFolder/subFolder7" + And file "/crowdedFolder/subFolder7/test.txt" is created "5524" times in "user0" user data + And invoking occ with "files:scan --path /user0/files/crowdedFolder/subFolder7" + And user "user0" created a folder "/crowdedFolder/subFolder7/subSubFolder" + And user "user0" created a folder "/crowdedFolder/subFolder7/subSubFolder/emptySubSubSubFolder" + And user "user0" created a folder "/crowdedFolder/subFolder7/emptySubSubFolder" + When user "user0" downloads zip file for entries '"welcome.txt","crowdedFolder"' in folder "/" + Then the downloaded zip file is a zip64 file + And the downloaded zip file contains a file named "welcome.txt" with the contents of "/welcome.txt" from "user0" data + And the downloaded zip file contains a folder named "crowdedFolder/" + And the downloaded zip file contains a folder named "crowdedFolder/subFolder1/" + And the downloaded zip file contains a file named "crowdedFolder/subFolder1/test.txt-0" with the contents of "/crowdedFolder/subFolder1/test.txt-0" from "user0" data + And the downloaded zip file contains a file named "crowdedFolder/subFolder7/test.txt-5523" with the contents of "/crowdedFolder/subFolder7/test.txt-5523" from "user0" data + And the downloaded zip file contains a folder named "crowdedFolder/subFolder7/subSubFolder/emptySubSubSubFolder/" + And the downloaded zip file contains a folder named "crowdedFolder/subFolder7/emptySubSubFolder/" + + @large + Scenario: downloading dir with 65525 small files and 10 nested directories returns a zip64 + Given using new dav path + And user "user0" exists + And user "user0" created a folder "/crowdedFolder" + And user "user0" created a folder "/crowdedFolder/subFolder1" + And file "/crowdedFolder/subFolder1/test.txt" is created "10000" times in "user0" user data + And invoking occ with "files:scan --path /user0/files/crowdedFolder/subFolder1" + And user "user0" created a folder "/crowdedFolder/subFolder2" + And file "/crowdedFolder/subFolder2/test.txt" is created "10000" times in "user0" user data + And invoking occ with "files:scan --path /user0/files/crowdedFolder/subFolder2" + And user "user0" created a folder "/crowdedFolder/subFolder3" + And file "/crowdedFolder/subFolder3/test.txt" is created "10000" times in "user0" user data + And invoking occ with "files:scan --path /user0/files/crowdedFolder/subFolder3" + And user "user0" created a folder "/crowdedFolder/subFolder4" + And file "/crowdedFolder/subFolder4/test.txt" is created "10000" times in "user0" user data + And invoking occ with "files:scan --path /user0/files/crowdedFolder/subFolder4" + And user "user0" created a folder "/crowdedFolder/subFolder5" + And file "/crowdedFolder/subFolder5/test.txt" is created "10000" times in "user0" user data + And invoking occ with "files:scan --path /user0/files/crowdedFolder/subFolder5" + And user "user0" created a folder "/crowdedFolder/subFolder6" + And file "/crowdedFolder/subFolder6/test.txt" is created "10000" times in "user0" user data + And invoking occ with "files:scan --path /user0/files/crowdedFolder/subFolder6" + And user "user0" created a folder "/crowdedFolder/subFolder7" + And file "/crowdedFolder/subFolder7/test.txt" is created "5525" times in "user0" user data + And invoking occ with "files:scan --path /user0/files/crowdedFolder/subFolder7" + And user "user0" created a folder "/crowdedFolder/subFolder7/subSubFolder" + And user "user0" created a folder "/crowdedFolder/subFolder7/subSubFolder/emptySubSubSubFolder" + And user "user0" created a folder "/crowdedFolder/subFolder7/emptySubSubFolder" + When user "user0" downloads zip file for entries '"crowdedFolder"' in folder "/" + Then the downloaded zip file is a zip64 file + And the downloaded zip file contains a folder named "crowdedFolder/" + And the downloaded zip file contains a folder named "crowdedFolder/subFolder1/" + And the downloaded zip file contains a file named "crowdedFolder/subFolder1/test.txt-0" with the contents of "/crowdedFolder/subFolder1/test.txt-0" from "user0" data + And the downloaded zip file contains a file named "crowdedFolder/subFolder7/test.txt-5524" with the contents of "/crowdedFolder/subFolder7/test.txt-5524" from "user0" data + And the downloaded zip file contains a folder named "crowdedFolder/subFolder7/subSubFolder/emptySubSubSubFolder/" + And the downloaded zip file contains a folder named "crowdedFolder/subFolder7/emptySubSubFolder/" diff --git a/build/integration/files_features/external-storage.feature b/build/integration/files_features/external-storage.feature new file mode 100644 index 00000000000..77abeb6c5a4 --- /dev/null +++ b/build/integration/files_features/external-storage.feature @@ -0,0 +1,127 @@ +# SPDX-FileCopyrightText: 2017-2024 Nextcloud GmbH and Nextcloud contributors +# SPDX-FileCopyrightText: 2016 ownCloud, Inc. +# SPDX-License-Identifier: AGPL-3.0-only +Feature: external-storage + Background: + Given using api version "1" + Given using old dav path + + @local_storage + Scenario: Share by link a file inside a local external storage + Given user "user0" exists + And user "user1" exists + And As an "user0" + And user "user0" created a folder "/local_storage/foo" + And User "user0" moved file "/textfile0.txt" to "/local_storage/foo/textfile0.txt" + And folder "/local_storage/foo" of user "user0" is shared with user "user1" + And As an "user1" + And accepting last share + When creating a share with + | path | foo | + | shareType | 3 | + Then the OCS status code should be "100" + And the HTTP status code should be "200" + And Share fields of last share match with + | id | A_NUMBER | + | url | AN_URL | + | token | A_TOKEN | + | mimetype | httpd/unix-directory | + + Scenario: Shares don't overwrite external storage + Given user "user0" exists + And user "user1" exists + And As an "user0" + And User "user0" moved file "/textfile0.txt" to "/local_storage/textfile0.txt" + And invoking occ with "files_external:create --user user0 test local null::null -c datadir=./build/integration/work/local_storage" + And invoking occ with "files:scan --path /user0/files/test" + And as "user0" the file "/local_storage/textfile0.txt" exists + And as "user0" the folder "/test" exists + And as "user0" the file "/test/textfile0.txt" exists + And As an "user1" + And user "user1" created a folder "/test" + And User "user1" moved file "/textfile0.txt" to "/test/textfile1.txt" + And folder "/test" of user "user1" is shared with user "user0" + And As an "user0" + Then as "user0" the file "/test/textfile1.txt" does not exist + + Scenario: Move a file into storage works + Given user "user0" exists + And user "user1" exists + And As an "user0" + And user "user0" created a folder "/local_storage/foo1" + When User "user0" moved file "/textfile0.txt" to "/local_storage/foo1/textfile0.txt" + Then as "user1" the file "/local_storage/foo1/textfile0.txt" exists + And as "user0" the file "/local_storage/foo1/textfile0.txt" exists + + Scenario: Move a file out of the storage works + Given user "user0" exists + And user "user1" exists + And As an "user0" + And user "user0" created a folder "/local_storage/foo2" + And User "user0" moved file "/textfile0.txt" to "/local_storage/foo2/textfile0.txt" + When User "user1" moved file "/local_storage/foo2/textfile0.txt" to "/local.txt" + Then as "user1" the file "/local_storage/foo2/textfile0.txt" does not exist + And as "user0" the file "/local_storage/foo2/textfile0.txt" does not exist + And as "user1" the file "/local.txt" exists + + + + Scenario: Save an external storage with password provided by user + Given Logging in using web as "admin" + And logged in user creates external global storage + | mountPoint | "ExternalStorageTest" | + | backend | "owncloud" | + | authMechanism | "password::userprovided" | + | backendOptions | {"host":"http://localhost:8080","secure":false} | + And fields of last external storage match with + | status | 2 | + When logged in user updates last external userglobal storage + | backendOptions | {"user":"admin","password":"admin"} | + Then fields of last external storage match with + | status | 0 | + + Scenario: Save an external storage again with an unmodified password provided by user + Given Logging in using web as "admin" + And logged in user creates external global storage + | mountPoint | "ExternalStorageTest" | + | backend | "owncloud" | + | authMechanism | "password::userprovided" | + | backendOptions | {"host":"http://localhost:8080","secure":false} | + And fields of last external storage match with + | status | 2 | + And logged in user updates last external userglobal storage + | backendOptions | {"user":"admin","password":"admin"} | + When logged in user updates last external userglobal storage + | backendOptions | {"user":"admin","password":"__unmodified__"} | + Then fields of last external storage match with + | status | 0 | + + Scenario: Save an external storage with global credentials provided by user + Given Logging in using web as "admin" + And logged in user creates external global storage + | mountPoint | "ExternalStorageTest" | + | backend | "owncloud" | + | authMechanism | "password::global::user" | + | backendOptions | {"host":"http://localhost:8080","secure":false} | + And fields of last external storage match with + | status | 2 | + When logged in user updates last external userglobal storage + | backendOptions | {"user":"admin","password":"admin"} | + Then fields of last external storage match with + | status | 0 | + + Scenario: Save an external storage again with unmodified global credentials provided by user + Given Logging in using web as "admin" + And logged in user creates external global storage + | mountPoint | "ExternalStorageTest" | + | backend | "owncloud" | + | authMechanism | "password::global::user" | + | backendOptions | {"host":"http://localhost:8080","secure":false} | + And fields of last external storage match with + | status | 2 | + And logged in user updates last external userglobal storage + | backendOptions | {"user":"admin","password":"admin"} | + When logged in user updates last external userglobal storage + | backendOptions | {"user":"admin","password":"__unmodified__"} | + Then fields of last external storage match with + | status | 0 | diff --git a/build/integration/files_features/favorites.feature b/build/integration/files_features/favorites.feature new file mode 100644 index 00000000000..8e510799d20 --- /dev/null +++ b/build/integration/files_features/favorites.feature @@ -0,0 +1,152 @@ +# SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors +# SPDX-FileCopyrightText: 2016 ownCloud, Inc. +# SPDX-License-Identifier: AGPL-3.0-only +Feature: favorite + Background: + Given using api version "1" + + Scenario: Favorite a folder + Given using old dav path + And As an "admin" + And user "user0" exists + When user "user0" favorites element "/FOLDER" + Then as "user0" gets properties of folder "/FOLDER" with + |{http://owncloud.org/ns}favorite| + And the single response should contain a property "{http://owncloud.org/ns}favorite" with value "1" + + Scenario: Favorite and unfavorite a folder + Given using old dav path + And As an "admin" + And user "user0" exists + When user "user0" favorites element "/FOLDER" + And user "user0" unfavorites element "/FOLDER" + Then as "user0" gets properties of folder "/FOLDER" with + |{http://owncloud.org/ns}favorite| + And the single response should contain a property "{http://owncloud.org/ns}favorite" with value "0" + + Scenario: Favorite a file + Given using old dav path + And As an "admin" + And user "user0" exists + When user "user0" favorites element "/textfile0.txt" + Then as "user0" gets properties of file "/textfile0.txt" with + |{http://owncloud.org/ns}favorite| + And the single response should contain a property "{http://owncloud.org/ns}favorite" with value "1" + + Scenario: Favorite and unfavorite a file + Given using old dav path + And As an "admin" + And user "user0" exists + When user "user0" favorites element "/textfile0.txt" + And user "user0" unfavorites element "/textfile0.txt" + Then as "user0" gets properties of file "/textfile0.txt" with + |{http://owncloud.org/ns}favorite| + And the single response should contain a property "{http://owncloud.org/ns}favorite" with value "0" + + Scenario: Favorite a folder new endpoint + Given using new dav path + And As an "admin" + And user "user0" exists + When user "user0" favorites element "/FOLDER" + Then as "user0" gets properties of folder "/FOLDER" with + |{http://owncloud.org/ns}favorite| + And the single response should contain a property "{http://owncloud.org/ns}favorite" with value "1" + + Scenario: Favorite and unfavorite a folder new endpoint + Given using new dav path + And As an "admin" + And user "user0" exists + When user "user0" favorites element "/FOLDER" + And user "user0" unfavorites element "/FOLDER" + Then as "user0" gets properties of folder "/FOLDER" with + |{http://owncloud.org/ns}favorite| + And the single response should contain a property "{http://owncloud.org/ns}favorite" with value "0" + + Scenario: Favorite a file new endpoint + Given using new dav path + And As an "admin" + And user "user0" exists + When user "user0" favorites element "/textfile0.txt" + Then as "user0" gets properties of file "/textfile0.txt" with + |{http://owncloud.org/ns}favorite| + And the single response should contain a property "{http://owncloud.org/ns}favorite" with value "1" + + Scenario: Favorite and unfavorite a file new endpoint + Given using new dav path + And As an "admin" + And user "user0" exists + When user "user0" favorites element "/textfile0.txt" + And user "user0" unfavorites element "/textfile0.txt" + Then as "user0" gets properties of file "/textfile0.txt" with + |{http://owncloud.org/ns}favorite| + And the single response should contain a property "{http://owncloud.org/ns}favorite" with value "0" + + Scenario: Get favorited elements of a folder + Given using old dav path + And As an "admin" + And user "user0" exists + When user "user0" favorites element "/FOLDER" + And user "user0" favorites element "/textfile0.txt" + And user "user0" favorites element "/textfile1.txt" + Then user "user0" in folder "/" should have favorited the following elements + | /FOLDER | + | /textfile0.txt | + | /textfile1.txt | + + Scenario: Get favorited elements of a folder using new path + Given using new dav path + And As an "admin" + And user "user0" exists + When user "user0" favorites element "/FOLDER" + And user "user0" favorites element "/textfile0.txt" + And user "user0" favorites element "/textfile1.txt" + Then user "user0" in folder "/" should have favorited the following elements + | /FOLDER | + | /textfile0.txt | + | /textfile1.txt | + + Scenario: Get favorited elements of a subfolder + Given using old dav path + And As an "admin" + And user "user0" exists + And user "user0" created a folder "/subfolder" + And User "user0" moves file "/textfile0.txt" to "/subfolder/textfile0.txt" + And User "user0" moves file "/textfile1.txt" to "/subfolder/textfile1.txt" + And User "user0" moves file "/textfile2.txt" to "/subfolder/textfile2.txt" + When user "user0" favorites element "/subfolder/textfile0.txt" + And user "user0" favorites element "/subfolder/textfile1.txt" + And user "user0" favorites element "/subfolder/textfile2.txt" + And user "user0" unfavorites element "/subfolder/textfile1.txt" + Then user "user0" in folder "/subfolder" should have favorited the following elements + | /subfolder/textfile0.txt | + | /subfolder/textfile2.txt | + + Scenario: Get favorited elements of a subfolder using new path + Given using old dav path + And As an "admin" + And user "user0" exists + And user "user0" created a folder "/subfolder" + And User "user0" moves file "/textfile0.txt" to "/subfolder/textfile0.txt" + And User "user0" moves file "/textfile1.txt" to "/subfolder/textfile1.txt" + And User "user0" moves file "/textfile2.txt" to "/subfolder/textfile2.txt" + When user "user0" favorites element "/subfolder/textfile0.txt" + And user "user0" favorites element "/subfolder/textfile1.txt" + And user "user0" favorites element "/subfolder/textfile2.txt" + And user "user0" unfavorites element "/subfolder/textfile1.txt" + Then user "user0" in folder "/subfolder" should have favorited the following elements + | /subfolder/textfile0.txt | + | /subfolder/textfile2.txt | + + Scenario: moving a favorite file out of a share keeps favorite state + Given using old dav path + And As an "admin" + And user "user0" exists + And user "user1" exists + And user "user0" created a folder "/shared" + And User "user0" moved file "/textfile0.txt" to "/shared/shared_file.txt" + And folder "/shared" of user "user0" is shared with user "user1" + And user "user1" accepts last share + And user "user1" favorites element "/shared/shared_file.txt" + When User "user1" moved file "/shared/shared_file.txt" to "/taken_out.txt" + Then user "user1" in folder "/" should have favorited the following elements + | /taken_out.txt | diff --git a/build/integration/files_features/metadata.feature b/build/integration/files_features/metadata.feature new file mode 100644 index 00000000000..553a7b62306 --- /dev/null +++ b/build/integration/files_features/metadata.feature @@ -0,0 +1,16 @@ +# SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors +# SPDX-License-Identifier: AGPL-3.0-only +Feature: metadata + + Scenario: Setting metadata works + Given user "user0" exists + When User "user0" uploads file with content "AAA" to "/test.txt" + And User "user0" sets the "metadata-files-live-photo" prop with value "metadata-value" on "/test.txt" + Then User "user0" should see the prop "metadata-files-live-photo" equal to "metadata-value" for file "/test.txt" + + Scenario: Deleting metadata works + Given user "user0" exists + When User "user0" uploads file with content "AAA" to "/test.txt" + And User "user0" sets the "metadata-files-live-photo" prop with value "metadata-value" on "/test.txt" + And User "user0" deletes the "metadata-files-live-photo" prop on "/test.txt" + Then User "user0" should not see the prop "metadata-files-live-photo" for file "/test.txt" diff --git a/build/integration/files_features/tags.feature b/build/integration/files_features/tags.feature new file mode 100644 index 00000000000..fef8068cbc8 --- /dev/null +++ b/build/integration/files_features/tags.feature @@ -0,0 +1,465 @@ +# SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors +# SPDX-FileCopyrightText: 2016 ownCloud, Inc. +# SPDX-License-Identifier: AGPL-3.0-only +Feature: tags + + Scenario: Creating a normal tag as regular user should work + Given user "user0" exists + When "user0" creates a "normal" tag with name "MySuperAwesomeTagName" + Then The response should have a status code "201" + And The following tags should exist for "admin" + |MySuperAwesomeTagName|true|true| + And The following tags should exist for "user0" + |MySuperAwesomeTagName|true|true| + + Scenario: Creating a not user-assignable tag as regular user should fail + Given user "user0" exists + When "user0" creates a "not user-assignable" tag with name "MySuperAwesomeTagName" + Then The response should have a status code "400" + And "0" tags should exist for "admin" + + Scenario: Creating a not user-visible tag as regular user should fail + Given user "user0" exists + When "user0" creates a "not user-visible" tag with name "MySuperAwesomeTagName" + Then The response should have a status code "400" + And "0" tags should exist for "admin" + + Scenario: Creating a not user-assignable tag with groups as admin should work + Given user "user0" exists + When "admin" creates a "not user-assignable" tag with name "TagWithGroups" and groups "group1|group2" + Then The response should have a status code "201" + And The "not user-assignable" tag with name "TagWithGroups" has the groups "group1|group2" + + Scenario: Creating a normal tag with groups as regular user should fail + Given user "user0" exists + When "user0" creates a "normal" tag with name "MySuperAwesomeTagName" and groups "group1|group2" + Then The response should have a status code "400" + And "0" tags should exist for "user0" + + Scenario: Renaming a normal tag as regular user should work + Given user "user0" exists + Given "admin" creates a "normal" tag with name "MySuperAwesomeTagName" + When "user0" edits the tag with name "MySuperAwesomeTagName" and sets its name to "AnotherTagName" + Then The response should have a status code "207" + And The following tags should exist for "admin" + |AnotherTagName|true|true| + + Scenario: Renaming a not user-assignable tag as regular user should fail + Given user "user0" exists + Given "admin" creates a "not user-assignable" tag with name "MySuperAwesomeTagName" + When "user0" edits the tag with name "MySuperAwesomeTagName" and sets its name to "AnotherTagName" + Then The response should have a status code "403" + And The following tags should exist for "admin" + |MySuperAwesomeTagName|true|false| + + Scenario: Renaming a not user-visible tag as regular user should fail + Given user "user0" exists + Given "admin" creates a "not user-visible" tag with name "MySuperAwesomeTagName" + When "user0" edits the tag with name "MySuperAwesomeTagName" and sets its name to "AnotherTagName" + Then The response should have a status code "404" + And The following tags should exist for "admin" + |MySuperAwesomeTagName|false|true| + + Scenario: Editing tag groups as admin should work + Given user "user0" exists + Given "admin" creates a "not user-assignable" tag with name "TagWithGroups" and groups "group1|group2" + When "admin" edits the tag with name "TagWithGroups" and sets its groups to "group1|group3" + Then The response should have a status code "207" + And The "not user-assignable" tag with name "TagWithGroups" has the groups "group1|group3" + + Scenario: Editing tag groups as regular user should fail + Given user "user0" exists + Given "admin" creates a "not user-assignable" tag with name "TagWithGroups" + When "user0" edits the tag with name "TagWithGroups" and sets its groups to "group1|group3" + Then The response should have a status code "403" + + Scenario: Deleting a normal tag as regular user should fail + Given user "user0" exists + Given "admin" creates a "normal" tag with name "MySuperAwesomeTagName" + When "user0" deletes the tag with name "MySuperAwesomeTagName" + Then The response should have a status code "403" + And The following tags should exist for "admin" + |MySuperAwesomeTagName|true|true| + + Scenario: Deleting a not user-assignable tag as regular user should fail + Given user "user0" exists + Given "admin" creates a "not user-assignable" tag with name "MySuperAwesomeTagName" + When "user0" deletes the tag with name "MySuperAwesomeTagName" + Then The response should have a status code "403" + And The following tags should exist for "admin" + |MySuperAwesomeTagName|true|false| + + Scenario: Deleting a not user-visible tag as regular user should fail + Given user "user0" exists + Given "admin" creates a "not user-visible" tag with name "MySuperAwesomeTagName" + When "user0" deletes the tag with name "MySuperAwesomeTagName" + Then The response should have a status code "404" + And The following tags should exist for "admin" + |MySuperAwesomeTagName|false|true| + + Scenario: Deleting a normal tag as admin should work + Given "admin" creates a "normal" tag with name "MySuperAwesomeTagName" + When "admin" deletes the tag with name "MySuperAwesomeTagName" + Then The response should have a status code "204" + And "0" tags should exist for "admin" + + Scenario: Deleting a not user-assignable tag as admin should work + Given "admin" creates a "not user-assignable" tag with name "MySuperAwesomeTagName" + When "admin" deletes the tag with name "MySuperAwesomeTagName" + Then The response should have a status code "204" + And "0" tags should exist for "admin" + + Scenario: Deleting a not user-visible tag as admin should work + Given "admin" creates a "not user-visible" tag with name "MySuperAwesomeTagName" + When "admin" deletes the tag with name "MySuperAwesomeTagName" + Then The response should have a status code "204" + And "0" tags should exist for "admin" + + Scenario: Assigning a normal tag to a file shared by someone else as regular user should work + Given user "user0" exists + Given user "12345" exists + Given "admin" creates a "normal" tag with name "MySuperAwesomeTagName" + Given user "user0" uploads file "data/textfile.txt" to "/myFileToTag.txt" + Given as "user0" creating a share with + | path | myFileToTag.txt | + | shareWith | 12345 | + | shareType | 0 | + Given user "12345" accepts last share + When "12345" adds the tag "MySuperAwesomeTagName" to "/myFileToTag.txt" shared by "user0" + Then The response should have a status code "201" + And "/myFileToTag.txt" shared by "user0" has the following tags + |MySuperAwesomeTagName| + + Scenario: Assigning a normal tag to a file belonging to someone else as regular user should fail + Given user "user0" exists + Given user "user1" exists + Given "admin" creates a "normal" tag with name "MyFirstTag" + Given "admin" creates a "normal" tag with name "MySecondTag" + Given user "user0" uploads file "data/textfile.txt" to "/myFileToTag.txt" + When "user0" adds the tag "MyFirstTag" to "/myFileToTag.txt" shared by "user0" + When "user1" adds the tag "MySecondTag" to "/myFileToTag.txt" shared by "user0" + Then The response should have a status code "404" + And "/myFileToTag.txt" shared by "user0" has the following tags + |MyFirstTag| + + Scenario: Assigning a not user-assignable tag to a file shared by someone else as regular user should fail + Given user "user0" exists + Given user "user1" exists + Given "admin" creates a "normal" tag with name "MyFirstTag" + Given "admin" creates a "not user-assignable" tag with name "MySecondTag" + Given user "user0" uploads file "data/textfile.txt" to "/myFileToTag.txt" + Given as "user0" creating a share with + | path | myFileToTag.txt | + | shareWith | user1 | + | shareType | 0 | + Given user "user1" accepts last share + When "user0" adds the tag "MyFirstTag" to "/myFileToTag.txt" shared by "user0" + When "user1" adds the tag "MySecondTag" to "/myFileToTag.txt" shared by "user0" + Then The response should have a status code "403" + And "/myFileToTag.txt" shared by "user0" has the following tags + |MyFirstTag| + + Scenario: Assigning a not user-assignable tag to a file shared by someone else as regular user belongs to tag's groups should work + Given user "user0" exists + Given user "user1" exists + Given group "group1" exists + Given user "user1" belongs to group "group1" + Given "admin" creates a "not user-assignable" tag with name "MySuperAwesomeTagName" and groups "group1" + Given user "user0" uploads file "data/textfile.txt" to "/myFileToTag.txt" + Given as "user0" creating a share with + | path | myFileToTag.txt | + | shareWith | user1 | + | shareType | 0 | + Given user "user1" accepts last share + When "user1" adds the tag "MySuperAwesomeTagName" to "/myFileToTag.txt" shared by "user0" + Then The response should have a status code "201" + And "/myFileToTag.txt" shared by "user0" has the following tags + |MySuperAwesomeTagName| + + + Scenario: Assigning a not user-visible tag to a file shared by someone else as regular user should fail + Given user "user0" exists + Given user "user1" exists + Given "admin" creates a "normal" tag with name "MyFirstTag" + Given "admin" creates a "not user-visible" tag with name "MySecondTag" + Given user "user0" uploads file "data/textfile.txt" to "/myFileToTag.txt" + Given as "user0" creating a share with + | path | myFileToTag.txt | + | shareWith | user1 | + | shareType | 0 | + Given user "user1" accepts last share + When "user0" adds the tag "MyFirstTag" to "/myFileToTag.txt" shared by "user0" + When "user1" adds the tag "MySecondTag" to "/myFileToTag.txt" shared by "user0" + Then The response should have a status code "412" + And "/myFileToTag.txt" shared by "user0" has the following tags + |MyFirstTag| + + Scenario: Assigning a not user-visible tag to a file shared by someone else as admin user should work + Given user "user0" exists + Given "admin" creates a "normal" tag with name "MyFirstTag" + Given "admin" creates a "not user-visible" tag with name "MySecondTag" + Given user "user0" uploads file "data/textfile.txt" to "/myFileToTag.txt" + Given as "user0" creating a share with + | path | myFileToTag.txt | + | shareWith | admin | + | shareType | 0 | + Given user "admin" accepts last share + When "user0" adds the tag "MyFirstTag" to "/myFileToTag.txt" shared by "user0" + When "admin" adds the tag "MySecondTag" to "/myFileToTag.txt" shared by "user0" + Then The response should have a status code "201" + And "/myFileToTag.txt" shared by "user0" has the following tags for "admin" + |MyFirstTag| + |MySecondTag| + And "/myFileToTag.txt" shared by "user0" has the following tags for "user0" + |MyFirstTag| + + Scenario: Assigning a not user-assignable tag to a file shared by someone else as admin user should worj + Given user "user0" exists + Given "admin" creates a "normal" tag with name "MyFirstTag" + Given "admin" creates a "not user-assignable" tag with name "MySecondTag" + Given user "user0" uploads file "data/textfile.txt" to "/myFileToTag.txt" + Given as "user0" creating a share with + | path | myFileToTag.txt | + | shareWith | admin | + | shareType | 0 | + Given user "admin" accepts last share + When "user0" adds the tag "MyFirstTag" to "/myFileToTag.txt" shared by "user0" + When "admin" adds the tag "MySecondTag" to "/myFileToTag.txt" shared by "user0" + Then The response should have a status code "201" + And "/myFileToTag.txt" shared by "user0" has the following tags for "admin" + |MyFirstTag| + |MySecondTag| + And "/myFileToTag.txt" shared by "user0" has the following tags for "user0" + |MyFirstTag| + |MySecondTag| + + Scenario: Unassigning a normal tag from a file shared by someone else as regular user should work + Given user "user0" exists + Given user "user1" exists + Given "admin" creates a "normal" tag with name "MyFirstTag" + Given "admin" creates a "normal" tag with name "MySecondTag" + Given user "user0" uploads file "data/textfile.txt" to "/myFileToTag.txt" + Given as "user0" creating a share with + | path | myFileToTag.txt | + | shareWith | user1 | + | shareType | 0 | + Given user "user1" accepts last share + Given "user0" adds the tag "MyFirstTag" to "/myFileToTag.txt" shared by "user0" + Given "user0" adds the tag "MySecondTag" to "/myFileToTag.txt" shared by "user0" + When "user1" removes the tag "MyFirstTag" from "/myFileToTag.txt" shared by "user0" + Then The response should have a status code "204" + And "/myFileToTag.txt" shared by "user0" has the following tags for "user0" + |MySecondTag| + + Scenario: Unassigning a normal tag from a file unshared by someone else as regular user should fail + Given user "user0" exists + Given user "user1" exists + Given "admin" creates a "normal" tag with name "MyFirstTag" + Given "admin" creates a "normal" tag with name "MySecondTag" + Given user "user0" uploads file "data/textfile.txt" to "/myFileToTag.txt" + Given "user0" adds the tag "MyFirstTag" to "/myFileToTag.txt" shared by "user0" + Given "user0" adds the tag "MySecondTag" to "/myFileToTag.txt" shared by "user0" + When "user1" removes the tag "MyFirstTag" from "/myFileToTag.txt" shared by "user0" + Then The response should have a status code "404" + And "/myFileToTag.txt" shared by "user0" has the following tags for "user0" + |MyFirstTag| + |MySecondTag| + + Scenario: Unassigning a not user-visible tag from a file shared by someone else as regular user should fail + Given user "user0" exists + Given user "user1" exists + Given "admin" creates a "not user-visible" tag with name "MyFirstTag" + Given "admin" creates a "normal" tag with name "MySecondTag" + Given user "user0" uploads file "data/textfile.txt" to "/myFileToTag.txt" + Given as "user0" creating a share with + | path | myFileToTag.txt | + | shareWith | user1 | + | shareType | 0 | + Given user "user1" accepts last share + Given as "user0" creating a share with + | path | myFileToTag.txt | + | shareWith | admin | + | shareType | 0 | + Given user "admin" accepts last share + Given "admin" adds the tag "MyFirstTag" to "/myFileToTag.txt" shared by "user0" + Given "user0" adds the tag "MySecondTag" to "/myFileToTag.txt" shared by "user0" + When "user1" removes the tag "MyFirstTag" from "/myFileToTag.txt" shared by "user0" + Then The response should have a status code "404" + And "/myFileToTag.txt" shared by "user0" has the following tags for "user0" + |MySecondTag| + And "/myFileToTag.txt" shared by "user0" has the following tags for "admin" + |MyFirstTag| + |MySecondTag| + + Scenario: Unassigning a not user-visible tag from a file shared by someone else as admin should work + Given user "user0" exists + Given user "user1" exists + Given "admin" creates a "not user-visible" tag with name "MyFirstTag" + Given "admin" creates a "normal" tag with name "MySecondTag" + Given user "user0" uploads file "data/textfile.txt" to "/myFileToTag.txt" + Given as "user0" creating a share with + | path | myFileToTag.txt | + | shareWith | user1 | + | shareType | 0 | + Given user "user1" accepts last share + Given as "user0" creating a share with + | path | myFileToTag.txt | + | shareWith | admin | + | shareType | 0 | + Given user "admin" accepts last share + Given "admin" adds the tag "MyFirstTag" to "/myFileToTag.txt" shared by "user0" + Given "user0" adds the tag "MySecondTag" to "/myFileToTag.txt" shared by "user0" + When "admin" removes the tag "MyFirstTag" from "/myFileToTag.txt" shared by "user0" + Then The response should have a status code "204" + And "/myFileToTag.txt" shared by "user0" has the following tags for "user0" + |MySecondTag| + And "/myFileToTag.txt" shared by "user0" has the following tags for "admin" + |MySecondTag| + + Scenario: Unassigning a not user-visible tag from a file unshared by someone else should fail + Given user "user0" exists + Given user "user1" exists + Given "admin" creates a "not user-visible" tag with name "MyFirstTag" + Given "admin" creates a "normal" tag with name "MySecondTag" + Given user "user0" uploads file "data/textfile.txt" to "/myFileToTag.txt" + Given as "user0" creating a share with + | path | myFileToTag.txt | + | shareWith | user1 | + | shareType | 0 | + Given user "user1" accepts last share + Given as "user0" creating a share with + | path | myFileToTag.txt | + | shareWith | admin | + | shareType | 0 | + Given user "admin" accepts last share + Given "admin" adds the tag "MyFirstTag" to "/myFileToTag.txt" shared by "user0" + Given "user0" adds the tag "MySecondTag" to "/myFileToTag.txt" shared by "user0" + Given As "user0" remove all shares from the file named "/myFileToTag.txt" + When "admin" removes the tag "MyFirstTag" from "/myFileToTag.txt" shared by "user0" + Then The response should have a status code "404" + + Scenario: Unassigning a not user-assignable tag from a file shared by someone else as regular user should fail + Given user "user0" exists + Given user "user1" exists + Given "admin" creates a "not user-assignable" tag with name "MyFirstTag" + Given "admin" creates a "normal" tag with name "MySecondTag" + Given user "user0" uploads file "data/textfile.txt" to "/myFileToTag.txt" + Given as "user0" creating a share with + | path | myFileToTag.txt | + | shareWith | user1 | + | shareType | 0 | + Given user "user1" accepts last share + Given as "user0" creating a share with + | path | myFileToTag.txt | + | shareWith | admin | + | shareType | 0 | + Given user "admin" accepts last share + Given "admin" adds the tag "MyFirstTag" to "/myFileToTag.txt" shared by "user0" + Given "user0" adds the tag "MySecondTag" to "/myFileToTag.txt" shared by "user0" + When "user1" removes the tag "MyFirstTag" from "/myFileToTag.txt" shared by "user0" + Then The response should have a status code "403" + And "/myFileToTag.txt" shared by "user0" has the following tags for "user0" + |MyFirstTag| + |MySecondTag| + And "/myFileToTag.txt" shared by "user0" has the following tags for "admin" + |MyFirstTag| + |MySecondTag| + + Scenario: Unassigning a not user-assignable tag from a file shared by someone else as admin should work + Given user "user0" exists + Given user "user1" exists + Given "admin" creates a "not user-assignable" tag with name "MyFirstTag" + Given "admin" creates a "normal" tag with name "MySecondTag" + Given user "user0" uploads file "data/textfile.txt" to "/myFileToTag.txt" + Given as "user0" creating a share with + | path | myFileToTag.txt | + | shareWith | user1 | + | shareType | 0 | + Given user "user1" accepts last share + Given as "user0" creating a share with + | path | myFileToTag.txt | + | shareWith | admin | + | shareType | 0 | + Given user "admin" accepts last share + Given "admin" adds the tag "MyFirstTag" to "/myFileToTag.txt" shared by "user0" + Given "user0" adds the tag "MySecondTag" to "/myFileToTag.txt" shared by "user0" + When "admin" removes the tag "MyFirstTag" from "/myFileToTag.txt" shared by "user0" + Then The response should have a status code "204" + And "/myFileToTag.txt" shared by "user0" has the following tags for "user0" + |MySecondTag| + And "/myFileToTag.txt" shared by "user0" has the following tags for "admin" + |MySecondTag| + + Scenario: Unassigning a not user-assignable tag from a file unshared by someone else should fail + Given user "user0" exists + Given user "user1" exists + Given "admin" creates a "not user-assignable" tag with name "MyFirstTag" + Given "admin" creates a "normal" tag with name "MySecondTag" + Given user "user0" uploads file "data/textfile.txt" to "/myFileToTag.txt" + Given as "user0" creating a share with + | path | myFileToTag.txt | + | shareWith | user1 | + | shareType | 0 | + Given user "user1" accepts last share + Given as "user0" creating a share with + | path | myFileToTag.txt | + | shareWith | admin | + | shareType | 0 | + Given user "admin" accepts last share + Given "admin" adds the tag "MyFirstTag" to "/myFileToTag.txt" shared by "user0" + Given "user0" adds the tag "MySecondTag" to "/myFileToTag.txt" shared by "user0" + Given As "user0" remove all shares from the file named "/myFileToTag.txt" + When "admin" removes the tag "MyFirstTag" from "/myFileToTag.txt" shared by "user0" + Then The response should have a status code "404" + + Scenario: Overwriting existing normal tags should fail + Given user "user0" exists + Given "user0" creates a "normal" tag with name "MyFirstTag" + When "user0" creates a "normal" tag with name "MyFirstTag" + Then The response should have a status code "409" + + Scenario: Overwriting existing not user-assignable tags should fail + Given "admin" creates a "not user-assignable" tag with name "MyFirstTag" + When "admin" creates a "not user-assignable" tag with name "MyFirstTag" + Then The response should have a status code "409" + + Scenario: Overwriting existing not user-visible tags should fail + Given "admin" creates a "not user-visible" tag with name "MyFirstTag" + When "admin" creates a "not user-visible" tag with name "MyFirstTag" + Then The response should have a status code "409" + + Scenario: Getting tags only works with access to the file + Given user "user0" exists + Given user "user1" exists + Given "admin" creates a "normal" tag with name "MyFirstTag" + Given user "user0" uploads file "data/textfile.txt" to "/myFileToTag.txt" + When "user0" adds the tag "MyFirstTag" to "/myFileToTag.txt" shared by "user0" + And "/myFileToTag.txt" shared by "user0" has the following tags for "user0" + |MyFirstTag| + And "/myFileToTag.txt" shared by "user0" has the following tags for "user1" + || + And The response should have a status code "404" + + Scenario: User can assign tags when in the tag's groups + Given user "user0" exists + Given group "group1" exists + Given user "user0" belongs to group "group1" + When "admin" creates a "not user-assignable" tag with name "TagWithGroups" and groups "group1|group2" + Then The response should have a status code "201" + And the user "user0" can assign the "not user-assignable" tag with name "TagWithGroups" + + Scenario: User cannot assign tags when not in the tag's groups + Given user "user0" exists + When "admin" creates a "not user-assignable" tag with name "TagWithGroups" and groups "group1|group2" + Then The response should have a status code "201" + And the user "user0" cannot assign the "not user-assignable" tag with name "TagWithGroups" + + Scenario: Assign a normal tag to a file + Given user "user0" exists + And "admin" creates a "normal" tag with name "Etiqueta" + And As an "user0" + When "user0" adds the tag "Etiqueta" to "/textfile0.txt" owned by "user0" + Then The response should have a status code "201" + And "textfile0.txt" owned by "user0" has the following tags + | Etiqueta | + diff --git a/build/integration/files_features/transfer-ownership.feature b/build/integration/files_features/transfer-ownership.feature new file mode 100644 index 00000000000..6f7a7944166 --- /dev/null +++ b/build/integration/files_features/transfer-ownership.feature @@ -0,0 +1,576 @@ +# SPDX-FileCopyrightText: 2017-2024 Nextcloud GmbH and Nextcloud contributors +# SPDX-FileCopyrightText: 2016 ownCloud, Inc. +# SPDX-License-Identifier: AGPL-3.0-only +Feature: transfer-ownership + + Scenario: transferring ownership of a file + Given user "user0" exists + And user "user1" exists + And User "user0" uploads file "data/textfile.txt" to "/somefile.txt" + When transferring ownership from "user0" to "user1" + And the command was successful + And As an "user1" + And using received transfer folder of "user1" as dav path + Then Downloaded content when downloading file "/somefile.txt" with range "bytes=0-6" should be "This is" + And using old dav path + And as "user0" the file "/somefile.txt" does not exist + And using received transfer folder of "user1" as dav path + And as "user1" the file "/somefile.txt" exists + + Scenario: transferring ownership of a folder + Given user "user0" exists + And user "user1" exists + And User "user0" created a folder "/test" + And User "user0" uploads file "data/textfile.txt" to "/test/somefile.txt" + When transferring ownership from "user0" to "user1" + And the command was successful + And As an "user1" + And using received transfer folder of "user1" as dav path + Then Downloaded content when downloading file "/test/somefile.txt" with range "bytes=0-6" should be "This is" + And using old dav path + And as "user0" the folder "/test" does not exist + And using received transfer folder of "user1" as dav path + And as "user1" the folder "/test" exists + + Scenario: transferring ownership from user with risky display name + Given user "user0" with displayname "user0 \"risky\"? ヂspḷay 'na|\/|e':.#" exists + And user "user1" exists + And User "user0" created a folder "/test" + And User "user0" uploads file "data/textfile.txt" to "/test/somefile.txt" + When transferring ownership from "user0" to "user1" + And the command was successful + And As an "user1" + And using received transfer folder of "user1" as dav path + Then Downloaded content when downloading file "/test/somefile.txt" with range "bytes=0-6" should be "This is" + And transfer folder name contains "Transferred from user0 -risky- ヂspḷay -na|-|e- on" + And using old dav path + And as "user0" the folder "/test" does not exist + And using received transfer folder of "user1" as dav path + And as "user1" the folder "/test" exists + + Scenario: transferring ownership of file shares + Given user "user0" exists + And user "user1" exists + And user "user2" exists + And User "user0" uploads file "data/textfile.txt" to "/somefile.txt" + And file "/somefile.txt" of user "user0" is shared with user "user2" with permissions 19 + And user "user2" accepts last share + When transferring ownership from "user0" to "user1" + And the command was successful + And As an "user2" + Then Downloaded content when downloading file "/somefile.txt" with range "bytes=0-6" should be "This is" + And using old dav path + And as "user0" the file "/somefile.txt" does not exist + And using received transfer folder of "user1" as dav path + And as "user1" the file "/somefile.txt" exists + And As an "user1" + And Getting info of last share + And the OCS status code should be "100" + And Share fields of last share match with + | uid_owner | user1 | + | uid_file_owner | user1 | + | share_with | user2 | + + Scenario: transferring ownership of folder shared with third user + Given user "user0" exists + And user "user1" exists + And user "user2" exists + And User "user0" created a folder "/test" + And User "user0" uploads file "data/textfile.txt" to "/test/somefile.txt" + And folder "/test" of user "user0" is shared with user "user2" with permissions 31 + And user "user2" accepts last share + When transferring ownership from "user0" to "user1" + And the command was successful + And As an "user2" + Then Downloaded content when downloading file "/test/somefile.txt" with range "bytes=0-6" should be "This is" + And using old dav path + And as "user0" the folder "/test" does not exist + And using received transfer folder of "user1" as dav path + And as "user1" the folder "/test" exists + And As an "user1" + And Getting info of last share + And the OCS status code should be "100" + And Share fields of last share match with + | uid_owner | user1 | + | uid_file_owner | user1 | + | share_with | user2 | + + Scenario: transferring ownership of folder shared with transfer recipient + Given user "user0" exists + And user "user1" exists + And User "user0" created a folder "/test" + And User "user0" uploads file "data/textfile.txt" to "/test/somefile.txt" + And folder "/test" of user "user0" is shared with user "user1" with permissions 31 + And user "user1" accepts last share + When transferring ownership from "user0" to "user1" + And the command was successful + And As an "user1" + Then as "user1" the folder "/test" does not exist + And using received transfer folder of "user1" as dav path + And Downloaded content when downloading file "/test/somefile.txt" with range "bytes=0-6" should be "This is" + And using old dav path + And as "user0" the folder "/test" does not exist + And using received transfer folder of "user1" as dav path + And as "user1" the folder "/test" exists + And Getting info of last share + And the OCS status code should be "404" + + Scenario: transferring ownership of folder doubly shared with third user + Given group "group1" exists + And user "user0" exists + And user "user1" exists + And user "user2" exists + And user "user2" belongs to group "group1" + And User "user0" created a folder "/test" + And User "user0" uploads file "data/textfile.txt" to "/test/somefile.txt" + And folder "/test" of user "user0" is shared with group "group1" with permissions 31 + And user "user2" accepts last share + And folder "/test" of user "user0" is shared with user "user2" with permissions 31 + And user "user2" accepts last share + When transferring ownership from "user0" to "user1" + And the command was successful + And As an "user2" + Then Downloaded content when downloading file "/test/somefile.txt" with range "bytes=0-6" should be "This is" + And using old dav path + And as "user0" the folder "/test" does not exist + And using received transfer folder of "user1" as dav path + And as "user1" the folder "/test" exists + And As an "user1" + And Getting info of last share + And the OCS status code should be "100" + And Share fields of last share match with + | uid_owner | user1 | + | uid_file_owner | user1 | + | share_with | user2 | + + Scenario: transferring ownership of file shares to user with the same id as the group + Given user "user0" exists + And user "test" exists + And user "user2" exists + And group "test" exists + And user "user2" belongs to group "test" + And User "user0" uploads file "data/textfile.txt" to "/somefile.txt" + And file "/somefile.txt" of user "user0" is shared with group "test" + And user "user2" accepts last share + When transferring ownership from "user0" to "test" + And the command was successful + And As an "user2" + Then Downloaded content when downloading file "/somefile.txt" with range "bytes=0-6" should be "This is" + And using old dav path + And as "user0" the file "/somefile.txt" does not exist + And using received transfer folder of "user1" as dav path + And as "test" the file "/somefile.txt" exists + And As an "test" + And Getting info of last share + And the OCS status code should be "100" + And Share fields of last share match with + | uid_owner | test | + | uid_file_owner | test | + | share_with | test | + + Scenario: transferring ownership of folder reshared with another user + Given user "user0" exists + And user "user1" exists + And user "user2" exists + And user "user3" exists + And User "user3" created a folder "/test" + And User "user3" uploads file "data/textfile.txt" to "/test/somefile.txt" + And folder "/test" of user "user3" is shared with user "user0" with permissions 31 + And user "user0" accepts last share + And folder "/test" of user "user0" is shared with user "user2" with permissions 31 + And user "user2" accepts last share + When transferring ownership from "user0" to "user1" + And the command was successful + And As an "user2" + Then Downloaded content when downloading file "/test/somefile.txt" with range "bytes=0-6" should be "This is" + And using old dav path + And as "user0" the folder "/test" does not exist + And using received transfer folder of "user1" as dav path + And as "user1" the folder "/test" exists + And As an "user1" + And Getting info of last share + And the OCS status code should be "100" + And Share fields of last share match with + | uid_owner | user0 | + | uid_file_owner | user3 | + | share_with | user2 | + + Scenario: transferring ownership of folder reshared with group to a user in the group + Given user "user0" exists + And user "user1" exists + And user "user2" exists + And user "user3" exists + And group "group1" exists + And user "user1" belongs to group "group1" + And User "user3" created a folder "/test" + And User "user3" uploads file "data/textfile.txt" to "/test/somefile.txt" + And folder "/test" of user "user3" is shared with user "user0" with permissions 31 + And user "user0" accepts last share + And folder "/test" of user "user0" is shared with group "group1" with permissions 31 + And user "user1" accepts last share + When transferring ownership from "user0" to "user1" + And the command was successful + And using old dav path + Then as "user0" the folder "/test" does not exist + When As an "user1" + And using received transfer folder of "user1" as dav path + Then as "user1" the folder "/test" exists + And Downloaded content when downloading file "/test/somefile.txt" with range "bytes=0-6" should be "This is" + And Getting info of last share + And the OCS status code should be "100" + And Share fields of last share match with + | uid_owner | user1 | + | uid_file_owner | user3 | + | share_with | group1 | + + Scenario: transferring ownership of folder reshared with group to a user not in the group + Given user "user0" exists + And user "user1" exists + And user "user2" exists + And user "user3" exists + And group "group1" exists + And user "user2" belongs to group "group1" + And User "user3" created a folder "/test" + And User "user3" uploads file "data/textfile.txt" to "/test/somefile.txt" + And folder "/test" of user "user3" is shared with user "user0" with permissions 31 + And user "user0" accepts last share + And folder "/test" of user "user0" is shared with group "group1" with permissions 31 + And user "user2" accepts last share + When transferring ownership from "user0" to "user1" + And the command was successful + And As an "user2" + Then Downloaded content when downloading file "/test/somefile.txt" with range "bytes=0-6" should be "This is" + And using old dav path + And as "user0" the folder "/test" does not exist + And using received transfer folder of "user1" as dav path + And as "user1" the folder "/test" exists + And As an "user1" + And Getting info of last share + And the OCS status code should be "100" + And Share fields of last share match with + | uid_owner | user0 | + | uid_file_owner | user3 | + | share_with | group1 | + + Scenario: transferring ownership transfers received shares + Given user "user0" exists + And user "user1" exists + And user "user2" exists + And User "user2" created a folder "/test" + And folder "/test" of user "user2" is shared with user "user0" with permissions 31 + And user "user0" accepts last share + When transferring ownership from "user0" to "user1" + And the command was successful + And As an "user1" + And using received transfer folder of "user1" as dav path + Then as "user1" the folder "/test" exists + And using old dav path + And as "user0" the folder "/test" does not exist + And As an "user2" + And Getting info of last share + And the OCS status code should be "100" + And Share fields of last share match with + | uid_owner | user2 | + | uid_file_owner | user2 | + | share_with | user1 | + + @local_storage + Scenario: transferring ownership does not transfer external storage + Given user "user0" exists + And user "user1" exists + When transferring ownership from "user0" to "user1" + And the command was successful + And As an "user1" + And using received transfer folder of "user1" as dav path + Then as "user1" the folder "/local_storage" does not exist + + Scenario: transferring ownership does not fail with shared trashed files + Given user "user0" exists + And user "user1" exists + And user "user2" exists + And User "user0" created a folder "/sub" + And User "user0" created a folder "/sub/test" + And folder "/sub/test" of user "user0" is shared with user "user2" with permissions 31 + And user "user2" accepts last share + And User "user0" deletes folder "/sub" + When transferring ownership from "user0" to "user1" + Then the command was successful + + Scenario: transferring ownership fails with invalid source user + Given user "user0" exists + When transferring ownership from "invalid_user" to "user0" + Then the command output contains the text "Unknown source user" + And the command failed with exit code 1 + + Scenario: transferring ownership fails with invalid target user + Given user "user0" exists + When transferring ownership from "user0" to "invalid_user" + Then the command output contains the text "Unknown destination user invalid_user" + And the command failed with exit code 1 + + Scenario: transferring ownership of a file + Given user "user0" exists + And user "user1" exists + And User "user0" uploads file "data/textfile.txt" to "/somefile.txt" + When transferring ownership of path "somefile.txt" from "user0" to "user1" + And the command was successful + And As an "user1" + And using received transfer folder of "user1" as dav path + Then Downloaded content when downloading file "/somefile.txt" with range "bytes=0-6" should be "This is" + And using old dav path + And as "user0" the file "/somefile.txt" does not exist + And using received transfer folder of "user1" as dav path + And as "user1" the file "/somefile.txt" exists + + Scenario: transferring ownership of a folder + Given user "user0" exists + And user "user1" exists + And User "user0" created a folder "/test" + And User "user0" uploads file "data/textfile.txt" to "/test/somefile.txt" + When transferring ownership of path "test" from "user0" to "user1" + And the command was successful + And As an "user1" + And using received transfer folder of "user1" as dav path + Then Downloaded content when downloading file "/test/somefile.txt" with range "bytes=0-6" should be "This is" + And using old dav path + And as "user0" the folder "/test" does not exist + And using received transfer folder of "user1" as dav path + And as "user1" the folder "/test" exists + + Scenario: transferring ownership from user with risky display name + Given user "user0" with displayname "user0 \"risky\"? ヂspḷay 'na|\/|e':.#" exists + And user "user1" exists + And User "user0" created a folder "/test" + And User "user0" uploads file "data/textfile.txt" to "/test/somefile.txt" + When transferring ownership of path "test" from "user0" to "user1" + And the command was successful + And As an "user1" + And using received transfer folder of "user1" as dav path + Then Downloaded content when downloading file "/test/somefile.txt" with range "bytes=0-6" should be "This is" + And transfer folder name contains "Transferred from user0 -risky- ヂspḷay -na|-|e- on" + And using old dav path + And as "user0" the folder "/test" does not exist + And using received transfer folder of "user1" as dav path + And as "user1" the folder "/test" exists + + Scenario: transferring ownership of path does not affect other files + Given user "user0" exists + And user "user1" exists + And User "user0" created a folder "/test" + And User "user0" uploads file "data/textfile.txt" to "/test/somefile.txt" + And User "user0" created a folder "/test2" + And User "user0" uploads file "data/textfile.txt" to "/test2/somefile.txt" + When transferring ownership of path "test" from "user0" to "user1" + And the command was successful + And As an "user1" + And using received transfer folder of "user1" as dav path + Then Downloaded content when downloading file "/test/somefile.txt" with range "bytes=0-6" should be "This is" + And using old dav path + And as "user0" the folder "/test" does not exist + And as "user0" the folder "/test2" exists + And as "user0" the file "/test2/somefile.txt" exists + And using received transfer folder of "user1" as dav path + And as "user1" the folder "/test" exists + And as "user1" the folder "/test2" does not exist + + Scenario: transferring ownership of path does not affect other shares + Given user "user0" exists + And user "user1" exists + And User "user0" created a folder "/test" + And User "user0" uploads file "data/textfile.txt" to "/test/somefile.txt" + And User "user0" created a folder "/test2" + And User "user0" uploads file "data/textfile.txt" to "/test2/sharedfile.txt" + And file "/test2/sharedfile.txt" of user "user0" is shared with user "user1" with permissions 19 + And user "user1" accepts last share + When transferring ownership of path "test" from "user0" to "user1" + And the command was successful + And As an "user1" + And using received transfer folder of "user1" as dav path + Then Downloaded content when downloading file "/test/somefile.txt" with range "bytes=0-6" should be "This is" + And using old dav path + And as "user0" the folder "/test" does not exist + And as "user0" the folder "/test2" exists + And as "user0" the file "/test2/sharedfile.txt" exists + And using received transfer folder of "user1" as dav path + And as "user1" the folder "/test" exists + And as "user1" the folder "/test2" does not exist + And using old dav path + And as "user1" the file "/sharedfile.txt" exists + And As an "user1" + And Getting info of last share + And the OCS status code should be "100" + And Share fields of last share match with + | uid_owner | user0 | + | uid_file_owner | user0 | + | share_with | user1 | + + Scenario: transferring ownership of file shares + Given user "user0" exists + And user "user1" exists + And user "user2" exists + And User "user0" created a folder "/test" + And User "user0" uploads file "data/textfile.txt" to "/test/somefile.txt" + And file "/test/somefile.txt" of user "user0" is shared with user "user2" with permissions 19 + And user "user2" accepts last share + When transferring ownership of path "test" from "user0" to "user1" + And the command was successful + And As an "user2" + Then Downloaded content when downloading file "/somefile.txt" with range "bytes=0-6" should be "This is" + And using old dav path + And as "user0" the folder "/test" does not exist + And using received transfer folder of "user1" as dav path + And as "user1" the folder "/test" exists + And As an "user1" + And Getting info of last share + And the OCS status code should be "100" + And Share fields of last share match with + | uid_owner | user1 | + | uid_file_owner | user1 | + | share_with | user2 | + + Scenario: transferring ownership of folder shared with third user + Given user "user0" exists + And user "user1" exists + And user "user2" exists + And User "user0" created a folder "/test" + And User "user0" uploads file "data/textfile.txt" to "/test/somefile.txt" + And folder "/test" of user "user0" is shared with user "user2" with permissions 31 + And user "user2" accepts last share + When transferring ownership of path "test" from "user0" to "user1" + And the command was successful + And As an "user2" + Then Downloaded content when downloading file "/test/somefile.txt" with range "bytes=0-6" should be "This is" + And using old dav path + And as "user0" the folder "/test" does not exist + And using received transfer folder of "user1" as dav path + And as "user1" the folder "/test" exists + And As an "user1" + And Getting info of last share + And the OCS status code should be "100" + And Share fields of last share match with + | uid_owner | user1 | + | uid_file_owner | user1 | + | share_with | user2 | + + Scenario: transferring ownership of folder shared with transfer recipient + Given user "user0" exists + And user "user1" exists + And User "user0" created a folder "/test" + And User "user0" uploads file "data/textfile.txt" to "/test/somefile.txt" + And folder "/test" of user "user0" is shared with user "user1" with permissions 31 + And user "user1" accepts last share + When transferring ownership of path "test" from "user0" to "user1" + And the command was successful + And As an "user1" + Then as "user1" the folder "/test" does not exist + And using received transfer folder of "user1" as dav path + And Downloaded content when downloading file "/test/somefile.txt" with range "bytes=0-6" should be "This is" + And using old dav path + And as "user0" the folder "/test" does not exist + And using received transfer folder of "user1" as dav path + And as "user1" the folder "/test" exists + And Getting info of last share + And the OCS status code should be "404" + + Scenario: transferring ownership of folder doubly shared with third user + Given group "group1" exists + And user "user0" exists + And user "user1" exists + And user "user2" exists + And user "user2" belongs to group "group1" + And User "user0" created a folder "/test" + And User "user0" uploads file "data/textfile.txt" to "/test/somefile.txt" + And folder "/test" of user "user0" is shared with group "group1" with permissions 31 + And user "user2" accepts last share + And folder "/test" of user "user0" is shared with user "user2" with permissions 31 + And user "user2" accepts last share + When transferring ownership of path "test" from "user0" to "user1" + And the command was successful + And As an "user2" + Then Downloaded content when downloading file "/test/somefile.txt" with range "bytes=0-6" should be "This is" + And using old dav path + And as "user0" the folder "/test" does not exist + And using received transfer folder of "user1" as dav path + And as "user1" the folder "/test" exists + And As an "user1" + And Getting info of last share + And the OCS status code should be "100" + And Share fields of last share match with + | uid_owner | user1 | + | uid_file_owner | user1 | + | share_with | user2 | + + Scenario: transferring ownership of path fails for reshares + Given user "user0" exists + And user "user1" exists + And user "user2" exists + And user "user3" exists + And User "user3" created a folder "/test" + And User "user3" uploads file "data/textfile.txt" to "/test/somefile.txt" + And folder "/test" of user "user3" is shared with user "user0" with permissions 31 + And user "user0" accepts last share + And folder "/test" of user "user0" is shared with user "user2" with permissions 31 + And user "user2" accepts last share + When transferring ownership of path "test" from "user0" to "user1" + Then the command failed with exit code 1 + And the command error output contains the text "Moving a storage (user0/files/test) into another storage (user1) is not allowed" + + Scenario: transferring ownership transfers received shares into subdir when requested + Given user "user0" exists + And user "user1" exists + And user "user2" exists + And User "user2" created a folder "/transfer-share" + And User "user2" created a folder "/do-not-transfer" + And User "user0" created a folder "/sub" + And folder "/transfer-share" of user "user2" is shared with user "user0" with permissions 31 + And user "user0" accepts last share + And User "user0" moved folder "/transfer-share" to "/sub/transfer-share" + And folder "/do-not-transfer" of user "user2" is shared with user "user0" with permissions 31 + And user "user0" accepts last share + When transferring ownership of path "sub" from "user0" to "user1" + And the command was successful + And As an "user1" + And using received transfer folder of "user1" as dav path + Then as "user1" the folder "/sub" exists + And as "user1" the folder "/do-not-transfer" does not exist + And as "user1" the folder "/sub/do-not-transfer" does not exist + And as "user1" the folder "/sub/transfer-share" exists + And using old dav path + And as "user1" the folder "/transfer-share" does not exist + And as "user1" the folder "/do-not-transfer" does not exist + And using old dav path + And as "user0" the folder "/sub" does not exist + And as "user0" the folder "/do-not-transfer" exists + And Getting info of last share + And the OCS status code should be "404" + + Scenario: transferring ownership does not transfer external storage + Given user "user0" exists + And user "user1" exists + And User "user0" created a folder "/sub" + When transferring ownership of path "sub" from "user0" to "user1" + And the command was successful + And As an "user1" + And using received transfer folder of "user1" as dav path + Then as "user1" the folder "/local_storage" does not exist + + Scenario: transferring ownership fails with invalid source user + Given user "user0" exists + And User "user0" created a folder "/sub" + When transferring ownership of path "sub" from "invalid_user" to "user0" + Then the command output contains the text "Unknown source user" + And the command failed with exit code 1 + + Scenario: transferring ownership fails with invalid target user + Given user "user0" exists + And User "user0" created a folder "/sub" + When transferring ownership of path "sub" from "user0" to "invalid_user" + Then the command output contains the text "Unknown destination user invalid_user" + And the command failed with exit code 1 + + Scenario: transferring ownership fails with invalid path + Given user "user0" exists + And user "user1" exists + When transferring ownership of path "test" from "user0" to "user1" + Then the command output contains the text "Unknown path provided: test" + And the command failed with exit code 1 diff --git a/build/integration/files_features/trashbin.feature b/build/integration/files_features/trashbin.feature new file mode 100644 index 00000000000..fd84e396ba3 --- /dev/null +++ b/build/integration/files_features/trashbin.feature @@ -0,0 +1,84 @@ +# SPDX-FileCopyrightText: 2017-2024 Nextcloud GmbH and Nextcloud contributors +# SPDX-FileCopyrightText: 2017 ownCloud, Inc. +# SPDX-License-Identifier: AGPL-3.0-only +Feature: trashbin + Background: + Given using api version "1" + And using new dav path + And As an "admin" + And app "files_trashbin" is enabled + + Scenario: deleting a file moves it to trashbin + Given As an "admin" + And user "user0" exists + When User "user0" deletes file "/textfile0.txt" + Then user "user0" in trash folder "/" should have 1 element + And user "user0" in trash folder "/" should have the following elements + | textfile0.txt | + + Scenario: clearing the trashbin + Given As an "admin" + And user "user0" exists + When User "user0" deletes file "/textfile0.txt" + And User "user0" empties trashbin + Then user "user0" in trash folder "/" should have 0 elements + + Scenario: restoring file from trashbin + Given As an "admin" + And user "user0" exists + When User "user0" deletes file "/textfile0.txt" + And user "user0" in restores "/textfile0.txt" from trash + Then user "user0" in trash folder "/" should have 0 elements + And as "user0" the file "/textfile0.txt" exists + + Scenario: deleting and restoring a folder + Given As an "admin" + And user "user0" exists + When User "user0" created a folder "/testfolder" + And User "user0" moves file "/textfile0.txt" to "/testfolder/textfile0.txt" + And as "user0" the file "/testfolder/textfile0.txt" exists + And User "user0" deletes file "/testfolder" + And user "user0" in trash folder "/" should have 1 element + And user "user0" in trash folder "/" should have the following elements + | testfolder | + And user "user0" in trash folder "/testfolder" should have 1 element + And user "user0" in trash folder "/testfolder" should have the following elements + | textfile0.txt | + And user "user0" in restores "/testfolder" from trash + Then user "user0" in trash folder "/" should have 0 elements + And as "user0" the file "/testfolder/textfile0.txt" exists + + Scenario: deleting a file from a subfolder and restoring it moves it back to the subfolder + Given As an "admin" + And user "user0" exists + When User "user0" created a folder "/testfolder" + And User "user0" moves file "/textfile0.txt" to "/testfolder/textfile0.txt" + And as "user0" the file "/testfolder/textfile0.txt" exists + And User "user0" deletes file "/testfolder/textfile0.txt" + And user "user0" in trash folder "/" should have 1 element + And user "user0" in trash folder "/" should have the following elements + | textfile0.txt | + And user "user0" in restores "/textfile0.txt" from trash + Then user "user0" in trash folder "/" should have 0 elements + And as "user0" the file "/textfile0.txt" does not exist + And as "user0" the file "/testfolder/textfile0.txt" exists + + Scenario: deleting and a folder and restoring a file inside it + Given As an "admin" + And user "user0" exists + When User "user0" created a folder "/testfolder" + And User "user0" moves file "/textfile0.txt" to "/testfolder/textfile0.txt" + And as "user0" the file "/testfolder/textfile0.txt" exists + And User "user0" deletes file "/testfolder" + And user "user0" in trash folder "/" should have 1 element + And user "user0" in trash folder "/" should have the following elements + | testfolder | + And user "user0" in trash folder "/testfolder" should have 1 element + And user "user0" in trash folder "/testfolder" should have the following elements + | textfile0.txt | + And user "user0" in restores "/testfolder/textfile0.txt" from trash + Then user "user0" in trash folder "/" should have 1 elements + And user "user0" in trash folder "/testfolder" should have 0 element + And as "user0" the file "/textfile0.txt" exists + + diff --git a/build/integration/files_features/windows_compatibility.feature b/build/integration/files_features/windows_compatibility.feature new file mode 100644 index 00000000000..feaaca1ed3a --- /dev/null +++ b/build/integration/files_features/windows_compatibility.feature @@ -0,0 +1,68 @@ +# SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors +# SPDX-License-Identifier: AGPL-3.0-or-later + +Feature: Windows compatible filenames + Background: + Given using api version "1" + And using new dav path + And As an "admin" + + Scenario: prevent upload files with invalid name + Given As an "admin" + And user "user0" exists + And invoking occ with "files:windows-compatible-filenames --enable" + Given User "user0" created a folder "/com1" + Then as "user0" the file "/com1" does not exist + + Scenario: renaming a folder with invalid name + Given As an "admin" + When invoking occ with "files:windows-compatible-filenames --disable" + And user "user0" exists + Given User "user0" created a folder "/aux" + When invoking occ with "files:windows-compatible-filenames --enable" + And invoking occ with "files:sanitize-filenames user0" + Then as "user0" the file "/aux" does not exist + And as "user0" the file "/aux (renamed)" exists + + Scenario: renaming a file with invalid base name + Given As an "admin" + When invoking occ with "files:windows-compatible-filenames --disable" + And user "user0" exists + When User "user0" uploads file with content "hello" to "/com0.txt" + And invoking occ with "files:windows-compatible-filenames --enable" + And invoking occ with "files:sanitize-filenames user0" + Then as "user0" the file "/com0.txt" does not exist + And as "user0" the file "/com0 (renamed).txt" exists + + Scenario: renaming a file with invalid extension + Given As an "admin" + When invoking occ with "files:windows-compatible-filenames --disable" + And user "user0" exists + When User "user0" uploads file with content "hello" to "/foo.txt." + And as "user0" the file "/foo.txt." exists + And invoking occ with "files:windows-compatible-filenames --enable" + And invoking occ with "files:sanitize-filenames user0" + Then as "user0" the file "/foo.txt." does not exist + And as "user0" the file "/foo.txt" exists + + Scenario: renaming a file with invalid character + Given As an "admin" + When invoking occ with "files:windows-compatible-filenames --disable" + And user "user0" exists + When User "user0" uploads file with content "hello" to "/2*2=4.txt" + And as "user0" the file "/2*2=4.txt" exists + And invoking occ with "files:windows-compatible-filenames --enable" + And invoking occ with "files:sanitize-filenames user0" + Then as "user0" the file "/2*2=4.txt" does not exist + And as "user0" the file "/2_2=4.txt" exists + + Scenario: renaming a file with invalid character and replacement setup + Given As an "admin" + When invoking occ with "files:windows-compatible-filenames --disable" + And user "user0" exists + When User "user0" uploads file with content "hello" to "/2*3=6.txt" + And as "user0" the file "/2*3=6.txt" exists + And invoking occ with "files:windows-compatible-filenames --enable" + And invoking occ with "files:sanitize-filenames --char-replacement + user0" + Then as "user0" the file "/2*3=6.txt" does not exist + And as "user0" the file "/2+3=6.txt" exists |