chore(server): small changes

This commit is contained in:
MedzikUser 2022-07-25 23:02:25 +02:00
parent 1d36af0bcb
commit ec04360f6c
No known key found for this signature in database
GPG Key ID: A5FAC1E185C112DB
16 changed files with 74 additions and 66 deletions

View File

@ -6,8 +6,8 @@
//! [code-size]: https://img.shields.io/github/languages/code-size/MedzikUser/HomeDisk?style=for-the-badge&color=c8df52&logo=github
//! [ci]: https://img.shields.io/github/workflow/status/MedzikUser/HomeDisk/Rust/main?style=for-the-badge
//!
//! [home-screenshot]: https://cdn.medzik.xyz/x4Glw7w.png
//! [login-screenshot]: https://cdn.medzik.xyz/KpwY4nb.png
//! [home-screenshot]: https://i.imgur.com/x4Glw7w.png
//! [login-screenshot]: https://i.imgur.com/KpwY4nb.png
//!
//! [![github]](https://github.com/MedzikUser/HomeDisk)
//! [![docs-rs]](https://homedisk-doc.vercel.app)

View File

@ -1,10 +1,10 @@
use tracing::level_filters::LevelFilter;
/// Max Logger Level on debug build
// Max Logger Level on debug build
#[cfg(debug_assertions)]
const MAX_LEVEL: LevelFilter = LevelFilter::DEBUG;
/// Max Logger Level on release build
// Max Logger Level on release build
#[cfg(not(debug_assertions))]
const MAX_LEVEL: LevelFilter = LevelFilter::INFO;

View File

@ -14,7 +14,7 @@ pub async fn handle(
request: Result<Json<Request>, JsonRejection>,
) -> Result<Json<Response>, ServerError> {
// validate json request
let request = validate_json::<Request>(request)?;
let request = validate_json(request)?;
// create `User` type
let user = User::new(&request.username, &request.password);
@ -42,5 +42,6 @@ pub async fn handle(
},
};
// send response
Ok(Json(response))
}

View File

