mirror of
https://github.com/MedzikUser/HomeDisk.git
synced 2024-08-14 21:46:53 +00:00
chore: use crate rust_utilities
This commit is contained in:
parent
dc28e67b5c
commit
bf5422b47f
16 changed files with 62 additions and 326 deletions
21
Cargo.lock
generated
21
Cargo.lock
generated
|
@ -529,6 +529,7 @@ dependencies = [
|
||||||
"homedisk-utils",
|
"homedisk-utils",
|
||||||
"hyper",
|
"hyper",
|
||||||
"log",
|
"log",
|
||||||
|
"rust_utilities",
|
||||||
"serde",
|
"serde",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"tower-http",
|
"tower-http",
|
||||||
|
@ -540,9 +541,7 @@ version = "0.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"axum",
|
"axum",
|
||||||
"chrono",
|
|
||||||
"dirs",
|
"dirs",
|
||||||
"jsonwebtoken",
|
|
||||||
"serde",
|
"serde",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"toml",
|
"toml",
|
||||||
|
@ -555,11 +554,9 @@ name = "homedisk-utils"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"hex",
|
|
||||||
"log",
|
"log",
|
||||||
|
"rust_utilities",
|
||||||
"serde",
|
"serde",
|
||||||
"sha-1",
|
|
||||||
"sha2",
|
|
||||||
"sqlx",
|
"sqlx",
|
||||||
"tokio",
|
"tokio",
|
||||||
"uuid",
|
"uuid",
|
||||||
|
@ -1072,6 +1069,20 @@ dependencies = [
|
||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rust_utilities"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8524c76496ed3097b6d24d7cb3b435cc8a84cbded6da7153942f6daa3ade9da7"
|
||||||
|
dependencies = [
|
||||||
|
"chrono",
|
||||||
|
"hex",
|
||||||
|
"jsonwebtoken",
|
||||||
|
"serde",
|
||||||
|
"sha-1",
|
||||||
|
"sha2",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustc-demangle"
|
name = "rustc-demangle"
|
||||||
version = "0.1.21"
|
version = "0.1.21"
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
# HTTP Server
|
||||||
[http]
|
[http]
|
||||||
host = "0.0.0.0"
|
host = "0.0.0.0"
|
||||||
port = 8080
|
port = 8080
|
||||||
|
@ -6,5 +7,7 @@ cors = [
|
||||||
"localhost:8000",
|
"localhost:8000",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
# Json Web Token
|
||||||
[jwt]
|
[jwt]
|
||||||
secret = "secret key used to sign tokens"
|
secret = "secret key used to sign tokens" # secret used to sign tokens
|
||||||
|
expires = 24 # validity of token in hours
|
||||||
|
|
|
@ -20,10 +20,14 @@ features = ["full"]
|
||||||
version = "1.0.136"
|
version = "1.0.136"
|
||||||
features = ["derive"]
|
features = ["derive"]
|
||||||
|
|
||||||
|
[dependencies.rust_utilities]
|
||||||
|
version = "0.2.0"
|
||||||
|
features = ["jsonwebtoken"]
|
||||||
|
|
||||||
[dependencies.homedisk-utils]
|
[dependencies.homedisk-utils]
|
||||||
path = "../utils"
|
path = "../utils"
|
||||||
features = ["full"]
|
features = ["database"]
|
||||||
|
|
||||||
[dependencies.homedisk-types]
|
[dependencies.homedisk-types]
|
||||||
path = "../types"
|
path = "../types"
|
||||||
features = ["axum", "token"]
|
features = ["axum"]
|
||||||
|
|
|
@ -3,9 +3,9 @@ use homedisk_types::{
|
||||||
auth::login::{Request, Response},
|
auth::login::{Request, Response},
|
||||||
config::types::Config,
|
config::types::Config,
|
||||||
errors::{AuthError, ServerError},
|
errors::{AuthError, ServerError},
|
||||||
token::{Claims, Token},
|
|
||||||
};
|
};
|
||||||
use homedisk_utils::database::{Database, User};
|
use homedisk_utils::database::{Database, Error, User};
|
||||||
|
use rust_utilities::crypto::jsonwebtoken::{Claims, Token};
|
||||||
|
|
||||||
pub async fn handle(
|
pub async fn handle(
|
||||||
db: Extension<Database>,
|
db: Extension<Database>,
|
||||||
|
@ -16,24 +16,25 @@ pub async fn handle(
|
||||||
|
|
||||||
let response = match db.find_user(&user.username, &user.password).await {
|
let response = match db.find_user(&user.username, &user.password).await {
|
||||||
Ok(res) => {
|
Ok(res) => {
|
||||||
let token = Token::new(config.jwt.secret.as_bytes(), Claims::new(res.id)).unwrap();
|
let token = Token::new(
|
||||||
|
config.jwt.secret.as_bytes(),
|
||||||
|
Claims::new(res.id, config.jwt.expires),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
Response::LoggedIn {
|
Response::LoggedIn {
|
||||||
access_token: token.encoded,
|
access_token: token.encoded,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Err(e) => {
|
Err(err) => match err {
|
||||||
use homedisk_utils::database::Error;
|
|
||||||
match e {
|
|
||||||
Error::UserNotFound => return Err(ServerError::AuthError(AuthError::UserNotFound)),
|
Error::UserNotFound => return Err(ServerError::AuthError(AuthError::UserNotFound)),
|
||||||
_ => {
|
_ => {
|
||||||
return Err(ServerError::AuthError(AuthError::UnknowError(
|
return Err(ServerError::AuthError(AuthError::UnknowError(
|
||||||
e.to_string(),
|
err.to_string(),
|
||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(Json(response))
|
Ok(Json(response))
|
||||||
|
|
|
@ -3,9 +3,9 @@ use homedisk_types::{
|
||||||
auth::login::{Request, Response},
|
auth::login::{Request, Response},
|
||||||
config::types::Config,
|
config::types::Config,
|
||||||
errors::{AuthError, ServerError},
|
errors::{AuthError, ServerError},
|
||||||
token::{Claims, Token},
|
|
||||||
};
|
};
|
||||||
use homedisk_utils::database::{Database, User};
|
use homedisk_utils::database::{Database, User};
|
||||||
|
use rust_utilities::crypto::jsonwebtoken::{Claims, Token};
|
||||||
|
|
||||||
pub async fn handle(
|
pub async fn handle(
|
||||||
db: Extension<Database>,
|
db: Extension<Database>,
|
||||||
|
@ -16,7 +16,11 @@ pub async fn handle(
|
||||||
|
|
||||||
let response = match db.create_user(&user).await {
|
let response = match db.create_user(&user).await {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
let token = Token::new(config.jwt.secret.as_bytes(), Claims::new(user.id)).unwrap();
|
let token = Token::new(
|
||||||
|
config.jwt.secret.as_bytes(),
|
||||||
|
Claims::new(user.id, config.jwt.expires),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
Response::LoggedIn {
|
Response::LoggedIn {
|
||||||
access_token: token.encoded,
|
access_token: token.encoded,
|
||||||
|
|
|
@ -4,7 +4,6 @@ version = "0.0.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
token = ["chrono", "jsonwebtoken"]
|
|
||||||
config = ["toml", "dirs"]
|
config = ["toml", "dirs"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
@ -31,11 +30,3 @@ optional = true
|
||||||
[dependencies.dirs]
|
[dependencies.dirs]
|
||||||
version = "4.0.0"
|
version = "4.0.0"
|
||||||
optional = true
|
optional = true
|
||||||
|
|
||||||
# token
|
|
||||||
[dependencies.chrono]
|
|
||||||
version = "0.4.19"
|
|
||||||
optional = true
|
|
||||||
[dependencies.jsonwebtoken]
|
|
||||||
version = "8.1.0"
|
|
||||||
optional = true
|
|
||||||
|
|
|
@ -16,4 +16,5 @@ pub struct ConfigHTTP {
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
pub struct ConfigJWT {
|
pub struct ConfigJWT {
|
||||||
pub secret: String,
|
pub secret: String,
|
||||||
|
pub expires: i64,
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,3 @@ pub mod auth;
|
||||||
pub mod config;
|
pub mod config;
|
||||||
pub mod errors;
|
pub mod errors;
|
||||||
pub mod macros;
|
pub mod macros;
|
||||||
|
|
||||||
#[cfg(feature = "token")]
|
|
||||||
pub mod token;
|
|
||||||
|
|
|
@ -1,114 +0,0 @@
|
||||||
use chrono::{Duration, Utc};
|
|
||||||
use jsonwebtoken::{
|
|
||||||
decode, encode, errors::Error, Algorithm, DecodingKey, EncodingKey, Header, TokenData,
|
|
||||||
Validation,
|
|
||||||
};
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
|
||||||
pub struct Claims {
|
|
||||||
pub sub: String,
|
|
||||||
pub exp: i64,
|
|
||||||
pub iat: i64,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Claims {
|
|
||||||
/// Generate Json Web Token Claims
|
|
||||||
/// ```
|
|
||||||
/// use homedisk_types::token::Claims;
|
|
||||||
///
|
|
||||||
/// let user_id = "123".to_string();
|
|
||||||
/// let claims = Claims::new(user_id);
|
|
||||||
/// ```
|
|
||||||
pub fn new(sub: String) -> Self {
|
|
||||||
let iat = Utc::now();
|
|
||||||
let exp = iat + Duration::hours(24);
|
|
||||||
|
|
||||||
Self {
|
|
||||||
sub,
|
|
||||||
iat: iat.timestamp(),
|
|
||||||
exp: exp.timestamp(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
|
||||||
pub struct Token {
|
|
||||||
header: Header,
|
|
||||||
pub claims: Claims,
|
|
||||||
pub encoded: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Token {
|
|
||||||
/// Generate new token
|
|
||||||
/// ```ignore
|
|
||||||
/// use homedisk_types::token::{Token, Claims};
|
|
||||||
///
|
|
||||||
/// let claims = Claims::new("user_id_1234".to_string());
|
|
||||||
/// let token = Token::new(secret, claims)?;
|
|
||||||
/// ```
|
|
||||||
pub fn new(key: &[u8], claims: Claims) -> Result<Self> {
|
|
||||||
let header = Header::new(Algorithm::HS256);
|
|
||||||
let encoded = encode(&header, &claims, &EncodingKey::from_secret(key))?;
|
|
||||||
|
|
||||||
Ok(Self {
|
|
||||||
header,
|
|
||||||
claims,
|
|
||||||
encoded,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Validate token
|
|
||||||
/// ```ignore
|
|
||||||
/// use homedisk_types::token::{Token, Claims};
|
|
||||||
///
|
|
||||||
/// let token = Token::new(secret, claims)?;
|
|
||||||
/// let decoded = Token::decode(secret, token.encoded)?;
|
|
||||||
/// ```
|
|
||||||
pub fn decode(key: &[u8], token: String) -> Result<TokenData<Claims>> {
|
|
||||||
decode::<Claims>(
|
|
||||||
&token,
|
|
||||||
&DecodingKey::from_secret(key),
|
|
||||||
&Validation::default(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub type Result<T> = std::result::Result<T, Error>;
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod test {
|
|
||||||
use super::{Claims, Token};
|
|
||||||
|
|
||||||
fn gen_token(key: &[u8]) -> Token {
|
|
||||||
Token::new(key, Claims::new("test".to_string())).expect("generate token")
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn new_token() {
|
|
||||||
let key = b"secret";
|
|
||||||
gen_token(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn decode_token() {
|
|
||||||
let key = b"secret";
|
|
||||||
let token = gen_token(key);
|
|
||||||
|
|
||||||
let decoded = Token::decode(key, token.encoded).unwrap();
|
|
||||||
|
|
||||||
assert_eq!(decoded.claims, token.claims)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn decode_token_invalid_token() {
|
|
||||||
let key = b"key";
|
|
||||||
let token = gen_token(key);
|
|
||||||
|
|
||||||
let other_key = b"other key";
|
|
||||||
|
|
||||||
let err = Token::decode(other_key, token.encoded).unwrap_err();
|
|
||||||
|
|
||||||
assert_eq!(err.to_string(), "InvalidSignature");
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -4,8 +4,7 @@ version = "0.0.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
full = ["crypto", "database"]
|
full = ["database"]
|
||||||
crypto = ["sha-1", "sha2", "hex"]
|
|
||||||
database = ["sqlx", "uuid"]
|
database = ["sqlx", "uuid"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
@ -16,17 +15,6 @@ futures-util = "0.3.21"
|
||||||
version = "1.0.136"
|
version = "1.0.136"
|
||||||
features = ["derive"]
|
features = ["derive"]
|
||||||
|
|
||||||
# crypto
|
|
||||||
[dependencies.sha-1]
|
|
||||||
version = "0.10.0"
|
|
||||||
optional = true
|
|
||||||
[dependencies.sha2]
|
|
||||||
version = "0.10.2"
|
|
||||||
optional = true
|
|
||||||
[dependencies.hex]
|
|
||||||
version = "0.4.3"
|
|
||||||
optional = true
|
|
||||||
|
|
||||||
# database
|
# database
|
||||||
[dependencies.sqlx]
|
[dependencies.sqlx]
|
||||||
version = "0.5.13"
|
version = "0.5.13"
|
||||||
|
@ -36,6 +24,9 @@ optional = true
|
||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
features = ["v5"]
|
features = ["v5"]
|
||||||
optional = true
|
optional = true
|
||||||
|
[dependencies.rust_utilities]
|
||||||
|
version = "0.2.0"
|
||||||
|
features = ["sha"]
|
||||||
|
|
||||||
[dev-dependencies.tokio]
|
[dev-dependencies.tokio]
|
||||||
version = "1.17.0"
|
version = "1.17.0"
|
||||||
|
|
|
@ -1,16 +0,0 @@
|
||||||
use std::fmt;
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
|
||||||
pub enum Error {
|
|
||||||
UnknownAlgorithm(&'static str, String),
|
|
||||||
}
|
|
||||||
|
|
||||||
pub type Result<T> = std::result::Result<T, Error>;
|
|
||||||
|
|
||||||
impl fmt::Display for Error {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
match self {
|
|
||||||
Error::UnknownAlgorithm(typ, named) => write!(f, "unknown {} algorithm {}", typ, named),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,120 +0,0 @@
|
||||||
use sha1::Sha1;
|
|
||||||
use sha2::{Digest, Sha256, Sha512};
|
|
||||||
|
|
||||||
use super::{Error, Result};
|
|
||||||
|
|
||||||
/// create a cryptographic hash from a string (sha1, sha256, sha512)
|
|
||||||
/// ```
|
|
||||||
/// use homedisk_utils::crypto::{CryptographicHash, encode};
|
|
||||||
///
|
|
||||||
/// let mut sha1 = CryptographicHash::new("SHA-1").unwrap();
|
|
||||||
/// sha1.update(b"test sha1 hash");
|
|
||||||
///
|
|
||||||
/// let hash = encode(sha1.finalize());
|
|
||||||
///
|
|
||||||
/// assert_eq!(hash, "7726bd9560e1ad4a1a4f056cae5c0c9ea8bacfc2".to_string())
|
|
||||||
/// ```
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub enum CryptographicHash {
|
|
||||||
Sha1(Sha1),
|
|
||||||
Sha256(Sha256),
|
|
||||||
Sha512(Sha512),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl CryptographicHash {
|
|
||||||
/// Create a new hasher
|
|
||||||
pub fn new(algo: &str) -> Result<Self> {
|
|
||||||
match algo {
|
|
||||||
"SHA-1" | "SHA1" | "Sha1" | "sha1" => Ok(Self::Sha1(Sha1::new())),
|
|
||||||
"SHA-256" | "SHA256" | "Sha256" | "sha256" => Ok(Self::Sha256(Sha256::new())),
|
|
||||||
"SHA-512" | "SHA512" | "Sha512" | "sha512" => Ok(Self::Sha512(Sha512::new())),
|
|
||||||
_ => Err(Error::UnknownAlgorithm("digest", algo.to_string())),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set a value for hasher
|
|
||||||
pub fn update(&mut self, input: &[u8]) {
|
|
||||||
match self {
|
|
||||||
Self::Sha1(sha1) => sha1.update(input),
|
|
||||||
Self::Sha256(sha256) => sha256.update(input),
|
|
||||||
Self::Sha512(sha512) => sha512.update(input),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Compute hash
|
|
||||||
pub fn finalize(&mut self) -> Vec<u8> {
|
|
||||||
match self {
|
|
||||||
Self::Sha1(sha1) => sha1.finalize_reset().to_vec(),
|
|
||||||
Self::Sha256(sha256) => sha256.finalize_reset().to_vec(),
|
|
||||||
Self::Sha512(sha512) => sha512.finalize_reset().to_vec(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Streamline the hash calculation to a single function
|
|
||||||
pub fn hash(algo: &str, input: &[u8]) -> Result<Vec<u8>> {
|
|
||||||
let mut hasher = Self::new(algo)?;
|
|
||||||
|
|
||||||
hasher.update(input);
|
|
||||||
|
|
||||||
Ok(hasher.finalize())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use crate::crypto::{encode, CryptographicHash, Error};
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn sha1() {
|
|
||||||
let mut sha1 = CryptographicHash::new("SHA-1").unwrap();
|
|
||||||
sha1.update(b"test sha1 hash");
|
|
||||||
|
|
||||||
let hash = encode(sha1.finalize());
|
|
||||||
|
|
||||||
assert_eq!(hash, "7726bd9560e1ad4a1a4f056cae5c0c9ea8bacfc2".to_string())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn sha256() {
|
|
||||||
let mut sha256 = CryptographicHash::new("SHA-256").unwrap();
|
|
||||||
sha256.update(b"test sha256 hash");
|
|
||||||
|
|
||||||
let hash = encode(sha256.finalize());
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
hash,
|
|
||||||
"eaf6e4198f39ccd63bc3e957d43bf4ef67f12c318c8e3cdc2567a37339902dac".to_string()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn sha512() {
|
|
||||||
let mut sha512 = CryptographicHash::new("SHA-512").unwrap();
|
|
||||||
sha512.update(b"test sha512 hash");
|
|
||||||
|
|
||||||
let hash = encode(sha512.finalize());
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
hash,
|
|
||||||
"b43b4d7178014c92f55be828d66c9f98211fc67b385f7790a5b4b2fcb89fe1831645b5a4c17f3f7f11d8f34d2800a77a2b8faa5a0fb9d6b8f7befbc29a9ce795".to_string()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn hash_fn() {
|
|
||||||
let hash = CryptographicHash::hash("SHA-512", b"test sha512 hash").unwrap();
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
encode(hash),
|
|
||||||
"b43b4d7178014c92f55be828d66c9f98211fc67b385f7790a5b4b2fcb89fe1831645b5a4c17f3f7f11d8f34d2800a77a2b8faa5a0fb9d6b8f7befbc29a9ce795".to_string()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn unknown_algorithm() {
|
|
||||||
let algo = "unknow_algo";
|
|
||||||
let err = CryptographicHash::new(algo).unwrap_err();
|
|
||||||
|
|
||||||
assert_eq!(err, Error::UnknownAlgorithm("digest", algo.to_string()))
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,5 +0,0 @@
|
||||||
mod error;
|
|
||||||
mod hash;
|
|
||||||
|
|
||||||
pub use hex::encode;
|
|
||||||
pub use {error::*, hash::*};
|
|
|
@ -1,21 +1,12 @@
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
use crate::crypto;
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
UserNotFound,
|
UserNotFound,
|
||||||
Crypto(crypto::Error),
|
|
||||||
SQLx(sqlx::Error),
|
SQLx(sqlx::Error),
|
||||||
Io(std::io::Error),
|
Io(std::io::Error),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<crypto::Error> for Error {
|
|
||||||
fn from(err: crypto::Error) -> Self {
|
|
||||||
Error::Crypto(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
||||||
|
@ -32,9 +23,8 @@ impl fmt::Display for Error {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
Error::UserNotFound => write!(f, "user not found"),
|
Error::UserNotFound => write!(f, "user not found"),
|
||||||
Error::Crypto(err) => write!(f, "crypto error: {}", err),
|
|
||||||
Error::SQLx(err) => write!(f, "sqlx error: {}", err),
|
Error::SQLx(err) => write!(f, "sqlx error: {}", err),
|
||||||
Error::Io(err) => write!(f, "error: {}", err),
|
Error::Io(err) => write!(f, "std::io error: {}", err),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
use hex::encode;
|
use rust_utilities::crypto::sha::{CryptographicHash, encode, Algorithm};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
use crate::crypto::CryptographicHash;
|
|
||||||
|
|
||||||
#[derive(Debug, sqlx::FromRow)]
|
#[derive(Debug, sqlx::FromRow)]
|
||||||
pub struct User {
|
pub struct User {
|
||||||
pub id: String,
|
pub id: String,
|
||||||
|
@ -11,21 +9,24 @@ pub struct User {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl User {
|
impl User {
|
||||||
/// Create a new User type (note **this doesn't create a new user in the database!**)
|
/// **Note this doesn't create a new user in the database!**
|
||||||
///
|
///
|
||||||
/// This function creates a unique UUID for the user and creates a password hash using SHA-512
|
/// This function creates a unique UUID for a user and creates a password hash using SHA-512
|
||||||
|
/// and returns in the User type
|
||||||
/// ```
|
/// ```
|
||||||
/// use homedisk_utils::database::User;
|
/// use homedisk_utils::database::User;
|
||||||
///
|
///
|
||||||
/// let user = User::new("medzik", "SuperSecretPassword123!");
|
/// let user = User::new("medzik", "SuperSecretPassword123!");
|
||||||
/// ```
|
/// ```
|
||||||
pub fn new(username: &str, password: &str) -> Self {
|
pub fn new(username: &str, password: &str) -> Self {
|
||||||
|
// change username to lowercase
|
||||||
|
let username = username.to_lowercase();
|
||||||
|
|
||||||
// create user UUID
|
// create user UUID
|
||||||
let sha1_name = CryptographicHash::hash("SHA-1", username.as_bytes()).unwrap();
|
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();
|
||||||
|
|
||||||
let username = username.to_lowercase();
|
let password = encode(CryptographicHash::hash(Algorithm::SHA512, password.as_bytes()));
|
||||||
let password = encode(CryptographicHash::hash("SHA-512", password.as_bytes()).unwrap());
|
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
id,
|
id,
|
||||||
|
@ -48,7 +49,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn check_password_is_hashed() {
|
fn check_password_is_hashed() {
|
||||||
let password = "Password";
|
let password = "password";
|
||||||
let user = User::new("test", password);
|
let user = User::new("test", password);
|
||||||
|
|
||||||
assert!(user.password != password)
|
assert!(user.password != password)
|
||||||
|
|
|
@ -1,5 +1,2 @@
|
||||||
#[cfg(feature = "crypto")]
|
|
||||||
pub mod crypto;
|
|
||||||
|
|
||||||
#[cfg(feature = "database")]
|
#[cfg(feature = "database")]
|
||||||
pub mod database;
|
pub mod database;
|
||||||
|
|
Loading…
Reference in a new issue