Skip to content

Commit

Permalink
Merge pull request #34665 from owncloud/corsAcceptanceTests
Browse files Browse the repository at this point in the history
test ocs endpoints with CORS headers
  • Loading branch information
individual-it authored Mar 6, 2019
2 parents 75e9d6f + f380b84 commit ec002f4
Show file tree
Hide file tree
Showing 5 changed files with 336 additions and 2 deletions.
5 changes: 3 additions & 2 deletions tests/TestHelpers/OcsApiHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,18 +38,19 @@ class OcsApiHelper {
* @param string $path
* @param array $body array of key, value pairs e.g ['value' => 'yes']
* @param int $ocsApiVersion (1|2) default 2
* @param array $headers
*
* @return ResponseInterface
*/
public static function sendRequest(
$baseUrl, $user, $password, $method, $path, $body = [], $ocsApiVersion = 2
$baseUrl, $user, $password, $method, $path, $body = [], $ocsApiVersion = 2, $headers = []
) {
$fullUrl = $baseUrl;
if (\substr($fullUrl, -1) !== '/') {
$fullUrl .= '/';
}
$fullUrl .= "ocs/v{$ocsApiVersion}.php" . $path;

return HttpRequestHelper::sendRequest($fullUrl, $method, $user, $password, [], $body);
return HttpRequestHelper::sendRequest($fullUrl, $method, $user, $password, $headers, $body);
}
}
1 change: 1 addition & 0 deletions tests/acceptance/config/behat.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ default:
- '%paths.base%/../features/apiAuth'
contexts:
- FeatureContext: *common_feature_context_params
- CorsContext:

apiCapabilities:
paths:
Expand Down
123 changes: 123 additions & 0 deletions tests/acceptance/features/apiAuth/cors.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
@api @TestAlsoOnExternalUserBackend
Feature: CORS headers
Background:
Given user "user0" has been created with default attributes
And a new client token for "user0" has been generated

Scenario Outline: CORS headers should be returned when setting CORS domain sending Origin header
Given using OCS API version "<ocs_api_version>"
And user "user0" has added "https://aphno.badal" to the list of personal CORS domains
When user "user0" sends HTTP method "GET" to OCS API endpoint "<endpoint>" with headers
| header | value |
| Origin | https://aphno.badal |
Then the OCS status code should be "<ocs-code>"
And the HTTP status code should be "<http-code>"
Then the following headers should be set
| Access-Control-Allow-Headers | OC-Checksum,OC-Total-Length,OCS-APIREQUEST,X-OC-Mtime,Accept,Authorization,Brief,Content-Length,Content-Range,Content-Type,Date,Depth,Destination,Host,If,If-Match,If-Modified-Since,If-None-Match,If-Range,If-Unmodified-Since,Location,Lock-Token,Overwrite,Prefer,Range,Schedule-Reply,Timeout,User-Agent,X-Expected-Entity-Length,Accept-Language,Access-Control-Request-Method,Access-Control-Allow-Origin,ETag,OC-Autorename,OC-CalDav-Import,OC-Chunked,OC-Etag,OC-FileId,OC-LazyOps,OC-Total-File-Length,Origin,X-Request-ID,X-Requested-With |
| Access-Control-Expose-Headers | Content-Location,DAV,ETag,Link,Lock-Token,OC-ETag,OC-Checksum,OC-FileId,OC-JobStatus-Location,Vary,Webdav-Location,X-Sabre-Status |
| Access-Control-Allow-Origin | https://aphno.badal |
| Access-Control-Allow-Methods | GET,OPTIONS,POST,PUT,DELETE,MKCOL,PROPFIND,PATCH,PROPPATCH,REPORT |
Examples:
| ocs_api_version |endpoint | ocs-code | http-code |
| 1 |/apps/files_external/api/v1/mounts | 100 | 200 |
| 2 |/apps/files_external/api/v1/mounts | 200 | 200 |
| 1 |/apps/files_sharing/api/v1/remote_shares | 100 | 200 |
| 2 |/apps/files_sharing/api/v1/remote_shares | 200 | 200 |
| 1 |/apps/files_sharing/api/v1/remote_shares/pending | 100 | 200 |
| 2 |/apps/files_sharing/api/v1/remote_shares/pending | 200 | 200 |
| 1 |/apps/files_sharing/api/v1/shares | 100 | 200 |
| 2 |/apps/files_sharing/api/v1/shares | 200 | 200 |
| 1 |/privatedata/getattribute | 100 | 200 |
| 2 |/privatedata/getattribute | 200 | 200 |

#merge into previous scenario when fixed
@issue-34664
Scenario Outline: CORS headers should be returned when setting CORS domain sending Origin header
Given using OCS API version "<ocs_api_version>"
And user "user0" has added "https://aphno.badal" to the list of personal CORS domains
When user "user0" sends HTTP method "GET" to OCS API endpoint "<endpoint>" with headers
| header | value |
| Origin | https://aphno.badal |
Then the OCS status code should be "<ocs-code>"
And the HTTP status code should be "<http-code>"
Then the following headers should not be set
| Access-Control-Allow-Headers |
| Access-Control-Expose-Headers |
| Access-Control-Allow-Origin |
| Access-Control-Allow-Methods |
Examples:
| ocs_api_version |endpoint | ocs-code | http-code |
| 1 |/config | 100 | 200 |
| 2 |/config | 200 | 200 |

