update code
This commit is contained in:
parent
18b6cb21b1
commit
ece96bb3af
|
@ -7,8 +7,6 @@
|
|||
|
||||
# database
|
||||
*.db
|
||||
|
||||
# why sqlx?
|
||||
*.db-shm
|
||||
*.db-wal
|
||||
|
||||
|
|
|
@ -1,26 +0,0 @@
|
|||
use std::fs::File;
|
||||
|
||||
use log::LevelFilter;
|
||||
use simplelog::{ColorChoice, CombinedLogger, Config, TermLogger, TerminalMode, WriteLogger};
|
||||
|
||||
pub fn init() -> anyhow::Result<()> {
|
||||
// init better_panic
|
||||
better_panic::install();
|
||||
|
||||
// init logger
|
||||
CombinedLogger::init(vec![
|
||||
TermLogger::new(
|
||||
LevelFilter::Debug,
|
||||
Config::default(),
|
||||
TerminalMode::Mixed,
|
||||
ColorChoice::Auto,
|
||||
),
|
||||
WriteLogger::new(
|
||||
LevelFilter::Info,
|
||||
Config::default(),
|
||||
File::create("logs.log").expect("create logs file"),
|
||||
),
|
||||
])?;
|
||||
|
||||
Ok(())
|
||||
}
|
|
@ -1,12 +1,14 @@
|
|||
mod init;
|
||||
|
||||
use homedisk_database::Database;
|
||||
use homedisk_server::run_http_server;
|
||||
use homedisk_types::config::types::Config;
|
||||
use homedisk_server::serve_http;
|
||||
use homedisk_types::config::Config;
|
||||
|
||||
/// Main function
|
||||
#[tokio::main]
|
||||
async fn main() -> anyhow::Result<()> {
|
||||
init::init()?;
|
||||
// init better_panic
|
||||
better_panic::install();
|
||||
// init logger
|
||||
init_logger()?;
|
||||
|
||||
// parse config
|
||||
let config = Config::parse()?;
|
||||
|
@ -22,6 +24,7 @@ async fn main() -> anyhow::Result<()> {
|
|||
.map(|e| e.parse().expect("parse CORS hosts"))
|
||||
.collect();
|
||||
|
||||
// format host ip and port
|
||||
let host = format!(
|
||||
"{host}:{port}",
|
||||
host = config.http.host,
|
||||
|
@ -29,7 +32,31 @@ async fn main() -> anyhow::Result<()> {
|
|||
);
|
||||
|
||||
// start http server
|
||||
run_http_server(host, origins, db, config).await?;
|
||||
serve_http(host, origins, db, config).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Init logger
|
||||
fn init_logger() -> anyhow::Result<()> {
|
||||
use std::fs::File;
|
||||
|
||||
use log::LevelFilter;
|
||||
use simplelog::{ColorChoice, CombinedLogger, Config, TermLogger, TerminalMode, WriteLogger};
|
||||
|
||||
CombinedLogger::init(vec![
|
||||
TermLogger::new(
|
||||
LevelFilter::Debug,
|
||||
Config::default(),
|
||||
TerminalMode::Mixed,
|
||||
ColorChoice::Auto,
|
||||
),
|
||||
WriteLogger::new(
|
||||
LevelFilter::Info,
|
||||
Config::default(),
|
||||
File::create("logs.log").expect("create logs file"),
|
||||
),
|
||||
])?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
mod error;
|
||||
mod sqlite;
|
||||
|
||||
pub use error::*;
|
||||
/// Imported from `homedisk_types::database::User`.
|
||||
pub use homedisk_types::database::User;
|
||||
/// Imported from `homedisk_types::errors::DatabaseError`.
|
||||
pub use homedisk_types::errors::DatabaseError as Error;
|
||||
pub use sqlite::*;
|
||||
|
|
|
@ -4,9 +4,10 @@ use sqlx::{sqlite::SqliteQueryResult, Executor, Row, SqlitePool};
|
|||
|
||||
use super::{Error, User};
|
||||
|
||||
/// SQL Database
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Database {
|
||||
/// Sqlite Connection Pool
|
||||
/// SQLite Connection Pool
|
||||
pub conn: SqlitePool,
|
||||
}
|
||||
|
||||
|
@ -15,7 +16,11 @@ impl Database {
|
|||
/// ```ignore,rust
|
||||
/// use homedisk_database::Database;
|
||||
///
|
||||
/// // open database in memory
|
||||
/// Database::open("sqlite::memory:").await?;
|
||||
///
|
||||
/// // open database from file
|
||||
/// Database::open("path/to/file.db").await?;
|
||||
/// ```
|
||||
pub async fn open(path: &str) -> Result<Self, Error> {
|
||||
debug!("Opening SQLite database");
|
||||
|
@ -29,7 +34,10 @@ impl Database {
|
|||
/// ```ignore,rust
|
||||
/// use homedisk_database::{Database, User};
|
||||
///
|
||||
/// // create `User` type
|
||||
/// let user = User::new("username", "password");
|
||||
///
|
||||
/// // create a user in database
|
||||
/// db.create_user(&user).await?;
|
||||
/// ```
|
||||
pub async fn create_user(&self, user: &User) -> Result<SqliteQueryResult, Error> {
|
||||
|
@ -47,24 +55,32 @@ impl Database {
|
|||
/// ```ignore,rust
|
||||
/// use homedisk_database::{Database, User};
|
||||
///
|
||||
/// // create `User` type
|
||||
/// let user = User::new("username", "password");
|
||||
///
|
||||
/// // search for a user in database
|
||||
/// db.find_user(&user.username, &user.password).await?;
|
||||
/// ```
|
||||
pub async fn find_user(&self, username: &str, password: &str) -> Result<User, Error> {
|
||||
debug!("Searching for a user - {}", username);
|
||||
|
||||
// create query request to database
|
||||
let query =
|
||||
sqlx::query_as::<_, User>("SELECT * FROM user WHERE username = ? AND password = ?")
|
||||
.bind(username)
|
||||
.bind(password);
|
||||
|
||||
// fetch query
|
||||
let mut stream = self.conn.fetch(query);
|
||||
|
||||
// get rows from query
|
||||
let row = stream.try_next().await?.ok_or(Error::UserNotFound)?;
|
||||
|
||||
// get `id` row
|
||||
let id = row.try_get("id")?;
|
||||
// get `username` row
|
||||
let username = row.try_get("username")?;
|
||||
// get `password` row
|
||||
let password = row.try_get("password")?;
|
||||
|
||||
Ok(User {
|
||||
|
@ -78,21 +94,29 @@ impl Database {
|
|||
/// ```ignore,rust
|
||||
/// use homedisk_database::{Database, User};
|
||||
///
|
||||
/// // create `User` type
|
||||
/// let user = User::new("username", "password");
|
||||
///
|
||||
/// // search for a user by UUID in database
|
||||
/// db.find_user_by_id(&user.id).await?;
|
||||
/// ```
|
||||
pub async fn find_user_by_id(&self, id: String) -> Result<User, Error> {
|
||||
debug!("Searching for a user by UUID - {}", id);
|
||||
|
||||
// create query request to database
|
||||
let query = sqlx::query_as::<_, User>("SELECT * FROM user WHERE id = ?").bind(id);
|
||||
|
||||
// fetch query
|
||||
let mut stream = self.conn.fetch(query);
|
||||
|
||||
// get rows from query
|
||||
let row = stream.try_next().await?.ok_or(Error::UserNotFound)?;
|
||||
|
||||
// get `id` row
|
||||
let id = row.try_get("id")?;
|
||||
// get `username` row
|
||||
let username = row.try_get("username")?;
|
||||
// get `password` row
|
||||
let password = row.try_get("password")?;
|
||||
|
||||
Ok(User {
|
||||
|
|
|
@ -2,7 +2,7 @@ use axum::{extract::rejection::JsonRejection, Extension, Json};
|
|||
use homedisk_database::{Database, Error, User};
|
||||
use homedisk_types::{
|
||||
auth::login::{Request, Response},
|
||||
config::types::Config,
|
||||
config::Config,
|
||||
errors::{AuthError, ServerError},
|
||||
};
|
||||
|
||||
|
|
|
@ -4,12 +4,13 @@ use axum::{extract::rejection::JsonRejection, Extension, Json};
|
|||
use homedisk_database::{Database, User};
|
||||
use homedisk_types::{
|
||||
auth::login::{Request, Response},
|
||||
config::types::Config,
|
||||
config::Config,
|
||||
errors::{AuthError, ServerError},
|
||||
};
|
||||
|
||||
use crate::middleware::{create_token, validate_json};
|
||||
|
||||
/// Handle `/auth/register` requests
|
||||
pub async fn handle(
|
||||
Extension(db): Extension<Database>,
|
||||
Extension(config): Extension<Config>,
|
||||
|
|
|
@ -3,7 +3,7 @@ use axum_auth::AuthBearer;
|
|||
use homedisk_database::{Database, Error};
|
||||
use homedisk_types::{
|
||||
auth::whoami::Response,
|
||||
config::types::Config,
|
||||
config::Config,
|
||||
errors::{AuthError, ServerError},
|
||||
};
|
||||
|
||||
|
@ -18,6 +18,7 @@ pub async fn handle(
|
|||
// validate user token
|
||||
let token = validate_jwt(config.jwt.secret.as_bytes(), &token)?;
|
||||
|
||||
// search for a user in database
|
||||
let response = match db.find_user_by_id(token.claims.sub).await {
|
||||
Ok(res) => Response {
|
||||
username: res.username,
|
||||
|
|
|
@ -1,29 +1,35 @@
|
|||
// HTTP Error
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum Error {
|
||||
// axum::Error
|
||||
#[error("axum error - {0}")]
|
||||
Axum(axum::Error),
|
||||
|
||||
// hyper::Error
|
||||
#[error("hyper error - {0}")]
|
||||
Hyper(hyper::Error),
|
||||
|
||||
// std::net::AddrParseError
|
||||
#[error("std::net::AddrParseError - {0}")]
|
||||
AddrParseError(std::net::AddrParseError),
|
||||
}
|
||||
|
||||
/// 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)
|
||||
|
|
|
@ -5,13 +5,14 @@ use axum_auth::AuthBearer;
|
|||
use homedisk_database::Database;
|
||||
use homedisk_types::fs::create_dir::{Request, Response};
|
||||
use homedisk_types::{
|
||||
config::types::Config,
|
||||
config::Config,
|
||||
errors::{FsError, ServerError},
|
||||
};
|
||||
|
||||
use crate::fs::validate_path;
|
||||
use crate::middleware::{find_user, validate_json, validate_jwt};
|
||||
|
||||
/// Handle `/fs/createdir` requests
|
||||
pub async fn handle(
|
||||
Extension(db): Extension<Database>,
|
||||
Extension(config): Extension<Config>,
|
||||
|
|
|
@ -5,7 +5,7 @@ use axum::Extension;
|
|||
use axum_auth::AuthBearer;
|
||||
use homedisk_database::Database;
|
||||
use homedisk_types::{
|
||||
config::types::Config,
|
||||
config::Config,
|
||||
errors::{FsError, ServerError},
|
||||
fs::delete::Request,
|
||||
};
|
||||
|
|
|
@ -6,10 +6,11 @@ use axum::Extension;
|
|||
use axum_auth::AuthBearer;
|
||||
use homedisk_database::Database;
|
||||
use homedisk_types::fs::upload::Pagination;
|
||||
use homedisk_types::{config::types::Config, errors::ServerError};
|
||||
use homedisk_types::{config::Config, errors::ServerError};
|
||||
|
||||
use crate::middleware::{find_user, validate_jwt};
|
||||
|
||||
/// Handle `/fs/download` requests
|
||||
pub async fn handle(
|
||||
Extension(db): Extension<Database>,
|
||||
Extension(config): Extension<Config>,
|
||||
|
|
|
@ -8,7 +8,7 @@ use byte_unit::Byte;
|
|||
use homedisk_database::Database;
|
||||
use homedisk_types::fs::list::DirInfo;
|
||||
use homedisk_types::{
|
||||
config::types::Config,
|
||||
config::Config,
|
||||
errors::{FsError, ServerError},
|
||||
fs::list::{FileInfo, Request, Response},
|
||||
};
|
||||
|
|
|
@ -7,7 +7,7 @@ use axum_auth::AuthBearer;
|
|||
use futures::TryStreamExt;
|
||||
use homedisk_database::Database;
|
||||
use homedisk_types::{
|
||||
config::types::Config,
|
||||
config::Config,
|
||||
errors::{FsError, ServerError},
|
||||
fs::upload::{Pagination, Response},
|
||||
};
|
||||
|
@ -15,6 +15,7 @@ use homedisk_types::{
|
|||
use crate::fs::validate_path;
|
||||
use crate::middleware::{find_user, validate_jwt};
|
||||
|
||||
/// Handle `/fs/upload` requests
|
||||
pub async fn handle(
|
||||
Extension(db): Extension<Database>,
|
||||
Extension(config): Extension<Config>,
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
pub mod auth;
|
||||
pub mod fs;
|
||||
pub mod middleware;
|
||||
|
||||
mod auth;
|
||||
mod error;
|
||||
mod fs;
|
||||
mod middleware;
|
||||
|
||||
use axum::{http::HeaderValue, routing::get, Extension, Router, Server};
|
||||
use homedisk_database::Database;
|
||||
use homedisk_types::config::types::Config;
|
||||
use homedisk_types::config::Config;
|
||||
use log::{debug, info};
|
||||
use tower_http::cors::{AllowOrigin, CorsLayer};
|
||||
|
||||
|
@ -15,7 +14,8 @@ async fn health_check() -> &'static str {
|
|||
"I'm alive!"
|
||||
}
|
||||
|
||||
pub async fn run_http_server(
|
||||
/// Start HTTP server
|
||||
pub async fn serve_http(
|
||||
host: String,
|
||||
origins: Vec<HeaderValue>,
|
||||
db: Database,
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
//! `/auth/login` Request and Response types
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use zeroize::{Zeroize, ZeroizeOnDrop};
|
||||
|
||||
|
|
|
@ -1,2 +1,4 @@
|
|||
//! HTTP `/auth/*` types for Request and Response
|
||||
|
||||
pub mod login;
|
||||
pub mod whoami;
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
//! `/auth/whoami` Response type
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
pub mod types;
|
||||
//! Types for configuration file
|
||||
|
||||
#[cfg(feature = "config")]
|
||||
pub mod toml;
|
||||
mod toml;
|
||||
mod types;
|
||||
|
||||
pub use types::*;
|
||||
|
|
|
@ -8,6 +8,11 @@ use super::types::Config;
|
|||
|
||||
impl Config {
|
||||
/// Parse configuration file
|
||||
/// ```
|
||||
/// use homedisk_types::config::Config;
|
||||
///
|
||||
/// let config = Config::parse().unwrap();
|
||||
/// ```
|
||||
pub fn parse() -> Result<Config> {
|
||||
// config file path
|
||||
let config_dir = option_return!(dirs::config_dir(), "get config dir")?;
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
//! Configuration file types
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// Config type
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct Config {
|
||||
pub http: ConfigHTTP,
|
||||
|
@ -7,6 +10,7 @@ pub struct Config {
|
|||
pub storage: ConfigStorage,
|
||||
}
|
||||
|
||||
/// HTTP config
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct ConfigHTTP {
|
||||
/// HTTP Host
|
||||
|
@ -17,6 +21,7 @@ pub struct ConfigHTTP {
|
|||
pub cors: Vec<String>,
|
||||
}
|
||||
|
||||
/// Json Web Token config
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct ConfigJWT {
|
||||
/// JWT Secret string
|
||||
|
@ -25,6 +30,7 @@ pub struct ConfigJWT {
|
|||
pub expires: i64,
|
||||
}
|
||||
|
||||
/// Storage config
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct ConfigStorage {
|
||||
/// Directory where user files will be stored
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
//! Typed for a database
|
||||
|
||||
mod user;
|
||||
|
||||
pub use user::*;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use rust_utilities::crypto::sha::{encode, Algorithm, CryptographicHash};
|
||||
use uuid::Uuid;
|
||||
|
||||
/// SQL `user` Table
|
||||
/// SQL user table
|
||||
#[derive(Debug, sqlx::FromRow)]
|
||||
pub struct User {
|
||||
pub id: String,
|
||||
|
@ -53,12 +53,14 @@ impl User {
|
|||
/// assert_eq!(dir, "/home/homedisk/medzik")
|
||||
/// ```
|
||||
pub fn user_dir(&self, storage: &str) -> String {
|
||||
// get a user storage path
|
||||
let path = format!(
|
||||
"{path}/{username}",
|
||||
path = storage,
|
||||
username = self.username,
|
||||
);
|
||||
|
||||
// return user storage path
|
||||
path
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// `/auth/*` Error
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, thiserror::Error)]
|
||||
pub enum Error {
|
||||
#[error("user not found")]
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
/// Database Error
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum Error {
|
||||
#[error("user not found")]
|
||||
UserNotFound,
|
||||
|
||||
/// sqlx::Error
|
||||
#[error("sqlx error - {0}")]
|
||||
SQLx(sqlx::Error),
|
||||
|
||||
/// std::io::Error
|
||||
#[error("std::io error - {0}")]
|
||||
Io(std::io::Error),
|
||||
StdIo(std::io::Error),
|
||||
}
|
||||
|
||||
/// sqlx::Error
|
||||
|
@ -20,6 +21,6 @@ impl From<sqlx::Error> for Error {
|
|||
/// std::io::Error
|
||||
impl From<std::io::Error> for Error {
|
||||
fn from(err: std::io::Error) -> Self {
|
||||
Error::Io(err)
|
||||
Error::StdIo(err)
|
||||
}
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// `/fs/*` Error
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, thiserror::Error)]
|
||||
pub enum Error {
|
||||
#[error("file already exists")]
|
||||
|
|
|
@ -1,79 +1,12 @@
|
|||
//! Error types
|
||||
|
||||
mod auth;
|
||||
#[cfg(feature = "database")]
|
||||
mod database;
|
||||
mod fs;
|
||||
mod server;
|
||||
|
||||
pub use auth::Error as AuthError;
|
||||
pub use database::Error as DatabaseError;
|
||||
pub use fs::Error as FsError;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, thiserror::Error)]
|
||||
#[serde(tag = "error", content = "error_message", rename_all = "kebab-case")]
|
||||
pub enum ServerError {
|
||||
#[error("auth error: {0}")]
|
||||
AuthError(#[from] AuthError),
|
||||
|
||||
#[error("fs error: {0}")]
|
||||
FsError(#[from] FsError),
|
||||
|
||||
#[error("too may requests, please slow down")]
|
||||
TooManyRequests,
|
||||
|
||||
#[error("missing json content type")]
|
||||
MissingJsonContentType,
|
||||
|
||||
#[error("error deserialize json")]
|
||||
JsonDataError,
|
||||
|
||||
#[error("json syntax error")]
|
||||
JsonSyntaxError,
|
||||
|
||||
#[error("failed to extract the request body")]
|
||||
BytesRejection,
|
||||
|
||||
#[error("unexpected error - {0}")]
|
||||
Other(String),
|
||||
}
|
||||
|
||||
#[cfg(feature = "axum")]
|
||||
impl axum::response::IntoResponse for ServerError {
|
||||
fn into_response(self) -> axum::response::Response {
|
||||
use axum::http::StatusCode;
|
||||
|
||||
let status = match self {
|
||||
Self::AuthError(ref err) => match err {
|
||||
AuthError::UserNotFound => StatusCode::BAD_REQUEST,
|
||||
AuthError::UserAlreadyExists => StatusCode::NOT_ACCEPTABLE,
|
||||
AuthError::UsernameTooShort => StatusCode::NOT_ACCEPTABLE,
|
||||
AuthError::UsernameTooLong => StatusCode::NOT_ACCEPTABLE,
|
||||
AuthError::PasswordTooShort => StatusCode::NOT_ACCEPTABLE,
|
||||
AuthError::TokenGenerate => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
AuthError::InvalidToken => StatusCode::BAD_REQUEST,
|
||||
AuthError::UnknownError(_) => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
},
|
||||
Self::FsError(ref err) => match err {
|
||||
FsError::FileAlreadyExists => StatusCode::BAD_REQUEST,
|
||||
FsError::FileDoesNotExist => StatusCode::BAD_REQUEST,
|
||||
FsError::MultipartError => StatusCode::BAD_REQUEST,
|
||||
FsError::CreateFile(_) => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
FsError::CreateDirectory(_) => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
FsError::DeleteFile(_) => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
FsError::DeleteDirectory(_) => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
FsError::WriteFile(_) => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
FsError::Base64(_) => StatusCode::BAD_REQUEST,
|
||||
FsError::ReadDir(_) => StatusCode::BAD_REQUEST,
|
||||
FsError::UnknownError(_) => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
},
|
||||
Self::TooManyRequests => StatusCode::TOO_MANY_REQUESTS,
|
||||
Self::MissingJsonContentType => StatusCode::BAD_REQUEST,
|
||||
Self::JsonDataError => StatusCode::BAD_REQUEST,
|
||||
Self::JsonSyntaxError => StatusCode::BAD_REQUEST,
|
||||
Self::BytesRejection => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
Self::Other(_) => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
};
|
||||
|
||||
let mut response = axum::Json(self).into_response();
|
||||
*response.status_mut() = status;
|
||||
|
||||
response
|
||||
}
|
||||
}
|
||||
pub use server::Error as ServerError;
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use super::{AuthError, FsError};
|
||||
|
||||
/// HTTP Server Error
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, thiserror::Error)]
|
||||
#[serde(tag = "error", content = "error_message", rename_all = "kebab-case")]
|
||||
pub enum Error {
|
||||
#[error("auth error: {0}")]
|
||||
AuthError(#[from] AuthError),
|
||||
|
||||
#[error("fs error: {0}")]
|
||||
FsError(#[from] FsError),
|
||||
|
||||
#[error("too may requests, please slow down")]
|
||||
TooManyRequests,
|
||||
|
||||
#[error("missing json content type")]
|
||||
MissingJsonContentType,
|
||||
|
||||
#[error("error deserialize json")]
|
||||
JsonDataError,
|
||||
|
||||
#[error("json syntax error")]
|
||||
JsonSyntaxError,
|
||||
|
||||
#[error("failed to extract the request body")]
|
||||
BytesRejection,
|
||||
|
||||
#[error("unexpected error - {0}")]
|
||||
Other(String),
|
||||
}
|
||||
|
||||
#[cfg(feature = "axum")]
|
||||
impl axum::response::IntoResponse for Error {
|
||||
fn into_response(self) -> axum::response::Response {
|
||||
use axum::http::StatusCode;
|
||||
|
||||
let status = match self {
|
||||
Self::AuthError(ref err) => match err {
|
||||
AuthError::UserNotFound => StatusCode::BAD_REQUEST,
|
||||
AuthError::UserAlreadyExists => StatusCode::NOT_ACCEPTABLE,
|
||||
AuthError::UsernameTooShort => StatusCode::NOT_ACCEPTABLE,
|
||||
AuthError::UsernameTooLong => StatusCode::NOT_ACCEPTABLE,
|
||||
AuthError::PasswordTooShort => StatusCode::NOT_ACCEPTABLE,
|
||||
AuthError::TokenGenerate => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
AuthError::InvalidToken => StatusCode::BAD_REQUEST,
|
||||
AuthError::UnknownError(_) => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
},
|
||||
Self::FsError(ref err) => match err {
|
||||
FsError::FileAlreadyExists => StatusCode::BAD_REQUEST,
|
||||
FsError::FileDoesNotExist => StatusCode::BAD_REQUEST,
|
||||
FsError::MultipartError => StatusCode::BAD_REQUEST,
|
||||
FsError::CreateFile(_) => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
FsError::CreateDirectory(_) => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
FsError::DeleteFile(_) => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
FsError::DeleteDirectory(_) => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
FsError::WriteFile(_) => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
FsError::Base64(_) => StatusCode::BAD_REQUEST,
|
||||
FsError::ReadDir(_) => StatusCode::BAD_REQUEST,
|
||||
FsError::UnknownError(_) => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
},
|
||||
Self::TooManyRequests => StatusCode::TOO_MANY_REQUESTS,
|
||||
Self::MissingJsonContentType => StatusCode::BAD_REQUEST,
|
||||
Self::JsonDataError => StatusCode::BAD_REQUEST,
|
||||
Self::JsonSyntaxError => StatusCode::BAD_REQUEST,
|
||||
Self::BytesRejection => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
Self::Other(_) => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
};
|
||||
|
||||
let mut response = axum::Json(self).into_response();
|
||||
*response.status_mut() = status;
|
||||
|
||||
response
|
||||
}
|
||||
}
|
|
@ -1,3 +1,5 @@
|
|||
//! HTTP `/fs/*` types for Request and Response
|
||||
|
||||
pub mod create_dir;
|
||||
pub mod delete;
|
||||
pub mod download;
|
||||
|
|
|
@ -4,4 +4,5 @@ pub mod config;
|
|||
pub mod database;
|
||||
pub mod errors;
|
||||
pub mod fs;
|
||||
pub mod macros;
|
||||
|
||||
mod macros;
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
/// Return value or error (if None) from Some(T)
|
||||
#[macro_export]
|
||||
macro_rules! option_return {
|
||||
($variable:expr,$err_desc:expr) => {
|
||||
|
|
Loading…
Reference in New Issue