Added hashing
All checks were successful
Rust Build / Check (pull_request) Successful in 1m24s
Rust Build / Test Suite (pull_request) Successful in 1m38s
Rust Build / Rustfmt (pull_request) Successful in 26s
Rust Build / Clippy (pull_request) Successful in 1m21s
Rust Build / build (pull_request) Successful in 2m40s
All checks were successful
Rust Build / Check (pull_request) Successful in 1m24s
Rust Build / Test Suite (pull_request) Successful in 1m38s
Rust Build / Rustfmt (pull_request) Successful in 26s
Rust Build / Clippy (pull_request) Successful in 1m21s
Rust Build / build (pull_request) Successful in 2m40s
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
use axum::{Json, http::StatusCode};
|
use axum::{Json, http::StatusCode};
|
||||||
|
|
||||||
|
use crate::hashing;
|
||||||
use crate::repo;
|
use crate::repo;
|
||||||
|
|
||||||
pub mod request {
|
pub mod request {
|
||||||
@@ -48,6 +49,7 @@ pub async fn register_user(
|
|||||||
email_verified: true,
|
email_verified: true,
|
||||||
date_created: String::from("2025-01-01 12:00:00"),
|
date_created: String::from("2025-01-01 12:00:00"),
|
||||||
last_login: String::from("nil"),
|
last_login: String::from("nil"),
|
||||||
|
salt_id: uuid::Uuid::nil(),
|
||||||
};
|
};
|
||||||
|
|
||||||
match repo::user::exists(&pool, &user.username).await {
|
match repo::user::exists(&pool, &user.username).await {
|
||||||
@@ -61,6 +63,12 @@ pub async fn register_user(
|
|||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
|
let salt_string = hashing::generate_salt().unwrap();
|
||||||
|
let mut salt = icarus_models::user::salt::Salt::default();
|
||||||
|
salt.salt = salt_string.as_str().to_string();
|
||||||
|
salt.id = repo::salt::insert(&pool, &salt).await.unwrap();
|
||||||
|
user.salt_id = salt.id;
|
||||||
|
|
||||||
match repo::user::insert(&pool, &user).await {
|
match repo::user::insert(&pool, &user).await {
|
||||||
Ok(id) => {
|
Ok(id) => {
|
||||||
user.id = id;
|
user.id = id;
|
||||||
|
@@ -9,17 +9,18 @@ use argon2::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
pub fn generate_salt() -> Result<SaltString, argon2::Error> {
|
pub fn generate_salt() -> Result<SaltString, argon2::Error> {
|
||||||
|
// Generate a random salt
|
||||||
|
// SaltString::generate uses OsRng internally for cryptographic security
|
||||||
let salt = SaltString::generate(&mut OsRng);
|
let salt = SaltString::generate(&mut OsRng);
|
||||||
Ok(salt)
|
Ok(salt)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn hash_password(password: &String) -> Result<String, argon2::password_hash::Error> {
|
pub fn hash_password(
|
||||||
|
password: &String,
|
||||||
|
salt: &SaltString,
|
||||||
|
) -> Result<String, argon2::password_hash::Error> {
|
||||||
let password_bytes = password.as_bytes();
|
let password_bytes = password.as_bytes();
|
||||||
|
|
||||||
// Generate a random salt
|
|
||||||
// SaltString::generate uses OsRng internally for cryptographic security
|
|
||||||
let salt = generate_salt().unwrap();
|
|
||||||
|
|
||||||
// Create an Argon2 instance with default parameters (recommended)
|
// Create an Argon2 instance with default parameters (recommended)
|
||||||
// You could customize parameters here if needed, but defaults are strong
|
// You could customize parameters here if needed, but defaults are strong
|
||||||
let argon2 = Argon2::default();
|
let argon2 = Argon2::default();
|
||||||
@@ -27,7 +28,7 @@ pub fn hash_password(password: &String) -> Result<String, argon2::password_hash:
|
|||||||
// Hash the password with the salt
|
// Hash the password with the salt
|
||||||
// The output is a PasswordHash string format that includes algorithm, version,
|
// The output is a PasswordHash string format that includes algorithm, version,
|
||||||
// parameters, salt, and the hash itself.
|
// parameters, salt, and the hash itself.
|
||||||
let password_hash = argon2.hash_password(password_bytes, &salt)?.to_string();
|
let password_hash = argon2.hash_password(password_bytes, salt)?.to_string();
|
||||||
|
|
||||||
Ok(password_hash)
|
Ok(password_hash)
|
||||||
}
|
}
|
||||||
@@ -61,7 +62,8 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_hash_password() {
|
fn test_hash_password() {
|
||||||
let some_password = String::from("somethingrandom");
|
let some_password = String::from("somethingrandom");
|
||||||
match hash_password(&some_password) {
|
let salt = generate_salt().unwrap();
|
||||||
|
match hash_password(&some_password, &salt) {
|
||||||
Ok(p) => match verify_password(&some_password, p.clone()) {
|
Ok(p) => match verify_password(&some_password, p.clone()) {
|
||||||
Ok(res) => {
|
Ok(res) => {
|
||||||
assert_eq!(res, true);
|
assert_eq!(res, true);
|
||||||
|
@@ -29,8 +29,8 @@ pub mod user {
|
|||||||
) -> Result<uuid::Uuid, sqlx::Error> {
|
) -> Result<uuid::Uuid, sqlx::Error> {
|
||||||
let row = sqlx::query(
|
let row = sqlx::query(
|
||||||
r#"
|
r#"
|
||||||
INSERT INTO "user" (username, password, email, phone, firstname, lastname, email_verified, status)
|
INSERT INTO "user" (username, password, email, phone, firstname, lastname, email_verified, status, salt_id)
|
||||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
|
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)
|
||||||
RETURNING id, date_created;
|
RETURNING id, date_created;
|
||||||
"#)
|
"#)
|
||||||
.bind(&user.username)
|
.bind(&user.username)
|
||||||
@@ -41,6 +41,7 @@ pub mod user {
|
|||||||
.bind(&user.lastname)
|
.bind(&user.lastname)
|
||||||
.bind(user.email_verified)
|
.bind(user.email_verified)
|
||||||
.bind(&user.status)
|
.bind(&user.status)
|
||||||
|
.bind(user.salt_id)
|
||||||
.fetch_one(pool)
|
.fetch_one(pool)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
@@ -62,3 +63,42 @@ pub mod user {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub mod salt {
|
||||||
|
use sqlx::Row;
|
||||||
|
|
||||||
|
#[derive(Debug, serde::Serialize, sqlx::FromRow)]
|
||||||
|
pub struct InsertedData {
|
||||||
|
pub id: uuid::Uuid,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn insert(
|
||||||
|
pool: &sqlx::PgPool,
|
||||||
|
salt: &icarus_models::user::salt::Salt,
|
||||||
|
) -> Result<uuid::Uuid, sqlx::Error> {
|
||||||
|
let row = sqlx::query(
|
||||||
|
r#"
|
||||||
|
INSERT INTO "salt" (salt)
|
||||||
|
VALUES ($1)
|
||||||
|
RETURNING id;
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.bind(&salt.salt)
|
||||||
|
.fetch_one(pool)
|
||||||
|
.await
|
||||||
|
.map_err(|e| {
|
||||||
|
eprintln!("Error inserting item: {}", e);
|
||||||
|
e
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let result = InsertedData {
|
||||||
|
id: row.try_get("id").map_err(|_e| sqlx::Error::RowNotFound)?,
|
||||||
|
};
|
||||||
|
|
||||||
|
if !result.id.is_nil() {
|
||||||
|
Ok(result.id)
|
||||||
|
} else {
|
||||||
|
Err(sqlx::Error::RowNotFound)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user