mirror of
				https://gitlab.com/comunic/comunicapiv3
				synced 2025-11-04 01:24:04 +00:00 
			
		
		
		
	Can login user
This commit is contained in:
		
							
								
								
									
										1
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										1
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							@@ -514,6 +514,7 @@ dependencies = [
 | 
				
			|||||||
 "mailchecker",
 | 
					 "mailchecker",
 | 
				
			||||||
 "mysql",
 | 
					 "mysql",
 | 
				
			||||||
 "percent-encoding",
 | 
					 "percent-encoding",
 | 
				
			||||||
 | 
					 "rand",
 | 
				
			||||||
 "serde",
 | 
					 "serde",
 | 
				
			||||||
 "sha1",
 | 
					 "sha1",
 | 
				
			||||||
 "yaml-rust",
 | 
					 "yaml-rust",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -16,4 +16,5 @@ futures = "0.3.5"
 | 
				
			|||||||
encoding_rs = "0.8.23"
 | 
					encoding_rs = "0.8.23"
 | 
				
			||||||
percent-encoding = "2.1.0"
 | 
					percent-encoding = "2.1.0"
 | 
				
			||||||
mailchecker = "3.3.6"
 | 
					mailchecker = "3.3.6"
 | 
				
			||||||
sha1 = "0.6.0"
 | 
					sha1 = "0.6.0"
 | 
				
			||||||
 | 
					rand = "0.7.3"
 | 
				
			||||||
@@ -4,4 +4,5 @@ pub mod config;
 | 
				
			|||||||
pub mod http_request_handler;
 | 
					pub mod http_request_handler;
 | 
				
			||||||
pub mod api_client;
 | 
					pub mod api_client;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub mod user;
 | 
					pub mod user;
 | 
				
			||||||
 | 
					pub mod user_token;
 | 
				
			||||||
@@ -1,9 +1,12 @@
 | 
				
			|||||||
/// User information
 | 
					///! User information
 | 
				
			||||||
///
 | 
					///!
 | 
				
			||||||
/// @author Pierre Hubert
 | 
					///! @author Pierre Hubert
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub type UserID = i64;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Debug)]
 | 
					#[derive(Debug)]
 | 
				
			||||||
pub struct User {
 | 
					pub struct User {
 | 
				
			||||||
    pub id: i64,
 | 
					    pub id: UserID,
 | 
				
			||||||
    pub email: String,
 | 
					    pub email: String,
 | 
				
			||||||
    pub password: String,
 | 
					    pub password: String,
 | 
				
			||||||
    pub first_name: String,
 | 
					    pub first_name: String,
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										11
									
								
								src/data/user_token.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								src/data/user_token.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,11 @@
 | 
				
			|||||||
 | 
					use crate::data::user::UserID;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// User access token information
 | 
				
			||||||
 | 
					///
 | 
				
			||||||
 | 
					/// Author : Pierre Hubert
 | 
				
			||||||
 | 
					#[derive(Debug)]
 | 
				
			||||||
 | 
					pub struct UserAccessToken {
 | 
				
			||||||
 | 
					    pub user_id: UserID,
 | 
				
			||||||
 | 
					    pub client_id: u32,
 | 
				
			||||||
 | 
					    pub token: String
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -5,5 +5,8 @@
 | 
				
			|||||||
/// API services tokens table
 | 
					/// API services tokens table
 | 
				
			||||||
pub const SERVICES_TABLES : &str = "comunic_api_services_tokens";
 | 
					pub const SERVICES_TABLES : &str = "comunic_api_services_tokens";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// User access tokens table
 | 
				
			||||||
 | 
					pub const USER_ACCESS_TOKENS_TABLE: &str = "comunic_api_users_tokens";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// User table
 | 
					/// User table
 | 
				
			||||||
pub const USERS_TABLE : &str = "utilisateurs";
 | 
					pub const USERS_TABLE : &str = "utilisateurs";
 | 
				
			||||||
@@ -1,6 +1,11 @@
 | 
				
			|||||||
use crate::data::api_client::APIClient;
 | 
					use crate::data::api_client::APIClient;
 | 
				
			||||||
use crate::data::error::ResultBoxError;
 | 
					use crate::data::error::{ExecError, ResultBoxError};
 | 
				
