diff --git a/fl-server/src/auth.rs b/fl-server/src/auth.rs index 238e376..de455d5 100644 --- a/fl-server/src/auth.rs +++ b/fl-server/src/auth.rs @@ -55,7 +55,7 @@ pub async fn sign_in_handler( Extension(cfg): Extension, Json(user_data): Json, ) -> impl IntoResponse { - let user = match get_user_by_username(cfg.users, &user_data.username) { + let user = match get_user_by_username(&cfg.users, &user_data.username) { Some(user) => user, None => { return Err(ResponseError::Unauthorized( @@ -70,7 +70,7 @@ pub async fn sign_in_handler( )); } - let token = encode_jwt(user.username, cfg.jwt_secret, cfg.jwt_expire_hours) + let token = encode_jwt(user.username.clone(), cfg.jwt_secret, cfg.jwt_expire_hours) .map_err(|_| ResponseError::InternalServerError)?; Ok(ResponseResult::SignedIn(SignInResponse { @@ -78,9 +78,8 @@ pub async fn sign_in_handler( })) } -fn get_user_by_username(users: Vec, username: &str) -> Option { - let user = users.iter().find(|u| u.username == username)?; - Some(user.clone()) +pub fn get_user_by_username<'a>(users: &'a [User], username: &str) -> Option<&'a User> { + users.iter().find(|u| u.username == username) } pub fn encode_jwt( @@ -129,7 +128,15 @@ pub async fn authorize( let mut header = auth_header.split_whitespace(); let (_, token) = (header.next(), header.next()); - let token_data = match decode_jwt(token.unwrap().to_string(), cfg.jwt_secret) { + let token_str = match token { + Some(t) => t.to_string(), + None => { + log::error!("failed to get token string"); + return Err(ResponseError::InternalServerError); + } + }; + + let token_data = match decode_jwt(token_str, cfg.jwt_secret) { Ok(data) => data, Err(_) => { return Err(ResponseError::Forbidden( @@ -138,7 +145,7 @@ pub async fn authorize( } }; - let current_user = match get_user_by_username(cfg.users, &token_data.claims.username) { + let current_user = match get_user_by_username(&cfg.users, &token_data.claims.username) { Some(user) => user, None => { return Err(ResponseError::Unauthorized( @@ -147,6 +154,6 @@ pub async fn authorize( } }; - req.extensions_mut().insert(current_user.username); + req.extensions_mut().insert(current_user.username.clone()); Ok(next.run(req).await) } diff --git a/fl-server/src/handlers.rs b/fl-server/src/handlers.rs index 7525acf..6665c48 100644 --- a/fl-server/src/handlers.rs +++ b/fl-server/src/handlers.rs @@ -5,7 +5,6 @@ use axum::{ }; use axum_macros::debug_handler; use std::{collections::HashMap, fs, sync::Arc}; -use tokio::io; use bollard::auth::DockerCredentials; use serde::{Deserialize, Serialize}; @@ -98,37 +97,28 @@ pub async fn create_flist_handler( } let fl_name = docker_image.replace([':', '/'], "-") + ".fl"; - let username_dir = format!("{}/{}", cfg.flist_dir, username); + let username_dir = std::path::Path::new(&cfg.flist_dir).join(&username); + let fl_path = username_dir.join(&fl_name); - match flist_exists(std::path::Path::new(&username_dir), &fl_name).await { - Ok(exists) => { - if exists { - return Err(ResponseError::Conflict("flist already exists".to_string())); - } - } - Err(e) => { - log::error!("failed to check flist existence with error {:?}", e); - return Err(ResponseError::InternalServerError); - } + if fl_path.exists() { + return Err(ResponseError::Conflict("flist already exists".to_string())); } let created = fs::create_dir_all(&username_dir); if created.is_err() { log::error!( - "failed to create user flist directory `{}` with error {:?}", + "failed to create user flist directory `{:?}` with error {:?}", &username_dir, created.err() ); return Err(ResponseError::InternalServerError); } - let fl_path: String = format!("{}/{}", username_dir, fl_name); - let meta = match Writer::new(&fl_path).await { Ok(writer) => writer, Err(err) => { log::error!( - "failed to create a new writer for flist `{}` with error {}", + "failed to create a new writer for flist `{:?}` with error {}", fl_path, err ); @@ -150,17 +140,25 @@ pub async fn create_flist_handler( }; let current_job = job.clone(); - state.jobs_state.lock().unwrap().insert( - job.id.clone(), - FlistState::Accepted(format!("flist '{}' is accepted", fl_name)), - ); - - tokio::spawn(async move { - state.jobs_state.lock().unwrap().insert( + state + .jobs_state + .lock() + .expect("failed to lock state") + .insert( job.id.clone(), - FlistState::Started(format!("flist '{}' is started", fl_name)), + FlistState::Accepted(format!("flist '{}' is accepted", fl_name)), ); + tokio::spawn(async move { + state + .jobs_state + .lock() + .expect("failed to lock state") + .insert( + job.id.clone(), + FlistState::Started(format!("flist '{}' is started", fl_name)), + ); + let res = docker2fl::convert(meta, store, &docker_image, credentials).await; // remove the file created with the writer if fl creation failed @@ -170,18 +168,22 @@ pub async fn create_flist_handler( state .jobs_state .lock() - .unwrap() + .expect("failed to lock state") .insert(job.id.clone(), FlistState::Failed); return; } - state.jobs_state.lock().unwrap().insert( - job.id.clone(), - FlistState::Created(format!( - "flist {}:{}/{}/{}/{} is created successfully", - cfg.host, cfg.port, cfg.flist_dir, username, fl_name - )), - ); + state + .jobs_state + .lock() + .expect("failed to lock state") + .insert( + job.id.clone(), + FlistState::Created(format!( + "flist {}:{}/{}/{}/{} is created successfully", + cfg.host, cfg.port, cfg.flist_dir, username, fl_name + )), + ); }); Ok(ResponseResult::FlistCreated(current_job)) @@ -209,7 +211,7 @@ pub async fn get_flist_state_handler( if !&state .jobs_state .lock() - .unwrap() + .expect("failed to lock state") .contains_key(&flist_job_id.clone()) { return Err(ResponseError::NotFound("flist doesn't exist".to_string())); @@ -218,9 +220,9 @@ pub async fn get_flist_state_handler( let res_state = state .jobs_state .lock() - .unwrap() + .expect("failed to lock state") .get(&flist_job_id.clone()) - .unwrap() + .expect("failed to get from state") .to_owned(); match res_state { @@ -230,7 +232,7 @@ pub async fn get_flist_state_handler( state .jobs_state .lock() - .unwrap() + .expect("failed to lock state") .remove(&flist_job_id.clone()); Ok(ResponseResult::FlistState(res_state)) @@ -239,7 +241,7 @@ pub async fn get_flist_state_handler( state .jobs_state .lock() - .unwrap() + .expect("failed to lock state") .remove(&flist_job_id.clone()); return Err(ResponseError::InternalServerError); @@ -261,13 +263,12 @@ pub async fn get_flist_state_handler( pub async fn list_flists_handler(Extension(cfg): Extension) -> impl IntoResponse { let mut flists: HashMap> = HashMap::new(); - let rs = visit_dir_one_level(std::path::Path::new(&cfg.flist_dir)).await; + let rs = visit_dir_one_level(&cfg.flist_dir).await; match rs { Ok(files) => { for file in files { if !file.is_file { - let flists_per_username = - visit_dir_one_level(std::path::Path::new(&file.path_uri)).await; + let flists_per_username = visit_dir_one_level(&file.path_uri).await; match flists_per_username { Ok(files) => flists.insert(file.name, files), Err(e) => { @@ -286,17 +287,3 @@ pub async fn list_flists_handler(Extension(cfg): Extension) -> i Ok(ResponseResult::Flists(flists)) } - -pub async fn flist_exists(dir_path: &std::path::Path, flist_name: &String) -> io::Result { - let mut dir = tokio::fs::read_dir(dir_path).await?; - - while let Some(child) = dir.next_entry().await? { - let file_name = child.file_name().to_string_lossy().to_string(); - - if file_name.eq(flist_name) { - return Ok(true); - } - } - - Ok(false) -} diff --git a/fl-server/src/serve_flists.rs b/fl-server/src/serve_flists.rs index dd31f16..07d61f3 100644 --- a/fl-server/src/serve_flists.rs +++ b/fl-server/src/serve_flists.rs @@ -77,7 +77,8 @@ pub async fn serve_flists(req: Request) -> impl IntoResponse { }; } -pub async fn visit_dir_one_level(path: &std::path::Path) -> io::Result> { +pub async fn visit_dir_one_level>(path: P) -> io::Result> { + let path = path.as_ref(); let mut dir = tokio::fs::read_dir(path).await?; let mut files: Vec = Vec::new(); @@ -94,7 +95,7 @@ pub async fn visit_dir_one_level(path: &std::path::Path) -> io::Result { *resp.status_mut() = StatusCode::NOT_FOUND; - resp.headers_mut() - .insert(FAIL_REASON_HEADER_NAME, reason.parse().unwrap()); + resp.headers_mut().insert( + FAIL_REASON_HEADER_NAME, + reason.parse().expect("failed to parse error"), + ); } ResponseError::BadRequest(reason) => { *resp.status_mut() = StatusCode::BAD_REQUEST; - resp.headers_mut() - .insert(FAIL_REASON_HEADER_NAME, reason.parse().unwrap()); + resp.headers_mut().insert( + FAIL_REASON_HEADER_NAME, + reason.parse().expect("failed to parse error"), + ); } ResponseError::InternalError(reason) => { *resp.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - resp.headers_mut() - .insert(FAIL_REASON_HEADER_NAME, reason.parse().unwrap()); + resp.headers_mut().insert( + FAIL_REASON_HEADER_NAME, + reason.parse().expect("failed to parse error"), + ); } } resp