@ -2,7 +2,6 @@ mod login;
mod register;
mod whoami;
/// Handle `/api/auth/*` requests
pub fn app() -> axum::Router {
use axum::routing::{get, post};

View File

@ -16,7 +16,7 @@ pub async fn handle(
request: Result<Json<Request>, JsonRejection>,
) -> Result<Json<Response>, ServerError> {
// validate json request
let request = validate_json::<Request>(request)?;
let request = validate_json(request)?;
// username must contain at least 4 characters
if request.username.len() < 4 {
@ -33,10 +33,12 @@ pub async fn handle(
return Err(ServerError::AuthError(AuthError::PasswordTooShort));
}
// create `User` type and hash password
let user = User::new(&request.username, &request.password);
// create user in the database
let response = match db.create_user(&user).await {
Ok(_) => {
Ok(_result) => {
let token = create_token(&user, config.jwt.secret.as_bytes(), config.jwt.expires)?;
Response::LoggedIn {
@ -56,14 +58,10 @@ pub async fn handle(
},
};
// create directory for user files
let user_dir = format!(
"{storage}/{username}",
storage = config.storage.path,
username = user.username,
);
fs::create_dir_all(&user_dir)
// create directory for the user files
fs::create_dir_all(&format!("{}/{}", config.storage.path, user.username,))
.map_err(|e| ServerError::FsError(FsError::CreateDirectory(e.to_string())))?;
// send response
Ok(Json(response))
}

View File

@ -19,8 +19,8 @@ pub async fn handle(
// search for a user in database
let response = match db.find_user_by_id(&token.claims.sub).await {
Ok(res) => Response {
username: res.username,
Ok(user) => Response {
username: user.username,
},
// error while searching for a user
@ -32,5 +32,6 @@ pub async fn handle(
},
};
// send response
Ok(Json(response))
}

View File

@ -15,21 +15,18 @@ pub enum Error {
/// Custom Result
pub type Result<T> = std::result::Result<T, Error>;
/// axum::Error
impl From<axum::Error> for Error {
fn from(err: axum::Error) -> Self {
Error::Axum(err)
}
}
/// hyper::Error
impl From<hyper::Error> for Error {
fn from(err: hyper::Error) -> Self {
Error::Hyper(err)
}
}
/// std::net::AddrParseError
impl From<std::net::AddrParseError> for Error {
fn from(err: std::net::AddrParseError) -> Self {
Error::AddrParseError(err)

View File

@ -9,9 +9,7 @@ use homedisk_types::{
fs::create_dir::Request,
};
use crate::middleware::{find_user, validate_json, validate_jwt};
use super::validate_path;
use crate::middleware::{find_user, validate_json, validate_jwt, validate_path};
pub async fn handle(
Extension(db): Extension<Database>,
@ -20,7 +18,7 @@ pub async fn handle(
request: Result<Json<Request>, JsonRejection>,
) -> Result<(), ServerError> {
// validate json request
let Json(request) = validate_json::<Request>(request)?;
let Json(request) = validate_json(request)?;
// validate user token
let token = validate_jwt(config.jwt.secret.as_bytes(), &token)?;
@ -42,6 +40,6 @@ pub async fn handle(
fs::create_dir_all(path)
.map_err(|err| ServerError::FsError(FsError::CreateDirectory(err.to_string())))?;
// send aan empty Response
// send an empty response
Ok(())
}

View File

@ -9,9 +9,7 @@ use homedisk_types::{
fs::delete::Request,
};
use crate::middleware::{find_user, validate_jwt};
use super::validate_path;
use crate::middleware::{find_user, validate_jwt, validate_path};
pub async fn handle(
Extension(db): Extension<Database>,
@ -53,6 +51,6 @@ pub async fn handle(
.map_err(|err| ServerError::FsError(FsError::DeleteDirectory(err.to_string())))?;
}
// send an empty Response
// send an empty response
Ok(())
}

View File

@ -7,9 +7,7 @@ use homedisk_types::errors::FsError;
use homedisk_types::fs::upload::Pagination;
use homedisk_types::{config::Config, errors::ServerError};
use crate::middleware::{find_user, validate_jwt};
use super::validate_path;
use crate::middleware::{find_user, validate_jwt, validate_path};
pub async fn handle(
Extension(db): Extension<Database>,
@ -37,6 +35,6 @@ pub async fn handle(
let content =
fs::read(path).map_err(|err| ServerError::FsError(FsError::ReadFile(err.to_string())))?;
// send file content in Response
// send file content in response
Ok(content)
}

View File

@ -11,9 +11,7 @@ use homedisk_types::{
fs::list::{DirInfo, FileInfo, Request, Response},
};
use crate::middleware::{find_user, validate_json, validate_jwt};
use super::validate_path;
use crate::middleware::{find_user, validate_json, validate_jwt, validate_path};
/// Get directory size on disk (size of all files in directory).
fn dir_size(path: impl Into<PathBuf>) -> io::Result<u64> {
@ -94,6 +92,8 @@ pub async fn handle(
.get_appropriate_unit(true)
.to_string();
// TODO: fix modification time
// check how long it has been since the file was last modified
let elapsed = metadata.modified().unwrap().elapsed().unwrap();
@ -123,5 +123,6 @@ pub async fn handle(
}
}
// send response
Ok(Json(Response { files, dirs }))
}

View File

@ -4,7 +4,6 @@ mod download;
mod list;
mod upload;
/// Handle `/api/fs/*` requests
pub fn app() -> axum::Router {
use axum::routing::{delete, get, post};
@ -15,25 +14,3 @@ pub fn app() -> axum::Router {
.route("/download", get(download::handle))
.route("/createdir", post(create_dir::handle))
}
pub fn validate_path(path: &str) -> Result<(), homedisk_types::errors::ServerError> {
use homedisk_types::errors::{FsError, ServerError};
// `path` can't contain `..`
// to prevent attack attempts because by using a `..` you can access the previous folder
if path.contains("..") {
return Err(ServerError::FsError(FsError::ReadDirectory(
"the `path` must not contain `..`".to_string(),
)));
}
// `path` can't contain `~`
// to prevent attack attempts because `~` can get up a directory on `$HOME`
if path.contains('~') {
return Err(ServerError::FsError(FsError::ReadDirectory(
"the `path` must not contain `~`".to_string(),
)));
}
Ok(())
}

View File

@ -14,9 +14,7 @@ use homedisk_types::{
fs::upload::Pagination,
};
use crate::middleware::{find_user, validate_jwt};
use super::validate_path;
use crate::middleware::{find_user, validate_jwt, validate_path};
pub async fn handle(
Extension(db): Extension<Database>,
@ -76,6 +74,6 @@ pub async fn handle(
.await
.map_err(|err| ServerError::FsError(FsError::WriteFile(err.to_string())))?;
// send an empty Response
// send an empty response
Ok(())
}

View File

@ -1,7 +1,9 @@
mod auth;
mod jwt;
mod validate_json;
mod validate_path;
pub use auth::*;
pub use jwt::*;
pub use validate_json::*;
pub use validate_path::*;

View File

@ -2,9 +2,9 @@ use axum::{extract::rejection::JsonRejection, Json};
use homedisk_types::errors::ServerError;
/// Validate json request
pub fn validate_json<Typ>(
payload: Result<Json<Typ>, JsonRejection>,
) -> Result<Json<Typ>, ServerError> {
pub fn validate_json<T>(
payload: Result<Json<T>, JsonRejection>,
) -> Result<Json<T>, ServerError> {
match payload {
// if success return payload
Ok(payload) => Ok(payload),

View File

@ -0,0 +1,40 @@
use homedisk_types::errors::{FsError, ServerError};
/// Validate path param provided in the request
pub fn validate_path(path: &str) -> Result<(), ServerError> {
// `path` can't contain `..`
// to prevent attack attempts because by using a `..` you can access the previous folder
if path.contains("..") {
return Err(ServerError::FsError(FsError::ReadDirectory(
"the `path` can't contain `..`".to_string(),
)));
}
// `path` can't contain `~`
// to prevent attack attempts because `~` can get up a directory on `$HOME`
if path.contains('~') {
return Err(ServerError::FsError(FsError::ReadDirectory(
"the `path` can't not contain `~`".to_string(),
)));
}
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_validate_path() {
// Successfully
assert!(validate_path("Directory/path/to/test.png").is_ok());
assert!(validate_path("/test.png").is_ok()); // `/` doesn't point to the system root
assert!(validate_path("./test.png").is_ok());
// Errors
assert!(validate_path("../../test.png").is_err());
assert!(validate_path("../test.png").is_err());
assert!(validate_path("~/test.png").is_err());
}
}