Refactor WebDAV client to expose BaseURL and update avatar upload logic for improved URL handling
This commit is contained in:
BIN
go_cloud/api
BIN
go_cloud/api
Binary file not shown.
@@ -4038,7 +4038,7 @@ func uploadUserAvatarHandler(w http.ResponseWriter, r *http.Request, db *databas
|
|||||||
|
|
||||||
// Upload to Nextcloud
|
// Upload to Nextcloud
|
||||||
client := storage.NewWebDAVClient(cfg)
|
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)
|
err = client.Upload(r.Context(), avatarPath, bytes.NewReader(fileBytes), header.Size)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errors.LogError(r, err, "Failed to upload avatar")
|
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
|
// 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
|
// In a real setup, you'd configure Nextcloud to serve public URLs or use a CDN
|
||||||
publicURL := "/user/avatar"
|
publicURL := "/user/avatar"
|
||||||
|
webdavURL := fmt.Sprintf("%s/%s", client.BaseURL, avatarPath)
|
||||||
|
|
||||||
// Update user profile with avatar URL
|
// Update user profile with avatar URL
|
||||||
_, err = db.ExecContext(r.Context(),
|
_, err = db.ExecContext(r.Context(),
|
||||||
`UPDATE users SET avatar_url = $1, updated_at = NOW() WHERE id = $2`,
|
`UPDATE users SET avatar_url = $1, updated_at = NOW() WHERE id = $2`,
|
||||||
publicURL, userID)
|
webdavURL, userID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errors.LogError(r, err, "Failed to update user avatar")
|
errors.LogError(r, err, "Failed to update user avatar")
|
||||||
errors.WriteError(w, errors.CodeInternal, "Server error", http.StatusInternalServerError)
|
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
|
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
|
// Download from WebDAV
|
||||||
client := storage.NewWebDAVClient(cfg)
|
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, "")
|
resp, err := client.Download(r.Context(), remotePath, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errors.LogError(r, err, "Failed to download avatar")
|
errors.LogError(r, err, "Failed to download avatar")
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ func NewUserWebDAVClient(nextcloudBaseURL, username, password string) *WebDAVCli
|
|||||||
fullURL := fmt.Sprintf("%s/remote.php/dav/files/%s", baseURL, username)
|
fullURL := fmt.Sprintf("%s/remote.php/dav/files/%s", baseURL, username)
|
||||||
|
|
||||||
return &WebDAVClient{
|
return &WebDAVClient{
|
||||||
baseURL: fullURL,
|
BaseURL: fullURL,
|
||||||
user: username,
|
user: username,
|
||||||
pass: password,
|
pass: password,
|
||||||
basePrefix: "/",
|
basePrefix: "/",
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type WebDAVClient struct {
|
type WebDAVClient struct {
|
||||||
baseURL string
|
BaseURL string
|
||||||
user string
|
user string
|
||||||
pass string
|
pass string
|
||||||
basePrefix string
|
basePrefix string
|
||||||
@@ -29,17 +29,20 @@ func NewWebDAVClient(cfg *config.Config) *WebDAVClient {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
u := strings.TrimRight(cfg.NextcloudURL, "/")
|
u := strings.TrimRight(cfg.NextcloudURL, "/")
|
||||||
|
if !strings.Contains(u, "/remote.php") {
|
||||||
|
u += "/remote.php/dav/files/" + cfg.NextcloudUser
|
||||||
|
}
|
||||||
base := cfg.NextcloudBase
|
base := cfg.NextcloudBase
|
||||||
if base == "" {
|
if base == "" {
|
||||||
base = "/"
|
base = "/"
|
||||||
}
|
}
|
||||||
log.Printf("[WEBDAV] Initializing WebDAV client - URL: %s, User: %s, BasePath: %s\n", u, cfg.NextcloudUser, base)
|
log.Printf("[WEBDAV] Initializing WebDAV client - URL: %s, User: %s, BasePath: %s\n", u, cfg.NextcloudUser, base)
|
||||||
return &WebDAVClient{
|
return &WebDAVClient{
|
||||||
baseURL: u,
|
BaseURL: u,
|
||||||
user: cfg.NextcloudUser,
|
user: cfg.NextcloudUser,
|
||||||
pass: cfg.NextcloudPass,
|
pass: cfg.NextcloudPass,
|
||||||
basePrefix: strings.TrimRight(base, "/"),
|
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)
|
cur = path.Join(cur, p)
|
||||||
var mkurl string
|
var mkurl string
|
||||||
if cur == "" || cur == "/" {
|
if cur == "" || cur == "/" {
|
||||||
mkurl = fmt.Sprintf("%s/%s", c.baseURL, url.PathEscape(p))
|
mkurl = fmt.Sprintf("%s/%s", c.BaseURL, url.PathEscape(p))
|
||||||
} else {
|
} else {
|
||||||
// Ensure there's a "/" between baseURL and cur
|
// Ensure there's a "/" between baseURL and cur
|
||||||
sep := ""
|
sep := ""
|
||||||
if !strings.HasSuffix(c.baseURL, "/") && !strings.HasPrefix(cur, "/") {
|
if !strings.HasSuffix(c.BaseURL, "/") && !strings.HasPrefix(cur, "/") {
|
||||||
sep = "/"
|
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)
|
req, _ := http.NewRequestWithContext(ctx, "MKCOL", mkurl, nil)
|
||||||
if c.user != "" {
|
if c.user != "" {
|
||||||
@@ -103,13 +106,13 @@ func (c *WebDAVClient) Upload(ctx context.Context, remotePath string, r io.Reade
|
|||||||
|
|
||||||
var full string
|
var full string
|
||||||
if u == "" {
|
if u == "" {
|
||||||
full = fmt.Sprintf("%s/%s", c.baseURL, url.PathEscape(rel))
|
full = fmt.Sprintf("%s/%s", c.BaseURL, url.PathEscape(rel))
|
||||||
} else {
|
} 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", "/")
|
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)
|
req, err := http.NewRequestWithContext(ctx, "PUT", full, r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -150,9 +153,9 @@ func (c *WebDAVClient) Download(ctx context.Context, remotePath string, rangeHea
|
|||||||
|
|
||||||
var full string
|
var full string
|
||||||
if u == "" {
|
if u == "" {
|
||||||
full = fmt.Sprintf("%s/%s", c.baseURL, url.PathEscape(rel))
|
full = fmt.Sprintf("%s/%s", c.BaseURL, url.PathEscape(rel))
|
||||||
} else {
|
} 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", "/")
|
full = strings.ReplaceAll(full, "%2F", "/")
|
||||||
|
|
||||||
@@ -196,9 +199,9 @@ func (c *WebDAVClient) Delete(ctx context.Context, remotePath string) error {
|
|||||||
|
|
||||||
var full string
|
var full string
|
||||||
if u == "" {
|
if u == "" {
|
||||||
full = fmt.Sprintf("%s/%s", c.baseURL, url.PathEscape(rel))
|
full = fmt.Sprintf("%s/%s", c.BaseURL, url.PathEscape(rel))
|
||||||
} else {
|
} 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", "/")
|
full = strings.ReplaceAll(full, "%2F", "/")
|
||||||
|
|
||||||
@@ -247,18 +250,18 @@ func (c *WebDAVClient) Move(ctx context.Context, sourcePath, targetPath string)
|
|||||||
// Build source URL
|
// Build source URL
|
||||||
var sourceURL string
|
var sourceURL string
|
||||||
if u == "" {
|
if u == "" {
|
||||||
sourceURL = fmt.Sprintf("%s/%s", c.baseURL, url.PathEscape(sourceRel))
|
sourceURL = fmt.Sprintf("%s/%s", c.BaseURL, url.PathEscape(sourceRel))
|
||||||
} else {
|
} 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", "/")
|
sourceURL = strings.ReplaceAll(sourceURL, "%2F", "/")
|
||||||
|
|
||||||
// Build target URL
|
// Build target URL
|
||||||
var targetURL string
|
var targetURL string
|
||||||
if u == "" {
|
if u == "" {
|
||||||
targetURL = fmt.Sprintf("%s/%s", c.baseURL, url.PathEscape(targetRel))
|
targetURL = fmt.Sprintf("%s/%s", c.BaseURL, url.PathEscape(targetRel))
|
||||||
} else {
|
} 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", "/")
|
targetURL = strings.ReplaceAll(targetURL, "%2F", "/")
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user