diff --git a/changelog/unreleased/bump-reva.md b/changelog/unreleased/bump-reva.md new file mode 100644 index 0000000000..a8bbfd69b8 --- /dev/null +++ b/changelog/unreleased/bump-reva.md @@ -0,0 +1,5 @@ +Enhancement: Bump Reva + +bumps reva + +https://github.com/owncloud/ocis/pull/6381 diff --git a/go.mod b/go.mod index 9b9ecc84f2..97e67cbc6d 100644 --- a/go.mod +++ b/go.mod @@ -13,7 +13,7 @@ require ( github.com/coreos/go-oidc v2.2.1+incompatible github.com/coreos/go-oidc/v3 v3.6.0 github.com/cs3org/go-cs3apis v0.0.0-20230516150832-730ac860c71d - github.com/cs3org/reva/v2 v2.13.4-0.20230523132457-4fb99464ab8d + github.com/cs3org/reva/v2 v2.13.4-0.20230525110514-9334e2174492 github.com/disintegration/imaging v1.6.2 github.com/dutchcoders/go-clamd v0.0.0-20170520113014-b970184f4d9e github.com/egirna/icap-client v0.1.1 diff --git a/go.sum b/go.sum index 7f13da01a9..1d8c7e3d54 100644 --- a/go.sum +++ b/go.sum @@ -627,8 +627,8 @@ github.com/crewjam/httperr v0.2.0 h1:b2BfXR8U3AlIHwNeFFvZ+BV1LFvKLlzMjzaTnZMybNo github.com/crewjam/httperr v0.2.0/go.mod h1:Jlz+Sg/XqBQhyMjdDiC+GNNRzZTD7x39Gu3pglZ5oH4= github.com/crewjam/saml v0.4.13 h1:TYHggH/hwP7eArqiXSJUvtOPNzQDyQ7vwmwEqlFWhMc= github.com/crewjam/saml v0.4.13/go.mod h1:igEejV+fihTIlHXYP8zOec3V5A8y3lws5bQBFsTm4gA= -github.com/cs3org/reva/v2 v2.13.4-0.20230523132457-4fb99464ab8d h1:Wuz6lxPY022NP9052zcDFpnqhLkDtik11fYHX1NLF74= -github.com/cs3org/reva/v2 v2.13.4-0.20230523132457-4fb99464ab8d/go.mod h1:jkngU/36YdFNQfFurjgKl8URY2dkhwgJ5gQXt1GUoPw= +github.com/cs3org/reva/v2 v2.13.4-0.20230525110514-9334e2174492 h1:hWJK5O45XN73GVOvRreymiF0lbrHgMcIP4oFkGfuQcg= +github.com/cs3org/reva/v2 v2.13.4-0.20230525110514-9334e2174492/go.mod h1:jkngU/36YdFNQfFurjgKl8URY2dkhwgJ5gQXt1GUoPw= 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/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4= diff --git a/vendor/github.com/cs3org/reva/v2/internal/grpc/services/gateway/storageprovider.go b/vendor/github.com/cs3org/reva/v2/internal/grpc/services/gateway/storageprovider.go index 7c6c6a7205..3ed435acdb 100644 --- a/vendor/github.com/cs3org/reva/v2/internal/grpc/services/gateway/storageprovider.go +++ b/vendor/github.com/cs3org/reva/v2/internal/grpc/services/gateway/storageprovider.go @@ -241,6 +241,11 @@ func (s *svc) ListStorageSpaces(ctx context.Context, req *provider.ListStorageSp // TODO check for allowed filters filters["mask"] = mask } + path := utils.ReadPlainFromOpaque(req.Opaque, "path") + if path != "" { + // TODO check for allowed filters + filters["path"] = path + } for _, f := range req.Filters { switch f.Type { diff --git a/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/propfind/propfind.go b/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/propfind/propfind.go index 3b98811d54..918a28cf08 100644 --- a/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/propfind/propfind.go +++ b/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/propfind/propfind.go @@ -53,6 +53,7 @@ import ( "github.com/rs/zerolog" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/codes" + "golang.org/x/sync/errgroup" "google.golang.org/protobuf/types/known/fieldmaskpb" ) @@ -876,13 +877,67 @@ func ReadPropfind(r io.Reader) (pf XML, status int, err error) { // MultistatusResponse converts a list of resource infos into a multistatus response string func MultistatusResponse(ctx context.Context, pf *XML, mds []*provider.ResourceInfo, publicURL, ns string, linkshares map[string]struct{}, returnMinimal bool) ([]byte, error) { - responses := make([]*ResponseXML, 0, len(mds)) - for i := range mds { - res, err := mdToPropResponse(ctx, pf, mds[i], publicURL, ns, linkshares, returnMinimal) - if err != nil { - return nil, err + g, ctx := errgroup.WithContext(ctx) + + type work struct { + position int + info *provider.ResourceInfo + } + type result struct { + position int + info *ResponseXML + } + workChan := make(chan work, len(mds)) + resultChan := make(chan result, len(mds)) + + // Distribute work + g.Go(func() error { + defer close(workChan) + for i, md := range mds { + select { + case workChan <- work{position: i, info: md}: + case <-ctx.Done(): + return ctx.Err() + } } - responses = append(responses, res) + return nil + }) + + // Spawn workers that'll concurrently work the queue + numWorkers := 50 + if len(mds) < numWorkers { + numWorkers = len(mds) + } + for i := 0; i < numWorkers; i++ { + g.Go(func() error { + for work := range workChan { + res, err := mdToPropResponse(ctx, pf, work.info, publicURL, ns, linkshares, returnMinimal) + if err != nil { + return err + } + select { + case resultChan <- result{position: work.position, info: res}: + case <-ctx.Done(): + return ctx.Err() + } + } + return nil + }) + } + + // Wait for things to settle down, then close results chan + go func() { + _ = g.Wait() // error is checked later + close(resultChan) + }() + + if err := g.Wait(); err != nil { + return nil, err + } + + responses := make([]*ResponseXML, len(mds)) + for res := range resultChan { + responses[res.position] = res.info } msr := NewMultiStatusResponseXML() @@ -904,11 +959,12 @@ func mdToPropResponse(ctx context.Context, pf *XML, md *provider.ResourceInfo, p defer span.End() sublog := appctx.GetLogger(ctx).With().Interface("md", md).Str("ns", ns).Logger() - md.Path = strings.TrimPrefix(md.Path, ns) + id := md.Id + p := strings.TrimPrefix(md.Path, ns) baseURI := ctx.Value(net.CtxKeyBaseURI).(string) - ref := path.Join(baseURI, md.Path) + ref := path.Join(baseURI, p) if md.Type == provider.ResourceType_RESOURCE_TYPE_CONTAINER { ref += "/" } @@ -952,7 +1008,7 @@ func mdToPropResponse(ctx context.Context, pf *XML, md *provider.ResourceInfo, p role := conversions.RoleFromResourcePermissions(md.PermissionSet, ls != nil) - if md.Space != nil && md.Space.SpaceType != "grant" && utils.ResourceIDEqual(md.Space.Root, md.Id) { + if md.Space != nil && md.Space.SpaceType != "grant" && utils.ResourceIDEqual(md.Space.Root, id) { // a space root is never shared shareTypes = "" } @@ -969,8 +1025,8 @@ func mdToPropResponse(ctx context.Context, pf *XML, md *provider.ResourceInfo, p } // replace fileid of /public/{token} mountpoint with grant fileid - if ls != nil && md.Id != nil && md.Id.SpaceId == utils.PublicStorageSpaceID && md.Id.OpaqueId == ls.Token { - md.Id = ls.ResourceId + if ls != nil && id != nil && id.SpaceId == utils.PublicStorageSpaceID && id.OpaqueId == ls.Token { + id = ls.ResourceId } propstatOK := PropstatXML{ @@ -996,12 +1052,12 @@ func mdToPropResponse(ctx context.Context, pf *XML, md *provider.ResourceInfo, p if pf.Allprop != nil { // return all known properties - if md.Id != nil { - id := storagespace.FormatResourceID(*md.Id) + if id != nil { + sid := storagespace.FormatResourceID(*id) appendToOK( - prop.Escaped("oc:id", id), - prop.Escaped("oc:fileid", id), - prop.Escaped("oc:spaceid", md.Id.SpaceId), + prop.Escaped("oc:id", sid), + prop.Escaped("oc:fileid", sid), + prop.Escaped("oc:spaceid", id.SpaceId), ) } @@ -1012,7 +1068,7 @@ func mdToPropResponse(ctx context.Context, pf *XML, md *provider.ResourceInfo, p } // we need to add the shareid if possible - the only way to extract it here is to parse it from the path - if ref, err := storagespace.ParseReference(strings.TrimPrefix(md.Path, "/")); err == nil && ref.GetResourceId().GetSpaceId() == utils.ShareStorageSpaceID { + if ref, err := storagespace.ParseReference(strings.TrimPrefix(p, "/")); err == nil && ref.GetResourceId().GetSpaceId() == utils.ShareStorageSpaceID { appendToOK(prop.Raw("oc:shareid", ref.GetResourceId().GetOpaqueId())) } @@ -1119,14 +1175,14 @@ func mdToPropResponse(ctx context.Context, pf *XML, md *provider.ResourceInfo, p // TODO(jfd): maybe phoenix and the other clients can just use this id as an opaque string? // I tested the desktop client and phoenix to annotate which properties are requestted, see below cases case "fileid": // phoenix only - if md.Id != nil { - appendToOK(prop.Escaped("oc:fileid", storagespace.FormatResourceID(*md.Id))) + if id != nil { + appendToOK(prop.Escaped("oc:fileid", storagespace.FormatResourceID(*id))) } else { appendToNotFound(prop.NotFound("oc:fileid")) } case "id": // desktop client only - if md.Id != nil { - appendToOK(prop.Escaped("oc:id", storagespace.FormatResourceID(*md.Id))) + if id != nil { + appendToOK(prop.Escaped("oc:id", storagespace.FormatResourceID(*id))) } else { appendToNotFound(prop.NotFound("oc:id")) } @@ -1137,8 +1193,8 @@ func mdToPropResponse(ctx context.Context, pf *XML, md *provider.ResourceInfo, p appendToNotFound(prop.NotFound("oc:file-parent")) } case "spaceid": - if md.Id != nil { - appendToOK(prop.Escaped("oc:spaceid", md.Id.SpaceId)) + if id != nil { + appendToOK(prop.Escaped("oc:spaceid", id.SpaceId)) } else { appendToNotFound(prop.Escaped("oc:spaceid", "")) } @@ -1204,7 +1260,7 @@ func mdToPropResponse(ctx context.Context, pf *XML, md *provider.ResourceInfo, p // TODO what is the difference to d:quota-used-bytes (which only exists for collections)? // oc:size is available on files and folders and behaves like d:getcontentlength or d:quota-used-bytes respectively // The hasPrefix is a workaround to make children of the link root show a size if they have 0 bytes - if ls == nil || strings.HasPrefix(md.Path, "/"+ls.Token+"/") { + if ls == nil || strings.HasPrefix(p, "/"+ls.Token+"/") { appendToOK(prop.Escaped("oc:size", size)) } else { // link share root collection has no size @@ -1289,8 +1345,8 @@ func mdToPropResponse(ctx context.Context, pf *XML, md *provider.ResourceInfo, p } } - if md.Id != nil { - if _, ok := linkshares[md.Id.OpaqueId]; ok { + if id != nil { + if _, ok := linkshares[id.OpaqueId]; ok { types.WriteString("3") } } @@ -1316,12 +1372,12 @@ func mdToPropResponse(ctx context.Context, pf *XML, md *provider.ResourceInfo, p if isPublic && md.Type == provider.ResourceType_RESOURCE_TYPE_FILE { var path string if !ls.PasswordProtected { - path = md.Path + path = p } else { expiration := time.Unix(int64(ls.Signature.SignatureExpiration.Seconds), int64(ls.Signature.SignatureExpiration.Nanos)) var sb strings.Builder - sb.WriteString(md.Path) + sb.WriteString(p) sb.WriteString("?signature=") sb.WriteString(ls.Signature.Signature) sb.WriteString("&expiration=") @@ -1335,8 +1391,8 @@ func mdToPropResponse(ctx context.Context, pf *XML, md *provider.ResourceInfo, p } case "privatelink": privateURL, err := url.Parse(publicURL) - if err == nil && md.Id != nil { - privateURL.Path = path.Join(privateURL.Path, "f", storagespace.FormatResourceID(*md.Id)) + if err == nil && id != nil { + privateURL.Path = path.Join(privateURL.Path, "f", storagespace.FormatResourceID(*id)) propstatOK.Prop = append(propstatOK.Prop, prop.Escaped("oc:privatelink", privateURL.String())) } else { propstatNotFound.Prop = append(propstatNotFound.Prop, prop.NotFound("oc:privatelink")) @@ -1344,7 +1400,7 @@ func mdToPropResponse(ctx context.Context, pf *XML, md *provider.ResourceInfo, p 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 { + if strings.HasSuffix(p, ls.Token) && ls.Signature != nil { expiration := time.Unix(int64(ls.Signature.SignatureExpiration.Seconds), int64(ls.Signature.SignatureExpiration.Nanos)) var sb strings.Builder sb.WriteString("") @@ -1366,7 +1422,7 @@ func mdToPropResponse(ctx context.Context, pf *XML, md *provider.ResourceInfo, p case "name": appendToOK(prop.Escaped("oc:name", md.Name)) case "shareid": - if ref, err := storagespace.ParseReference(strings.TrimPrefix(md.Path, "/")); err == nil && ref.GetResourceId().GetSpaceId() == utils.ShareStorageSpaceID { + if ref, err := storagespace.ParseReference(strings.TrimPrefix(p, "/")); err == nil && ref.GetResourceId().GetSpaceId() == utils.ShareStorageSpaceID { appendToOK(prop.Raw("oc:shareid", ref.GetResourceId().GetOpaqueId())) } case "dDC": // desktop diff --git a/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/public.go b/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/public.go index ff35aadbba..9e2cd9398e 100644 --- a/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/public.go +++ b/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/public.go @@ -273,7 +273,7 @@ func (h *Handler) listPublicShares(r *http.Request, filters []*link.ListPublicSh return ocsDataPayload, nil, errors.New("bad request") } -func (h *Handler) isPublicShare(r *http.Request, oid string) bool { +func (h *Handler) isPublicShare(r *http.Request, oid string) (*link.PublicShare, bool) { logger := appctx.GetLogger(r.Context()) client, err := pool.GetGatewayServiceClient(h.gatewayAddr) if err != nil { @@ -291,19 +291,19 @@ func (h *Handler) isPublicShare(r *http.Request, oid string) bool { }) if err != nil { logger.Err(err) - return false + return nil, false } - return psRes.GetShare() != nil + return psRes.GetShare(), psRes.GetShare() != nil } -func (h *Handler) updatePublicShare(w http.ResponseWriter, r *http.Request, shareID string) { +func (h *Handler) updatePublicShare(w http.ResponseWriter, r *http.Request, share *link.PublicShare) { updates := []*link.UpdatePublicShareRequest_Update{} logger := appctx.GetLogger(r.Context()) gwC, err := pool.GetGatewayServiceClient(h.gatewayAddr) if err != nil { - log.Err(err).Str("shareID", shareID).Msg("updatePublicShare") + log.Err(err).Str("shareID", share.GetId().GetOpaqueId()).Msg("updatePublicShare") response.WriteOCSError(w, r, response.MetaBadRequest.StatusCode, "error getting a connection to the gateway service", nil) return } @@ -317,21 +317,7 @@ func (h *Handler) updatePublicShare(w http.ResponseWriter, r *http.Request, shar return } - before, err := gwC.GetPublicShare(r.Context(), &link.GetPublicShareRequest{ - Ref: &link.PublicShareReference{ - Spec: &link.PublicShareReference_Id{ - Id: &link.PublicShareId{ - OpaqueId: shareID, - }, - }, - }, - }) - if err != nil { - response.WriteOCSError(w, r, response.MetaBadRequest.StatusCode, "failed to get public share", nil) - return - } - - createdByUser := publicshare.IsCreatedByUser(*before.Share, user) + createdByUser := publicshare.IsCreatedByUser(*share, user) // NOTE: you are allowed to update a link TO a public link without the `PublicLink.Write` permission if you created it yourself if (permKey != nil && *permKey != 0) || !createdByUser { @@ -355,9 +341,9 @@ func (h *Handler) updatePublicShare(w http.ResponseWriter, r *http.Request, shar } if !createdByUser { - sRes, err := gwC.Stat(r.Context(), &provider.StatRequest{Ref: &provider.Reference{ResourceId: before.Share.ResourceId}}) + sRes, err := gwC.Stat(r.Context(), &provider.StatRequest{Ref: &provider.Reference{ResourceId: share.ResourceId}}) if err != nil { - log.Err(err).Interface("resource_id", before.Share.ResourceId).Msg("failed to stat shared resource") + log.Err(err).Interface("resource_id", share.ResourceId).Msg("failed to stat shared resource") response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "failed to get public share", nil) return } @@ -382,7 +368,7 @@ func (h *Handler) updatePublicShare(w http.ResponseWriter, r *http.Request, shar newName, ok := r.Form["name"] if ok { updatesFound = true - if newName[0] != before.Share.DisplayName { + if newName[0] != share.DisplayName { updates = append(updates, &link.UpdatePublicShareRequest_Update{ Type: link.UpdatePublicShareRequest_Update_TYPE_DISPLAYNAME, DisplayName: newName[0], @@ -404,7 +390,7 @@ func (h *Handler) updatePublicShare(w http.ResponseWriter, r *http.Request, shar publicSharePermissions := &link.PublicSharePermissions{ Permissions: newPermissions, } - beforePerm, _ := json.Marshal(before.GetShare().Permissions) + beforePerm, _ := json.Marshal(share.Permissions) afterPerm, _ := json.Marshal(publicSharePermissions) if string(beforePerm) != string(afterPerm) { logger.Info().Str("shares", "update").Msgf("updating permissions from %v to: %v", string(beforePerm), string(afterPerm)) @@ -418,7 +404,7 @@ func (h *Handler) updatePublicShare(w http.ResponseWriter, r *http.Request, shar } } - statReq := provider.StatRequest{Ref: &provider.Reference{ResourceId: before.Share.ResourceId}} + statReq := provider.StatRequest{Ref: &provider.Reference{ResourceId: share.ResourceId}} statRes, err := gwC.Stat(r.Context(), &statReq) if err != nil { log.Debug().Err(err).Str("shares", "update public share").Msg("error during stat") @@ -446,7 +432,7 @@ func (h *Handler) updatePublicShare(w http.ResponseWriter, r *http.Request, shar } } - beforeExpiration, _ := json.Marshal(before.Share.Expiration) + beforeExpiration, _ := json.Marshal(share.Expiration) afterExpiration, _ := json.Marshal(newExpiration) if string(afterExpiration) != string(beforeExpiration) { logger.Debug().Str("shares", "update").Msgf("updating expire date from %v to: %v", string(beforeExpiration), string(afterExpiration)) @@ -473,47 +459,45 @@ func (h *Handler) updatePublicShare(w http.ResponseWriter, r *http.Request, shar }) } - publicShare := before.Share - // Updates are atomical. See: https://github.com/cs3org/cs3apis/pull/67#issuecomment-617651428 so in order to get the latest updated version if len(updates) > 0 { - uRes := &link.UpdatePublicShareResponse{Share: before.Share} + uRes := &link.UpdatePublicShareResponse{Share: share} for k := range updates { uRes, err = gwC.UpdatePublicShare(r.Context(), &link.UpdatePublicShareRequest{ Ref: &link.PublicShareReference{ Spec: &link.PublicShareReference_Id{ Id: &link.PublicShareId{ - OpaqueId: shareID, + OpaqueId: share.Id.OpaqueId, }, }, }, Update: updates[k], }) if err != nil { - log.Err(err).Str("shareID", shareID).Msg("sending update request to public link provider") + log.Err(err).Str("shareID", share.Id.OpaqueId).Msg("sending update request to public link provider") response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "Error sending update request to public link provider", err) return } if uRes.Status.Code != rpc.Code_CODE_OK { - log.Debug().Str("shareID", shareID).Msgf("sending update request to public link provider failed: %s", uRes.Status.Message) + log.Debug().Str("shareID", share.Id.OpaqueId).Msgf("sending update request to public link provider failed: %s", uRes.Status.Message) response.WriteOCSError(w, r, response.MetaServerError.StatusCode, fmt.Sprintf("Error sending update request to public link provider: %s", uRes.Status.Message), nil) return } } - publicShare = uRes.Share + share = uRes.Share } else if !updatesFound { response.WriteOCSError(w, r, response.MetaBadRequest.StatusCode, "No updates specified in request", nil) return } - s := conversions.PublicShare2ShareData(publicShare, r, h.publicURL) + s := conversions.PublicShare2ShareData(share, r, h.publicURL) h.addFileInfo(r.Context(), s, statRes.Info) h.mapUserIds(r.Context(), gwC, s) response.WriteOCSSuccess(w, r, s) } -func (h *Handler) removePublicShare(w http.ResponseWriter, r *http.Request, shareID string) { +func (h *Handler) removePublicShare(w http.ResponseWriter, r *http.Request, share *link.PublicShare) { ctx := r.Context() c, err := pool.GetGatewayServiceClient(h.gatewayAddr) @@ -522,25 +506,11 @@ func (h *Handler) removePublicShare(w http.ResponseWriter, r *http.Request, shar return } - before, err := c.GetPublicShare(r.Context(), &link.GetPublicShareRequest{ - Ref: &link.PublicShareReference{ - Spec: &link.PublicShareReference_Id{ - Id: &link.PublicShareId{ - OpaqueId: shareID, - }, - }, - }, - }) - if err != nil { - response.WriteOCSError(w, r, response.MetaBadRequest.StatusCode, "failed to get public share", nil) - return - } - u := ctxpkg.ContextMustGetUser(ctx) - if !publicshare.IsCreatedByUser(*before.Share, u) { - sRes, err := c.Stat(r.Context(), &provider.StatRequest{Ref: &provider.Reference{ResourceId: before.Share.ResourceId}}) + if !publicshare.IsCreatedByUser(*share, u) { + sRes, err := c.Stat(r.Context(), &provider.StatRequest{Ref: &provider.Reference{ResourceId: share.ResourceId}}) if err != nil { - log.Err(err).Interface("resource_id", before.Share.ResourceId).Msg("failed to stat shared resource") + log.Err(err).Interface("resource_id", share.ResourceId).Msg("failed to stat shared resource") response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "failed to get public share", nil) return } @@ -555,7 +525,7 @@ func (h *Handler) removePublicShare(w http.ResponseWriter, r *http.Request, shar Ref: &link.PublicShareReference{ Spec: &link.PublicShareReference_Id{ Id: &link.PublicShareId{ - OpaqueId: shareID, + OpaqueId: share.GetId().GetOpaqueId(), }, }, }, diff --git a/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/shares.go b/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/shares.go index 5fa074205f..415e865586 100644 --- a/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/shares.go +++ b/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/shares.go @@ -679,16 +679,21 @@ func (h *Handler) UpdateShare(w http.ResponseWriter, r *http.Request) { shareID := chi.URLParam(r, "shareid") // FIXME: isPublicShare is already doing a GetShare and GetPublicShare, // we should just reuse that object when doing updates - if h.isPublicShare(r, shareID) { - h.updatePublicShare(w, r, shareID) + if share, ok := h.isPublicShare(r, shareID); ok { + h.updatePublicShare(w, r, share) return } - h.updateShare(w, r, shareID) // TODO PUT is used with incomplete data to update a share} + + if share, ok := h.isUserShare(r, shareID); ok { + h.updateShare(w, r, share) // TODO PUT is used with incomplete data to update a share} + return + } + response.WriteOCSError(w, r, response.MetaNotFound.StatusCode, "cannot find share", nil) } -func (h *Handler) updateShare(w http.ResponseWriter, r *http.Request, shareID string) { +func (h *Handler) updateShare(w http.ResponseWriter, r *http.Request, share *collaboration.Share) { ctx := r.Context() - sublog := appctx.GetLogger(ctx).With().Str("shareID", shareID).Logger() + sublog := appctx.GetLogger(ctx).With().Str("shareID", share.GetId().GetOpaqueId()).Logger() client, err := pool.GetGatewayServiceClient(h.gatewayAddr) if err != nil { @@ -696,28 +701,7 @@ func (h *Handler) updateShare(w http.ResponseWriter, r *http.Request, shareID st return } - shareR, err := client.GetShare(r.Context(), &collaboration.GetShareRequest{ - Ref: &collaboration.ShareReference{ - Spec: &collaboration.ShareReference_Id{ - Id: &collaboration.ShareId{ - OpaqueId: shareID, - }, - }, - }, - }) - - if err != nil { - response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "error sending a grpc update share request", err) - return - } - - if shareR.Status.GetCode() != rpc.Code_CODE_OK { - // TODO: error code from shareR response - response.WriteOCSError(w, r, response.MetaNotFound.StatusCode, "cant find requested share", fmt.Errorf("Can't find share %s. Response code: %v", shareID, shareR.Status.GetCode())) - return - } - - info, status, err := h.getResourceInfoByID(ctx, client, shareR.Share.ResourceId) + info, status, err := h.getResourceInfoByID(ctx, client, share.ResourceId) if err != nil || status.Code != rpc.Code_CODE_OK { response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "error mapping share data", err) return @@ -729,7 +713,7 @@ func (h *Handler) updateShare(w http.ResponseWriter, r *http.Request, shareID st return } - shareR.Share.Permissions = &collaboration.SharePermissions{Permissions: role.CS3ResourcePermissions()} + share.Permissions = &collaboration.SharePermissions{Permissions: role.CS3ResourcePermissions()} var fieldMaskPaths = []string{"permissions"} @@ -747,16 +731,16 @@ func (h *Handler) updateShare(w http.ResponseWriter, r *http.Request, shareID st Nanos: uint32(expiration.UnixNano() % int64(time.Second)), } - shareR.Share.Expiration = expirationTs + share.Expiration = expirationTs fieldMaskPaths = append(fieldMaskPaths, "expiration") } else if r.Form.Has("expireDate") { // If the expiration parameter was sent but is empty, then the expiration should be removed. - shareR.Share.Expiration = nil + share.Expiration = nil fieldMaskPaths = append(fieldMaskPaths, "expiration") } uReq := &collaboration.UpdateShareRequest{ - Share: shareR.Share, + Share: share, UpdateMask: &fieldmaskpb.FieldMask{ Paths: fieldMaskPaths, }, @@ -777,10 +761,10 @@ func (h *Handler) updateShare(w http.ResponseWriter, r *http.Request, shareID st } if currentUser, ok := ctxpkg.ContextGetUser(ctx); ok { - h.statCache.RemoveStat(currentUser.Id, shareR.Share.ResourceId) + h.statCache.RemoveStat(currentUser.Id, share.ResourceId) } - share, err := conversions.CS3Share2ShareData(ctx, uRes.Share) + resultshare, err := conversions.CS3Share2ShareData(ctx, uRes.Share) if err != nil { response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "error mapping share data", err) return @@ -807,24 +791,30 @@ func (h *Handler) updateShare(w http.ResponseWriter, r *http.Request, shareID st return } - h.addFileInfo(r.Context(), share, statRes.Info) - h.mapUserIds(ctx, client, share) + h.addFileInfo(r.Context(), resultshare, statRes.Info) + h.mapUserIds(ctx, client, resultshare) - response.WriteOCSSuccess(w, r, share) + response.WriteOCSSuccess(w, r, resultshare) } // RemoveShare handles DELETE requests on /apps/files_sharing/api/v1/shares/(shareid) func (h *Handler) RemoveShare(w http.ResponseWriter, r *http.Request) { shareID := chi.URLParam(r, "shareid") - switch { - case h.isPublicShare(r, shareID): - h.removePublicShare(w, r, shareID) - case h.isUserShare(r, shareID): - h.removeUserShare(w, r, shareID) - default: - // The request is a remove space member request. - h.removeSpaceMember(w, r, shareID) + if share, ok := h.isPublicShare(r, shareID); ok { + h.removePublicShare(w, r, share) + return } + if share, ok := h.isUserShare(r, shareID); ok { + h.removeUserShare(w, r, share) + return + } + + if prov, ok := h.isSpaceShare(r, shareID); ok { + // The request is a remove space member request. + h.removeSpaceMember(w, r, shareID, prov) + return + } + response.WriteOCSError(w, r, response.MetaNotFound.StatusCode, "cannot find share", nil) } // ListShares handles GET requests on /apps/files_sharing/api/v1/shares diff --git a/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/spaces.go b/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/spaces.go index 20c4bbb43f..39a2cd97c6 100644 --- a/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/spaces.go +++ b/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/spaces.go @@ -143,7 +143,21 @@ func (h *Handler) addSpaceMember(w http.ResponseWriter, r *http.Request, info *p response.WriteOCSSuccess(w, r, nil) } -func (h *Handler) removeSpaceMember(w http.ResponseWriter, r *http.Request, spaceID string) { +func (h *Handler) isSpaceShare(r *http.Request, spaceID string) (*registry.ProviderInfo, bool) { + ref, err := storagespace.ParseReference(spaceID) + if err != nil { + return nil, false + } + + if ref.ResourceId.OpaqueId == "" { + ref.ResourceId.OpaqueId = ref.ResourceId.SpaceId + } + + p, err := h.findProvider(r.Context(), &ref) + return p, err == nil +} + +func (h *Handler) removeSpaceMember(w http.ResponseWriter, r *http.Request, spaceID string, prov *registry.ProviderInfo) { ctx := r.Context() shareWith := r.URL.Query().Get("shareWith") @@ -168,13 +182,7 @@ func (h *Handler) removeSpaceMember(w http.ResponseWriter, r *http.Request, spac ref.ResourceId.OpaqueId = ref.ResourceId.SpaceId } - p, err := h.findProvider(ctx, &ref) - if err != nil { - response.WriteOCSError(w, r, response.MetaNotFound.StatusCode, "error getting storage provider", err) - return - } - - providerClient, err := h.getStorageProviderClient(p) + providerClient, err := h.getStorageProviderClient(prov) if err != nil { response.WriteOCSError(w, r, response.MetaNotFound.StatusCode, "error getting storage provider client", err) return diff --git a/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/user.go b/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/user.go index e6089ce1c3..722f53a820 100644 --- a/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/user.go +++ b/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/user.go @@ -129,7 +129,7 @@ func (h *Handler) createUserShare(w http.ResponseWriter, r *http.Request, statIn return share, nil } -func (h *Handler) isUserShare(r *http.Request, oid string) bool { +func (h *Handler) isUserShare(r *http.Request, oid string) (*collaboration.Share, bool) { logger := appctx.GetLogger(r.Context()) client, err := pool.GetGatewayServiceClient(h.gatewayAddr) if err != nil { @@ -147,13 +147,13 @@ func (h *Handler) isUserShare(r *http.Request, oid string) bool { }) if err != nil { logger.Err(err) - return false + return nil, false } - return getShareRes.GetShare() != nil + return getShareRes.GetShare(), getShareRes.GetShare() != nil } -func (h *Handler) removeUserShare(w http.ResponseWriter, r *http.Request, shareID string) { +func (h *Handler) removeUserShare(w http.ResponseWriter, r *http.Request, share *collaboration.Share) { ctx := r.Context() uClient, err := h.getClient() @@ -164,26 +164,11 @@ func (h *Handler) removeUserShare(w http.ResponseWriter, r *http.Request, shareI shareRef := &collaboration.ShareReference{ Spec: &collaboration.ShareReference_Id{ - Id: &collaboration.ShareId{ - OpaqueId: shareID, - }, + Id: share.Id, }, } - // Get the share, so that we can include it in the response. - getShareResp, err := uClient.GetShare(ctx, &collaboration.GetShareRequest{Ref: shareRef}) - if err != nil { - response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "error sending a grpc delete share request", err) - return - } else if getShareResp.Status.Code != rpc.Code_CODE_OK { - if getShareResp.Status.Code == rpc.Code_CODE_NOT_FOUND { - response.WriteOCSError(w, r, response.MetaNotFound.StatusCode, "not found", nil) - return - } - response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "deleting share failed", err) - return - } - data, err := conversions.CS3Share2ShareData(ctx, getShareResp.Share) + data, err := conversions.CS3Share2ShareData(ctx, share) if err != nil { response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "deleting share failed", err) return @@ -207,7 +192,7 @@ func (h *Handler) removeUserShare(w http.ResponseWriter, r *http.Request, shareI return } if currentUser, ok := ctxpkg.ContextGetUser(ctx); ok { - h.statCache.RemoveStat(currentUser.Id, getShareResp.Share.ResourceId) + h.statCache.RemoveStat(currentUser.Id, share.ResourceId) } response.WriteOCSSuccess(w, r, data) } diff --git a/vendor/github.com/cs3org/reva/v2/pkg/storage/registry/spaces/spaces.go b/vendor/github.com/cs3org/reva/v2/pkg/storage/registry/spaces/spaces.go index 4ce986cf0c..17f3cea740 100644 --- a/vendor/github.com/cs3org/reva/v2/pkg/storage/registry/spaces/spaces.go +++ b/vendor/github.com/cs3org/reva/v2/pkg/storage/registry/spaces/spaces.go @@ -22,6 +22,7 @@ import ( "bytes" "context" "encoding/json" + "os" "path/filepath" "regexp" "strconv" @@ -534,9 +535,10 @@ func (r *registry) findProvidersForResource(ctx context.Context, id string, find // findProvidersForAbsolutePathReference takes a path and returns the storage provider with the longest matching path prefix // FIXME use regex to return the correct provider when multiple are configured -func (r *registry) findProvidersForAbsolutePathReference(ctx context.Context, path string, unique, unrestricted bool, _ string) []*registrypb.ProviderInfo { +func (r *registry) findProvidersForAbsolutePathReference(ctx context.Context, requestedPath string, unique, unrestricted bool, _ string) []*registrypb.ProviderInfo { currentUser := ctxpkg.ContextMustGetUser(ctx) + pathSegments := strings.Split(strings.TrimPrefix(requestedPath, string(os.PathSeparator)), string(os.PathSeparator)) deepestMountPath := "" var deepestMountSpace *providerpb.StorageSpace var deepestMountPathProvider *registrypb.ProviderInfo @@ -549,12 +551,42 @@ func (r *registry) findProvidersForAbsolutePathReference(ctx context.Context, pa var spaces []*providerpb.StorageSpace var err error + // check if any space in the provider has a valid mountpoint + containsRelatedSpace := false + + spaceLoop: + for _, space := range provider.Spaces { + spacePath, _ := space.SpacePath(currentUser, nil) + spacePathSegments := strings.Split(strings.TrimPrefix(spacePath, string(os.PathSeparator)), string(os.PathSeparator)) + + for i, segment := range spacePathSegments { + if i >= len(pathSegments) { + break + } + if pathSegments[i] != segment { + if segment != "" && !strings.Contains(segment, "{{") { + // Mount path points elsewhere -> irrelevant + continue spaceLoop + } + // Encountered a template which couldn't be filled -> potentially relevant + break + } + } + + containsRelatedSpace = true + break + } + + if !containsRelatedSpace { + continue + } + // when listing paths also return mountpoints filters := []*providerpb.ListStorageSpacesRequest_Filter{ { Type: providerpb.ListStorageSpacesRequest_Filter_TYPE_PATH, Term: &providerpb.ListStorageSpacesRequest_Filter_Path{ - Path: strings.TrimPrefix(path, p.ProviderPath), + Path: strings.TrimPrefix(requestedPath, p.ProviderPath), // FIXME this no longer has an effect as the p.Providerpath is always empty }, }, { @@ -595,14 +627,14 @@ func (r *registry) findProvidersForAbsolutePathReference(ctx context.Context, pa // determine deepest mount point switch { - case spacePath == path && unique: + case spacePath == requestedPath && unique: validSpaces = append(validSpaces, space) deepestMountPath = spacePath deepestMountSpace = space deepestMountPathProvider = p - case !unique && isSubpath(spacePath, path): + case !unique && isSubpath(spacePath, requestedPath): // and add all providers below and exactly matching the path // requested /foo, mountPath /foo/sub validSpaces = append(validSpaces, space) @@ -612,7 +644,7 @@ func (r *registry) findProvidersForAbsolutePathReference(ctx context.Context, pa deepestMountPathProvider = p } - case isSubpath(path, spacePath) && len(spacePath) > len(deepestMountPath): + case isSubpath(requestedPath, spacePath) && len(spacePath) > len(deepestMountPath): // eg. three providers: /foo, /foo/sub, /foo/sub/bar // requested /foo/sub/mob deepestMountPath = spacePath diff --git a/vendor/modules.txt b/vendor/modules.txt index 1b766a56d5..4796a31594 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -349,7 +349,7 @@ github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1 github.com/cs3org/go-cs3apis/cs3/storage/registry/v1beta1 github.com/cs3org/go-cs3apis/cs3/tx/v1beta1 github.com/cs3org/go-cs3apis/cs3/types/v1beta1 -# github.com/cs3org/reva/v2 v2.13.4-0.20230523132457-4fb99464ab8d +# github.com/cs3org/reva/v2 v2.13.4-0.20230525110514-9334e2174492 ## explicit; go 1.19 github.com/cs3org/reva/v2/cmd/revad/internal/grace github.com/cs3org/reva/v2/cmd/revad/runtime