From 059e6baedf6955c0a5783392f03d455e30f6feda Mon Sep 17 00:00:00 2001 From: Michael Mayer Date: Thu, 27 Nov 2025 17:54:05 +0100 Subject: [PATCH] API: Improve logging in batch edit request handler #271 Signed-off-by: Michael Mayer --- internal/api/batch_photos_edit.go | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/internal/api/batch_photos_edit.go b/internal/api/batch_photos_edit.go index 687f8b2fd..94674fec1 100644 --- a/internal/api/batch_photos_edit.go +++ b/internal/api/batch_photos_edit.go @@ -11,10 +11,12 @@ import ( "github.com/photoprism/photoprism/internal/entity" "github.com/photoprism/photoprism/internal/entity/query" "github.com/photoprism/photoprism/internal/entity/search" + "github.com/photoprism/photoprism/internal/event" "github.com/photoprism/photoprism/internal/photoprism/batch" "github.com/photoprism/photoprism/internal/photoprism/get" "github.com/photoprism/photoprism/pkg/clean" "github.com/photoprism/photoprism/pkg/i18n" + "github.com/photoprism/photoprism/pkg/log/status" ) // BatchPhotosEdit returns and updates the metadata of multiple photos. @@ -76,8 +78,8 @@ func BatchPhotosEdit(router *gin.RouterGroup) { var preloadedPhotos map[string]*entity.Photo - if hydrated, err := query.PhotoPreloadByUIDs(photos.UIDs()); err != nil { - log.Errorf("batch: failed to preload photo selection: %s", err) + if hydrated, preloadErr := query.PhotoPreloadByUIDs(photos.UIDs()); preloadErr != nil { + log.Errorf("batch: %s (preload selection)", preloadErr) AbortUnexpectedError(c) return } else { @@ -95,11 +97,12 @@ func BatchPhotosEdit(router *gin.RouterGroup) { switch { case errors.Is(saveErr, batch.ErrBatchEditBusy), errors.Is(saveErr, batch.ErrBatchEditCanceled): - log.Warnf("batch: %s", saveErr) + log.Warnf("batch: %s (save)", saveErr) AbortBusy(c) return case saveErr != nil: - log.Errorf("batch: failed to persist photo updates: %s", saveErr) + log.Errorf("batch: %s (save)", saveErr) + event.AuditErr([]string{ClientIP(c), "session %s", "batch edit", status.Error(saveErr)}, s.RefID) AbortUnexpectedError(c) return } @@ -108,13 +111,18 @@ func BatchPhotosEdit(router *gin.RouterGroup) { saveResults = outcome.Results preloadedPhotos = outcome.Preloaded savedAny = outcome.SavedAny + + if n := len(saveRequests); n > 0 && (savedAny || outcome.Stats.AlbumMutations > 0 || outcome.Stats.LabelMutations > 0) { + event.AuditInfo([]string{ClientIP(c), "session %s", "batch edit", "update %s", status.Succeeded}, + s.RefID, english.Plural(n, "picture", "pictures")) + } } - // Refresh selected photos from database? - if !savedAny { - // Don't refresh. - } else if photos, _, err = search.BatchPhotos(frm.Photos, s); err != nil { - log.Errorf("batch: %s (refresh selection)", clean.Error(err)) + // Refresh selection if core metadata changed; albums and labels are automatically refreshed. + if savedAny { + if photos, _, err = search.BatchPhotos(frm.Photos, s); err != nil { + log.Errorf("batch: %s (refresh selection)", clean.Error(err)) + } } // Create batch edit form values form from photo metadata using the refreshed entities so