Scenario Outline: CORS headers should be returned when setting CORS domain sending Origin header (admin only endpoints)
Given using OCS API version "<ocs_api_version>"
And the administrator has added "https://aphno.badal" to the list of personal CORS domains
When the administrator sends HTTP method "GET" to OCS API endpoint "<endpoint>" with headers
| header | value |
| Origin | https://aphno.badal |
Then the OCS status code should be "<ocs-code>"
And the HTTP status code should be "<http-code>"
Then the following headers should be set
| Access-Control-Allow-Headers | OC-Checksum,OC-Total-Length,OCS-APIREQUEST,X-OC-Mtime,Accept,Authorization,Brief,Content-Length,Content-Range,Content-Type,Date,Depth,Destination,Host,If,If-Match,If-Modified-Since,If-None-Match,If-Range,If-Unmodified-Since,Location,Lock-Token,Overwrite,Prefer,Range,Schedule-Reply,Timeout,User-Agent,X-Expected-Entity-Length,Accept-Language,Access-Control-Request-Method,Access-Control-Allow-Origin,ETag,OC-Autorename,OC-CalDav-Import,OC-Chunked,OC-Etag,OC-FileId,OC-LazyOps,OC-Total-File-Length,Origin,X-Request-ID,X-Requested-With |
| Access-Control-Expose-Headers | Content-Location,DAV,ETag,Link,Lock-Token,OC-ETag,OC-Checksum,OC-FileId,OC-JobStatus-Location,Vary,Webdav-Location,X-Sabre-Status |
| Access-Control-Allow-Origin | https://aphno.badal |
| Access-Control-Allow-Methods | GET,OPTIONS,POST,PUT,DELETE,MKCOL,PROPFIND,PATCH,PROPPATCH,REPORT |
Examples:
| ocs_api_version |endpoint | ocs-code | http-code |
| 1 |/cloud/apps | 100 | 200 |
| 2 |/cloud/apps | 200 | 200 |
| 1 |/cloud/groups | 100 | 200 |
| 2 |/cloud/groups | 200 | 200 |
| 1 |/cloud/users | 100 | 200 |
| 2 |/cloud/users | 200 | 200 |

Scenario Outline: no CORS headers should be returned when CORS domain does not match Origin header
Given using OCS API version "<ocs_api_version>"
And user "user0" has added "https://mero.badal" to the list of personal CORS domains
When user "user0" sends HTTP method "GET" to OCS API endpoint "<endpoint>" with headers
| header | value |
| Origin | https://aphno.badal |
Then the OCS status code should be "<ocs-code>"
And the HTTP status code should be "<http-code>"
Then the following headers should not be set
| Access-Control-Allow-Headers |
| Access-Control-Expose-Headers |
| Access-Control-Allow-Origin |
| Access-Control-Allow-Methods |
Examples:
| ocs_api_version |endpoint | ocs-code | http-code |
| 1 |/apps/files_external/api/v1/mounts | 100 | 200 |
| 2 |/apps/files_external/api/v1/mounts | 200 | 200 |
| 1 |/apps/files_sharing/api/v1/remote_shares | 100 | 200 |
| 2 |/apps/files_sharing/api/v1/remote_shares | 200 | 200 |
| 1 |/apps/files_sharing/api/v1/remote_shares/pending | 100 | 200 |
| 2 |/apps/files_sharing/api/v1/remote_shares/pending | 200 | 200 |
| 1 |/apps/files_sharing/api/v1/shares | 100 | 200 |
| 2 |/apps/files_sharing/api/v1/shares | 200 | 200 |
| 1 |/config | 100 | 200 |
| 2 |/config | 200 | 200 |
| 1 |/privatedata/getattribute | 100 | 200 |
| 2 |/privatedata/getattribute | 200 | 200 |

Scenario Outline: no CORS headers should be returned when CORS domain does not match Origin header (admin only endpoints)
Given using OCS API version "<ocs_api_version>"
And the administrator has added "https://mero.badal" to the list of personal CORS domains
When the administrator sends HTTP method "GET" to OCS API endpoint "<endpoint>" with headers
| header | value |
| Origin | https://aphno.badal |
Then the OCS status code should be "<ocs-code>"
And the HTTP status code should be "<http-code>"
Then the following headers should not be set
| Access-Control-Allow-Headers |
| Access-Control-Expose-Headers |
| Access-Control-Allow-Origin |
| Access-Control-Allow-Methods |
Examples:
| ocs_api_version |endpoint | ocs-code | http-code |
| 1 |/cloud/apps | 100 | 200 |
| 2 |/cloud/apps | 200 | 200 |
| 1 |/cloud/groups | 100 | 200 |
| 2 |/cloud/groups | 200 | 200 |
| 1 |/cloud/users | 100 | 200 |
| 2 |/cloud/users | 200 | 200 |
44 changes: 44 additions & 0 deletions tests/acceptance/features/bootstrap/BasicStructure.php
Original file line number Diff line number Diff line change
Expand Up @@ -801,6 +801,50 @@ public function userSendsToOcsApiEndpoint($user, $verb, $url, $password = null)
);
}

