Skip to content

Commit

Permalink
fix flist_exists, get_user and visit_dir_one_level
Browse files Browse the repository at this point in the history
  • Loading branch information
rawdaGastan committed Sep 17, 2024
1 parent e588b80 commit 056aabf
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 72 deletions.
23 changes: 15 additions & 8 deletions fl-server/src/auth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ pub async fn sign_in_handler(
Extension(cfg): Extension<config::Config>,
Json(user_data): Json<SignInBody>,
) -> 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(
Expand All @@ -70,17 +70,16 @@ 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 {
access_token: token,
}))
}

fn get_user_by_username(users: Vec<User>, username: &str) -> Option<User> {
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(
Expand Down Expand Up @@ -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(
Expand All @@ -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(
Expand All @@ -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)
}
95 changes: 41 additions & 54 deletions fl-server/src/handlers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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
);
Expand All @@ -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
Expand All @@ -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))
Expand Down Expand Up @@ -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()));
Expand All @@ -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 {
Expand All @@ -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))
Expand All @@ -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);
Expand All @@ -261,13 +263,12 @@ pub async fn get_flist_state_handler(
pub async fn list_flists_handler(Extension(cfg): Extension<config::Config>) -> impl IntoResponse {
let mut flists: HashMap<String, Vec<FileInfo>> = 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) => {
Expand All @@ -286,17 +287,3 @@ pub async fn list_flists_handler(Extension(cfg): Extension<config::Config>) -> i

Ok(ResponseResult::Flists(flists))
}

pub async fn flist_exists(dir_path: &std::path::Path, flist_name: &String) -> io::Result<bool> {
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)
}
27 changes: 17 additions & 10 deletions fl-server/src/serve_flists.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,8 @@ pub async fn serve_flists(req: Request<Body>) -> impl IntoResponse {
};
}

pub async fn visit_dir_one_level(path: &std::path::Path) -> io::Result<Vec<FileInfo>> {
pub async fn visit_dir_one_level<P: AsRef<std::path::Path>>(path: P) -> io::Result<Vec<FileInfo>> {
let path = path.as_ref();
let mut dir = tokio::fs::read_dir(path).await?;
let mut files: Vec<FileInfo> = Vec::new();

Expand All @@ -94,7 +95,7 @@ pub async fn visit_dir_one_level(path: &std::path::Path) -> io::Result<Vec<FileI
.await?
.modified()?
.duration_since(std::time::SystemTime::UNIX_EPOCH)
.unwrap()
.expect("failed to get duration")
.as_secs() as i64,
});
}
Expand All @@ -108,9 +109,9 @@ mod filters {
time::format_description::parse("[year]-[month]-[day] [hour]:[minute]:[second] UTC")
{
return Ok(time::OffsetDateTime::from_unix_timestamp(*ts)
.unwrap()
.expect("failed to get utc time")
.format(&format)
.unwrap());
.expect("failed to format time"));
}
Err(askama::Error::Fmt(std::fmt::Error))
}
Expand Down Expand Up @@ -172,18 +173,24 @@ impl IntoResponse for ErrorTemplate {
match t.err {
ResponseError::FileNotFound(reason) => {
*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
Expand Down

0 comments on commit 056aabf

Please sign in to comment.