From 923ff697156ab7c5be6a1f97ffb8d8f84dbdaa7a Mon Sep 17 00:00:00 2001 From: Gianmaria Del Monte Date: Tue, 8 Feb 2022 10:18:22 +0100 Subject: [PATCH 1/5] function to append a timestamp to filename before the extension --- pkg/utils/utils.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/pkg/utils/utils.go b/pkg/utils/utils.go index 14ec95e4fa..ae67530c3c 100644 --- a/pkg/utils/utils.go +++ b/pkg/utils/utils.go @@ -352,3 +352,11 @@ func GetViewMode(viewMode string) gateway.OpenInAppRequest_ViewMode { return gateway.OpenInAppRequest_VIEW_MODE_INVALID } } + +// AppendNowToPath appends the now timestamp just before the extension (if present) +func AppendNowToPath(p string) string { + now := time.Now().Format("2006-01-02T15.04.05") + ext := path.Ext(p) + baseFile := strings.TrimSuffix(p, ext) + return fmt.Sprintf("%s.%s%s", baseFile, now, ext) +} From 14171c4c7f90fbfe9583305ff9955bbcc6475ab6 Mon Sep 17 00:00:00 2001 From: Gianmaria Del Monte Date: Tue, 8 Feb 2022 10:22:12 +0100 Subject: [PATCH 2/5] forbidden overwrite in a drop zone (non atomic) --- internal/http/services/owncloud/ocdav/put.go | 31 ++++++++++++++++++++ internal/http/services/owncloud/ocdav/tus.go | 19 ++++++++++++ 2 files changed, 50 insertions(+) diff --git a/internal/http/services/owncloud/ocdav/put.go b/internal/http/services/owncloud/ocdav/put.go index 1114d604f6..79515a46f4 100644 --- a/internal/http/services/owncloud/ocdav/put.go +++ b/internal/http/services/owncloud/ocdav/put.go @@ -26,11 +26,13 @@ import ( "strings" "time" + userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1" provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" typespb "github.com/cs3org/go-cs3apis/cs3/types/v1beta1" "github.com/cs3org/reva/internal/http/services/datagateway" "github.com/cs3org/reva/pkg/appctx" + ctxpkg "github.com/cs3org/reva/pkg/ctx" "github.com/cs3org/reva/pkg/errtypes" "github.com/cs3org/reva/pkg/rhttp" "github.com/cs3org/reva/pkg/storage/utils/chunking" @@ -149,6 +151,24 @@ func (s *svc) handlePut(ctx context.Context, w http.ResponseWriter, r *http.Requ return } + if sRes.Status.Code == rpc.Code_CODE_OK { + // the file already exists + // will append a timestamp to the end of the file + // sorry, this code is not atomic, data loss may occur :'( + + user, ok := ctxpkg.ContextGetUser(ctx) + if !ok { + log.Error().Msg("error getting user from context") + w.WriteHeader(http.StatusInternalServerError) + return + } + + if hasUploaderRole(user) { + ref.Path = utils.AppendNowToPath(ref.Path) + log.Debug().Msgf("user %s has uploader role, changed file destination to %s", user.Username, ref.Path) + } + } + info := sRes.Info if info != nil { if info.Type != provider.ResourceType_RESOURCE_TYPE_FILE { @@ -331,6 +351,17 @@ func (s *svc) handlePut(ctx context.Context, w http.ResponseWriter, r *http.Requ w.WriteHeader(http.StatusNoContent) } +func hasUploaderRole(user *userpb.User) bool { + if user.Opaque == nil { + return false + } + publicShare, ok := user.Opaque.Map["public-share-role"] + if !ok { + return false + } + return string(publicShare.Value) == "uploader" +} + func (s *svc) handleSpacesPut(w http.ResponseWriter, r *http.Request, spaceID string) { ctx, span := rtrace.Provider.Tracer("ocdav").Start(r.Context(), "spaces_put") defer span.End() diff --git a/internal/http/services/owncloud/ocdav/tus.go b/internal/http/services/owncloud/ocdav/tus.go index b795d482d4..34d526e628 100644 --- a/internal/http/services/owncloud/ocdav/tus.go +++ b/internal/http/services/owncloud/ocdav/tus.go @@ -33,6 +33,7 @@ import ( typespb "github.com/cs3org/go-cs3apis/cs3/types/v1beta1" "github.com/cs3org/reva/internal/http/services/owncloud/ocs/conversions" "github.com/cs3org/reva/pkg/appctx" + ctxpkg "github.com/cs3org/reva/pkg/ctx" "github.com/cs3org/reva/pkg/rhttp" rtrace "github.com/cs3org/reva/pkg/trace" "github.com/cs3org/reva/pkg/utils" @@ -138,6 +139,24 @@ func (s *svc) handleTusPost(ctx context.Context, w http.ResponseWriter, r *http. return } + if sRes.Status.Code == rpc.Code_CODE_OK { + // the file already exists + // will append a timestamp to the end of the file + // sorry, this code is not atomic, data loss may occur :'( + + user, ok := ctxpkg.ContextGetUser(ctx) + if !ok { + log.Error().Msg("error getting user from context") + w.WriteHeader(http.StatusInternalServerError) + return + } + + if hasUploaderRole(user) { + ref.Path = utils.AppendNowToPath(ref.Path) + log.Debug().Msgf("user %s has uploader role, changed file destination to %s", user.Username, ref.Path) + } + } + info := sRes.Info if info != nil && info.Type != provider.ResourceType_RESOURCE_TYPE_FILE { log.Warn().Msg("resource is not a file") From ede861668da0da006ec060b635769333d07251e7 Mon Sep 17 00:00:00 2001 From: Gianmaria Del Monte Date: Tue, 8 Feb 2022 10:23:06 +0100 Subject: [PATCH 3/5] Add changelog --- changelog/unreleased/drop-zone-collision.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 changelog/unreleased/drop-zone-collision.md diff --git a/changelog/unreleased/drop-zone-collision.md b/changelog/unreleased/drop-zone-collision.md new file mode 100644 index 0000000000..0db8c873fe --- /dev/null +++ b/changelog/unreleased/drop-zone-collision.md @@ -0,0 +1,5 @@ +Enhancement: Append a timestamp to filename when +a collision is detected during upload + +https://github.com/cs3org/reva/issues/2480 +https://github.com/cs3org/reva/pull/2510 \ No newline at end of file From f27126471cc96a19a42d26515dbcb5c70f909199 Mon Sep 17 00:00:00 2001 From: Gianmaria Del Monte <39946305+gmgigi96@users.noreply.github.com> Date: Fri, 11 Feb 2022 09:34:51 +0100 Subject: [PATCH 4/5] Use key-value in logs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Jörn Friedrich Dreyer --- internal/http/services/owncloud/ocdav/put.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/http/services/owncloud/ocdav/put.go b/internal/http/services/owncloud/ocdav/put.go index 79515a46f4..87117cc5c6 100644 --- a/internal/http/services/owncloud/ocdav/put.go +++ b/internal/http/services/owncloud/ocdav/put.go @@ -165,7 +165,7 @@ func (s *svc) handlePut(ctx context.Context, w http.ResponseWriter, r *http.Requ if hasUploaderRole(user) { ref.Path = utils.AppendNowToPath(ref.Path) - log.Debug().Msgf("user %s has uploader role, changed file destination to %s", user.Username, ref.Path) + log.Debug().Str("user", user.Username).Str("path", ref.Path).Msg("user has uploader role, changed file name") } } From 526d2662c4e5acf6c8151e69b4740566a13310d1 Mon Sep 17 00:00:00 2001 From: Gianmaria Del Monte <39946305+gmgigi96@users.noreply.github.com> Date: Fri, 11 Feb 2022 09:35:03 +0100 Subject: [PATCH 5/5] Use key-value in logs for user MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Jörn Friedrich Dreyer --- internal/http/services/owncloud/ocdav/tus.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/http/services/owncloud/ocdav/tus.go b/internal/http/services/owncloud/ocdav/tus.go index 34d526e628..f0f87a3e1b 100644 --- a/internal/http/services/owncloud/ocdav/tus.go +++ b/internal/http/services/owncloud/ocdav/tus.go @@ -153,7 +153,7 @@ func (s *svc) handleTusPost(ctx context.Context, w http.ResponseWriter, r *http. if hasUploaderRole(user) { ref.Path = utils.AppendNowToPath(ref.Path) - log.Debug().Msgf("user %s has uploader role, changed file destination to %s", user.Username, ref.Path) + log.Debug().Str("user", user.Username).Str("path", ref.Path).Msg("user has uploader role, changed file name") } }