diff options
Diffstat (limited to 'build/integration')
-rw-r--r-- | build/integration/config/behat.yml | 10 | ||||
-rw-r--r-- | build/integration/features/bootstrap/Sharing.php | 2 | ||||
-rw-r--r-- | build/integration/features/bootstrap/SharingContext.php | 40 | ||||
-rwxr-xr-x | build/integration/run-docker.sh | 261 | ||||
-rw-r--r-- | build/integration/sharing_features/sharing-v1-part2.feature (renamed from build/integration/features/sharing-v1-part2.feature) | 54 | ||||
-rw-r--r-- | build/integration/sharing_features/sharing-v1-part3.feature (renamed from build/integration/features/sharing-v1-part3.feature) | 64 | ||||
-rw-r--r-- | build/integration/sharing_features/sharing-v1.feature (renamed from build/integration/features/sharing-v1.feature) | 20 |
7 files changed, 449 insertions, 2 deletions
diff --git a/build/integration/config/behat.yml b/build/integration/config/behat.yml index 51b749360e3..27d7daa4818 100644 --- a/build/integration/config/behat.yml +++ b/build/integration/config/behat.yml @@ -55,6 +55,16 @@ default: - admin - admin regular_user_password: 123456 + sharing: + paths: + - "%paths.base%/../sharing_features" + contexts: + - SharingContext: + baseUrl: http://localhost:8080/ocs/ + admin: + - admin + - admin + regular_user_password: 123456 setup: paths: - "%paths.base%/../setup_features" diff --git a/build/integration/features/bootstrap/Sharing.php b/build/integration/features/bootstrap/Sharing.php index abbac030e3b..4e62ea73c5d 100644 --- a/build/integration/features/bootstrap/Sharing.php +++ b/build/integration/features/bootstrap/Sharing.php @@ -218,8 +218,6 @@ trait Sharing { } catch (\GuzzleHttp\Exception\ClientException $ex) { $this->response = $ex->getResponse(); } - - Assert::assertEquals(200, $this->response->getStatusCode()); } public function createShare($user, diff --git a/build/integration/features/bootstrap/SharingContext.php b/build/integration/features/bootstrap/SharingContext.php new file mode 100644 index 00000000000..f208565740b --- /dev/null +++ b/build/integration/features/bootstrap/SharingContext.php @@ -0,0 +1,40 @@ +<?php +/** + * + * + * @author Joas Schilling <coding@schilljs.com> + * @author Roeland Jago Douma <roeland@famdouma.nl> + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ +use Behat\Behat\Context\Context; +use Behat\Behat\Context\SnippetAcceptingContext; +use PHPUnit\Framework\Assert; +use Psr\Http\Message\ResponseInterface; + +require __DIR__ . '/../../vendor/autoload.php'; + + +/** + * Features context. + */ +class SharingContext implements Context, SnippetAcceptingContext { + use Sharing; + use AppConfiguration; + + protected function resetAppConfigs() {} +} diff --git a/build/integration/run-docker.sh b/build/integration/run-docker.sh new file mode 100755 index 00000000000..5e9bea867a0 --- /dev/null +++ b/build/integration/run-docker.sh @@ -0,0 +1,261 @@ +#!/usr/bin/env bash + +# @copyright Copyright (c) 2017, Daniel Calviño Sánchez (danxuliu@gmail.com) +# @copyright Copyright (c) 2018, Daniel Calviño Sánchez (danxuliu@gmail.com) +# +# @license GNU AGPL version 3 or any later version +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# Helper script to run the integration tests on a fresh Nextcloud server through +# Docker. +# +# The integration tests are run in its own Docker container; the grandparent +# directory of the integration tests directory (that is, the root directory of +# the Nextcloud server) is copied to the container and the integration tests are +# run inside it; in the container the configuration/data from the original +# Nextcloud server is ignored, and a new server installation is performed inside +# the container instead. Once the tests end the container is stopped. +# +# To perform its job, the script requires the "docker" command to be available. +# +# The Docker Command Line Interface (the "docker" command) requires special +# permissions to talk to the Docker daemon, and those permissions are typically +# available only to the root user. Please see the Docker documentation to find +# out how to give access to a regular user to the Docker daemon: +# https://docs.docker.com/engine/installation/linux/linux-postinstall/ +# +# Note, however, that being able to communicate with the Docker daemon is the +# same as being able to get root privileges for the system. Therefore, you must +# give access to the Docker daemon (and thus run this script as) ONLY to trusted +# and secure users: +# https://docs.docker.com/engine/security/security/#docker-daemon-attack-surface +# +# Finally, take into account that this script will automatically remove the +# Docker containers named "database-nextcloud-local-test-integration" and +# "nextcloud-local-test-integration", even if the script did not create them +# (probably you will not have containers nor images with that name, but just in +# case). + +# Sets the variables that abstract the differences in command names and options +# between operating systems. +# +# Switches between mktemp on GNU/Linux and gmktemp on macOS. +function setOperatingSystemAbstractionVariables() { + case "$OSTYPE" in + darwin*) + if [ "$(which gtimeout)" == "" ]; then + echo "Please install coreutils (brew install coreutils)" + exit 1 + fi + + MKTEMP=gmktemp + TIMEOUT=gtimeout + ;; + linux*) + MKTEMP=mktemp + TIMEOUT=timeout + ;; + *) + echo "Operating system ($OSTYPE) not supported" + exit 1 + ;; + esac +} + +# Launches the database server in a Docker container. +# +# No server is started if "SQLite" is being used; in other cases the database +# is set up as needed and generic "$DATABASE_NAME/USER/PASSWORD" variables +# (independent of the database type) are set to be used when installing the +# Nextcloud server. +# +# The Docker container started here will be automatically stopped when the +# script exits (see cleanUp). If the database server can not be started then the +# script will be exited immediately with an error state. +function prepareDatabase() { + if [ "$DATABASE" = "sqlite" ]; then + return + fi + + DATABASE_CONTAINER=database-nextcloud-local-test-integration + + DATABASE_NAME=oc_autotest + DATABASE_USER=oc_autotest + DATABASE_PASSWORD=nextcloud + + DATABASE_CONTAINER_OPTIONS="--env MYSQL_ROOT_PASSWORD=nextcloud_root --env MYSQL_USER=$DATABASE_USER --env MYSQL_PASSWORD=$DATABASE_PASSWORD --env MYSQL_DATABASE=$DATABASE_NAME" + if [ "$DATABASE" = "pgsql" ]; then + DATABASE_CONTAINER_OPTIONS=" --env POSTGRES_USER=$DATABASE_USER --env POSTGRES_PASSWORD=$DATABASE_PASSWORD --env POSTGRES_DB=${DATABASE_NAME}_dummy" + fi + + echo "Starting database server" + docker run --detach --name=$DATABASE_CONTAINER $DATABASE_CONTAINER_OPTIONS $DATABASE_IMAGE + + DATABASE_IP=$(docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $DATABASE_CONTAINER) + + DATABASE_PORT=3306 + if [ "$DATABASE" = "pgsql" ]; then + DATABASE_PORT=5432 + fi + + echo "Waiting for database server to be ready" + if ! $TIMEOUT 600s bash -c "while ! (</dev/tcp/$DATABASE_IP/$DATABASE_PORT) >/dev/null 2>&1; do sleep 1; done"; then + echo "Could not start database server after 600 seconds" >&2 + + exit 1 + fi +} + +# Creates a Docker container to run the integration tests. +# +# This function starts a Docker container with a copy of the Nextcloud code from +# the grandparent directory, although ignoring any configuration or data that it +# may provide (for example, if that directory was used directly to deploy a +# Nextcloud instance in a web server). As the Nextcloud code is copied to the +# container instead of referenced the original code can be modified while the +# integration tests are running without interfering in them. +function prepareDocker() { + NEXTCLOUD_LOCAL_CONTAINER=nextcloud-local-test-integration + + NEXTCLOUD_LOCAL_CONTAINER_NETWORK_OPTIONS="" + if [ -n "$DATABASE_CONTAINER" ]; then + # The network stack is shared between the database and the Nextcloud + # container, so the Nextcloud server can access the database directly on + # 127.0.0.1. + NEXTCLOUD_LOCAL_CONTAINER_NETWORK_OPTIONS="--network=container:$DATABASE_CONTAINER" + fi + + echo "Starting the Nextcloud container" + # When using "nextcloudci/phpX.Y" images the container exits immediately if + # no command is given, so a Bash session is created to prevent that. + docker run --detach --name=$NEXTCLOUD_LOCAL_CONTAINER $NEXTCLOUD_LOCAL_CONTAINER_NETWORK_OPTIONS --interactive --tty $NEXTCLOUD_LOCAL_IMAGE bash + + # Use the $TMPDIR or, if not set, fall back to /tmp. + NEXTCLOUD_LOCAL_TAR="$($MKTEMP --tmpdir="${TMPDIR:-/tmp}" --suffix=.tar nextcloud-local-XXXXXXXXXX)" + + # Setting the user and group of files in the tar would be superfluous, as + # "docker cp" does not take them into account (the extracted files are set + # to root). + echo "Copying local Git working directory of Nextcloud to the container" + tar --create --file="$NEXTCLOUD_LOCAL_TAR" \ + --exclude=".git" \ + --exclude="./config/config.php" \ + --exclude="./data" \ + --exclude="./data-autotest" \ + --exclude="./tests" \ + --exclude="node_modules" \ + --directory=../../ \ + . + + docker exec $NEXTCLOUD_LOCAL_CONTAINER mkdir /nextcloud + docker cp - $NEXTCLOUD_LOCAL_CONTAINER:/nextcloud/ < "$NEXTCLOUD_LOCAL_TAR" + + # Database options are needed only when a database other than SQLite is + # used. + NEXTCLOUD_LOCAL_CONTAINER_INSTALL_DATABASE_OPTIONS="" + if [ -n "$DATABASE_CONTAINER" ]; then + NEXTCLOUD_LOCAL_CONTAINER_INSTALL_DATABASE_OPTIONS="--database=$DATABASE --database-name=$DATABASE_NAME --database-user=$DATABASE_USER --database-pass=$DATABASE_PASSWORD --database-host=127.0.0.1" + fi + + echo "Installing Nextcloud in the container" + docker exec $NEXTCLOUD_LOCAL_CONTAINER bash -c "cd nextcloud && php occ maintenance:install --admin-pass=admin $NEXTCLOUD_LOCAL_CONTAINER_INSTALL_DATABASE_OPTIONS" +} + +# Removes/stops temporal elements created/started by this script. +function cleanUp() { + # Disable (yes, "+" disables) exiting immediately on errors to ensure that + # all the cleanup commands are executed (well, no errors should occur during + # the cleanup anyway, but just in case). + set +o errexit + + echo "Cleaning up" + + if [ -f "$NEXTCLOUD_LOCAL_TAR" ]; then + echo "Removing $NEXTCLOUD_LOCAL_TAR" + rm $NEXTCLOUD_LOCAL_TAR + fi + + # The name filter must be specified as "^/XXX$" to get an exact match; using + # just "XXX" would match every name that contained "XXX". + if [ -n "$(docker ps --all --quiet --filter name="^/$NEXTCLOUD_LOCAL_CONTAINER$")" ]; then + echo "Removing Docker container $NEXTCLOUD_LOCAL_CONTAINER" + docker rm --volumes --force $NEXTCLOUD_LOCAL_CONTAINER + fi + + if [ -n "$DATABASE_CONTAINER" -a -n "$(docker ps --all --quiet --filter name="^/$DATABASE_CONTAINER$")" ]; then + echo "Removing Docker container $DATABASE_CONTAINER" + docker rm --volumes --force $DATABASE_CONTAINER + fi +} + +# Exit immediately on errors. +set -o errexit + +# Execute cleanUp when the script exits, either normally or due to an error. +trap cleanUp EXIT + +# Ensure working directory is script directory, as some actions (like copying +# the Git working directory to the container) expect that. +cd "$(dirname $0)" + +# "--image XXX" option can be provided to set the Docker image to use to run +# the integration tests (one of the "nextcloudci/phpX.Y:phpX.Y-Z" images). +NEXTCLOUD_LOCAL_IMAGE="nextcloudci/php7.1:php7.1-15" +if [ "$1" = "--image" ]; then + NEXTCLOUD_LOCAL_IMAGE=$2 + + shift 2 +fi + +# "--database XXX" option can be provided to set the database to use to run the +# integration tests (one of "sqlite", "mysql" or "pgsql"; "sqlite" is used +# by default). +DATABASE="sqlite" +if [ "$1" = "--database" ]; then + DATABASE=$2 + + shift 2 +fi + +if [ "$DATABASE" != "sqlite" ] && [ "$DATABASE" != "mysql" ] && [ "$DATABASE" != "pgsql" ]; then + echo "--database must be followed by one of: sqlite, mysql or pgsql" + + exit 1 +fi + +# "--database-image XXX" option can be provided to set the Docker image to use +# for the database container (ignored when using "sqlite"). +if [ "$DATABASE" = "mysql" ]; then + DATABASE_IMAGE="mysql:5.7" +elif [ "$DATABASE" = "pgsql" ]; then + DATABASE_IMAGE="postgres:10" +fi +if [ "$1" = "--database-image" ]; then + DATABASE_IMAGE=$2 + + shift 2 +fi + +# If no parameter is provided to this script all the integration tests are run. +SCENARIO_TO_RUN=$1 + +setOperatingSystemAbstractionVariables + +prepareDatabase +prepareDocker + +echo "Running tests" +# --tty is needed to get colourful output. +docker exec --tty $NEXTCLOUD_LOCAL_CONTAINER bash -c "cd nextcloud/build/integration && ./run.sh $SCENARIO_TO_RUN" diff --git a/build/integration/features/sharing-v1-part2.feature b/build/integration/sharing_features/sharing-v1-part2.feature index 9fbb4cda947..3316f3d94ba 100644 --- a/build/integration/features/sharing-v1-part2.feature +++ b/build/integration/sharing_features/sharing-v1-part2.feature @@ -321,6 +321,36 @@ Feature: sharing 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 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.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 @@ -409,6 +439,27 @@ Feature: sharing 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 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 "401" + Scenario: Keep usergroup shares (#22143) Given As an "admin" And user "user0" exists @@ -455,6 +506,7 @@ Feature: sharing When Updating last share with | permissions | 1 | 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 @@ -476,6 +528,7 @@ Feature: sharing 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 @@ -498,6 +551,7 @@ Feature: sharing 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 diff --git a/build/integration/features/sharing-v1-part3.feature b/build/integration/sharing_features/sharing-v1-part3.feature index 7c2e66f281b..4a02e89a671 100644 --- a/build/integration/features/sharing-v1-part3.feature +++ b/build/integration/sharing_features/sharing-v1-part3.feature @@ -127,6 +127,30 @@ Feature: sharing Then the OCS status code should be "997" And the HTTP status code should be "401" + Scenario: Deleting a group share as its owner + Given As an "admin" + And user "user0" exists + And user "user1" exists + And group "group1" exists + And user "user0" belongs to group "group1" + And user "user1" belongs to group "group1" + And As an "user0" + And creating a share with + | path | welcome.txt | + | shareType | 1 | + | shareWith | group1 | + When As an "user0" + And Deleting last share + Then the OCS status code should be "100" + And the HTTP status code should be "200" + And Getting info of last share + And the OCS status code should be "404" + And the HTTP status code should be "200" + And As an "user1" + And Getting info of last share + And the OCS status code should be "404" + And the HTTP status code should be "200" + Scenario: Deleting a group share as user Given As an "admin" And user "user0" exists @@ -337,6 +361,46 @@ Feature: sharing Then etag of element "/" of user "user1" has changed And etag of element "/PARENT" of user "user0" has not changed + Scenario: do not allow to increase permissions on received share + Given As an "admin" + And user "user0" exists + And user "user1" exists + And user "user0" created a folder "/TMP" + And As an "user0" + And creating a share with + | path | TMP | + | shareType | 0 | + | shareWith | user1 | + | permissions | 17 | + When As an "user1" + And Updating last share with + | permissions | 19 | + Then the OCS status code should be "403" + And the HTTP status code should be "401" + + Scenario: do not allow to increase permissions on non received share with user with resharing rights + Given As an "admin" + And 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 | 31 | + And creating a share with + | path | TMP | + | shareType | 0 | + | shareWith | user2 | + | permissions | 17 | + When As an "user1" + And Updating last share with + | permissions | 19 | + Then the OCS status code should be "403" + And the HTTP status code should be "401" + Scenario: do not allow to increase link share permissions on reshare Given As an "admin" And user "user0" exists diff --git a/build/integration/features/sharing-v1.feature b/build/integration/sharing_features/sharing-v1.feature index dd5cc9fff4f..81c96b8be5c 100644 --- a/build/integration/features/sharing-v1.feature +++ b/build/integration/sharing_features/sharing-v1.feature @@ -118,6 +118,7 @@ Feature: sharing And Updating last share with | expireDate | +3 days | And the OCS status code should be "100" + And the HTTP status code should be "200" And Getting info of last share Then the OCS status code should be "100" And the HTTP status code should be "200" @@ -150,6 +151,7 @@ Feature: sharing And Updating last share with | password | publicpw | And the OCS status code should be "100" + And the HTTP status code should be "200" And Getting info of last share Then the OCS status code should be "100" And the HTTP status code should be "200" @@ -181,6 +183,7 @@ Feature: sharing And Updating last share with | permissions | 7 | And the OCS status code should be "100" + And the HTTP status code should be "200" And Getting info of last share Then the OCS status code should be "100" And the HTTP status code should be "200" @@ -212,6 +215,7 @@ Feature: sharing And Updating last share with | permissions | 4 | And the OCS status code should be "100" + And the HTTP status code should be "200" And Getting info of last share Then the OCS status code should be "100" And the HTTP status code should be "200" @@ -243,6 +247,7 @@ Feature: sharing And Updating last share with | publicUpload | true | And the OCS status code should be "100" + And the HTTP status code should be "200" And Getting info of last share Then the OCS status code should be "100" And the HTTP status code should be "200" @@ -300,4 +305,19 @@ Feature: sharing And User "user2" should be included in the response And User "user3" should not be included in the response + Scenario: getting all shares of a file with a user with resharing rights + Given user "user0" exists + And user "user1" exists + And user "user2" exists + And user "user3" exists + And file "textfile0.txt" of user "user0" is shared with user "user1" + And file "textfile0.txt" of user "user0" is shared with user "user2" + And As an "user1" + When sending "GET" to "/apps/files_sharing/api/v1/shares?path=textfile0 (2).txt&reshares=true" + Then the OCS status code should be "100" + And the HTTP status code should be "200" + And User "user1" should be included in the response + And User "user2" should be included in the response + And User "user3" should not be included in the response + # See sharing-v1-part2.feature |