Skip to content

Commit

Permalink
extract FindName and use it for PUT and TUS
Browse files Browse the repository at this point in the history
Signed-off-by: Jörn Friedrich Dreyer <[email protected]>
  • Loading branch information
butonic committed Feb 1, 2024
1 parent 4b087c2 commit 877335b
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 28 deletions.
47 changes: 47 additions & 0 deletions internal/http/services/owncloud/ocdav/filedrop.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package ocdav

import (
"context"
"errors"
"path/filepath"
"strconv"
"strings"

gatewayv1beta1 "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1"
rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1"
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
)

// FindName returns the next filename available when the current
func FindName(ctx context.Context, client gatewayv1beta1.GatewayAPIClient, name string, parentid *provider.ResourceId) (string, *rpc.Status, error) {
lReq := &provider.ListContainerRequest{
Ref: &provider.Reference{
ResourceId: parentid,
},
}
lRes, err := client.ListContainer(ctx, lReq)
if err != nil {
return "", nil, err
}
if lRes.Status.Code != rpc.Code_CODE_OK {
return "", lRes.Status, nil
}
// iterate over the listing to determine next suffix
var itemMap = make(map[string]struct{})
for _, fi := range lRes.Infos {
itemMap[fi.GetName()] = struct{}{}
}
ext := filepath.Ext(name)
fileName := strings.TrimSuffix(name, ext)
if strings.HasSuffix(fileName, ".tar") {
fileName = strings.TrimSuffix(fileName, ".tar")
ext = filepath.Ext(fileName) + "." + ext
}
// starts with two because "normal" humans begin counting with 1 and we say the existing file is the first one
for i := 2; i < len(itemMap)+3; i++ {
if _, ok := itemMap[fileName+" ("+strconv.Itoa(i)+")"+ext]; !ok {
return fileName + " (" + strconv.Itoa(i) + ")" + ext, nil, nil
}
}
return "", nil, errors.New("could not determine new filename")
}
41 changes: 41 additions & 0 deletions internal/http/services/owncloud/ocdav/put.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,47 @@ func (s *svc) handlePut(ctx context.Context, w http.ResponseWriter, r *http.Requ
w.WriteHeader(http.StatusInternalServerError)
return
}

// Test if the target is a secret filedrop
tokenStatInfo, ok := TokenStatInfoFromContext(ctx)
// We assume that when the uploader can create containers, but is not allowed to list them, it is a secret file drop
if ok && tokenStatInfo.GetPermissionSet().CreateContainer && !tokenStatInfo.GetPermissionSet().ListContainer {
// TODO we can skip this stat if the tokenStatInfo is the direct parent
sReq := &provider.StatRequest{
Ref: ref,
}
sRes, err := client.Stat(ctx, sReq)
if err != nil {
log.Error().Err(err).Msg("error sending grpc stat request")
w.WriteHeader(http.StatusInternalServerError)
return
}

// We also need to continue if we are not allowed to stat a resource. We may not have stat permission. That still means it exists and we need to find a new filename.
switch sRes.Status.Code {
case rpc.Code_CODE_OK, rpc.Code_CODE_PERMISSION_DENIED:
// find next filename
newName, status, err := FindName(ctx, client, filepath.Base(ref.Path), sRes.GetInfo().GetParentId())
if err != nil {
log.Error().Err(err).Msg("error sending grpc stat request")
w.WriteHeader(http.StatusInternalServerError)
return
}
if status.Code != rpc.Code_CODE_OK {
log.Error().Interface("status", status).Msg("error listing file")
errors.HandleErrorStatus(&log, w, status)
return
}
ref.Path = utils.MakeRelativePath(filepath.Join(filepath.Dir(ref.GetPath()), newName))
case rpc.Code_CODE_NOT_FOUND:
// just continue with normal upload
default:
log.Error().Interface("status", sRes.Status).Msg("error stating file")
errors.HandleErrorStatus(&log, w, sRes.Status)
return
}
}

opaque := &typespb.Opaque{}
if mtime := r.Header.Get(net.HeaderOCMtime); mtime != "" {
utils.AppendPlainToOpaque(opaque, net.HeaderOCMtime, mtime)
Expand Down
35 changes: 7 additions & 28 deletions internal/http/services/owncloud/ocdav/tus.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,41 +169,20 @@ func (s *svc) handleTusPost(ctx context.Context, w http.ResponseWriter, r *http.
}
}
if isSecretFileDrop {
lReq := &provider.ListContainerRequest{
Ref: &provider.Reference{
ResourceId: sRes.GetInfo().GetParentId(),
},
}
lRes, err := client.ListContainer(ctx, lReq)
// find next filename
newName, status, err := FindName(ctx, client, filepath.Base(ref.Path), sRes.GetInfo().GetParentId())
if err != nil {
log.Error().Err(err).Msg("error sending grpc stat request")
w.WriteHeader(http.StatusInternalServerError)
return
}
if lRes.Status.Code != rpc.Code_CODE_OK {
log.Debug().Err(err).Msg("error listing container")
errors.HandleErrorStatus(&log, w, lRes.Status)
if status.Code != rpc.Code_CODE_OK {
log.Error().Interface("status", status).Msg("error listing file")
errors.HandleErrorStatus(&log, w, status)
return
}
// iterate over the listing to determine next suffix
var itemMap = make(map[string]struct{})
for _, fi := range lRes.Infos {
itemMap[fi.GetName()] = struct{}{}
}
ext := filepath.Ext(sRes.GetInfo().GetName())
fileName := strings.TrimSuffix(sRes.GetInfo().GetName(), ext)
if strings.HasSuffix(fileName, ".tar") {
fileName = strings.TrimSuffix(fileName, ".tar")
ext = filepath.Ext(fileName) + "." + ext
}
// starts with two because "normal" humans begin counting with 1 and we say the existing file is the first one
for i := 2; i < len(itemMap)+3; i++ {
if _, ok := itemMap[fileName+" ("+strconv.Itoa(i)+")"+ext]; !ok {
sRes.GetInfo().Name = fileName + " (" + strconv.Itoa(i) + ")" + ext
ref.Path = filepath.Join(filepath.Dir(ref.GetPath()), sRes.GetInfo().GetName())
break
}
}
ref.Path = utils.MakeRelativePath(filepath.Join(filepath.Dir(ref.GetPath()), newName))
sRes.GetInfo().Name = newName
}
}

Expand Down

0 comments on commit 877335b

Please sign in to comment.