From 939768a1af06cf2064761353685f4f090d699c8b Mon Sep 17 00:00:00 2001 From: Giuseppe Lo Presti Date: Fri, 3 Dec 2021 23:57:13 +0100 Subject: [PATCH 01/28] [Build-deps] Additional rules for CODEOWNERS (#2323) --- CODEOWNERS | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CODEOWNERS b/CODEOWNERS index 830c037728..4c9822be14 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -11,5 +11,7 @@ pkg/storage/fs/owncloudsql @cs3org/owncloud-team pkg/storage/fs/owncloud @cs3org/owncloud-team pkg/storage/fs/ocis @cs3org/owncloud-team pkg/storage/utils/decomposedfs @cs3org/owncloud-team +pkg/storage/utils/eosfs @labkode @ishank011 @glpatcern pkg/user/manager/owncloudsql @cs3org/owncloud-team +pkg/eosclient @labkode @ishank011 @glpatcern pkg/app @labkode @ishank011 @wkloucek @glpatcern From ed9517bc36eaaed3b448ca4fb3aca1c5e0df27cb Mon Sep 17 00:00:00 2001 From: Gianmaria Del Monte <39946305+gmgigi96@users.noreply.github.com> Date: Mon, 6 Dec 2021 11:07:24 +0100 Subject: [PATCH 02/28] Remove share refs from trashbin (#2298) --- changelog/unreleased/fix-share-recyclebin.md | 3 +++ pkg/eosclient/eosbinary/eosbinary.go | 8 ++++++-- pkg/eosclient/eosclient.go | 2 +- pkg/eosclient/eosgrpc/eosgrpc.go | 13 +++++++------ pkg/storage/utils/eosfs/eosfs.go | 14 ++++++-------- 5 files changed, 23 insertions(+), 17 deletions(-) create mode 100644 changelog/unreleased/fix-share-recyclebin.md diff --git a/changelog/unreleased/fix-share-recyclebin.md b/changelog/unreleased/fix-share-recyclebin.md new file mode 100644 index 0000000000..fb0b500138 --- /dev/null +++ b/changelog/unreleased/fix-share-recyclebin.md @@ -0,0 +1,3 @@ +Bugfix: Remove share refs from trashbin + +https://github.com/cs3org/reva/pull/2298 \ No newline at end of file diff --git a/pkg/eosclient/eosbinary/eosbinary.go b/pkg/eosclient/eosbinary/eosbinary.go index 6773513962..b9c1f6a5a4 100644 --- a/pkg/eosclient/eosbinary/eosbinary.go +++ b/pkg/eosclient/eosbinary/eosbinary.go @@ -632,8 +632,12 @@ func (c *Client) CreateDir(ctx context.Context, auth eosclient.Authorization, pa } // Remove removes the resource at the given path -func (c *Client) Remove(ctx context.Context, auth eosclient.Authorization, path string) error { - args := []string{"rm", "-r", path} +func (c *Client) Remove(ctx context.Context, auth eosclient.Authorization, path string, noRecycle bool) error { + args := []string{"rm", "-r"} + if noRecycle { + args = append(args, "--no-recycle-bin") // do not put the file in the recycle bin + } + args = append(args, path) _, _, err := c.executeEOS(ctx, args, auth) return err } diff --git a/pkg/eosclient/eosclient.go b/pkg/eosclient/eosclient.go index 30aed21697..c4e47e7b23 100644 --- a/pkg/eosclient/eosclient.go +++ b/pkg/eosclient/eosclient.go @@ -44,7 +44,7 @@ type EOSClient interface { Chown(ctx context.Context, auth, chownauth Authorization, path string) error Chmod(ctx context.Context, auth Authorization, mode, path string) error CreateDir(ctx context.Context, auth Authorization, path string) error - Remove(ctx context.Context, auth Authorization, path string) error + Remove(ctx context.Context, auth Authorization, path string, noRecycle bool) error Rename(ctx context.Context, auth Authorization, oldPath, newPath string) error List(ctx context.Context, auth Authorization, path string) ([]*FileInfo, error) Read(ctx context.Context, auth Authorization, path string) (io.ReadCloser, error) diff --git a/pkg/eosclient/eosgrpc/eosgrpc.go b/pkg/eosclient/eosgrpc/eosgrpc.go index 5e4df305d0..ea906c9de5 100644 --- a/pkg/eosclient/eosgrpc/eosgrpc.go +++ b/pkg/eosclient/eosgrpc/eosgrpc.go @@ -981,7 +981,7 @@ func (c *Client) CreateDir(ctx context.Context, auth eosclient.Authorization, pa } -func (c *Client) rm(ctx context.Context, auth eosclient.Authorization, path string) error { +func (c *Client) rm(ctx context.Context, auth eosclient.Authorization, path string, noRecycle bool) error { log := appctx.GetLogger(ctx) log.Info().Str("func", "rm").Str("uid,gid", auth.Role.UID+","+auth.Role.GID).Str("path", path).Msg("") @@ -995,6 +995,7 @@ func (c *Client) rm(ctx context.Context, auth eosclient.Authorization, path stri msg.Id = new(erpc.MDId) msg.Id.Path = []byte(path) + msg.Norecycle = noRecycle rq.Command = &erpc.NSRequest_Unlink{Unlink: msg} @@ -1016,7 +1017,7 @@ func (c *Client) rm(ctx context.Context, auth eosclient.Authorization, path stri } -func (c *Client) rmdir(ctx context.Context, auth eosclient.Authorization, path string) error { +func (c *Client) rmdir(ctx context.Context, auth eosclient.Authorization, path string, noRecycle bool) error { log := appctx.GetLogger(ctx) log.Info().Str("func", "rmdir").Str("uid,gid", auth.Role.UID+","+auth.Role.GID).Str("path", path).Msg("") @@ -1031,7 +1032,7 @@ func (c *Client) rmdir(ctx context.Context, auth eosclient.Authorization, path s msg.Id = new(erpc.MDId) msg.Id.Path = []byte(path) msg.Recursive = true - msg.Norecycle = false + msg.Norecycle = noRecycle rq.Command = &erpc.NSRequest_Rm{Rm: msg} @@ -1053,7 +1054,7 @@ func (c *Client) rmdir(ctx context.Context, auth eosclient.Authorization, path s } // Remove removes the resource at the given path -func (c *Client) Remove(ctx context.Context, auth eosclient.Authorization, path string) error { +func (c *Client) Remove(ctx context.Context, auth eosclient.Authorization, path string, noRecycle bool) error { log := appctx.GetLogger(ctx) log.Info().Str("func", "Remove").Str("uid,gid", auth.Role.UID+","+auth.Role.GID).Str("path", path).Msg("") @@ -1064,10 +1065,10 @@ func (c *Client) Remove(ctx context.Context, auth eosclient.Authorization, path } if nfo.IsDir { - return c.rmdir(ctx, auth, path) + return c.rmdir(ctx, auth, path, noRecycle) } - return c.rm(ctx, auth, path) + return c.rm(ctx, auth, path, noRecycle) } // Rename renames the resource referenced by oldPath to newPath diff --git a/pkg/storage/utils/eosfs/eosfs.go b/pkg/storage/utils/eosfs/eosfs.go index 602496a2c5..3d045dd553 100644 --- a/pkg/storage/utils/eosfs/eosfs.go +++ b/pkg/storage/utils/eosfs/eosfs.go @@ -1283,7 +1283,7 @@ func (fs *eosfs) Delete(ctx context.Context, ref *provider.Reference) error { return err } - return fs.c.Remove(ctx, auth, fn) + return fs.c.Remove(ctx, auth, fn, false) } func (fs *eosfs) deleteShadow(ctx context.Context, p string) error { @@ -1292,19 +1292,17 @@ func (fs *eosfs) deleteShadow(ctx context.Context, p string) error { } if fs.isShareFolderChild(ctx, p) { - u, err := getUser(ctx) - if err != nil { - return errors.Wrap(err, "eosfs: no user in ctx") - } - fn := fs.wrapShadow(ctx, p) - auth, err := fs.getUserAuth(ctx, u, "") + // in order to remove the folder or the file without + // moving it to the recycle bin, we should take + // the privileges of the root + auth, err := fs.getRootAuth(ctx) if err != nil { return err } - return fs.c.Remove(ctx, auth, fn) + return fs.c.Remove(ctx, auth, fn, true) } return errors.New("eosfs: shadow delete of share folder that is neither root nor child. path=" + p) From 147c0c2c1c000b636c0a425afbec68d029975045 Mon Sep 17 00:00:00 2001 From: David Christofas Date: Mon, 6 Dec 2021 11:09:02 +0100 Subject: [PATCH 03/28] Public link propfind (#2315) --- changelog/unreleased/public-link-propfind.md | 6 ++++++ .../http/services/owncloud/ocdav/propfind.go | 18 ++++++++++++++++++ .../http/services/owncloud/ocdav/publicfile.go | 3 --- 3 files changed, 24 insertions(+), 3 deletions(-) create mode 100644 changelog/unreleased/public-link-propfind.md diff --git a/changelog/unreleased/public-link-propfind.md b/changelog/unreleased/public-link-propfind.md new file mode 100644 index 0000000000..d2809bbdb0 --- /dev/null +++ b/changelog/unreleased/public-link-propfind.md @@ -0,0 +1,6 @@ +Enhancement: Add new attributes to public link propfinds + +Added a new property "oc:signature-auth" to public link propfinds. +This is a necessary change to be able to support archive downloads in password protected public links. + +https://github.com/cs3org/reva/pull/2315 diff --git a/internal/http/services/owncloud/ocdav/propfind.go b/internal/http/services/owncloud/ocdav/propfind.go index e1c43146b6..320049dfe1 100644 --- a/internal/http/services/owncloud/ocdav/propfind.go +++ b/internal/http/services/owncloud/ocdav/propfind.go @@ -847,6 +847,24 @@ func (s *svc) mdToPropResponse(ctx context.Context, pf *propfindXML, md *provide } else { propstatNotFound.Prop = append(propstatNotFound.Prop, s.newProp("oc:"+pf.Prop[i].Local, "")) } + case "signature-auth": + if isPublic { + // We only want to add the attribute to the root of the propfind. + if strings.HasSuffix(md.Path, ls.Token) && ls.Signature != nil { + expiration := time.Unix(int64(ls.Signature.SignatureExpiration.Seconds), int64(ls.Signature.SignatureExpiration.Nanos)) + var sb strings.Builder + sb.WriteString("") + sb.WriteString(ls.Signature.Signature) + sb.WriteString("") + sb.WriteString("") + sb.WriteString(expiration.Format(time.RFC3339)) + sb.WriteString("") + + propstatOK.Prop = append(propstatOK.Prop, s.newPropRaw("oc:signature-auth", sb.String())) + } else { + propstatNotFound.Prop = append(propstatNotFound.Prop, s.newProp("oc:signature-auth", "")) + } + } case "privatelink": // phoenix only // https://phoenix.owncloud.com/f/9 fallthrough diff --git a/internal/http/services/owncloud/ocdav/publicfile.go b/internal/http/services/owncloud/ocdav/publicfile.go index b369f6650b..ed75e31672 100644 --- a/internal/http/services/owncloud/ocdav/publicfile.go +++ b/internal/http/services/owncloud/ocdav/publicfile.go @@ -181,9 +181,6 @@ func (s *svc) handlePropfindOnToken(w http.ResponseWriter, r *http.Request, ns s w.WriteHeader(http.StatusNotFound) return } - // adjust path - tokenStatInfo.Path = path.Join("/", tokenStatInfo.Path, path.Base(pathRes.Path)) - infos := s.getPublicFileInfos(onContainer, depth == "0", tokenStatInfo) propRes, err := s.multistatusResponse(ctx, &pf, infos, ns, nil) From 7f7f9ec8cc33d536e89e72fb7905d88921455dce Mon Sep 17 00:00:00 2001 From: David Christofas Date: Tue, 7 Dec 2021 12:28:19 +0100 Subject: [PATCH 04/28] fix public share type in propfinds (#2316) --- changelog/unreleased/fix-propfind-sharetype.md | 5 +++++ internal/http/services/owncloud/ocdav/propfind.go | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 changelog/unreleased/fix-propfind-sharetype.md diff --git a/changelog/unreleased/fix-propfind-sharetype.md b/changelog/unreleased/fix-propfind-sharetype.md new file mode 100644 index 0000000000..35f6aa4dd7 --- /dev/null +++ b/changelog/unreleased/fix-propfind-sharetype.md @@ -0,0 +1,5 @@ +Bugfix: Fix the share types in propfinds + +The share types for public links were not correctly added to propfinds. + +https://github.com/cs3org/reva/pull/2316 diff --git a/internal/http/services/owncloud/ocdav/propfind.go b/internal/http/services/owncloud/ocdav/propfind.go index 320049dfe1..eb0e0b197f 100644 --- a/internal/http/services/owncloud/ocdav/propfind.go +++ b/internal/http/services/owncloud/ocdav/propfind.go @@ -159,7 +159,7 @@ func (s *svc) propfindResponse(ctx context.Context, w http.ResponseWriter, r *ht var linkshares map[string]struct{} listResp, err := client.ListPublicShares(ctx, &link.ListPublicSharesRequest{Filters: filters}) if err == nil { - linkshares := make(map[string]struct{}) + linkshares = make(map[string]struct{}, len(listResp.Share)) for i := range listResp.Share { linkshares[listResp.Share[i].ResourceId.OpaqueId] = struct{}{} } From d9eefe2937896b7c93a9c43813af12fa504bcb10 Mon Sep 17 00:00:00 2001 From: Swikriti Tripathi <41103328+SwikritiT@users.noreply.github.com> Date: Wed, 8 Dec 2021 14:39:34 +0545 Subject: [PATCH 05/28] Bump core commit id for tests (#2331) --- .drone.env | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.drone.env b/.drone.env index 549174112e..cce5230458 100644 --- a/.drone.env +++ b/.drone.env @@ -1,3 +1,3 @@ # The test runner source for API tests -CORE_COMMITID=918845e387e18e0ecd765458bc721b2b571b9024 +CORE_COMMITID=4bbd91de68aefdf94c03d2920a3353702f856280 CORE_BRANCH=acceptance-test-changes-waiting-2021-11 From 4dde766d9e015ee4c875e0e8312003fa054d248e Mon Sep 17 00:00:00 2001 From: Ishank Arora Date: Thu, 9 Dec 2021 14:04:24 +0530 Subject: [PATCH 06/28] Revert "Fix content disposition (#2303)" (#2332) This reverts commit 3cba22371b78213f2e49197c2783220331a264bd. --- changelog/unreleased/fix-content-disposition.md | 3 ++- .../publicstorageprovider/publicstorageprovider.go | 7 ++++++- internal/http/services/owncloud/ocdav/publicfile.go | 4 ---- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/changelog/unreleased/fix-content-disposition.md b/changelog/unreleased/fix-content-disposition.md index dcd887266d..58f126a7ac 100644 --- a/changelog/unreleased/fix-content-disposition.md +++ b/changelog/unreleased/fix-content-disposition.md @@ -1,4 +1,5 @@ Bugfix: Fix content disposition header for public links files https://github.com/cs3org/reva/pull/2303 -https://github.com/cs3org/reva/pull/2297 \ No newline at end of file +https://github.com/cs3org/reva/pull/2297 +https://github.com/cs3org/reva/pull/2332 \ No newline at end of file diff --git a/internal/grpc/services/publicstorageprovider/publicstorageprovider.go b/internal/grpc/services/publicstorageprovider/publicstorageprovider.go index 4a8185dc47..c6ec4e983e 100644 --- a/internal/grpc/services/publicstorageprovider/publicstorageprovider.go +++ b/internal/grpc/services/publicstorageprovider/publicstorageprovider.go @@ -163,7 +163,12 @@ func (s *service) translatePublicRefToCS3Ref(ctx context.Context, ref *provider. return nil, "", nil, st, nil } - cs3Ref := &provider.Reference{Path: path.Join("/", shareInfo.Path, relativePath)} + p := shareInfo.Path + if shareInfo.Type != provider.ResourceType_RESOURCE_TYPE_FILE { + p = path.Join("/", shareInfo.Path, relativePath) + } + cs3Ref := &provider.Reference{Path: p} + log.Debug(). Interface("sourceRef", ref). Interface("cs3Ref", cs3Ref). diff --git a/internal/http/services/owncloud/ocdav/publicfile.go b/internal/http/services/owncloud/ocdav/publicfile.go index ed75e31672..b7a62d8bc7 100644 --- a/internal/http/services/owncloud/ocdav/publicfile.go +++ b/internal/http/services/owncloud/ocdav/publicfile.go @@ -55,7 +55,6 @@ func (h *PublicFileHandler) Handler(s *svc) http.Handler { return } - r.URL.Path = path.Base(r.URL.Path) switch r.Method { case MethodPropfind: s.handlePropfindOnToken(w, r, h.namespace, false) @@ -121,9 +120,6 @@ func (s *svc) adjustResourcePathInURL(w http.ResponseWriter, r *http.Request) bo return false } - // adjust path in request URL to point at the parent - r.URL.Path = path.Dir(r.URL.Path) - return true } From 8fde5db7c6484d7c8261db6019da80ad1172c674 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 9 Dec 2021 14:43:38 +0530 Subject: [PATCH 07/28] [Build-deps]: Bump github.com/gomodule/redigo from 1.8.5 to 1.8.6 (#2326) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 1e6cbb7387..a76d7ed305 100644 --- a/go.mod +++ b/go.mod @@ -27,7 +27,7 @@ require ( github.com/go-sql-driver/mysql v1.6.0 github.com/golang-jwt/jwt v3.2.2+incompatible github.com/golang/protobuf v1.5.2 - github.com/gomodule/redigo v1.8.5 + github.com/gomodule/redigo v1.8.6 github.com/google/go-cmp v0.5.6 github.com/google/go-github v17.0.0+incompatible github.com/google/go-querystring v1.1.0 // indirect diff --git a/go.sum b/go.sum index 7b3613ae08..3061cb2797 100644 --- a/go.sum +++ b/go.sum @@ -313,8 +313,8 @@ github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/gomodule/redigo v1.8.5 h1:nRAxCa+SVsyjSBrtZmG/cqb6VbTmuRzpg/PoTFlpumc= -github.com/gomodule/redigo v1.8.5/go.mod h1:P9dn9mFrCBvWhGE1wpxx6fgq7BAeLBk+UUUzlpkBYO0= +github.com/gomodule/redigo v1.8.6 h1:h7kHSqUl2kxeaQtVslsfUCPJ1oz2pxcyzLy4zezIzPw= +github.com/gomodule/redigo v1.8.6/go.mod h1:P9dn9mFrCBvWhGE1wpxx6fgq7BAeLBk+UUUzlpkBYO0= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= From e2109124d15549d54a40d3c39e63cde1dfcc9223 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 9 Dec 2021 14:43:51 +0530 Subject: [PATCH 08/28] [Build-deps]: Bump github.com/mitchellh/mapstructure from 1.4.2 to 1.4.3 (#2324) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index a76d7ed305..e2428123a2 100644 --- a/go.mod +++ b/go.mod @@ -44,7 +44,7 @@ require ( github.com/minio/minio-go/v7 v7.0.16 github.com/mitchellh/copystructure v1.2.0 // indirect github.com/mitchellh/go-testing-interface v1.14.1 // indirect - github.com/mitchellh/mapstructure v1.4.2 + github.com/mitchellh/mapstructure v1.4.3 github.com/onsi/ginkgo v1.16.5 github.com/onsi/gomega v1.17.0 github.com/pkg/errors v0.9.1 diff --git a/go.sum b/go.sum index 3061cb2797..d7042900ca 100644 --- a/go.sum +++ b/go.sum @@ -487,8 +487,8 @@ github.com/mitchellh/mapstructure v1.3.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RR github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.4.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/mitchellh/mapstructure v1.4.2 h1:6h7AQ0yhTcIsmFmnAwQls75jp2Gzs4iB8W7pjMO+rqo= -github.com/mitchellh/mapstructure v1.4.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/mapstructure v1.4.3 h1:OVowDSCllw/YjdLkam3/sm7wEtOy59d8ndGgCcyj8cs= +github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= From 66071c8e76a3f6aa9326e459025cd14bf80ac7cb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 9 Dec 2021 14:44:02 +0530 Subject: [PATCH 09/28] [Build-deps]: Bump github.com/aws/aws-sdk-go from 1.42.9 to 1.42.19 (#2325) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index e2428123a2..167002151e 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/Masterminds/sprig v2.22.0+incompatible github.com/ReneKroon/ttlcache/v2 v2.9.0 github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d // indirect - github.com/aws/aws-sdk-go v1.42.9 + github.com/aws/aws-sdk-go v1.42.19 github.com/beevik/etree v1.1.0 github.com/bluele/gcache v0.0.2 github.com/c-bata/go-prompt v0.2.5 diff --git a/go.sum b/go.sum index d7042900ca..dd5a0265b6 100644 --- a/go.sum +++ b/go.sum @@ -77,8 +77,8 @@ github.com/aws/aws-sdk-go v1.20.1/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN github.com/aws/aws-sdk-go v1.34.28/go.mod h1:H7NKnBqNVzoTJpGfLrQkkD+ytBA93eiDYi/+8rV9s48= github.com/aws/aws-sdk-go v1.38.35/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro= github.com/aws/aws-sdk-go v1.40.11/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q= -github.com/aws/aws-sdk-go v1.42.9 h1:8ptAGgA+uC2TUbdvUeOVSfBocIZvGE2NKiLxkAcn1GA= -github.com/aws/aws-sdk-go v1.42.9/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q= +github.com/aws/aws-sdk-go v1.42.19 h1:L/aM1QwsqVia9qIqexTHwYN+lgLYuOtf11VDgz0YIyw= +github.com/aws/aws-sdk-go v1.42.19/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q= github.com/beevik/etree v1.1.0 h1:T0xke/WvNtMoCqgzPhkX2r4rjY3GDZFi+FjpRZY2Jbs= github.com/beevik/etree v1.1.0/go.mod h1:r8Aw8JqVegEf0w2fDnATrX9VpkMcyFeM0FhwO62wh+A= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= From 68b64bf2be8c703f7d5e12d8979cba78077e0711 Mon Sep 17 00:00:00 2001 From: Willy Kloucek <34452982+wkloucek@users.noreply.github.com> Date: Thu, 9 Dec 2021 14:48:20 +0100 Subject: [PATCH 10/28] fix app provider new file action and improve app provider error codes (#2210) --- changelog/unreleased/app-provider-new-file.md | 8 + internal/grpc/services/gateway/appprovider.go | 7 +- .../http/services/appprovider/appprovider.go | 260 +++++++++++------- internal/http/services/appprovider/errors.go | 78 ++++++ internal/http/services/archiver/handler.go | 32 +-- internal/http/services/owncloud/ocdav/get.go | 3 +- internal/http/services/owncloud/ocdav/head.go | 3 +- internal/http/services/owncloud/ocdav/meta.go | 3 +- internal/http/services/owncloud/ocdav/move.go | 3 +- .../http/services/owncloud/ocdav/ocdav.go | 38 --- .../services/owncloud/ocdav/ocdav_test.go | 58 +--- .../http/services/owncloud/ocdav/propfind.go | 7 +- internal/http/services/owncloud/ocdav/put.go | 3 +- .../http/services/owncloud/ocdav/trashbin.go | 3 +- internal/http/services/owncloud/ocdav/tus.go | 3 +- .../http/services/owncloud/ocdav/versions.go | 3 +- .../handlers/apps/sharing/shares/shares.go | 20 +- pkg/utils/resourceid/owncloud.go | 77 ++++++ pkg/utils/resourceid/owncloud_test.go | 88 ++++++ 19 files changed, 449 insertions(+), 248 deletions(-) create mode 100644 changelog/unreleased/app-provider-new-file.md create mode 100644 internal/http/services/appprovider/errors.go create mode 100644 pkg/utils/resourceid/owncloud.go create mode 100644 pkg/utils/resourceid/owncloud_test.go diff --git a/changelog/unreleased/app-provider-new-file.md b/changelog/unreleased/app-provider-new-file.md new file mode 100644 index 0000000000..223070bfac --- /dev/null +++ b/changelog/unreleased/app-provider-new-file.md @@ -0,0 +1,8 @@ +Change: Fix app provider new file creation and improved error codes + +We've fixed the behavior for the app provider when creating new files. +Previously the app provider would overwrite already existing files when creating a new file, this is now handled and prevented. +The new file endpoint accepted a path to a file, but this does not work for spaces. Therefore we now use the resource id of the folder where the file should be created and a filename to create the new file. +Also the app provider returns more useful error codes in a lot of cases. + +https://github.com/cs3org/reva/pull/2210 diff --git a/internal/grpc/services/gateway/appprovider.go b/internal/grpc/services/gateway/appprovider.go index 74e8a5adec..cbcad414c2 100644 --- a/internal/grpc/services/gateway/appprovider.go +++ b/internal/grpc/services/gateway/appprovider.go @@ -242,7 +242,7 @@ func (s *svc) findAppProvider(ctx context.Context, ri *storageprovider.ResourceI // we did not find a default provider if res.Status.Code == rpc.Code_CODE_NOT_FOUND { - err := errtypes.NotFound(fmt.Sprintf("gateway: default app rovider for mime type:%s not found", ri.MimeType)) + err := errtypes.NotFound(fmt.Sprintf("gateway: default app provider for mime type:%s not found", ri.MimeType)) return nil, err } @@ -285,7 +285,10 @@ func (s *svc) findAppProvider(ctx context.Context, ri *storageprovider.ResourceI } res.Providers = filteredProviders - // if we only have one app provider we verify that it matches the requested app name + if len(res.Providers) == 0 { + return nil, errtypes.NotFound(fmt.Sprintf("app '%s' not found", app)) + } + if len(res.Providers) == 1 { return res.Providers[0], nil } diff --git a/internal/http/services/appprovider/appprovider.go b/internal/http/services/appprovider/appprovider.go index 9795b1302e..ed101a0f3c 100644 --- a/internal/http/services/appprovider/appprovider.go +++ b/internal/http/services/appprovider/appprovider.go @@ -19,13 +19,9 @@ package appprovider import ( - "context" - "encoding/base64" "encoding/json" - "fmt" "net/http" - "strings" - "unicode/utf8" + "path" appregistry "github.com/cs3org/go-cs3apis/cs3/app/registry/v1beta1" gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1" @@ -33,8 +29,6 @@ import ( provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" typespb "github.com/cs3org/go-cs3apis/cs3/types/v1beta1" "github.com/cs3org/reva/internal/http/services/datagateway" - "github.com/cs3org/reva/internal/http/services/ocmd" - "github.com/cs3org/reva/pkg/errtypes" "github.com/cs3org/reva/pkg/rgrpc/status" "github.com/cs3org/reva/pkg/rgrpc/todo/pool" "github.com/cs3org/reva/pkg/rhttp" @@ -42,15 +36,11 @@ import ( "github.com/cs3org/reva/pkg/rhttp/router" "github.com/cs3org/reva/pkg/sharedconf" "github.com/cs3org/reva/pkg/utils" + "github.com/cs3org/reva/pkg/utils/resourceid" ua "github.com/mileusna/useragent" "github.com/mitchellh/mapstructure" "github.com/pkg/errors" "github.com/rs/zerolog" - "github.com/rs/zerolog/log" -) - -const ( - idDelimiter string = ":" ) func init() { @@ -61,6 +51,7 @@ func init() { type Config struct { Prefix string `mapstructure:"prefix"` GatewaySvc string `mapstructure:"gatewaysvc"` + Insecure bool `mapstructure:"insecure"` } func (c *Config) init() { @@ -115,17 +106,17 @@ func (s *svc) Handler() http.Handler { case "open": s.handleOpen(w, r) default: - ocmd.WriteError(w, r, ocmd.APIErrorServerError, "unsupported POST endpoint", nil) + writeError(w, r, appErrorUnimplemented, "unsupported POST endpoint", nil) } case "GET": switch head { case "list": s.handleList(w, r) default: - ocmd.WriteError(w, r, ocmd.APIErrorServerError, "unsupported GET endpoint", nil) + writeError(w, r, appErrorUnimplemented, "unsupported GET endpoint", nil) } default: - ocmd.WriteError(w, r, ocmd.APIErrorServerError, "unsupported method", nil) + writeError(w, r, appErrorUnimplemented, "unsupported method", nil) } }) } @@ -135,34 +126,86 @@ func (s *svc) handleNew(w http.ResponseWriter, r *http.Request) { client, err := pool.GetGatewayServiceClient(s.conf.GatewaySvc) if err != nil { - ocmd.WriteError(w, r, ocmd.APIErrorServerError, "error getting grpc gateway client", err) + writeError(w, r, appErrorServerError, "error getting grpc gateway client", err) return } if r.URL.Query().Get("template") != "" { // TODO in the future we want to create a file out of the given template - ocmd.WriteError(w, r, ocmd.APIErrorInvalidParameter, "Template not implemented", - errtypes.NotSupported("Templates are not yet supported")) + writeError(w, r, appErrorUnimplemented, "template is not implemented", nil) + return + } + + parentContainerID := r.URL.Query().Get("parent_container_id") + if parentContainerID == "" { + writeError(w, r, appErrorInvalidParameter, "missing parent container ID", nil) + return + } + + parentContainerRef := resourceid.OwnCloudResourceIDUnwrap(parentContainerID) + if parentContainerRef == nil { + writeError(w, r, appErrorInvalidParameter, "invalid parent container ID", nil) + return + } + + filename := r.URL.Query().Get("filename") + if filename == "" { + writeError(w, r, appErrorInvalidParameter, "missing filename", nil) + return + } + + dirPart, filePart := path.Split(filename) + if dirPart != "" || filePart != filename { + writeError(w, r, appErrorInvalidParameter, "the filename must not contain a path segment", nil) + return + } + + statParentContainerReq := &provider.StatRequest{ + Ref: &provider.Reference{ + ResourceId: parentContainerRef, + }, + } + parentContainer, err := client.Stat(ctx, statParentContainerReq) + if err != nil { + writeError(w, r, appErrorServerError, "error sending a grpc stat request", err) + return + } + + if parentContainer.Status.Code != rpc.Code_CODE_OK { + writeError(w, r, appErrorNotFound, "the parent container is not accessible or does not exist", err) return } - target := r.URL.Query().Get("filename") - if target == "" { - ocmd.WriteError(w, r, ocmd.APIErrorInvalidParameter, "Missing filename", - errtypes.UserRequired("Missing filename")) + if parentContainer.Info.Type != provider.ResourceType_RESOURCE_TYPE_CONTAINER { + writeError(w, r, appErrorInvalidParameter, "the parent container id does not point to a container", nil) return } - // TODO(lopresti) if target is relative, currently the gateway fails to identify a storage provider (?) - // and just returns a CODE_INTERNAL error on InitiateFileUpload. - // Therefore for now make sure the target is absolute. - if target[0] != '/' { - target = "/" + target + fileRef := &provider.Reference{ + Path: path.Join(parentContainer.Info.Path, utils.MakeRelativePath(filename)), + } + + statFileReq := &provider.StatRequest{ + Ref: fileRef, + } + statFileRes, err := client.Stat(ctx, statFileReq) + if err != nil { + writeError(w, r, appErrorServerError, "failed to stat the file", err) + return + } + + if statFileRes.Status.Code != rpc.Code_CODE_NOT_FOUND { + if statFileRes.Status.Code == rpc.Code_CODE_OK { + writeError(w, r, appErrorAlreadyExists, "the file already exists", nil) + return + } + writeError(w, r, appErrorServerError, "statting the file returned unexpected status code", err) + return } // Create empty file via storageprovider createReq := &provider.InitiateFileUploadRequest{ - Ref: &provider.Reference{Path: target}, + Ref: fileRef, Opaque: &typespb.Opaque{ Map: map[string]*typespb.OpaqueEntry{ "Upload-Length": { @@ -172,13 +215,16 @@ func (s *svc) handleNew(w http.ResponseWriter, r *http.Request) { }, }, } + + // having a client.CreateFile() function would come in handy here... + createRes, err := client.InitiateFileUpload(ctx, createReq) if err != nil { - ocmd.WriteError(w, r, ocmd.APIErrorServerError, "error calling InitiateFileUpload", err) + writeError(w, r, appErrorServerError, "error calling InitiateFileUpload", err) return } if createRes.Status.Code != rpc.Code_CODE_OK { - ocmd.WriteError(w, r, ocmd.APIErrorServerError, "error creating resource", status.NewErrorFromCode(createRes.Status.Code, "appprovider")) + writeError(w, r, appErrorServerError, "error calling InitiateFileUpload", nil) return } @@ -191,44 +237,58 @@ func (s *svc) handleNew(w http.ResponseWriter, r *http.Request) { } httpReq, err := rhttp.NewRequest(ctx, http.MethodPut, ep, nil) if err != nil { - ocmd.WriteError(w, r, ocmd.APIErrorServerError, "error executing PUT", err) + writeError(w, r, appErrorServerError, "failed to create the file", err) return } httpReq.Header.Set(datagateway.TokenTransportHeader, token) - httpRes, err := rhttp.GetHTTPClient().Do(httpReq) + httpRes, err := rhttp.GetHTTPClient( + rhttp.Context(ctx), + rhttp.Insecure(s.conf.Insecure), + ).Do(httpReq) if err != nil { - log.Error().Err(err).Msg("error doing PUT request to data service") - ocmd.WriteError(w, r, ocmd.APIErrorServerError, "error executing PUT", err) + writeError(w, r, appErrorServerError, "failed to create the file", err) return } defer httpRes.Body.Close() - if httpRes.StatusCode != http.StatusOK { - log.Error().Msg("PUT request to data server failed") - ocmd.WriteError(w, r, ocmd.APIErrorServerError, "error executing PUT", - errtypes.InternalError(fmt.Sprint(httpRes.StatusCode))) + if httpRes.StatusCode == http.StatusForbidden { + // the file upload was already finished since it is a zero byte file + // TODO: why do we get a 401 then!? + } else if httpRes.StatusCode != http.StatusOK { + writeError(w, r, appErrorServerError, "failed to create the file", nil) return } // Stat the newly created file - statRes, ocmderr, err := statRef(ctx, provider.Reference{Path: target}, client) + statRes, err := client.Stat(ctx, statFileReq) if err != nil { - log.Error().Err(err).Msg("error statting created file") - ocmd.WriteError(w, r, ocmderr, "Created file not found", errtypes.NotFound("Created file not found")) + writeError(w, r, appErrorServerError, "statting the created file failed", err) + return + } + + if statRes.Status.Code != rpc.Code_CODE_OK { + writeError(w, r, appErrorServerError, "statting the created file failed", nil) + return + } + + if statRes.Info.Type != provider.ResourceType_RESOURCE_TYPE_FILE { + writeError(w, r, appErrorInvalidParameter, "the given file id does not point to a file", nil) return } - // Base64-encode the fileid for the web to consume it - b64id := base64.StdEncoding.EncodeToString([]byte(statRes.Id.StorageId + idDelimiter + statRes.Id.OpaqueId)) - js, err := json.Marshal(map[string]interface{}{"file_id": b64id}) + js, err := json.Marshal( + map[string]interface{}{ + "file_id": resourceid.OwnCloudResourceIDWrap(statRes.Info.Id), + }, + ) if err != nil { - ocmd.WriteError(w, r, ocmd.APIErrorServerError, "error marshalling JSON response", err) + writeError(w, r, appErrorServerError, "error marshalling JSON response", err) return } w.Header().Set("Content-Type", "application/json") if _, err = w.Write(js); err != nil { - ocmd.WriteError(w, r, ocmd.APIErrorServerError, "error writing JSON response", err) + writeError(w, r, appErrorServerError, "error writing JSON response", err) return } } @@ -237,31 +297,30 @@ func (s *svc) handleList(w http.ResponseWriter, r *http.Request) { ctx := r.Context() client, err := pool.GetGatewayServiceClient(s.conf.GatewaySvc) if err != nil { - ocmd.WriteError(w, r, ocmd.APIErrorServerError, "error getting grpc gateway client", err) + writeError(w, r, appErrorServerError, "error getting grpc gateway client", err) return } listRes, err := client.ListSupportedMimeTypes(ctx, &appregistry.ListSupportedMimeTypesRequest{}) if err != nil { - ocmd.WriteError(w, r, ocmd.APIErrorServerError, "error listing supported mime types", err) + writeError(w, r, appErrorServerError, "error listing supported mime types", err) return } if listRes.Status.Code != rpc.Code_CODE_OK { - ocmd.WriteError(w, r, ocmd.APIErrorServerError, "error listing supported mime types", - status.NewErrorFromCode(listRes.Status.Code, "appprovider")) + writeError(w, r, appErrorServerError, "error listing supported mime types", nil) return } res := filterAppsByUserAgent(listRes.MimeTypes, r.UserAgent()) js, err := json.Marshal(map[string]interface{}{"mime-types": res}) if err != nil { - ocmd.WriteError(w, r, ocmd.APIErrorServerError, "error marshalling JSON response", err) + writeError(w, r, appErrorServerError, "error marshalling JSON response", err) return } w.Header().Set("Content-Type", "application/json") if _, err = w.Write(js); err != nil { - ocmd.WriteError(w, r, ocmd.APIErrorServerError, "error writing JSON response", err) + writeError(w, r, appErrorServerError, "error writing JSON response", err) return } } @@ -271,43 +330,83 @@ func (s *svc) handleOpen(w http.ResponseWriter, r *http.Request) { client, err := pool.GetGatewayServiceClient(s.conf.GatewaySvc) if err != nil { - ocmd.WriteError(w, r, ocmd.APIErrorServerError, "Internal error with the gateway, please try again later", err) + writeError(w, r, appErrorServerError, "Internal error with the gateway, please try again later", err) + return + } + + fileID := r.URL.Query().Get("file_id") + + if fileID == "" { + writeError(w, r, appErrorInvalidParameter, "missing file ID", nil) return } - info, errCode, err := s.getStatInfo(ctx, r.URL.Query().Get("file_id"), client) + resourceID := resourceid.OwnCloudResourceIDUnwrap(fileID) + if resourceID == nil { + writeError(w, r, appErrorInvalidParameter, "invalid file ID", nil) + return + } + + fileRef := &provider.Reference{ + ResourceId: resourceID, + } + + statRes, err := client.Stat(ctx, &provider.StatRequest{Ref: fileRef}) if err != nil { - ocmd.WriteError(w, r, errCode, "Internal error accessing the file, please try again later", err) + writeError(w, r, appErrorServerError, "Internal error accessing the file, please try again later", err) + return + } + + if statRes.Status.Code == rpc.Code_CODE_NOT_FOUND { + writeError(w, r, appErrorNotFound, "file does not exist", nil) + return + } else if statRes.Status.Code != rpc.Code_CODE_OK { + writeError(w, r, appErrorServerError, "failed to stat the file", nil) + return + } + + if statRes.Info.Type != provider.ResourceType_RESOURCE_TYPE_FILE { + writeError(w, r, appErrorInvalidParameter, "the given file id does not point to a file", nil) + return + } + + viewMode := getViewMode(statRes.Info, r.URL.Query().Get("view_mode")) + if viewMode == gateway.OpenInAppRequest_VIEW_MODE_INVALID { + writeError(w, r, appErrorInvalidParameter, "invalid view mode", err) return } openReq := gateway.OpenInAppRequest{ - Ref: &provider.Reference{ResourceId: info.Id}, - ViewMode: getViewMode(info, r.URL.Query().Get("view_mode")), + Ref: fileRef, + ViewMode: viewMode, App: r.URL.Query().Get("app_name"), } openRes, err := client.OpenInApp(ctx, &openReq) if err != nil { - ocmd.WriteError(w, r, ocmd.APIErrorServerError, + writeError(w, r, appErrorServerError, "Error contacting the requested application, please use a different one or try again later", err) return } if openRes.Status.Code != rpc.Code_CODE_OK { - ocmd.WriteError(w, r, ocmd.APIErrorServerError, openRes.Status.Message, - status.NewErrorFromCode(openRes.Status.Code, "Error calling OpenInApp")) + if openRes.Status.Code == rpc.Code_CODE_NOT_FOUND { + writeError(w, r, appErrorNotFound, openRes.Status.Message, nil) + return + } + writeError(w, r, appErrorServerError, openRes.Status.Message, + status.NewErrorFromCode(openRes.Status.Code, "error calling OpenInApp")) return } js, err := json.Marshal(openRes.AppUrl) if err != nil { - ocmd.WriteError(w, r, ocmd.APIErrorServerError, "Internal error with JSON payload", + writeError(w, r, appErrorServerError, "Internal error with JSON payload", errors.Wrap(err, "error marshalling JSON response")) return } w.Header().Set("Content-Type", "application/json") if _, err = w.Write(js); err != nil { - ocmd.WriteError(w, r, ocmd.APIErrorServerError, "Internal error with JSON payload", + writeError(w, r, appErrorServerError, "Internal error with JSON payload", errors.Wrap(err, "error writing JSON response")) return } @@ -334,43 +433,6 @@ func filterAppsByUserAgent(mimeTypes []*appregistry.MimeTypeInfo, userAgent stri return res } -func (s *svc) getStatInfo(ctx context.Context, fileID string, client gateway.GatewayAPIClient) (*provider.ResourceInfo, ocmd.APIErrorCode, error) { - if fileID == "" { - return nil, ocmd.APIErrorInvalidParameter, errors.New("fileID parameter missing in request") - } - - decodedID, err := base64.URLEncoding.DecodeString(fileID) - if err != nil { - return nil, ocmd.APIErrorInvalidParameter, errors.Wrap(err, fmt.Sprintf("fileID %s doesn't follow the required format", fileID)) - } - - parts := strings.Split(string(decodedID), idDelimiter) - if !utf8.ValidString(parts[0]) || !utf8.ValidString(parts[1]) { - return nil, ocmd.APIErrorInvalidParameter, errtypes.BadRequest(fmt.Sprintf("fileID %s contains illegal characters", fileID)) - } - res := &provider.ResourceId{ - StorageId: parts[0], - OpaqueId: parts[1], - } - - return statRef(ctx, provider.Reference{ResourceId: res}, client) -} - -func statRef(ctx context.Context, ref provider.Reference, client gateway.GatewayAPIClient) (*provider.ResourceInfo, ocmd.APIErrorCode, error) { - statReq := provider.StatRequest{Ref: &ref} - statRes, err := client.Stat(ctx, &statReq) - if err != nil { - return nil, ocmd.APIErrorServerError, err - } - if statRes.Status.Code != rpc.Code_CODE_OK { - return nil, ocmd.APIErrorServerError, status.NewErrorFromCode(statRes.Status.Code, "appprovider") - } - if statRes.Info.Type != provider.ResourceType_RESOURCE_TYPE_FILE { - return nil, ocmd.APIErrorServerError, errors.New("unsupported resource type") - } - return statRes.Info, ocmd.APIErrorCode(""), nil -} - func getViewMode(res *provider.ResourceInfo, vm string) gateway.OpenInAppRequest_ViewMode { if vm != "" { return utils.GetViewMode(vm) diff --git a/internal/http/services/appprovider/errors.go b/internal/http/services/appprovider/errors.go new file mode 100644 index 0000000000..353925423d --- /dev/null +++ b/internal/http/services/appprovider/errors.go @@ -0,0 +1,78 @@ +// Copyright 2018-2021 CERN +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// In applying this license, CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +package appprovider + +import ( + "encoding/json" + "net/http" + + "github.com/cs3org/reva/pkg/appctx" +) + +// appErrorCode stores the type of error encountered +type appErrorCode string + +const ( + appErrorNotFound appErrorCode = "RESOURCE_NOT_FOUND" + appErrorAlreadyExists appErrorCode = "RESOURCE_ALREADY_EXISTS" + appErrorUnauthenticated appErrorCode = "UNAUTHENTICATED" + appErrorUnimplemented appErrorCode = "NOT_IMPLEMENTED" + appErrorInvalidParameter appErrorCode = "INVALID_PARAMETER" + appErrorServerError appErrorCode = "SERVER_ERROR" +) + +// appErrorCodeMapping stores the HTTP error code mapping for various APIErrorCodes +var appErrorCodeMapping = map[appErrorCode]int{ + appErrorNotFound: http.StatusNotFound, + appErrorAlreadyExists: http.StatusForbidden, + appErrorUnauthenticated: http.StatusUnauthorized, + appErrorUnimplemented: http.StatusNotImplemented, + appErrorInvalidParameter: http.StatusBadRequest, + appErrorServerError: http.StatusInternalServerError, +} + +// APIError encompasses the error type and message +type appError struct { + Code appErrorCode `json:"code"` + Message string `json:"message"` +} + +// writeError handles writing error responses +func writeError(w http.ResponseWriter, r *http.Request, code appErrorCode, message string, err error) { + if err != nil { + appctx.GetLogger(r.Context()).Error().Err(err).Msg(message) + } + + var encoded []byte + w.Header().Set("Content-Type", "application/json") + encoded, err = json.MarshalIndent(appError{Code: code, Message: message}, "", " ") + + if err != nil { + appctx.GetLogger(r.Context()).Error().Err(err).Msg("error encoding response") + w.WriteHeader(http.StatusInternalServerError) + return + } + + w.WriteHeader(appErrorCodeMapping[code]) + _, err = w.Write(encoded) + if err != nil { + appctx.GetLogger(r.Context()).Error().Err(err).Msg("error writing response") + w.WriteHeader(http.StatusInternalServerError) + } +} diff --git a/internal/http/services/archiver/handler.go b/internal/http/services/archiver/handler.go index ffa8df0356..ee2c05f111 100644 --- a/internal/http/services/archiver/handler.go +++ b/internal/http/services/archiver/handler.go @@ -20,12 +20,10 @@ package archiver import ( "context" - "encoding/base64" + "errors" "fmt" "net/http" - "strings" "time" - "unicode/utf8" gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1" rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1" @@ -41,6 +39,7 @@ import ( "github.com/cs3org/reva/pkg/sharedconf" "github.com/cs3org/reva/pkg/storage/utils/downloader" "github.com/cs3org/reva/pkg/storage/utils/walker" + "github.com/cs3org/reva/pkg/utils/resourceid" "github.com/gdexlab/go-render/render" ua "github.com/mileusna/useragent" "github.com/mitchellh/mapstructure" @@ -130,17 +129,14 @@ func (s *svc) getFiles(ctx context.Context, files, ids []string) ([]string, erro for _, id := range ids { // id is base64 encoded and after decoding has the form : - storageID, opaqueID, err := decodeResourceID(id) - if err != nil { - return nil, err + ref := resourceid.OwnCloudResourceIDUnwrap(id) + if ref == nil { + return nil, errors.New("could not unwrap given file id") } resp, err := s.gtwClient.Stat(ctx, &provider.StatRequest{ Ref: &provider.Reference{ - ResourceId: &provider.ResourceId{ - StorageId: storageID, - OpaqueId: opaqueID, - }, + ResourceId: ref, }, }) @@ -279,19 +275,3 @@ func (s *svc) Close() error { func (s *svc) Unprotected() []string { return nil } - -func decodeResourceID(encodedID string) (string, string, error) { - decodedID, err := base64.URLEncoding.DecodeString(encodedID) - if err != nil { - return "", "", errtypes.BadRequest("resource ID does not follow the required format") - } - - parts := strings.Split(string(decodedID), ":") - if len(parts) != 2 { - return "", "", errtypes.BadRequest("resource ID does not follow the required format") - } - if !utf8.ValidString(parts[0]) || !utf8.ValidString(parts[1]) { - return "", "", errtypes.BadRequest("resourceID contains illegal characters") - } - return parts[0], parts[1], nil -} diff --git a/internal/http/services/owncloud/ocdav/get.go b/internal/http/services/owncloud/ocdav/get.go index cefc4da7df..a812365846 100644 --- a/internal/http/services/owncloud/ocdav/get.go +++ b/internal/http/services/owncloud/ocdav/get.go @@ -36,6 +36,7 @@ import ( "github.com/cs3org/reva/pkg/rhttp" rtrace "github.com/cs3org/reva/pkg/trace" "github.com/cs3org/reva/pkg/utils" + "github.com/cs3org/reva/pkg/utils/resourceid" "github.com/rs/zerolog" ) @@ -126,7 +127,7 @@ func (s *svc) handleGet(ctx context.Context, w http.ResponseWriter, r *http.Requ w.Header().Set(HeaderContentDisposistion, "attachment; filename*=UTF-8''"+ path.Base(r.RequestURI)+"; filename=\""+path.Base(r.RequestURI)+"\"") w.Header().Set(HeaderETag, info.Etag) - w.Header().Set(HeaderOCFileID, wrapResourceID(info.Id)) + w.Header().Set(HeaderOCFileID, resourceid.OwnCloudResourceIDWrap(info.Id)) w.Header().Set(HeaderOCETag, info.Etag) t := utils.TSToTime(info.Mtime).UTC() lastModifiedString := t.Format(time.RFC1123Z) diff --git a/internal/http/services/owncloud/ocdav/head.go b/internal/http/services/owncloud/ocdav/head.go index 7b3094595b..7acdca6a8e 100644 --- a/internal/http/services/owncloud/ocdav/head.go +++ b/internal/http/services/owncloud/ocdav/head.go @@ -28,6 +28,7 @@ import ( "time" rtrace "github.com/cs3org/reva/pkg/trace" + "github.com/cs3org/reva/pkg/utils/resourceid" rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1" provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" @@ -73,7 +74,7 @@ func (s *svc) handleHead(ctx context.Context, w http.ResponseWriter, r *http.Req info := res.Info w.Header().Set(HeaderContentType, info.MimeType) w.Header().Set(HeaderETag, info.Etag) - w.Header().Set(HeaderOCFileID, wrapResourceID(info.Id)) + w.Header().Set(HeaderOCFileID, resourceid.OwnCloudResourceIDWrap(info.Id)) w.Header().Set(HeaderOCETag, info.Etag) if info.Checksum != nil { w.Header().Set(HeaderOCChecksum, fmt.Sprintf("%s:%s", strings.ToUpper(string(storageprovider.GRPC2PKGXS(info.Checksum.Type))), info.Checksum.Sum)) diff --git a/internal/http/services/owncloud/ocdav/meta.go b/internal/http/services/owncloud/ocdav/meta.go index f40baa2396..7aaffea142 100644 --- a/internal/http/services/owncloud/ocdav/meta.go +++ b/internal/http/services/owncloud/ocdav/meta.go @@ -22,6 +22,7 @@ import ( "net/http" "github.com/cs3org/reva/pkg/rhttp/router" + "github.com/cs3org/reva/pkg/utils/resourceid" ) // MetaHandler handles meta requests @@ -45,7 +46,7 @@ func (h *MetaHandler) Handler(s *svc) http.Handler { return } - did := unwrap(id) + did := resourceid.OwnCloudResourceIDUnwrap(id) var head string head, r.URL.Path = router.ShiftPath(r.URL.Path) diff --git a/internal/http/services/owncloud/ocdav/move.go b/internal/http/services/owncloud/ocdav/move.go index 376f57d72b..53d3852f8c 100644 --- a/internal/http/services/owncloud/ocdav/move.go +++ b/internal/http/services/owncloud/ocdav/move.go @@ -30,6 +30,7 @@ import ( "github.com/cs3org/reva/pkg/appctx" "github.com/cs3org/reva/pkg/rhttp/router" rtrace "github.com/cs3org/reva/pkg/trace" + "github.com/cs3org/reva/pkg/utils/resourceid" "github.com/rs/zerolog" ) @@ -259,7 +260,7 @@ func (s *svc) handleMove(ctx context.Context, w http.ResponseWriter, r *http.Req info := dstStatRes.Info w.Header().Set(HeaderContentType, info.MimeType) w.Header().Set(HeaderETag, info.Etag) - w.Header().Set(HeaderOCFileID, wrapResourceID(info.Id)) + w.Header().Set(HeaderOCFileID, resourceid.OwnCloudResourceIDWrap(info.Id)) w.Header().Set(HeaderOCETag, info.Etag) w.WriteHeader(successCode) } diff --git a/internal/http/services/owncloud/ocdav/ocdav.go b/internal/http/services/owncloud/ocdav/ocdav.go index 27d11407b2..e53daa7ccf 100644 --- a/internal/http/services/owncloud/ocdav/ocdav.go +++ b/internal/http/services/owncloud/ocdav/ocdav.go @@ -20,7 +20,6 @@ package ocdav import ( "context" - "encoding/base64" "fmt" "net/http" "net/url" @@ -28,11 +27,9 @@ import ( "regexp" "strings" "time" - "unicode/utf8" gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1" userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" - provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" "github.com/cs3org/reva/pkg/appctx" ctxpkg "github.com/cs3org/reva/pkg/ctx" "github.com/cs3org/reva/pkg/errtypes" @@ -53,8 +50,6 @@ type ctxKey int const ( ctxKeyBaseURI ctxKey = iota - - idDelimiter string = ":" ) var ( @@ -271,39 +266,6 @@ func applyLayout(ctx context.Context, ns string, useLoggedInUserNS bool, request return templates.WithUser(u, ns) } -func wrapResourceID(r *provider.ResourceId) string { - return wrap(r.StorageId, r.OpaqueId) -} - -// The fileID must be encoded -// - XML safe, because it is going to be used in the propfind result -// - url safe, because the id might be used in a url, eg. the /dav/meta nodes -// which is why we base64 encode it -func wrap(sid string, oid string) string { - return base64.URLEncoding.EncodeToString([]byte(sid + idDelimiter + oid)) -} - -func unwrap(rid string) *provider.ResourceId { - decodedID, err := base64.URLEncoding.DecodeString(rid) - if err != nil { - return nil - } - - parts := strings.SplitN(string(decodedID), idDelimiter, 2) - if len(parts) != 2 { - return nil - } - - if !utf8.ValidString(parts[0]) || !utf8.ValidString(parts[1]) { - return nil - } - - return &provider.ResourceId{ - StorageId: parts[0], - OpaqueId: parts[1], - } -} - func addAccessHeaders(w http.ResponseWriter, r *http.Request) { headers := w.Header() // the webdav api is accessible from anywhere diff --git a/internal/http/services/owncloud/ocdav/ocdav_test.go b/internal/http/services/owncloud/ocdav/ocdav_test.go index 24326cb9f9..7d0de23167 100644 --- a/internal/http/services/owncloud/ocdav/ocdav_test.go +++ b/internal/http/services/owncloud/ocdav/ocdav_test.go @@ -25,7 +25,7 @@ import ( "testing" providerv1beta1 "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" - "github.com/cs3org/reva/pkg/utils" + "github.com/cs3org/reva/pkg/utils/resourceid" ) /* @@ -41,69 +41,15 @@ func BenchmarkEncodePath(b *testing.B) { } } -func BenchmarkWrap(b *testing.B) { - for i := 0; i < b.N; i++ { - _ = wrap("storageid", "opaqueid") - } -} - -func TestWrap(t *testing.T) { - expected := "c3RvcmFnZWlkOm9wYXF1ZWlk" - wrapped := wrap("storageid", "opaqueid") - - if wrapped != expected { - t.Errorf("wrapped id doesn't have the expected format: got %s expected %s", wrapped, expected) - } -} - func TestWrapResourceID(t *testing.T) { expected := "c3RvcmFnZWlkOm9wYXF1ZWlk" - wrapped := wrapResourceID(&providerv1beta1.ResourceId{StorageId: "storageid", OpaqueId: "opaqueid"}) + wrapped := resourceid.OwnCloudResourceIDWrap(&providerv1beta1.ResourceId{StorageId: "storageid", OpaqueId: "opaqueid"}) if wrapped != expected { t.Errorf("wrapped id doesn't have the expected format: got %s expected %s", wrapped, expected) } } -func BenchmarkUnwrap(b *testing.B) { - for i := 0; i < b.N; i++ { - _ = unwrap("c3RvcmFnZWlkOm9wYXF1ZWlk") - } -} - -func TestUnwrap(t *testing.T) { - tests := []struct { - input string - expected *providerv1beta1.ResourceId - }{ - { - "c3RvcmFnZWlkOm9wYXF1ZWlk", - &providerv1beta1.ResourceId{StorageId: "storageid", OpaqueId: "opaqueid"}, - }, - { - "", - nil, - }, - { - "c", - nil, - }, - } - - for _, tt := range tests { - rid := unwrap(tt.input) - - if tt.expected == nil { - if rid != nil { - t.Errorf("Expected unwrap to return nil, got %v", rid) - } - } else if !utils.ResourceIDEqual(rid, tt.expected) { - t.Error("StorageID or OpaqueID doesn't match") - } - } - -} - func TestExtractDestination(t *testing.T) { expected := "/dst" request := httptest.NewRequest(http.MethodGet, "https://example.org/remote.php/dav/src", nil) diff --git a/internal/http/services/owncloud/ocdav/propfind.go b/internal/http/services/owncloud/ocdav/propfind.go index eb0e0b197f..a9adf2848d 100644 --- a/internal/http/services/owncloud/ocdav/propfind.go +++ b/internal/http/services/owncloud/ocdav/propfind.go @@ -44,6 +44,7 @@ import ( "github.com/cs3org/reva/pkg/publicshare" rtrace "github.com/cs3org/reva/pkg/trace" "github.com/cs3org/reva/pkg/utils" + "github.com/cs3org/reva/pkg/utils/resourceid" "github.com/rs/zerolog" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/codes" @@ -550,7 +551,7 @@ func (s *svc) mdToPropResponse(ctx context.Context, pf *propfindXML, md *provide // return all known properties if md.Id != nil { - id := wrapResourceID(md.Id) + id := resourceid.OwnCloudResourceIDWrap(md.Id) propstatOK.Prop = append(propstatOK.Prop, s.newProp("oc:id", id), s.newProp("oc:fileid", id), @@ -649,13 +650,13 @@ func (s *svc) mdToPropResponse(ctx context.Context, pf *propfindXML, md *provide // I tested the desktop client and phoenix to annotate which properties are requestted, see below cases case "fileid": // phoenix only if md.Id != nil { - propstatOK.Prop = append(propstatOK.Prop, s.newProp("oc:fileid", wrapResourceID(md.Id))) + propstatOK.Prop = append(propstatOK.Prop, s.newProp("oc:fileid", resourceid.OwnCloudResourceIDWrap(md.Id))) } else { propstatNotFound.Prop = append(propstatNotFound.Prop, s.newProp("oc:fileid", "")) } case "id": // desktop client only if md.Id != nil { - propstatOK.Prop = append(propstatOK.Prop, s.newProp("oc:id", wrapResourceID(md.Id))) + propstatOK.Prop = append(propstatOK.Prop, s.newProp("oc:id", resourceid.OwnCloudResourceIDWrap(md.Id))) } else { propstatNotFound.Prop = append(propstatNotFound.Prop, s.newProp("oc:id", "")) } diff --git a/internal/http/services/owncloud/ocdav/put.go b/internal/http/services/owncloud/ocdav/put.go index f28a423404..1114d604f6 100644 --- a/internal/http/services/owncloud/ocdav/put.go +++ b/internal/http/services/owncloud/ocdav/put.go @@ -36,6 +36,7 @@ import ( "github.com/cs3org/reva/pkg/storage/utils/chunking" rtrace "github.com/cs3org/reva/pkg/trace" "github.com/cs3org/reva/pkg/utils" + "github.com/cs3org/reva/pkg/utils/resourceid" "github.com/rs/zerolog" ) @@ -314,7 +315,7 @@ func (s *svc) handlePut(ctx context.Context, w http.ResponseWriter, r *http.Requ w.Header().Add(HeaderContentType, newInfo.MimeType) w.Header().Set(HeaderETag, newInfo.Etag) - w.Header().Set(HeaderOCFileID, wrapResourceID(newInfo.Id)) + w.Header().Set(HeaderOCFileID, resourceid.OwnCloudResourceIDWrap(newInfo.Id)) w.Header().Set(HeaderOCETag, newInfo.Etag) t := utils.TSToTime(newInfo.Mtime).UTC() lastModifiedString := t.Format(time.RFC1123Z) diff --git a/internal/http/services/owncloud/ocdav/trashbin.go b/internal/http/services/owncloud/ocdav/trashbin.go index 5d7425d1bd..7d27aa0964 100644 --- a/internal/http/services/owncloud/ocdav/trashbin.go +++ b/internal/http/services/owncloud/ocdav/trashbin.go @@ -30,6 +30,7 @@ import ( "time" rtrace "github.com/cs3org/reva/pkg/trace" + "github.com/cs3org/reva/pkg/utils/resourceid" userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1" @@ -580,7 +581,7 @@ func (h *TrashbinHandler) restore(w http.ResponseWriter, r *http.Request, s *svc info := dstStatRes.Info w.Header().Set(HeaderContentType, info.MimeType) w.Header().Set(HeaderETag, info.Etag) - w.Header().Set(HeaderOCFileID, wrapResourceID(info.Id)) + w.Header().Set(HeaderOCFileID, resourceid.OwnCloudResourceIDWrap(info.Id)) w.Header().Set(HeaderOCETag, info.Etag) w.WriteHeader(successCode) diff --git a/internal/http/services/owncloud/ocdav/tus.go b/internal/http/services/owncloud/ocdav/tus.go index 8dea0a0fce..b795d482d4 100644 --- a/internal/http/services/owncloud/ocdav/tus.go +++ b/internal/http/services/owncloud/ocdav/tus.go @@ -36,6 +36,7 @@ import ( "github.com/cs3org/reva/pkg/rhttp" rtrace "github.com/cs3org/reva/pkg/trace" "github.com/cs3org/reva/pkg/utils" + "github.com/cs3org/reva/pkg/utils/resourceid" "github.com/rs/zerolog" tusd "github.com/tus/tusd/pkg/handler" ) @@ -313,7 +314,7 @@ func (s *svc) handleTusPost(ctx context.Context, w http.ResponseWriter, r *http. ) w.Header().Set(HeaderContentType, info.MimeType) - w.Header().Set(HeaderOCFileID, wrapResourceID(info.Id)) + w.Header().Set(HeaderOCFileID, resourceid.OwnCloudResourceIDWrap(info.Id)) w.Header().Set(HeaderOCETag, info.Etag) w.Header().Set(HeaderETag, info.Etag) w.Header().Set(HeaderOCPermissions, permissions) diff --git a/internal/http/services/owncloud/ocdav/versions.go b/internal/http/services/owncloud/ocdav/versions.go index ad6620ccd9..75467dd39e 100644 --- a/internal/http/services/owncloud/ocdav/versions.go +++ b/internal/http/services/owncloud/ocdav/versions.go @@ -24,6 +24,7 @@ import ( "path" rtrace "github.com/cs3org/reva/pkg/trace" + "github.com/cs3org/reva/pkg/utils/resourceid" rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1" provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" @@ -53,7 +54,7 @@ func (h *VersionsHandler) Handler(s *svc, rid *provider.ResourceId) http.Handler } // baseURI is encoded as part of the response payload in href field - baseURI := path.Join(ctx.Value(ctxKeyBaseURI).(string), wrapResourceID(rid)) + baseURI := path.Join(ctx.Value(ctxKeyBaseURI).(string), resourceid.OwnCloudResourceIDWrap(rid)) ctx = context.WithValue(ctx, ctxKeyBaseURI, baseURI) r = r.WithContext(ctx) diff --git a/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/shares.go b/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/shares.go index f1937658ca..53c859c7c0 100644 --- a/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/shares.go +++ b/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/shares.go @@ -21,7 +21,6 @@ package shares import ( "bytes" "context" - "encoding/base64" "encoding/json" "fmt" "mime" @@ -55,6 +54,7 @@ import ( "github.com/cs3org/reva/pkg/share/cache" "github.com/cs3org/reva/pkg/share/cache/registry" "github.com/cs3org/reva/pkg/utils" + "github.com/cs3org/reva/pkg/utils/resourceid" "github.com/pkg/errors" ) @@ -119,7 +119,7 @@ func (h *Handler) startCacheWarmup(c cache.Warmup) { return } for _, r := range infos { - key := wrapResourceID(r.Id) + key := resourceid.OwnCloudResourceIDWrap(r.Id) _ = h.resourceInfoCache.SetWithExpire(key, r, h.resourceInfoCacheTTL) } } @@ -856,18 +856,6 @@ func (h *Handler) addFilters(w http.ResponseWriter, r *http.Request, prefix stri return collaborationFilters, linkFilters, nil } -func wrapResourceID(r *provider.ResourceId) string { - return wrap(r.StorageId, r.OpaqueId) -} - -// The fileID must be encoded -// - XML safe, because it is going to be used in the propfind result -// - url safe, because the id might be used in a url, eg. the /dav/meta nodes -// which is why we base64 encode it -func wrap(sid string, oid string) string { - return base64.URLEncoding.EncodeToString([]byte(fmt.Sprintf("%s:%s", sid, oid))) -} - func (h *Handler) addFileInfo(ctx context.Context, s *conversions.ShareData, info *provider.ResourceInfo) error { log := appctx.GetLogger(ctx) if info != nil { @@ -880,7 +868,7 @@ func (h *Handler) addFileInfo(ctx context.Context, s *conversions.ShareData, inf s.MimeType = parsedMt // TODO STime: &types.Timestamp{Seconds: info.Mtime.Seconds, Nanos: info.Mtime.Nanos}, // TODO Storage: int - s.ItemSource = wrapResourceID(info.Id) + s.ItemSource = resourceid.OwnCloudResourceIDWrap(info.Id) s.FileSource = s.ItemSource switch { case h.sharePrefix == "/": @@ -1041,7 +1029,7 @@ func (h *Handler) getResourceInfoByPath(ctx context.Context, client gateway.Gate } func (h *Handler) getResourceInfoByID(ctx context.Context, client gateway.GatewayAPIClient, id *provider.ResourceId) (*provider.ResourceInfo, *rpc.Status, error) { - return h.getResourceInfo(ctx, client, wrapResourceID(id), &provider.Reference{ResourceId: id}) + return h.getResourceInfo(ctx, client, resourceid.OwnCloudResourceIDWrap(id), &provider.Reference{ResourceId: id}) } // getResourceInfo retrieves the resource info to a target. diff --git a/pkg/utils/resourceid/owncloud.go b/pkg/utils/resourceid/owncloud.go new file mode 100644 index 0000000000..39abc460a4 --- /dev/null +++ b/pkg/utils/resourceid/owncloud.go @@ -0,0 +1,77 @@ +// Copyright 2018-2021 CERN +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// In applying this license, CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +package resourceid + +import ( + "encoding/base64" + "errors" + "strings" + "unicode/utf8" + + provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" +) + +const ( + idDelimiter string = ":" +) + +// OwnCloudResourceIDUnwrap returns the wrapped resource id +// by OwnCloudResourceIDWrap and returns nil if not possible +func OwnCloudResourceIDUnwrap(rid string) *provider.ResourceId { + id, err := unwrap(rid) + if err != nil { + return nil + } + return id +} + +func unwrap(rid string) (*provider.ResourceId, error) { + decodedID, err := base64.URLEncoding.DecodeString(rid) + if err != nil { + return nil, err + } + + parts := strings.SplitN(string(decodedID), idDelimiter, 2) + if len(parts) != 2 { + return nil, errors.New("could not find two parts with given delimiter") + } + + if !utf8.ValidString(parts[0]) || !utf8.ValidString(parts[1]) { + return nil, errors.New("invalid utf8 string found") + } + + return &provider.ResourceId{ + StorageId: parts[0], + OpaqueId: parts[1], + }, nil +} + +// OwnCloudResourceIDWrap wraps a resource id into a xml safe string +// which can then be passed to the outside world +func OwnCloudResourceIDWrap(r *provider.ResourceId) string { + return wrap(r.StorageId, r.OpaqueId) +} + +// The fileID must be encoded +// - XML safe, because it is going to be used in the propfind result +// - url safe, because the id might be used in a url, eg. the /dav/meta nodes +// which is why we base64 encode it +func wrap(sid string, oid string) string { + return base64.URLEncoding.EncodeToString([]byte(sid + idDelimiter + oid)) +} diff --git a/pkg/utils/resourceid/owncloud_test.go b/pkg/utils/resourceid/owncloud_test.go new file mode 100644 index 0000000000..5fc45af94a --- /dev/null +++ b/pkg/utils/resourceid/owncloud_test.go @@ -0,0 +1,88 @@ +// Copyright 2021 CERN +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// In applying this license, CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +package resourceid + +import ( + "testing" + + providerv1beta1 "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" + "github.com/cs3org/reva/pkg/utils" +) + +func BenchmarkWrap(b *testing.B) { + for i := 0; i < b.N; i++ { + _ = wrap("storageid", "opaqueid") + } +} + +func TestWrap(t *testing.T) { + expected := "c3RvcmFnZWlkOm9wYXF1ZWlk" + wrapped := wrap("storageid", "opaqueid") + + if wrapped != expected { + t.Errorf("wrapped id doesn't have the expected format: got %s expected %s", wrapped, expected) + } +} + +func TestWrapResourceID(t *testing.T) { + expected := "c3RvcmFnZWlkOm9wYXF1ZWlk" + wrapped := OwnCloudResourceIDWrap(&providerv1beta1.ResourceId{StorageId: "storageid", OpaqueId: "opaqueid"}) + + if wrapped != expected { + t.Errorf("wrapped id doesn't have the expected format: got %s expected %s", wrapped, expected) + } +} + +func BenchmarkUnwrap(b *testing.B) { + for i := 0; i < b.N; i++ { + _, _ = unwrap("c3RvcmFnZWlkOm9wYXF1ZWlk") + } +} + +func TestUnwrap(t *testing.T) { + tests := []struct { + input string + expected *providerv1beta1.ResourceId + }{ + { + "c3RvcmFnZWlkOm9wYXF1ZWlk", + &providerv1beta1.ResourceId{StorageId: "storageid", OpaqueId: "opaqueid"}, + }, + { + "", + nil, + }, + { + "c", + nil, + }, + } + + for _, tt := range tests { + rid := OwnCloudResourceIDUnwrap(tt.input) + + if tt.expected == nil { + if rid != nil { + t.Errorf("Expected unwrap to return nil, got %v", rid) + } + } else if !utils.ResourceIDEqual(rid, tt.expected) { + t.Error("StorageID or OpaqueID doesn't match") + } + } + +} From 2f727fc050a596458f6d96406a513e8bb053002a Mon Sep 17 00:00:00 2001 From: Ishank Arora Date: Thu, 9 Dec 2021 19:36:07 +0530 Subject: [PATCH 11/28] Parse URL path to determine file name (#2346) --- .../unreleased/fix-content-disposition.md | 3 +- .../auth/manager/oidcmapping/_index.md | 66 +++++++++++++++++++ internal/http/services/owncloud/ocdav/get.go | 2 +- 3 files changed, 69 insertions(+), 2 deletions(-) create mode 100644 docs/content/en/docs/config/packages/auth/manager/oidcmapping/_index.md diff --git a/changelog/unreleased/fix-content-disposition.md b/changelog/unreleased/fix-content-disposition.md index 58f126a7ac..da3822ceb1 100644 --- a/changelog/unreleased/fix-content-disposition.md +++ b/changelog/unreleased/fix-content-disposition.md @@ -2,4 +2,5 @@ Bugfix: Fix content disposition header for public links files https://github.com/cs3org/reva/pull/2303 https://github.com/cs3org/reva/pull/2297 -https://github.com/cs3org/reva/pull/2332 \ No newline at end of file +https://github.com/cs3org/reva/pull/2332 +https://github.com/cs3org/reva/pull/2346 \ No newline at end of file diff --git a/docs/content/en/docs/config/packages/auth/manager/oidcmapping/_index.md b/docs/content/en/docs/config/packages/auth/manager/oidcmapping/_index.md new file mode 100644 index 0000000000..a7309eb3e1 --- /dev/null +++ b/docs/content/en/docs/config/packages/auth/manager/oidcmapping/_index.md @@ -0,0 +1,66 @@ +--- +title: "oidcmapping" +linkTitle: "oidcmapping" +weight: 10 +description: > + Configuration for the oidcmapping service +--- + +# _struct: config_ + +{{% dir name="insecure" type="bool" default=false %}} +Whether to skip certificate checks when sending requests. [[Ref]](https://github.com/cs3org/reva/tree/master/pkg/auth/manager/oidcmapping/oidcmapping.go#L57) +{{< highlight toml >}} +[auth.manager.oidcmapping] +insecure = false +{{< /highlight >}} +{{% /dir %}} + +{{% dir name="issuer" type="string" default="" %}} +The issuer of the OIDC token. [[Ref]](https://github.com/cs3org/reva/tree/master/pkg/auth/manager/oidcmapping/oidcmapping.go#L58) +{{< highlight toml >}} +[auth.manager.oidcmapping] +issuer = "" +{{< /highlight >}} +{{% /dir %}} + +{{% dir name="id_claim" type="string" default="sub" %}} +The claim containing the ID of the user. [[Ref]](https://github.com/cs3org/reva/tree/master/pkg/auth/manager/oidcmapping/oidcmapping.go#L59) +{{< highlight toml >}} +[auth.manager.oidcmapping] +id_claim = "sub" +{{< /highlight >}} +{{% /dir %}} + +{{% dir name="uid_claim" type="string" default="" %}} +The claim containing the UID of the user. [[Ref]](https://github.com/cs3org/reva/tree/master/pkg/auth/manager/oidcmapping/oidcmapping.go#L60) +{{< highlight toml >}} +[auth.manager.oidcmapping] +uid_claim = "" +{{< /highlight >}} +{{% /dir %}} + +{{% dir name="gid_claim" type="string" default="" %}} +The claim containing the GID of the user. [[Ref]](https://github.com/cs3org/reva/tree/master/pkg/auth/manager/oidcmapping/oidcmapping.go#L61) +{{< highlight toml >}} +[auth.manager.oidcmapping] +gid_claim = "" +{{< /highlight >}} +{{% /dir %}} + +{{% dir name="userprovidersvc" type="string" default="" %}} +The endpoint at which the GRPC userprovider is exposed. [[Ref]](https://github.com/cs3org/reva/tree/master/pkg/auth/manager/oidcmapping/oidcmapping.go#L62) +{{< highlight toml >}} +[auth.manager.oidcmapping] +userprovidersvc = "" +{{< /highlight >}} +{{% /dir %}} + +{{% dir name="usersmapping" type="string" default="" %}} + The OIDC users mapping file path [[Ref]](https://github.com/cs3org/reva/tree/master/pkg/auth/manager/oidcmapping/oidcmapping.go#L63) +{{< highlight toml >}} +[auth.manager.oidcmapping] +usersmapping = "" +{{< /highlight >}} +{{% /dir %}} + diff --git a/internal/http/services/owncloud/ocdav/get.go b/internal/http/services/owncloud/ocdav/get.go index a812365846..b93230ab51 100644 --- a/internal/http/services/owncloud/ocdav/get.go +++ b/internal/http/services/owncloud/ocdav/get.go @@ -125,7 +125,7 @@ func (s *svc) handleGet(ctx context.Context, w http.ResponseWriter, r *http.Requ w.Header().Set(HeaderContentType, info.MimeType) w.Header().Set(HeaderContentDisposistion, "attachment; filename*=UTF-8''"+ - path.Base(r.RequestURI)+"; filename=\""+path.Base(r.RequestURI)+"\"") + path.Base(r.URL.Path)+"; filename=\""+path.Base(r.URL.Path)+"\"") w.Header().Set(HeaderETag, info.Etag) w.Header().Set(HeaderOCFileID, resourceid.OwnCloudResourceIDWrap(info.Id)) w.Header().Set(HeaderOCETag, info.Etag) From d54df2f488df3560d332a68bcc70ee175954140e Mon Sep 17 00:00:00 2001 From: Ishank Arora Date: Thu, 9 Dec 2021 19:41:11 +0530 Subject: [PATCH 12/28] v1.17.0 --- CHANGELOG.md | 121 ++++++++ RELEASE_DATE | 2 +- VERSION | 2 +- .../app-abspath.md | 0 .../app-provider-new-file.md | 0 .../fix-content-disposition.md | 0 .../fix-propfind-sharetype.md | 0 .../fix-public-link-wopi.md | 0 .../fix-share-recyclebin.md | 0 .../fix-skip-early-empty-file-creation.md | 0 .../iodc-escape-auth.md | 0 .../ocs-user-type.md | 0 .../public-link-propfind.md | 0 .../space-membership.md | 0 .../sysacl-from-xattr.md | 0 .../tus-upload-with-transfer-token-only.md | 0 .../user-claim-fallback.md | 0 changelog/NOTE.md | 288 +++++------------- .../en/docs/changelog/1.17.0/_index.md | 130 ++++++++ 19 files changed, 321 insertions(+), 222 deletions(-) rename changelog/{unreleased => 1.17.0_2021-12-09}/app-abspath.md (100%) rename changelog/{unreleased => 1.17.0_2021-12-09}/app-provider-new-file.md (100%) rename changelog/{unreleased => 1.17.0_2021-12-09}/fix-content-disposition.md (100%) rename changelog/{unreleased => 1.17.0_2021-12-09}/fix-propfind-sharetype.md (100%) rename changelog/{unreleased => 1.17.0_2021-12-09}/fix-public-link-wopi.md (100%) rename changelog/{unreleased => 1.17.0_2021-12-09}/fix-share-recyclebin.md (100%) rename changelog/{unreleased => 1.17.0_2021-12-09}/fix-skip-early-empty-file-creation.md (100%) rename changelog/{unreleased => 1.17.0_2021-12-09}/iodc-escape-auth.md (100%) rename changelog/{unreleased => 1.17.0_2021-12-09}/ocs-user-type.md (100%) rename changelog/{unreleased => 1.17.0_2021-12-09}/public-link-propfind.md (100%) rename changelog/{unreleased => 1.17.0_2021-12-09}/space-membership.md (100%) rename changelog/{unreleased => 1.17.0_2021-12-09}/sysacl-from-xattr.md (100%) rename changelog/{unreleased => 1.17.0_2021-12-09}/tus-upload-with-transfer-token-only.md (100%) rename changelog/{unreleased => 1.17.0_2021-12-09}/user-claim-fallback.md (100%) create mode 100644 docs/content/en/docs/changelog/1.17.0/_index.md diff --git a/CHANGELOG.md b/CHANGELOG.md index c012445f1e..825b70bcaf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,124 @@ +Changelog for reva 1.17.0 (2021-12-09) +======================================= + +The following sections list the changes in reva 1.17.0 relevant to +reva users. The changes are ordered by importance. + +Summary +------- + + * Fix #2305: Make sure /app/new takes `target` as absolute path + * Fix #2303: Fix content disposition header for public links files + * Fix #2316: Fix the share types in propfinds + * Fix #2803: Fix app provider for editor public links + * Fix #2298: Remove share refs from trashbin + * Fix #2309: Remove early finish for zero byte file uploads + * Fix #1941: Fix TUS uploads with transfer token only + * Chg #2210: Fix app provider new file creation and improved error codes + * Enh #2217: OIDC auth driver for ESCAPE IAM + * Enh #2256: Return user type in the response of the ocs GET user call + * Enh #2315: Add new attributes to public link propfinds + * Enh #2740: Implement space membership endpoints + * Enh #2252: Add the xattr sys.acl to SysACL (eosgrpc) + * Enh #2314: OIDC: fallback if IDP doesn't provide "preferred_username" claim + +Details +------- + + * Bugfix #2305: Make sure /app/new takes `target` as absolute path + + A mini-PR to make the `target` parameter absolute (by prepending `/` if missing). + + https://github.com/cs3org/reva/pull/2305 + + * Bugfix #2303: Fix content disposition header for public links files + + https://github.com/cs3org/reva/pull/2303 + https://github.com/cs3org/reva/pull/2297 + https://github.com/cs3org/reva/pull/2332 + https://github.com/cs3org/reva/pull/2346 + + * Bugfix #2316: Fix the share types in propfinds + + The share types for public links were not correctly added to propfinds. + + https://github.com/cs3org/reva/pull/2316 + + * Bugfix #2803: Fix app provider for editor public links + + Fixed opening the app provider in public links with the editor permission. The app provider + failed to open the file in read write mode. + + https://github.com/owncloud/ocis/issues/2803 + https://github.com/cs3org/reva/pull/2310 + + * Bugfix #2298: Remove share refs from trashbin + + https://github.com/cs3org/reva/pull/2298 + + * Bugfix #2309: Remove early finish for zero byte file uploads + + We've fixed the upload of zero byte files by removing the early upload finishing mechanism. + + https://github.com/cs3org/reva/issues/2309 + https://github.com/owncloud/ocis/issues/2609 + + * Bugfix #1941: Fix TUS uploads with transfer token only + + TUS uploads had been stopped when the user JWT token expired, even if only the transfer token + should be validated. Now uploads will continue as intended. + + https://github.com/cs3org/reva/pull/1941 + + * Change #2210: Fix app provider new file creation and improved error codes + + We've fixed the behavior for the app provider when creating new files. Previously the app + provider would overwrite already existing files when creating a new file, this is now handled + and prevented. The new file endpoint accepted a path to a file, but this does not work for spaces. + Therefore we now use the resource id of the folder where the file should be created and a filename + to create the new file. Also the app provider returns more useful error codes in a lot of cases. + + https://github.com/cs3org/reva/pull/2210 + + * Enhancement #2217: OIDC auth driver for ESCAPE IAM + + This enhancement allows for oidc token authentication via the ESCAPE IAM service. + Authentication relies on mappings of ESCAPE IAM groups to REVA users. For a valid token, if at + the most one group from the groups claim is mapped to one REVA user, authentication can take + place. + + https://github.com/cs3org/reva/pull/2217 + + * Enhancement #2256: Return user type in the response of the ocs GET user call + + https://github.com/cs3org/reva/pull/2256 + + * Enhancement #2315: Add new attributes to public link propfinds + + Added a new property "oc:signature-auth" to public link propfinds. This is a necessary change + to be able to support archive downloads in password protected public links. + + https://github.com/cs3org/reva/pull/2315 + + * Enhancement #2740: Implement space membership endpoints + + Implemented endpoints to add and remove members to spaces. + + https://github.com/owncloud/ocis/issues/2740 + https://github.com/cs3org/reva/pull/2250 + + * Enhancement #2252: Add the xattr sys.acl to SysACL (eosgrpc) + + https://github.com/cs3org/reva/pull/2252 + + * Enhancement #2314: OIDC: fallback if IDP doesn't provide "preferred_username" claim + + Some IDPs don't support the "preferred_username" claim. Fallback to the "email" claim in that + case. + + https://github.com/cs3org/reva/pull/2314 + + Changelog for reva 1.16.0 (2021-11-19) ======================================= diff --git a/RELEASE_DATE b/RELEASE_DATE index 15e3b281a6..3b6b771b94 100644 --- a/RELEASE_DATE +++ b/RELEASE_DATE @@ -1 +1 @@ -2021-11-19 \ No newline at end of file +2021-12-09 \ No newline at end of file diff --git a/VERSION b/VERSION index 71bd5d9ee6..73d74673c7 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.16.0 \ No newline at end of file +1.17.0 \ No newline at end of file diff --git a/changelog/unreleased/app-abspath.md b/changelog/1.17.0_2021-12-09/app-abspath.md similarity index 100% rename from changelog/unreleased/app-abspath.md rename to changelog/1.17.0_2021-12-09/app-abspath.md diff --git a/changelog/unreleased/app-provider-new-file.md b/changelog/1.17.0_2021-12-09/app-provider-new-file.md similarity index 100% rename from changelog/unreleased/app-provider-new-file.md rename to changelog/1.17.0_2021-12-09/app-provider-new-file.md diff --git a/changelog/unreleased/fix-content-disposition.md b/changelog/1.17.0_2021-12-09/fix-content-disposition.md similarity index 100% rename from changelog/unreleased/fix-content-disposition.md rename to changelog/1.17.0_2021-12-09/fix-content-disposition.md diff --git a/changelog/unreleased/fix-propfind-sharetype.md b/changelog/1.17.0_2021-12-09/fix-propfind-sharetype.md similarity index 100% rename from changelog/unreleased/fix-propfind-sharetype.md rename to changelog/1.17.0_2021-12-09/fix-propfind-sharetype.md diff --git a/changelog/unreleased/fix-public-link-wopi.md b/changelog/1.17.0_2021-12-09/fix-public-link-wopi.md similarity index 100% rename from changelog/unreleased/fix-public-link-wopi.md rename to changelog/1.17.0_2021-12-09/fix-public-link-wopi.md diff --git a/changelog/unreleased/fix-share-recyclebin.md b/changelog/1.17.0_2021-12-09/fix-share-recyclebin.md similarity index 100% rename from changelog/unreleased/fix-share-recyclebin.md rename to changelog/1.17.0_2021-12-09/fix-share-recyclebin.md diff --git a/changelog/unreleased/fix-skip-early-empty-file-creation.md b/changelog/1.17.0_2021-12-09/fix-skip-early-empty-file-creation.md similarity index 100% rename from changelog/unreleased/fix-skip-early-empty-file-creation.md rename to changelog/1.17.0_2021-12-09/fix-skip-early-empty-file-creation.md diff --git a/changelog/unreleased/iodc-escape-auth.md b/changelog/1.17.0_2021-12-09/iodc-escape-auth.md similarity index 100% rename from changelog/unreleased/iodc-escape-auth.md rename to changelog/1.17.0_2021-12-09/iodc-escape-auth.md diff --git a/changelog/unreleased/ocs-user-type.md b/changelog/1.17.0_2021-12-09/ocs-user-type.md similarity index 100% rename from changelog/unreleased/ocs-user-type.md rename to changelog/1.17.0_2021-12-09/ocs-user-type.md diff --git a/changelog/unreleased/public-link-propfind.md b/changelog/1.17.0_2021-12-09/public-link-propfind.md similarity index 100% rename from changelog/unreleased/public-link-propfind.md rename to changelog/1.17.0_2021-12-09/public-link-propfind.md diff --git a/changelog/unreleased/space-membership.md b/changelog/1.17.0_2021-12-09/space-membership.md similarity index 100% rename from changelog/unreleased/space-membership.md rename to changelog/1.17.0_2021-12-09/space-membership.md diff --git a/changelog/unreleased/sysacl-from-xattr.md b/changelog/1.17.0_2021-12-09/sysacl-from-xattr.md similarity index 100% rename from changelog/unreleased/sysacl-from-xattr.md rename to changelog/1.17.0_2021-12-09/sysacl-from-xattr.md diff --git a/changelog/unreleased/tus-upload-with-transfer-token-only.md b/changelog/1.17.0_2021-12-09/tus-upload-with-transfer-token-only.md similarity index 100% rename from changelog/unreleased/tus-upload-with-transfer-token-only.md rename to changelog/1.17.0_2021-12-09/tus-upload-with-transfer-token-only.md diff --git a/changelog/unreleased/user-claim-fallback.md b/changelog/1.17.0_2021-12-09/user-claim-fallback.md similarity index 100% rename from changelog/unreleased/user-claim-fallback.md rename to changelog/1.17.0_2021-12-09/user-claim-fallback.md diff --git a/changelog/NOTE.md b/changelog/NOTE.md index 031de420a3..07b1251bac 100644 --- a/changelog/NOTE.md +++ b/changelog/NOTE.md @@ -1,273 +1,121 @@ -Changelog for reva 1.16.0 (2021-11-19) +Changelog for reva 1.17.0 (2021-12-09) ======================================= -The following sections list the changes in reva 1.16.0 relevant to +The following sections list the changes in reva 1.17.0 relevant to reva users. The changes are ordered by importance. Summary ------- - * Fix #2245: Don't announce search-files capability - * Fix #2247: Merge user ACLs from EOS to sys ACLs - * Fix #2279: Return the inode of the version folder for files when listing in EOS - * Fix #2294: Fix HTTP return code when path is invalid - * Fix #2231: Fix share permission on a single file in sql share driver (cbox pkg) - * Fix #2230: Fix open by default app and expose default app - * Fix #2265: Fix nil pointer exception when resolving members of a group (rest driver) - * Fix #1214: Fix restoring versions - * Fix #2254: Fix spaces propfind - * Fix #2260: Fix unset quota xattr on darwin - * Fix #5776: Enforce permissions in public share apps - * Fix #2767: Fix status code for WebDAV mkcol requests where an ancestor is missing - * Fix #2287: Add public link access via mount-ID:token/relative-path to the scope - * Fix #2244: Fix the permissions response for shared files in the cbox sql driver - * Enh #2219: Add virtual view tests - * Enh #2230: Add priority to app providers - * Enh #2258: Improved error messages from the AppProviders - * Enh #2119: Add authprovider owncloudsql - * Enh #2211: Enhance the cbox share sql driver to store accepted group shares - * Enh #2212: Filter root path according to the agent that makes the request - * Enh #2237: Skip get user call in eosfs in case previous ones also failed - * Enh #2266: Callback for the EOS UID cache to retry fetch for failed keys - * Enh #2215: Aggregrate resource info properties for virtual views - * Enh #2271: Revamp the favorite manager and add the cbox sql driver - * Enh #2248: Cache whether a user home was created or not - * Enh #2282: Return a proper NOT_FOUND error when a user or group is not found - * Enh #2268: Add the reverseproxy http service - * Enh #2207: Enable users to list all spaces - * Enh #2286: Add trace ID to middleware loggers - * Enh #2251: Mentix service inference - * Enh #2218: Allow filtering of mime types supported by app providers - * Enh #2213: Add public link share type to propfind response - * Enh #2253: Support the file editor role for public links - * Enh #2208: Reduce redundant stat calls when statting by resource ID - * Enh #2235: Specify a list of allowed folders/files to be archived - * Enh #2267: Restrict the paths where share creation is allowed + * Fix #2305: Make sure /app/new takes `target` as absolute path + * Fix #2303: Fix content disposition header for public links files + * Fix #2316: Fix the share types in propfinds + * Fix #2803: Fix app provider for editor public links + * Fix #2298: Remove share refs from trashbin + * Fix #2309: Remove early finish for zero byte file uploads + * Fix #1941: Fix TUS uploads with transfer token only + * Chg #2210: Fix app provider new file creation and improved error codes + * Enh #2217: OIDC auth driver for ESCAPE IAM + * Enh #2256: Return user type in the response of the ocs GET user call + * Enh #2315: Add new attributes to public link propfinds + * Enh #2740: Implement space membership endpoints * Enh #2252: Add the xattr sys.acl to SysACL (eosgrpc) - * Enh #2239: Update toml configs + * Enh #2314: OIDC: fallback if IDP doesn't provide "preferred_username" claim Details ------- - * Bugfix #2245: Don't announce search-files capability + * Bugfix #2305: Make sure /app/new takes `target` as absolute path - The `dav.reports` capability contained a `search-files` report which is currently not - implemented. We removed it from the defaults. + A mini-PR to make the `target` parameter absolute (by prepending `/` if missing). - https://github.com/cs3org/reva/pull/2245 + https://github.com/cs3org/reva/pull/2305 - * Bugfix #2247: Merge user ACLs from EOS to sys ACLs + * Bugfix #2303: Fix content disposition header for public links files - https://github.com/cs3org/reva/pull/2247 + https://github.com/cs3org/reva/pull/2303 + https://github.com/cs3org/reva/pull/2297 + https://github.com/cs3org/reva/pull/2332 + https://github.com/cs3org/reva/pull/2346 - * Bugfix #2279: Return the inode of the version folder for files when listing in EOS + * Bugfix #2316: Fix the share types in propfinds - https://github.com/cs3org/reva/pull/2279 + The share types for public links were not correctly added to propfinds. - * Bugfix #2294: Fix HTTP return code when path is invalid + https://github.com/cs3org/reva/pull/2316 - Before when a path was invalid, the archiver returned a 500 error code. Now this is fixed and - returns a 404 code. + * Bugfix #2803: Fix app provider for editor public links - https://github.com/cs3org/reva/pull/2294 + Fixed opening the app provider in public links with the editor permission. The app provider + failed to open the file in read write mode. - * Bugfix #2231: Fix share permission on a single file in sql share driver (cbox pkg) + https://github.com/owncloud/ocis/issues/2803 + https://github.com/cs3org/reva/pull/2310 - https://github.com/cs3org/reva/pull/2231 + * Bugfix #2298: Remove share refs from trashbin - * Bugfix #2230: Fix open by default app and expose default app + https://github.com/cs3org/reva/pull/2298 - We've fixed the open by default app name behaviour which previously only worked, if the default - app was configured by the provider address. We also now expose the default app on the - `/app/list` endpoint to clients. + * Bugfix #2309: Remove early finish for zero byte file uploads - https://github.com/cs3org/reva/issues/2230 - https://github.com/cs3org/cs3apis/pull/157 + We've fixed the upload of zero byte files by removing the early upload finishing mechanism. - * Bugfix #2265: Fix nil pointer exception when resolving members of a group (rest driver) + https://github.com/cs3org/reva/issues/2309 + https://github.com/owncloud/ocis/issues/2609 - https://github.com/cs3org/reva/pull/2265 + * Bugfix #1941: Fix TUS uploads with transfer token only - * Bugfix #1214: Fix restoring versions + TUS uploads had been stopped when the user JWT token expired, even if only the transfer token + should be validated. Now uploads will continue as intended. - Restoring a version would not remove that version from the version list. Now the behavior is - compatible to ownCloud 10. + https://github.com/cs3org/reva/pull/1941 - https://github.com/owncloud/ocis/issues/1214 - https://github.com/cs3org/reva/pull/2270 + * Change #2210: Fix app provider new file creation and improved error codes - * Bugfix #2254: Fix spaces propfind + We've fixed the behavior for the app provider when creating new files. Previously the app + provider would overwrite already existing files when creating a new file, this is now handled + and prevented. The new file endpoint accepted a path to a file, but this does not work for spaces. + Therefore we now use the resource id of the folder where the file should be created and a filename + to create the new file. Also the app provider returns more useful error codes in a lot of cases. - Fixed the deep listing of spaces. + https://github.com/cs3org/reva/pull/2210 - https://github.com/cs3org/reva/pull/2254 + * Enhancement #2217: OIDC auth driver for ESCAPE IAM - * Bugfix #2260: Fix unset quota xattr on darwin + This enhancement allows for oidc token authentication via the ESCAPE IAM service. + Authentication relies on mappings of ESCAPE IAM groups to REVA users. For a valid token, if at + the most one group from the groups claim is mapped to one REVA user, authentication can take + place. - Unset quota attributes were creating errors in the logfile on darwin. + https://github.com/cs3org/reva/pull/2217 - https://github.com/cs3org/reva/pull/2260 + * Enhancement #2256: Return user type in the response of the ocs GET user call - * Bugfix #5776: Enforce permissions in public share apps + https://github.com/cs3org/reva/pull/2256 - A receiver of a read-only public share could still edit files via apps like Collabora. These - changes enforce the share permissions in apps used on publicly shared resources. + * Enhancement #2315: Add new attributes to public link propfinds - https://github.com/owncloud/web/issues/5776 - https://github.com/owncloud/ocis/issues/2479 - https://github.com/cs3org/reva/pull/22142214 + Added a new property "oc:signature-auth" to public link propfinds. This is a necessary change + to be able to support archive downloads in password protected public links. - * Bugfix #2767: Fix status code for WebDAV mkcol requests where an ancestor is missing + https://github.com/cs3org/reva/pull/2315 - We've fixed the status code to 409 according to the WebDAV standard for MKCOL requests where an - ancestor is missing. Previously these requests would fail with an different error code (eg. - 500) because of storage driver limitations (eg. oCIS FS cannot handle recursive creation of - directories). + * Enhancement #2740: Implement space membership endpoints - https://github.com/owncloud/ocis/issues/2767 - https://github.com/cs3org/reva/pull/2293 + Implemented endpoints to add and remove members to spaces. - * Bugfix #2287: Add public link access via mount-ID:token/relative-path to the scope - - https://github.com/cs3org/reva/pull/2287 - - * Bugfix #2244: Fix the permissions response for shared files in the cbox sql driver - - https://github.com/cs3org/reva/pull/2244 - - * Enhancement #2219: Add virtual view tests - - https://github.com/cs3org/reva/pull/2219 - - * Enhancement #2230: Add priority to app providers - - Before the order of the list returned by the method FindProviders of app providers depended - from the order in which the app provider registered themselves. Now, it is possible to specify a - priority for each app provider, and even if an app provider re-register itself (for example - after a restart), the order is kept. - - https://github.com/cs3org/reva/pull/2230 - https://github.com/cs3org/cs3apis/pull/157 - https://github.com/cs3org/reva/pull/2263 - - * Enhancement #2258: Improved error messages from the AppProviders - - Some rather cryptic messages are now hidden to users, and some others are made more - user-friendly. Support for multiple locales is still missing and out of scope for now. - - https://github.com/cs3org/reva/pull/2258 - - * Enhancement #2119: Add authprovider owncloudsql - - We added an authprovider that can be configured to authenticate against an owncloud classic - mysql database. It verifies the password from the oc_users table. - - https://github.com/cs3org/reva/pull/2119 - - * Enhancement #2211: Enhance the cbox share sql driver to store accepted group shares - - https://github.com/cs3org/reva/pull/2211 - - * Enhancement #2212: Filter root path according to the agent that makes the request - - https://github.com/cs3org/reva/pull/2212 - - * Enhancement #2237: Skip get user call in eosfs in case previous ones also failed - - https://github.com/cs3org/reva/pull/2237 - - * Enhancement #2266: Callback for the EOS UID cache to retry fetch for failed keys - - https://github.com/cs3org/reva/pull/2266 - - * Enhancement #2215: Aggregrate resource info properties for virtual views - - https://github.com/cs3org/reva/pull/2215 - - * Enhancement #2271: Revamp the favorite manager and add the cbox sql driver - - https://github.com/cs3org/reva/pull/2271 - - * Enhancement #2248: Cache whether a user home was created or not - - Previously, on every call, we used to stat the user home to make sure that it existed. Now we cache - it for a given amount of time so as to avoid repeated calls. - - https://github.com/cs3org/reva/pull/2248 - - * Enhancement #2282: Return a proper NOT_FOUND error when a user or group is not found - - https://github.com/cs3org/reva/pull/2282 - - * Enhancement #2268: Add the reverseproxy http service - - This PR adds an HTTP service which does the job of authenticating incoming requests via the reva - middleware before forwarding them to the respective backends. This is useful for extensions - which do not have the auth mechanisms. - - https://github.com/cs3org/reva/pull/2268 - - * Enhancement #2207: Enable users to list all spaces - - Added a permission check if the user has the `list-all-spaces` permission. This enables users - to list all spaces, even those which they are not members of. - - https://github.com/cs3org/reva/pull/2207 - - * Enhancement #2286: Add trace ID to middleware loggers - - https://github.com/cs3org/reva/pull/2286 - - * Enhancement #2251: Mentix service inference - - Previously, 4 different services per site had to be created in the GOCDB. This PR removes this - redundancy by infering all endpoints from a single service entity, making site - administration a lot easier. - - https://github.com/cs3org/reva/pull/2251 - - * Enhancement #2218: Allow filtering of mime types supported by app providers - - https://github.com/cs3org/reva/pull/2218 - - * Enhancement #2213: Add public link share type to propfind response - - Added share type for public links to propfind responses. - - https://github.com/cs3org/reva/pull/2213 - https://github.com/cs3org/reva/pull/2257 - - * Enhancement #2253: Support the file editor role for public links - - https://github.com/cs3org/reva/pull/2253 - - * Enhancement #2208: Reduce redundant stat calls when statting by resource ID - - https://github.com/cs3org/reva/pull/2208 - - * Enhancement #2235: Specify a list of allowed folders/files to be archived - - Adds a configuration to the archiver service in order to specify a list of folders (as regex) - that can be archived. - - https://github.com/cs3org/reva/pull/2235 - - * Enhancement #2267: Restrict the paths where share creation is allowed - - This PR limits share creation to certain specified paths. These can be useful when users have - access to global spaces and virtual views but these should not be sharable. - - https://github.com/cs3org/reva/pull/2267 + https://github.com/owncloud/ocis/issues/2740 + https://github.com/cs3org/reva/pull/2250 * Enhancement #2252: Add the xattr sys.acl to SysACL (eosgrpc) https://github.com/cs3org/reva/pull/2252 - * Enhancement #2239: Update toml configs + * Enhancement #2314: OIDC: fallback if IDP doesn't provide "preferred_username" claim - We updated the local and drone configurations, cleanad up the example configs and removed the - reva gen subcommand which was generating outdated config. + Some IDPs don't support the "preferred_username" claim. Fallback to the "email" claim in that + case. - https://github.com/cs3org/reva/pull/2239 + https://github.com/cs3org/reva/pull/2314 diff --git a/docs/content/en/docs/changelog/1.17.0/_index.md b/docs/content/en/docs/changelog/1.17.0/_index.md new file mode 100644 index 0000000000..1e55092ca1 --- /dev/null +++ b/docs/content/en/docs/changelog/1.17.0/_index.md @@ -0,0 +1,130 @@ + +--- +title: "v1.17.0" +linkTitle: "v1.17.0" +weight: 40 +description: > + Changelog for Reva v1.17.0 (2021-12-09) +--- + +Changelog for reva 1.17.0 (2021-12-09) +======================================= + +The following sections list the changes in reva 1.17.0 relevant to +reva users. The changes are ordered by importance. + +Summary +------- + + * Fix #2305: Make sure /app/new takes `target` as absolute path + * Fix #2303: Fix content disposition header for public links files + * Fix #2316: Fix the share types in propfinds + * Fix #2803: Fix app provider for editor public links + * Fix #2298: Remove share refs from trashbin + * Fix #2309: Remove early finish for zero byte file uploads + * Fix #1941: Fix TUS uploads with transfer token only + * Chg #2210: Fix app provider new file creation and improved error codes + * Enh #2217: OIDC auth driver for ESCAPE IAM + * Enh #2256: Return user type in the response of the ocs GET user call + * Enh #2315: Add new attributes to public link propfinds + * Enh #2740: Implement space membership endpoints + * Enh #2252: Add the xattr sys.acl to SysACL (eosgrpc) + * Enh #2314: OIDC: fallback if IDP doesn't provide "preferred_username" claim + +Details +------- + + * Bugfix #2305: Make sure /app/new takes `target` as absolute path + + A mini-PR to make the `target` parameter absolute (by prepending `/` if missing). + + https://github.com/cs3org/reva/pull/2305 + + * Bugfix #2303: Fix content disposition header for public links files + + https://github.com/cs3org/reva/pull/2303 + https://github.com/cs3org/reva/pull/2297 + https://github.com/cs3org/reva/pull/2332 + https://github.com/cs3org/reva/pull/2346 + + * Bugfix #2316: Fix the share types in propfinds + + The share types for public links were not correctly added to propfinds. + + https://github.com/cs3org/reva/pull/2316 + + * Bugfix #2803: Fix app provider for editor public links + + Fixed opening the app provider in public links with the editor permission. The app provider + failed to open the file in read write mode. + + https://github.com/owncloud/ocis/issues/2803 + https://github.com/cs3org/reva/pull/2310 + + * Bugfix #2298: Remove share refs from trashbin + + https://github.com/cs3org/reva/pull/2298 + + * Bugfix #2309: Remove early finish for zero byte file uploads + + We've fixed the upload of zero byte files by removing the early upload finishing mechanism. + + https://github.com/cs3org/reva/issues/2309 + https://github.com/owncloud/ocis/issues/2609 + + * Bugfix #1941: Fix TUS uploads with transfer token only + + TUS uploads had been stopped when the user JWT token expired, even if only the transfer token + should be validated. Now uploads will continue as intended. + + https://github.com/cs3org/reva/pull/1941 + + * Change #2210: Fix app provider new file creation and improved error codes + + We've fixed the behavior for the app provider when creating new files. Previously the app + provider would overwrite already existing files when creating a new file, this is now handled + and prevented. The new file endpoint accepted a path to a file, but this does not work for spaces. + Therefore we now use the resource id of the folder where the file should be created and a filename + to create the new file. Also the app provider returns more useful error codes in a lot of cases. + + https://github.com/cs3org/reva/pull/2210 + + * Enhancement #2217: OIDC auth driver for ESCAPE IAM + + This enhancement allows for oidc token authentication via the ESCAPE IAM service. + Authentication relies on mappings of ESCAPE IAM groups to REVA users. For a valid token, if at + the most one group from the groups claim is mapped to one REVA user, authentication can take + place. + + https://github.com/cs3org/reva/pull/2217 + + * Enhancement #2256: Return user type in the response of the ocs GET user call + + https://github.com/cs3org/reva/pull/2256 + + * Enhancement #2315: Add new attributes to public link propfinds + + Added a new property "oc:signature-auth" to public link propfinds. This is a necessary change + to be able to support archive downloads in password protected public links. + + https://github.com/cs3org/reva/pull/2315 + + * Enhancement #2740: Implement space membership endpoints + + Implemented endpoints to add and remove members to spaces. + + https://github.com/owncloud/ocis/issues/2740 + https://github.com/cs3org/reva/pull/2250 + + * Enhancement #2252: Add the xattr sys.acl to SysACL (eosgrpc) + + https://github.com/cs3org/reva/pull/2252 + + * Enhancement #2314: OIDC: fallback if IDP doesn't provide "preferred_username" claim + + Some IDPs don't support the "preferred_username" claim. Fallback to the "email" claim in that + case. + + https://github.com/cs3org/reva/pull/2314 + + From 778de37266ff27af25023538ca8aa28fe68a0150 Mon Sep 17 00:00:00 2001 From: Michael Barz Date: Sun, 12 Dec 2021 16:12:13 +0100 Subject: [PATCH 13/28] handle non existent spaces gracefully (#2354) --- changelog/unreleased/update-handle-empty-spaces.md | 5 +++++ pkg/storage/utils/decomposedfs/spaces.go | 13 ++++++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 changelog/unreleased/update-handle-empty-spaces.md diff --git a/changelog/unreleased/update-handle-empty-spaces.md b/changelog/unreleased/update-handle-empty-spaces.md new file mode 100644 index 0000000000..6ee2ebe634 --- /dev/null +++ b/changelog/unreleased/update-handle-empty-spaces.md @@ -0,0 +1,5 @@ +Change: Return not found when updating non existent space + +If a spaceid of a space which is updated doesn't exist, handle it as a not found error. + +https://github.com/cs3org/reva/pull/2354 diff --git a/pkg/storage/utils/decomposedfs/spaces.go b/pkg/storage/utils/decomposedfs/spaces.go index 8c61ecf1e1..b34bb57f65 100644 --- a/pkg/storage/utils/decomposedfs/spaces.go +++ b/pkg/storage/utils/decomposedfs/spaces.go @@ -254,7 +254,12 @@ func (fs *Decomposedfs) UpdateStorageSpace(ctx context.Context, req *provider.Up } if len(matches) != 1 { - return nil, fmt.Errorf("update space failed: found %d matching spaces", len(matches)) + return &provider.UpdateStorageSpaceResponse{ + Status: &v1beta11.Status{ + Code: v1beta11.Code_CODE_NOT_FOUND, + Message: fmt.Sprintf("update space failed: found %d matching spaces", len(matches)), + }, + }, nil } target, err := os.Readlink(matches[0]) @@ -267,6 +272,12 @@ func (fs *Decomposedfs) UpdateStorageSpace(ctx context.Context, req *provider.Up return nil, err } + u, ok := ctxpkg.ContextGetUser(ctx) + if !ok { + return nil, fmt.Errorf("decomposedfs: spaces: contextual user not found") + } + space.Owner = u + if space.Name != "" { if err := node.SetMetadata(xattrs.SpaceNameAttr, space.Name); err != nil { return nil, err From 7e9eff358991d9bb6e63418c940cfa5b0fe90355 Mon Sep 17 00:00:00 2001 From: Swikriti Tripathi <41103328+SwikritiT@users.noreply.github.com> Date: Mon, 13 Dec 2021 21:30:18 +0545 Subject: [PATCH 14/28] Bump core commit id for tests (#2365) --- .drone.env | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.drone.env b/.drone.env index cce5230458..c8ba576897 100644 --- a/.drone.env +++ b/.drone.env @@ -1,3 +1,3 @@ # The test runner source for API tests -CORE_COMMITID=4bbd91de68aefdf94c03d2920a3353702f856280 +CORE_COMMITID=5f98837bd95d75660fc9fbc9a8802f7db8793a89 CORE_BRANCH=acceptance-test-changes-waiting-2021-11 From 30b629ed978d9f5252c5181d0b9e85cd2fb55f27 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 Dec 2021 21:15:42 +0530 Subject: [PATCH 15/28] [Build-deps]: Bump github.com/minio/minio-go/v7 from 7.0.16 to 7.0.18 (#2363) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 167002151e..2f0bdf11aa 100644 --- a/go.mod +++ b/go.mod @@ -41,7 +41,7 @@ require ( github.com/juliangruber/go-intersect v1.1.0 github.com/mattn/go-sqlite3 v1.14.9 github.com/mileusna/useragent v1.0.2 - github.com/minio/minio-go/v7 v7.0.16 + github.com/minio/minio-go/v7 v7.0.18 github.com/mitchellh/copystructure v1.2.0 // indirect github.com/mitchellh/go-testing-interface v1.14.1 // indirect github.com/mitchellh/mapstructure v1.4.3 diff --git a/go.sum b/go.sum index dd5a0265b6..6ee774d844 100644 --- a/go.sum +++ b/go.sum @@ -468,8 +468,8 @@ github.com/mileusna/useragent v1.0.2 h1:DgVKtiPnjxlb73z9bCwgdUvU2nQNQ97uhgfO8l9u github.com/mileusna/useragent v1.0.2/go.mod h1:3d8TOmwL/5I8pJjyVDteHtgDGcefrFUX4ccGOMKNYYc= github.com/minio/md5-simd v1.1.0 h1:QPfiOqlZH+Cj9teu0t9b1nTBfPbyTl16Of5MeuShdK4= github.com/minio/md5-simd v1.1.0/go.mod h1:XpBqgZULrMYD3R+M28PcmP0CkI7PEMzB3U77ZrKZ0Gw= -github.com/minio/minio-go/v7 v7.0.16 h1:GspaSBS8lOuEUCAqMe0W3UxSoyOA4b4F8PTspRVI+k4= -github.com/minio/minio-go/v7 v7.0.16/go.mod h1:pUV0Pc+hPd1nccgmzQF/EXh48l/Z/yps6QPF1aaie4g= +github.com/minio/minio-go/v7 v7.0.18 h1:fncn6iacnK+i2uYfNc5aVPG7bEqQH0nU4yAGMSunY0w= +github.com/minio/minio-go/v7 v7.0.18/go.mod h1:SyQ1IFeJuaa+eV5yEDxW7hYE1s5VVq5sgImDe27R+zg= github.com/minio/sha256-simd v0.1.1 h1:5QHSlgo3nt5yKOJrC7W8w7X+NFl8cMPZm96iu8kKUJU= github.com/minio/sha256-simd v0.1.1/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= From 2fae455725c1652349748372421882d49bb6d1db Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 Dec 2021 21:17:23 +0530 Subject: [PATCH 16/28] [Build-deps]: Bump github.com/ReneKroon/ttlcache/v2 from 2.9.0 to 2.10.0 (#2358) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 2f0bdf11aa..086baed2fe 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/Masterminds/goutils v1.1.1 // indirect github.com/Masterminds/semver v1.5.0 // indirect github.com/Masterminds/sprig v2.22.0+incompatible - github.com/ReneKroon/ttlcache/v2 v2.9.0 + github.com/ReneKroon/ttlcache/v2 v2.10.0 github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d // indirect github.com/aws/aws-sdk-go v1.42.19 github.com/beevik/etree v1.1.0 diff --git a/go.sum b/go.sum index 6ee774d844..07b1c13c72 100644 --- a/go.sum +++ b/go.sum @@ -52,8 +52,8 @@ github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAE github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= -github.com/ReneKroon/ttlcache/v2 v2.9.0 h1:NzwfErbifoNA3djEGwQJXKp/386imbyrc6Qmns5IX7c= -github.com/ReneKroon/ttlcache/v2 v2.9.0/go.mod h1:mBxvsNY+BT8qLLd6CuAJubbKo6r0jh3nb5et22bbfGY= +github.com/ReneKroon/ttlcache/v2 v2.10.0 h1:y4g2gs2fSqAugSseq7vUB1jClqzT/e0CjSrMJywoWa8= +github.com/ReneKroon/ttlcache/v2 v2.10.0/go.mod h1:mBxvsNY+BT8qLLd6CuAJubbKo6r0jh3nb5et22bbfGY= github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= From 0771dfa7cfd52585b6d6e67254c37bdcf9fdeaec Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 Dec 2021 21:17:45 +0530 Subject: [PATCH 17/28] [Build-deps]: Bump go.opentelemetry.io/otel/exporters/jaeger (#2362) --- go.mod | 8 ++++---- go.sum | 19 +++++++++++++------ 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/go.mod b/go.mod index 086baed2fe..168ad5d487 100644 --- a/go.mod +++ b/go.mod @@ -65,10 +65,10 @@ require ( go.mongodb.org/mongo-driver v1.7.2 // indirect go.opencensus.io v0.23.0 go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.27.0 - go.opentelemetry.io/otel v1.2.0 - go.opentelemetry.io/otel/exporters/jaeger v1.2.0 - go.opentelemetry.io/otel/sdk v1.2.0 - go.opentelemetry.io/otel/trace v1.2.0 + go.opentelemetry.io/otel v1.3.0 + go.opentelemetry.io/otel/exporters/jaeger v1.3.0 + go.opentelemetry.io/otel/sdk v1.3.0 + go.opentelemetry.io/otel/trace v1.3.0 golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f golang.org/x/sys v0.0.0-20210921065528-437939a70204 diff --git a/go.sum b/go.sum index 07b1c13c72..11ef1e3104 100644 --- a/go.sum +++ b/go.sum @@ -153,6 +153,11 @@ github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9 github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0 h1:TrB8swr/68K7m9CcGut2g3UOihhbcbiMAYiuTXdEih4= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= +github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.2.1 h1:DX7uPQ4WgAWfoh+NGGlbJQswnYIVvz0SRlLS3rPZQDA= +github.com/go-logr/logr v1.2.1/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/stdr v1.2.0 h1:j4LrlVXgrbIWO83mmQUnK0Hi+YnbD+vzrE1z/EphbFE= +github.com/go-logr/stdr v1.2.0/go.mod h1:YkVgnZu1ZjjL7xTxrfm/LLZBfkhTqSR1ydtm6jTKKwI= github.com/go-openapi/analysis v0.0.0-20180825180245-b006789cd277/go.mod h1:k70tL6pCuVxPJOHXQ+wIac1FUrvNkHolPie/cLEU6hI= github.com/go-openapi/analysis v0.17.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik= github.com/go-openapi/analysis v0.18.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik= @@ -666,14 +671,16 @@ go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M= go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.27.0 h1:TON1iU3Y5oIytGQHIejDYLam5uoSMsmA0UV9Yupb5gQ= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.27.0/go.mod h1:T/zQwBldOpoAEpE3HMbLnI8ydESZVz4ggw6Is4FF9LI= -go.opentelemetry.io/otel v1.2.0 h1:YOQDvxO1FayUcT9MIhJhgMyNO1WqoduiyvQHzGN0kUQ= go.opentelemetry.io/otel v1.2.0/go.mod h1:aT17Fk0Z1Nor9e0uisf98LrntPGMnk4frBO9+dkf69I= -go.opentelemetry.io/otel/exporters/jaeger v1.2.0 h1:C/5Egj3MJBXRJi22cSl07suqPqtZLnLFmH//OxETUEc= -go.opentelemetry.io/otel/exporters/jaeger v1.2.0/go.mod h1:KJLFbEMKTNPIfOxcg/WikIozEoKcPgJRz3Ce1vLlM8E= -go.opentelemetry.io/otel/sdk v1.2.0 h1:wKN260u4DesJYhyjxDa7LRFkuhH7ncEVKU37LWcyNIo= -go.opentelemetry.io/otel/sdk v1.2.0/go.mod h1:jNN8QtpvbsKhgaC6V5lHiejMoKD+V8uadoSafgHPx1U= -go.opentelemetry.io/otel/trace v1.2.0 h1:Ys3iqbqZhcf28hHzrm5WAquMkDHNZTUkw7KHbuNjej0= +go.opentelemetry.io/otel v1.3.0 h1:APxLf0eiBwLl+SOXiJJCVYzA1OOJNyAoV8C5RNRyy7Y= +go.opentelemetry.io/otel v1.3.0/go.mod h1:PWIKzi6JCp7sM0k9yZ43VX+T345uNbAkDKwHVjb2PTs= +go.opentelemetry.io/otel/exporters/jaeger v1.3.0 h1:HfydzioALdtcB26H5WHc4K47iTETJCdloL7VN579/L0= +go.opentelemetry.io/otel/exporters/jaeger v1.3.0/go.mod h1:KoYHi1BtkUPncGSRtCe/eh1ijsnePhSkxwzz07vU0Fc= +go.opentelemetry.io/otel/sdk v1.3.0 h1:3278edCoH89MEJ0Ky8WQXVmDQv3FX4ZJ3Pp+9fJreAI= +go.opentelemetry.io/otel/sdk v1.3.0/go.mod h1:rIo4suHNhQwBIPg9axF8V9CA72Wz2mKF1teNrup8yzs= go.opentelemetry.io/otel/trace v1.2.0/go.mod h1:N5FLswTubnxKxOJHM7XZC074qpeEdLy3CgAVsdMucK0= +go.opentelemetry.io/otel/trace v1.3.0 h1:doy8Hzb1RJ+I3yFhtDmwNc7tIyw1tNMOIsyPzp1NOGY= +go.opentelemetry.io/otel/trace v1.3.0/go.mod h1:c/VDhno8888bvQYmbYLqe41/Ldmr/KKunbvWM4/fEjk= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/goleak v1.1.10 h1:z+mqJhf6ss6BSfSM671tgKyZBFPTTJM+HLxnhPC3wu0= From 8236ffa3f824cd7129e086b00c7329c36905d467 Mon Sep 17 00:00:00 2001 From: Willy Kloucek <34452982+wkloucek@users.noreply.github.com> Date: Wed, 15 Dec 2021 08:45:11 +0100 Subject: [PATCH 18/28] fix tests by pointing to the right owncloud/core commit id for tests (#2375) --- .drone.env | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.drone.env b/.drone.env index c8ba576897..71e1a71ad8 100644 --- a/.drone.env +++ b/.drone.env @@ -1,3 +1,3 @@ # The test runner source for API tests -CORE_COMMITID=5f98837bd95d75660fc9fbc9a8802f7db8793a89 +CORE_COMMITID=2987544bfd6f6823df68f6ea392ba41c1ea4f07c CORE_BRANCH=acceptance-test-changes-waiting-2021-11 From f76d428f4bed52eba909cf0a3787f603337354a7 Mon Sep 17 00:00:00 2001 From: Willy Kloucek <34452982+wkloucek@users.noreply.github.com> Date: Wed, 15 Dec 2021 14:27:23 +0100 Subject: [PATCH 19/28] add new file capabilties to ocs for the app provider (#2379) --- .../unreleased/enhancement-add-new-file-capability.md | 8 ++++++++ internal/http/services/owncloud/ocs/data/capabilities.go | 1 + 2 files changed, 9 insertions(+) create mode 100644 changelog/unreleased/enhancement-add-new-file-capability.md diff --git a/changelog/unreleased/enhancement-add-new-file-capability.md b/changelog/unreleased/enhancement-add-new-file-capability.md new file mode 100644 index 0000000000..23805aeff3 --- /dev/null +++ b/changelog/unreleased/enhancement-add-new-file-capability.md @@ -0,0 +1,8 @@ +Enhancement: add new file url of the app provider to the ocs capabilities + +We've added the new file capability of the app provider to the ocs capabilities, so that +clients can discover this url analogous to the app list and file open urls. + +https://github.com/cs3org/reva/pull/2379 +https://github.com/owncloud/ocis/pull/2884 +https://github.com/owncloud/web/pull/5890#issuecomment-993905242 diff --git a/internal/http/services/owncloud/ocs/data/capabilities.go b/internal/http/services/owncloud/ocs/data/capabilities.go index 3c3c693952..81ee4e3320 100644 --- a/internal/http/services/owncloud/ocs/data/capabilities.go +++ b/internal/http/services/owncloud/ocs/data/capabilities.go @@ -117,6 +117,7 @@ type CapabilitiesAppProvider struct { Version string `json:"version" xml:"version" mapstructure:"version"` AppsURL string `json:"apps_url" xml:"apps_url" mapstructure:"apps_url"` OpenURL string `json:"open_url" xml:"open_url" mapstructure:"open_url"` + NewURL string `json:"new_url" xml:"new_url" mapstructure:"new_url"` } // CapabilitiesFiles TODO this is storage specific, not global. What effect do these options have on the clients? From 8c6bad69fc49a83dba356fc30f6703b561da9bd4 Mon Sep 17 00:00:00 2001 From: Swikriti Tripathi <41103328+SwikritiT@users.noreply.github.com> Date: Wed, 15 Dec 2021 19:12:54 +0545 Subject: [PATCH 20/28] Remove test from expected to fail and bump commit id (#2380) --- .drone.env | 2 +- tests/acceptance/expected-failures-on-OCIS-storage.md | 3 --- tests/acceptance/expected-failures-on-S3NG-storage.md | 3 --- 3 files changed, 1 insertion(+), 7 deletions(-) diff --git a/.drone.env b/.drone.env index 71e1a71ad8..b07b2f80cc 100644 --- a/.drone.env +++ b/.drone.env @@ -1,3 +1,3 @@ # The test runner source for API tests -CORE_COMMITID=2987544bfd6f6823df68f6ea392ba41c1ea4f07c +CORE_COMMITID=38ee68e6358443e980ba5e7036cf1fb554443814 CORE_BRANCH=acceptance-test-changes-waiting-2021-11 diff --git a/tests/acceptance/expected-failures-on-OCIS-storage.md b/tests/acceptance/expected-failures-on-OCIS-storage.md index 100f8ae9f8..a509283234 100644 --- a/tests/acceptance/expected-failures-on-OCIS-storage.md +++ b/tests/acceptance/expected-failures-on-OCIS-storage.md @@ -1365,6 +1365,3 @@ _ocs: api compatibility, return correct status code_ ### [Content-type is not multipart/byteranges when downloading file with Range Header](https://github.com/owncloud/ocis/issues/2677) - [apiWebdavOperations/downloadFile.feature:169](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavOperations/downloadFile.feature#L169) - [apiWebdavOperations/downloadFile.feature:170](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavOperations/downloadFile.feature#L170) - -### [send PUT requests to another user's webDav endpoints as normal user](https://github.com/owncloud/ocis/issues/2759) -- [apiAuthWebDav/webDavPUTAuth.feature:40](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiAuthWebDav/webDavPUTAuth.feature#L40) diff --git a/tests/acceptance/expected-failures-on-S3NG-storage.md b/tests/acceptance/expected-failures-on-S3NG-storage.md index 7fc64d6809..9c7bfff96b 100644 --- a/tests/acceptance/expected-failures-on-S3NG-storage.md +++ b/tests/acceptance/expected-failures-on-S3NG-storage.md @@ -1365,6 +1365,3 @@ _ocs: api compatibility, return correct status code_ ### [Content-type is not multipart/byteranges when downloading file with Range Header](https://github.com/owncloud/ocis/issues/2677) - [apiWebdavOperations/downloadFile.feature:169](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavOperations/downloadFile.feature#L169) - [apiWebdavOperations/downloadFile.feature:170](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavOperations/downloadFile.feature#L170) - -### [send PUT requests to another user's webDav endpoints as normal user](https://github.com/owncloud/ocis/issues/2759) -- [apiAuthWebDav/webDavPUTAuth.feature:40](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiAuthWebDav/webDavPUTAuth.feature#L40) From e65efdcb40a0e5c6e12c2943d6e4044e96a875b0 Mon Sep 17 00:00:00 2001 From: Phil Davis Date: Wed, 15 Dec 2021 19:13:23 +0545 Subject: [PATCH 21/28] add .drone.env to CODEOWNERS as it is part of the test files (#2378) --- CODEOWNERS | 1 + 1 file changed, 1 insertion(+) diff --git a/CODEOWNERS b/CODEOWNERS index 4c9822be14..f22f6c60db 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -1,4 +1,5 @@ * @labkode @ishank011 +.drone.env @labkode @ishank011 @glpatcern @cs3org/owncloud-team changelog @labkode @ishank011 @glpatcern @cs3org/owncloud-team examples @labkode @ishank011 @glpatcern @cs3org/owncloud-team tests @labkode @ishank011 @glpatcern @cs3org/owncloud-team From 5cde0187454be9e5de90cca00eedca2473ee82db Mon Sep 17 00:00:00 2001 From: Willy Kloucek <34452982+wkloucek@users.noreply.github.com> Date: Wed, 15 Dec 2021 14:29:08 +0100 Subject: [PATCH 22/28] fix webdav copy for zero byte files (#2374) --- .../fix-webdav-copy-zero-byte-file.md | 9 ++++ internal/http/services/owncloud/ocdav/copy.go | 53 +++++++++---------- 2 files changed, 34 insertions(+), 28 deletions(-) create mode 100644 changelog/unreleased/fix-webdav-copy-zero-byte-file.md diff --git a/changelog/unreleased/fix-webdav-copy-zero-byte-file.md b/changelog/unreleased/fix-webdav-copy-zero-byte-file.md new file mode 100644 index 0000000000..2fc971cd54 --- /dev/null +++ b/changelog/unreleased/fix-webdav-copy-zero-byte-file.md @@ -0,0 +1,9 @@ +Bugfix: Fix webdav copy of zero byte files + +We've fixed the webdav copy action of zero byte files, which was not performed +because the webdav api assumed, that zero byte uploads are created when initiating +the upload, which was recently removed from all storage drivers. Therefore the +webdav api also uploads zero byte files after initiating the upload. + +https://github.com/cs3org/reva/pull/2374 +https://github.com/cs3org/reva/pull/2309 diff --git a/internal/http/services/owncloud/ocdav/copy.go b/internal/http/services/owncloud/ocdav/copy.go index 8663d48c6a..eefb8d74e1 100644 --- a/internal/http/services/owncloud/ocdav/copy.go +++ b/internal/http/services/owncloud/ocdav/copy.go @@ -237,22 +237,21 @@ func (s *svc) executePathCopy(ctx context.Context, client gateway.GatewayAPIClie // 4. do upload - if cp.sourceInfo.GetSize() > 0 { - httpUploadReq, err := rhttp.NewRequest(ctx, "PUT", uploadEP, httpDownloadRes.Body) - if err != nil { - return err - } - httpUploadReq.Header.Set(datagateway.TokenTransportHeader, uploadToken) + httpUploadReq, err := rhttp.NewRequest(ctx, "PUT", uploadEP, httpDownloadRes.Body) + if err != nil { + return err + } + httpUploadReq.Header.Set(datagateway.TokenTransportHeader, uploadToken) - httpUploadRes, err := s.client.Do(httpUploadReq) - if err != nil { - return err - } - defer httpUploadRes.Body.Close() - if httpUploadRes.StatusCode != http.StatusOK { - return err - } + httpUploadRes, err := s.client.Do(httpUploadReq) + if err != nil { + return err + } + defer httpUploadRes.Body.Close() + if httpUploadRes.StatusCode != http.StatusOK { + return err } + } return nil } @@ -457,21 +456,19 @@ func (s *svc) executeSpacesCopy(ctx context.Context, w http.ResponseWriter, clie // 4. do upload - if cp.sourceInfo.GetSize() > 0 { - httpUploadReq, err := rhttp.NewRequest(ctx, http.MethodPut, uploadEP, httpDownloadRes.Body) - if err != nil { - return err - } - httpUploadReq.Header.Set(datagateway.TokenTransportHeader, uploadToken) + httpUploadReq, err := rhttp.NewRequest(ctx, http.MethodPut, uploadEP, httpDownloadRes.Body) + if err != nil { + return err + } + httpUploadReq.Header.Set(datagateway.TokenTransportHeader, uploadToken) - httpUploadRes, err := s.client.Do(httpUploadReq) - if err != nil { - return err - } - defer httpUploadRes.Body.Close() - if httpUploadRes.StatusCode != http.StatusOK { - return err - } + httpUploadRes, err := s.client.Do(httpUploadReq) + if err != nil { + return err + } + defer httpUploadRes.Body.Close() + if httpUploadRes.StatusCode != http.StatusOK { + return err } } return nil From f3c8b621731124c49061c4375566e259809dee02 Mon Sep 17 00:00:00 2001 From: Willy Kloucek <34452982+wkloucek@users.noreply.github.com> Date: Fri, 17 Dec 2021 12:02:16 +0100 Subject: [PATCH 23/28] Implement touch file (#2369) * implement cs3org/cs3apis#154 * use TouchFile for the app provider * add changelog and comments * revert use TouchFile in app provider * fix resource typo Co-authored-by: Giuseppe Lo Presti Co-authored-by: Giuseppe Lo Presti --- .../unreleased/enhancement-add-touch-file.md | 6 ++++ go.mod | 2 +- go.sum | 4 +++ internal/grpc/interceptors/auth/scope.go | 2 ++ .../grpc/interceptors/readonly/readonly.go | 6 +++- .../grpc/services/gateway/storageprovider.go | 19 ++++++++++++ .../publicstorageprovider.go | 13 ++++++++ .../storageprovider/storageprovider.go | 30 +++++++++++++++++++ pkg/auth/scope/publicshare.go | 2 ++ pkg/auth/scope/resourceinfo.go | 2 ++ pkg/auth/scope/share.go | 2 ++ pkg/storage/fs/nextcloud/nextcloud.go | 5 ++++ pkg/storage/fs/owncloud/owncloud.go | 5 ++++ pkg/storage/fs/owncloudsql/owncloudsql.go | 5 ++++ pkg/storage/fs/s3/s3.go | 5 ++++ pkg/storage/storage.go | 1 + .../utils/decomposedfs/decomposedfs.go | 6 ++++ pkg/storage/utils/eosfs/eosfs.go | 23 ++++++++++++++ pkg/storage/utils/localfs/localfs.go | 5 ++++ 19 files changed, 141 insertions(+), 2 deletions(-) create mode 100644 changelog/unreleased/enhancement-add-touch-file.md diff --git a/changelog/unreleased/enhancement-add-touch-file.md b/changelog/unreleased/enhancement-add-touch-file.md new file mode 100644 index 0000000000..8e9c04e0b9 --- /dev/null +++ b/changelog/unreleased/enhancement-add-touch-file.md @@ -0,0 +1,6 @@ +Enhancement: Implement TouchFile from the CS3apis + +We've updated the CS3apis and implemented the TouchFile method. + +https://github.com/cs3org/reva/pull/2369 +https://github.com/cs3org/cs3apis/pull/154 diff --git a/go.mod b/go.mod index 168ad5d487..b5b9d08395 100644 --- a/go.mod +++ b/go.mod @@ -16,7 +16,7 @@ require ( github.com/cheggaaa/pb v1.0.29 github.com/coreos/go-oidc v2.2.1+incompatible github.com/cs3org/cato v0.0.0-20200828125504-e418fc54dd5e - github.com/cs3org/go-cs3apis v0.0.0-20211104090126-8e972dca8304 + github.com/cs3org/go-cs3apis v0.0.0-20211213090556-12c0d565f51d github.com/cubewise-code/go-mime v0.0.0-20200519001935-8c5762b177d8 github.com/eventials/go-tus v0.0.0-20200718001131-45c7ec8f5d59 github.com/gdexlab/go-render v1.0.1 diff --git a/go.sum b/go.sum index 11ef1e3104..c937822ad9 100644 --- a/go.sum +++ b/go.sum @@ -111,8 +111,12 @@ github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSV github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/cs3org/cato v0.0.0-20200828125504-e418fc54dd5e h1:tqSPWQeueWTKnJVMJffz4pz0o1WuQxJ28+5x5JgaHD8= github.com/cs3org/cato v0.0.0-20200828125504-e418fc54dd5e/go.mod h1:XJEZ3/EQuI3BXTp/6DUzFr850vlxq11I6satRtz0YQ4= +github.com/cs3org/go-cs3apis v0.0.0-20210325133324-32b03d75a535 h1:555D8A3ddKqb4OyK9v5mdphw2zDLWKGXOkcnf1RQwTA= +github.com/cs3org/go-cs3apis v0.0.0-20210325133324-32b03d75a535/go.mod h1:UXha4TguuB52H14EMoSsCqDj7k8a/t7g4gVP+bgY5LY= github.com/cs3org/go-cs3apis v0.0.0-20211104090126-8e972dca8304 h1:e/nIPR518vyvrulo9goAZTtYD6gFfu/2/9MDe6mTGcw= github.com/cs3org/go-cs3apis v0.0.0-20211104090126-8e972dca8304/go.mod h1:UXha4TguuB52H14EMoSsCqDj7k8a/t7g4gVP+bgY5LY= +github.com/cs3org/go-cs3apis v0.0.0-20211213090556-12c0d565f51d h1:gnb2ciU4N+RwUug/nwe54wenWi7vSp5bAAjXINlgHZ8= +github.com/cs3org/go-cs3apis v0.0.0-20211213090556-12c0d565f51d/go.mod h1:UXha4TguuB52H14EMoSsCqDj7k8a/t7g4gVP+bgY5LY= github.com/cubewise-code/go-mime v0.0.0-20200519001935-8c5762b177d8 h1:Z9lwXumT5ACSmJ7WGnFl+OMLLjpz5uR2fyz7dC255FI= github.com/cubewise-code/go-mime v0.0.0-20200519001935-8c5762b177d8/go.mod h1:4abs/jPXcmJzYoYGF91JF9Uq9s/KL5n1jvFDix8KcqY= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= diff --git a/internal/grpc/interceptors/auth/scope.go b/internal/grpc/interceptors/auth/scope.go index 8c9a907ce3..8bad148478 100644 --- a/internal/grpc/interceptors/auth/scope.go +++ b/internal/grpc/interceptors/auth/scope.go @@ -241,6 +241,8 @@ func extractRef(req interface{}, hasEditorRole bool) (*provider.Reference, bool) // Write Requests case *provider.CreateContainerRequest: return v.GetRef(), true + case *provider.TouchFileRequest: + return v.GetRef(), true case *provider.DeleteRequest: return v.GetRef(), true case *provider.MoveRequest: diff --git a/internal/grpc/interceptors/readonly/readonly.go b/internal/grpc/interceptors/readonly/readonly.go index f82a7ab46b..d1d8801c2d 100644 --- a/internal/grpc/interceptors/readonly/readonly.go +++ b/internal/grpc/interceptors/readonly/readonly.go @@ -99,7 +99,11 @@ func NewUnary(map[string]interface{}) (grpc.UnaryServerInterceptor, int, error) }, nil case *provider.CreateContainerRequest: return &provider.CreateContainerResponse{ - Status: rstatus.NewPermissionDenied(ctx, nil, "permission denied: tried to create resoure on readonly storage"), + Status: rstatus.NewPermissionDenied(ctx, nil, "permission denied: tried to create resource on read-only storage"), + }, nil + case *provider.TouchFileRequest: + return &provider.TouchFileResponse{ + Status: rstatus.NewPermissionDenied(ctx, nil, "permission denied: tried to create resource on read-only storage"), }, nil case *provider.CreateHomeRequest: return &provider.CreateHomeResponse{ diff --git a/internal/grpc/services/gateway/storageprovider.go b/internal/grpc/services/gateway/storageprovider.go index 66599a324e..cdd622e9c7 100644 --- a/internal/grpc/services/gateway/storageprovider.go +++ b/internal/grpc/services/gateway/storageprovider.go @@ -851,6 +851,25 @@ func (s *svc) createContainer(ctx context.Context, req *provider.CreateContainer return res, nil } +func (s *svc) TouchFile(ctx context.Context, req *provider.TouchFileRequest) (*provider.TouchFileResponse, error) { + c, err := s.find(ctx, req.Ref) + if err != nil { + return &provider.TouchFileResponse{ + Status: status.NewStatusFromErrType(ctx, "TouchFile ref="+req.Ref.String(), err), + }, nil + } + + res, err := c.TouchFile(ctx, req) + if err != nil { + if gstatus.Code(err) == codes.PermissionDenied { + return &provider.TouchFileResponse{Status: &rpc.Status{Code: rpc.Code_CODE_PERMISSION_DENIED}}, nil + } + return nil, errors.Wrap(err, "gateway: error calling TouchFile") + } + + return res, nil +} + // check if the path contains the prefix of the shared folder func (s *svc) inSharedFolder(ctx context.Context, p string) bool { sharedFolder := s.getSharedFolder(ctx) diff --git a/internal/grpc/services/publicstorageprovider/publicstorageprovider.go b/internal/grpc/services/publicstorageprovider/publicstorageprovider.go index c6ec4e983e..80b64f4e99 100644 --- a/internal/grpc/services/publicstorageprovider/publicstorageprovider.go +++ b/internal/grpc/services/publicstorageprovider/publicstorageprovider.go @@ -363,6 +363,19 @@ func (s *service) CreateContainer(ctx context.Context, req *provider.CreateConta return res, nil } +func (s *service) TouchFile(ctx context.Context, req *provider.TouchFileRequest) (*provider.TouchFileResponse, error) { + ref, _, _, st, err := s.translatePublicRefToCS3Ref(ctx, req.Ref) + switch { + case err != nil: + return nil, err + case st != nil: + return &provider.TouchFileResponse{ + Status: st, + }, nil + } + return s.gateway.TouchFile(ctx, &provider.TouchFileRequest{Opaque: req.Opaque, Ref: ref}) +} + func (s *service) Delete(ctx context.Context, req *provider.DeleteRequest) (*provider.DeleteResponse, error) { ctx, span := rtrace.Provider.Tracer("publicstorageprovider").Start(ctx, "Delete") defer span.End() diff --git a/internal/grpc/services/storageprovider/storageprovider.go b/internal/grpc/services/storageprovider/storageprovider.go index aac7f68453..a0d659005a 100644 --- a/internal/grpc/services/storageprovider/storageprovider.go +++ b/internal/grpc/services/storageprovider/storageprovider.go @@ -544,6 +544,36 @@ func (s *service) CreateContainer(ctx context.Context, req *provider.CreateConta return res, nil } +func (s *service) TouchFile(ctx context.Context, req *provider.TouchFileRequest) (*provider.TouchFileResponse, error) { + newRef, err := s.unwrap(ctx, req.Ref) + if err != nil { + return &provider.TouchFileResponse{ + Status: status.NewInternal(ctx, err, "error unwrapping path"), + }, nil + } + if err := s.storage.TouchFile(ctx, newRef); err != nil { + var st *rpc.Status + switch err.(type) { + case errtypes.IsNotFound: + st = status.NewNotFound(ctx, "path not found when touching the file") + case errtypes.AlreadyExists: + st = status.NewAlreadyExists(ctx, err, "file already exists") + case errtypes.PermissionDenied: + st = status.NewPermissionDenied(ctx, err, "permission denied") + default: + st = status.NewInternal(ctx, err, "error touching file: "+req.Ref.String()) + } + return &provider.TouchFileResponse{ + Status: st, + }, nil + } + + res := &provider.TouchFileResponse{ + Status: status.NewOK(ctx), + } + return res, nil +} + func (s *service) Delete(ctx context.Context, req *provider.DeleteRequest) (*provider.DeleteResponse, error) { newRef, err := s.unwrap(ctx, req.Ref) if err != nil { diff --git a/pkg/auth/scope/publicshare.go b/pkg/auth/scope/publicshare.go index b7f7d078b6..7de007ca87 100644 --- a/pkg/auth/scope/publicshare.go +++ b/pkg/auth/scope/publicshare.go @@ -57,6 +57,8 @@ func publicshareScope(ctx context.Context, scope *authpb.Scope, resource interfa // need to return appropriate status codes in the ocs/ocdav layers. case *provider.CreateContainerRequest: return hasRoleEditor(*scope) && checkStorageRef(ctx, &share, v.GetRef()), nil + case *provider.TouchFileRequest: + return hasRoleEditor(*scope) && checkStorageRef(ctx, &share, v.GetRef()), nil case *provider.DeleteRequest: return hasRoleEditor(*scope) && checkStorageRef(ctx, &share, v.GetRef()), nil case *provider.MoveRequest: diff --git a/pkg/auth/scope/resourceinfo.go b/pkg/auth/scope/resourceinfo.go index f5afe94cfe..1a6c41a40f 100644 --- a/pkg/auth/scope/resourceinfo.go +++ b/pkg/auth/scope/resourceinfo.go @@ -55,6 +55,8 @@ func resourceinfoScope(_ context.Context, scope *authpb.Scope, resource interfac // need to return appropriate status codes in the ocs/ocdav layers. case *provider.CreateContainerRequest: return hasRoleEditor(*scope) && checkResourceInfo(&r, v.GetRef()), nil + case *provider.TouchFileRequest: + return hasRoleEditor(*scope) && checkResourceInfo(&r, v.GetRef()), nil case *provider.DeleteRequest: return hasRoleEditor(*scope) && checkResourceInfo(&r, v.GetRef()), nil case *provider.MoveRequest: diff --git a/pkg/auth/scope/share.go b/pkg/auth/scope/share.go index 1e29fd44e1..48683dea17 100644 --- a/pkg/auth/scope/share.go +++ b/pkg/auth/scope/share.go @@ -56,6 +56,8 @@ func shareScope(_ context.Context, scope *authpb.Scope, resource interface{}, lo // need to return appropriate status codes in the ocs/ocdav layers. case *provider.CreateContainerRequest: return checkShareStorageRef(&share, v.GetRef()), nil + case *provider.TouchFileRequest: + return checkShareStorageRef(&share, v.GetRef()), nil case *provider.DeleteRequest: return checkShareStorageRef(&share, v.GetRef()), nil case *provider.MoveRequest: diff --git a/pkg/storage/fs/nextcloud/nextcloud.go b/pkg/storage/fs/nextcloud/nextcloud.go index 7ee908beda..567a880863 100644 --- a/pkg/storage/fs/nextcloud/nextcloud.go +++ b/pkg/storage/fs/nextcloud/nextcloud.go @@ -253,6 +253,11 @@ func (nc *StorageDriver) CreateDir(ctx context.Context, ref *provider.Reference) return err } +// TouchFile as defined in the storage.FS interface +func (nc *StorageDriver) TouchFile(ctx context.Context, ref *provider.Reference) error { + return fmt.Errorf("unimplemented: TouchFile") +} + // Delete as defined in the storage.FS interface func (nc *StorageDriver) Delete(ctx context.Context, ref *provider.Reference) error { bodyStr, err := json.Marshal(ref) diff --git a/pkg/storage/fs/owncloud/owncloud.go b/pkg/storage/fs/owncloud/owncloud.go index 51a1299ec3..51a5ef8b05 100644 --- a/pkg/storage/fs/owncloud/owncloud.go +++ b/pkg/storage/fs/owncloud/owncloud.go @@ -1186,6 +1186,11 @@ func (fs *ocfs) CreateDir(ctx context.Context, ref *provider.Reference) (err err return fs.propagate(ctx, ip) } +// TouchFile as defined in the storage.FS interface +func (fs *ocfs) TouchFile(ctx context.Context, ref *provider.Reference) error { + return fmt.Errorf("unimplemented: TouchFile") +} + func (fs *ocfs) isShareFolderChild(sp string) bool { return strings.HasPrefix(sp, fs.c.ShareFolder) } diff --git a/pkg/storage/fs/owncloudsql/owncloudsql.go b/pkg/storage/fs/owncloudsql/owncloudsql.go index 43db8f3b89..05b929330f 100644 --- a/pkg/storage/fs/owncloudsql/owncloudsql.go +++ b/pkg/storage/fs/owncloudsql/owncloudsql.go @@ -766,6 +766,11 @@ func (fs *owncloudsqlfs) CreateDir(ctx context.Context, ref *provider.Reference) return fs.propagate(ctx, filepath.Dir(ip)) } +// TouchFile as defined in the storage.FS interface +func (fs *owncloudsqlfs) TouchFile(ctx context.Context, ref *provider.Reference) error { + return fmt.Errorf("unimplemented: TouchFile") +} + func (fs *owncloudsqlfs) CreateReference(ctx context.Context, sp string, targetURI *url.URL) error { return errtypes.NotSupported("owncloudsql: operation not supported") } diff --git a/pkg/storage/fs/s3/s3.go b/pkg/storage/fs/s3/s3.go index 39d9fb7d6a..330706aae0 100644 --- a/pkg/storage/fs/s3/s3.go +++ b/pkg/storage/fs/s3/s3.go @@ -326,6 +326,11 @@ func (fs *s3FS) CreateDir(ctx context.Context, ref *provider.Reference) error { return nil } +// TouchFile as defined in the storage.FS interface +func (fs *s3FS) TouchFile(ctx context.Context, ref *provider.Reference) error { + return fmt.Errorf("unimplemented: TouchFile") +} + func (fs *s3FS) Delete(ctx context.Context, ref *provider.Reference) error { log := appctx.GetLogger(ctx) diff --git a/pkg/storage/storage.go b/pkg/storage/storage.go index f43a938152..8b61b6f616 100644 --- a/pkg/storage/storage.go +++ b/pkg/storage/storage.go @@ -32,6 +32,7 @@ type FS interface { GetHome(ctx context.Context) (string, error) CreateHome(ctx context.Context) error CreateDir(ctx context.Context, ref *provider.Reference) error + TouchFile(ctx context.Context, ref *provider.Reference) error Delete(ctx context.Context, ref *provider.Reference) error Move(ctx context.Context, oldRef, newRef *provider.Reference) error GetMD(ctx context.Context, ref *provider.Reference, mdKeys []string) (*provider.ResourceInfo, error) diff --git a/pkg/storage/utils/decomposedfs/decomposedfs.go b/pkg/storage/utils/decomposedfs/decomposedfs.go index 4ebb5c3cb2..6b968febf2 100644 --- a/pkg/storage/utils/decomposedfs/decomposedfs.go +++ b/pkg/storage/utils/decomposedfs/decomposedfs.go @@ -23,6 +23,7 @@ package decomposedfs import ( "context" + "fmt" "io" "net/url" "os" @@ -320,6 +321,11 @@ func (fs *Decomposedfs) CreateDir(ctx context.Context, ref *provider.Reference) return } +// TouchFile as defined in the storage.FS interface +func (fs *Decomposedfs) TouchFile(ctx context.Context, ref *provider.Reference) error { + return fmt.Errorf("unimplemented: TouchFile") +} + // CreateReference creates a reference as a node folder with the target stored in extended attributes // There is no difference between the /Shares folder and normal nodes because the storage is not supposed to be accessible without the storage provider. // In effect everything is a shadow namespace. diff --git a/pkg/storage/utils/eosfs/eosfs.go b/pkg/storage/utils/eosfs/eosfs.go index 3d045dd553..ce62dde0c5 100644 --- a/pkg/storage/utils/eosfs/eosfs.go +++ b/pkg/storage/utils/eosfs/eosfs.go @@ -1214,6 +1214,29 @@ func (fs *eosfs) CreateDir(ctx context.Context, ref *provider.Reference) error { return fs.c.CreateDir(ctx, auth, fn) } +// TouchFile as defined in the storage.FS interface +func (fs *eosfs) TouchFile(ctx context.Context, ref *provider.Reference) error { + log := appctx.GetLogger(ctx) + u, err := getUser(ctx) + if err != nil { + return errors.Wrap(err, "eosfs: no user in ctx") + } + p, err := fs.resolve(ctx, ref) + if err != nil { + return nil + } + + auth, err := fs.getUserAuth(ctx, u, p) + if err != nil { + return err + } + + log.Info().Msgf("eosfs: touch file: path=%s", p) + + fn := fs.wrap(ctx, p) + return fs.c.Touch(ctx, auth, fn) +} + func (fs *eosfs) CreateReference(ctx context.Context, p string, targetURI *url.URL) error { // TODO(labkode): for the time being we only allow creating references // in the virtual share folder to not pollute the nominal user tree. diff --git a/pkg/storage/utils/localfs/localfs.go b/pkg/storage/utils/localfs/localfs.go index 9f807d9ad2..4dc7c37e78 100644 --- a/pkg/storage/utils/localfs/localfs.go +++ b/pkg/storage/utils/localfs/localfs.go @@ -782,6 +782,11 @@ func (fs *localfs) CreateDir(ctx context.Context, ref *provider.Reference) error return fs.propagate(ctx, path.Dir(fn)) } +// TouchFile as defined in the storage.FS interface +func (fs *localfs) TouchFile(ctx context.Context, ref *provider.Reference) error { + return fmt.Errorf("unimplemented: TouchFile") +} + func (fs *localfs) Delete(ctx context.Context, ref *provider.Reference) error { fn, err := fs.resolve(ctx, ref) if err != nil { From 3271cfe782cc93dd68650b8cd51c380cb69bbcdc Mon Sep 17 00:00:00 2001 From: jkoberg Date: Fri, 17 Dec 2021 12:52:18 +0100 Subject: [PATCH 24/28] add TouchFile method to sharesstorageprovider --- .../services/sharesstorageprovider/sharesstorageprovider.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/internal/grpc/services/sharesstorageprovider/sharesstorageprovider.go b/internal/grpc/services/sharesstorageprovider/sharesstorageprovider.go index c15c986d99..790b4ef798 100644 --- a/internal/grpc/services/sharesstorageprovider/sharesstorageprovider.go +++ b/internal/grpc/services/sharesstorageprovider/sharesstorageprovider.go @@ -667,6 +667,10 @@ func (s *service) RemoveGrant(ctx context.Context, req *provider.RemoveGrantRequ return nil, gstatus.Errorf(codes.Unimplemented, "method not implemented") } +func (s *service) TouchFile(ctx context.Context, req *provider.TouchFileRequest) (*provider.TouchFileResponse, error) { + return nil, gstatus.Errorf(codes.Unimplemented, "method not implemented") +} + // GetQuota returns 0 free quota. It is virtual ... the shares may have a different quota ... func (s *service) GetQuota(ctx context.Context, req *provider.GetQuotaRequest) (*provider.GetQuotaResponse, error) { // FIXME use req.Ref to get real quota From f239592db487689707992b65a3d3c4e1317a8a09 Mon Sep 17 00:00:00 2001 From: jkoberg Date: Fri, 17 Dec 2021 14:32:37 +0100 Subject: [PATCH 25/28] fix linting and remove unexpected passes Signed-off-by: jkoberg --- internal/grpc/services/gateway/storageprovider.go | 6 ------ tests/acceptance/expected-failures-on-OCIS-storage.md | 4 ---- tests/acceptance/expected-failures-on-S3NG-storage.md | 4 ---- 3 files changed, 14 deletions(-) diff --git a/internal/grpc/services/gateway/storageprovider.go b/internal/grpc/services/gateway/storageprovider.go index 6e2c2414b6..7f0f6e20eb 100644 --- a/internal/grpc/services/gateway/storageprovider.go +++ b/internal/grpc/services/gateway/storageprovider.go @@ -599,12 +599,6 @@ func (s *svc) TouchFile(ctx context.Context, req *provider.TouchFileRequest) (*p return res, nil } -// check if the path contains the prefix of the shared folder -//func (s *svc) inSharedFolder(ctx context.Context, p string) bool { -//sharedFolder := s.getSharedFolder(ctx) -//return strings.HasPrefix(p, sharedFolder) -//} - func (s *svc) Delete(ctx context.Context, req *provider.DeleteRequest) (*provider.DeleteResponse, error) { // TODO(ishank011): enable deleting references spread across storage providers, eg. /eos var c provider.ProviderAPIClient diff --git a/tests/acceptance/expected-failures-on-OCIS-storage.md b/tests/acceptance/expected-failures-on-OCIS-storage.md index c32d2bb73c..3aed5984c1 100644 --- a/tests/acceptance/expected-failures-on-OCIS-storage.md +++ b/tests/acceptance/expected-failures-on-OCIS-storage.md @@ -562,10 +562,6 @@ Scenario Outline: Retrieving folder quota when quota is set and a file was recei - [apiWebdavProperties1/getQuota.feature:27](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties1/getQuota.feature#L27) - [apiWebdavProperties1/getQuota.feature:28](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties1/getQuota.feature#L28) -#### [cannot get share-types webdav property](https://github.com/owncloud/ocis/issues/567) -- [apiWebdavProperties2/getFileProperties.feature:174](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties2/getFileProperties.feature#L174) -- [apiWebdavProperties2/getFileProperties.feature:175](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties2/getFileProperties.feature#L175) - #### [Private link support](https://github.com/owncloud/product/issues/201) #### [oc:privatelink property not returned in webdav responses](https://github.com/owncloud/product/issues/262) - [apiWebdavProperties2/getFileProperties.feature:232](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties2/getFileProperties.feature#L232) diff --git a/tests/acceptance/expected-failures-on-S3NG-storage.md b/tests/acceptance/expected-failures-on-S3NG-storage.md index bccfe6e2be..36de968d54 100644 --- a/tests/acceptance/expected-failures-on-S3NG-storage.md +++ b/tests/acceptance/expected-failures-on-S3NG-storage.md @@ -540,10 +540,6 @@ Scenario Outline: Retrieving folder quota when quota is set and a file was recei - [apiWebdavProperties1/getQuota.feature:27](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties1/getQuota.feature#L27) - [apiWebdavProperties1/getQuota.feature:28](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties1/getQuota.feature#L28) -#### [cannot get share-types webdav property](https://github.com/owncloud/ocis/issues/567) -- [apiWebdavProperties2/getFileProperties.feature:174](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties2/getFileProperties.feature#L174) -- [apiWebdavProperties2/getFileProperties.feature:175](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties2/getFileProperties.feature#L175) - #### [Private link support](https://github.com/owncloud/product/issues/201) #### [oc:privatelink property not returned in webdav responses](https://github.com/owncloud/product/issues/262) - [apiWebdavProperties2/getFileProperties.feature:232](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties2/getFileProperties.feature#L232) From 8e41ebbf0b70a8f40a6b7c32b7c6c68a93001046 Mon Sep 17 00:00:00 2001 From: jkoberg Date: Fri, 17 Dec 2021 15:19:41 +0100 Subject: [PATCH 26/28] see what fails with lazy change Signed-off-by: jkoberg --- pkg/rhttp/datatx/utils/download/download.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/rhttp/datatx/utils/download/download.go b/pkg/rhttp/datatx/utils/download/download.go index 1062368bfa..0697f80887 100644 --- a/pkg/rhttp/datatx/utils/download/download.go +++ b/pkg/rhttp/datatx/utils/download/download.go @@ -58,7 +58,7 @@ func GetOrHeadFile(w http.ResponseWriter, r *http.Request, fs storage.FS, spaceI ref = &provider.Reference{ ResourceId: &provider.ResourceId{StorageId: storageid, OpaqueId: opaqeid}, // ensure the relative path starts with '.' - Path: utils.MakeRelativePath(fn), + // Path: utils.MakeRelativePath(fn), } } // TODO check preconditions like If-Range, If-Match ... From 758d893e0ac3d6247914bbc4670f15fc9cac42fc Mon Sep 17 00:00:00 2001 From: jkoberg Date: Fri, 17 Dec 2021 15:44:43 +0100 Subject: [PATCH 27/28] Revert "see what fails with lazy change" This reverts commit 8e41ebbf0b70a8f40a6b7c32b7c6c68a93001046. --- pkg/rhttp/datatx/utils/download/download.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/rhttp/datatx/utils/download/download.go b/pkg/rhttp/datatx/utils/download/download.go index 0697f80887..1062368bfa 100644 --- a/pkg/rhttp/datatx/utils/download/download.go +++ b/pkg/rhttp/datatx/utils/download/download.go @@ -58,7 +58,7 @@ func GetOrHeadFile(w http.ResponseWriter, r *http.Request, fs storage.FS, spaceI ref = &provider.Reference{ ResourceId: &provider.ResourceId{StorageId: storageid, OpaqueId: opaqeid}, // ensure the relative path starts with '.' - // Path: utils.MakeRelativePath(fn), + Path: utils.MakeRelativePath(fn), } } // TODO check preconditions like If-Range, If-Match ... From a75182c56565bbac6b9be3150de76d9e4fb75fd9 Mon Sep 17 00:00:00 2001 From: jkoberg Date: Mon, 20 Dec 2021 10:28:33 +0100 Subject: [PATCH 28/28] adjust path when statting public link Signed-off-by: jkoberg --- .../publicstorageprovider.go | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/internal/grpc/services/publicstorageprovider/publicstorageprovider.go b/internal/grpc/services/publicstorageprovider/publicstorageprovider.go index 90e404cb88..b200a3bdcc 100644 --- a/internal/grpc/services/publicstorageprovider/publicstorageprovider.go +++ b/internal/grpc/services/publicstorageprovider/publicstorageprovider.go @@ -153,9 +153,22 @@ func (s *service) translatePublicRefToCS3Ref(ctx context.Context, ref *provider. return nil, "", nil, st, nil } + var path string + switch shareInfo.Type { + case provider.ResourceType_RESOURCE_TYPE_CONTAINER: + // folders point to the folder -> path needs to be added + path = utils.MakeRelativePath(relativePath) + case provider.ResourceType_RESOURCE_TYPE_FILE: + // files already point to the correct id + path = "." + default: + // TODO: can this happen? + // path = utils.MakeRelativePath(relativePath) + } + cs3Ref := &provider.Reference{ ResourceId: shareInfo.Id, - Path: utils.MakeRelativePath(relativePath), + Path: path, } log.Debug().