This commit is contained in:
MedzikUser 2022-06-09 00:02:20 +02:00
parent 44e6caf093
commit 6b0ce6f057
No known key found for this signature in database
GPG Key ID: A5FAC1E185C112DB
19 changed files with 103 additions and 34 deletions

View File

@ -1,15 +0,0 @@
# EditorConfig is awesome: https://EditorConfig.org
# top-most EditorConfig file
root = true
[*]
indent_style = space
indent_size = 4
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = false
[*.yml]
indent_size = 2

6
.gitignore vendored
View File

@ -2,14 +2,14 @@
# will have compiled files and executables # will have compiled files and executables
/target /target
# log files # Logs files
*.log *.log
# database # SQLite
*.db *.db
*.db-shm *.db-shm
*.db-wal *.db-wal
# ide config # IDE configs
.idea .idea
.vscode .vscode

View File

@ -1,5 +1,6 @@
# HomeDisk cloud server # HomeDisk cloud server
[![docs](https://img.shields.io/badge/docs-rust_docs-fff)](https://homedisk-doc.vercel.app/cloud/)
[![license badge](https://img.shields.io/github/license/MedzikUser/HomeDisk)](https://github.com/MedzikUser/HomeDisk) [![license badge](https://img.shields.io/github/license/MedzikUser/HomeDisk)](https://github.com/MedzikUser/HomeDisk)
[![code size badge](https://img.shields.io/github/languages/code-size/MedzikUser/HomeDisk)](https://github.com/MedzikUser/HomeDisk) [![code size badge](https://img.shields.io/github/languages/code-size/MedzikUser/HomeDisk)](https://github.com/MedzikUser/HomeDisk)
[![total lines badge](https://img.shields.io/tokei/lines/github/MedzikUser/HomeDisk)](https://github.com/MedzikUser/HomeDisk) [![total lines badge](https://img.shields.io/tokei/lines/github/MedzikUser/HomeDisk)](https://github.com/MedzikUser/HomeDisk)

View File

@ -1,7 +1,10 @@
# HTTP Server # HTTP Server
[http] [http]
# HTTP host
host = "0.0.0.0" host = "0.0.0.0"
port = 8080 # HTTP port
port = 8080
# Cors domains
cors = [ cors = [
"127.0.0.1:8000", "127.0.0.1:8000",
"localhost:8000", "localhost:8000",
@ -9,9 +12,12 @@ cors = [
# Json Web Token # Json Web Token
[jwt] [jwt]
secret = "secret key used to sign tokens" # secret used to sign tokens # JWT Secret string (used to sign tokens)
expires = 24 # validity of token in hours secret = "secret key used to sign tokens"
# Token expiration time in hours
expires = 24
# Storage # Storage
[storage] [storage]
path = "/home/homedisk" # the folder where the user files will be stored # Directory where user files will be stored
path = "/home/homedisk"

View File

@ -12,7 +12,7 @@ pub struct Database {
} }
impl Database { impl Database {
/// Open SQLite Database file /// Open a SQLite database
/// ```ignore,rust /// ```ignore,rust
/// use homedisk_database::Database; /// use homedisk_database::Database;
/// ///
@ -30,7 +30,7 @@ impl Database {
Ok(Self { conn }) Ok(Self { conn })
} }
/// Create new User /// Create a new User
/// ```ignore,rust /// ```ignore,rust
/// use homedisk_database::{Database, User}; /// use homedisk_database::{Database, User};
/// ///

View File

@ -9,3 +9,22 @@ pub fn validate_jwt(secret: &[u8], token: &str) -> Result<TokenData<Claims>, Ser
Err(_) => Err(ServerError::AuthError(AuthError::InvalidToken)), Err(_) => Err(ServerError::AuthError(AuthError::InvalidToken)),
} }
} }
#[cfg(test)]
mod tests {
use homedisk_database::User;
use crate::middleware::create_token;
use super::validate_jwt;
#[test]
fn validate_token() {
let secret = b"secret";
let user = User::new("username", "password");
let token = create_token(&user, secret, 1).unwrap();
validate_jwt(secret, &token).unwrap();
}
}

View File

@ -26,3 +26,18 @@ pub async fn find_user(db: Database, user_id: String) -> Result<User, ServerErro
}, },
} }
} }
#[cfg(test)]
mod tests {
use homedisk_database::User;
use super::create_token;
#[test]
fn test_create_token() {
let secret = b"secret";
let user = User::new("username", "password");
create_token(&user, secret, 1).unwrap();
}
}

View File

@ -3,13 +3,20 @@
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use zeroize::{Zeroize, ZeroizeOnDrop}; use zeroize::{Zeroize, ZeroizeOnDrop};
/// `/auth/login` Request
#[derive(Debug, Serialize, Deserialize, Clone, Zeroize, ZeroizeOnDrop)] #[derive(Debug, Serialize, Deserialize, Clone, Zeroize, ZeroizeOnDrop)]
pub struct Request { pub struct Request {
/// Username
pub username: String, pub username: String,
/// Unencrypted user password
pub password: String, pub password: String,
} }
/// `/auth/login` Response
#[derive(Debug, Serialize, Deserialize, Clone, Zeroize, ZeroizeOnDrop)] #[derive(Debug, Serialize, Deserialize, Clone, Zeroize, ZeroizeOnDrop)]
pub enum Response { pub enum Response {
LoggedIn { access_token: String }, LoggedIn {
/// Token of a user
access_token: String,
},
} }

View File

@ -2,7 +2,9 @@
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
/// `/auth/whoami` Response
#[derive(Debug, Serialize, Deserialize, Clone)] #[derive(Debug, Serialize, Deserialize, Clone)]
pub struct Response { pub struct Response {
/// Logged user username
pub username: String, pub username: String,
} }

View File

@ -14,11 +14,11 @@ impl Config {
/// let config = Config::parse().unwrap(); /// let config = Config::parse().unwrap();
/// ``` /// ```
pub fn parse() -> Result<Config> { pub fn parse() -> Result<Config> {
// config file path // get file path of config file
let config_dir = option_return!(dirs::config_dir(), "find config dir")?; let config_dir = option_return!(dirs::config_dir(), "find 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());
// read file // read file content to string
let config = fs::read_to_string(config_path)?; let config = fs::read_to_string(config_path)?;
// parse config and return it // parse config and return it

View File

@ -17,16 +17,16 @@ pub struct ConfigHTTP {
pub host: String, pub host: String,
/// Port HTTP Port /// Port HTTP Port
pub port: u16, pub port: u16,
/// CORS Domaing (e.g ["site1.example.com", "site2.example.com"]) /// CORS Domains (e.g ["site1.example.com", "site2.example.com"])
pub cors: Vec<String>, pub cors: Vec<String>,
} }
/// Json Web Token config /// Json Web Token config
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ConfigJWT { pub struct ConfigJWT {
/// JWT Secret string /// JWT Secret string (used to sign tokens)
pub secret: String, pub secret: String,
/// Token expiers time in seconds /// Token expiration time in hours
pub expires: i64, pub expires: i64,
} }

View File

@ -4,8 +4,11 @@ use uuid::Uuid;
/// SQL user table /// SQL user table
#[derive(Debug, sqlx::FromRow)] #[derive(Debug, sqlx::FromRow)]
pub struct User { pub struct User {
/// UUID of the user
pub id: String, pub id: String,
/// Username
pub username: String, pub username: String,
/// Encryped user password
pub password: String, pub password: String,
} }
@ -33,6 +36,7 @@ impl User {
password.as_bytes(), password.as_bytes(),
)); ));
// return `User`
Self { Self {
id, id,
username, username,

View File

@ -33,6 +33,6 @@ pub enum Error {
#[error("read dir - {0}")] #[error("read dir - {0}")]
ReadDir(String), ReadDir(String),
#[error("unknown error")] #[error("unknown error - {0}")]
UnknownError(String), UnknownError(String),
} }

View File

@ -6,10 +6,10 @@ use super::{AuthError, FsError};
#[derive(Debug, Clone, Serialize, Deserialize, thiserror::Error)] #[derive(Debug, Clone, Serialize, Deserialize, thiserror::Error)]
#[serde(tag = "error", content = "error_message", rename_all = "kebab-case")] #[serde(tag = "error", content = "error_message", rename_all = "kebab-case")]
pub enum Error { pub enum Error {
#[error("auth error: {0}")] #[error("auth error - {0}")]
AuthError(#[from] AuthError), AuthError(#[from] AuthError),
#[error("fs error: {0}")] #[error("fs error - {0}")]
FsError(#[from] FsError), FsError(#[from] FsError),
#[error("too may requests, please slow down")] #[error("too may requests, please slow down")]
@ -27,7 +27,7 @@ pub enum Error {
#[error("failed to extract the request body")] #[error("failed to extract the request body")]
BytesRejection, BytesRejection,
#[error("unexpected error - {0}")] #[error("unknown error - {0}")]
Other(String), Other(String),
} }

View File

@ -1,11 +1,16 @@
//! HTTP `/fs/createdir` Request and Response types
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
/// `/fs/createdir` Request
#[derive(Debug, Serialize, Deserialize, Clone)] #[derive(Debug, Serialize, Deserialize, Clone)]
pub struct Request { pub struct Request {
pub path: String, pub path: String,
} }
/// `/fs/createdir` Reponse
#[derive(Debug, Serialize, Deserialize, Clone)] #[derive(Debug, Serialize, Deserialize, Clone)]
pub struct Response { pub struct Response {
/// Directory created?
pub created: bool, pub created: bool,
} }

View File

@ -1,6 +1,10 @@
//! HTTP `/fs/delete` Request type
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
/// `/fs/delete` Request
#[derive(Debug, Serialize, Deserialize, Clone)] #[derive(Debug, Serialize, Deserialize, Clone)]
pub struct Request { pub struct Request {
/// Path of file/directory to delete
pub path: String, pub path: String,
} }

View File

@ -1,6 +1,10 @@
//! HTTP `/fs/download` Request type
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
/// `/fs/download` Request
#[derive(Debug, Serialize, Deserialize, Clone)] #[derive(Debug, Serialize, Deserialize, Clone)]
pub struct Request { pub struct Request {
/// Path of file to download
pub path: String, pub path: String,
} }

View File

@ -1,25 +1,36 @@
//! HTTP `/fs/list` Request, Response, FileInfo and DirInfo types
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
/// `/fs/list` Request
#[derive(Debug, Serialize, Deserialize, Clone)] #[derive(Debug, Serialize, Deserialize, Clone)]
pub struct Request { pub struct Request {
pub path: String, pub path: String,
} }
/// `/fs/list` Response
#[derive(Debug, Serialize, Deserialize, Clone)] #[derive(Debug, Serialize, Deserialize, Clone)]
pub struct Response { pub struct Response {
pub files: Vec<FileInfo>, pub files: Vec<FileInfo>,
pub dirs: Vec<DirInfo>, pub dirs: Vec<DirInfo>,
} }
/// Info about a file
#[derive(Debug, Serialize, Deserialize, Clone)] #[derive(Debug, Serialize, Deserialize, Clone)]
pub struct FileInfo { pub struct FileInfo {
/// File name
pub name: String, pub name: String,
/// File size
pub size: String, pub size: String,
/// Latest modification of this file
pub modified: String, pub modified: String,
} }
/// Info about a directory
#[derive(Debug, Serialize, Deserialize, Clone)] #[derive(Debug, Serialize, Deserialize, Clone)]
pub struct DirInfo { pub struct DirInfo {
/// Directory name
pub name: String, pub name: String,
/// Directory size (size of all files in directory)
pub size: String, pub size: String,
} }

View File

@ -1,11 +1,17 @@
//! HTTP `/fs/upload` Request and Response types
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
/// `/fs/upload` Queries
#[derive(Debug, Serialize, Deserialize, Clone)] #[derive(Debug, Serialize, Deserialize, Clone)]
pub struct Pagination { pub struct Pagination {
/// Path where the file will be uploaded
pub path: String, pub path: String,
} }
/// `/fs/upload` Response
#[derive(Debug, Serialize, Deserialize, Clone)] #[derive(Debug, Serialize, Deserialize, Clone)]
pub struct Response { pub struct Response {
/// The file has been uploaded?
pub uploaded: bool, pub uploaded: bool,
} }