Starting to see services being made
This commit is contained in:
parent
67a990de1f
commit
c31586573b
|
@ -1609,6 +1609,7 @@ dependencies = [
|
||||||
"chrono",
|
"chrono",
|
||||||
"data-encoding",
|
"data-encoding",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
|
"log",
|
||||||
"ring",
|
"ring",
|
||||||
"serde",
|
"serde",
|
||||||
"sqlx",
|
"sqlx",
|
||||||
|
|
|
@ -17,3 +17,4 @@ chrono = { version = "0.4", features = [ "serde" ] }
|
||||||
ring = "0.16.20"
|
ring = "0.16.20"
|
||||||
data-encoding = "2.3.2"
|
data-encoding = "2.3.2"
|
||||||
futures-util = "0.3"
|
futures-util = "0.3"
|
||||||
|
log = "0.4.19"
|
|
@ -32,3 +32,10 @@ pub async fn fetch_user_credentials(
|
||||||
) -> Result<Vec<Credential>, Error> {
|
) -> Result<Vec<Credential>, Error> {
|
||||||
sqlx::query_as(r#"SELECT user_id, credential_type as "credential_type: _", credential, validated, time_created, last_updated FROM credential WHERE user_id = $1 "#).bind(user_id).fetch_all(conn).await
|
sqlx::query_as(r#"SELECT user_id, credential_type as "credential_type: _", credential, validated, time_created, last_updated FROM credential WHERE user_id = $1 "#).bind(user_id).fetch_all(conn).await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn get_credential(
|
||||||
|
conn: &PgPool,
|
||||||
|
credential: String,
|
||||||
|
) -> Result<Option<Credential>, Error> {
|
||||||
|
sqlx::query_as(r#"SELECT user_id, credential_type as "credential_type: _", credential, validated, time_created, last_updated FROM credential WHERE credential = $1"#).bind(credential).fetch_optional(conn).await
|
||||||
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@ pub const ERROR_INVALID_PASSWORD: (&str, &str) = (
|
||||||
|
|
||||||
pub const ERROR_USER_ALREADY_EXISTS: (&str, &str) = (
|
pub const ERROR_USER_ALREADY_EXISTS: (&str, &str) = (
|
||||||
"ERROR.USER_ALREADY_EXISTS",
|
"ERROR.USER_ALREADY_EXISTS",
|
||||||
"A user with that email already exists.",
|
"A user with that credential already exists.",
|
||||||
);
|
);
|
||||||
|
|
||||||
pub const ERROR_USER_DOES_NOT_EXIST: (&str, &str) = (
|
pub const ERROR_USER_DOES_NOT_EXIST: (&str, &str) = (
|
||||||
|
@ -60,3 +60,8 @@ pub const ERROR_CREATING_TOKEN: (&str, &str) = (
|
||||||
"ERROR.CREATING_TOKEN",
|
"ERROR.CREATING_TOKEN",
|
||||||
"The server had an error creating the auth tokens.",
|
"The server had an error creating the auth tokens.",
|
||||||
);
|
);
|
||||||
|
|
||||||
|
pub const ERROR_TOO_MANY_CREDENTIALS: (&str, &str) = (
|
||||||
|
"ERROR.TOO_MANY_CREDENTIALS",
|
||||||
|
"Only up to 3 credentials are allowed. One of each type.",
|
||||||
|
);
|
||||||
|
|
|
@ -1,5 +1,76 @@
|
||||||
|
use std::error::Error;
|
||||||
|
use log::{error, log};
|
||||||
|
use crate::dao::credential::get_credential;
|
||||||
|
use crate::domain::credential::Credential;
|
||||||
use crate::dto::users::UserRegisterPayload;
|
use crate::dto::users::UserRegisterPayload;
|
||||||
|
use crate::resources::error_messages::{ERROR_TOO_MANY_CREDENTIALS, ERROR_USER_ALREADY_EXISTS, ErrorResource};
|
||||||
|
use crate::validation::user_validator::validate_user_for_creation;
|
||||||
|
|
||||||
pub async fn register_user(db_conn: &sqlx::PgPool, user: UserRegisterPayload) -> Result<(), ()> {
|
pub async fn register_user(db_conn: &sqlx::PgPool, user: UserRegisterPayload) -> Result<(), Vec<ErrorResource>> {
|
||||||
|
let mut error_resources: Vec<ErrorResource> = Vec::new();
|
||||||
|
// Validate user
|
||||||
|
validate_user_for_creation(&user, &mut error_resources);
|
||||||
|
// Find if user exists
|
||||||
|
if user.credentials.len() > 3 {
|
||||||
|
error_resources.push(ERROR_TOO_MANY_CREDENTIALS);
|
||||||
|
|
||||||
|
}
|
||||||
|
for credential_dto in user.credentials.iter() {
|
||||||
|
match get_credential(
|
||||||
|
&db_conn,
|
||||||
|
credential_dto.credential.clone(),
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
Ok(credential_opt) => {
|
||||||
|
match credential_opt {
|
||||||
|
None => {}
|
||||||
|
Some(_) => {
|
||||||
|
error_resources.push(
|
||||||
|
ERROR_USER_ALREADY_EXISTS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
error!("{}", e);
|
||||||
|
error_resources.push(("ERROR.DATABASE_ERROR", ""));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
// If validation gave any errors blow up and send them back to the client
|
||||||
|
if error_resources.len() > 0 {
|
||||||
|
return Err(error_resources);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO:
|
||||||
|
// Get salt and hashed password from hashing function then give the results to the user
|
||||||
|
let hash_result = hasher::hash_password(&user_to_insert.password);
|
||||||
|
user_to_insert.password = hash_result.hash;
|
||||||
|
user_to_insert.salt = hash_result.salt;
|
||||||
|
|
||||||
|
// Insert user in DB
|
||||||
|
match insert_user(&db_conn, &user_to_insert).await{
|
||||||
|
Ok(resultrs) => {
|
||||||
|
user_to_insert.id = resultrs.last_insert_id() as u32;
|
||||||
|
},
|
||||||
|
Err(error) => {
|
||||||
|
println!("Error while inserting user in database from create_user method. Log: {}", error);
|
||||||
|
return HttpResponse::InternalServerError().finish();
|
||||||
|
}};
|
||||||
|
|
||||||
|
// Create token and send it back.
|
||||||
|
let tokens: Vec<String> = hasher::generate_multiple_random_token_with_rng(2).await.expect("Error creating multiple random tokens.");
|
||||||
|
let mut token_to_insert =
|
||||||
|
Token::new(user_to_insert.id,
|
||||||
|
tokens.get(0).expect("Error. Token doesn't exist in list.").to_string(),
|
||||||
|
tokens.get(1).expect("Error. Token doesn't exist in list.").to_string()
|
||||||
|
);
|
||||||
|
|
||||||
|
// Insert token in DB
|
||||||
|
match insert_token(&db_conn, &token_to_insert).await{
|
||||||
|
Ok(resultrs) => {token_to_insert.id = resultrs.last_insert_id() as u32},
|
||||||
|
Err(_e) => {return HttpResponse::InternalServerError().finish()}
|
||||||
|
}
|
||||||
|
*/
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,9 @@ use tokio::task::JoinError;
|
||||||
|
|
||||||
const SALT_ROUNDS: u32 = 1000;
|
const SALT_ROUNDS: u32 = 1000;
|
||||||
|
|
||||||
pub async fn generate_multiple_random_token_with_rng(amount: u8) -> Result<Vec<String>, JoinError> {
|
pub(crate) async fn generate_multiple_random_token_with_rng(
|
||||||
|
amount: u8,
|
||||||
|
) -> Result<Vec<String>, JoinError> {
|
||||||
// Get a new instance of a Random Number Generator
|
// Get a new instance of a Random Number Generator
|
||||||
let rng = SystemRandom::new();
|
let rng = SystemRandom::new();
|
||||||
|
|
||||||
|
@ -20,7 +22,7 @@ pub async fn generate_multiple_random_token_with_rng(amount: u8) -> Result<Vec<S
|
||||||
let future_token = async move {
|
let future_token = async move {
|
||||||
let mut token_arr = [0u8; digest::SHA512_OUTPUT_LEN];
|
let mut token_arr = [0u8; digest::SHA512_OUTPUT_LEN];
|
||||||
match cloned_rng.fill(&mut token_arr) {
|
match cloned_rng.fill(&mut token_arr) {
|
||||||
Ok(()) => BASE64.encode(&token_arr), //TODO: Remove this panic, make your own error and fix this
|
Ok(()) => BASE64.encode(&token_arr),
|
||||||
Err(_e) => {
|
Err(_e) => {
|
||||||
panic!("Failed to generate random token for some reason.")
|
panic!("Failed to generate random token for some reason.")
|
||||||
}
|
}
|
||||||
|
@ -42,7 +44,10 @@ pub async fn generate_multiple_random_token_with_rng(amount: u8) -> Result<Vec<S
|
||||||
Ok(all_tokens_solved)
|
Ok(all_tokens_solved)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn hash_password_with_existing_salt(password: &String, input_salt: &String) -> HashResult {
|
pub(crate) fn hash_password_with_existing_salt(
|
||||||
|
password: &String,
|
||||||
|
input_salt: &String,
|
||||||
|
) -> HashResult {
|
||||||
// Get output length from a sha512 hash
|
// Get output length from a sha512 hash
|
||||||
const CREDENTIAL_LEN: usize = digest::SHA512_OUTPUT_LEN;
|
const CREDENTIAL_LEN: usize = digest::SHA512_OUTPUT_LEN;
|
||||||
let n_iter = NonZeroU32::new(SALT_ROUNDS).unwrap();
|
let n_iter = NonZeroU32::new(SALT_ROUNDS).unwrap();
|
||||||
|
@ -65,7 +70,7 @@ pub fn hash_password_with_existing_salt(password: &String, input_salt: &String)
|
||||||
HashResult::new(BASE64.encode(&salt), BASE64.encode(&pbkdf2_hash))
|
HashResult::new(BASE64.encode(&salt), BASE64.encode(&pbkdf2_hash))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn hash_password(password: &String) -> HashResult {
|
pub(crate) fn hash_password(password: &String) -> HashResult {
|
||||||
// Get output length from a sha512 hash
|
// Get output length from a sha512 hash
|
||||||
const CREDENTIAL_LEN: usize = digest::SHA512_OUTPUT_LEN;
|
const CREDENTIAL_LEN: usize = digest::SHA512_OUTPUT_LEN;
|
||||||
let n_iter = NonZeroU32::new(SALT_ROUNDS).unwrap();
|
let n_iter = NonZeroU32::new(SALT_ROUNDS).unwrap();
|
||||||
|
|
Loading…
Reference in New Issue