fix: honor library param in /image, /photos, /memories
The Phase 3 plumbing accepted `library=` but didn't actually route requests through the scoped library once it was resolved. Three concrete bugs surfaced when testing against a second mounted library: - `/image` always resolved paths against AppState.base_path (primary), so thumbnails for non-primary libraries 400'd when their rel_paths didn't exist under primary. Now resolves against the scoped library and defaults to primary when the param is omitted. - `/memories` walked the scoped library correctly but its helper functions hardcoded `library_id: PRIMARY_LIBRARY_ID` on every MemoryItem, causing clients to route thumbnails back to primary regardless of which library the memory actually came from. - `/photos` non-recursive listing delegated to a `RealFileSystem` constructed from AppState.base_path at startup, so walks always hit primary even when `library=2` was passed. The non-primary path now uses list_files against the scoped library's root; primary still goes through FileSystemAccess to preserve the existing test mock plumbing. Also adds `library` to ThumbnailRequest so the /image query param is actually parsed. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
40
src/files.rs
40
src/files.rs
@@ -422,7 +422,7 @@ pub async fn list_photos<TagD: TagDao, FS: FileSystemAccess>(
|
||||
sort_type,
|
||||
&mut exif_dao_guard,
|
||||
&span_context,
|
||||
app_state.base_path.as_ref(),
|
||||
scoped_library.root_path.as_ref(),
|
||||
limit,
|
||||
offset,
|
||||
);
|
||||
@@ -473,11 +473,14 @@ pub async fn list_photos<TagD: TagDao, FS: FileSystemAccess>(
|
||||
.unwrap_or_else(|e| e.error_response());
|
||||
}
|
||||
|
||||
// Use recursive or non-recursive file listing based on flag
|
||||
// Use recursive or non-recursive file listing based on flag. Both
|
||||
// paths must walk the *scoped* library's root; the generic
|
||||
// FileSystemAccess trait (file_system.get_files_for_path) is pinned
|
||||
// to AppState's base_path at construction time and doesn't know
|
||||
// which library the request targets.
|
||||
let files_result = if search_recursively {
|
||||
// For recursive search without tags, manually list files recursively
|
||||
is_valid_full_path(
|
||||
&PathBuf::from(&app_state.base_path),
|
||||
&PathBuf::from(&scoped_library.root_path),
|
||||
&PathBuf::from(search_path),
|
||||
false,
|
||||
)
|
||||
@@ -486,8 +489,21 @@ pub async fn list_photos<TagD: TagDao, FS: FileSystemAccess>(
|
||||
list_files_recursive(&path).unwrap_or_default()
|
||||
})
|
||||
.context("Invalid path")
|
||||
} else {
|
||||
} else if scoped_library.id == app_state.primary_library().id {
|
||||
// Primary library: preserve the original FileSystemAccess path so
|
||||
// the test-mock path (MockFileSystem) continues to work.
|
||||
file_system.get_files_for_path(search_path)
|
||||
} else {
|
||||
is_valid_full_path(
|
||||
&PathBuf::from(&scoped_library.root_path),
|
||||
&PathBuf::from(search_path),
|
||||
false,
|
||||
)
|
||||
.map(|path| {
|
||||
debug!("Valid path for non-recursive search: {:?}", path);
|
||||
list_files(&path).unwrap_or_default()
|
||||
})
|
||||
.context("Invalid path")
|
||||
};
|
||||
|
||||
match files_result {
|
||||
@@ -510,10 +526,10 @@ pub async fn list_photos<TagD: TagDao, FS: FileSystemAccess>(
|
||||
match path.metadata() {
|
||||
Ok(md) => {
|
||||
let relative =
|
||||
path.strip_prefix(&app_state.base_path).unwrap_or_else(|_| {
|
||||
path.strip_prefix(&scoped_library.root_path).unwrap_or_else(|_| {
|
||||
panic!(
|
||||
"Unable to strip base path {} from file path {}",
|
||||
&app_state.base_path.path(),
|
||||
"Unable to strip library root {} from file path {}",
|
||||
&scoped_library.root_path,
|
||||
path.display()
|
||||
)
|
||||
});
|
||||
@@ -530,11 +546,11 @@ pub async fn list_photos<TagD: TagDao, FS: FileSystemAccess>(
|
||||
// Include files without metadata if they have extensions
|
||||
if path.extension().is_some() {
|
||||
let relative = path
|
||||
.strip_prefix(&app_state.base_path)
|
||||
.strip_prefix(&scoped_library.root_path)
|
||||
.unwrap_or_else(|_| {
|
||||
panic!(
|
||||
"Unable to strip base path {} from file path {}",
|
||||
&app_state.base_path.path(),
|
||||
"Unable to strip library root {} from file path {}",
|
||||
&scoped_library.root_path,
|
||||
path.display()
|
||||
)
|
||||
});
|
||||
@@ -668,7 +684,7 @@ pub async fn list_photos<TagD: TagDao, FS: FileSystemAccess>(
|
||||
sort_type,
|
||||
&mut exif_dao_guard,
|
||||
&span_context,
|
||||
app_state.base_path.as_ref(),
|
||||
scoped_library.root_path.as_ref(),
|
||||
limit,
|
||||
offset,
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user