Added gps-summary endpoint for Map integration
This commit is contained in:
75
src/files.rs
75
src/files.rs
@@ -951,6 +951,77 @@ fn is_path_above_base_dir<P: AsRef<Path> + Debug>(
|
||||
)
|
||||
}
|
||||
|
||||
/// Handler for GPS summary endpoint
|
||||
/// Returns lightweight GPS data for all photos with coordinates
|
||||
pub async fn get_gps_summary(
|
||||
_: Claims,
|
||||
request: HttpRequest,
|
||||
req: web::Query<FilesRequest>,
|
||||
state: web::Data<AppState>,
|
||||
exif_dao: web::Data<Mutex<Box<dyn ExifDao>>>,
|
||||
) -> Result<HttpResponse, actix_web::Error> {
|
||||
use crate::data::{GpsPhotoSummary, GpsPhotosResponse};
|
||||
|
||||
let parent_cx = extract_context_from_request(&request);
|
||||
let tracer = global_tracer();
|
||||
let mut span = tracer
|
||||
.span_builder("get_gps_summary")
|
||||
.start_with_context(&tracer, &parent_cx);
|
||||
|
||||
span.set_attribute(KeyValue::new("path", req.path.clone()));
|
||||
span.set_attribute(KeyValue::new("recursive", req.recursive.unwrap_or(false).to_string()));
|
||||
|
||||
let cx = opentelemetry::Context::current_with_span(span);
|
||||
|
||||
// The database stores relative paths, so we use the path as-is
|
||||
// Normalize empty path or "/" to return all GPS photos
|
||||
let requested_path = if req.path.is_empty() || req.path == "/" {
|
||||
""
|
||||
} else {
|
||||
// Just do basic validation to prevent path traversal
|
||||
if req.path.contains("..") {
|
||||
warn!("Path traversal attempt: {}", req.path);
|
||||
cx.span().set_status(Status::error("Invalid path"));
|
||||
return Ok(HttpResponse::Forbidden().json(serde_json::json!({
|
||||
"error": "Invalid path"
|
||||
})));
|
||||
}
|
||||
req.path.as_str()
|
||||
};
|
||||
|
||||
let recursive = req.recursive.unwrap_or(false);
|
||||
info!("Fetching GPS photos for path='{}' recursive={}", requested_path, recursive);
|
||||
|
||||
// Query database for all photos with GPS
|
||||
let mut exif_dao_guard = exif_dao.lock().expect("Unable to get ExifDao");
|
||||
match exif_dao_guard.get_all_with_gps(&cx, requested_path, recursive) {
|
||||
Ok(gps_data) => {
|
||||
let photos: Vec<GpsPhotoSummary> = gps_data
|
||||
.into_iter()
|
||||
.map(|(path, lat, lon, date_taken)| GpsPhotoSummary {
|
||||
path,
|
||||
lat,
|
||||
lon,
|
||||
date_taken,
|
||||
})
|
||||
.collect();
|
||||
|
||||
let total = photos.len();
|
||||
cx.span().set_attribute(KeyValue::new("result_count", total as i64));
|
||||
cx.span().set_status(Status::Ok);
|
||||
|
||||
Ok(HttpResponse::Ok().json(GpsPhotosResponse { photos, total }))
|
||||
}
|
||||
Err(e) => {
|
||||
error!("Error querying GPS data: {:?}", e);
|
||||
cx.span().set_status(Status::error(format!("Database error: {:?}", e)));
|
||||
Ok(HttpResponse::InternalServerError().json(serde_json::json!({
|
||||
"error": "Failed to query GPS data"
|
||||
})))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn move_file<FS: FileSystemAccess>(
|
||||
_: Claims,
|
||||
file_system: web::Data<FS>,
|
||||
@@ -1256,6 +1327,10 @@ mod tests {
|
||||
let count = file_paths.len() as i64;
|
||||
Ok((file_paths.to_vec(), count))
|
||||
}
|
||||
|
||||
fn get_all_with_gps(&mut self, context: &opentelemetry::Context, base_path: &str, recursive: bool) -> Result<Vec<(String, f64, f64, Option<i64>)>, DbError> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
mod api {
|
||||
|
||||
Reference in New Issue
Block a user