diff --git a/go_cloud/api b/go_cloud/api index 752bb19..ed3cf5e 100755 Binary files a/go_cloud/api and b/go_cloud/api differ diff --git a/go_cloud/internal/http/routes.go b/go_cloud/internal/http/routes.go index 06da2ee..406c73e 100644 --- a/go_cloud/internal/http/routes.go +++ b/go_cloud/internal/http/routes.go @@ -4038,7 +4038,7 @@ func uploadUserAvatarHandler(w http.ResponseWriter, r *http.Request, db *databas // Upload to Nextcloud client := storage.NewWebDAVClient(cfg) - avatarPath := fmt.Sprintf("remote.php/dav/files/b0esche/avatars/%s", filename) + avatarPath := fmt.Sprintf("avatars/%s", filename) err = client.Upload(r.Context(), avatarPath, bytes.NewReader(fileBytes), header.Size) if err != nil { errors.LogError(r, err, "Failed to upload avatar") @@ -4049,11 +4049,12 @@ func uploadUserAvatarHandler(w http.ResponseWriter, r *http.Request, db *databas // Get public URL - for now, construct it manually since Nextcloud doesn't provide direct public URLs // In a real setup, you'd configure Nextcloud to serve public URLs or use a CDN publicURL := "/user/avatar" + webdavURL := fmt.Sprintf("%s/%s", client.BaseURL, avatarPath) // Update user profile with avatar URL _, err = db.ExecContext(r.Context(), `UPDATE users SET avatar_url = $1, updated_at = NOW() WHERE id = $2`, - publicURL, userID) + webdavURL, userID) if err != nil { errors.LogError(r, err, "Failed to update user avatar") errors.WriteError(w, errors.CodeInternal, "Server error", http.StatusInternalServerError) @@ -4112,16 +4113,13 @@ func getUserAvatarHandler(w http.ResponseWriter, r *http.Request, db *database.D return } - // Parse the avatar URL to get the remote path - // Assuming avatarURL is like https://storage.b0esche.cloud/remote.php/dav/files/b0esche/avatars/filename - baseURL := cfg.NextcloudURL - if !strings.HasSuffix(baseURL, "/") { - baseURL += "/" - } - remotePath := strings.TrimPrefix(*avatarURL, baseURL) - // Download from WebDAV client := storage.NewWebDAVClient(cfg) + if client == nil { + errors.WriteError(w, errors.CodeInternal, "WebDAV client not configured", http.StatusInternalServerError) + return + } + remotePath := strings.TrimPrefix(*avatarURL, client.BaseURL+"/") resp, err := client.Download(r.Context(), remotePath, "") if err != nil { errors.LogError(r, err, "Failed to download avatar") diff --git a/go_cloud/internal/storage/nextcloud.go b/go_cloud/internal/storage/nextcloud.go index fade96b..4eedf0a 100644 --- a/go_cloud/internal/storage/nextcloud.go +++ b/go_cloud/internal/storage/nextcloud.go @@ -69,7 +69,7 @@ func NewUserWebDAVClient(nextcloudBaseURL, username, password string) *WebDAVCli fullURL := fmt.Sprintf("%s/remote.php/dav/files/%s", baseURL, username) return &WebDAVClient{ - baseURL: fullURL, + BaseURL: fullURL, user: username, pass: password, basePrefix: "/", diff --git a/go_cloud/internal/storage/webdav.go b/go_cloud/internal/storage/webdav.go index 5e3169f..bc28c57 100644 --- a/go_cloud/internal/storage/webdav.go +++ b/go_cloud/internal/storage/webdav.go @@ -15,7 +15,7 @@ import ( ) type WebDAVClient struct { - baseURL string + BaseURL string user string pass string basePrefix string @@ -29,17 +29,20 @@ func NewWebDAVClient(cfg *config.Config) *WebDAVClient { return nil } u := strings.TrimRight(cfg.NextcloudURL, "/") + if !strings.Contains(u, "/remote.php") { + u += "/remote.php/dav/files/" + cfg.NextcloudUser + } base := cfg.NextcloudBase if base == "" { base = "/" } log.Printf("[WEBDAV] Initializing WebDAV client - URL: %s, User: %s, BasePath: %s\n", u, cfg.NextcloudUser, base) return &WebDAVClient{ - baseURL: u, + BaseURL: u, user: cfg.NextcloudUser, pass: cfg.NextcloudPass, basePrefix: strings.TrimRight(base, "/"), - httpClient: &http.Client{Timeout: 10 * time.Minute}, + httpClient: &http.Client{Timeout: 30 * time.Second}, } } @@ -57,14 +60,14 @@ func (c *WebDAVClient) ensureParent(ctx context.Context, remotePath string) erro cur = path.Join(cur, p) var mkurl string if cur == "" || cur == "/" { - mkurl = fmt.Sprintf("%s/%s", c.baseURL, url.PathEscape(p)) + mkurl = fmt.Sprintf("%s/%s", c.BaseURL, url.PathEscape(p)) } else { // Ensure there's a "/" between baseURL and cur sep := "" - if !strings.HasSuffix(c.baseURL, "/") && !strings.HasPrefix(cur, "/") { + if !strings.HasSuffix(c.BaseURL, "/") && !strings.HasPrefix(cur, "/") { sep = "/" } - mkurl = fmt.Sprintf("%s%s%s", c.baseURL, sep, strings.TrimPrefix(cur, "/")) + mkurl = fmt.Sprintf("%s%s%s", c.BaseURL, sep, strings.TrimPrefix(cur, "/")) } req, _ := http.NewRequestWithContext(ctx, "MKCOL", mkurl, nil) if c.user != "" { @@ -103,13 +106,13 @@ func (c *WebDAVClient) Upload(ctx context.Context, remotePath string, r io.Reade var full string if u == "" { - full = fmt.Sprintf("%s/%s", c.baseURL, url.PathEscape(rel)) + full = fmt.Sprintf("%s/%s", c.BaseURL, url.PathEscape(rel)) } else { - full = fmt.Sprintf("%s%s/%s", c.baseURL, u, url.PathEscape(rel)) + full = fmt.Sprintf("%s%s/%s", c.BaseURL, u, url.PathEscape(rel)) } full = strings.ReplaceAll(full, "%2F", "/") - fmt.Printf("[WEBDAV-UPLOAD] BaseURL: %s, BasePrefix: %s, RemotePath: %s, Full URL: %s\n", c.baseURL, c.basePrefix, remotePath, full) + fmt.Printf("[WEBDAV-UPLOAD] BaseURL: %s, BasePrefix: %s, RemotePath: %s, Full URL: %s\n", c.BaseURL, c.basePrefix, remotePath, full) req, err := http.NewRequestWithContext(ctx, "PUT", full, r) if err != nil { @@ -150,9 +153,9 @@ func (c *WebDAVClient) Download(ctx context.Context, remotePath string, rangeHea var full string if u == "" { - full = fmt.Sprintf("%s/%s", c.baseURL, url.PathEscape(rel)) + full = fmt.Sprintf("%s/%s", c.BaseURL, url.PathEscape(rel)) } else { - full = fmt.Sprintf("%s%s/%s", c.baseURL, u, url.PathEscape(rel)) + full = fmt.Sprintf("%s%s/%s", c.BaseURL, u, url.PathEscape(rel)) } full = strings.ReplaceAll(full, "%2F", "/") @@ -196,9 +199,9 @@ func (c *WebDAVClient) Delete(ctx context.Context, remotePath string) error { var full string if u == "" { - full = fmt.Sprintf("%s/%s", c.baseURL, url.PathEscape(rel)) + full = fmt.Sprintf("%s/%s", c.BaseURL, url.PathEscape(rel)) } else { - full = fmt.Sprintf("%s%s/%s", c.baseURL, u, url.PathEscape(rel)) + full = fmt.Sprintf("%s%s/%s", c.BaseURL, u, url.PathEscape(rel)) } full = strings.ReplaceAll(full, "%2F", "/") @@ -247,18 +250,18 @@ func (c *WebDAVClient) Move(ctx context.Context, sourcePath, targetPath string) // Build source URL var sourceURL string if u == "" { - sourceURL = fmt.Sprintf("%s/%s", c.baseURL, url.PathEscape(sourceRel)) + sourceURL = fmt.Sprintf("%s/%s", c.BaseURL, url.PathEscape(sourceRel)) } else { - sourceURL = fmt.Sprintf("%s%s/%s", c.baseURL, u, url.PathEscape(sourceRel)) + sourceURL = fmt.Sprintf("%s%s/%s", c.BaseURL, u, url.PathEscape(sourceRel)) } sourceURL = strings.ReplaceAll(sourceURL, "%2F", "/") // Build target URL var targetURL string if u == "" { - targetURL = fmt.Sprintf("%s/%s", c.baseURL, url.PathEscape(targetRel)) + targetURL = fmt.Sprintf("%s/%s", c.BaseURL, url.PathEscape(targetRel)) } else { - targetURL = fmt.Sprintf("%s%s/%s", c.baseURL, u, url.PathEscape(targetRel)) + targetURL = fmt.Sprintf("%s%s/%s", c.BaseURL, u, url.PathEscape(targetRel)) } targetURL = strings.ReplaceAll(targetURL, "%2F", "/")