Merge branch 'master' into try-gookikt-config

This commit is contained in:
A.Unger
2021-11-15 19:38:05 +01:00
13 changed files with 229 additions and 27 deletions

View File

@@ -1,5 +1,5 @@
# The test runner source for API tests
CORE_COMMITID=2eead619a0e1bab2ca21bc7bbc4ef77f9d82c42d
CORE_COMMITID=4e808c1a89462fb91d2439dc3d9c490ebced3139
CORE_BRANCH=master
# The test runner source for UI tests

View File

@@ -8,6 +8,7 @@ The following sections list the changes for unreleased.
* Bugfix - Don't allow empty password: [#197](https://github.com/owncloud/product/issues/197)
* Bugfix - Fix basic auth config: [#2719](https://github.com/owncloud/ocis/pull/2719)
* Bugfix - Fix basic auth with custom user claim: [#2755](https://github.com/owncloud/ocis/pull/2755)
* Bugfix - Fix oCIS startup ony systems with IPv6: [#2698](https://github.com/owncloud/ocis/pull/2698)
* Bugfix - Fix opening images in media viewer for some usernames: [#2738](https://github.com/owncloud/ocis/pull/2738)
* Bugfix - Fix error logging when there is no thumbnail for a file: [#2702](https://github.com/owncloud/ocis/pull/2702)
@@ -32,6 +33,14 @@ The following sections list the changes for unreleased.
https://github.com/owncloud/ocis/issues/2466
https://github.com/owncloud/ocis/pull/2719
* Bugfix - Fix basic auth with custom user claim: [#2755](https://github.com/owncloud/ocis/pull/2755)
We've fixed authentication with basic if oCIS is configured to use a non-standard claim as user
claim (`PROXY_USER_OIDC_CLAIM`). Prior to this bugfix the authentication always failed and
is now working.
https://github.com/owncloud/ocis/pull/2755
* Bugfix - Fix oCIS startup ony systems with IPv6: [#2698](https://github.com/owncloud/ocis/pull/2698)
We've fixed failing startup of oCIS on systems with IPv6 addresses.

View File

@@ -0,0 +1,7 @@
Bugfix: Fix basic auth with custom user claim
We've fixed authentication with basic if oCIS is configured to use a non-standard claim
as user claim (`PROXY_USER_OIDC_CLAIM`). Prior to this bugfix the authentication always
failed and is now working.
https://github.com/owncloud/ocis/pull/2755

View File

@@ -5,7 +5,7 @@ ARG REVISION=""
RUN apk update && \
apk upgrade && \
apk add ca-certificates mailcap && \
apk add ca-certificates mailcap tree attr && \
rm -rf /var/cache/apk/* && \
echo 'hosts: files dns' >| /etc/nsswitch.conf

View File

@@ -5,7 +5,7 @@ ARG REVISION=""
RUN apk update && \
apk upgrade && \
apk add ca-certificates mailcap && \
apk add ca-certificates mailcap tree attr && \
rm -rf /var/cache/apk/* && \
echo 'hosts: files dns' >| /etc/nsswitch.conf

View File

@@ -5,7 +5,7 @@ ARG REVISION=""
RUN apk update && \
apk upgrade && \
apk add ca-certificates mailcap && \
apk add ca-certificates mailcap tree attr && \
rm -rf /var/cache/apk/* && \
echo 'hosts: files dns' >| /etc/nsswitch.conf

View File

@@ -216,6 +216,8 @@ func loadMiddlewares(ctx context.Context, logger log.Logger, cfg *config.Config)
middleware.EnableBasicAuth(cfg.EnableBasicAuth),
middleware.UserProvider(userProvider),
middleware.OIDCIss(cfg.OIDC.Issuer),
middleware.UserOIDCClaim(cfg.UserOIDCClaim),
middleware.UserCS3Claim(cfg.UserCS3Claim),
middleware.CredentialsByUserAgent(cfg.Reva.Middleware.Auth.CredentialsByUserAgent),
),
middleware.SignedURLAuth(

View File

@@ -126,6 +126,8 @@ func newBasicAuth(options Options) func(http.Handler) http.Handler {
EnableBasicAuth(options.EnableBasicAuth),
AccountsClient(options.AccountsClient),
OIDCIss(options.OIDCIss),
UserOIDCClaim(options.UserOIDCClaim),
UserCS3Claim(options.UserCS3Claim),
CredentialsByUserAgent(options.CredentialsByUserAgent),
)
}

View File

@@ -84,10 +84,17 @@ func BasicAuth(optionSetters ...Option) func(next http.Handler) http.Handler {
// fake oidc claims
claims := map[string]interface{}{
oidc.OwncloudUUID: user.Id.OpaqueId,
oidc.Iss: user.Id.Idp,
oidc.PreferredUsername: user.Username,
oidc.Email: user.Mail,
oidc.OwncloudUUID: user.Id.OpaqueId,
}
if options.UserCS3Claim == "userid" {
// set the custom user claim only if users will be looked up by the userid on the CS3api
// OpaqueId contains the userid configured in STORAGE_LDAP_USER_SCHEMA_UID
claims[options.UserOIDCClaim] = user.Id.OpaqueId
}
next.ServeHTTP(w, req.WithContext(oidc.NewContext(req.Context(), claims)))

View File

@@ -3,3 +3,6 @@
#### [downloading the /Shares folder using the archiver endpoint does not work](https://github.com/owncloud/ocis/issues/2751)
- [apiArchiver/downloadById.feature:134](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiArchiver/downloadById.feature#L134)
- [apiArchiver/downloadById.feature:135](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiArchiver/downloadById.feature#L135)
#### [downloading an archive with invalid path returns HTTP/500](https://github.com/owncloud/ocis/issues/2768)
- [apiArchiver/downloadByPath.feature:69](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiArchiver/apiArchiver/downloadByPath.feature#L69)

View File

@@ -124,11 +124,11 @@ Feature: download multiple resources bundled into an archive
| User-Agent | <user-agent> |
Then the HTTP status code should be "200"
And the downloaded <archive-type> archive should contain these files:
| name | content |
| Shares/textfile0.txt | some data |
| Shares/textfile1.txt | other data |
| Shares/my_data/textfile0.txt | some data |
| Shares/my_data/an_other_file.txt | more data |
| name | content |
| Shares/textfile0.txt | some data |
| Shares/textfile1.txt | other data |
| Shares/my_data/textfile2.txt | some data |
| Shares/more_data/an_other_file.txt | more data |
Examples:
| user-agent | archive-type |
| Linux | tar |

View File

@@ -0,0 +1,133 @@
@api @skipOnOcV10
Feature: download multiple resources bundled into an archive
As a user
I want to be able to download multiple items at once
So that I don't have to execute repetitive tasks
As a developer
I want to be able to use the full path of the resource to download multiple items at once
So that I don't have to know the ID of the resource
Background:
Given user "Alice" has been created with default attributes and without skeleton files
Scenario Outline: download a single file
Given user "Alice" has uploaded file with content "some data" to "/textfile0.txt"
When user "Alice" downloads the archive of "/home/textfile0.txt" using the resource path and setting these headers
| header | value |
| User-Agent | <user-agent> |
Then the HTTP status code should be "200"
And the downloaded <archive-type> archive should contain these files:
| name | content |
| textfile0.txt | some data |
Examples:
| user-agent | archive-type |
| Linux | tar |
| Windows NT | zip |
Scenario Outline: download a single folder
Given user "Alice" has created folder "my_data"
And user "Alice" has uploaded file with content "some data" to "/my_data/textfile0.txt"
And user "Alice" has uploaded file with content "more data" to "/my_data/an_other_file.txt"
When user "Alice" downloads the archive of "/home/my_data" using the resource path and setting these headers
| header | value |
| User-Agent | <user-agent> |
Then the HTTP status code should be "200"
And the downloaded <archive-type> archive should contain these files:
| name | content |
| my_data/textfile0.txt | some data |
| my_data/an_other_file.txt | more data |
Examples:
| user-agent | archive-type |
| Linux | tar |
| Windows NT | zip |
Scenario: download multiple files and folders
Given user "Alice" has uploaded file with content "some data" to "/textfile0.txt"
And user "Alice" has uploaded file with content "other data" to "/textfile1.txt"
And user "Alice" has created folder "my_data"
And user "Alice" has uploaded file with content "some data" to "/my_data/textfile2.txt"
And user "Alice" has created folder "more_data"
And user "Alice" has uploaded file with content "more data" to "/more_data/an_other_file.txt"
When user "Alice" downloads the archive of these items using the resource paths
| /home/textfile0.txt |
| /home/textfile1.txt |
| /home/my_data |
| /home/more_data |
Then the HTTP status code should be "200"
And the downloaded tar archive should contain these files:
| name | content |
| textfile0.txt | some data |
| textfile1.txt | other data |
| my_data/textfile2.txt | some data |
| more_data/an_other_file.txt | more data |
Scenario: download a not existing single file
When user "Alice" downloads the archive of "/doesnotexist.txt" of user "Alice" using the resource path
Then the HTTP status code should be "400"
Scenario: download multiple shared items as share receiver
Given user "Brian" has been created with default attributes and without skeleton files
And user "Alice" has uploaded file with content "some data" to "/textfile0.txt"
And user "Alice" has uploaded file with content "other data" to "/textfile1.txt"
And user "Alice" has created folder "my_data"
And user "Alice" has uploaded file with content "some data" to "/my_data/textfile2.txt"
And user "Alice" has created folder "more_data"
And user "Alice" has uploaded file with content "more data" to "/more_data/an_other_file.txt"
And user "Alice" has shared file "textfile0.txt" with user "Brian"
And user "Alice" has shared file "textfile1.txt" with user "Brian"
And user "Alice" has shared folder "my_data" with user "Brian"
And user "Alice" has shared folder "more_data" with user "Brian"
And user "Brian" has accepted share "/textfile0.txt" offered by user "Alice"
And user "Brian" has accepted share "/textfile1.txt" offered by user "Alice"
And user "Brian" has accepted share "/my_data" offered by user "Alice"
And user "Brian" has accepted share "/more_data" offered by user "Alice"
When user "Brian" downloads the archive of these items using the resource path
| /home/Shares/textfile0.txt |
| /home/Shares/textfile1.txt |
| /home/Shares/my_data |
| /home/Shares/more_data |
Then the HTTP status code should be "200"
And the downloaded tar archive should contain these files:
| name | content |
| textfile0.txt | some data |
| textfile1.txt | other data |
| my_data/textfile2.txt | some data |
| more_data/an_other_file.txt | more data |
Scenario Outline: download the Shares folder as share receiver
Given user "Brian" has been created with default attributes and without skeleton files
And user "Alice" has uploaded file with content "some data" to "/textfile0.txt"
And user "Alice" has uploaded file with content "other data" to "/textfile1.txt"
And user "Alice" has created folder "my_data"
And user "Alice" has uploaded file with content "some data" to "/my_data/textfile2.txt"
And user "Alice" has created folder "more_data"
And user "Alice" has uploaded file with content "more data" to "/more_data/an_other_file.txt"
And user "Alice" has shared file "textfile0.txt" with user "Brian"
And user "Alice" has shared file "textfile1.txt" with user "Brian"
And user "Alice" has shared folder "my_data" with user "Brian"
And user "Alice" has shared folder "more_data" with user "Brian"
And user "Brian" has accepted share "/textfile0.txt" offered by user "Alice"
And user "Brian" has accepted share "/textfile1.txt" offered by user "Alice"
And user "Brian" has accepted share "/my_data" offered by user "Alice"
And user "Brian" has accepted share "/more_data" offered by user "Alice"
When user "Brian" downloads the archive of "/home/Shares" using the resource path and setting these headers
| header | value |
| User-Agent | <user-agent> |
Then the HTTP status code should be "200"
And the downloaded <archive-type> archive should contain these files:
| name | content |
| Shares/textfile0.txt | some data |
| Shares/textfile1.txt | other data |
| Shares/my_data/textfile2.txt | some data |
| Shares/more_data/an_other_file.txt | more data |
Examples:
| user-agent | archive-type |
| Linux | tar |
| Windows NT | zip |

View File

@@ -63,19 +63,52 @@ class ArchiverContext implements Context {
}
/**
* @When user :user downloads the archive of :resourceId using the resource id and setting these headers
* @param string $user
* @param string $resource
* @param string $addressType id|ids|path|paths
*
* @return string
*
* @throws Exception
*/
private function getArchiverQueryString(
string $user,
string $resource,
string $addressType
): string {
switch ($addressType) {
case 'id':
case 'ids':
return 'id=' . $this->featureContext->getFileIdForPath($user, $resource);
break;
case 'path':
case 'paths':
return 'path=' . $resource;
default:
throw new Exception(
'"' . $addressType .
'" is not a legal value for $addressType, must be id|ids|path|paths'
);
}
}
/**
* @When user :user downloads the archive of :resource using the resource :addressType and setting these headers
*
* @param string $user
* @param string $resource
* @param string $addressType id|path
* @param TableNode $headersTable
*
* @return void
*
* @throws \GuzzleHttp\Exception\GuzzleException
* @throws Exception
*/
public function userDownloadsTheArchiveOfUsingTheResourceId(
public function userDownloadsTheArchive(
string $user,
string $resource,
string $addressType,
TableNode $headersTable
): void {
$this->featureContext->verifyTableNodeColumns(
@@ -86,11 +119,12 @@ class ArchiverContext implements Context {
foreach ($headersTable as $row) {
$headers[$row['header']] = $row ['value'];
}
$resourceId = $this->featureContext->getFileIdForPath($user, $resource);
$user = $this->featureContext->getActualUsername($user);
$queryString = $this->getArchiverQueryString($user, $resource, $addressType);
$this->featureContext->setResponse(
HttpRequestHelper::get(
$this->featureContext->getBaseUrl() . '/archiver?id=' . $resourceId,
$this->featureContext->getBaseUrl() . '/archiver?' . $queryString,
'',
$user,
$this->featureContext->getPasswordForUser($user),
@@ -100,26 +134,29 @@ class ArchiverContext implements Context {
}
/**
* @When user :downloader downloads the archive of :item of user :owner using the resource id
* @When user :downloader downloads the archive of :item of user :owner using the resource :addressType
*
* @param string $downloader Who sends the request
* @param string $resource
* @param string $owner Who is the real owner of the file
* @param string $addressType id|path
*
* @return void
*
* @throws \GuzzleHttp\Exception\GuzzleException
* @throws Exception
*/
public function userDownloadsTheArchiveOfItemOfUserUsingTheResourceId(
public function userDownloadsTheArchiveOfItemOfUser(
string $downloader,
string $resource,
string $owner
string $owner,
string $addressType
): void {
$resourceId = $this->featureContext->getFileIdForPath($owner, $resource);
$downloader = $this->featureContext->getActualUsername($downloader);
$queryString = $this->getArchiverQueryString($owner, $resource, $addressType);
$this->featureContext->setResponse(
HttpRequestHelper::get(
$this->featureContext->getBaseUrl() . '/archiver?id=' . $resourceId,
$this->featureContext->getBaseUrl() . '/archiver?' . $queryString,
'',
$downloader,
$this->featureContext->getPasswordForUser($downloader),
@@ -128,29 +165,31 @@ class ArchiverContext implements Context {
}
/**
* @When user :arg1 downloads the archive of these items using the resource ids
* @When user :user downloads the archive of these items using the resource :addressType
*
* @param string $user
* @param TableNode $items
* @param string $addressType ids|paths
*
* @return void
*
* @throws \GuzzleHttp\Exception\GuzzleException
*/
public function userDownloadsTheArchiveOfTheseItemsUsingTheResourceIds(
public function userDownloadsTheArchiveOfTheseItems(
string $user,
TableNode $items
TableNode $items,
string $addressType
): void {
$user = $this->featureContext->getActualUsername($user);
$resourceIdsString = '';
$queryString = '';
foreach ($items->getRows() as $item) {
$fileId = $this->featureContext->getFileIdForPath($user, $item[0]);
$resourceIdsString .= 'id=' . $fileId . '&';
$queryString .= $this->getArchiverQueryString($user, $item[0], $addressType) . '&';
}
$resourceIdsString = \rtrim($resourceIdsString, '&');
$queryString = \rtrim($queryString, '&');
$this->featureContext->setResponse(
HttpRequestHelper::get(
$this->featureContext->getBaseUrl() . '/archiver?' . $resourceIdsString,
$this->featureContext->getBaseUrl() . '/archiver?' . $queryString,
'',
$user,
$this->featureContext->getPasswordForUser($user),