sidecar: scoped labels + counts proxy (fixes cross-user label leak)

- New GET /api/sidecar/labels — proxies PP's labels, recalculates
  PhotoCount per user's BasePath via DB query
- New GET /api/sidecar/counts — returns user-scoped sidebar badges
  (all, review, archived, private, photos, videos, favorites)
- Fixed auth middleware to expose userUID and basePath on context
- Fixed ppClient.resolveSession — uses correct endpoint
  (GET /api/v1/session, not /api/v1/session/{token}) and correct
  JSON field names (UID, Name instead of UserUID, UserName)
- Frontend: listLabels now calls /api/sidecar/labels instead of /api/v1/labels
This commit is contained in:
2026-06-06 19:23:22 +02:00
parent 4c08eba27a
commit 8f97590d9f
6 changed files with 530 additions and 21 deletions

View File

@@ -26,6 +26,8 @@ func requireSession(pp *ppClient) gin.HandlerFunc {
}
c.Set("token", token)
c.Set("userName", user.UserName)
c.Set("userUID", user.UserUID)
c.Set("basePath", user.BasePath)
c.Next()
}
}
@@ -57,3 +59,29 @@ func ctxUserName(c *gin.Context) string {
}
return s
}
// ctxUserUID returns the PhotoPrism user UID resolved by requireSession.
func ctxUserUID(c *gin.Context) string {
v, ok := c.Get("userUID")
if !ok {
return ""
}
s, ok := v.(string)
if !ok {
return ""
}
return s
}
// ctxBasePath returns the PhotoPrism user BasePath resolved by requireSession.
func ctxBasePath(c *gin.Context) string {
v, ok := c.Get("basePath")
if !ok {
return ""
}
s, ok := v.(string)
if !ok {
return ""
}
return s
}