From b1ac8ce102401af1d64fb3a8f6f6b8bb04a50e43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20B=C3=B6sche?= Date: Sat, 7 Feb 2026 23:35:48 +0100 Subject: [PATCH] Improve error handling in WebDAV file move operations and ensure target directory exists --- go_cloud/internal/http/routes.go | 42 +++++++++++++++++------------ go_cloud/internal/storage/webdav.go | 5 ++++ 2 files changed, 30 insertions(+), 17 deletions(-) diff --git a/go_cloud/internal/http/routes.go b/go_cloud/internal/http/routes.go index a6a5939..17231ad 100644 --- a/go_cloud/internal/http/routes.go +++ b/go_cloud/internal/http/routes.go @@ -2286,15 +2286,19 @@ func moveOrgFileHandler(w http.ResponseWriter, r *http.Request, db *database.DB, // Get or create user's WebDAV client and move in Nextcloud storageClient, err := getUserWebDAVClient(r.Context(), db, userID, cfg.NextcloudURL, cfg.NextcloudUser, cfg.NextcloudPass) if err != nil { - errors.LogError(r, err, "Failed to get user WebDAV client (continuing with database operation)") - } else { - sourceRel := strings.TrimPrefix(req.SourcePath, "/") - sourcePath := path.Join("/orgs", orgID.String(), sourceRel) - targetRel := strings.TrimPrefix(newPath, "/") - targetPath := path.Join("/orgs", orgID.String(), targetRel) - if err := storageClient.Move(r.Context(), sourcePath, targetPath); err != nil { - errors.LogError(r, err, "Failed to move in Nextcloud (continuing with database operation)") - } + errors.LogError(r, err, "Failed to get user WebDAV client") + errors.WriteError(w, errors.CodeInternal, "Storage error", http.StatusInternalServerError) + return + } + + sourceRel := strings.TrimPrefix(req.SourcePath, "/") + sourcePath := path.Join("/orgs", orgID.String(), sourceRel) + targetRel := strings.TrimPrefix(newPath, "/") + targetPath := path.Join("/orgs", orgID.String(), targetRel) + if err := storageClient.Move(r.Context(), sourcePath, targetPath); err != nil { + errors.LogError(r, err, "Failed to move in Nextcloud") + errors.WriteError(w, errors.CodeInternal, "Failed to move file in storage", http.StatusInternalServerError) + return } // Update file record path and name in-place (preserves file ID for WOPI sessions) @@ -2514,14 +2518,18 @@ func moveUserFileHandler(w http.ResponseWriter, r *http.Request, db *database.DB // Get or create user's WebDAV client and move in Nextcloud storageClient, err := getUserWebDAVClient(r.Context(), db, userID, cfg.NextcloudURL, cfg.NextcloudUser, cfg.NextcloudPass) if err != nil { - errors.LogError(r, err, "Failed to get user WebDAV client (continuing with database operation)") - } else { - // User files are stored directly in the user's WebDAV root (no /users/{id} prefix) - sourcePath := "/" + strings.TrimPrefix(req.SourcePath, "/") - targetPath := "/" + strings.TrimPrefix(newPath, "/") - if err := storageClient.Move(r.Context(), sourcePath, targetPath); err != nil { - errors.LogError(r, err, "Failed to move in Nextcloud (continuing with database operation)") - } + errors.LogError(r, err, "Failed to get user WebDAV client") + errors.WriteError(w, errors.CodeInternal, "Storage error", http.StatusInternalServerError) + return + } + + // User files are stored directly in the user's WebDAV root (no /users/{id} prefix) + sourcePath := "/" + strings.TrimPrefix(req.SourcePath, "/") + targetPath := "/" + strings.TrimPrefix(newPath, "/") + if err := storageClient.Move(r.Context(), sourcePath, targetPath); err != nil { + errors.LogError(r, err, "Failed to move in Nextcloud") + errors.WriteError(w, errors.CodeInternal, "Failed to move file in storage", http.StatusInternalServerError) + return } // Update file record path and name in-place (preserves file ID for WOPI sessions) diff --git a/go_cloud/internal/storage/webdav.go b/go_cloud/internal/storage/webdav.go index 5e2464a..4b90bec 100644 --- a/go_cloud/internal/storage/webdav.go +++ b/go_cloud/internal/storage/webdav.go @@ -240,6 +240,11 @@ func (c *WebDAVClient) Move(ctx context.Context, sourcePath, targetPath string) return fmt.Errorf("no webdav client configured") } + // Ensure target parent directory exists before moving + if err := c.ensureParent(ctx, targetPath); err != nil { + return fmt.Errorf("failed to create target directory: %w", err) + } + sourceRel := strings.TrimLeft(sourcePath, "/") targetRel := strings.TrimLeft(targetPath, "/")