diff --git a/.drone.starlark b/.drone.starlark index d6dc5ce1af3c..71cd2184865d 100644 --- a/.drone.starlark +++ b/.drone.starlark @@ -79,6 +79,7 @@ config = { 'suites': [ 'apiAuth', 'apiAuthOcs', + 'apiAuthWebDav', 'apiCapabilities', 'apiComments', 'apiFavorites', diff --git a/.drone.yml b/.drone.yml index 05407b226575..9e67ac491a1b 100644 --- a/.drone.yml +++ b/.drone.yml @@ -3912,6 +3912,152 @@ depends_on: - phan-php7.2 - phan-php7.3 +--- +kind: pipeline +type: docker +name: apiAuthWebDav-mariadb10.2-php7.1 + +platform: + os: linux + arch: amd64 + +workspace: + base: /drone + path: src + +steps: +- name: cache-restore + pull: always + image: plugins/s3-cache:1 + settings: + access_key: + from_secret: cache_s3_access_key + endpoint: + from_secret: cache_s3_endpoint + restore: true + secret_key: + from_secret: cache_s3_secret_key + when: + instance: + - drone.owncloud.services + - drone.owncloud.com + +- name: composer-install + pull: always + image: owncloudci/php:7.1 + commands: + - make install-composer-deps + environment: + COMPOSER_HOME: /drone/src/.cache/composer + +- name: vendorbin-install + pull: always + image: owncloudci/php:7.1 + commands: + - make vendor-bin-deps + environment: + COMPOSER_HOME: /drone/src/.cache/composer + +- name: yarn-install + pull: always + image: owncloudci/php:7.1 + commands: + - make install-nodejs-deps + environment: + NPM_CONFIG_CACHE: /drone/src/.cache/npm + YARN_CACHE_FOLDER: /drone/src/.cache/yarn + bower_storage__packages: /drone/src/.cache/bower + +- name: install-server + pull: always + image: owncloudci/php:7.1 + commands: + - bash tests/drone/install-server.sh + - php occ a:l + - php occ config:system:set trusted_domains 1 --value=server + - php occ log:manage --level 2 + - php occ config:list + - php occ security:certificates:import /drone/server.crt + - php occ security:certificates + environment: + DB_TYPE: mariadb + +- name: install-extra-apps + pull: always + image: owncloudci/php:7.1 + commands: + - git clone https://github.com/owncloud/testing.git /drone/src/apps/testing + - cd /drone/src/apps/testing + - composer install + - cd /drone/src + - php occ a:l + - php occ a:e testing + - php occ a:l + +- name: fix-permissions + pull: always + image: owncloudci/php:7.1 + commands: + - chown -R www-data /drone/src + +- name: owncloud-log-server + pull: always + image: owncloud/ubuntu:18.04 + detach: true + commands: + - tail -f /drone/src/data/owncloud.log + +- name: acceptance-tests + pull: always + image: owncloudci/php:7.1 + commands: + - touch /drone/saved-settings.sh + - . /drone/saved-settings.sh + - make test-acceptance-api + environment: + BEHAT_SUITE: apiAuthWebDav + TESTING_REMOTE_SYSTEM: true + TEST_SERVER_URL: https://server + +services: +- name: mariadb + pull: always + image: mariadb:10.2 + environment: + MYSQL_DATABASE: owncloud + MYSQL_PASSWORD: owncloud + MYSQL_ROOT_PASSWORD: owncloud + MYSQL_USER: owncloud + +- name: server + pull: always + image: owncloudci/php:7.1 + command: + - /usr/local/bin/apachectl + - -e + - debug + - -D + - FOREGROUND + environment: + APACHE_CONFIG_TEMPLATE: ssl + APACHE_SSL_CERT: /drone/server.crt + APACHE_SSL_CERT_CN: server + APACHE_SSL_KEY: /drone/server.key + APACHE_WEBROOT: /drone/src + +trigger: + ref: + - refs/pull/** + - refs/tags/** + - refs/heads/master + +depends_on: +- coding-standard-php7.3 +- phpstan-php7.1 +- phan-php7.1 +- phan-php7.2 +- phan-php7.3 + --- kind: pipeline type: docker @@ -14553,6 +14699,7 @@ depends_on: - phpunit-php7.1-sqlite-scality - apiAuth-mariadb10.2-php7.1 - apiAuthOcs-mariadb10.2-php7.1 +- apiAuthWebDav-mariadb10.2-php7.1 - apiCapabilities-mariadb10.2-php7.1 - apiComments-mariadb10.2-php7.1 - apiFavorites-mariadb10.2-php7.1 diff --git a/tests/acceptance/config/behat.yml b/tests/acceptance/config/behat.yml index 48f3393277a4..f81284777158 100644 --- a/tests/acceptance/config/behat.yml +++ b/tests/acceptance/config/behat.yml @@ -33,6 +33,17 @@ default: contexts: - FeatureContext: *common_feature_context_params + apiAuthWebDav: + paths: + - '%paths.base%/../features/apiAuthWebDav' + contexts: + - FeatureContext: *common_feature_context_params + - LoggingContext: + - OccContext: + - SearchContext: + - PublicWebDavContext: + - WebDavPropertiesContext: + apiCapabilities: paths: - '%paths.base%/../features/apiCapabilities' diff --git a/tests/acceptance/features/apiAuthWebDav/webDavDELETEAuth.feature b/tests/acceptance/features/apiAuthWebDav/webDavDELETEAuth.feature new file mode 100644 index 000000000000..1ae66105ad89 --- /dev/null +++ b/tests/acceptance/features/apiAuthWebDav/webDavDELETEAuth.feature @@ -0,0 +1,40 @@ +@api @TestAlsoOnExternalUserBackend +Feature: delete file/folder + + Background: + Given user "user0" has been created with default attributes and skeleton files + And user "user1" has been created with default attributes and without skeleton files + + Scenario: send DELETE requests to webDav endpoints as normal user with wrong password + When user "user0" requests these endpoints with "DELETE" including body using password "invalid" then the status codes should be as listed + | endpoint | http-code | body | + | /remote.php/webdav/textfile0.txt | 401 | doesnotmatter | + | /remote.php/dav/files/user0/textfile0.txt | 401 | doesnotmatter | + | /remote.php/webdav/PARENT | 401 | doesnotmatter | + | /remote.php/dav/files/user0/PARENT | 401 | doesnotmatter | + | /remote.php/dav/files/user0/PARENT/parent.txt | 401 | doesnotmatter | + + Scenario: send DELETE requests to webDav endpoints as normal user with no password + When user "user0" requests these endpoints with "DELETE" including body using password "" then the status codes should be as listed + | endpoint | http-code | body | + | /remote.php/webdav/textfile0.txt | 401 | doesnotmatter | + | /remote.php/dav/files/user0/textfile0.txt | 401 | doesnotmatter | + | /remote.php/webdav/PARENT | 401 | doesnotmatter | + | /remote.php/dav/files/user0/PARENT | 401 | doesnotmatter | + | /remote.php/dav/files/user0/PARENT/parent.txt | 401 | doesnotmatter | + + Scenario: send DELETE requests to another user's webDav endpoints as normal user + When user "user1" requests these endpoints with "DELETE" including body then the status codes should be as listed + | endpoint | http-code | body | + | /remote.php/dav/files/user0/textfile0.txt | 404 | doesnotmatter | + | /remote.php/dav/files/user0/PARENT | 404 | doesnotmatter | + | /remote.php/dav/files/user0/PARENT/parent.txt | 404 | doesnotmatter | + + Scenario: send DELETE requests to webDav endpoints using invalid username but correct password + When user "usero" requests these endpoints with "DELETE" including body using the password of user "user0" then the status codes should be as listed + | endpoint | http-code | body | + | /remote.php/webdav/textfile0.txt | 401 | doesnotmatter | + | /remote.php/dav/files/user0/textfile0.txt | 401 | doesnotmatter | + | /remote.php/webdav/PARENT | 401 | doesnotmatter | + | /remote.php/dav/files/user0/PARENT | 401 | doesnotmatter | + | /remote.php/dav/files/user0/PARENT/parent.txt | 401 | doesnotmatter | diff --git a/tests/acceptance/features/apiAuthWebDav/webDavMOVEAuth.feature b/tests/acceptance/features/apiAuthWebDav/webDavMOVEAuth.feature new file mode 100644 index 000000000000..432543608812 --- /dev/null +++ b/tests/acceptance/features/apiAuthWebDav/webDavMOVEAuth.feature @@ -0,0 +1,40 @@ +@api @TestAlsoOnExternalUserBackend +Feature: MOVE file/folder + + Background: + Given user "user0" has been created with default attributes and skeleton files + And user "user1" has been created with default attributes and without skeleton files + + Scenario: send MOVE requests to webDav endpoints as normal user with wrong password + When user "user0" requests these endpoints with "MOVE" including body using password "invalid" then the status codes should be as listed + | endpoint | http-code | body | + | /remote.php/webdav/textfile0.txt | 401 | doesnotmatter | + | /remote.php/dav/files/user0/textfile0.txt | 401 | doesnotmatter | + | /remote.php/webdav/PARENT | 401 | doesnotmatter | + | /remote.php/dav/files/user0/PARENT | 401 | doesnotmatter | + | /remote.php/dav/files/user0/PARENT/parent.txt | 401 | doesnotmatter | + + Scenario: send MOVE requests to webDav endpoints as normal user with no password + When user "user0" requests these endpoints with "MOVE" including body using password "" then the status codes should be as listed + | endpoint | http-code | body | + | /remote.php/webdav/textfile0.txt | 401 | doesnotmatter | + | /remote.php/dav/files/user0/textfile0.txt | 401 | doesnotmatter | + | /remote.php/webdav/PARENT | 401 | doesnotmatter | + | /remote.php/dav/files/user0/PARENT | 401 | doesnotmatter | + | /remote.php/dav/files/user0/PARENT/parent.txt | 401 | doesnotmatter | + + Scenario: send MOVE requests to another user's webDav endpoints as normal user + When user "user1" requests these endpoints with "MOVE" including body then the status codes should be as listed + | endpoint | http-code | body | + | /remote.php/dav/files/user0/textfile0.txt | 403 | doesnotmatter | + | /remote.php/dav/files/user0/PARENT | 403 | doesnotmatter | + | /remote.php/dav/files/user0/PARENT/parent.txt | 403 | doesnotmatter | + + Scenario: send MOVE requests to webDav endpoints using invalid username but correct password + When user "usero" requests these endpoints with "MOVE" including body using the password of user "user0" then the status codes should be as listed + | endpoint | http-code | body | + | /remote.php/webdav/textfile0.txt | 401 | doesnotmatter | + | /remote.php/dav/files/user0/textfile0.txt | 401 | doesnotmatter | + | /remote.php/webdav/PARENT | 401 | doesnotmatter | + | /remote.php/dav/files/user0/PARENT | 401 | doesnotmatter | + | /remote.php/dav/files/user0/PARENT/parent.txt | 401 | doesnotmatter | diff --git a/tests/acceptance/features/bootstrap/Auth.php b/tests/acceptance/features/bootstrap/Auth.php index 62cac614a407..5fa48e0ccb9e 100644 --- a/tests/acceptance/features/bootstrap/Auth.php +++ b/tests/acceptance/features/bootstrap/Auth.php @@ -118,10 +118,12 @@ public function userHasRequestedURLWith($url, $method) { * @return void */ public function verifyStatusCode($ocsCode, $httpCode, $endPoint) { - $this->ocsContext->theOCSStatusCodeShouldBe( - $ocsCode, - $message = "Got unexpected OCS code while sending request to endpoint " . $endPoint - ); + if ($ocsCode !== null) { + $this->ocsContext->theOCSStatusCodeShouldBe( + $ocsCode, + $message = "Got unexpected OCS code while sending request to endpoint " . $endPoint + ); + } $this->theHTTPStatusCodeShouldBe( $httpCode, $message = "Got unexpected HTTP code while sending request to endpoint " . $endPoint @@ -374,7 +376,7 @@ public function userRequestsURLWithUsingBasicAuth($user, $url, $method, $passwor if ($password === null) { $authString = "$user:" . $this->getPasswordForUser($user); } else { - $authString = $password; + $authString = $user . ":" . $password; } $this->sendRequest( $url, $method, 'basic ' . \base64_encode($authString), false, $body diff --git a/tests/acceptance/features/bootstrap/OCSContext.php b/tests/acceptance/features/bootstrap/OCSContext.php index 587f09249763..b5dec3585727 100644 --- a/tests/acceptance/features/bootstrap/OCSContext.php +++ b/tests/acceptance/features/bootstrap/OCSContext.php @@ -101,7 +101,7 @@ public function userSendsHTTPMethodToOcsApiEndpointWithBody( if ($body instanceof TableNode) { $bodyArray = $body->getRowsHash(); } - + if ($user !== 'UNAUTHORIZED_USER') { $user = $this->featureContext->getActualUsername($user); if ($password === null) { @@ -111,7 +111,7 @@ public function userSendsHTTPMethodToOcsApiEndpointWithBody( $user = null; $password = null; } - + $response = OcsApiHelper::sendRequest( $this->featureContext->getBaseUrl(), $user, $password, $verb, $url, $bodyArray, $this->featureContext->getOcsApiVersion() @@ -192,7 +192,7 @@ public function userSendsToOcsApiEndpointWithHeadersAndPassword( foreach ($headersTable as $row) { $headers[$row['header']] = $row ['value']; } - + $response = OcsApiHelper::sendRequest( $this->featureContext->getBaseUrl(), $user, $password, $verb, $url, [], $this->featureContext->getOcsApiVersion(), $headers @@ -336,7 +336,64 @@ public function userSendsRequestToTheseEndpointsWithBodyUsingPassword($user, $me $password, $row['body'] ); - $this->featureContext->verifyStatusCode($row['ocs-code'], $row['http-code'], $row['endpoint']); + $ocsCode = null; + if (\array_key_exists('ocs-code', $row)) { + $ocsCode = $row['ocs-code']; + } + $this->featureContext->verifyStatusCode($ocsCode, $row['http-code'], $row['endpoint']); + } + } + + /** + * @When user :user requests these endpoints with :method including body then the status codes should be as listed + * + * @param string $user + * @param string $method + * @param TableNode $table + * + * @return void + */ + public function userSendsRequestToTheseEndpointsWithBody($user, $method, TableNode $table) { + foreach ($table->getHash() as $row) { + $this->featureContext->userRequestsURLWithUsingBasicAuth( + $user, + $row['endpoint'], + $method, + $this->featureContext->getPasswordForUser($user), + $row['body'] + ); + $ocsCode = null; + if (\array_key_exists('ocs-code', $row)) { + $ocsCode = $row['ocs-code']; + } + $this->featureContext->verifyStatusCode($ocsCode, $row['http-code'], $row['endpoint']); + } + } + + /** + * @When user :asUser requests these endpoints with :method including body using the password of user :user then the status codes should be as listed + * + * @param string $asUser + * @param string $method + * @param string $user + * @param TableNode $table + * + * @return void + */ + public function userRequestsTheseEndpointsWithUsingThePasswordOfUser($asUser, $method, $user, TableNode $table) { + foreach ($table->getHash() as $row) { + $this->featureContext->userRequestsURLWithUsingBasicAuth( + $asUser, + $row['endpoint'], + $method, + $this->featureContext->getPasswordForUser($user), + $row['body'] + ); + $ocsCode = null; + if (\array_key_exists('ocs-code', $row)) { + $ocsCode = $row['ocs-code']; + } + $this->featureContext->verifyStatusCode($ocsCode, $row['http-code'], $row['endpoint']); } } @@ -352,7 +409,7 @@ public function theOCSStatusCodeShouldBe($statusCode, $message = "") { if ($message === "") { $message = "OCS status code is not the expected value"; } - + $responseStatusCode = $this->getOCSResponseStatusCode( $this->featureContext->getResponse() );