From 9779dd8b16ea21615d96818304fa5edeaa0597b9 Mon Sep 17 00:00:00 2001 From: Josh Date: Tue, 7 Apr 2026 07:49:46 -0400 Subject: [PATCH 01/16] test(files_features): add Behat annotation to tags.feature Signed-off-by: Josh --- build/integration/files_features/tags.feature | 1 + 1 file changed, 1 insertion(+) diff --git a/build/integration/files_features/tags.feature b/build/integration/files_features/tags.feature index fef8068cbc809..5bc8fd889b4a6 100644 --- a/build/integration/files_features/tags.feature +++ b/build/integration/files_features/tags.feature @@ -1,6 +1,7 @@ # SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors # SPDX-FileCopyrightText: 2016 ownCloud, Inc. # SPDX-License-Identifier: AGPL-3.0-only +@tags Feature: tags Scenario: Creating a normal tag as regular user should work From 408c8d447e0d2730a346be4f911d9eddd706ec67 Mon Sep 17 00:00:00 2001 From: Josh Date: Tue, 7 Apr 2026 07:50:43 -0400 Subject: [PATCH 02/16] test(files_features): add Behat annotation to transfr-ownership.feature Signed-off-by: Josh --- build/integration/files_features/transfer-ownership.feature | 1 + 1 file changed, 1 insertion(+) diff --git a/build/integration/files_features/transfer-ownership.feature b/build/integration/files_features/transfer-ownership.feature index 6f7a79441662e..08b93334bdd97 100644 --- a/build/integration/files_features/transfer-ownership.feature +++ b/build/integration/files_features/transfer-ownership.feature @@ -1,6 +1,7 @@ # SPDX-FileCopyrightText: 2017-2024 Nextcloud GmbH and Nextcloud contributors # SPDX-FileCopyrightText: 2016 ownCloud, Inc. # SPDX-License-Identifier: AGPL-3.0-only +@transfer-ownership Feature: transfer-ownership Scenario: transferring ownership of a file From 497a40ed60ae49c075a8ee7bc584cc69803d4172 Mon Sep 17 00:00:00 2001 From: Josh Date: Tue, 7 Apr 2026 07:59:14 -0400 Subject: [PATCH 03/16] test(integration-sqlite): split slowest behat suites into into parallel jobs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Split sharing_features and files_features into separate matrix entries to reduce wall-clock time by running them in parallel. sharing_features (~20m) is split by its existing part files into 3 jobs. files_features (~18m) is split by @tags and @transfer-ownership feature annotations into 3 jobs. This adds 4 matrix entries (20 → 24) with minor setup overhead each, and should reduce the critical path by 50% (e.g. from ~20m to ~9m). Signed-off-by: Josh --- .github/workflows/integration-sqlite.yml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/integration-sqlite.yml b/.github/workflows/integration-sqlite.yml index b39698813a18d..5152a04085958 100644 --- a/.github/workflows/integration-sqlite.yml +++ b/.github/workflows/integration-sqlite.yml @@ -59,7 +59,9 @@ jobs: - 'dav_features' - 'features' - 'federation_features' - - '--tags ~@large files_features' + - '--tags ~@large~@tags~@transfer-ownership files_features' + - '--tags @tags files_features' + - '--tags @transfer-ownership files_features' - 'filesdrop_features' - 'file_conversions' - 'files_reminders' @@ -70,7 +72,9 @@ jobs: - 'routing_features' - 'setup_features' - 'sharees_features' - - 'sharing_features' + - 'sharing_features/sharing-v1.feature sharing_features/sharing-activity.feature' + - 'sharing_features/sharing-v1-part2.feature' + - 'sharing_features/sharing-v1-part3.feature sharing_features/sharing-v1-part4.feature' - 'theming_features' - 'videoverification_features' From 95246af71e869a761edef21fe3da785f65088dc5 Mon Sep 17 00:00:00 2001 From: Josh Date: Tue, 7 Apr 2026 08:04:43 -0400 Subject: [PATCH 04/16] test(integration-sqlite): update activity app checkout condition Signed-off-by: Josh --- .github/workflows/integration-sqlite.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/integration-sqlite.yml b/.github/workflows/integration-sqlite.yml index 5152a04085958..19721031fb2d9 100644 --- a/.github/workflows/integration-sqlite.yml +++ b/.github/workflows/integration-sqlite.yml @@ -116,7 +116,7 @@ jobs: ref: ${{ matrix.spreed-versions }} - name: Checkout Activity app - if: ${{ matrix.test-suite == 'sharing_features' }} + if: ${{ contains(matrix.test-suite, 'sharing_features') }} uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false From c60826c750d83be0b08f59c3fb6bb8988ab894ef Mon Sep 17 00:00:00 2001 From: Josh Date: Tue, 7 Apr 2026 09:34:56 -0400 Subject: [PATCH 05/16] ci(integration-sqlite): fixup matrix entry syntax Signed-off-by: Josh --- .github/workflows/integration-sqlite.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/integration-sqlite.yml b/.github/workflows/integration-sqlite.yml index 19721031fb2d9..3779e447632c1 100644 --- a/.github/workflows/integration-sqlite.yml +++ b/.github/workflows/integration-sqlite.yml @@ -59,7 +59,7 @@ jobs: - 'dav_features' - 'features' - 'federation_features' - - '--tags ~@large~@tags~@transfer-ownership files_features' + - '--tags ~@large&&~@tags&&~@transfer-ownership files_features' - '--tags @tags files_features' - '--tags @transfer-ownership files_features' - 'filesdrop_features' From c75f12db4c2080deca55d601595e756c84501e26 Mon Sep 17 00:00:00 2001 From: Josh Date: Tue, 7 Apr 2026 18:05:58 -0400 Subject: [PATCH 06/16] ci(integration-sqlite): deal multiple levels of quote matters Signed-off-by: Josh --- .github/workflows/integration-sqlite.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/integration-sqlite.yml b/.github/workflows/integration-sqlite.yml index 3779e447632c1..b55ba622500ec 100644 --- a/.github/workflows/integration-sqlite.yml +++ b/.github/workflows/integration-sqlite.yml @@ -59,7 +59,7 @@ jobs: - 'dav_features' - 'features' - 'federation_features' - - '--tags ~@large&&~@tags&&~@transfer-ownership files_features' + - '--tags ~@large,~@tags,~@transfer-ownership files_features' - '--tags @tags files_features' - '--tags @transfer-ownership files_features' - 'filesdrop_features' From 0016157b9ea79c177072621cee727de4da7ae14c Mon Sep 17 00:00:00 2001 From: Josh Date: Tue, 7 Apr 2026 18:34:02 -0400 Subject: [PATCH 07/16] chore(integration-sqlite): matrix entry fix Signed-off-by: Josh --- .github/workflows/integration-sqlite.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/integration-sqlite.yml b/.github/workflows/integration-sqlite.yml index b55ba622500ec..3779e447632c1 100644 --- a/.github/workflows/integration-sqlite.yml +++ b/.github/workflows/integration-sqlite.yml @@ -59,7 +59,7 @@ jobs: - 'dav_features' - 'features' - 'federation_features' - - '--tags ~@large,~@tags,~@transfer-ownership files_features' + - '--tags ~@large&&~@tags&&~@transfer-ownership files_features' - '--tags @tags files_features' - '--tags @transfer-ownership files_features' - 'filesdrop_features' From 2c5439e52ee19cc9286d7cd40d4f9e4cf9469dd0 Mon Sep 17 00:00:00 2001 From: Josh Date: Tue, 7 Apr 2026 18:34:56 -0400 Subject: [PATCH 08/16] test: fix quoting of tags arg in run.sh Signed-off-by: Josh --- build/integration/run.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/integration/run.sh b/build/integration/run.sh index 4ff808b5056b9..1983111568e1c 100755 --- a/build/integration/run.sh +++ b/build/integration/run.sh @@ -97,7 +97,7 @@ $BEHAT_EXECUTABLE \ --colors \ -f junit \ -f pretty \ - $TAGS \ + "$TAGS" \ $SCENARIO_TO_RUN RESULT=$? From ec4b88d5adad07915b22ea8cd419f58be7c6b0c3 Mon Sep 17 00:00:00 2001 From: Josh Date: Tue, 7 Apr 2026 18:43:11 -0400 Subject: [PATCH 09/16] ci: [perf] compute dataDirectory only once in BasicStructure.php Signed-off-by: Josh --- build/integration/features/bootstrap/BasicStructure.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/build/integration/features/bootstrap/BasicStructure.php b/build/integration/features/bootstrap/BasicStructure.php index 8d1d3b38793f5..969c05ea70532 100644 --- a/build/integration/features/bootstrap/BasicStructure.php +++ b/build/integration/features/bootstrap/BasicStructure.php @@ -411,8 +411,9 @@ private function getDataDirectory() { * @param string $user */ public function fileIsCreatedTimesInUserData($filename, $times, $user) { + $dataDirectory = $this->getDataDirectory(); for ($i = 0; $i < $times; $i++) { - file_put_contents($this->getDataDirectory() . "/$user/files" . "$filename-$i", "content-$i"); + file_put_contents($dataDirectory . "/$user/files" . "$filename-$i", "content-$i"); } } From b8a6559c80a9010a0c5ef5b697557a73be9bcd44 Mon Sep 17 00:00:00 2001 From: Josh Date: Wed, 8 Apr 2026 08:07:11 -0400 Subject: [PATCH 10/16] chore: slightly better run.sh tag arg parsing Signed-off-by: Josh --- build/integration/run.sh | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/build/integration/run.sh b/build/integration/run.sh index 1983111568e1c..206cdb8c915c8 100755 --- a/build/integration/run.sh +++ b/build/integration/run.sh @@ -12,10 +12,9 @@ fi OC_PATH=../../ OCC=${OC_PATH}occ -TAGS="" +BEHAT_ARGS=() if [ "$1" = "--tags" ]; then - TAGS="--tags=$2" - + BEHAT_ARGS+=("--tags=$2") shift 2 fi SCENARIO_TO_RUN=$1 @@ -97,7 +96,7 @@ $BEHAT_EXECUTABLE \ --colors \ -f junit \ -f pretty \ - "$TAGS" \ + "${BEHAT_ARGS[@]}" \ $SCENARIO_TO_RUN RESULT=$? From 69ceeb08055befb217dde640ebf1713ada1af22e Mon Sep 17 00:00:00 2001 From: Josh Date: Wed, 8 Apr 2026 08:45:36 -0400 Subject: [PATCH 11/16] chore(integration-sqlite): avoid direct-interpoloation problem from GA Signed-off-by: Josh --- .github/workflows/integration-sqlite.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/integration-sqlite.yml b/.github/workflows/integration-sqlite.yml index 3779e447632c1..ec92a9c739780 100644 --- a/.github/workflows/integration-sqlite.yml +++ b/.github/workflows/integration-sqlite.yml @@ -164,7 +164,8 @@ jobs: working-directory: build/integration env: LDAP_HOST: localhost - run: bash run.sh ${{ matrix.test-suite }} no-tail-log + BEHAT_SUITE: ${{ matrix.test-suite }} + run: bash run.sh $BEHAT_SUITE no-tail-log - name: Print logs if: always() From c601033fc827eec62c9baf0e20e96aad95ae0e47 Mon Sep 17 00:00:00 2001 From: Josh Date: Wed, 8 Apr 2026 10:12:13 -0400 Subject: [PATCH 12/16] ci(integration-sqlite): split up features and sharee_features Signed-off-by: Josh --- .github/workflows/integration-sqlite.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/integration-sqlite.yml b/.github/workflows/integration-sqlite.yml index ec92a9c739780..a462e587d1805 100644 --- a/.github/workflows/integration-sqlite.yml +++ b/.github/workflows/integration-sqlite.yml @@ -57,7 +57,8 @@ jobs: - 'collaboration_features' - 'comments_features' - 'dav_features' - - 'features' + - 'features/provisioning-v1.feature' + - 'features/contacts-menu.feature features/auth.feature features/avatar.feature features/maintenance-mode.feature features/provisioning-v2.feature features/log-condition.feature features/ocs-v1.feature' - 'federation_features' - '--tags ~@large&&~@tags&&~@transfer-ownership files_features' - '--tags @tags files_features' @@ -71,7 +72,8 @@ jobs: - 'remoteapi_features' - 'routing_features' - 'setup_features' - - 'sharees_features' + - 'sharees_features/sharees.feature sharees_features/sharees_provisioningapiv2.feature' + - 'sharees_features/sharees_user.feature' - 'sharing_features/sharing-v1.feature sharing_features/sharing-activity.feature' - 'sharing_features/sharing-v1-part2.feature' - 'sharing_features/sharing-v1-part3.feature sharing_features/sharing-v1-part4.feature' From ed1330f89ecc6948992b4f9934639007a48b87e8 Mon Sep 17 00:00:00 2001 From: Josh Date: Wed, 8 Apr 2026 10:16:30 -0400 Subject: [PATCH 13/16] test(sharing): Split sharing-v1-part2.feature in half Signed-off-by: Josh --- ...art2.feature => sharing-v1-part2a.feature} | 611 +----------------- 1 file changed, 1 insertion(+), 610 deletions(-) rename build/integration/sharing_features/{sharing-v1-part2.feature => sharing-v1-part2a.feature} (56%) diff --git a/build/integration/sharing_features/sharing-v1-part2.feature b/build/integration/sharing_features/sharing-v1-part2a.feature similarity index 56% rename from build/integration/sharing_features/sharing-v1-part2.feature rename to build/integration/sharing_features/sharing-v1-part2a.feature index 0c83975fc39b5..d3b7771e9aabf 100644 --- a/build/integration/sharing_features/sharing-v1-part2.feature +++ b/build/integration/sharing_features/sharing-v1-part2a.feature @@ -724,613 +724,4 @@ Feature: sharing Then the OCS status code should be "404" And the HTTP status code should be "200" - Scenario: download restrictions can not be dropped - As an "admin" - Given user "user0" exists - And user "user1" exists - And user "user2" exists - And User "user0" uploads file with content "foo" to "/tmp.txt" - And As an "user0" - And creating a share with - | path | /tmp.txt | - | shareType | 0 | - | shareWith | user1 | - | permissions | 17 | - | attributes | [{"scope":"permissions","key":"download","value":false}] | - And As an "user1" - And accepting last share - When Getting info of last share - Then Share fields of last share match with - | uid_owner | user0 | - | uid_file_owner | user0 | - | permissions | 17 | - | attributes | [{"scope":"permissions","key":"download","value":false}] | - When creating a share with - | path | /tmp.txt | - | shareType | 0 | - | shareWith | user2 | - | permissions | 1 | - Then the OCS status code should be "100" - And the HTTP status code should be "200" - When As an "user2" - And accepting last share - And Getting info of last share - Then Share fields of last share match with - | share_type | 0 | - | permissions | 1 | - | uid_owner | user1 | - | uid_file_owner | user0 | - | attributes | [{"scope":"permissions","key":"download","value":false}] | - - Scenario: download restrictions can not be dropped when re-sharing even on link shares - As an "admin" - Given user "user0" exists - And user "user1" exists - And User "user0" uploads file with content "foo" to "/tmp.txt" - And As an "user0" - And creating a share with - | path | /tmp.txt | - | shareType | 0 | - | shareWith | user1 | - | permissions | 17 | - | attributes | [{"scope":"permissions","key":"download","value":false}] | - And As an "user1" - And accepting last share - When Getting info of last share - Then Share fields of last share match with - | uid_owner | user0 | - | attributes | [{"scope":"permissions","key":"download","value":false}] | - When creating a share with - | path | /tmp.txt | - | shareType | 3 | - | permissions | 1 | - And Getting info of last share - And Updating last share with - | hideDownload | false | - Then the OCS status code should be "100" - And the HTTP status code should be "200" - When Getting info of last share - Then Share fields of last share match with - | share_type | 3 | - | uid_owner | user1 | - | uid_file_owner | user0 | - | hide_download | 1 | - | attributes | [{"scope":"permissions","key":"download","value":false}] | - - Scenario: User is not allowed to reshare file with additional delete permissions - As an "admin" - Given user "user0" exists - And user "user1" exists - And user "user2" exists - And As an "user0" - And creating a share with - | path | /PARENT | - | shareType | 0 | - | shareWith | user1 | - | permissions | 16 | - And As an "user1" - And accepting last share - When creating a share with - | path | /PARENT (2) | - | shareType | 0 | - | shareWith | user2 | - | permissions | 25 | - Then the OCS status code should be "404" - And the HTTP status code should be "200" - - Scenario: User is not allowed to reshare file with additional delete permissions for files - As an "admin" - Given user "user0" exists - And user "user1" exists - And user "user2" exists - And As an "user0" - And creating a share with - | path | /textfile0.txt | - | shareType | 0 | - | shareWith | user1 | - | permissions | 16 | - And As an "user1" - And accepting last share - When creating a share with - | path | /textfile0 (2).txt | - | shareType | 0 | - | shareWith | user2 | - | permissions | 25 | - Then the OCS status code should be "100" - And the HTTP status code should be "200" - When Getting info of last share - Then Share fields of last share match with - | id | A_NUMBER | - | item_type | file | - | item_source | A_NUMBER | - | share_type | 0 | - | share_with | user2 | - | file_source | A_NUMBER | - | file_target | /textfile0 (2).txt | - | path | /textfile0 (2).txt | - | permissions | 17 | - | stime | A_NUMBER | - | storage | A_NUMBER | - | mail_send | 0 | - | uid_owner | user1 | - | storage_id | shared::/textfile0 (2).txt | - | file_parent | A_NUMBER | - | share_with_displayname | user2 | - | displayname_owner | user1 | - | mimetype | text/plain | - - Scenario: Get a share with a user which didn't received the share - Given user "user0" exists - And user "user1" exists - And user "user2" exists - And file "textfile0.txt" of user "user0" is shared with user "user1" - And As an "user2" - When Getting info of last share - Then the OCS status code should be "404" - And the HTTP status code should be "200" - - Scenario: Get a share with a user with resharing rights - Given user "user0" exists - And user "user1" exists - And user "user2" exists - And file "textfile0.txt" of user "user0" is shared with user "user1" - And user "user1" accepts last share - And file "textfile0.txt" of user "user0" is shared with user "user2" - And As an "user1" - When Getting info of last share - 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 | - | item_type | file | - | item_source | A_NUMBER | - | share_type | 0 | - | share_with | user2 | - | file_source | A_NUMBER | - | file_target | /textfile0 (2).txt | - | path | /textfile0 (2).txt | - | permissions | 19 | - | stime | A_NUMBER | - | storage | A_NUMBER | - | mail_send | 0 | - | uid_owner | user0 | - | storage_id | shared::/textfile0 (2).txt | - | file_parent | A_NUMBER | - | share_with_displayname | user2 | - | displayname_owner | user0 | - | mimetype | text/plain | - - Scenario: Share of folder and sub-folder to same user - core#20645 - Given As an "admin" - And user "user0" exists - And user "user1" exists - And group "group0" exists - And user "user1" belongs to group "group0" - And file "/PARENT" of user "user0" is shared with user "user1" - And user "user1" accepts last share - When file "/PARENT/CHILD" of user "user0" is shared with group "group0" - And user "user1" accepts last share - Then user "user1" should see following elements - | /FOLDER/ | - | /PARENT/ | - | /PARENT/CHILD/ | - | /PARENT/parent.txt | - | /PARENT/CHILD/child.txt | - | /PARENT%20(2)/ | - | /PARENT%20(2)/CHILD/ | - | /PARENT%20(2)/parent.txt | - | /PARENT%20(2)/CHILD/child.txt | - | /CHILD/ | - | /CHILD/child.txt | - And the HTTP status code should be "200" - - Scenario: Share a file by multiple channels - Given As an "admin" - And user "user0" exists - And user "user1" exists - And user "user2" exists - And group "group0" exists - And user "user1" belongs to group "group0" - And user "user2" belongs to group "group0" - And user "user0" created a folder "/common" - And user "user0" created a folder "/common/sub" - And file "common" of user "user0" is shared with group "group0" - And user "user1" accepts last share - And user "user2" accepts last share - And file "textfile0.txt" of user "user1" is shared with user "user2" - And user "user2" accepts last share - And User "user1" moved file "/textfile0.txt" to "/common/textfile0.txt" - And User "user1" moved file "/common/textfile0.txt" to "/common/sub/textfile0.txt" - And As an "user2" - When Downloading file "/common/sub/textfile0.txt" with range "bytes=10-18" - Then Downloaded content should be "test text" - And Downloaded content when downloading file "/textfile0.txt" with range "bytes=10-18" should be "test text" - And user "user2" should see following elements - | /common/sub/textfile0.txt | - - Scenario: Share a file by multiple channels - Given As an "admin" - And user "user0" exists - And user "user1" exists - And user "user2" exists - And group "group0" exists - And user "user1" belongs to group "group0" - And user "user2" belongs to group "group0" - And user "user0" created a folder "/common" - And user "user0" created a folder "/common/sub" - And file "common" of user "user0" is shared with group "group0" - And user "user1" accepts last share - And user "user2" accepts last share - And file "textfile0.txt" of user "user1" is shared with user "user2" - And user "user2" accepts last share - And User "user1" moved file "/textfile0.txt" to "/common/textfile0.txt" - And User "user1" moved file "/common/textfile0.txt" to "/common/sub/textfile0.txt" - And As an "user2" - When Downloading file "/textfile0 (2).txt" with range "bytes=10-18" - Then Downloaded content should be "test text" - And user "user2" should see following elements - | /common/sub/textfile0.txt | - - Scenario: Delete all group shares - Given As an "admin" - And user "user0" exists - And user "user1" exists - And group "group1" exists - And user "user1" belongs to group "group1" - And file "textfile0.txt" of user "user0" is shared with group "group1" - And user "user1" accepts last share - And User "user1" moved file "/textfile0 (2).txt" to "/FOLDER/textfile0.txt" - And As an "user0" - And Deleting last share - And As an "user1" - When sending "GET" to "/apps/files_sharing/api/v1/shares?shared_with_me=true" - Then the OCS status code should be "100" - And the HTTP status code should be "200" - And last share_id is not included in the answer - - Scenario: delete a share - Given user "user0" exists - And user "user1" exists - And file "textfile0.txt" of user "user0" is shared with user "user1" - And As an "user0" - When Deleting last share - Then the OCS status code should be "100" - And the HTTP status code should be "200" - - Scenario: delete a share with a user that didn't receive the share - Given user "user0" exists - And user "user1" exists - And user "user2" exists - And file "textfile0.txt" of user "user0" is shared with user "user1" - And As an "user2" - When Deleting last share - Then the OCS status code should be "404" - And the HTTP status code should be "200" - - Scenario: delete a share with a user with resharing rights that didn't receive the share - Given user "user0" exists - And user "user1" exists - And user "user2" exists - And file "textfile0.txt" of user "user0" is shared with user "user1" - And user "user1" accepts last share - And file "textfile0.txt" of user "user0" is shared with user "user2" - And As an "user1" - When Deleting last share - Then the OCS status code should be "403" - And the HTTP status code should be "200" - - Scenario: Keep usergroup shares (#22143) - Given As an "admin" - And user "user0" exists - And user "user1" exists - And user "user2" exists - And group "group" exists - And user "user1" belongs to group "group" - And user "user2" belongs to group "group" - And user "user0" created a folder "/TMP" - And file "TMP" of user "user0" is shared with group "group" - And user "user1" accepts last share - And user "user2" accepts last share - And user "user1" created a folder "/myFOLDER" - And User "user1" moves file "/TMP" to "/myFOLDER/myTMP" - And user "user2" does not exist - And user "user1" should see following elements - | /myFOLDER/myTMP/ | - - Scenario: Check quota of owners parent directory of a shared file - Given using old dav path - And As an "admin" - And user "user0" exists - And user "user1" exists - And user "user1" has a quota of "0" - And User "user0" moved file "/welcome.txt" to "/myfile.txt" - And file "myfile.txt" of user "user0" is shared with user "user1" - And user "user1" accepts last share - When User "user1" uploads file "data/textfile.txt" to "/myfile.txt" - Then the HTTP status code should be "204" - - Scenario: Don't allow sharing of the root - Given user "user0" exists - And As an "user0" - When creating a share with - | path | / | - | shareType | 3 | - Then the OCS status code should be "403" - - Scenario: Allow modification of reshare - Given user "user0" exists - And user "user1" exists - And user "user2" exists - And user "user0" created a folder "/TMP" - And file "TMP" of user "user0" is shared with user "user1" - And user "user1" accepts last share - And file "TMP" of user "user1" is shared with user "user2" - And As an "user1" - When Updating last share with - | permissions | 1 | - Then the OCS status code should be "100" - And the HTTP status code should be "200" - - Scenario: Allow reshare to exceed permissions if shares of same file to same user have them - Given user "user0" exists - And user "user1" exists - And user "user2" exists - And group "group1" exists - And user "user1" belongs to group "group1" - And user "user0" created a folder "/TMP" - And As an "user0" - And creating a share with - | path | /TMP | - | shareType | 1 | - | shareWith | group1 | - | permissions | 15 | - And As an "user1" - And accepting last share - And As an "user0" - And creating a share with - | path | /TMP | - | shareType | 0 | - | shareWith | user1 | - | permissions | 17 | - And As an "user1" - And accepting last share - And creating a share with - | path | /TMP | - | shareType | 0 | - | shareWith | user2 | - | permissions | 17 | - When Updating last share with - | permissions | 31 | - Then the OCS status code should be "100" - And the HTTP status code should be "200" - - Scenario: Do not allow reshare to exceed permissions - Given user "user0" exists - And user "user1" exists - And user "user2" exists - And user "user0" created a folder "/TMP" - And As an "user0" - And creating a share with - | path | /TMP | - | shareType | 0 | - | shareWith | user1 | - | permissions | 21 | - And As an "user1" - And accepting last share - And creating a share with - | path | /TMP | - | shareType | 0 | - | shareWith | user2 | - | permissions | 21 | - When Updating last share with - | permissions | 31 | - Then the OCS status code should be "404" - And the HTTP status code should be "200" - - Scenario: Do not allow reshare to exceed permissions even if shares of same file to other users have them - Given user "user0" exists - And user "user1" exists - And user "user2" exists - And user "user3" exists - And user "user0" created a folder "/TMP" - And As an "user0" - And creating a share with - | path | /TMP | - | shareType | 0 | - | shareWith | user3 | - | permissions | 15 | - And As an "user3" - And accepting last share - And As an "user0" - And creating a share with - | path | /TMP | - | shareType | 0 | - | shareWith | user1 | - | permissions | 21 | - And As an "user1" - And accepting last share - And creating a share with - | path | /TMP | - | shareType | 0 | - | shareWith | user2 | - | permissions | 21 | - When Updating last share with - | permissions | 31 | - Then the OCS status code should be "404" - And the HTTP status code should be "200" - - Scenario: Do not allow reshare to exceed permissions even if shares of other files from same user have them - Given user "user0" exists - And user "user1" exists - And user "user2" exists - And As an "user0" - And creating a share with - | path | /FOLDER | - | shareType | 0 | - | shareWith | user1 | - | permissions | 15 | - And As an "user1" - And accepting last share - And user "user0" created a folder "/TMP" - And As an "user0" - And creating a share with - | path | /TMP | - | shareType | 0 | - | shareWith | user1 | - | permissions | 21 | - And As an "user1" - And accepting last share - And creating a share with - | path | /TMP | - | shareType | 0 | - | shareWith | user2 | - | permissions | 21 | - When Updating last share with - | permissions | 31 | - Then the OCS status code should be "404" - And the HTTP status code should be "200" - - Scenario: Do not allow reshare to exceed permissions even if shares of other files from other users have them - Given user "user0" exists - And user "user1" exists - And user "user2" exists - And user "user3" exists - And As an "user3" - And creating a share with - | path | /FOLDER | - | shareType | 0 | - | shareWith | user1 | - | permissions | 15 | - And As an "user1" - And accepting last share - And user "user0" created a folder "/TMP" - And As an "user0" - And creating a share with - | path | /TMP | - | shareType | 0 | - | shareWith | user1 | - | permissions | 21 | - And As an "user1" - And accepting last share - And creating a share with - | path | /TMP | - | shareType | 0 | - | shareWith | user2 | - | permissions | 21 | - When Updating last share with - | permissions | 31 | - Then the OCS status code should be "404" - And the HTTP status code should be "200" - - Scenario: Do not allow sub reshare to exceed permissions - Given user "user0" exists - And user "user1" exists - And user "user2" exists - And user "user0" created a folder "/TMP" - And user "user0" created a folder "/TMP/SUB" - And As an "user0" - And creating a share with - | path | /TMP | - | shareType | 0 | - | shareWith | user1 | - | permissions | 21 | - And As an "user1" - And accepting last share - And creating a share with - | path | /TMP/SUB | - | shareType | 0 | - | shareWith | user2 | - | permissions | 21 | - When Updating last share with - | permissions | 31 | - Then the OCS status code should be "404" - And the HTTP status code should be "200" - - Scenario: Only allow 1 link share per file/folder - Given user "user0" exists - And As an "user0" - And creating a share with - | path | welcome.txt | - | shareType | 3 | - When save last share id - And creating a share with - | path | welcome.txt | - | shareType | 3 | - Then share ids should match - - Scenario: Correct webdav share-permissions for owned file - Given user "user0" exists - And User "user0" uploads file with content "foo" to "/tmp.txt" - When as "user0" gets properties of folder "/tmp.txt" with - |{http://open-collaboration-services.org/ns}share-permissions | - Then the single response should contain a property "{http://open-collaboration-services.org/ns}share-permissions" with value "19" - - Scenario: Cannot download a file when it's shared view-only without shareapi_allow_view_without_download - Given As an "admin" - And parameter "shareapi_allow_view_without_download" of app "core" is set to "no" - Given user "user0" exists - And user "user1" exists - And User "user0" moves file "/textfile0.txt" to "/document.odt" - And file "document.odt" of user "user0" is shared with user "user1" view-only - And user "user1" accepts last share - When As an "user1" - And Downloading file "/document.odt" - Then the HTTP status code should be "403" - Then As an "admin" - And parameter "shareapi_allow_view_without_download" of app "core" is set to "yes" - Then As an "user1" - And Downloading file "/document.odt" - Then the HTTP status code should be "200" - - Scenario: Cannot download a file when its parent is shared view-only without shareapi_allow_view_without_download - Given As an "admin" - And parameter "shareapi_allow_view_without_download" of app "core" is set to "no" - Given user "user0" exists - And user "user1" exists - And User "user0" created a folder "/sharedviewonly" - And User "user0" moves file "/textfile0.txt" to "/sharedviewonly/document.odt" - And folder "sharedviewonly" of user "user0" is shared with user "user1" view-only - And user "user1" accepts last share - When As an "user1" - And Downloading file "/sharedviewonly/document.odt" - Then the HTTP status code should be "403" - Then As an "admin" - And parameter "shareapi_allow_view_without_download" of app "core" is set to "yes" - Then As an "user1" - And Downloading file "/sharedviewonly/document.odt" - Then the HTTP status code should be "200" - - Scenario: Cannot copy a file when it's shared view-only even with shareapi_allow_view_without_download enabled - Given As an "admin" - And parameter "shareapi_allow_view_without_download" of app "core" is set to "no" - Given user "user0" exists - And user "user1" exists - And User "user0" moves file "/textfile0.txt" to "/document.odt" - And file "document.odt" of user "user0" is shared with user "user1" view-only - And user "user1" accepts last share - When User "user1" copies file "/document.odt" to "/copyforbidden.odt" - Then the HTTP status code should be "403" - Then As an "admin" - And parameter "shareapi_allow_view_without_download" of app "core" is set to "yes" - Then As an "user1" - And User "user1" copies file "/document.odt" to "/copyforbidden.odt" - Then the HTTP status code should be "403" - - Scenario: Cannot copy a file when its parent is shared view-only - Given As an "admin" - And parameter "shareapi_allow_view_without_download" of app "core" is set to "no" - Given user "user0" exists - And user "user1" exists - And User "user0" created a folder "/sharedviewonly" - And User "user0" moves file "/textfile0.txt" to "/sharedviewonly/document.odt" - And folder "sharedviewonly" of user "user0" is shared with user "user1" view-only - And user "user1" accepts last share - When User "user1" copies file "/sharedviewonly/document.odt" to "/copyforbidden.odt" - Then the HTTP status code should be "403" - Then As an "admin" - And parameter "shareapi_allow_view_without_download" of app "core" is set to "yes" - Then As an "user1" - And User "user1" copies file "/sharedviewonly/document.odt" to "/copyforbidden.odt" - Then the HTTP status code should be "403" - -# See sharing-v1-part3.feature +# see sharing-v1-part2b.feature From 384b79d4fbdbac5e60512019a9788d6ad3b6edad Mon Sep 17 00:00:00 2001 From: Josh Date: Wed, 8 Apr 2026 10:18:02 -0400 Subject: [PATCH 14/16] test(sharing): move half of tests into new sharing-v1-part2b.feature Signed-off-by: Josh --- .../sharing-v1-part2b.feature | 612 ++++++++++++++++++ 1 file changed, 612 insertions(+) create mode 100644 build/integration/sharing_features/sharing-v1-part2b.feature diff --git a/build/integration/sharing_features/sharing-v1-part2b.feature b/build/integration/sharing_features/sharing-v1-part2b.feature new file mode 100644 index 0000000000000..f0943f3386d18 --- /dev/null +++ b/build/integration/sharing_features/sharing-v1-part2b.feature @@ -0,0 +1,612 @@ +# SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors +# SPDX-License-Identifier: AGPL-3.0-or-later + Scenario: download restrictions can not be dropped + As an "admin" + Given user "user0" exists + And user "user1" exists + And user "user2" exists + And User "user0" uploads file with content "foo" to "/tmp.txt" + And As an "user0" + And creating a share with + | path | /tmp.txt | + | shareType | 0 | + | shareWith | user1 | + | permissions | 17 | + | attributes | [{"scope":"permissions","key":"download","value":false}] | + And As an "user1" + And accepting last share + When Getting info of last share + Then Share fields of last share match with + | uid_owner | user0 | + | uid_file_owner | user0 | + | permissions | 17 | + | attributes | [{"scope":"permissions","key":"download","value":false}] | + When creating a share with + | path | /tmp.txt | + | shareType | 0 | + | shareWith | user2 | + | permissions | 1 | + Then the OCS status code should be "100" + And the HTTP status code should be "200" + When As an "user2" + And accepting last share + And Getting info of last share + Then Share fields of last share match with + | share_type | 0 | + | permissions | 1 | + | uid_owner | user1 | + | uid_file_owner | user0 | + | attributes | [{"scope":"permissions","key":"download","value":false}] | + + Scenario: download restrictions can not be dropped when re-sharing even on link shares + As an "admin" + Given user "user0" exists + And user "user1" exists + And User "user0" uploads file with content "foo" to "/tmp.txt" + And As an "user0" + And creating a share with + | path | /tmp.txt | + | shareType | 0 | + | shareWith | user1 | + | permissions | 17 | + | attributes | [{"scope":"permissions","key":"download","value":false}] | + And As an "user1" + And accepting last share + When Getting info of last share + Then Share fields of last share match with + | uid_owner | user0 | + | attributes | [{"scope":"permissions","key":"download","value":false}] | + When creating a share with + | path | /tmp.txt | + | shareType | 3 | + | permissions | 1 | + And Getting info of last share + And Updating last share with + | hideDownload | false | + Then the OCS status code should be "100" + And the HTTP status code should be "200" + When Getting info of last share + Then Share fields of last share match with + | share_type | 3 | + | uid_owner | user1 | + | uid_file_owner | user0 | + | hide_download | 1 | + | attributes | [{"scope":"permissions","key":"download","value":false}] | + + Scenario: User is not allowed to reshare file with additional delete permissions + As an "admin" + Given user "user0" exists + And user "user1" exists + And user "user2" exists + And As an "user0" + And creating a share with + | path | /PARENT | + | shareType | 0 | + | shareWith | user1 | + | permissions | 16 | + And As an "user1" + And accepting last share + When creating a share with + | path | /PARENT (2) | + | shareType | 0 | + | shareWith | user2 | + | permissions | 25 | + Then the OCS status code should be "404" + And the HTTP status code should be "200" + + Scenario: User is not allowed to reshare file with additional delete permissions for files + As an "admin" + Given user "user0" exists + And user "user1" exists + And user "user2" exists + And As an "user0" + And creating a share with + | path | /textfile0.txt | + | shareType | 0 | + | shareWith | user1 | + | permissions | 16 | + And As an "user1" + And accepting last share + When creating a share with + | path | /textfile0 (2).txt | + | shareType | 0 | + | shareWith | user2 | + | permissions | 25 | + Then the OCS status code should be "100" + And the HTTP status code should be "200" + When Getting info of last share + Then Share fields of last share match with + | id | A_NUMBER | + | item_type | file | + | item_source | A_NUMBER | + | share_type | 0 | + | share_with | user2 | + | file_source | A_NUMBER | + | file_target | /textfile0 (2).txt | + | path | /textfile0 (2).txt | + | permissions | 17 | + | stime | A_NUMBER | + | storage | A_NUMBER | + | mail_send | 0 | + | uid_owner | user1 | + | storage_id | shared::/textfile0 (2).txt | + | file_parent | A_NUMBER | + | share_with_displayname | user2 | + | displayname_owner | user1 | + | mimetype | text/plain | + + Scenario: Get a share with a user which didn't received the share + Given user "user0" exists + And user "user1" exists + And user "user2" exists + And file "textfile0.txt" of user "user0" is shared with user "user1" + And As an "user2" + When Getting info of last share + Then the OCS status code should be "404" + And the HTTP status code should be "200" + + Scenario: Get a share with a user with resharing rights + Given user "user0" exists + And user "user1" exists + And user "user2" exists + And file "textfile0.txt" of user "user0" is shared with user "user1" + And user "user1" accepts last share + And file "textfile0.txt" of user "user0" is shared with user "user2" + And As an "user1" + When Getting info of last share + 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 | + | item_type | file | + | item_source | A_NUMBER | + | share_type | 0 | + | share_with | user2 | + | file_source | A_NUMBER | + | file_target | /textfile0 (2).txt | + | path | /textfile0 (2).txt | + | permissions | 19 | + | stime | A_NUMBER | + | storage | A_NUMBER | + | mail_send | 0 | + | uid_owner | user0 | + | storage_id | shared::/textfile0 (2).txt | + | file_parent | A_NUMBER | + | share_with_displayname | user2 | + | displayname_owner | user0 | + | mimetype | text/plain | + + Scenario: Share of folder and sub-folder to same user - core#20645 + Given As an "admin" + And user "user0" exists + And user "user1" exists + And group "group0" exists + And user "user1" belongs to group "group0" + And file "/PARENT" of user "user0" is shared with user "user1" + And user "user1" accepts last share + When file "/PARENT/CHILD" of user "user0" is shared with group "group0" + And user "user1" accepts last share + Then user "user1" should see following elements + | /FOLDER/ | + | /PARENT/ | + | /PARENT/CHILD/ | + | /PARENT/parent.txt | + | /PARENT/CHILD/child.txt | + | /PARENT%20(2)/ | + | /PARENT%20(2)/CHILD/ | + | /PARENT%20(2)/parent.txt | + | /PARENT%20(2)/CHILD/child.txt | + | /CHILD/ | + | /CHILD/child.txt | + And the HTTP status code should be "200" + + Scenario: Share a file by multiple channels + Given As an "admin" + And user "user0" exists + And user "user1" exists + And user "user2" exists + And group "group0" exists + And user "user1" belongs to group "group0" + And user "user2" belongs to group "group0" + And user "user0" created a folder "/common" + And user "user0" created a folder "/common/sub" + And file "common" of user "user0" is shared with group "group0" + And user "user1" accepts last share + And user "user2" accepts last share + And file "textfile0.txt" of user "user1" is shared with user "user2" + And user "user2" accepts last share + And User "user1" moved file "/textfile0.txt" to "/common/textfile0.txt" + And User "user1" moved file "/common/textfile0.txt" to "/common/sub/textfile0.txt" + And As an "user2" + When Downloading file "/common/sub/textfile0.txt" with range "bytes=10-18" + Then Downloaded content should be "test text" + And Downloaded content when downloading file "/textfile0.txt" with range "bytes=10-18" should be "test text" + And user "user2" should see following elements + | /common/sub/textfile0.txt | + + Scenario: Share a file by multiple channels + Given As an "admin" + And user "user0" exists + And user "user1" exists + And user "user2" exists + And group "group0" exists + And user "user1" belongs to group "group0" + And user "user2" belongs to group "group0" + And user "user0" created a folder "/common" + And user "user0" created a folder "/common/sub" + And file "common" of user "user0" is shared with group "group0" + And user "user1" accepts last share + And user "user2" accepts last share + And file "textfile0.txt" of user "user1" is shared with user "user2" + And user "user2" accepts last share + And User "user1" moved file "/textfile0.txt" to "/common/textfile0.txt" + And User "user1" moved file "/common/textfile0.txt" to "/common/sub/textfile0.txt" + And As an "user2" + When Downloading file "/textfile0 (2).txt" with range "bytes=10-18" + Then Downloaded content should be "test text" + And user "user2" should see following elements + | /common/sub/textfile0.txt | + + Scenario: Delete all group shares + Given As an "admin" + And user "user0" exists + And user "user1" exists + And group "group1" exists + And user "user1" belongs to group "group1" + And file "textfile0.txt" of user "user0" is shared with group "group1" + And user "user1" accepts last share + And User "user1" moved file "/textfile0 (2).txt" to "/FOLDER/textfile0.txt" + And As an "user0" + And Deleting last share + And As an "user1" + When sending "GET" to "/apps/files_sharing/api/v1/shares?shared_with_me=true" + Then the OCS status code should be "100" + And the HTTP status code should be "200" + And last share_id is not included in the answer + + Scenario: delete a share + Given user "user0" exists + And user "user1" exists + And file "textfile0.txt" of user "user0" is shared with user "user1" + And As an "user0" + When Deleting last share + Then the OCS status code should be "100" + And the HTTP status code should be "200" + + Scenario: delete a share with a user that didn't receive the share + Given user "user0" exists + And user "user1" exists + And user "user2" exists + And file "textfile0.txt" of user "user0" is shared with user "user1" + And As an "user2" + When Deleting last share + Then the OCS status code should be "404" + And the HTTP status code should be "200" + + Scenario: delete a share with a user with resharing rights that didn't receive the share + Given user "user0" exists + And user "user1" exists + And user "user2" exists + And file "textfile0.txt" of user "user0" is shared with user "user1" + And user "user1" accepts last share + And file "textfile0.txt" of user "user0" is shared with user "user2" + And As an "user1" + When Deleting last share + Then the OCS status code should be "403" + And the HTTP status code should be "200" + + Scenario: Keep usergroup shares (#22143) + Given As an "admin" + And user "user0" exists + And user "user1" exists + And user "user2" exists + And group "group" exists + And user "user1" belongs to group "group" + And user "user2" belongs to group "group" + And user "user0" created a folder "/TMP" + And file "TMP" of user "user0" is shared with group "group" + And user "user1" accepts last share + And user "user2" accepts last share + And user "user1" created a folder "/myFOLDER" + And User "user1" moves file "/TMP" to "/myFOLDER/myTMP" + And user "user2" does not exist + And user "user1" should see following elements + | /myFOLDER/myTMP/ | + + Scenario: Check quota of owners parent directory of a shared file + Given using old dav path + And As an "admin" + And user "user0" exists + And user "user1" exists + And user "user1" has a quota of "0" + And User "user0" moved file "/welcome.txt" to "/myfile.txt" + And file "myfile.txt" of user "user0" is shared with user "user1" + And user "user1" accepts last share + When User "user1" uploads file "data/textfile.txt" to "/myfile.txt" + Then the HTTP status code should be "204" + + Scenario: Don't allow sharing of the root + Given user "user0" exists + And As an "user0" + When creating a share with + | path | / | + | shareType | 3 | + Then the OCS status code should be "403" + + Scenario: Allow modification of reshare + Given user "user0" exists + And user "user1" exists + And user "user2" exists + And user "user0" created a folder "/TMP" + And file "TMP" of user "user0" is shared with user "user1" + And user "user1" accepts last share + And file "TMP" of user "user1" is shared with user "user2" + And As an "user1" + When Updating last share with + | permissions | 1 | + Then the OCS status code should be "100" + And the HTTP status code should be "200" + + Scenario: Allow reshare to exceed permissions if shares of same file to same user have them + Given user "user0" exists + And user "user1" exists + And user "user2" exists + And group "group1" exists + And user "user1" belongs to group "group1" + And user "user0" created a folder "/TMP" + And As an "user0" + And creating a share with + | path | /TMP | + | shareType | 1 | + | shareWith | group1 | + | permissions | 15 | + And As an "user1" + And accepting last share + And As an "user0" + And creating a share with + | path | /TMP | + | shareType | 0 | + | shareWith | user1 | + | permissions | 17 | + And As an "user1" + And accepting last share + And creating a share with + | path | /TMP | + | shareType | 0 | + | shareWith | user2 | + | permissions | 17 | + When Updating last share with + | permissions | 31 | + Then the OCS status code should be "100" + And the HTTP status code should be "200" + + Scenario: Do not allow reshare to exceed permissions + Given user "user0" exists + And user "user1" exists + And user "user2" exists + And user "user0" created a folder "/TMP" + And As an "user0" + And creating a share with + | path | /TMP | + | shareType | 0 | + | shareWith | user1 | + | permissions | 21 | + And As an "user1" + And accepting last share + And creating a share with + | path | /TMP | + | shareType | 0 | + | shareWith | user2 | + | permissions | 21 | + When Updating last share with + | permissions | 31 | + Then the OCS status code should be "404" + And the HTTP status code should be "200" + + Scenario: Do not allow reshare to exceed permissions even if shares of same file to other users have them + Given user "user0" exists + And user "user1" exists + And user "user2" exists + And user "user3" exists + And user "user0" created a folder "/TMP" + And As an "user0" + And creating a share with + | path | /TMP | + | shareType | 0 | + | shareWith | user3 | + | permissions | 15 | + And As an "user3" + And accepting last share + And As an "user0" + And creating a share with + | path | /TMP | + | shareType | 0 | + | shareWith | user1 | + | permissions | 21 | + And As an "user1" + And accepting last share + And creating a share with + | path | /TMP | + | shareType | 0 | + | shareWith | user2 | + | permissions | 21 | + When Updating last share with + | permissions | 31 | + Then the OCS status code should be "404" + And the HTTP status code should be "200" + + Scenario: Do not allow reshare to exceed permissions even if shares of other files from same user have them + Given user "user0" exists + And user "user1" exists + And user "user2" exists + And As an "user0" + And creating a share with + | path | /FOLDER | + | shareType | 0 | + | shareWith | user1 | + | permissions | 15 | + And As an "user1" + And accepting last share + And user "user0" created a folder "/TMP" + And As an "user0" + And creating a share with + | path | /TMP | + | shareType | 0 | + | shareWith | user1 | + | permissions | 21 | + And As an "user1" + And accepting last share + And creating a share with + | path | /TMP | + | shareType | 0 | + | shareWith | user2 | + | permissions | 21 | + When Updating last share with + | permissions | 31 | + Then the OCS status code should be "404" + And the HTTP status code should be "200" + + Scenario: Do not allow reshare to exceed permissions even if shares of other files from other users have them + Given user "user0" exists + And user "user1" exists + And user "user2" exists + And user "user3" exists + And As an "user3" + And creating a share with + | path | /FOLDER | + | shareType | 0 | + | shareWith | user1 | + | permissions | 15 | + And As an "user1" + And accepting last share + And user "user0" created a folder "/TMP" + And As an "user0" + And creating a share with + | path | /TMP | + | shareType | 0 | + | shareWith | user1 | + | permissions | 21 | + And As an "user1" + And accepting last share + And creating a share with + | path | /TMP | + | shareType | 0 | + | shareWith | user2 | + | permissions | 21 | + When Updating last share with + | permissions | 31 | + Then the OCS status code should be "404" + And the HTTP status code should be "200" + + Scenario: Do not allow sub reshare to exceed permissions + Given user "user0" exists + And user "user1" exists + And user "user2" exists + And user "user0" created a folder "/TMP" + And user "user0" created a folder "/TMP/SUB" + And As an "user0" + And creating a share with + | path | /TMP | + | shareType | 0 | + | shareWith | user1 | + | permissions | 21 | + And As an "user1" + And accepting last share + And creating a share with + | path | /TMP/SUB | + | shareType | 0 | + | shareWith | user2 | + | permissions | 21 | + When Updating last share with + | permissions | 31 | + Then the OCS status code should be "404" + And the HTTP status code should be "200" + + Scenario: Only allow 1 link share per file/folder + Given user "user0" exists + And As an "user0" + And creating a share with + | path | welcome.txt | + | shareType | 3 | + When save last share id + And creating a share with + | path | welcome.txt | + | shareType | 3 | + Then share ids should match + + Scenario: Correct webdav share-permissions for owned file + Given user "user0" exists + And User "user0" uploads file with content "foo" to "/tmp.txt" + When as "user0" gets properties of folder "/tmp.txt" with + |{http://open-collaboration-services.org/ns}share-permissions | + Then the single response should contain a property "{http://open-collaboration-services.org/ns}share-permissions" with value "19" + + Scenario: Cannot download a file when it's shared view-only without shareapi_allow_view_without_download + Given As an "admin" + And parameter "shareapi_allow_view_without_download" of app "core" is set to "no" + Given user "user0" exists + And user "user1" exists + And User "user0" moves file "/textfile0.txt" to "/document.odt" + And file "document.odt" of user "user0" is shared with user "user1" view-only + And user "user1" accepts last share + When As an "user1" + And Downloading file "/document.odt" + Then the HTTP status code should be "403" + Then As an "admin" + And parameter "shareapi_allow_view_without_download" of app "core" is set to "yes" + Then As an "user1" + And Downloading file "/document.odt" + Then the HTTP status code should be "200" + + Scenario: Cannot download a file when its parent is shared view-only without shareapi_allow_view_without_download + Given As an "admin" + And parameter "shareapi_allow_view_without_download" of app "core" is set to "no" + Given user "user0" exists + And user "user1" exists + And User "user0" created a folder "/sharedviewonly" + And User "user0" moves file "/textfile0.txt" to "/sharedviewonly/document.odt" + And folder "sharedviewonly" of user "user0" is shared with user "user1" view-only + And user "user1" accepts last share + When As an "user1" + And Downloading file "/sharedviewonly/document.odt" + Then the HTTP status code should be "403" + Then As an "admin" + And parameter "shareapi_allow_view_without_download" of app "core" is set to "yes" + Then As an "user1" + And Downloading file "/sharedviewonly/document.odt" + Then the HTTP status code should be "200" + + Scenario: Cannot copy a file when it's shared view-only even with shareapi_allow_view_without_download enabled + Given As an "admin" + And parameter "shareapi_allow_view_without_download" of app "core" is set to "no" + Given user "user0" exists + And user "user1" exists + And User "user0" moves file "/textfile0.txt" to "/document.odt" + And file "document.odt" of user "user0" is shared with user "user1" view-only + And user "user1" accepts last share + When User "user1" copies file "/document.odt" to "/copyforbidden.odt" + Then the HTTP status code should be "403" + Then As an "admin" + And parameter "shareapi_allow_view_without_download" of app "core" is set to "yes" + Then As an "user1" + And User "user1" copies file "/document.odt" to "/copyforbidden.odt" + Then the HTTP status code should be "403" + + Scenario: Cannot copy a file when its parent is shared view-only + Given As an "admin" + And parameter "shareapi_allow_view_without_download" of app "core" is set to "no" + Given user "user0" exists + And user "user1" exists + And User "user0" created a folder "/sharedviewonly" + And User "user0" moves file "/textfile0.txt" to "/sharedviewonly/document.odt" + And folder "sharedviewonly" of user "user0" is shared with user "user1" view-only + And user "user1" accepts last share + When User "user1" copies file "/sharedviewonly/document.odt" to "/copyforbidden.odt" + Then the HTTP status code should be "403" + Then As an "admin" + And parameter "shareapi_allow_view_without_download" of app "core" is set to "yes" + Then As an "user1" + And User "user1" copies file "/sharedviewonly/document.odt" to "/copyforbidden.odt" + Then the HTTP status code should be "403" + +# See sharing-v1-part3.feature From 2161469624b2cde14854b11cedaa8831c7b48446 Mon Sep 17 00:00:00 2001 From: Josh Date: Wed, 8 Apr 2026 10:19:57 -0400 Subject: [PATCH 15/16] ci(integration-sqlite): split sharing-v1-part2 in half Signed-off-by: Josh --- .github/workflows/integration-sqlite.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/integration-sqlite.yml b/.github/workflows/integration-sqlite.yml index a462e587d1805..58c9873990dd5 100644 --- a/.github/workflows/integration-sqlite.yml +++ b/.github/workflows/integration-sqlite.yml @@ -75,7 +75,8 @@ jobs: - 'sharees_features/sharees.feature sharees_features/sharees_provisioningapiv2.feature' - 'sharees_features/sharees_user.feature' - 'sharing_features/sharing-v1.feature sharing_features/sharing-activity.feature' - - 'sharing_features/sharing-v1-part2.feature' + - 'sharing_features/sharing-v1-part2a.feature' + - 'sharing_features/sharing-v1-part2b.feature' - 'sharing_features/sharing-v1-part3.feature sharing_features/sharing-v1-part4.feature' - 'theming_features' - 'videoverification_features' From 21e5944fc65df876eb748c54956b5ebfacd1e26e Mon Sep 17 00:00:00 2001 From: Josh Date: Wed, 8 Apr 2026 10:29:34 -0400 Subject: [PATCH 16/16] chore(sharing_features): add Feature context to split off part2b Signed-off-by: Josh --- .../integration/sharing_features/sharing-v1-part2b.feature | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/build/integration/sharing_features/sharing-v1-part2b.feature b/build/integration/sharing_features/sharing-v1-part2b.feature index f0943f3386d18..feb58afdff5e3 100644 --- a/build/integration/sharing_features/sharing-v1-part2b.feature +++ b/build/integration/sharing_features/sharing-v1-part2b.feature @@ -1,5 +1,11 @@ # SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors # SPDX-License-Identifier: AGPL-3.0-or-later +Feature: sharing + Background: + Given using api version "1" + Given using old dav path + +# See sharing-v1.feature Scenario: download restrictions can not be dropped As an "admin" Given user "user0" exists