1
0
mirror of https://gitlab.com/comunic/comunicapiv3 synced 2024-11-22 13:29:21 +00:00

Can login user

This commit is contained in:
Pierre HUBERT 2020-05-24 16:35:54 +02:00
parent 6f6cd550ea
commit f0cf3202f4
9 changed files with 153 additions and 11 deletions

1
Cargo.lock generated
View File

@ -514,6 +514,7 @@ dependencies = [
"mailchecker",
"mysql",
"percent-encoding",
"rand",
"serde",
"sha1",
"yaml-rust",

View File

@ -17,3 +17,4 @@ encoding_rs = "0.8.23"
percent-encoding = "2.1.0"
mailchecker = "3.3.6"
sha1 = "0.6.0"
rand = "0.7.3"

View File

@ -5,3 +5,4 @@ pub mod http_request_handler;
pub mod api_client;
pub mod user;
pub mod user_token;

View File

@ -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
View 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
}

View File

@ -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";

View File

@ -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
println!("{:#?}", user);
Ok("d".to_string())
// Validate user password
let password = crypt_pass(password)?;
if !user.password.eq(&password) {
return Err(ExecError::boxed_new("The user gave an invalid password!"));
}
// 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);
}
// 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")?,
})
},
)
}

View File

@ -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
///
@ -225,3 +226,61 @@ 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(())
}

View File

@ -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
///
@ -45,3 +47,19 @@ 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()
}