comment code

This commit is contained in:
MedzikUser 2022-06-08 19:08:06 +02:00
parent d6f02632c5
commit 18b6cb21b1
No known key found for this signature in database
GPG Key ID: A5FAC1E185C112DB
16 changed files with 37 additions and 15 deletions

View File

@ -6,10 +6,10 @@ on:
- '**' - '**'
- '!website/**' - '!website/**'
# pull_request: # pull_request:
# paths: # paths:
# - '**' # - '**'
# - '!website/**' # - '!website/**'
workflow_dispatch: workflow_dispatch:

View File

@ -10,12 +10,14 @@ pub enum Error {
Io(std::io::Error), Io(std::io::Error),
} }
/// sqlx::Error
impl From<sqlx::Error> for Error { impl From<sqlx::Error> for Error {
fn from(err: sqlx::Error) -> Self { fn from(err: sqlx::Error) -> Self {
Error::SQLx(err) Error::SQLx(err)
} }
} }
/// std::io::Error
impl From<std::io::Error> for Error { impl From<std::io::Error> for Error {
fn from(err: std::io::Error) -> Self { fn from(err: std::io::Error) -> Self {
Error::Io(err) Error::Io(err)

View File

@ -43,7 +43,7 @@ impl Database {
Ok(self.conn.execute(query).await?) Ok(self.conn.execute(query).await?)
} }
/// Find user /// Search for a user
/// ```ignore,rust /// ```ignore,rust
/// use homedisk_database::{Database, User}; /// use homedisk_database::{Database, User};
/// ///
@ -52,7 +52,7 @@ impl Database {
/// db.find_user(&user.username, &user.password).await?; /// db.find_user(&user.username, &user.password).await?;
/// ``` /// ```
pub async fn find_user(&self, username: &str, password: &str) -> Result<User, Error> { pub async fn find_user(&self, username: &str, password: &str) -> Result<User, Error> {
debug!("Searching for user - {}", username); debug!("Searching for a user - {}", username);
let query = let query =
sqlx::query_as::<_, User>("SELECT * FROM user WHERE username = ? AND password = ?") sqlx::query_as::<_, User>("SELECT * FROM user WHERE username = ? AND password = ?")
@ -74,7 +74,7 @@ impl Database {
}) })
} }
/// Find user by UUID /// Search for a user by UUID
/// ```ignore,rust /// ```ignore,rust
/// use homedisk_database::{Database, User}; /// use homedisk_database::{Database, User};
/// ///
@ -111,10 +111,12 @@ mod tests {
use crate::{Database, User}; use crate::{Database, User};
/// Utils to open database in tests
async fn open_db() -> Database { async fn open_db() -> Database {
Database::open("sqlite::memory:").await.expect("open db") Database::open("sqlite::memory:").await.expect("open db")
} }
/// Utils to create a new user in tests
async fn new_user(db: &Database) { async fn new_user(db: &Database) {
// create user table // create user table
db.conn db.conn
@ -129,11 +131,13 @@ mod tests {
db.create_user(&user).await.expect("create user"); db.create_user(&user).await.expect("create user");
} }
/// Open database in memory
#[tokio::test] #[tokio::test]
async fn open_db_in_memory() { async fn open_db_in_memory() {
open_db().await; open_db().await;
} }
/// Create a new user
#[tokio::test] #[tokio::test]
async fn create_user() { async fn create_user() {
let db = open_db().await; let db = open_db().await;
@ -141,6 +145,7 @@ mod tests {
new_user(&db).await; new_user(&db).await;
} }
/// Search for a user
#[tokio::test] #[tokio::test]
async fn find_user() { async fn find_user() {
let db = open_db().await; let db = open_db().await;
@ -157,6 +162,7 @@ mod tests {
assert_eq!(res.password, user.password) assert_eq!(res.password, user.password)
} }
/// Search for a user with an invalid password to see if the user is returned (it shouldn't be)
#[tokio::test] #[tokio::test]
async fn find_user_wrong_password() { async fn find_user_wrong_password() {
let db = open_db().await; let db = open_db().await;
@ -173,6 +179,7 @@ mod tests {
assert_eq!(err.to_string(), "user not found") assert_eq!(err.to_string(), "user not found")
} }
/// Search for a user who does not exist
#[tokio::test] #[tokio::test]
async fn find_user_wrong_username() { async fn find_user_wrong_username() {
let db = open_db().await; let db = open_db().await;
@ -189,6 +196,7 @@ mod tests {
assert_eq!(err.to_string(), "user not found") assert_eq!(err.to_string(), "user not found")
} }
/// Search for a user by UUID
#[tokio::test] #[tokio::test]
async fn find_user_by_id() { async fn find_user_by_id() {
let db = open_db().await; let db = open_db().await;
@ -202,13 +210,14 @@ mod tests {
assert_eq!(res.password, user.password) assert_eq!(res.password, user.password)
} }
/// Search for a user by UUID who does not exist
#[tokio::test] #[tokio::test]
async fn find_user_wrong_id() { async fn find_user_wrong_id() {
let db = open_db().await; let db = open_db().await;
new_user(&db).await; new_user(&db).await;
let other_user = User::new("other_user", "secret@passphrase123!"); let other_user = User::new("other_user", "my secret passphrase");
let err = db.find_user_by_id(other_user.id).await.unwrap_err(); let err = db.find_user_by_id(other_user.id).await.unwrap_err();

View File

@ -8,6 +8,7 @@ use homedisk_types::{
use crate::middleware::{create_token, validate_json}; use crate::middleware::{create_token, validate_json};
/// Handle `/auth/login` requests
pub async fn handle( pub async fn handle(
Extension(db): Extension<Database>, Extension(db): Extension<Database>,
Extension(config): Extension<Config>, Extension(config): Extension<Config>,
@ -16,10 +17,13 @@ pub async fn handle(
// validate json request // validate json request
let request = validate_json::<Request>(request)?; let request = validate_json::<Request>(request)?;
// create `User` type
let user = User::new(&request.username, &request.password); let user = User::new(&request.username, &request.password);
// search for a user in database
let response = match db.find_user(&user.username, &user.password).await { let response = match db.find_user(&user.username, &user.password).await {
Ok(user) => { Ok(user) => {
// create user token
let token = create_token(&user, config.jwt.secret.as_bytes(), config.jwt.expires)?; let token = create_token(&user, config.jwt.secret.as_bytes(), config.jwt.expires)?;
Response::LoggedIn { Response::LoggedIn {

View File

@ -9,6 +9,7 @@ use homedisk_types::{
use crate::middleware::validate_jwt; use crate::middleware::validate_jwt;
/// Handle `/auth/whoami` requests
pub async fn handle( pub async fn handle(
db: Extension<Database>, db: Extension<Database>,
config: Extension<Config>, config: Extension<Config>,

View File

@ -13,6 +13,7 @@ use homedisk_types::{
use crate::fs::validate_path; use crate::fs::validate_path;
use crate::middleware::{find_user, validate_jwt}; use crate::middleware::{find_user, validate_jwt};
/// Handle `/fs/delete` requests
pub async fn handle( pub async fn handle(
Extension(db): Extension<Database>, Extension(db): Extension<Database>,
Extension(config): Extension<Config>, Extension(config): Extension<Config>,

View File

@ -31,6 +31,7 @@ fn dir_size(path: impl Into<PathBuf>) -> io::Result<u64> {
dir_size(fs::read_dir(path.into())?) dir_size(fs::read_dir(path.into())?)
} }
/// Handle `/fs/list` requests
pub async fn handle( pub async fn handle(
Extension(db): Extension<Database>, Extension(db): Extension<Database>,
Extension(config): Extension<Config>, Extension(config): Extension<Config>,

View File

@ -10,7 +10,7 @@ pub fn app() -> axum::Router {
axum::Router::new() axum::Router::new()
.route("/list", post(list::handle)) .route("/list", post(list::handle))
.route("/upload", post(upload::handle)) .route("/upload", post(upload::handle))
.route("/delete", delete(upload::handle)) .route("/delete", delete(delete::handle))
.route("/download", get(download::handle)) .route("/download", get(download::handle))
.route("/createdir", post(create_dir::handle)) .route("/createdir", post(create_dir::handle))
} }

View File

@ -10,6 +10,7 @@ use homedisk_types::config::types::Config;
use log::{debug, info}; use log::{debug, info};
use tower_http::cors::{AllowOrigin, CorsLayer}; use tower_http::cors::{AllowOrigin, CorsLayer};
/// Handle `/health-check` requests
async fn health_check() -> &'static str { async fn health_check() -> &'static str {
"I'm alive!" "I'm alive!"
} }

View File

@ -2,6 +2,7 @@ use homedisk_types::errors::{AuthError, ServerError};
use jsonwebtoken::TokenData; use jsonwebtoken::TokenData;
use rust_utilities::crypto::jsonwebtoken::{Claims, Token}; use rust_utilities::crypto::jsonwebtoken::{Claims, Token};
/// Validate user token
pub fn validate_jwt(secret: &[u8], token: &str) -> Result<TokenData<Claims>, ServerError> { pub fn validate_jwt(secret: &[u8], token: &str) -> Result<TokenData<Claims>, ServerError> {
match Token::decode(secret, token.to_string()) { match Token::decode(secret, token.to_string()) {
Ok(claims) => Ok(claims), Ok(claims) => Ok(claims),

View File

@ -2,6 +2,7 @@ use homedisk_database::{Database, User};
use homedisk_types::errors::{AuthError, ServerError}; use homedisk_types::errors::{AuthError, ServerError};
use rust_utilities::crypto::jsonwebtoken::{Claims, Token}; use rust_utilities::crypto::jsonwebtoken::{Claims, Token};
/// Create user token
pub fn create_token(user: &User, secret: &[u8], expires: i64) -> Result<String, ServerError> { pub fn create_token(user: &User, secret: &[u8], expires: i64) -> Result<String, ServerError> {
let token = Token::new(secret, Claims::new(user.id.clone(), expires)); let token = Token::new(secret, Claims::new(user.id.clone(), expires));
@ -11,6 +12,7 @@ pub fn create_token(user: &User, secret: &[u8], expires: i64) -> Result<String,
} }
} }
/// Search for a user
pub async fn find_user(db: Database, user_id: String) -> Result<User, ServerError> { pub async fn find_user(db: Database, user_id: String) -> Result<User, ServerError> {
match db.find_user_by_id(user_id).await { match db.find_user_by_id(user_id).await {
Ok(user) => Ok(user), Ok(user) => Ok(user),

View File

@ -1,6 +1,7 @@
use axum::{extract::rejection::JsonRejection, Json}; use axum::{extract::rejection::JsonRejection, Json};
use homedisk_types::errors::ServerError; use homedisk_types::errors::ServerError;
/// Validate json request
pub fn validate_json<Typ>( pub fn validate_json<Typ>(
payload: Result<Json<Typ>, JsonRejection>, payload: Result<Json<Typ>, JsonRejection>,
) -> Result<Json<Typ>, ServerError> { ) -> Result<Json<Typ>, ServerError> {

View File

@ -9,7 +9,7 @@ use super::types::Config;
impl Config { impl Config {
/// Parse configuration file /// Parse configuration file
pub fn parse() -> Result<Config> { pub fn parse() -> Result<Config> {
// configuration file path // config file path
let config_dir = option_return!(dirs::config_dir(), "get config dir")?; let config_dir = option_return!(dirs::config_dir(), "get config dir")?;
let config_path = format!("{}/homedisk/config.toml", config_dir.to_string_lossy()); let config_path = format!("{}/homedisk/config.toml", config_dir.to_string_lossy());

View File

@ -23,7 +23,7 @@ impl User {
// change username to lowercase // change username to lowercase
let username = username.to_lowercase(); let username = username.to_lowercase();
// create user UUID // generate a user UUID
let sha1_name = CryptographicHash::hash(Algorithm::SHA1, username.as_bytes()); let sha1_name = CryptographicHash::hash(Algorithm::SHA1, username.as_bytes());
let id = Uuid::new_v5(&Uuid::NAMESPACE_X500, &sha1_name).to_string(); let id = Uuid::new_v5(&Uuid::NAMESPACE_X500, &sha1_name).to_string();

View File

@ -30,7 +30,7 @@ pub enum ServerError {
#[error("failed to extract the request body")] #[error("failed to extract the request body")]
BytesRejection, BytesRejection,
#[error("unexcepted error")] #[error("unexpected error - {0}")]
Other(String), Other(String),
} }

View File

@ -1,8 +1,7 @@
pub mod auth; pub mod auth;
pub mod config; pub mod config;
pub mod errors;
pub mod macros;
#[cfg(feature = "database")] #[cfg(feature = "database")]
pub mod database; pub mod database;
pub mod errors;
pub mod fs; pub mod fs;
pub mod macros;