/**
* @When /^user "([^"]*)" sends HTTP method "([^"]*)" to OCS API endpoint "([^"]*)" with headers$/
*
* @param string $user
* @param string $verb
* @param string $url
* @param TableNode $headersTable
*
* @return void
*/
public function userSendsToOcsApiEndpointWithHeaders(
$user, $verb, $url, TableNode $headersTable
) {
$user = $this->getActualUsername($user);
$password = $this->getPasswordForUser($user);

$headers = [];
foreach ($headersTable as $row) {
$headers[$row['header']] = $row ['value'];
}

$this->response = OcsApiHelper::sendRequest(
$this->getBaseUrl(), $user, $password, $verb,
$url, [], $this->ocsApiVersion, $headers
);
}

/**
* @When /^the administrator sends HTTP method "([^"]*)" to OCS API endpoint "([^"]*)" with headers$/
*
* @param string $verb
* @param string $url
* @param TableNode $headersTable
*
* @return void
*/
public function administratorSendsToOcsApiEndpointWithHeaders(
$verb, $url, TableNode $headersTable
) {
$this->userSendsToOcsApiEndpointWithHeaders(
$this->getAdminUsername(), $verb, $url, $headersTable
);
}

/**
* @When the administrator sends HTTP method :verb to OCS API endpoint :url
* @When the administrator sends HTTP method :verb to OCS API endpoint :url using password :password
Expand Down
165 changes: 165 additions & 0 deletions tests/acceptance/features/bootstrap/CorsContext.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
<?php
/**
* ownCloud
*
* @author Artur Neumann <artur@jankaritech.com>
* @copyright Copyright (c) 2019, ownCloud GmbH
*
* This code 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 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\Hook\Scope\BeforeScenarioScope;
use Behat\Behat\Hook\Scope\AfterScenarioScope;

require_once 'bootstrap.php';
/**
* Steps that relate to CORS tests
*/
class CorsContext implements Context {
/**
*
* @var FeatureContext
*/
private $featureContext;

private $originalAdminCorsDomains = null;

/**
* @Given user :user has added :domain to the list of personal CORS domains
*
* @param string $user
* @param string $domain
*
* @return void
*/
public function addDomainToPrivateCORSLists($user, $domain) {
$this->featureContext->runOcc(
[
'user:setting',
$user,
'core',
'domains'
]
);
if ($this->featureContext->getExitStatusCodeOfOccCommand() === 0) {
$domainsJson = $this->featureContext->getStdOutOfOccCommand();
$domains = \json_decode($domainsJson);
} else {
$domainsJson = "";
$domains = [];
}
if ($user === $this->featureContext->getAdminUsername()
&& $this->originalAdminCorsDomains === null
) {
$this->originalAdminCorsDomains = $domainsJson;
}

$domains[] = $domain;
$valueString = \json_encode($domains);

$this->featureContext->runOcc(
[
'user:setting',
$user,
'core',
'domains',
'--value=\'' . $valueString . '\''
]
);
if ($this->featureContext->getExitStatusCodeOfOccCommand() !== 0) {
throw new \Exception(
"could not set CORS domain. " .
$this->featureContext->getStdErrOfOccCommand()
);
}
//double check if it was set
$this->featureContext->runOcc(
[
'user:setting',
$user,
'core',
'domains'
]
);
$domains = \json_decode($this->featureContext->getStdOutOfOccCommand());
PHPUnit_Framework_Assert::assertContains(
$domain, $domains, "CORS domain was not added correctly"
);
}

/**
* @Given the administrator has added :domain to the list of personal CORS domains
*
* @param string $domain
*
* @return void
*/
public function adminAddDomainToPrivateCORSLists($domain) {
$this->addDomainToPrivateCORSLists(
$this->featureContext->getAdminUsername(), $domain
);
}

/**
* This will run before EVERY scenario.
* It will set the properties for this object.
*
* @BeforeScenario
*
* @param BeforeScenarioScope $scope
*
* @return void
*/
public function before(BeforeScenarioScope $scope) {
// Get the environment
$environment = $scope->getEnvironment();
// Get all the contexts you need in this context
$this->featureContext = $environment->getContext('FeatureContext');
}

/**
* @AfterScenario
*
* @param AfterScenarioScope $scope
*
* @return void
*/
public function resetAdminCors(AfterScenarioScope $scope) {
if ($this->originalAdminCorsDomains !== null) {
if ($this->originalAdminCorsDomains !== "") {
$this->featureContext->runOcc(
[
'user:setting',
$this->featureContext->getAdminUsername(),
'core',
'domains',
'--value=\'' . $this->originalAdminCorsDomains . '\''
]
);
} else {
$this->featureContext->runOcc(
[
'user:setting',
$this->featureContext->getAdminUsername(),
'core',
'domains',
'--delete'
]
);
}
}
}
}

0 comments on commit ec002f4

Please sign in to comment.