feat(reva): bump reva

Signed-off-by: jkoberg <jkoberg@owncloud.com>
This commit is contained in:
jkoberg
2024-08-07 09:13:13 +02:00
parent 3626621c9d
commit 0ad0d9bf78
53 changed files with 6396 additions and 69 deletions
@@ -127,7 +127,7 @@ func (s *svc) handlePathCopy(w http.ResponseWriter, r *http.Request, ns string)
return
}
cp := s.prepareCopy(ctx, w, r, spacelookup.MakeRelativeReference(srcSpace, src, false), spacelookup.MakeRelativeReference(dstSpace, dst, false), &sublog)
cp := s.prepareCopy(ctx, w, r, spacelookup.MakeRelativeReference(srcSpace, src, false), spacelookup.MakeRelativeReference(dstSpace, dst, false), &sublog, dstSpace.GetRoot().GetStorageId() == utils.ShareStorageProviderID)
if cp == nil {
return
}
@@ -362,7 +362,7 @@ func (s *svc) handleSpacesCopy(w http.ResponseWriter, r *http.Request, spaceID s
return
}
cp := s.prepareCopy(ctx, w, r, &srcRef, &dstRef, &sublog)
cp := s.prepareCopy(ctx, w, r, &srcRef, &dstRef, &sublog, dstRef.GetResourceId().GetStorageId() == utils.ShareStorageProviderID)
if cp == nil {
return
}
@@ -552,7 +552,7 @@ func (s *svc) executeSpacesCopy(ctx context.Context, w http.ResponseWriter, sele
return nil
}
func (s *svc) prepareCopy(ctx context.Context, w http.ResponseWriter, r *http.Request, srcRef, dstRef *provider.Reference, log *zerolog.Logger) *copy {
func (s *svc) prepareCopy(ctx context.Context, w http.ResponseWriter, r *http.Request, srcRef, dstRef *provider.Reference, log *zerolog.Logger, destInShareJail bool) *copy {
isChild, err := s.referenceIsChildOf(ctx, s.gatewaySelector, dstRef, srcRef)
if err != nil {
switch err.(type) {
@@ -675,11 +675,6 @@ func (s *svc) prepareCopy(ctx context.Context, w http.ResponseWriter, r *http.Re
if dstStatRes.Status.Code == rpc.Code_CODE_OK {
successCode = http.StatusNoContent // 204 if target already existed, see https://tools.ietf.org/html/rfc4918#section-9.8.5
if utils.IsSpaceRoot(dstStatRes.GetInfo()) {
log.Error().Msg("overwriting is not allowed")
w.WriteHeader(http.StatusBadRequest)
return nil
}
if !overwrite {
log.Warn().Bool("overwrite", overwrite).Msg("dst already exists")
w.WriteHeader(http.StatusPreconditionFailed)
@@ -688,10 +683,29 @@ func (s *svc) prepareCopy(ctx context.Context, w http.ResponseWriter, r *http.Re
errors.HandleWebdavError(log, w, b, err) // 412, see https://tools.ietf.org/html/rfc4918#section-9.8.5
return nil
}
if utils.IsSpaceRoot(dstStatRes.GetInfo()) {
log.Error().Msg("overwriting is not allowed")
w.WriteHeader(http.StatusBadRequest)
return nil
}
// delete existing tree when overwriting a directory or replacing a file with a directory
if dstStatRes.Info.Type == provider.ResourceType_RESOURCE_TYPE_CONTAINER ||
(dstStatRes.Info.Type == provider.ResourceType_RESOURCE_TYPE_FILE &&
srcStatRes.Info.Type == provider.ResourceType_RESOURCE_TYPE_CONTAINER) {
// we must not allow to override mountpoints - so we check if we have access to the parent. If not this is a mountpoint
if destInShareJail {
dir, file := filepath.Split(dstRef.GetPath())
if dir == "/" || dir == "" || file == "" {
log.Error().Msg("must not overwrite mount points")
w.WriteHeader(http.StatusBadRequest)
_, _ = w.Write([]byte("must not overwrite mount points"))
return nil
}
}
delReq := &provider.DeleteRequest{Ref: dstRef}
delRes, err := client.Delete(ctx, delReq)
if err != nil {
@@ -42,7 +42,7 @@ import (
"github.com/cs3org/reva/v2/pkg/storagespace"
"github.com/cs3org/reva/v2/pkg/utils"
"github.com/rs/zerolog"
tusd "github.com/tus/tusd/pkg/handler"
tusd "github.com/tus/tusd/v2/pkg/handler"
"go.opentelemetry.io/otel/propagation"
)
+2 -2
View File
@@ -35,7 +35,7 @@ import (
"strings"
"github.com/google/uuid"
tusd "github.com/tus/tusd/pkg/handler"
tusd "github.com/tus/tusd/v2/pkg/handler"
userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
@@ -266,7 +266,7 @@ func (u *upload) GetInfo(ctx context.Context) (tusd.FileInfo, error) {
return u.Info, nil
}
func (u *upload) GetReader(ctx context.Context) (io.Reader, error) {
func (u *upload) GetReader(ctx context.Context) (io.ReadCloser, error) {
return os.Open(u.BinPath())
}
+24
View File
@@ -0,0 +1,24 @@
package rgrpc
import (
"math"
"os"
"time"
)
const (
_serverMaxConnectionAgeEnv = "GRPC_MAX_CONNECTION_AGE"
// same default as grpc
infinity = time.Duration(math.MaxInt64)
_defaultMaxConnectionAge = infinity
)
// GetMaxConnectionAge returns the maximum grpc connection age.
func GetMaxConnectionAge() time.Duration {
d, err := time.ParseDuration(os.Getenv(_serverMaxConnectionAgeEnv))
if err != nil {
return _defaultMaxConnectionAge
}
return d
}
+4
View File
@@ -42,6 +42,7 @@ import (
"go.opentelemetry.io/otel/trace"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
"google.golang.org/grpc/keepalive"
"google.golang.org/grpc/reflection"
)
@@ -245,6 +246,9 @@ func (s *Server) registerServices() error {
if s.conf.TLSSettings.tlsConfig != nil {
opts = append(opts, grpc.Creds(credentials.NewTLS(s.conf.TLSSettings.tlsConfig)))
}
opts = append(opts, grpc.KeepaliveParams(keepalive.ServerParameters{
MaxConnectionAge: GetMaxConnectionAge(), // this forces clients to reconnect after 30 seconds, triggering a new DNS lookup to pick up new IPs
}))
grpcServer := grpc.NewServer(opts...)
+33 -3
View File
@@ -20,13 +20,13 @@ package tus
import (
"context"
"log"
"net/http"
"path"
"regexp"
"github.com/pkg/errors"
tusd "github.com/tus/tusd/pkg/handler"
"github.com/rs/zerolog"
tusd "github.com/tus/tusd/v2/pkg/handler"
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
"github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/net"
@@ -39,6 +39,7 @@ import (
"github.com/cs3org/reva/v2/pkg/storage"
"github.com/cs3org/reva/v2/pkg/storagespace"
"github.com/mitchellh/mapstructure"
"golang.org/x/exp/slog"
)
func init() {
@@ -99,7 +100,7 @@ func (m *manager) Handler(fs storage.FS) (http.Handler, error) {
config := tusd.Config{
StoreComposer: composer,
NotifyCompleteUploads: true,
Logger: log.New(appctx.GetLogger(context.Background()), "", 0),
Logger: slog.New(tusdLogger{log: appctx.GetLogger(context.Background())}), // Note: this is a noop logger
}
if m.conf.CorsEnabled {
@@ -222,3 +223,32 @@ func setHeaders(fs storage.FS, w http.ResponseWriter, r *http.Request) {
}
w.Header().Set(net.HeaderOCFileID, storagespace.FormatResourceID(resourceid))
}
// tusdLogger is a logger implementation (slog) for tusd that uses zerolog.
type tusdLogger struct {
log *zerolog.Logger
}
// Handle handles the record
func (l tusdLogger) Handle(_ context.Context, r slog.Record) error {
switch r.Level {
case slog.LevelDebug:
l.log.Debug().Msg(r.Message)
case slog.LevelInfo:
l.log.Info().Msg(r.Message)
case slog.LevelWarn:
l.log.Warn().Msg(r.Message)
case slog.LevelError:
l.log.Error().Msg(r.Message)
}
return nil
}
// Enabled returns true
func (l tusdLogger) Enabled(_ context.Context, _ slog.Level) bool { return true }
// WithAttrs is not implemented
func (l tusdLogger) WithAttrs(_ []slog.Attr) slog.Handler { return l }
// WithGroup is not implemented
func (l tusdLogger) WithGroup(_ string) slog.Handler { return l }
+2 -2
View File
@@ -39,7 +39,7 @@ import (
"github.com/cs3org/reva/v2/pkg/utils"
"github.com/google/uuid"
"github.com/pkg/errors"
tusd "github.com/tus/tusd/pkg/handler"
tusd "github.com/tus/tusd/v2/pkg/handler"
)
func (fs *cephfs) Upload(ctx context.Context, req storage.UploadRequest, uff storage.UploadFinishedFunc) (*provider.ResourceInfo, error) {
@@ -299,7 +299,7 @@ func (upload *fileUpload) GetInfo(ctx context.Context) (tusd.FileInfo, error) {
}
// GetReader returns an io.Reader for the upload
func (upload *fileUpload) GetReader(ctx context.Context) (file io.Reader, err error) {
func (upload *fileUpload) GetReader(ctx context.Context) (file io.ReadCloser, err error) {
user := upload.fs.makeUser(upload.ctx)
user.op(func(cv *cacheVal) {
file, err = cv.mount.Open(upload.binPath, os.O_RDONLY, 0)
+241
View File
@@ -0,0 +1,241 @@
// Copyright 2018-2021 CERN
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// In applying this license, CERN does not waive the privileges and immunities
// granted to it by virtue of its status as an Intergovernmental Organization
// or submit itself to any jurisdiction.
package hello
import (
"bytes"
"context"
"crypto/md5"
"encoding/binary"
"fmt"
"io"
"strings"
"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"
"github.com/cs3org/reva/v2/pkg/storage/fs/registry"
"github.com/cs3org/reva/v2/pkg/utils"
)
func init() {
registry.Register("hello", New)
}
type hellofs struct {
bootTime time.Time
}
const (
storageid = "hello-storage-id"
spaceid = "hello-space-id"
rootid = "hello-root-id"
fileid = "hello-file-id"
filename = "Hello world.txt"
content = "Hello world!"
)
func (fs *hellofs) space(withRoot bool) *provider.StorageSpace {
s := &provider.StorageSpace{
Id: &provider.StorageSpaceId{OpaqueId: spaceid},
Root: &provider.ResourceId{
StorageId: storageid,
SpaceId: spaceid,
OpaqueId: rootid,
},
Quota: &provider.Quota{
QuotaMaxBytes: uint64(len(content)),
QuotaMaxFiles: 1,
},
Name: "Hello Space",
SpaceType: "project",
RootInfo: fs.rootInfo(),
Mtime: utils.TimeToTS(fs.bootTime),
}
// FIXME move this to the CS3 API
s.Opaque = utils.AppendPlainToOpaque(s.Opaque, "spaceAlias", "project/hello")
if withRoot {
s.RootInfo = fs.rootInfo()
}
return s
}
func (fs *hellofs) rootInfo() *provider.ResourceInfo {
return &provider.ResourceInfo{
Type: provider.ResourceType_RESOURCE_TYPE_CONTAINER,
Id: &provider.ResourceId{
StorageId: storageid,
SpaceId: spaceid,
OpaqueId: rootid,
},
Etag: calcEtag(fs.bootTime, rootid),
MimeType: "httpd/unix-directory",
Mtime: utils.TimeToTS(fs.bootTime),
Path: ".",
PermissionSet: &provider.ResourcePermissions{
GetPath: true,
GetQuota: true,
InitiateFileDownload: true,
Stat: true,
ListContainer: true,
},
Size: uint64(len(content)),
}
}
func (fs *hellofs) fileInfo() *provider.ResourceInfo {
return &provider.ResourceInfo{
Type: provider.ResourceType_RESOURCE_TYPE_FILE,
Id: &provider.ResourceId{
StorageId: storageid,
SpaceId: spaceid,
OpaqueId: fileid,
},
Etag: calcEtag(fs.bootTime, fileid),
MimeType: "text/plain",
Mtime: utils.TimeToTS(fs.bootTime),
Path: ".",
PermissionSet: &provider.ResourcePermissions{
GetPath: true,
GetQuota: true,
InitiateFileDownload: true,
Stat: true,
ListContainer: true,
},
Size: uint64(len(content)),
ParentId: &provider.ResourceId{
StorageId: storageid,
SpaceId: spaceid,
OpaqueId: rootid,
},
Name: filename,
Space: fs.space(false),
}
}
func calcEtag(t time.Time, nodeid string) string {
h := md5.New()
_ = binary.Write(h, binary.BigEndian, t.Unix())
_ = binary.Write(h, binary.BigEndian, int64(t.Nanosecond()))
_ = binary.Write(h, binary.BigEndian, []byte(nodeid))
etag := fmt.Sprintf(`"%x"`, h.Sum(nil))
return fmt.Sprintf("\"%s\"", strings.Trim(etag, "\""))
}
// New returns an implementation to of the storage.FS interface that talks to
// a local filesystem with user homes disabled.
func New(_ map[string]interface{}, _ events.Stream) (storage.FS, error) {
return &hellofs{
bootTime: time.Now(),
}, nil
}
// Shutdown is called when the process is exiting to give the driver a chance to flush and close all open handles
func (fs *hellofs) Shutdown(ctx context.Context) error {
return nil
}
// ListStorageSpaces lists the spaces in the storage.
func (fs *hellofs) ListStorageSpaces(ctx context.Context, filter []*provider.ListStorageSpacesRequest_Filter, unrestricted bool) ([]*provider.StorageSpace, error) {
return []*provider.StorageSpace{fs.space(true)}, nil
}
// GetQuota returns the quota on the referenced resource
func (fs *hellofs) GetQuota(ctx context.Context, ref *provider.Reference) (uint64, uint64, uint64, error) {
return uint64(len(content)), uint64(len(content)), 0, nil
}
func (fs *hellofs) lookup(ctx context.Context, ref *provider.Reference) (*provider.ResourceInfo, error) {
if ref.GetResourceId().GetStorageId() != storageid || ref.GetResourceId().GetSpaceId() != spaceid {
return nil, errtypes.NotFound("")
}
// switch root or file
switch ref.GetResourceId().GetOpaqueId() {
case rootid:
switch ref.GetPath() {
case "", ".":
return fs.rootInfo(), nil
case filename:
return fs.fileInfo(), nil
default:
return nil, errtypes.NotFound("unknown filename")
}
case fileid:
return fs.fileInfo(), nil
}
return nil, errtypes.NotFound("unknown id")
}
// GetPathByID returns the path pointed by the file id
func (fs *hellofs) GetPathByID(ctx context.Context, resID *provider.ResourceId) (string, error) {
info, err := fs.lookup(ctx, &provider.Reference{ResourceId: resID})
if err != nil {
return "", err
}
return info.Path, nil
}
// GetMD returns the resuorce info for the referenced resource
func (fs *hellofs) GetMD(ctx context.Context, ref *provider.Reference, mdKeys []string, fieldMask []string) (*provider.ResourceInfo, error) {
return fs.lookup(ctx, ref)
}
// ListFolder returns the resource infos for all children of the referenced resource
func (fs *hellofs) ListFolder(ctx context.Context, ref *provider.Reference, mdKeys, fieldMask []string) ([]*provider.ResourceInfo, error) {
info, err := fs.lookup(ctx, ref)
if err != nil {
return nil, err
}
if info.Type != provider.ResourceType_RESOURCE_TYPE_CONTAINER {
return nil, errtypes.InternalError("expected a container")
}
if info.GetId().GetOpaqueId() != rootid {
return nil, errtypes.InternalError("unknown folder")
}
return []*provider.ResourceInfo{
fs.fileInfo(),
}, nil
}
// Download returns a ReadCloser for the content of the referenced resource
func (fs *hellofs) Download(ctx context.Context, ref *provider.Reference) (io.ReadCloser, error) {
info, err := fs.lookup(ctx, ref)
if err != nil {
return nil, err
}
if info.Type != provider.ResourceType_RESOURCE_TYPE_FILE {
return nil, errtypes.InternalError("expected a file")
}
if info.GetId().GetOpaqueId() != fileid {
return nil, errtypes.InternalError("unknown file")
}
b := &bytes.Buffer{}
b.WriteString(content)
return io.NopCloser(b), nil
}
+198
View File
@@ -0,0 +1,198 @@
// Copyright 2018-2021 CERN
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// In applying this license, CERN does not waive the privileges and immunities
// granted to it by virtue of its status as an Intergovernmental Organization
// or submit itself to any jurisdiction.
package hello
import (
"context"
"io"
"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"
)
// hellofs is readonly so these remain unimplemented
// CreateReference creates a resource of type reference
func (fs *hellofs) CreateReference(ctx context.Context, path string, targetURI *url.URL) error {
return errtypes.NotSupported("unimplemented")
}
// CreateStorageSpace creates a storage space
func (fs *hellofs) CreateStorageSpace(ctx context.Context, req *provider.CreateStorageSpaceRequest) (*provider.CreateStorageSpaceResponse, error) {
return nil, errtypes.NotSupported("unimplemented: CreateStorageSpace")
}
// UpdateStorageSpace updates a storage space
func (fs *hellofs) UpdateStorageSpace(ctx context.Context, req *provider.UpdateStorageSpaceRequest) (*provider.UpdateStorageSpaceResponse, error) {
return nil, errtypes.NotSupported("update storage space")
}
// DeleteStorageSpace deletes a storage space
func (fs *hellofs) DeleteStorageSpace(ctx context.Context, req *provider.DeleteStorageSpaceRequest) error {
return errtypes.NotSupported("delete storage space")
}
// CreateDir creates a resource of type container
func (fs *hellofs) CreateDir(ctx context.Context, ref *provider.Reference) error {
return errtypes.NotSupported("unimplemented")
}
// TouchFile sets the mtime of a resource, creating an empty file if it does not exist
// FIXME the markprocessing flag is an implementation detail of decomposedfs, remove it from the function
// FIXME the mtime should either be a time.Time or a CS3 Timestamp, not a string
func (fs *hellofs) TouchFile(ctx context.Context, ref *provider.Reference, _ bool, _ string) error {
return errtypes.NotSupported("unimplemented")
}
// Delete deletes a resource.
// If the storage driver supports a recycle bin it should moves it to the recycle bin
func (fs *hellofs) Delete(ctx context.Context, ref *provider.Reference) error {
return errtypes.NotSupported("unimplemented")
}
// Move changes the path of a resource
func (fs *hellofs) Move(ctx context.Context, oldRef, newRef *provider.Reference) error {
return errtypes.NotSupported("unimplemented")
}
// Upload creates or updates a resource of type file with a new revision
func (fs *hellofs) Upload(ctx context.Context, req storage.UploadRequest, uff storage.UploadFinishedFunc) (*provider.ResourceInfo, error) {
return nil, errtypes.NotSupported("hellofs: upload not supported")
}
// InitiateUpload returns a list of protocols with urls that can be used to append bytes to a new upload session
func (fs *hellofs) InitiateUpload(ctx context.Context, ref *provider.Reference, uploadLength int64, metadata map[string]string) (map[string]string, error) {
return nil, errtypes.NotSupported("hellofs: initiate upload not supported")
}
// grants
// DenyGrant marks a resource as denied for a recipient
// The resource and its children must be completely hidden for the recipient
func (fs *hellofs) DenyGrant(ctx context.Context, ref *provider.Reference, g *provider.Grantee) error {
return errtypes.NotSupported("hellofs: deny grant not supported")
}
// AddGrant adds a grant to a resource
func (fs *hellofs) AddGrant(ctx context.Context, ref *provider.Reference, g *provider.Grant) error {
return errtypes.NotSupported("unimplemented")
}
// ListGrants lists all grants on a resource
func (fs *hellofs) ListGrants(ctx context.Context, ref *provider.Reference) ([]*provider.Grant, error) {
return nil, errtypes.NotSupported("unimplemented")
}
// RemoveGrant removes a grant from a resource
func (fs *hellofs) RemoveGrant(ctx context.Context, ref *provider.Reference, g *provider.Grant) error {
return errtypes.NotSupported("unimplemented")
}
// UpdateGrant updates a grant on a resource
func (fs *hellofs) UpdateGrant(ctx context.Context, ref *provider.Reference, g *provider.Grant) error {
return errtypes.NotSupported("unimplemented")
}
// arbitrary metadata
// SetArbitraryMetadata sets arbitraty metadata on a resource
func (fs *hellofs) SetArbitraryMetadata(ctx context.Context, ref *provider.Reference, md *provider.ArbitraryMetadata) error {
return errtypes.NotSupported("unimplemented")
}
// UnsetArbitraryMetadata removes arbitraty metadata from a resource
func (fs *hellofs) UnsetArbitraryMetadata(ctx context.Context, ref *provider.Reference, keys []string) error {
return errtypes.NotSupported("unimplemented")
}
// locks
// GetLock returns an existing lock on the given reference
func (fs *hellofs) GetLock(ctx context.Context, ref *provider.Reference) (*provider.Lock, error) {
return nil, errtypes.NotSupported("unimplemented")
}
// SetLock puts a lock on the given reference
func (fs *hellofs) SetLock(ctx context.Context, ref *provider.Reference, lock *provider.Lock) error {
return errtypes.NotSupported("unimplemented")
}
// RefreshLock refreshes an existing lock on the given reference
func (fs *hellofs) RefreshLock(ctx context.Context, ref *provider.Reference, lock *provider.Lock, existingLockID string) error {
return errtypes.NotSupported("unimplemented")
}
// Unlock removes an existing lock from the given reference
func (fs *hellofs) Unlock(ctx context.Context, ref *provider.Reference, lock *provider.Lock) error {
return errtypes.NotSupported("unimplemented")
}
// revisions
// ListRevisions lists all revisions for the referenced resource
func (fs *hellofs) ListRevisions(ctx context.Context, ref *provider.Reference) ([]*provider.FileVersion, error) {
return nil, errtypes.NotSupported("unimplemented")
}
// DownloadRevision downloads a revision
func (fs *hellofs) DownloadRevision(ctx context.Context, ref *provider.Reference, revisionKey string) (io.ReadCloser, error) {
return nil, errtypes.NotSupported("unimplemented")
}
// RestoreRevision restores a revision
func (fs *hellofs) RestoreRevision(ctx context.Context, ref *provider.Reference, revisionKey string) error {
return errtypes.NotSupported("unimplemented")
}
// trash
// PurgeRecycleItem removes a resource from the recycle bin
func (fs *hellofs) PurgeRecycleItem(ctx context.Context, ref *provider.Reference, key, relativePath string) error {
return errtypes.NotSupported("unimplemented")
}
// EmptyRecycle removes all resource from the recycle bin
func (fs *hellofs) EmptyRecycle(ctx context.Context, ref *provider.Reference) error {
return errtypes.NotSupported("unimplemented")
}
// ListRecycle lists the content of the recycle bin
func (fs *hellofs) ListRecycle(ctx context.Context, ref *provider.Reference, key, relativePath string) ([]*provider.RecycleItem, error) {
return nil, errtypes.NotSupported("unimplemented")
}
// RestoreRecycleItem restores an item from the recyle bin
// if restoreRef is nil the resource should be restored at the original path
func (fs *hellofs) RestoreRecycleItem(ctx context.Context, ref *provider.Reference, key, relativePath string, restoreRef *provider.Reference) error {
return errtypes.NotSupported("unimplemented")
}
// CreateHome creates a users home
// Deprecated: use CreateStorageSpace with type personal
func (fs *hellofs) CreateHome(ctx context.Context) error {
return errtypes.NotSupported("unimplemented")
}
// GetHome returns the path to the users home
// Deprecated: use ListStorageSpaces with type personal
func (fs *hellofs) GetHome(ctx context.Context) (string, error) {
return "", errtypes.NotSupported("unimplemented")
}
+1
View File
@@ -26,6 +26,7 @@ import (
_ "github.com/cs3org/reva/v2/pkg/storage/fs/eosgrpc"
_ "github.com/cs3org/reva/v2/pkg/storage/fs/eosgrpchome"
_ "github.com/cs3org/reva/v2/pkg/storage/fs/eoshome"
_ "github.com/cs3org/reva/v2/pkg/storage/fs/hello"
_ "github.com/cs3org/reva/v2/pkg/storage/fs/local"
_ "github.com/cs3org/reva/v2/pkg/storage/fs/localhome"
_ "github.com/cs3org/reva/v2/pkg/storage/fs/nextcloud"
+2 -2
View File
@@ -44,7 +44,7 @@ import (
"github.com/google/uuid"
"github.com/pkg/errors"
"github.com/rs/zerolog/log"
tusd "github.com/tus/tusd/pkg/handler"
tusd "github.com/tus/tusd/v2/pkg/handler"
)
var defaultFilePerm = os.FileMode(0664)
@@ -388,7 +388,7 @@ func (upload *fileUpload) WriteChunk(ctx context.Context, offset int64, src io.R
}
// GetReader returns an io.Reader for the upload
func (upload *fileUpload) GetReader(ctx context.Context) (io.Reader, error) {
func (upload *fileUpload) GetReader(ctx context.Context) (io.ReadCloser, error) {
return os.Open(upload.binPath)
}
+1 -1
View File
@@ -27,7 +27,7 @@ import (
"os"
"syscall"
tusd "github.com/tus/tusd/pkg/handler"
tusd "github.com/tus/tusd/v2/pkg/handler"
microstore "go-micro.dev/v4/store"
"github.com/cs3org/reva/v2/pkg/events"
+107 -35
View File
@@ -23,7 +23,7 @@ import (
"io"
"net/url"
tusd "github.com/tus/tusd/pkg/handler"
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"
@@ -31,46 +31,118 @@ import (
// FS is the interface to implement access to the storage.
type FS interface {
GetHome(ctx context.Context) (string, error)
CreateHome(ctx context.Context) error
CreateDir(ctx context.Context, ref *provider.Reference) error
TouchFile(ctx context.Context, ref *provider.Reference, markprocessing bool, mtime string) error
Delete(ctx context.Context, ref *provider.Reference) error
Move(ctx context.Context, oldRef, newRef *provider.Reference) error
GetMD(ctx context.Context, ref *provider.Reference, mdKeys, fieldMask []string) (*provider.ResourceInfo, error)
ListFolder(ctx context.Context, ref *provider.Reference, mdKeys, fieldMask []string) ([]*provider.ResourceInfo, error)
InitiateUpload(ctx context.Context, ref *provider.Reference, uploadLength int64, metadata map[string]string) (map[string]string, error)
Upload(ctx context.Context, req UploadRequest, uploadFunc UploadFinishedFunc) (*provider.ResourceInfo, error)
Download(ctx context.Context, ref *provider.Reference) (io.ReadCloser, error)
ListRevisions(ctx context.Context, ref *provider.Reference) ([]*provider.FileVersion, error)
DownloadRevision(ctx context.Context, ref *provider.Reference, key string) (io.ReadCloser, error)
RestoreRevision(ctx context.Context, ref *provider.Reference, key string) error
ListRecycle(ctx context.Context, ref *provider.Reference, key, relativePath string) ([]*provider.RecycleItem, error)
RestoreRecycleItem(ctx context.Context, ref *provider.Reference, key, relativePath string, restoreRef *provider.Reference) error
PurgeRecycleItem(ctx context.Context, ref *provider.Reference, key, relativePath string) error
EmptyRecycle(ctx context.Context, ref *provider.Reference) error
GetPathByID(ctx context.Context, id *provider.ResourceId) (string, error)
AddGrant(ctx context.Context, ref *provider.Reference, g *provider.Grant) error
DenyGrant(ctx context.Context, ref *provider.Reference, g *provider.Grantee) error
RemoveGrant(ctx context.Context, ref *provider.Reference, g *provider.Grant) error
UpdateGrant(ctx context.Context, ref *provider.Reference, g *provider.Grant) error
ListGrants(ctx context.Context, ref *provider.Reference) ([]*provider.Grant, error)
GetQuota(ctx context.Context, ref *provider.Reference) ( /*TotalBytes*/ uint64 /*UsedBytes*/, uint64 /*RemainingBytes*/, uint64, error)
CreateReference(ctx context.Context, path string, targetURI *url.URL) error
// Minimal set for a readonly storage driver
// Shutdown is called when the process is exiting to give the driver a chance to flush and close all open handles
Shutdown(ctx context.Context) error
SetArbitraryMetadata(ctx context.Context, ref *provider.Reference, md *provider.ArbitraryMetadata) error
UnsetArbitraryMetadata(ctx context.Context, ref *provider.Reference, keys []string) error
SetLock(ctx context.Context, ref *provider.Reference, lock *provider.Lock) error
GetLock(ctx context.Context, ref *provider.Reference) (*provider.Lock, error)
RefreshLock(ctx context.Context, ref *provider.Reference, lock *provider.Lock, existingLockID string) error
Unlock(ctx context.Context, ref *provider.Reference, lock *provider.Lock) error
// ListStorageSpaces lists the spaces in the storage.
// The unrestricted parameter can be used to list other user's spaces when
// the user has the necessary permissions.
// FIXME The unrestricted parameter is an implementation detail of decomposedfs, remove it from the function?
ListStorageSpaces(ctx context.Context, filter []*provider.ListStorageSpacesRequest_Filter, unrestricted bool) ([]*provider.StorageSpace, error)
// GetQuota returns the quota on the referenced resource
GetQuota(ctx context.Context, ref *provider.Reference) ( /*TotalBytes*/ uint64 /*UsedBytes*/, uint64 /*RemainingBytes*/, uint64, error)
// GetMD returns the resuorce info for the referenced resource
GetMD(ctx context.Context, ref *provider.Reference, mdKeys, fieldMask []string) (*provider.ResourceInfo, error)
// 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)
// 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
// FIXME should be deprecated in favor of calls to GetMD and the fieldmask 'path'
GetPathByID(ctx context.Context, id *provider.ResourceId) (string, error)
// Functions for a writeable storage space
// CreateReference creates a resource of type reference
CreateReference(ctx context.Context, path string, targetURI *url.URL) error
// CreateDir creates a resource of type container
CreateDir(ctx context.Context, ref *provider.Reference) error
// TouchFile sets the mtime of a resource, creating an empty file if it does not exist
// FIXME the markprocessing flag is an implementation detail of decomposedfs, remove it from the function
// FIXME the mtime should either be a time.Time or a CS3 Timestamp, not a string
TouchFile(ctx context.Context, ref *provider.Reference, markprocessing bool, mtime string) error
// Delete deletes a resource.
// If the storage driver supports a recycle bin it should moves it to the recycle bin
Delete(ctx context.Context, ref *provider.Reference) error
// Move changes the path of a resource
Move(ctx context.Context, oldRef, newRef *provider.Reference) error
// InitiateUpload returns a list of protocols with urls that can be used to append bytes to a new upload session
InitiateUpload(ctx context.Context, ref *provider.Reference, uploadLength int64, metadata map[string]string) (map[string]string, error)
// Upload creates or updates a resource of type file with a new revision
Upload(ctx context.Context, req UploadRequest, uploadFunc UploadFinishedFunc) (*provider.ResourceInfo, error)
// Revisions
// 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)
// RestoreRevision restores a revision
RestoreRevision(ctx context.Context, ref *provider.Reference, key string) error
// Recyce bin
// ListRecycle lists the content of the recycle bin
ListRecycle(ctx context.Context, ref *provider.Reference, key, relativePath string) ([]*provider.RecycleItem, error)
// RestoreRecycleItem restores an item from the recyle bin
// if restoreRef is nil the resource should be restored at the original path
RestoreRecycleItem(ctx context.Context, ref *provider.Reference, key, relativePath string, restoreRef *provider.Reference) error
// PurgeRecycleItem removes a resource from the recycle bin
PurgeRecycleItem(ctx context.Context, ref *provider.Reference, key, relativePath string) error
// EmptyRecycle removes all resource from the recycle bin
EmptyRecycle(ctx context.Context, ref *provider.Reference) error
// Grants
// AddGrant adds a grant to a resource
AddGrant(ctx context.Context, ref *provider.Reference, g *provider.Grant) error
// DenyGrant marks a resource as denied for a recipient
// The resource and its children must be completely hidden for the recipient
DenyGrant(ctx context.Context, ref *provider.Reference, g *provider.Grantee) error
// RemoveGrant removes a grant from a resource
RemoveGrant(ctx context.Context, ref *provider.Reference, g *provider.Grant) error
// UpdateGrant updates a grant on a resource
UpdateGrant(ctx context.Context, ref *provider.Reference, g *provider.Grant) error
// ListGrants lists all grants on a resource
ListGrants(ctx context.Context, ref *provider.Reference) ([]*provider.Grant, error)
// Arbitrary Metadata
// SetArbitraryMetadata sets arbitraty metadata on a resource
SetArbitraryMetadata(ctx context.Context, ref *provider.Reference, md *provider.ArbitraryMetadata) error
// UnsetArbitraryMetadata removes arbitraty metadata from a resource
UnsetArbitraryMetadata(ctx context.Context, ref *provider.Reference, keys []string) error
// Locks
// GetLock returns an existing lock on the given reference
GetLock(ctx context.Context, ref *provider.Reference) (*provider.Lock, error)
// SetLock puts a lock on the given reference
SetLock(ctx context.Context, ref *provider.Reference, lock *provider.Lock) error
// RefreshLock refreshes an existing lock on the given reference
RefreshLock(ctx context.Context, ref *provider.Reference, lock *provider.Lock, existingLockID string) error
// Unlock removes an existing lock from the given reference
Unlock(ctx context.Context, ref *provider.Reference, lock *provider.Lock) error
// Spaces
// CreateStorageSpace creates a storage space
CreateStorageSpace(ctx context.Context, req *provider.CreateStorageSpaceRequest) (*provider.CreateStorageSpaceResponse, error)
// UpdateStorageSpace updates a storage space
UpdateStorageSpace(ctx context.Context, req *provider.UpdateStorageSpaceRequest) (*provider.UpdateStorageSpaceResponse, error)
// DeleteStorageSpace deletes a storage space
DeleteStorageSpace(ctx context.Context, req *provider.DeleteStorageSpaceRequest) error
// CreateHome creates a users home
// Deprecated: use CreateStorageSpace with type personal
CreateHome(ctx context.Context) error
// GetHome returns the path to the users home
// Deprecated: use ListStorageSpaces with type personal
GetHome(ctx context.Context) (string, error)
}
// UnscopeFunc is a function that unscopes a user
+1 -1
View File
@@ -25,7 +25,7 @@ import (
userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
tusd "github.com/tus/tusd/pkg/handler"
tusd "github.com/tus/tusd/v2/pkg/handler"
)
// UploadFinishedFunc is a callback function used in storage drivers to indicate that an upload has finished
@@ -59,7 +59,7 @@ import (
"github.com/cs3org/reva/v2/pkg/utils"
"github.com/jellydator/ttlcache/v2"
"github.com/pkg/errors"
tusd "github.com/tus/tusd/pkg/handler"
tusd "github.com/tus/tusd/v2/pkg/handler"
microstore "go-micro.dev/v4/store"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/trace"
+1 -1
View File
@@ -27,7 +27,7 @@ import (
"time"
"github.com/google/uuid"
tusd "github.com/tus/tusd/pkg/handler"
tusd "github.com/tus/tusd/v2/pkg/handler"
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
"github.com/cs3org/reva/v2/pkg/appctx"
@@ -26,7 +26,7 @@ import (
"strconv"
"time"
tusd "github.com/tus/tusd/pkg/handler"
tusd "github.com/tus/tusd/v2/pkg/handler"
userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
@@ -44,7 +44,7 @@ import (
"github.com/google/uuid"
"github.com/pkg/errors"
"github.com/rogpeppe/go-internal/lockedfile"
tusd "github.com/tus/tusd/pkg/handler"
tusd "github.com/tus/tusd/v2/pkg/handler"
)
var _idRegexp = regexp.MustCompile(".*/([^/]+).info")
@@ -40,7 +40,7 @@ import (
"github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/node"
"github.com/golang-jwt/jwt"
"github.com/pkg/errors"
tusd "github.com/tus/tusd/pkg/handler"
tusd "github.com/tus/tusd/v2/pkg/handler"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/trace"
)
@@ -94,7 +94,7 @@ func (session *OcisSession) GetInfo(_ context.Context) (tusd.FileInfo, error) {
}
// GetReader returns an io.Reader for the upload
func (session *OcisSession) GetReader(ctx context.Context) (io.Reader, error) {
func (session *OcisSession) GetReader(ctx context.Context) (io.ReadCloser, error) {
_, span := tracer.Start(session.Context(ctx), "GetReader")
defer span.End()
return os.Open(session.binPath())
+2 -2
View File
@@ -35,7 +35,7 @@ import (
"github.com/cs3org/reva/v2/pkg/utils"
"github.com/google/uuid"
"github.com/pkg/errors"
tusd "github.com/tus/tusd/pkg/handler"
tusd "github.com/tus/tusd/v2/pkg/handler"
)
var defaultFilePerm = os.FileMode(0664)
@@ -296,7 +296,7 @@ func (upload *fileUpload) GetInfo(ctx context.Context) (tusd.FileInfo, error) {
}
// GetReader returns an io.Reader for the upload
func (upload *fileUpload) GetReader(ctx context.Context) (io.Reader, error) {
func (upload *fileUpload) GetReader(ctx context.Context) (io.ReadCloser, error) {
return os.Open(upload.binPath)
}
@@ -23,7 +23,7 @@ import (
"io"
"net/url"
tusd "github.com/tus/tusd/pkg/handler"
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"