feat(sidecar): extend scoped proxy to web-client mutations, harden path classification

Batch archive/restore/delete/approve/private validate every UID against
the PhotoPrism DB in one query. Per-photo PUT/approve/like/stack-file
ops are ownership-checked. Admin-role sessions pass through fully so
settings/users/index dialogs keep working. Paths are unescaped+cleaned
before classification so encoded dot-segments can't smuggle past the
allowlist. Full httptest coverage of the routing decisions.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-03 13:05:12 +02:00
parent e578e1ce75
commit 312a4c1ee4
7 changed files with 307 additions and 72 deletions

View File

@@ -115,14 +115,14 @@ func handleLabels(pp *ppClient, ppDb *gorm.DB) gin.HandlerFunc {
// PpCounts mirrors PhotoPrism's session config.count block that drives
// the sidebar badges (review, archive, all, etc.).
type PpCounts struct {
All int `json:"all"`
Photos int `json:"photos"`
Media int `json:"media"`
Videos int `json:"videos"`
Review int `json:"review"`
Archived int `json:"archived"`
Hidden int `json:"hidden"`
Private int `json:"private"`
All int `json:"all"`
Photos int `json:"photos"`
Media int `json:"media"`
Videos int `json:"videos"`
Review int `json:"review"`
Archived int `json:"archived"`
Hidden int `json:"hidden"`
Private int `json:"private"`
Favorites int `json:"favorites"`
}
@@ -168,4 +168,4 @@ func handleScopedCounts(ppDb *gorm.DB) gin.HandlerFunc {
c.JSON(http.StatusOK, counts)
}
}
}