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 crate::hashing;
|
||||
use crate::repo;
|
||||
|
||||
pub mod request {
|
||||
@@ -48,6 +49,7 @@ pub async fn register_user(
|
||||
email_verified: true,
|
||||
date_created: String::from("2025-01-01 12:00:00"),
|
||||
last_login: String::from("nil"),
|
||||
salt_id: uuid::Uuid::nil(),
|
||||
};
|
||||
|
||||
match repo::user::exists(&pool, &user.username).await {
|
||||
@@ -61,6 +63,12 @@ pub async fn register_user(
|
||||
}),
|
||||
)
|
||||
} 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 {
|
||||
Ok(id) => {
|
||||
user.id = id;
|
||||
|
@@ -9,17 +9,18 @@ use argon2::{
|
||||
};
|
||||
|
||||
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);
|
||||
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();
|
||||
|
||||
// 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)
|
||||
// You could customize parameters here if needed, but defaults are strong
|
||||
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
|
||||
// The output is a PasswordHash string format that includes algorithm, version,
|
||||
// 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)
|
||||
}
|
||||
@@ -61,7 +62,8 @@ mod tests {
|
||||
#[test]
|
||||
fn test_hash_password() {
|
||||
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(res) => {
|
||||
assert_eq!(res, true);
|
||||
|
@@ -29,8 +29,8 @@ pub mod user {
|
||||
) -> Result<uuid::Uuid, sqlx::Error> {
|
||||
let row = sqlx::query(
|
||||
r#"
|
||||
INSERT INTO "user" (username, password, email, phone, firstname, lastname, email_verified, status)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
|
||||
INSERT INTO "user" (username, password, email, phone, firstname, lastname, email_verified, status, salt_id)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)
|
||||
RETURNING id, date_created;
|
||||
"#)
|
||||
.bind(&user.username)
|
||||
@@ -41,6 +41,7 @@ pub mod user {
|
||||
.bind(&user.lastname)
|
||||
.bind(user.email_verified)
|
||||
.bind(&user.status)
|
||||
.bind(user.salt_id)
|
||||
.fetch_one(pool)
|
||||
.await
|
||||
.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