mirror of
https://github.com/opencloud-eu/opencloud.git
synced 2025-12-31 01:10:20 -06:00
bump reva to v2.26.5
Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de>
This commit is contained in:
@@ -1,5 +1,9 @@
|
||||
Bugfix: Bump Reva
|
||||
Bugfix: Bump Reva to v2.26.5
|
||||
|
||||
bumps reva version
|
||||
* Fix [cs3org/reva#4926](https://github.com/cs3org/reva/issues/4926): Make etag always match content on downloads
|
||||
* Fix [cs3org/reva#4920](https://github.com/cs3org/reva/issues/4920): Return correct status codes for simple uploads
|
||||
* Fix [cs3org/reva#4924](https://github.com/cs3org/reva/issues/4924): Fix sync propagation
|
||||
* Fix [cs3org/reva#4916](https://github.com/cs3org/reva/issues/4916): Improve posixfs stability and performanc
|
||||
|
||||
https://github.com/owncloud/ocis/pull/10552
|
||||
https://github.com/owncloud/ocis/pull/10539
|
||||
|
||||
2
go.mod
2
go.mod
@@ -16,7 +16,7 @@ require (
|
||||
github.com/cenkalti/backoff v2.2.1+incompatible
|
||||
github.com/coreos/go-oidc/v3 v3.11.0
|
||||
github.com/cs3org/go-cs3apis v0.0.0-20241105092511-3ad35d174fc1
|
||||
github.com/cs3org/reva/v2 v2.26.5-0.20241111162950-e77dd61e7edb
|
||||
github.com/cs3org/reva/v2 v2.26.5
|
||||
github.com/davidbyttow/govips/v2 v2.15.0
|
||||
github.com/dhowden/tag v0.0.0-20240417053706-3d75831295e8
|
||||
github.com/dutchcoders/go-clamd v0.0.0-20170520113014-b970184f4d9e
|
||||
|
||||
4
go.sum
4
go.sum
@@ -255,8 +255,8 @@ github.com/crewjam/saml v0.4.14 h1:g9FBNx62osKusnFzs3QTN5L9CVA/Egfgm+stJShzw/c=
|
||||
github.com/crewjam/saml v0.4.14/go.mod h1:UVSZCf18jJkk6GpWNVqcyQJMD5HsRugBPf4I1nl2mME=
|
||||
github.com/cs3org/go-cs3apis v0.0.0-20241105092511-3ad35d174fc1 h1:RU6LT6mkD16xZs011+8foU7T3LrPvTTSWeTQ9OgfhkA=
|
||||
github.com/cs3org/go-cs3apis v0.0.0-20241105092511-3ad35d174fc1/go.mod h1:DedpcqXl193qF/08Y04IO0PpxyyMu8+GrkD6kWK2MEQ=
|
||||
github.com/cs3org/reva/v2 v2.26.5-0.20241111162950-e77dd61e7edb h1:owRv9x5GlKKdqCCM70kZKCsLAcDkFPkyOb129Jmklt0=
|
||||
github.com/cs3org/reva/v2 v2.26.5-0.20241111162950-e77dd61e7edb/go.mod h1:KP0Zomt3dNIr/kU2M1mXzTIVFOtxBVS4qmBDMRCfrOQ=
|
||||
github.com/cs3org/reva/v2 v2.26.5 h1:LWIOSpmgoVQDfe9S2renzqqAXorFs6lT+5Vodhr3M68=
|
||||
github.com/cs3org/reva/v2 v2.26.5/go.mod h1:KP0Zomt3dNIr/kU2M1mXzTIVFOtxBVS4qmBDMRCfrOQ=
|
||||
github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4=
|
||||
github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg=
|
||||
github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=
|
||||
|
||||
11
vendor/github.com/cs3org/reva/v2/pkg/cbox/storage/eoswrapper/eoswrapper.go
generated
vendored
11
vendor/github.com/cs3org/reva/v2/pkg/cbox/storage/eoswrapper/eoswrapper.go
generated
vendored
@@ -28,6 +28,9 @@ import (
|
||||
|
||||
"github.com/Masterminds/sprig"
|
||||
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
|
||||
"github.com/mitchellh/mapstructure"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
ctxpkg "github.com/cs3org/reva/v2/pkg/ctx"
|
||||
"github.com/cs3org/reva/v2/pkg/errtypes"
|
||||
"github.com/cs3org/reva/v2/pkg/events"
|
||||
@@ -36,8 +39,6 @@ import (
|
||||
"github.com/cs3org/reva/v2/pkg/storage/utils/eosfs"
|
||||
"github.com/cs3org/reva/v2/pkg/storagespace"
|
||||
"github.com/cs3org/reva/v2/pkg/utils"
|
||||
"github.com/mitchellh/mapstructure"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -193,12 +194,12 @@ func (w *wrapper) ListRevisions(ctx context.Context, ref *provider.Reference) ([
|
||||
return w.FS.ListRevisions(ctx, ref)
|
||||
}
|
||||
|
||||
func (w *wrapper) DownloadRevision(ctx context.Context, ref *provider.Reference, revisionKey string) (io.ReadCloser, error) {
|
||||
func (w *wrapper) DownloadRevision(ctx context.Context, ref *provider.Reference, revisionKey string, openReaderfunc func(*provider.ResourceInfo) bool) (*provider.ResourceInfo, io.ReadCloser, error) {
|
||||
if err := w.userIsProjectAdmin(ctx, ref); err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
return w.FS.DownloadRevision(ctx, ref, revisionKey)
|
||||
return w.FS.DownloadRevision(ctx, ref, revisionKey, openReaderfunc)
|
||||
}
|
||||
|
||||
func (w *wrapper) RestoreRevision(ctx context.Context, ref *provider.Reference, revisionKey string) error {
|
||||
|
||||
32
vendor/github.com/cs3org/reva/v2/pkg/ocm/storage/received/ocm.go
generated
vendored
32
vendor/github.com/cs3org/reva/v2/pkg/ocm/storage/received/ocm.go
generated
vendored
@@ -38,6 +38,8 @@ import (
|
||||
ocmpb "github.com/cs3org/go-cs3apis/cs3/sharing/ocm/v1beta1"
|
||||
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
|
||||
typepb "github.com/cs3org/go-cs3apis/cs3/types/v1beta1"
|
||||
"github.com/studio-b12/gowebdav"
|
||||
|
||||
"github.com/cs3org/reva/v2/pkg/errtypes"
|
||||
"github.com/cs3org/reva/v2/pkg/events"
|
||||
"github.com/cs3org/reva/v2/pkg/mime"
|
||||
@@ -49,7 +51,6 @@ import (
|
||||
"github.com/cs3org/reva/v2/pkg/storagespace"
|
||||
"github.com/cs3org/reva/v2/pkg/utils"
|
||||
"github.com/cs3org/reva/v2/pkg/utils/cfg"
|
||||
"github.com/studio-b12/gowebdav"
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -364,13 +365,30 @@ func (d *driver) ListFolder(ctx context.Context, ref *provider.Reference, _ []st
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (d *driver) Download(ctx context.Context, ref *provider.Reference) (io.ReadCloser, error) {
|
||||
client, _, rel, err := d.webdavClient(ctx, nil, ref)
|
||||
func (d *driver) Download(ctx context.Context, ref *provider.Reference, openReaderfunc func(*provider.ResourceInfo) bool) (*provider.ResourceInfo, io.ReadCloser, error) {
|
||||
client, share, rel, err := d.webdavClient(ctx, nil, ref)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
return client.ReadStream(rel)
|
||||
info, err := client.StatWithProps(rel, []string{}) // request all properties by giving an empty list
|
||||
if err != nil {
|
||||
if gowebdav.IsErrNotFound(err) {
|
||||
return nil, nil, errtypes.NotFound(ref.GetPath())
|
||||
}
|
||||
return nil, nil, err
|
||||
}
|
||||
md, err := convertStatToResourceInfo(ref, info, share)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
if !openReaderfunc(md) {
|
||||
return md, nil, nil
|
||||
}
|
||||
|
||||
reader, err := client.ReadStream(rel)
|
||||
return md, reader, err
|
||||
}
|
||||
|
||||
func (d *driver) GetPathByID(ctx context.Context, id *provider.ResourceId) (string, error) {
|
||||
@@ -396,8 +414,8 @@ func (d *driver) ListRevisions(ctx context.Context, ref *provider.Reference) ([]
|
||||
return nil, errtypes.NotSupported("operation not supported")
|
||||
}
|
||||
|
||||
func (d *driver) DownloadRevision(ctx context.Context, ref *provider.Reference, key string) (io.ReadCloser, error) {
|
||||
return nil, errtypes.NotSupported("operation not supported")
|
||||
func (d *driver) DownloadRevision(ctx context.Context, ref *provider.Reference, key string, openReaderFunc func(md *provider.ResourceInfo) bool) (*provider.ResourceInfo, io.ReadCloser, error) {
|
||||
return nil, nil, errtypes.NotSupported("operation not supported")
|
||||
}
|
||||
|
||||
func (d *driver) RestoreRevision(ctx context.Context, ref *provider.Reference, key string) error {
|
||||
|
||||
66
vendor/github.com/cs3org/reva/v2/pkg/rhttp/datatx/utils/download/download.go
generated
vendored
66
vendor/github.com/cs3org/reva/v2/pkg/rhttp/datatx/utils/download/download.go
generated
vendored
@@ -30,6 +30,8 @@ import (
|
||||
"strings"
|
||||
|
||||
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
|
||||
"github.com/rs/zerolog"
|
||||
|
||||
"github.com/cs3org/reva/v2/internal/grpc/services/storageprovider"
|
||||
"github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/net"
|
||||
"github.com/cs3org/reva/v2/pkg/appctx"
|
||||
@@ -37,7 +39,6 @@ import (
|
||||
"github.com/cs3org/reva/v2/pkg/storage"
|
||||
"github.com/cs3org/reva/v2/pkg/storagespace"
|
||||
"github.com/cs3org/reva/v2/pkg/utils"
|
||||
"github.com/rs/zerolog"
|
||||
)
|
||||
|
||||
type contextKey struct{}
|
||||
@@ -91,27 +92,47 @@ func GetOrHeadFile(w http.ResponseWriter, r *http.Request, fs storage.FS, spaceI
|
||||
// TODO check preconditions like If-Range, If-Match ...
|
||||
|
||||
var md *provider.ResourceInfo
|
||||
var content io.ReadCloser
|
||||
var err error
|
||||
var notModified bool
|
||||
|
||||
// do a stat to set a Content-Length header
|
||||
// do a stat to set Content-Length and etag headers
|
||||
|
||||
if md, err = fs.GetMD(ctx, ref, nil, []string{"size", "mimetype", "etag"}); err != nil {
|
||||
handleError(w, &sublog, err, "stat")
|
||||
md, content, err = fs.Download(ctx, ref, func(md *provider.ResourceInfo) bool {
|
||||
// range requests always need to open the reader to check if it is seekable
|
||||
if r.Header.Get("Range") != "" {
|
||||
return true
|
||||
}
|
||||
// otherwise, HEAD requests do not need to open a reader
|
||||
if r.Method == "HEAD" {
|
||||
return false
|
||||
}
|
||||
|
||||
// check etag, see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/If-None-Match
|
||||
for _, etag := range r.Header.Values(net.HeaderIfNoneMatch) {
|
||||
if md.Etag == etag {
|
||||
// When the condition fails for GET and HEAD methods, then the server must return
|
||||
// HTTP status code 304 (Not Modified). [...] Note that the server generating a
|
||||
// 304 response MUST generate any of the following header fields that would have
|
||||
// been sent in a 200 (OK) response to the same request:
|
||||
// Cache-Control, Content-Location, Date, ETag, Expires, and Vary.
|
||||
notModified = true
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
})
|
||||
if err != nil {
|
||||
handleError(w, &sublog, err, "download")
|
||||
return
|
||||
}
|
||||
|
||||
// check etag, see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/If-None-Match
|
||||
for _, etag := range r.Header.Values(net.HeaderIfNoneMatch) {
|
||||
if md.Etag == etag {
|
||||
// When the condition fails for GET and HEAD methods, then the server must return
|
||||
// HTTP status code 304 (Not Modified). [...] Note that the server generating a
|
||||
// 304 response MUST generate any of the following header fields that would have
|
||||
// been sent in a 200 (OK) response to the same request:
|
||||
// Cache-Control, Content-Location, Date, ETag, Expires, and Vary.
|
||||
w.Header().Set(net.HeaderETag, md.Etag)
|
||||
w.WriteHeader(http.StatusNotModified)
|
||||
return
|
||||
}
|
||||
if content != nil {
|
||||
defer content.Close()
|
||||
}
|
||||
if notModified {
|
||||
w.Header().Set(net.HeaderETag, md.Etag)
|
||||
w.WriteHeader(http.StatusNotModified)
|
||||
return
|
||||
}
|
||||
|
||||
// fill in storage provider id if it is missing
|
||||
@@ -141,14 +162,6 @@ func GetOrHeadFile(w http.ResponseWriter, r *http.Request, fs storage.FS, spaceI
|
||||
}
|
||||
}
|
||||
|
||||
ctx = ContextWithEtag(ctx, md.Etag)
|
||||
content, err := fs.Download(ctx, ref)
|
||||
if err != nil {
|
||||
handleError(w, &sublog, err, "download")
|
||||
return
|
||||
}
|
||||
defer content.Close()
|
||||
|
||||
code := http.StatusOK
|
||||
sendSize := int64(md.Size)
|
||||
var sendContent io.Reader = content
|
||||
@@ -259,6 +272,9 @@ func handleError(w http.ResponseWriter, log *zerolog.Logger, err error, action s
|
||||
case errtypes.IsPermissionDenied:
|
||||
log.Debug().Err(err).Str("action", action).Msg("permission denied")
|
||||
w.WriteHeader(http.StatusForbidden)
|
||||
case errtypes.Aborted:
|
||||
log.Debug().Err(err).Str("action", action).Msg("etags do not match")
|
||||
w.WriteHeader(http.StatusPreconditionFailed)
|
||||
default:
|
||||
log.Error().Err(err).Str("action", action).Msg("unexpected error")
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
|
||||
41
vendor/github.com/cs3org/reva/v2/pkg/storage/fs/cephfs/cephfs.go
generated
vendored
41
vendor/github.com/cs3org/reva/v2/pkg/storage/fs/cephfs/cephfs.go
generated
vendored
@@ -33,13 +33,14 @@ import (
|
||||
|
||||
cephfs2 "github.com/ceph/go-ceph/cephfs"
|
||||
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
|
||||
"github.com/mitchellh/mapstructure"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/cs3org/reva/v2/pkg/appctx"
|
||||
"github.com/cs3org/reva/v2/pkg/errtypes"
|
||||
"github.com/cs3org/reva/v2/pkg/events"
|
||||
"github.com/cs3org/reva/v2/pkg/storage"
|
||||
"github.com/cs3org/reva/v2/pkg/storage/fs/registry"
|
||||
"github.com/mitchellh/mapstructure"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -276,11 +277,11 @@ func (fs *cephfs) ListFolder(ctx context.Context, ref *provider.Reference, mdKey
|
||||
return files, getRevaError(err)
|
||||
}
|
||||
|
||||
func (fs *cephfs) Download(ctx context.Context, ref *provider.Reference) (rc io.ReadCloser, err error) {
|
||||
func (fs *cephfs) Download(ctx context.Context, ref *provider.Reference, openReaderFunc func(md *provider.ResourceInfo) bool) (ri *provider.ResourceInfo, rc io.ReadCloser, err error) {
|
||||
var path string
|
||||
user := fs.makeUser(ctx)
|
||||
if path, err = user.resolveRef(ref); err != nil {
|
||||
return nil, errors.Wrap(err, "cephfs: error resolving ref")
|
||||
return nil, nil, errors.Wrap(err, "cephfs: error resolving ref")
|
||||
}
|
||||
|
||||
user.op(func(cv *cacheVal) {
|
||||
@@ -288,10 +289,24 @@ func (fs *cephfs) Download(ctx context.Context, ref *provider.Reference) (rc io.
|
||||
err = errtypes.PermissionDenied("cephfs: cannot download under the virtual share folder")
|
||||
return
|
||||
}
|
||||
|
||||
var stat Statx
|
||||
if stat, err = cv.mount.Statx(path, cephfs2.StatxBasicStats, 0); err != nil {
|
||||
return
|
||||
}
|
||||
ri, err = user.fileAsResourceInfo(cv, path, stat, nil)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if !openReaderFunc(ri) {
|
||||
return
|
||||
}
|
||||
|
||||
rc, err = cv.mount.Open(path, os.O_RDONLY, 0)
|
||||
})
|
||||
|
||||
return rc, getRevaError(err)
|
||||
return ri, rc, getRevaError(err)
|
||||
}
|
||||
|
||||
func (fs *cephfs) ListRevisions(ctx context.Context, ref *provider.Reference) (fvs []*provider.FileVersion, err error) {
|
||||
@@ -341,7 +356,7 @@ func (fs *cephfs) ListRevisions(ctx context.Context, ref *provider.Reference) (f
|
||||
return fvs, getRevaError(err)
|
||||
}
|
||||
|
||||
func (fs *cephfs) DownloadRevision(ctx context.Context, ref *provider.Reference, key string) (file io.ReadCloser, err error) {
|
||||
func (fs *cephfs) DownloadRevision(ctx context.Context, ref *provider.Reference, key string, openReaderFunc func(md *provider.ResourceInfo) bool) (ri *provider.ResourceInfo, file io.ReadCloser, err error) {
|
||||
//TODO(tmourati): Fix entry id logic
|
||||
user := fs.makeUser(ctx)
|
||||
|
||||
@@ -352,10 +367,22 @@ func (fs *cephfs) DownloadRevision(ctx context.Context, ref *provider.Reference,
|
||||
return
|
||||
}
|
||||
|
||||
var stat Statx
|
||||
stat, err = cv.mount.Statx(revPath, cephfs2.StatxMtime|cephfs2.StatxSize, 0)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
ri, err = user.fileAsResourceInfo(cv, revPath, stat, nil)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if !openReaderFunc(ri) {
|
||||
return
|
||||
}
|
||||
file, err = cv.mount.Open(revPath, os.O_RDONLY, 0)
|
||||
})
|
||||
|
||||
return file, getRevaError(err)
|
||||
return ri, file, getRevaError(err)
|
||||
}
|
||||
|
||||
func (fs *cephfs) RestoreRevision(ctx context.Context, ref *provider.Reference, key string) (err error) {
|
||||
|
||||
16
vendor/github.com/cs3org/reva/v2/pkg/storage/fs/hello/hello.go
generated
vendored
16
vendor/github.com/cs3org/reva/v2/pkg/storage/fs/hello/hello.go
generated
vendored
@@ -29,6 +29,7 @@ import (
|
||||
"time"
|
||||
|
||||
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
|
||||
|
||||
"github.com/cs3org/reva/v2/pkg/errtypes"
|
||||
"github.com/cs3org/reva/v2/pkg/events"
|
||||
"github.com/cs3org/reva/v2/pkg/storage"
|
||||
@@ -222,20 +223,23 @@ func (fs *hellofs) ListFolder(ctx context.Context, ref *provider.Reference, mdKe
|
||||
}
|
||||
|
||||
// Download returns a ReadCloser for the content of the referenced resource
|
||||
func (fs *hellofs) Download(ctx context.Context, ref *provider.Reference) (io.ReadCloser, error) {
|
||||
func (fs *hellofs) Download(ctx context.Context, ref *provider.Reference, openReaderFunc func(md *provider.ResourceInfo) bool) (*provider.ResourceInfo, io.ReadCloser, error) {
|
||||
info, err := fs.lookup(ctx, ref)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
if info.Type != provider.ResourceType_RESOURCE_TYPE_FILE {
|
||||
return nil, errtypes.InternalError("expected a file")
|
||||
return nil, nil, errtypes.InternalError("expected a file")
|
||||
}
|
||||
if info.GetId().GetOpaqueId() != fileid {
|
||||
return nil, errtypes.InternalError("unknown file")
|
||||
return nil, nil, errtypes.InternalError("unknown file")
|
||||
}
|
||||
|
||||
if !openReaderFunc(info) {
|
||||
return info, nil, nil
|
||||
}
|
||||
|
||||
b := &bytes.Buffer{}
|
||||
b.WriteString(content)
|
||||
return io.NopCloser(b), nil
|
||||
return info, io.NopCloser(b), nil
|
||||
}
|
||||
|
||||
5
vendor/github.com/cs3org/reva/v2/pkg/storage/fs/hello/unimplemented.go
generated
vendored
5
vendor/github.com/cs3org/reva/v2/pkg/storage/fs/hello/unimplemented.go
generated
vendored
@@ -24,6 +24,7 @@ import (
|
||||
"net/url"
|
||||
|
||||
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
|
||||
|
||||
"github.com/cs3org/reva/v2/pkg/errtypes"
|
||||
"github.com/cs3org/reva/v2/pkg/storage"
|
||||
)
|
||||
@@ -153,8 +154,8 @@ func (fs *hellofs) ListRevisions(ctx context.Context, ref *provider.Reference) (
|
||||
}
|
||||
|
||||
// DownloadRevision downloads a revision
|
||||
func (fs *hellofs) DownloadRevision(ctx context.Context, ref *provider.Reference, revisionKey string) (io.ReadCloser, error) {
|
||||
return nil, errtypes.NotSupported("unimplemented")
|
||||
func (fs *hellofs) DownloadRevision(ctx context.Context, ref *provider.Reference, revisionKey string, openReaderFunc func(md *provider.ResourceInfo) bool) (*provider.ResourceInfo, io.ReadCloser, error) {
|
||||
return nil, nil, errtypes.NotSupported("unimplemented")
|
||||
}
|
||||
|
||||
// RestoreRevision restores a revision
|
||||
|
||||
66
vendor/github.com/cs3org/reva/v2/pkg/storage/fs/nextcloud/nextcloud.go
generated
vendored
66
vendor/github.com/cs3org/reva/v2/pkg/storage/fs/nextcloud/nextcloud.go
generated
vendored
@@ -25,18 +25,21 @@ import (
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
user "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
|
||||
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
|
||||
types "github.com/cs3org/go-cs3apis/cs3/types/v1beta1"
|
||||
"github.com/mitchellh/mapstructure"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/cs3org/reva/v2/pkg/appctx"
|
||||
ctxpkg "github.com/cs3org/reva/v2/pkg/ctx"
|
||||
"github.com/cs3org/reva/v2/pkg/errtypes"
|
||||
"github.com/cs3org/reva/v2/pkg/events"
|
||||
"github.com/cs3org/reva/v2/pkg/storage"
|
||||
"github.com/cs3org/reva/v2/pkg/storage/fs/registry"
|
||||
"github.com/mitchellh/mapstructure"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -413,8 +416,17 @@ func (nc *StorageDriver) Upload(ctx context.Context, req storage.UploadRequest,
|
||||
}
|
||||
|
||||
// Download as defined in the storage.FS interface
|
||||
func (nc *StorageDriver) Download(ctx context.Context, ref *provider.Reference) (io.ReadCloser, error) {
|
||||
return nc.doDownload(ctx, ref.Path)
|
||||
func (nc *StorageDriver) Download(ctx context.Context, ref *provider.Reference, openReaderfunc func(*provider.ResourceInfo) bool) (*provider.ResourceInfo, io.ReadCloser, error) {
|
||||
md, err := nc.GetMD(ctx, ref, []string{}, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if !openReaderfunc(md) {
|
||||
return md, nil, nil
|
||||
}
|
||||
|
||||
reader, err := nc.doDownload(ctx, ref.Path)
|
||||
return md, reader, err
|
||||
}
|
||||
|
||||
// ListRevisions as defined in the storage.FS interface
|
||||
@@ -441,12 +453,54 @@ func (nc *StorageDriver) ListRevisions(ctx context.Context, ref *provider.Refere
|
||||
}
|
||||
|
||||
// DownloadRevision as defined in the storage.FS interface
|
||||
func (nc *StorageDriver) DownloadRevision(ctx context.Context, ref *provider.Reference, key string) (io.ReadCloser, error) {
|
||||
func (nc *StorageDriver) DownloadRevision(ctx context.Context, ref *provider.Reference, key string, openReaderfunc func(*provider.ResourceInfo) bool) (*provider.ResourceInfo, io.ReadCloser, error) {
|
||||
log := appctx.GetLogger(ctx)
|
||||
log.Info().Msgf("DownloadRevision %s %s", ref.Path, key)
|
||||
|
||||
md, err := nc.GetMD(ctx, ref, []string{}, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
revs, err := nc.ListRevisions(ctx, ref)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
var ri *provider.ResourceInfo
|
||||
for _, rev := range revs {
|
||||
if rev.Key == key {
|
||||
|
||||
ri = &provider.ResourceInfo{
|
||||
// TODO(jfd) we cannot access version content, this will be a problem when trying to fetch version thumbnails
|
||||
// Opaque
|
||||
Type: provider.ResourceType_RESOURCE_TYPE_FILE,
|
||||
Id: &provider.ResourceId{
|
||||
StorageId: "versions",
|
||||
OpaqueId: md.Id.OpaqueId + "@" + rev.GetKey(),
|
||||
},
|
||||
// Checksum
|
||||
Etag: rev.Etag,
|
||||
// MimeType
|
||||
Mtime: &types.Timestamp{
|
||||
Seconds: rev.Mtime,
|
||||
// TODO cs3apis FileVersion should use types.Timestamp instead of uint64
|
||||
},
|
||||
Path: path.Join("v", rev.Key),
|
||||
// PermissionSet
|
||||
Size: rev.Size,
|
||||
Owner: md.Owner,
|
||||
}
|
||||
}
|
||||
}
|
||||
if ri == nil {
|
||||
return nil, nil, errtypes.NotFound("revision not found")
|
||||
}
|
||||
|
||||
if !openReaderfunc(ri) {
|
||||
return ri, nil, nil
|
||||
}
|
||||
|
||||
readCloser, err := nc.doDownloadRevision(ctx, ref.Path, key)
|
||||
return readCloser, err
|
||||
return ri, readCloser, err
|
||||
}
|
||||
|
||||
// RestoreRevision as defined in the storage.FS interface
|
||||
|
||||
1
vendor/github.com/cs3org/reva/v2/pkg/storage/fs/nextcloud/nextcloud_server_mock.go
generated
vendored
1
vendor/github.com/cs3org/reva/v2/pkg/storage/fs/nextcloud/nextcloud_server_mock.go
generated
vendored
@@ -164,6 +164,7 @@ var responses = map[string]Response{
|
||||
`POST /apps/sciencemesh/~tester/api/storage/GetMD {"ref":{"resource_id":{"storage_id":"storage-id","opaque_id":"opaque-id"},"path":"some/file/path.txt"},"mdKeys":[]}`: {200, `{"opaque":{},"type":1,"id":{"opaque_id":"fileid-/some/path"},"checksum":{},"etag":"deadbeef","mime_type":"text/plain","mtime":{"seconds":1234567890},"path":"/versionedFile","permission_set":{},"size":12345,"canonical_metadata":{},"arbitrary_metadata":{"metadata":{"key1":"val1","key2":"val2","key3":"val3"}}}`, serverStateEmpty},
|
||||
`GET /apps/sciencemesh/~tester/api/storage/Download/some/file/path.txt `: {200, `the contents of the file`, serverStateEmpty},
|
||||
`POST /apps/sciencemesh/~tester/api/storage/ListRevisions {"resource_id":{"storage_id":"storage-id","opaque_id":"opaque-id"},"path":"/some/path"}`: {200, `[{"opaque":{"map":{"some":{"value":"ZGF0YQ=="}}},"key":"version-12","size":12345,"mtime":1234567890,"etag":"deadb00f"},{"opaque":{"map":{"different":{"value":"c3R1ZmY="}}},"key":"asdf","size":12345,"mtime":1234567890,"etag":"deadbeef"}]`, serverStateEmpty},
|
||||
`POST /apps/sciencemesh/~tester/api/storage/ListRevisions {"resource_id":{"storage_id":"storage-id","opaque_id":"opaque-id"},"path":"some/file/path.txt"}`: {200, `[{"key":"some/revision","size":12345,"mtime":1234567890,"etag":"deadb00f"}]`, serverStateEmpty},
|
||||
`GET /apps/sciencemesh/~tester/api/storage/DownloadRevision/some%2Frevision/some/file/path.txt `: {200, `the contents of that revision`, serverStateEmpty},
|
||||
`POST /apps/sciencemesh/~tester/api/storage/RestoreRevision {"ref":{"resource_id":{"storage_id":"storage-id","opaque_id":"opaque-id"},"path":"some/file/path.txt"},"key":"asdf"}`: {200, ``, serverStateEmpty},
|
||||
`POST /apps/sciencemesh/~tester/api/storage/ListRecycle {"key":"asdf","path":"/some/file.txt"}`: {200, `[{"opaque":{},"key":"some-deleted-version","ref":{"resource_id":{},"path":"/some/file.txt"},"size":12345,"deletion_time":{"seconds":1234567890}}]`, serverStateEmpty},
|
||||
|
||||
57
vendor/github.com/cs3org/reva/v2/pkg/storage/fs/owncloudsql/owncloudsql.go
generated
vendored
57
vendor/github.com/cs3org/reva/v2/pkg/storage/fs/owncloudsql/owncloudsql.go
generated
vendored
@@ -39,6 +39,11 @@ import (
|
||||
rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1"
|
||||
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
|
||||
types "github.com/cs3org/go-cs3apis/cs3/types/v1beta1"
|
||||
"github.com/mitchellh/mapstructure"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/pkg/xattr"
|
||||
"github.com/rs/zerolog/log"
|
||||
|
||||
"github.com/cs3org/reva/v2/internal/grpc/services/storageprovider"
|
||||
"github.com/cs3org/reva/v2/pkg/appctx"
|
||||
"github.com/cs3org/reva/v2/pkg/conversions"
|
||||
@@ -54,10 +59,6 @@ import (
|
||||
"github.com/cs3org/reva/v2/pkg/storage/fs/registry"
|
||||
"github.com/cs3org/reva/v2/pkg/storage/utils/chunking"
|
||||
"github.com/cs3org/reva/v2/pkg/storage/utils/templates"
|
||||
"github.com/mitchellh/mapstructure"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/pkg/xattr"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -1544,32 +1545,60 @@ func (fs *owncloudsqlfs) archiveRevision(ctx context.Context, vbp string, ip str
|
||||
return err
|
||||
}
|
||||
|
||||
func (fs *owncloudsqlfs) Download(ctx context.Context, ref *provider.Reference) (io.ReadCloser, error) {
|
||||
func (fs *owncloudsqlfs) Download(ctx context.Context, ref *provider.Reference, openReaderfunc func(*provider.ResourceInfo) bool) (*provider.ResourceInfo, io.ReadCloser, error) {
|
||||
ip, err := fs.resolve(ctx, ref)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "owncloudsql: error resolving reference")
|
||||
return nil, nil, errors.Wrap(err, "owncloudsql: error resolving reference")
|
||||
}
|
||||
p := fs.toStoragePath(ctx, ip)
|
||||
|
||||
// If Download is called for a path shared with the user then the path is
|
||||
// already wrapped. (fs.resolve wraps the path)
|
||||
if strings.HasPrefix(p, fs.c.DataDirectory) {
|
||||
ip = p
|
||||
}
|
||||
|
||||
// check permissions
|
||||
if perm, err := fs.readPermissions(ctx, ip); err == nil {
|
||||
if !perm.InitiateFileDownload {
|
||||
return nil, errtypes.PermissionDenied("")
|
||||
return nil, nil, errtypes.PermissionDenied("")
|
||||
}
|
||||
} else {
|
||||
if isNotFound(err) {
|
||||
return nil, errtypes.NotFound(fs.toStoragePath(ctx, filepath.Dir(ip)))
|
||||
return nil, nil, errtypes.NotFound(fs.toStoragePath(ctx, filepath.Dir(ip)))
|
||||
}
|
||||
return nil, errors.Wrap(err, "owncloudsql: error reading permissions")
|
||||
return nil, nil, errors.Wrap(err, "owncloudsql: error reading permissions")
|
||||
}
|
||||
|
||||
ownerStorageID, err := fs.filecache.GetNumericStorageID(ctx, "home::"+fs.getOwner(ip))
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
entry, err := fs.filecache.Get(ctx, ownerStorageID, fs.toDatabasePath(ip))
|
||||
switch {
|
||||
case err == sql.ErrNoRows:
|
||||
return nil, nil, errtypes.NotFound(fs.toStoragePath(ctx, filepath.Dir(ip)))
|
||||
case err != nil:
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
md, err := fs.convertToResourceInfo(ctx, entry, ip, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
if !openReaderfunc(md) {
|
||||
return md, nil, nil
|
||||
}
|
||||
|
||||
r, err := os.Open(ip)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return nil, errtypes.NotFound(fs.toStoragePath(ctx, ip))
|
||||
return nil, nil, errtypes.NotFound(fs.toStoragePath(ctx, ip))
|
||||
}
|
||||
return nil, errors.Wrap(err, "owncloudsql: error reading "+ip)
|
||||
return nil, nil, errors.Wrap(err, "owncloudsql: error reading "+ip)
|
||||
}
|
||||
return r, nil
|
||||
return md, r, nil
|
||||
}
|
||||
|
||||
func (fs *owncloudsqlfs) ListRevisions(ctx context.Context, ref *provider.Reference) ([]*provider.FileVersion, error) {
|
||||
@@ -1623,8 +1652,8 @@ func (fs *owncloudsqlfs) ListRevisions(ctx context.Context, ref *provider.Refere
|
||||
return revisions, nil
|
||||
}
|
||||
|
||||
func (fs *owncloudsqlfs) DownloadRevision(ctx context.Context, ref *provider.Reference, revisionKey string) (io.ReadCloser, error) {
|
||||
return nil, errtypes.NotSupported("download revision")
|
||||
func (fs *owncloudsqlfs) DownloadRevision(ctx context.Context, ref *provider.Reference, revisionKey string, openReaderfunc func(*provider.ResourceInfo) bool) (*provider.ResourceInfo, io.ReadCloser, error) {
|
||||
return nil, nil, errtypes.NotSupported("download revision")
|
||||
}
|
||||
|
||||
func (fs *owncloudsqlfs) RestoreRevision(ctx context.Context, ref *provider.Reference, revisionKey string) error {
|
||||
|
||||
23
vendor/github.com/cs3org/reva/v2/pkg/storage/fs/s3/s3.go
generated
vendored
23
vendor/github.com/cs3org/reva/v2/pkg/storage/fs/s3/s3.go
generated
vendored
@@ -616,12 +616,21 @@ func (fs *s3FS) ListFolder(ctx context.Context, ref *provider.Reference, mdKeys,
|
||||
return finfos, nil
|
||||
}
|
||||
|
||||
func (fs *s3FS) Download(ctx context.Context, ref *provider.Reference) (io.ReadCloser, error) {
|
||||
func (fs *s3FS) Download(ctx context.Context, ref *provider.Reference, openReaderfunc func(*provider.ResourceInfo) bool) (*provider.ResourceInfo, io.ReadCloser, error) {
|
||||
log := appctx.GetLogger(ctx)
|
||||
|
||||
fn, err := fs.resolve(ctx, ref)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error resolving ref")
|
||||
return nil, nil, errors.Wrap(err, "error resolving ref")
|
||||
}
|
||||
|
||||
ri, err := fs.GetMD(ctx, ref, nil, []string{"size", "mimetype", "etag"})
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err, "error getting metadata")
|
||||
}
|
||||
|
||||
if !openReaderfunc(ri) {
|
||||
return ri, nil, nil
|
||||
}
|
||||
|
||||
// use GetObject instead of s3manager.Downloader:
|
||||
@@ -637,20 +646,20 @@ func (fs *s3FS) Download(ctx context.Context, ref *provider.Reference) (io.ReadC
|
||||
switch aerr.Code() {
|
||||
case s3.ErrCodeNoSuchBucket:
|
||||
case s3.ErrCodeNoSuchKey:
|
||||
return nil, errtypes.NotFound(fn)
|
||||
return nil, nil, errtypes.NotFound(fn)
|
||||
}
|
||||
}
|
||||
return nil, errors.Wrap(err, "s3fs: error deleting "+fn)
|
||||
return nil, nil, errors.Wrap(err, "s3fs: error deleting "+fn)
|
||||
}
|
||||
return r.Body, nil
|
||||
return ri, r.Body, nil
|
||||
}
|
||||
|
||||
func (fs *s3FS) ListRevisions(ctx context.Context, ref *provider.Reference) ([]*provider.FileVersion, error) {
|
||||
return nil, errtypes.NotSupported("list revisions")
|
||||
}
|
||||
|
||||
func (fs *s3FS) DownloadRevision(ctx context.Context, ref *provider.Reference, revisionKey string) (io.ReadCloser, error) {
|
||||
return nil, errtypes.NotSupported("download revision")
|
||||
func (fs *s3FS) DownloadRevision(ctx context.Context, ref *provider.Reference, revisionKey string, openReaderfunc func(*provider.ResourceInfo) bool) (*provider.ResourceInfo, io.ReadCloser, error) {
|
||||
return nil, nil, errtypes.NotSupported("download revision")
|
||||
}
|
||||
|
||||
func (fs *s3FS) RestoreRevision(ctx context.Context, ref *provider.Reference, revisionKey string) error {
|
||||
|
||||
7
vendor/github.com/cs3org/reva/v2/pkg/storage/storage.go
generated
vendored
7
vendor/github.com/cs3org/reva/v2/pkg/storage/storage.go
generated
vendored
@@ -23,10 +23,9 @@ import (
|
||||
"io"
|
||||
"net/url"
|
||||
|
||||
tusd "github.com/tus/tusd/v2/pkg/handler"
|
||||
|
||||
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
|
||||
registry "github.com/cs3org/go-cs3apis/cs3/storage/registry/v1beta1"
|
||||
tusd "github.com/tus/tusd/v2/pkg/handler"
|
||||
)
|
||||
|
||||
// FS is the interface to implement access to the storage.
|
||||
@@ -48,7 +47,7 @@ type FS interface {
|
||||
// ListFolder returns the resource infos for all children of the referenced resource
|
||||
ListFolder(ctx context.Context, ref *provider.Reference, mdKeys, fieldMask []string) ([]*provider.ResourceInfo, error)
|
||||
// Download returns a ReadCloser for the content of the referenced resource
|
||||
Download(ctx context.Context, ref *provider.Reference) (io.ReadCloser, error)
|
||||
Download(ctx context.Context, ref *provider.Reference, openReaderfunc func(*provider.ResourceInfo) bool) (*provider.ResourceInfo, io.ReadCloser, error)
|
||||
|
||||
// GetPathByID returns the path for the given resource id relative to the space root
|
||||
// It should only reveal the path visible to the current user to not leak the names uf unshared parent resources
|
||||
@@ -80,7 +79,7 @@ type FS interface {
|
||||
// ListRevisions lists all revisions for the referenced resource
|
||||
ListRevisions(ctx context.Context, ref *provider.Reference) ([]*provider.FileVersion, error)
|
||||
// DownloadRevision downloads a revision
|
||||
DownloadRevision(ctx context.Context, ref *provider.Reference, key string) (io.ReadCloser, error)
|
||||
DownloadRevision(ctx context.Context, ref *provider.Reference, key string, openReaderFunc func(md *provider.ResourceInfo) bool) (*provider.ResourceInfo, io.ReadCloser, error)
|
||||
// RestoreRevision restores a revision
|
||||
RestoreRevision(ctx context.Context, ref *provider.Reference, key string) error
|
||||
|
||||
|
||||
53
vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/decomposedfs.go
generated
vendored
53
vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/decomposedfs.go
generated
vendored
@@ -33,13 +33,20 @@ import (
|
||||
user "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
|
||||
rpcv1beta1 "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1"
|
||||
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
|
||||
"github.com/jellydator/ttlcache/v2"
|
||||
"github.com/pkg/errors"
|
||||
tusd "github.com/tus/tusd/v2/pkg/handler"
|
||||
microstore "go-micro.dev/v4/store"
|
||||
"go.opentelemetry.io/otel"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
"golang.org/x/sync/errgroup"
|
||||
|
||||
ctxpkg "github.com/cs3org/reva/v2/pkg/ctx"
|
||||
"github.com/cs3org/reva/v2/pkg/errtypes"
|
||||
"github.com/cs3org/reva/v2/pkg/events"
|
||||
"github.com/cs3org/reva/v2/pkg/logger"
|
||||
"github.com/cs3org/reva/v2/pkg/rgrpc/todo/pool"
|
||||
"github.com/cs3org/reva/v2/pkg/rhttp/datatx/metrics"
|
||||
"github.com/cs3org/reva/v2/pkg/rhttp/datatx/utils/download"
|
||||
"github.com/cs3org/reva/v2/pkg/storage"
|
||||
"github.com/cs3org/reva/v2/pkg/storage/utils/chunking"
|
||||
"github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/aspects"
|
||||
@@ -60,13 +67,6 @@ import (
|
||||
"github.com/cs3org/reva/v2/pkg/storagespace"
|
||||
"github.com/cs3org/reva/v2/pkg/store"
|
||||
"github.com/cs3org/reva/v2/pkg/utils"
|
||||
"github.com/jellydator/ttlcache/v2"
|
||||
"github.com/pkg/errors"
|
||||
tusd "github.com/tus/tusd/v2/pkg/handler"
|
||||
microstore "go-micro.dev/v4/store"
|
||||
"go.opentelemetry.io/otel"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
"golang.org/x/sync/errgroup"
|
||||
)
|
||||
|
||||
type CtxKey int
|
||||
@@ -1054,54 +1054,49 @@ func (fs *Decomposedfs) Delete(ctx context.Context, ref *provider.Reference) (er
|
||||
}
|
||||
|
||||
// Download returns a reader to the specified resource
|
||||
func (fs *Decomposedfs) Download(ctx context.Context, ref *provider.Reference) (io.ReadCloser, error) {
|
||||
func (fs *Decomposedfs) Download(ctx context.Context, ref *provider.Reference, openReaderFunc func(md *provider.ResourceInfo) bool) (*provider.ResourceInfo, io.ReadCloser, error) {
|
||||
ctx, span := tracer.Start(ctx, "Download")
|
||||
defer span.End()
|
||||
// check if we are trying to download a revision
|
||||
// TODO the CS3 api should allow initiating a revision download
|
||||
if ref.ResourceId != nil && strings.Contains(ref.ResourceId.OpaqueId, node.RevisionIDDelimiter) {
|
||||
return fs.DownloadRevision(ctx, ref, ref.ResourceId.OpaqueId)
|
||||
return fs.DownloadRevision(ctx, ref, ref.ResourceId.OpaqueId, openReaderFunc)
|
||||
}
|
||||
|
||||
n, err := fs.lu.NodeFromResource(ctx, ref)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "Decomposedfs: error resolving ref")
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
if !n.Exists {
|
||||
err = errtypes.NotFound(filepath.Join(n.ParentID, n.Name))
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
rp, err := fs.p.AssemblePermissions(ctx, n)
|
||||
switch {
|
||||
case err != nil:
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
case !rp.InitiateFileDownload:
|
||||
f, _ := storagespace.FormatReference(ref)
|
||||
if rp.Stat {
|
||||
return nil, errtypes.PermissionDenied(f)
|
||||
return nil, nil, errtypes.PermissionDenied(f)
|
||||
}
|
||||
return nil, errtypes.NotFound(f)
|
||||
return nil, nil, errtypes.NotFound(f)
|
||||
}
|
||||
|
||||
mtime, err := n.GetMTime(ctx)
|
||||
ri, err := n.AsResourceInfo(ctx, rp, nil, []string{"size", "mimetype", "etag"}, true)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "Decomposedfs: error getting mtime for '"+n.ID+"'")
|
||||
return nil, nil, err
|
||||
}
|
||||
currentEtag, err := node.CalculateEtag(n.ID, mtime)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "Decomposedfs: error calculating etag for '"+n.ID+"'")
|
||||
var reader io.ReadCloser
|
||||
if openReaderFunc(ri) {
|
||||
reader, err = fs.tp.ReadBlob(n)
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err, "Decomposedfs: error download blob '"+n.ID+"'")
|
||||
}
|
||||
}
|
||||
expectedEtag := download.EtagFromContext(ctx)
|
||||
if currentEtag != expectedEtag {
|
||||
return nil, errtypes.Aborted(fmt.Sprintf("file changed from etag %s to %s", expectedEtag, currentEtag))
|
||||
}
|
||||
reader, err := fs.tp.ReadBlob(n)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "Decomposedfs: error download blob '"+n.ID+"'")
|
||||
}
|
||||
return reader, nil
|
||||
return ri, reader, nil
|
||||
}
|
||||
|
||||
// GetLock returns an existing lock on the given reference
|
||||
|
||||
48
vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/revisions.go
generated
vendored
48
vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/revisions.go
generated
vendored
@@ -27,13 +27,15 @@ import (
|
||||
"time"
|
||||
|
||||
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/rogpeppe/go-internal/lockedfile"
|
||||
|
||||
"github.com/cs3org/reva/v2/pkg/appctx"
|
||||
"github.com/cs3org/reva/v2/pkg/errtypes"
|
||||
"github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/metadata/prefixes"
|
||||
"github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/node"
|
||||
"github.com/cs3org/reva/v2/pkg/storagespace"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/rogpeppe/go-internal/lockedfile"
|
||||
"github.com/cs3org/reva/v2/pkg/utils"
|
||||
)
|
||||
|
||||
// Revision entries are stored inside the node folder and start with the same uuid as the current version.
|
||||
@@ -112,14 +114,14 @@ func (fs *Decomposedfs) ListRevisions(ctx context.Context, ref *provider.Referen
|
||||
|
||||
// DownloadRevision returns a reader for the specified revision
|
||||
// FIXME the CS3 api should explicitly allow initiating revision and trash download, a related issue is https://github.com/cs3org/reva/issues/1813
|
||||
func (fs *Decomposedfs) DownloadRevision(ctx context.Context, ref *provider.Reference, revisionKey string) (io.ReadCloser, error) {
|
||||
func (fs *Decomposedfs) DownloadRevision(ctx context.Context, ref *provider.Reference, revisionKey string, openReaderFunc func(md *provider.ResourceInfo) bool) (*provider.ResourceInfo, io.ReadCloser, error) {
|
||||
log := appctx.GetLogger(ctx)
|
||||
|
||||
// verify revision key format
|
||||
kp := strings.SplitN(revisionKey, node.RevisionIDDelimiter, 2)
|
||||
if len(kp) != 2 {
|
||||
log.Error().Str("revisionKey", revisionKey).Msg("malformed revisionKey")
|
||||
return nil, errtypes.NotFound(revisionKey)
|
||||
return nil, nil, errtypes.NotFound(revisionKey)
|
||||
}
|
||||
log.Debug().Str("revisionKey", revisionKey).Msg("DownloadRevision")
|
||||
|
||||
@@ -127,39 +129,59 @@ func (fs *Decomposedfs) DownloadRevision(ctx context.Context, ref *provider.Refe
|
||||
// check if the node is available and has not been deleted
|
||||
n, err := node.ReadNode(ctx, fs.lu, spaceID, kp[0], false, nil, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
if !n.Exists {
|
||||
err = errtypes.NotFound(filepath.Join(n.ParentID, n.Name))
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
rp, err := fs.p.AssemblePermissions(ctx, n)
|
||||
switch {
|
||||
case err != nil:
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
case !rp.ListFileVersions || !rp.InitiateFileDownload: // TODO add explicit permission in the CS3 api?
|
||||
f, _ := storagespace.FormatReference(ref)
|
||||
if rp.Stat {
|
||||
return nil, errtypes.PermissionDenied(f)
|
||||
return nil, nil, errtypes.PermissionDenied(f)
|
||||
}
|
||||
return nil, errtypes.NotFound(f)
|
||||
return nil, nil, errtypes.NotFound(f)
|
||||
}
|
||||
|
||||
contentPath := fs.lu.InternalPath(spaceID, revisionKey)
|
||||
|
||||
blobid, blobsize, err := fs.lu.ReadBlobIDAndSizeAttr(ctx, contentPath, nil)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "Decomposedfs: could not read blob id and size for revision '%s' of node '%s'", n.ID, revisionKey)
|
||||
return nil, nil, errors.Wrapf(err, "Decomposedfs: could not read blob id and size for revision '%s' of node '%s'", kp[1], n.ID)
|
||||
}
|
||||
|
||||
revisionNode := node.Node{SpaceID: spaceID, BlobID: blobid, Blobsize: blobsize} // blobsize is needed for the s3ng blobstore
|
||||
|
||||
reader, err := fs.tp.ReadBlob(&revisionNode)
|
||||
ri, err := n.AsResourceInfo(ctx, rp, nil, []string{"size", "mimetype", "etag"}, true)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "Decomposedfs: could not download blob of revision '%s' for node '%s'", n.ID, revisionKey)
|
||||
return nil, nil, err
|
||||
}
|
||||
return reader, nil
|
||||
|
||||
// update resource info with revision data
|
||||
mtime, err := time.Parse(time.RFC3339Nano, kp[1])
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrapf(err, "Decomposedfs: could not parse mtime for revision '%s' of node '%s'", kp[1], n.ID)
|
||||
}
|
||||
ri.Size = uint64(blobsize)
|
||||
ri.Mtime = utils.TimeToTS(mtime)
|
||||
ri.Etag, err = node.CalculateEtag(n.ID, mtime)
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrapf(err, "error calculating etag for revision '%s' of node '%s'", kp[1], n.ID)
|
||||
}
|
||||
|
||||
var reader io.ReadCloser
|
||||
if openReaderFunc(ri) {
|
||||
reader, err = fs.tp.ReadBlob(&revisionNode)
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrapf(err, "Decomposedfs: could not download blob of revision '%s' for node '%s'", n.ID, revisionKey)
|
||||
}
|
||||
}
|
||||
return ri, reader, nil
|
||||
}
|
||||
|
||||
// RestoreRevision restores the specified revision of the resource
|
||||
|
||||
4
vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/upload.go
generated
vendored
4
vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/upload.go
generated
vendored
@@ -228,6 +228,10 @@ func (fs *Decomposedfs) InitiateUpload(ctx context.Context, ref *provider.Refere
|
||||
}
|
||||
}
|
||||
|
||||
if session.MTime().IsZero() {
|
||||
session.SetMetadata("mtime", utils.TimeToOCMtime(time.Now()))
|
||||
}
|
||||
|
||||
log.Debug().Str("uploadid", session.ID()).Str("spaceid", n.SpaceID).Str("nodeid", n.ID).Interface("metadata", metadata).Msg("Decomposedfs: resolved filename")
|
||||
|
||||
_, err = node.CheckQuota(ctx, n.SpaceRoot, n.Exists, uint64(n.Blobsize), uint64(session.Size()))
|
||||
|
||||
42
vendor/github.com/cs3org/reva/v2/pkg/storage/utils/eosfs/eosfs.go
generated
vendored
42
vendor/github.com/cs3org/reva/v2/pkg/storage/utils/eosfs/eosfs.go
generated
vendored
@@ -1834,13 +1834,23 @@ func (fs *eosfs) moveShadow(ctx context.Context, oldPath, newPath string) error
|
||||
return fs.c.Rename(ctx, auth, oldfn, newfn)
|
||||
}
|
||||
|
||||
func (fs *eosfs) Download(ctx context.Context, ref *provider.Reference) (io.ReadCloser, error) {
|
||||
func (fs *eosfs) Download(ctx context.Context, ref *provider.Reference, openReaderfunc func(*provider.ResourceInfo) bool) (*provider.ResourceInfo, io.ReadCloser, error) {
|
||||
fn, auth, err := fs.resolveRefForbidShareFolder(ctx, ref)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
return fs.c.Read(ctx, auth, fn)
|
||||
md, err := fs.GetMD(ctx, ref, nil, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
if !openReaderfunc(md) {
|
||||
return md, nil, nil
|
||||
}
|
||||
|
||||
reader, err := fs.c.Read(ctx, auth, fn)
|
||||
return md, reader, err
|
||||
}
|
||||
|
||||
func (fs *eosfs) ListRevisions(ctx context.Context, ref *provider.Reference) ([]*provider.FileVersion, error) {
|
||||
@@ -1886,37 +1896,43 @@ func (fs *eosfs) ListRevisions(ctx context.Context, ref *provider.Reference) ([]
|
||||
return revisions, nil
|
||||
}
|
||||
|
||||
func (fs *eosfs) DownloadRevision(ctx context.Context, ref *provider.Reference, revisionKey string) (io.ReadCloser, error) {
|
||||
func (fs *eosfs) DownloadRevision(ctx context.Context, ref *provider.Reference, revisionKey string, openReaderfunc func(*provider.ResourceInfo) bool) (*provider.ResourceInfo, io.ReadCloser, error) {
|
||||
var auth eosclient.Authorization
|
||||
var fn string
|
||||
var err error
|
||||
|
||||
md, err := fs.GetMD(ctx, ref, nil, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
if !fs.conf.EnableHome && fs.conf.ImpersonateOwnerforRevisions {
|
||||
// We need to access the revisions for a non-home reference.
|
||||
// We'll get the owner of the particular resource and impersonate them
|
||||
// if we have access to it.
|
||||
md, err := fs.GetMD(ctx, ref, nil, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fn = fs.wrap(ctx, md.Path)
|
||||
|
||||
fn = fs.wrap(ctx, md.Path)
|
||||
if md.PermissionSet.InitiateFileDownload {
|
||||
auth, err = fs.getUIDGateway(ctx, md.Owner)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
} else {
|
||||
return nil, errtypes.PermissionDenied("eosfs: user doesn't have permissions to download revisions")
|
||||
return nil, nil, errtypes.PermissionDenied("eosfs: user doesn't have permissions to download revisions")
|
||||
}
|
||||
} else {
|
||||
fn, auth, err = fs.resolveRefForbidShareFolder(ctx, ref)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return fs.c.ReadVersion(ctx, auth, fn, revisionKey)
|
||||
if !openReaderfunc(md) {
|
||||
return md, nil, nil
|
||||
}
|
||||
|
||||
reader, err := fs.c.ReadVersion(ctx, auth, fn, revisionKey)
|
||||
return md, reader, err
|
||||
}
|
||||
|
||||
func (fs *eosfs) RestoreRevision(ctx context.Context, ref *provider.Reference, revisionKey string) error {
|
||||
|
||||
57
vendor/github.com/cs3org/reva/v2/pkg/storage/utils/localfs/localfs.go
generated
vendored
57
vendor/github.com/cs3org/reva/v2/pkg/storage/utils/localfs/localfs.go
generated
vendored
@@ -1045,25 +1045,42 @@ func (fs *localfs) listShareFolderRoot(ctx context.Context, home string, mdKeys
|
||||
return finfos, nil
|
||||
}
|
||||
|
||||
func (fs *localfs) Download(ctx context.Context, ref *provider.Reference) (io.ReadCloser, error) {
|
||||
func (fs *localfs) Download(ctx context.Context, ref *provider.Reference, openReaderfunc func(*provider.ResourceInfo) bool) (*provider.ResourceInfo, io.ReadCloser, error) {
|
||||
fn, err := fs.resolve(ctx, ref)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "localfs: error resolving ref")
|
||||
return nil, nil, errors.Wrap(err, "localfs: error resolving ref")
|
||||
}
|
||||
|
||||
if fs.isShareFolder(ctx, fn) {
|
||||
return nil, errtypes.PermissionDenied("localfs: cannot download under the virtual share folder")
|
||||
return nil, nil, errtypes.PermissionDenied("localfs: cannot download under the virtual share folder")
|
||||
}
|
||||
|
||||
fn = fs.wrap(ctx, fn)
|
||||
md, err := os.Stat(fn)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return nil, nil, errtypes.NotFound(fn)
|
||||
}
|
||||
return nil, nil, errors.Wrap(err, "localfs: error stating "+fn)
|
||||
}
|
||||
|
||||
ri, err := fs.normalize(ctx, md, fn, []string{"size", "mimetype", "etag"})
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
if !openReaderfunc(ri) {
|
||||
return ri, nil, nil
|
||||
}
|
||||
|
||||
r, err := os.Open(fn)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return nil, errtypes.NotFound(fn)
|
||||
return nil, nil, errtypes.NotFound(fn)
|
||||
}
|
||||
return nil, errors.Wrap(err, "localfs: error reading "+fn)
|
||||
return nil, nil, errors.Wrap(err, "localfs: error reading "+fn)
|
||||
}
|
||||
return r, nil
|
||||
return ri, r, nil
|
||||
}
|
||||
|
||||
func (fs *localfs) archiveRevision(ctx context.Context, np string) error {
|
||||
@@ -1117,28 +1134,42 @@ func (fs *localfs) ListRevisions(ctx context.Context, ref *provider.Reference) (
|
||||
return revisions, nil
|
||||
}
|
||||
|
||||
func (fs *localfs) DownloadRevision(ctx context.Context, ref *provider.Reference, revisionKey string) (io.ReadCloser, error) {
|
||||
func (fs *localfs) DownloadRevision(ctx context.Context, ref *provider.Reference, revisionKey string, openReaderfunc func(*provider.ResourceInfo) bool) (*provider.ResourceInfo, io.ReadCloser, error) {
|
||||
np, err := fs.resolve(ctx, ref)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "localfs: error resolving ref")
|
||||
return nil, nil, errors.Wrap(err, "localfs: error resolving ref")
|
||||
}
|
||||
|
||||
if fs.isShareFolder(ctx, np) {
|
||||
return nil, errtypes.PermissionDenied("localfs: cannot download revisions under the virtual share folder")
|
||||
return nil, nil, errtypes.PermissionDenied("localfs: cannot download revisions under the virtual share folder")
|
||||
}
|
||||
|
||||
versionsDir := fs.wrapVersions(ctx, np)
|
||||
vp := path.Join(versionsDir, revisionKey)
|
||||
|
||||
r, err := os.Open(vp)
|
||||
md, err := os.Stat(vp)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return nil, errtypes.NotFound(vp)
|
||||
return nil, nil, errtypes.NotFound(vp)
|
||||
}
|
||||
return nil, errors.Wrap(err, "localfs: error reading "+vp)
|
||||
return nil, nil, errors.Wrap(err, "localfs: error stating "+vp)
|
||||
}
|
||||
|
||||
return r, nil
|
||||
ri, err := fs.normalize(ctx, md, vp, []string{"size", "mimetype", "etag"})
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
if !openReaderfunc(ri) {
|
||||
return ri, nil, nil
|
||||
}
|
||||
|
||||
r, err := os.Open(vp)
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err, "localfs: error reading "+vp)
|
||||
}
|
||||
|
||||
return ri, r, nil
|
||||
}
|
||||
|
||||
func (fs *localfs) RestoreRevision(ctx context.Context, ref *provider.Reference, revisionKey string) error {
|
||||
|
||||
9
vendor/github.com/cs3org/reva/v2/pkg/storage/utils/metadata/cs3.go
generated
vendored
9
vendor/github.com/cs3org/reva/v2/pkg/storage/utils/metadata/cs3.go
generated
vendored
@@ -34,14 +34,15 @@ import (
|
||||
rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1"
|
||||
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
|
||||
types "github.com/cs3org/go-cs3apis/cs3/types/v1beta1"
|
||||
"go.opentelemetry.io/otel"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
"google.golang.org/grpc/metadata"
|
||||
|
||||
"github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/net"
|
||||
ctxpkg "github.com/cs3org/reva/v2/pkg/ctx"
|
||||
"github.com/cs3org/reva/v2/pkg/errtypes"
|
||||
"github.com/cs3org/reva/v2/pkg/rgrpc/todo/pool"
|
||||
"github.com/cs3org/reva/v2/pkg/utils"
|
||||
"go.opentelemetry.io/otel"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
"google.golang.org/grpc/metadata"
|
||||
)
|
||||
|
||||
var tracer trace.Tracer
|
||||
@@ -212,7 +213,7 @@ func (cs3 *CS3) Upload(ctx context.Context, req UploadRequest) (*UploadResponse,
|
||||
}
|
||||
if req.MTime != (time.Time{}) {
|
||||
// The format of the X-OC-Mtime header is <epoch>.<nanoseconds>, e.g. '1691053416.934129485'
|
||||
ifuReq.Opaque = utils.AppendPlainToOpaque(ifuReq.Opaque, "X-OC-Mtime", strconv.Itoa(int(req.MTime.Unix()))+"."+strconv.Itoa(req.MTime.Nanosecond()))
|
||||
ifuReq.Opaque = utils.AppendPlainToOpaque(ifuReq.Opaque, "X-OC-Mtime", utils.TimeToOCMtime(req.MTime))
|
||||
}
|
||||
|
||||
ifuReq.Opaque = utils.AppendPlainToOpaque(ifuReq.Opaque, net.HeaderUploadLength, strconv.FormatInt(int64(len(req.Content)), 10))
|
||||
|
||||
22
vendor/github.com/cs3org/reva/v2/pkg/storage/utils/middleware/middleware.go
generated
vendored
22
vendor/github.com/cs3org/reva/v2/pkg/storage/utils/middleware/middleware.go
generated
vendored
@@ -23,9 +23,9 @@ import (
|
||||
"io"
|
||||
"net/url"
|
||||
|
||||
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
|
||||
tusd "github.com/tus/tusd/v2/pkg/handler"
|
||||
|
||||
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
|
||||
"github.com/cs3org/reva/v2/pkg/storage"
|
||||
"github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/upload"
|
||||
"github.com/cs3org/reva/v2/pkg/storagespace"
|
||||
@@ -361,7 +361,7 @@ func (f *FS) Upload(ctx context.Context, req storage.UploadRequest, uploadFunc s
|
||||
return res0, res1
|
||||
}
|
||||
|
||||
func (f *FS) Download(ctx context.Context, ref *provider.Reference) (io.ReadCloser, error) {
|
||||
func (f *FS) Download(ctx context.Context, ref *provider.Reference, openReaderFunc func(md *provider.ResourceInfo) bool) (*provider.ResourceInfo, io.ReadCloser, error) {
|
||||
var (
|
||||
err error
|
||||
unhook UnHook
|
||||
@@ -370,22 +370,22 @@ func (f *FS) Download(ctx context.Context, ref *provider.Reference) (io.ReadClos
|
||||
for _, hook := range f.hooks {
|
||||
ctx, unhook, err = hook("Download", ctx, ref.GetResourceId().GetSpaceId())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
if unhook != nil {
|
||||
unhooks = append(unhooks, unhook)
|
||||
}
|
||||
}
|
||||
|
||||
res0, res1 := f.next.Download(ctx, ref)
|
||||
res0, res1, res2 := f.next.Download(ctx, ref, openReaderFunc)
|
||||
|
||||
for _, unhook := range unhooks {
|
||||
if err := unhook(); err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return res0, res1
|
||||
return res0, res1, res2
|
||||
}
|
||||
|
||||
func (f *FS) ListRevisions(ctx context.Context, ref *provider.Reference) ([]*provider.FileVersion, error) {
|
||||
@@ -415,7 +415,7 @@ func (f *FS) ListRevisions(ctx context.Context, ref *provider.Reference) ([]*pro
|
||||
return res0, res1
|
||||
}
|
||||
|
||||
func (f *FS) DownloadRevision(ctx context.Context, ref *provider.Reference, key string) (io.ReadCloser, error) {
|
||||
func (f *FS) DownloadRevision(ctx context.Context, ref *provider.Reference, key string, openReaderFunc func(md *provider.ResourceInfo) bool) (*provider.ResourceInfo, io.ReadCloser, error) {
|
||||
var (
|
||||
err error
|
||||
unhook UnHook
|
||||
@@ -424,22 +424,22 @@ func (f *FS) DownloadRevision(ctx context.Context, ref *provider.Reference, key
|
||||
for _, hook := range f.hooks {
|
||||
ctx, unhook, err = hook("DownloadRevision", ctx, ref.GetResourceId().GetSpaceId())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
if unhook != nil {
|
||||
unhooks = append(unhooks, unhook)
|
||||
}
|
||||
}
|
||||
|
||||
res0, res1 := f.next.DownloadRevision(ctx, ref, key)
|
||||
res0, res1, res2 := f.next.DownloadRevision(ctx, ref, key, openReaderFunc)
|
||||
|
||||
for _, unhook := range unhooks {
|
||||
if err := unhook(); err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return res0, res1
|
||||
return res0, res1, res2
|
||||
}
|
||||
|
||||
func (f *FS) RestoreRevision(ctx context.Context, ref *provider.Reference, key string) error {
|
||||
|
||||
5
vendor/github.com/cs3org/reva/v2/pkg/utils/utils.go
generated
vendored
5
vendor/github.com/cs3org/reva/v2/pkg/utils/utils.go
generated
vendored
@@ -201,6 +201,11 @@ func MTimeToTime(v string) (t time.Time, err error) {
|
||||
return time.Unix(sec, nsec), err
|
||||
}
|
||||
|
||||
// TimeToOCMtime converts a Go time.Time to a string in the form "<unix>.<nanoseconds>"
|
||||
func TimeToOCMtime(t time.Time) string {
|
||||
return strconv.FormatInt(t.Unix(), 10) + "." + strconv.FormatInt(int64(t.Nanosecond()), 10)
|
||||
}
|
||||
|
||||
// ExtractGranteeID returns the ID, user or group, set in the GranteeId object
|
||||
func ExtractGranteeID(grantee *provider.Grantee) (*userpb.UserId, *grouppb.GroupId) {
|
||||
switch t := grantee.Id.(type) {
|
||||
|
||||
2
vendor/modules.txt
vendored
2
vendor/modules.txt
vendored
@@ -367,7 +367,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.26.5-0.20241111162950-e77dd61e7edb
|
||||
# github.com/cs3org/reva/v2 v2.26.5
|
||||
## explicit; go 1.22.0
|
||||
github.com/cs3org/reva/v2/cmd/revad/internal/grace
|
||||
github.com/cs3org/reva/v2/cmd/revad/runtime
|
||||
|
||||
Reference in New Issue
Block a user