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
/target
# log files
# Logs files
*.log
# database
# SQLite
*.db
*.db-shm
*.db-wal
# ide config
# IDE configs
.idea
.vscode

View File

@ -1,5 +1,6 @@
# 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)
[![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)

View File

@ -1,7 +1,10 @@
# HTTP Server
[http]
# HTTP host
host = "0.0.0.0"
port = 8080
# HTTP port
port = 8080
# Cors domains
cors = [
"127.0.0.1:8000",
"localhost:8000",
@ -9,9 +12,12 @@ cors = [
# Json Web Token
[jwt]
secret = "secret key used to sign tokens" # secret used to sign tokens
expires = 24 # validity of token in hours
# JWT Secret string (used to sign tokens)
secret = "secret key used to sign tokens"
# Token expiration time in hours
expires = 24
# 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 {
/// Open SQLite Database file
/// Open a SQLite database
/// ```ignore,rust
/// use homedisk_database::Database;
///
@ -30,7 +30,7 @@ impl Database {
Ok(Self { conn })
}
/// Create new User
/// Create a new User
/// ```ignore,rust
/// 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)),
}
}
#[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 zeroize::{Zeroize, ZeroizeOnDrop};
/// `/auth/login` Request
#[derive(Debug, Serialize, Deserialize, Clone, Zeroize, ZeroizeOnDrop)]
pub struct Request {
/// Username
pub username: String,
/// Unencrypted user password
pub password: String,
}
/// `/auth/login` Response
#[derive(Debug, Serialize, Deserialize, Clone, Zeroize, ZeroizeOnDrop)]
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};
/// `/auth/whoami` Response
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct Response {
/// Logged user username
pub username: String,
}

View File

@ -14,11 +14,11 @@ impl Config {
/// let config = Config::parse().unwrap();
/// ```
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_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)?;
// parse config and return it

View File

@ -17,16 +17,16 @@ pub struct ConfigHTTP {
pub host: String,
/// Port HTTP Port
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>,
}
/// Json Web Token config
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ConfigJWT {
/// JWT Secret string
/// JWT Secret string (used to sign tokens)
pub secret: String,
/// Token expiers time in seconds
/// Token expiration time in hours
pub expires: i64,
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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