Add Move File functionality and endpoint
This commit is contained in:
61
src/files.rs
61
src/files.rs
@@ -1,17 +1,19 @@
|
||||
use std::fmt::Debug;
|
||||
use std::fs::read_dir;
|
||||
use std::io;
|
||||
use std::io::ErrorKind;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::sync::Mutex;
|
||||
|
||||
use ::anyhow;
|
||||
use anyhow::{anyhow, Context};
|
||||
|
||||
use actix_web::web::Data;
|
||||
use actix_web::{
|
||||
web::{self, Query},
|
||||
HttpResponse,
|
||||
};
|
||||
use log::{debug, error};
|
||||
use log::{debug, error, info};
|
||||
|
||||
use crate::data::{Claims, FilesRequest, FilterMode, PhotosResponse};
|
||||
use crate::AppState;
|
||||
@@ -19,6 +21,7 @@ use crate::AppState;
|
||||
use crate::error::IntoHttpError;
|
||||
use crate::tags::TagDao;
|
||||
use path_absolutize::*;
|
||||
use serde::Deserialize;
|
||||
|
||||
pub async fn list_photos<TagD: TagDao, FS: FileSystemAccess>(
|
||||
_: Claims,
|
||||
@@ -182,8 +185,49 @@ fn is_path_above_base_dir<P: AsRef<Path> + Debug>(
|
||||
)
|
||||
}
|
||||
|
||||
pub async fn move_file<FS: FileSystemAccess>(
|
||||
_: Claims,
|
||||
file_system: web::Data<FS>,
|
||||
app_state: Data<AppState>,
|
||||
request: web::Json<MoveFileRequest>,
|
||||
) -> HttpResponse {
|
||||
match is_valid_full_path(&app_state.base_path, &request.source, false)
|
||||
.and_then(|source| {
|
||||
is_valid_full_path(&app_state.base_path, &request.destination, true)
|
||||
.map(|dest| (source, dest))
|
||||
})
|
||||
.ok_or(ErrorKind::InvalidData)
|
||||
.map(|(source, dest)| file_system.move_file(source, dest))
|
||||
{
|
||||
Ok(_) => {
|
||||
info!("Moved file: {} -> {}", request.source, request.destination,);
|
||||
|
||||
HttpResponse::Ok().finish()
|
||||
}
|
||||
Err(e) => {
|
||||
error!(
|
||||
"Error moving file: {} to: {}. {}",
|
||||
request.source, request.destination, e
|
||||
);
|
||||
|
||||
if e == ErrorKind::InvalidData {
|
||||
HttpResponse::BadRequest().finish()
|
||||
} else {
|
||||
HttpResponse::InternalServerError().finish()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct MoveFileRequest {
|
||||
source: String,
|
||||
destination: String,
|
||||
}
|
||||
|
||||
pub trait FileSystemAccess {
|
||||
fn get_files_for_path(&self, path: &str) -> anyhow::Result<Vec<PathBuf>>;
|
||||
fn move_file<P: AsRef<Path>>(&self, from: P, destination: P) -> anyhow::Result<()>;
|
||||
}
|
||||
|
||||
pub struct RealFileSystem {
|
||||
@@ -205,6 +249,17 @@ impl FileSystemAccess for RealFileSystem {
|
||||
})
|
||||
.context("Invalid path")
|
||||
}
|
||||
|
||||
fn move_file<P: AsRef<Path>>(&self, from: P, destination: P) -> anyhow::Result<()> {
|
||||
let name = from
|
||||
.as_ref()
|
||||
.file_name()
|
||||
.map(|n| n.to_str().unwrap_or_default().to_string())
|
||||
.unwrap_or_default();
|
||||
|
||||
std::fs::rename(from, destination)
|
||||
.with_context(|| format!("Failed to move file: {:?}", name))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@@ -248,6 +303,10 @@ mod tests {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn move_file<P: AsRef<Path>>(&self, from: P, destination: P) -> anyhow::Result<()> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
mod api {
|
||||
|
||||
Reference in New Issue
Block a user