work on better path response, add dir route

This commit is contained in:
jb-alvarado 2022-07-01 15:45:24 +02:00
parent 7352735f15
commit 70f5dd7b5b
3 changed files with 79 additions and 14 deletions

View File

@ -15,11 +15,11 @@ use utils::{
auth, db_path, init_config,
models::LoginUser,
routes::{
add_preset, add_user, del_playlist, file_browser, gen_playlist, get_all_settings, get_log,
get_playlist, get_playout_config, get_presets, get_settings, get_user, jump_to_last,
jump_to_next, login, media_current, media_last, media_next, move_rename, patch_settings,
process_control, remove, reset_playout, save_file, save_playlist, send_text_message,
update_playout_config, update_preset, update_user,
add_dir, add_preset, add_user, del_playlist, file_browser, gen_playlist, get_all_settings,
get_log, get_playlist, get_playout_config, get_presets, get_settings, get_user,
jump_to_last, jump_to_next, login, media_current, media_last, media_next, move_rename,
patch_settings, process_control, remove, reset_playout, save_file, save_playlist,
send_text_message, update_playout_config, update_preset, update_user,
},
run_args, Role,
};
@ -101,6 +101,7 @@ async fn main() -> std::io::Result<()> {
.service(del_playlist)
.service(get_log)
.service(file_browser)
.service(add_dir)
.service(move_rename)
.service(remove)
.service(save_file),

View File

@ -19,6 +19,7 @@ use ffplayout_lib::utils::file_extension;
#[derive(Debug, Deserialize, Serialize, Clone)]
pub struct PathObject {
pub source: String,
parent: Option<String>,
folders: Option<Vec<String>>,
files: Option<Vec<String>>,
}
@ -27,6 +28,7 @@ impl PathObject {
fn new(source: String) -> Self {
Self {
source,
parent: None,
folders: Some(vec![]),
files: Some(vec![]),
}
@ -39,21 +41,52 @@ pub struct MoveObject {
target: String,
}
pub async fn browser(id: i64, path_obj: &PathObject) -> Result<PathObject, ServiceError> {
let (config, _) = playout_config(&id).await?;
let path = PathBuf::from(config.storage.path);
let extensions = config.storage.extensions;
let path_component = RelativePath::new(&path_obj.source)
/// Normalize absolut path
///
/// This function takes care, that it is not possible to break out from root_path.
/// It also gives alway a relative path back.
fn norm_abs_path(root_path: String, path_obj: &PathObject) -> (PathBuf, String, String) {
let mut path = PathBuf::from(root_path.clone());
let path_relative = RelativePath::new(&root_path)
.normalize()
.to_string()
.replace("../", "");
let path = path.join(path_component.clone());
let mut obj = PathObject::new(path_component.clone());
let mut source_relative = RelativePath::new(&path_obj.source)
.normalize()
.to_string()
.replace("../", "");
let path_suffix = path.file_name().unwrap().to_string_lossy().to_string();
if path_obj.source.starts_with(&root_path) || source_relative.starts_with(&path_relative) {
source_relative = source_relative
.strip_prefix(&path_relative)
.and_then(|s| s.strip_prefix('/'))
.unwrap_or_default()
.to_string();
} else {
source_relative = source_relative
.strip_prefix(&path_suffix)
.and_then(|s| s.strip_prefix('/'))
.unwrap_or(&source_relative)
.to_string();
}
path = path.join(&source_relative);
(path, path_suffix, source_relative)
}
pub async fn browser(id: i64, path_obj: &PathObject) -> Result<PathObject, ServiceError> {
let (config, _) = playout_config(&id).await?;
let extensions = config.storage.extensions;
let (path, parent, path_component) = norm_abs_path(config.storage.path, path_obj);
let mut obj = PathObject::new(path_component);
obj.parent = Some(parent);
let mut paths: Vec<_> = match fs::read_dir(path) {
Ok(p) => p.filter_map(|r| r.ok()).collect(),
Err(e) => {
error!("{e} in {path_component}");
error!("{e} in {}", path_obj.source);
return Err(ServiceError::InternalServerError);
}
};
@ -87,6 +120,22 @@ pub async fn browser(id: i64, path_obj: &PathObject) -> Result<PathObject, Servi
Ok(obj)
}
pub async fn create_directory(
id: i64,
path_obj: &PathObject,
) -> Result<HttpResponse, ServiceError> {
let (config, _) = playout_config(&id).await?;
let (path, _, _) = norm_abs_path(config.storage.path, path_obj);
if let Err(e) = fs::create_dir_all(&path) {
return Err(ServiceError::BadRequest(e.to_string()));
}
info!("create folder: <b><magenta>{}</></b>", path.display());
Ok(HttpResponse::Ok().into())
}
// fn copy_and_delete(source: &PathBuf, target: &PathBuf) -> Result<PathObject, ServiceError> {
// match fs::copy(&source, &target) {
// Ok(_) => {

View File

@ -14,7 +14,10 @@ use crate::utils::{
auth::{create_jwt, Claims},
control::{control_service, control_state, media_info, send_message, Process},
errors::ServiceError,
files::{browser, remove_file_or_folder, rename_file, upload, MoveObject, PathObject},
files::{
browser, create_directory, remove_file_or_folder, rename_file, upload, MoveObject,
PathObject,
},
handles::{
db_add_preset, db_add_user, db_get_all_settings, db_get_presets, db_get_settings,
db_get_user, db_login, db_role, db_update_preset, db_update_settings, db_update_user,
@ -481,6 +484,18 @@ pub async fn file_browser(
}
}
/// curl -X POST http://localhost:8080/api/file/1/create-folder/
/// --header 'Content-Type: application/json' --header 'Authorization: <TOKEN>'
/// -d '{"source": "<FOLDER PATH>"}'
#[post("/file/{id}/create-folder/")]
#[has_any_role("Role::Admin", "Role::User", type = "Role")]
pub async fn add_dir(
id: web::Path<i64>,
data: web::Json<PathObject>,
) -> Result<HttpResponse, ServiceError> {
create_directory(*id, &data.into_inner()).await
}
/// curl -X POST http://localhost:8080/api/file/1/move/
/// --header 'Content-Type: application/json' --header 'Authorization: <TOKEN>'
/// -d '{"source": "<SOURCE>", "target": "<TARGET>"}'