			||||||
use crate::helpers::user_helper;
 | 
					use crate::data::user::UserID;
 | 
				
			||||||
 | 
					use crate::data::user_token::UserAccessToken;
 | 
				
			||||||
 | 
					use crate::database_structure::USER_ACCESS_TOKENS_TABLE;
 | 
				
			||||||
 | 
					use crate::helpers::{database, user_helper};
 | 
				
			||||||
 | 
					use crate::helpers::database::{QueryInfo, InsertQuery};
 | 
				
			||||||
 | 
					use crate::utils::crypt_utils::{crypt_pass, rand_str};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Account helper
 | 
					/// Account helper
 | 
				
			||||||
///
 | 
					///
 | 
				
			||||||
@@ -13,9 +18,49 @@ use crate::helpers::user_helper;
 | 
				
			|||||||
pub fn login_user(email: &str, password: &str, client: &APIClient) -> ResultBoxError<String> {
 | 
					pub fn login_user(email: &str, password: &str, client: &APIClient) -> ResultBoxError<String> {
 | 
				
			||||||
    let user = user_helper::find_user_by_email(email)?;
 | 
					    let user = user_helper::find_user_by_email(email)?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // TODO : check user password
 | 
					    // Validate user password
 | 
				
			||||||
 | 
					    let password = crypt_pass(password)?;
 | 
				
			||||||
 | 
					    if !user.password.eq(&password) {
 | 
				
			||||||
 | 
					        return Err(ExecError::boxed_new("The user gave an invalid password!"));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    println!("{:#?}", user);
 | 
					    // Check if we already have a login token for this user
 | 
				
			||||||
 | 
					    if let Ok(token) = get_client_tokens(user.id, client) {
 | 
				
			||||||
 | 
					        return Ok(token.token);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Ok("d".to_string())
 | 
					
 | 
				
			||||||
 | 
					    // Create new login tokens
 | 
				
			||||||
 | 
					    let new_token = UserAccessToken {
 | 
				
			||||||
 | 
					        user_id: user.id,
 | 
				
			||||||
 | 
					        client_id: client.id,
 | 
				
			||||||
 | 
					        token: rand_str(150)
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Save it
 | 
				
			||||||
 | 
					    database::insert(
 | 
				
			||||||
 | 
					        InsertQuery::new(USER_ACCESS_TOKENS_TABLE)
 | 
				
			||||||
 | 
					            .add_i64("user_id", new_token.user_id)
 | 
				
			||||||
 | 
					            .add_u32("service_id", client.id)
 | 
				
			||||||
 | 
					            .add_str("token1", &new_token.token)
 | 
				
			||||||
 | 
					            .add_str("token2", "dummy_data")
 | 
				
			||||||
 | 
					    )?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Ok(new_token.token)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Get user login tokens
 | 
				
			||||||
 | 
					fn get_client_tokens(user_id: UserID, client: &APIClient) -> ResultBoxError<UserAccessToken> {
 | 
				
			||||||
 | 
					    database::query_row(
 | 
				
			||||||
 | 
					        QueryInfo::new(USER_ACCESS_TOKENS_TABLE)
 | 
				
			||||||
 | 
					            .cond("user_id", user_id.to_string().as_ref())
 | 
				
			||||||
 | 
					            .cond("service_id", client.id.to_string().as_ref()),
 | 
				
			||||||
 | 
					        |res| {
 | 
				
			||||||
 | 
					            Ok(UserAccessToken {
 | 
				
			||||||
 | 
					                user_id: res.get_int64("user_id")?,
 | 
				
			||||||
 | 
					                client_id: res.get_int64("service_id")? as u32,
 | 
				
			||||||
 | 
					                token: res.get_str("token1")?,
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -8,6 +8,7 @@ use mysql::prelude::Queryable;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
use crate::data::config::DatabaseConfig;
 | 
					use crate::data::config::DatabaseConfig;
 | 
				
			||||||
use crate::data::error::{ExecError, ResultBoxError};
 | 
					use crate::data::error::{ExecError, ResultBoxError};
 | 
				
			||||||
 | 
					use std::collections::HashMap;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Database access helper
 | 
					/// Database access helper
 | 
				
			||||||
///
 | 
					///
 | 
				
			||||||
@@ -224,4 +225,62 @@ pub fn query<E, F: Fn(&RowResult) -> ProcessRowResult<E>>(info: QueryInfo, proce
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Ok(res)
 | 
					    Ok(res)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Structure used to execute a insert query
 | 
				
			||||||
 | 
					pub struct InsertQuery {
 | 
				
			||||||
 | 
					    pub table : String,
 | 
				
			||||||
 | 
					    pub values: HashMap<String, mysql::Value>,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl InsertQuery {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Construct a new InsertQuery instance
 | 
				
			||||||
 | 
					    pub fn new(table: &str) -> InsertQuery {
 | 
				
			||||||
 | 
					        InsertQuery {
 | 
				
			||||||
 | 
					            table: table.to_string(),
 | 
				
			||||||
 | 
					            values: HashMap::new()
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Add a string
 | 
				
			||||||
 | 
					    pub fn add_str(mut self, key: &str, value: &str) -> InsertQuery {
 | 
				
			||||||
 | 
					        self.values.insert(key.to_string(), Value::from(value));
 | 
				
			||||||
 | 
					        self
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Add an integer
 | 
				
			||||||
 | 
					    pub fn add_i64(mut self, key: &str, value: i64) -> InsertQuery {
 | 
				
			||||||
 | 
					        self.values.insert(key.to_string(), Value::from(value));
 | 
				
			||||||
 | 
					        self
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub fn add_u32(mut self, key: &str, value: u32) -> InsertQuery {
 | 
				
			||||||
 | 
					        self.values.insert(key.to_string(), Value::from(value));
 | 
				
			||||||
 | 
					        self
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Insert a new entry into the database
 | 
				
			||||||
 | 
					pub fn insert(query: InsertQuery) -> ResultBoxError<()> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Collect keys
 | 
				
			||||||
 | 
					    let keys = query.values
 | 
				
			||||||
 | 
					        .keys()
 | 
				
			||||||
 | 
					        .map(|f|f.to_string())
 | 
				
			||||||
 | 
					        .collect::<Vec<String>>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let query_sql = format!(
 | 
				
			||||||
 | 
					        "INSERT INTO {} ({}) VALUES({})",
 | 
				
			||||||
 | 
					        query.table,
 | 
				
			||||||
 | 
					        keys.join(", "),
 | 
				
			||||||
 | 
					        keys.iter().map(|_| "?").collect::<Vec<&str>>().join(", ")
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    get_connection()?.exec_drop(
 | 
				
			||||||
 | 
					        query_sql,
 | 
				
			||||||
 | 
					        query.values.values().collect::<Vec<&mysql::Value>>()
 | 
				
			||||||
 | 
					    )?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Ok(())
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -5,6 +5,8 @@
 | 
				
			|||||||
extern crate sha1;
 | 
					extern crate sha1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use crate::data::error::{ResultBoxError, ExecError};
 | 
					use crate::data::error::{ResultBoxError, ExecError};
 | 
				
			||||||
 | 
					use rand::{thread_rng, Rng};
 | 
				
			||||||
 | 
					use rand::distributions::Alphanumeric;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Generate a new sha1 string
 | 
					/// Generate a new sha1 string
 | 
				
			||||||
///
 | 
					///
 | 
				
			||||||
@@ -44,4 +46,20 @@ pub fn crypt_pass(pass: &str) -> ResultBoxError<String> {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Ok(String::from_utf8(result.stdout)?)
 | 
					    Ok(String::from_utf8(result.stdout)?)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Generate a random string of a given size
 | 
				
			||||||
 | 
					///
 | 
				
			||||||
 | 
					/// ```
 | 
				
			||||||
 | 
					/// use comunic_server::utils::crypt_utils::rand_str;
 | 
				
			||||||
 | 
					///
 | 
				
			||||||
 | 
					/// let size = 10;
 | 
				
			||||||
 | 
					/// let rand = rand_str(size);
 | 
				
			||||||
 | 
					/// assert_eq!(size, rand.len());
 | 
				
			||||||
 | 
					/// ```
 | 
				
			||||||
 | 
					pub fn rand_str(len: usize) -> String {
 | 
				
			||||||
 | 
					    thread_rng()
 | 
				
			||||||
 | 
					        .sample_iter(&Alphanumeric)
 | 
				
			||||||
 | 
					        .take(len)
 | 
				
			||||||
 | 
					        .collect()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user