mirror of
				https://gitlab.com/comunic/comunicapiv3
				synced 2025-11-04 09:34: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",
 | 
			
		||||
 "mysql",
 | 
			
		||||
 "percent-encoding",
 | 
			
		||||
 "rand",
 | 
			
		||||
 "serde",
 | 
			
		||||
 "sha1",
 | 
			
		||||
 "yaml-rust",
 | 
			
		||||
 
 | 
			
		||||
@@ -16,4 +16,5 @@ futures = "0.3.5"
 | 
			
		||||
encoding_rs = "0.8.23"
 | 
			
		||||
percent-encoding = "2.1.0"
 | 
			
		||||
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 api_client;
 | 
			
		||||
 | 
			
		||||
pub mod user;
 | 
			
		||||
pub mod user;
 | 
			
		||||
pub mod user_token;
 | 
			
		||||
@@ -1,9 +1,12 @@
 | 
			
		||||
/// User information
 | 
			
		||||
///
 | 
			
		||||
/// @author Pierre Hubert
 | 
			
		||||
///! User information
 | 
			
		||||
///!
 | 
			
		||||
///! @author Pierre Hubert
 | 
			
		||||
 | 
			
		||||
pub type UserID = i64;
 | 
			
		||||
 | 
			
		||||
#[derive(Debug)]
 | 
			
		||||
pub struct User {
 | 
			
		||||
    pub id: i64,
 | 
			
		||||
    pub id: UserID,
 | 
			
		||||
    pub email: String,
 | 
			
		||||
    pub password: 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
 | 
			
		||||
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
 | 
			
		||||
pub const USERS_TABLE : &str = "utilisateurs";
 | 
			
		||||
@@ -1,6 +1,11 @@
 | 
			
		||||
use crate::data::api_client::APIClient;
 | 
			
		||||
use crate::data::error::ResultBoxError;
 | 
			
		||||
use crate::helpers::user_helper;
 | 
			
		||||
use crate::data::error::{ExecError, ResultBoxError};
 | 
			
		||||
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
 | 
			
		||||
///
 | 
			
		||||
@@ -13,9 +18,49 @@ use crate::helpers::user_helper;
 | 
			
		||||
pub fn login_user(email: &str, password: &str, client: &APIClient) -> ResultBoxError<String> {
 | 
			
		||||
    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::error::{ExecError, ResultBoxError};
 | 
			
		||||
use std::collections::HashMap;
 | 
			
		||||
 | 
			
		||||
/// Database access helper
 | 
			
		||||
///
 | 
			
		||||
@@ -224,4 +225,62 @@ pub fn query<E, F: Fn(&RowResult) -> ProcessRowResult<E>>(info: QueryInfo, proce
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    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;
 | 
			
		||||
 | 
			
		||||
use crate::data::error::{ResultBoxError, ExecError};
 | 
			
		||||
use rand::{thread_rng, Rng};
 | 
			
		||||
use rand::distributions::Alphanumeric;
 | 
			
		||||
 | 
			
		||||
/// Generate a new sha1 string
 | 
			
		||||
///
 | 
			
		||||
@@ -44,4 +46,20 @@ pub fn crypt_pass(pass: &str) -> ResultBoxError<String> {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    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