Skip to content

Commit

Permalink
Implement touch file (#2369)
Browse files Browse the repository at this point in the history
* implement cs3org/cs3apis#154

* use TouchFile for the app provider

* add changelog and comments

* revert use TouchFile in app provider

* fix resource typo

Co-authored-by: Giuseppe Lo Presti <giuseppe.lopresti@cern.ch>

Co-authored-by: Giuseppe Lo Presti <giuseppe.lopresti@cern.ch>
  • Loading branch information
wkloucek and glpatcern authored Dec 17, 2021
1 parent 5cde018 commit f3c8b62
Show file tree
Hide file tree
Showing 19 changed files with 141 additions and 2 deletions.
6 changes: 6 additions & 0 deletions changelog/unreleased/enhancement-add-touch-file.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Enhancement: Implement TouchFile from the CS3apis

We've updated the CS3apis and implemented the TouchFile method.

https://github.com/cs3org/reva/pull/2369
https://github.com/cs3org/cs3apis/pull/154
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ require (
github.com/cheggaaa/pb v1.0.29
github.com/coreos/go-oidc v2.2.1+incompatible
github.com/cs3org/cato v0.0.0-20200828125504-e418fc54dd5e
github.com/cs3org/go-cs3apis v0.0.0-20211104090126-8e972dca8304
github.com/cs3org/go-cs3apis v0.0.0-20211213090556-12c0d565f51d
github.com/cubewise-code/go-mime v0.0.0-20200519001935-8c5762b177d8
github.com/eventials/go-tus v0.0.0-20200718001131-45c7ec8f5d59
github.com/gdexlab/go-render v1.0.1
Expand Down
4 changes: 4 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,12 @@ github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSV
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/cs3org/cato v0.0.0-20200828125504-e418fc54dd5e h1:tqSPWQeueWTKnJVMJffz4pz0o1WuQxJ28+5x5JgaHD8=
github.com/cs3org/cato v0.0.0-20200828125504-e418fc54dd5e/go.mod h1:XJEZ3/EQuI3BXTp/6DUzFr850vlxq11I6satRtz0YQ4=
github.com/cs3org/go-cs3apis v0.0.0-20210325133324-32b03d75a535 h1:555D8A3ddKqb4OyK9v5mdphw2zDLWKGXOkcnf1RQwTA=
github.com/cs3org/go-cs3apis v0.0.0-20210325133324-32b03d75a535/go.mod h1:UXha4TguuB52H14EMoSsCqDj7k8a/t7g4gVP+bgY5LY=
github.com/cs3org/go-cs3apis v0.0.0-20211104090126-8e972dca8304 h1:e/nIPR518vyvrulo9goAZTtYD6gFfu/2/9MDe6mTGcw=
github.com/cs3org/go-cs3apis v0.0.0-20211104090126-8e972dca8304/go.mod h1:UXha4TguuB52H14EMoSsCqDj7k8a/t7g4gVP+bgY5LY=
github.com/cs3org/go-cs3apis v0.0.0-20211213090556-12c0d565f51d h1:gnb2ciU4N+RwUug/nwe54wenWi7vSp5bAAjXINlgHZ8=
github.com/cs3org/go-cs3apis v0.0.0-20211213090556-12c0d565f51d/go.mod h1:UXha4TguuB52H14EMoSsCqDj7k8a/t7g4gVP+bgY5LY=
github.com/cubewise-code/go-mime v0.0.0-20200519001935-8c5762b177d8 h1:Z9lwXumT5ACSmJ7WGnFl+OMLLjpz5uR2fyz7dC255FI=
github.com/cubewise-code/go-mime v0.0.0-20200519001935-8c5762b177d8/go.mod h1:4abs/jPXcmJzYoYGF91JF9Uq9s/KL5n1jvFDix8KcqY=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
Expand Down
2 changes: 2 additions & 0 deletions internal/grpc/interceptors/auth/scope.go
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,8 @@ func extractRef(req interface{}, hasEditorRole bool) (*provider.Reference, bool)
// Write Requests
case *provider.CreateContainerRequest:
return v.GetRef(), true
case *provider.TouchFileRequest:
return v.GetRef(), true
case *provider.DeleteRequest:
return v.GetRef(), true
case *provider.MoveRequest:
Expand Down
6 changes: 5 additions & 1 deletion internal/grpc/interceptors/readonly/readonly.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,11 @@ func NewUnary(map[string]interface{}) (grpc.UnaryServerInterceptor, int, error)
}, nil
case *provider.CreateContainerRequest:
return &provider.CreateContainerResponse{
Status: rstatus.NewPermissionDenied(ctx, nil, "permission denied: tried to create resoure on readonly storage"),
Status: rstatus.NewPermissionDenied(ctx, nil, "permission denied: tried to create resource on read-only storage"),
}, nil
case *provider.TouchFileRequest:
return &provider.TouchFileResponse{
Status: rstatus.NewPermissionDenied(ctx, nil, "permission denied: tried to create resource on read-only storage"),
}, nil
case *provider.CreateHomeRequest:
return &provider.CreateHomeResponse{
Expand Down
19 changes: 19 additions & 0 deletions internal/grpc/services/gateway/storageprovider.go
Original file line number Diff line number Diff line change
Expand Up @@ -851,6 +851,25 @@ func (s *svc) createContainer(ctx context.Context, req *provider.CreateContainer
return res, nil
}

func (s *svc) TouchFile(ctx context.Context, req *provider.TouchFileRequest) (*provider.TouchFileResponse, error) {
c, err := s.find(ctx, req.Ref)
if err != nil {
return &provider.TouchFileResponse{
Status: status.NewStatusFromErrType(ctx, "TouchFile ref="+req.Ref.String(), err),
}, nil
}

res, err := c.TouchFile(ctx, req)
if err != nil {
if gstatus.Code(err) == codes.PermissionDenied {
return &provider.TouchFileResponse{Status: &rpc.Status{Code: rpc.Code_CODE_PERMISSION_DENIED}}, nil
}
return nil, errors.Wrap(err, "gateway: error calling TouchFile")
}

return res, nil
}

// check if the path contains the prefix of the shared folder
func (s *svc) inSharedFolder(ctx context.Context, p string) bool {
sharedFolder := s.getSharedFolder(ctx)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,19 @@ func (s *service) CreateContainer(ctx context.Context, req *provider.CreateConta
return res, nil
}

func (s *service) TouchFile(ctx context.Context, req *provider.TouchFileRequest) (*provider.TouchFileResponse, error) {
ref, _, _, st, err := s.translatePublicRefToCS3Ref(ctx, req.Ref)
switch {
case err != nil:
return nil, err
case st != nil:
return &provider.TouchFileResponse{
Status: st,
}, nil
}
return s.gateway.TouchFile(ctx, &provider.TouchFileRequest{Opaque: req.Opaque, Ref: ref})
}

func (s *service) Delete(ctx context.Context, req *provider.DeleteRequest) (*provider.DeleteResponse, error) {
ctx, span := rtrace.Provider.Tracer("publicstorageprovider").Start(ctx, "Delete")
defer span.End()
Expand Down
30 changes: 30 additions & 0 deletions internal/grpc/services/storageprovider/storageprovider.go
Original file line number Diff line number Diff line change
Expand Up @@ -544,6 +544,36 @@ func (s *service) CreateContainer(ctx context.Context, req *provider.CreateConta
return res, nil
}

func (s *service) TouchFile(ctx context.Context, req *provider.TouchFileRequest) (*provider.TouchFileResponse, error) {
newRef, err := s.unwrap(ctx, req.Ref)
if err != nil {
return &provider.TouchFileResponse{
Status: status.NewInternal(ctx, err, "error unwrapping path"),
}, nil
}
if err := s.storage.TouchFile(ctx, newRef); err != nil {
var st *rpc.Status
switch err.(type) {
case errtypes.IsNotFound:
st = status.NewNotFound(ctx, "path not found when touching the file")
case errtypes.AlreadyExists:
st = status.NewAlreadyExists(ctx, err, "file already exists")
case errtypes.PermissionDenied:
st = status.NewPermissionDenied(ctx, err, "permission denied")
default:
st = status.NewInternal(ctx, err, "error touching file: "+req.Ref.String())
}
return &provider.TouchFileResponse{
Status: st,
}, nil
}

res := &provider.TouchFileResponse{
Status: status.NewOK(ctx),
}
return res, nil
}

func (s *service) Delete(ctx context.Context, req *provider.DeleteRequest) (*provider.DeleteResponse, error) {
newRef, err := s.unwrap(ctx, req.Ref)
if err != nil {
Expand Down
2 changes: 2 additions & 0 deletions pkg/auth/scope/publicshare.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ func publicshareScope(ctx context.Context, scope *authpb.Scope, resource interfa
// need to return appropriate status codes in the ocs/ocdav layers.
case *provider.CreateContainerRequest:
return hasRoleEditor(*scope) && checkStorageRef(ctx, &share, v.GetRef()), nil
case *provider.TouchFileRequest:
return hasRoleEditor(*scope) && checkStorageRef(ctx, &share, v.GetRef()), nil
case *provider.DeleteRequest:
return hasRoleEditor(*scope) && checkStorageRef(ctx, &share, v.GetRef()), nil
case *provider.MoveRequest:
Expand Down
2 changes: 2 additions & 0 deletions pkg/auth/scope/resourceinfo.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ func resourceinfoScope(_ context.Context, scope *authpb.Scope, resource interfac
// need to return appropriate status codes in the ocs/ocdav layers.
case *provider.CreateContainerRequest:
return hasRoleEditor(*scope) && checkResourceInfo(&r, v.GetRef()), nil
case *provider.TouchFileRequest:
return hasRoleEditor(*scope) && checkResourceInfo(&r, v.GetRef()), nil
case *provider.DeleteRequest:
return hasRoleEditor(*scope) && checkResourceInfo(&r, v.GetRef()), nil
case *provider.MoveRequest:
Expand Down
2 changes: 2 additions & 0 deletions pkg/auth/scope/share.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ func shareScope(_ context.Context, scope *authpb.Scope, resource interface{}, lo
// need to return appropriate status codes in the ocs/ocdav layers.
case *provider.CreateContainerRequest:
return checkShareStorageRef(&share, v.GetRef()), nil
case *provider.TouchFileRequest:
return checkShareStorageRef(&share, v.GetRef()), nil
case *provider.DeleteRequest:
return checkShareStorageRef(&share, v.GetRef()), nil
case *provider.MoveRequest:
Expand Down
5 changes: 5 additions & 0 deletions pkg/storage/fs/nextcloud/nextcloud.go
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,11 @@ func (nc *StorageDriver) CreateDir(ctx context.Context, ref *provider.Reference)
return err
}

// TouchFile as defined in the storage.FS interface
func (nc *StorageDriver) TouchFile(ctx context.Context, ref *provider.Reference) error {
return fmt.Errorf("unimplemented: TouchFile")
}

// Delete as defined in the storage.FS interface
func (nc *StorageDriver) Delete(ctx context.Context, ref *provider.Reference) error {
bodyStr, err := json.Marshal(ref)
Expand Down
5 changes: 5 additions & 0 deletions pkg/storage/fs/owncloud/owncloud.go
Original file line number Diff line number Diff line change
Expand Up @@ -1186,6 +1186,11 @@ func (fs *ocfs) CreateDir(ctx context.Context, ref *provider.Reference) (err err
return fs.propagate(ctx, ip)
}

// TouchFile as defined in the storage.FS interface
func (fs *ocfs) TouchFile(ctx context.Context, ref *provider.Reference) error {
return fmt.Errorf("unimplemented: TouchFile")
}

func (fs *ocfs) isShareFolderChild(sp string) bool {
return strings.HasPrefix(sp, fs.c.ShareFolder)
}
Expand Down
5 changes: 5 additions & 0 deletions pkg/storage/fs/owncloudsql/owncloudsql.go
Original file line number Diff line number Diff line change
Expand Up @@ -766,6 +766,11 @@ func (fs *owncloudsqlfs) CreateDir(ctx context.Context, ref *provider.Reference)
return fs.propagate(ctx, filepath.Dir(ip))
}

// TouchFile as defined in the storage.FS interface
func (fs *owncloudsqlfs) TouchFile(ctx context.Context, ref *provider.Reference) error {
return fmt.Errorf("unimplemented: TouchFile")
}

func (fs *owncloudsqlfs) CreateReference(ctx context.Context, sp string, targetURI *url.URL) error {
return errtypes.NotSupported("owncloudsql: operation not supported")
}
Expand Down
5 changes: 5 additions & 0 deletions pkg/storage/fs/s3/s3.go
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,11 @@ func (fs *s3FS) CreateDir(ctx context.Context, ref *provider.Reference) error {
return nil
}

// TouchFile as defined in the storage.FS interface
func (fs *s3FS) TouchFile(ctx context.Context, ref *provider.Reference) error {
return fmt.Errorf("unimplemented: TouchFile")
}

func (fs *s3FS) Delete(ctx context.Context, ref *provider.Reference) error {
log := appctx.GetLogger(ctx)

Expand Down
1 change: 1 addition & 0 deletions pkg/storage/storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ type FS interface {
GetHome(ctx context.Context) (string, error)
CreateHome(ctx context.Context) error
CreateDir(ctx context.Context, ref *provider.Reference) error
TouchFile(ctx context.Context, ref *provider.Reference) error
Delete(ctx context.Context, ref *provider.Reference) error
Move(ctx context.Context, oldRef, newRef *provider.Reference) error
GetMD(ctx context.Context, ref *provider.Reference, mdKeys []string) (*provider.ResourceInfo, error)
Expand Down
6 changes: 6 additions & 0 deletions pkg/storage/utils/decomposedfs/decomposedfs.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ package decomposedfs

import (
"context"
"fmt"
"io"
"net/url"
"os"
Expand Down Expand Up @@ -320,6 +321,11 @@ func (fs *Decomposedfs) CreateDir(ctx context.Context, ref *provider.Reference)
return
}

// TouchFile as defined in the storage.FS interface
func (fs *Decomposedfs) TouchFile(ctx context.Context, ref *provider.Reference) error {
return fmt.Errorf("unimplemented: TouchFile")
}

// CreateReference creates a reference as a node folder with the target stored in extended attributes
// There is no difference between the /Shares folder and normal nodes because the storage is not supposed to be accessible without the storage provider.
// In effect everything is a shadow namespace.
Expand Down
23 changes: 23 additions & 0 deletions pkg/storage/utils/eosfs/eosfs.go
Original file line number Diff line number Diff line change
Expand Up @@ -1214,6 +1214,29 @@ func (fs *eosfs) CreateDir(ctx context.Context, ref *provider.Reference) error {
return fs.c.CreateDir(ctx, auth, fn)
}

// TouchFile as defined in the storage.FS interface
func (fs *eosfs) TouchFile(ctx context.Context, ref *provider.Reference) error {
log := appctx.GetLogger(ctx)
u, err := getUser(ctx)
if err != nil {
return errors.Wrap(err, "eosfs: no user in ctx")
}
p, err := fs.resolve(ctx, ref)
if err != nil {
return nil
}

auth, err := fs.getUserAuth(ctx, u, p)
if err != nil {
return err
}

log.Info().Msgf("eosfs: touch file: path=%s", p)

fn := fs.wrap(ctx, p)
return fs.c.Touch(ctx, auth, fn)
}

func (fs *eosfs) CreateReference(ctx context.Context, p string, targetURI *url.URL) error {
// TODO(labkode): for the time being we only allow creating references
// in the virtual share folder to not pollute the nominal user tree.
Expand Down
5 changes: 5 additions & 0 deletions pkg/storage/utils/localfs/localfs.go
Original file line number Diff line number Diff line change
Expand Up @@ -782,6 +782,11 @@ func (fs *localfs) CreateDir(ctx context.Context, ref *provider.Reference) error
return fs.propagate(ctx, path.Dir(fn))
}

// TouchFile as defined in the storage.FS interface
func (fs *localfs) TouchFile(ctx context.Context, ref *provider.Reference) error {
return fmt.Errorf("unimplemented: TouchFile")
}

func (fs *localfs) Delete(ctx context.Context, ref *provider.Reference) error {
fn, err := fs.resolve(ctx, ref)
if err != nil {
Expand Down

0 comments on commit f3c8b62

Please sign in to comment.