Refactor avatar upload and download handlers to use internal WebDAV client for server-to-server operations
This commit is contained in:
@@ -4195,16 +4195,19 @@ func uploadUserAvatarHandler(w http.ResponseWriter, r *http.Request, db *databas
|
||||
filename := fmt.Sprintf("%s%s", userID.String(), ext)
|
||||
|
||||
// Upload to Nextcloud at .avatars/<user-id>.<ext>
|
||||
client := storage.NewWebDAVClient(cfg)
|
||||
// Use internal Nextcloud WebDAV endpoint for server-to-server operations to avoid external TLS/timeouts
|
||||
internalClient := storage.NewUserWebDAVClient(cfg.NextcloudURL, cfg.NextcloudUser, cfg.NextcloudPass)
|
||||
avatarPath := fmt.Sprintf(".avatars/%s", filename)
|
||||
err = client.Upload(r.Context(), avatarPath, bytes.NewReader(fileBytes), header.Size)
|
||||
err = internalClient.Upload(r.Context(), avatarPath, bytes.NewReader(fileBytes), header.Size)
|
||||
if err != nil {
|
||||
errors.LogError(r, err, "Failed to upload avatar")
|
||||
errors.LogError(r, err, "Failed to upload avatar (internal)")
|
||||
errors.WriteError(w, errors.CodeInternal, "Server error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
webdavURL := fmt.Sprintf("%s/%s", client.BaseURL, avatarPath)
|
||||
// Store external-facing avatar URL in DB (so other components can reference it)
|
||||
externalClient := storage.NewWebDAVClient(cfg)
|
||||
webdavURL := fmt.Sprintf("%s/%s", strings.TrimRight(externalClient.BaseURL, "/"), avatarPath)
|
||||
|
||||
// Update user profile with avatar URL and updated_at
|
||||
_, err = db.ExecContext(r.Context(),
|
||||
@@ -4222,7 +4225,7 @@ func uploadUserAvatarHandler(w http.ResponseWriter, r *http.Request, db *databas
|
||||
verifyTimeout := 5 // seconds
|
||||
for i := 0; i < verifyRetries; i++ {
|
||||
vctx, vcancel := context.WithTimeout(r.Context(), time.Duration(verifyTimeout)*time.Second)
|
||||
resp, derr := client.Download(vctx, avatarPath, "")
|
||||
resp, derr := internalClient.Download(vctx, avatarPath, "")
|
||||
vcancel()
|
||||
if derr == nil && resp != nil {
|
||||
resp.Body.Close()
|
||||
@@ -4368,12 +4371,16 @@ func getUserAvatarHandler(w http.ResponseWriter, r *http.Request, db *database.D
|
||||
}
|
||||
|
||||
// Download from WebDAV with retries and backoff
|
||||
client := storage.NewWebDAVClient(cfg)
|
||||
if client == nil {
|
||||
// Use external client instance only to compute remotePath from stored avatar URL
|
||||
externalClient := storage.NewWebDAVClient(cfg)
|
||||
if externalClient == nil {
|
||||
errors.WriteError(w, errors.CodeInternal, "WebDAV client not configured", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
remotePath := strings.TrimPrefix(*avatarURL, client.BaseURL+"/")
|
||||
remotePath := strings.TrimPrefix(*avatarURL, externalClient.BaseURL+"/")
|
||||
|
||||
// Use internal admin WebDAV client to actually fetch the avatar (server-to-server)
|
||||
internalClient := storage.NewUserWebDAVClient(cfg.NextcloudURL, cfg.NextcloudUser, cfg.NextcloudPass)
|
||||
|
||||
// Configure retry & timeout from config
|
||||
timeoutSeconds := cfg.AvatarDownloadTimeoutSeconds
|
||||
@@ -4390,7 +4397,8 @@ func getUserAvatarHandler(w http.ResponseWriter, r *http.Request, db *database.D
|
||||
var dlErr error
|
||||
for attempt := 0; attempt < attempts; attempt++ {
|
||||
ctx, cancel := context.WithTimeout(r.Context(), time.Duration(timeoutSeconds)*time.Second)
|
||||
resp, dlErr = client.Download(ctx, remotePath, "")
|
||||
// Use internal client to avoid external network/TLS overhead
|
||||
resp, dlErr = internalClient.Download(ctx, remotePath, "")
|
||||
cancel()
|
||||
if dlErr == nil {
|
||||
break
|
||||
|
||||
Reference in New Issue
Block a user