mirror of
				https://gitlab.com/comunic/comunicapiv3
				synced 2025-11-04 09:34:04 +00:00 
			
		
		
		
	Upgrade user tokens system
This commit is contained in:
		@@ -39,9 +39,9 @@ CREATE TABLE `commentaires` (
 | 
				
			|||||||
  PRIMARY KEY (`ID`)
 | 
					  PRIMARY KEY (`ID`)
 | 
				
			||||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
 | 
					) ENGINE=InnoDB DEFAULT CHARSET=latin1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
DROP TABLE IF EXISTS `comunic_client`;
 | 
					DROP TABLE IF EXISTS `comunic_clients`;
 | 
				
			||||||
CREATE TABLE `comunic_client` (
 | 
					CREATE TABLE `comunic_clients` (
 | 
				
			||||||
  `ID` INT NOT NULL AUTO_INCREMENT,
 | 
					  `id` INT NOT NULL AUTO_INCREMENT,
 | 
				
			||||||
  `name` VARCHAR(45) NOT NULL,
 | 
					  `name` VARCHAR(45) NOT NULL,
 | 
				
			||||||
  `domain` VARCHAR(45) NULL COMMENT 'Use to check Referer & define Access-Control-Allow-Origin',
 | 
					  `domain` VARCHAR(45) NULL COMMENT 'Use to check Referer & define Access-Control-Allow-Origin',
 | 
				
			||||||
  `comment` VARCHAR(45) NULL COMMENT 'Information about the client',
 | 
					  `comment` VARCHAR(45) NULL COMMENT 'Information about the client',
 | 
				
			||||||
@@ -49,10 +49,11 @@ CREATE TABLE `comunic_client` (
 | 
				
			|||||||
  PRIMARY KEY (`ID`));
 | 
					  PRIMARY KEY (`ID`));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
DROP TABLE IF EXISTS `comunic_user_access_token`;
 | 
					DROP TABLE IF EXISTS `comunic_user_access_tokens`;
 | 
				
			||||||
CREATE TABLE `comunic_user_access_token` (
 | 
					CREATE TABLE `comunic_user_access_tokens` (
 | 
				
			||||||
  `id` INT NOT NULL AUTO_INCREMENT,
 | 
					  `id` INT NOT NULL AUTO_INCREMENT,
 | 
				
			||||||
  `client_id` INT NOT NULL,
 | 
					  `client_id` INT NOT NULL,
 | 
				
			||||||
 | 
					  `user_id` INT NOT NULL,
 | 
				
			||||||
  `token` VARCHAR(255) NOT NULL,
 | 
					  `token` VARCHAR(255) NOT NULL,
 | 
				
			||||||
  `last_refresh` INT NOT NULL,
 | 
					  `last_refresh` INT NOT NULL,
 | 
				
			||||||
  `timeout` INT NOT NULL,
 | 
					  `timeout` INT NOT NULL,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,3 +4,20 @@ DROP TABLE IF EXISTS `comunic_api_users_tokens`;
 | 
				
			|||||||
DROP TABLE IF EXISTS `comunic_api_services_tokens`;
 | 
					DROP TABLE IF EXISTS `comunic_api_services_tokens`;
 | 
				
			||||||
DROP TABLE IF EXISTS `comunic_calls_members`;
 | 
					DROP TABLE IF EXISTS `comunic_calls_members`;
 | 
				
			||||||
DROP TABLE IF EXISTS `comunic_calls`;
 | 
					DROP TABLE IF EXISTS `comunic_calls`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					CREATE TABLE `comunic_clients` (
 | 
				
			||||||
 | 
					  `id` INT NOT NULL AUTO_INCREMENT,
 | 
				
			||||||
 | 
					  `name` VARCHAR(45) NOT NULL,
 | 
				
			||||||
 | 
					  `domain` VARCHAR(45) NULL COMMENT 'Use to check Referer & define Access-Control-Allow-Origin',
 | 
				
			||||||
 | 
					  `comment` VARCHAR(45) NULL COMMENT 'Information about the client',
 | 
				
			||||||
 | 
					  `default_expiration_time` INT GENERATED ALWAYS AS (2592000)  COMMENT '2592000 = 1 month',
 | 
				
			||||||
 | 
					  PRIMARY KEY (`ID`));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					CREATE TABLE `comunic_user_access_tokens` (
 | 
				
			||||||
 | 
					  `id` INT NOT NULL AUTO_INCREMENT,
 | 
				
			||||||
 | 
					  `client_id` INT NOT NULL,
 | 
				
			||||||
 | 
					  `user_id` INT NOT NULL,
 | 
				
			||||||
 | 
					  `token` VARCHAR(255) NOT NULL,
 | 
				
			||||||
 | 
					  `last_refresh` INT NOT NULL,
 | 
				
			||||||
 | 
					  `timeout` INT NOT NULL,
 | 
				
			||||||
 | 
					  PRIMARY KEY (`id`));
 | 
				
			||||||
@@ -9,10 +9,10 @@ use std::time::Duration;
 | 
				
			|||||||
/// The name of the tables
 | 
					/// The name of the tables
 | 
				
			||||||
pub mod database_tables_names {
 | 
					pub mod database_tables_names {
 | 
				
			||||||
    /// API services tokens table
 | 
					    /// API services tokens table
 | 
				
			||||||
    pub const SERVICES_TABLES: &str = "comunic_api_services_tokens";
 | 
					    pub const CLIENTS_TABLE: &str = "comunic_clients";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// User access tokens table
 | 
					    /// User access tokens table
 | 
				
			||||||
    pub const USER_ACCESS_TOKENS_TABLE: &str = "comunic_api_users_tokens";
 | 
					    pub const USER_ACCESS_TOKENS_TABLE: &str = "comunic_user_access_tokens";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// User table
 | 
					    /// User table
 | 
				
			||||||
    pub const USERS_TABLE: &str = "utilisateurs";
 | 
					    pub const USERS_TABLE: &str = "utilisateurs";
 | 
				
			||||||
@@ -109,3 +109,6 @@ pub const SUPPORTED_LANGUAGES: &'static [&'static str] = &["en", "fr"];
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/// Interval at which last active time of user should be recorded
 | 
					/// Interval at which last active time of user should be recorded
 | 
				
			||||||
pub const USER_LAST_ACTIVITY_REFRESH: Duration = Duration::from_secs(60);
 | 
					pub const USER_LAST_ACTIVITY_REFRESH: Duration = Duration::from_secs(60);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Interval at which last activity of an access token should be recorded
 | 
				
			||||||
 | 
					pub const USER_ACCESS_TOKEN_ACTIVITY_REFRESH: Duration = Duration::from_secs(60*60);
 | 
				
			||||||
@@ -86,10 +86,9 @@ pub fn login_user(request: &mut HttpRequestHandler) -> RequestResult {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/// Sign out user
 | 
					/// Sign out user
 | 
				
			||||||
pub fn logout_user(request: &mut HttpRequestHandler) -> RequestResult {
 | 
					pub fn logout_user(request: &mut HttpRequestHandler) -> RequestResult {
 | 
				
			||||||
    account_helper::destroy_login_tokens(
 | 
					    if let Some(token) = request.user_access_token() {
 | 
				
			||||||
        &request.user_id()?,
 | 
					        account_helper::destroy_login_tokens(token)?;
 | 
				
			||||||
        request.api_client(),
 | 
					    }
 | 
				
			||||||
    )?;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    request.success("User disconnected.")
 | 
					    request.success("User disconnected.")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -50,7 +50,7 @@ impl UserWsRequestHandler {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        let mut found = false;
 | 
					        let mut found = false;
 | 
				
			||||||
        user_ws_controller::foreach_connection(|p| {
 | 
					        user_ws_controller::foreach_connection(|p| {
 | 
				
			||||||
            if !found && p.user_id == peer_id && p.is_having_call_with_conversation(call_id) {
 | 
					            if !found && p.user_id() == peer_id && p.is_having_call_with_conversation(call_id) {
 | 
				
			||||||
                found = true;
 | 
					                found = true;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -148,7 +148,7 @@ pub fn join_call(r: &mut UserWsRequestHandler) -> RequestResult {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    // Remove any other active connection to current call of current user
 | 
					    // Remove any other active connection to current call of current user
 | 
				
			||||||
    user_ws_controller::foreach_connection(|conn| {
 | 
					    user_ws_controller::foreach_connection(|conn| {
 | 
				
			||||||
        if &conn.user_id != r.user_id_ref()? || conn.session.eq(&r.get_conn().session) {
 | 
					        if conn.user_id() != r.user_id_ref()? || conn.session.eq(&r.get_conn().session) {
 | 
				
			||||||
            return Ok(());
 | 
					            return Ok(());
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -197,7 +197,7 @@ pub fn get_members_list(r: &mut UserWsRequestHandler) -> RequestResult {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    user_ws_controller::foreach_connection(|conn| {
 | 
					    user_ws_controller::foreach_connection(|conn| {
 | 
				
			||||||
        if conn.is_having_call_with_conversation(&conv_id) {
 | 
					        if conn.is_having_call_with_conversation(&conv_id) {
 | 
				
			||||||
            list.push(CallMemberInfo::new(&conn.user_id, &conn.active_call.as_ref().unwrap()));
 | 
					            list.push(CallMemberInfo::new(conn.user_id(), &conn.active_call.as_ref().unwrap()));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Ok(())
 | 
					        Ok(())
 | 
				
			||||||
@@ -297,7 +297,7 @@ pub fn mark_user_ready(r: &mut UserWsRequestHandler) -> Res {
 | 
				
			|||||||
    r.update_call(|call| call.ready = true)?;
 | 
					    r.update_call(|call| call.ready = true)?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    user_ws_controller::send_message_to_specific_connections(
 | 
					    user_ws_controller::send_message_to_specific_connections(
 | 
				
			||||||
        |c| c.user_id != &user_id && c.is_having_call_with_conversation(&call_id),
 | 
					        |c| c.user_id() != &user_id && c.is_having_call_with_conversation(&call_id),
 | 
				
			||||||
        |_| UserWsMessage::no_id_message("call_peer_ready", CallPeerReadyAPI::new(&call_id, r.user_id_ref()?)),
 | 
					        |_| UserWsMessage::no_id_message("call_peer_ready", CallPeerReadyAPI::new(&call_id, r.user_id_ref()?)),
 | 
				
			||||||
        None::<fn(&_) -> _>,
 | 
					        None::<fn(&_) -> _>,
 | 
				
			||||||
    )?;
 | 
					    )?;
 | 
				
			||||||
@@ -335,7 +335,7 @@ pub fn stop_streaming(r: &mut UserWsRequestHandler) -> Res {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        // Notify all other users
 | 
					        // Notify all other users
 | 
				
			||||||
        user_ws_controller::send_message_to_specific_connections(
 | 
					        user_ws_controller::send_message_to_specific_connections(
 | 
				
			||||||
            |c| c.is_having_call_with_conversation(&call_id) && c.user_id != &user_id,
 | 
					            |c| c.is_having_call_with_conversation(&call_id) && c.user_id() != &user_id,
 | 
				
			||||||
            |_| UserWsMessage::no_id_message("call_peer_interrupted_streaming", CallPeerInterruptedStreamingAPI::new(&call_id, &user_id)),
 | 
					            |_| UserWsMessage::no_id_message("call_peer_interrupted_streaming", CallPeerInterruptedStreamingAPI::new(&call_id, &user_id)),
 | 
				
			||||||
            None::<fn(&_) -> _>,
 | 
					            None::<fn(&_) -> _>,
 | 
				
			||||||
        )?;
 | 
					        )?;
 | 
				
			||||||
@@ -362,17 +362,17 @@ pub fn make_user_leave_call(conv_id: &ConvID, connection: &UserWsConnection) ->
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    // Close main stream (sender)
 | 
					    // Close main stream (sender)
 | 
				
			||||||
    events_helper::propagate_event(&Event::CloseCallStream(&CloseCallStream {
 | 
					    events_helper::propagate_event(&Event::CloseCallStream(&CloseCallStream {
 | 
				
			||||||
        call_hash: gen_call_hash(&conv_id, &connection.user_id),
 | 
					        call_hash: gen_call_hash(&conv_id, connection.user_id()),
 | 
				
			||||||
        peer_id: None,
 | 
					        peer_id: None,
 | 
				
			||||||
    }))?;
 | 
					    }))?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Close receiver streams (other users streams)
 | 
					    // Close receiver streams (other users streams)
 | 
				
			||||||
    user_ws_controller::foreach_connection(
 | 
					    user_ws_controller::foreach_connection(
 | 
				
			||||||
        |peer_conn| {
 | 
					        |peer_conn| {
 | 
				
			||||||
            if peer_conn.is_having_call_with_conversation(conv_id) && &peer_conn.user_id != &connection.user_id {
 | 
					            if peer_conn.is_having_call_with_conversation(conv_id) && peer_conn.user_id() != connection.user_id() {
 | 
				
			||||||
                events_helper::propagate_event(&Event::CloseCallStream(&CloseCallStream {
 | 
					                events_helper::propagate_event(&Event::CloseCallStream(&CloseCallStream {
 | 
				
			||||||
                    call_hash: gen_call_hash(&conv_id, &peer_conn.user_id),
 | 
					                    call_hash: gen_call_hash(&conv_id, peer_conn.user_id()),
 | 
				
			||||||
                    peer_id: Some(connection.user_id.clone()),
 | 
					                    peer_id: Some(connection.user_id().clone()),
 | 
				
			||||||
                }))?;
 | 
					                }))?;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -381,7 +381,7 @@ pub fn make_user_leave_call(conv_id: &ConvID, connection: &UserWsConnection) ->
 | 
				
			|||||||
    )?;
 | 
					    )?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Create a notification
 | 
					    // Create a notification
 | 
				
			||||||
    events_helper::propagate_event(&Event::UserLeftCall(conv_id, &connection.user_id))?;
 | 
					    events_helper::propagate_event(&Event::UserLeftCall(conv_id, connection.user_id()))?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Ok(())
 | 
					    Ok(())
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -391,7 +391,7 @@ pub fn handle_event(e: &events_helper::Event) -> Res {
 | 
				
			|||||||
    match e {
 | 
					    match e {
 | 
				
			||||||
        Event::UserJoinedCall(conv_id, user_id) => {
 | 
					        Event::UserJoinedCall(conv_id, user_id) => {
 | 
				
			||||||
            user_ws_controller::send_message_to_specific_connections(
 | 
					            user_ws_controller::send_message_to_specific_connections(
 | 
				
			||||||
                |c| c.is_having_call_with_conversation(conv_id) && &c.user_id != user_id,
 | 
					                |c| c.is_having_call_with_conversation(conv_id) && c.user_id() != user_id,
 | 
				
			||||||
                |_| UserWsMessage::no_id_message("user_joined_call", JoinedCallMessage::new(conv_id, user_id)),
 | 
					                |_| UserWsMessage::no_id_message("user_joined_call", JoinedCallMessage::new(conv_id, user_id)),
 | 
				
			||||||
                None::<fn(&_) -> _>,
 | 
					                None::<fn(&_) -> _>,
 | 
				
			||||||
            )?;
 | 
					            )?;
 | 
				
			||||||
@@ -429,7 +429,7 @@ pub fn handle_event(e: &events_helper::Event) -> Res {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            user_ws_controller::send_message_to_specific_connections(
 | 
					            user_ws_controller::send_message_to_specific_connections(
 | 
				
			||||||
                |c| c.user_id == target_user && c.is_having_call_with_conversation(&call_id),
 | 
					                |c| c.user_id() == target_user && c.is_having_call_with_conversation(&call_id),
 | 
				
			||||||
                |_| UserWsMessage::no_id_message("new_call_signal", NewCallSignalAPI::new(&call_id, &peer_id, &msg.data)?),
 | 
					                |_| UserWsMessage::no_id_message("new_call_signal", NewCallSignalAPI::new(&call_id, &peer_id, &msg.data)?),
 | 
				
			||||||
                None::<fn(&_) -> _>,
 | 
					                None::<fn(&_) -> _>,
 | 
				
			||||||
            )?;
 | 
					            )?;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -94,7 +94,7 @@ pub fn handle_event(e: &events_helper::Event) -> Res {
 | 
				
			|||||||
                |c| c.posts.contains(&comment.post_id),
 | 
					                |c| c.posts.contains(&comment.post_id),
 | 
				
			||||||
                |c| UserWsMessage::no_id_message(
 | 
					                |c| UserWsMessage::no_id_message(
 | 
				
			||||||
                    "new_comment",
 | 
					                    "new_comment",
 | 
				
			||||||
                    CommentAPI::new(comment, &Some(c.user_id.clone()))?,
 | 
					                    CommentAPI::new(comment, &Some(c.user_id().clone()))?,
 | 
				
			||||||
                ),
 | 
					                ),
 | 
				
			||||||
                None::<fn(&_) -> _>,
 | 
					                None::<fn(&_) -> _>,
 | 
				
			||||||
            )?;
 | 
					            )?;
 | 
				
			||||||
@@ -105,7 +105,7 @@ pub fn handle_event(e: &events_helper::Event) -> Res {
 | 
				
			|||||||
                |c| c.posts.contains(&comment.post_id),
 | 
					                |c| c.posts.contains(&comment.post_id),
 | 
				
			||||||
                |c| UserWsMessage::no_id_message(
 | 
					                |c| UserWsMessage::no_id_message(
 | 
				
			||||||
                    "comment_updated",
 | 
					                    "comment_updated",
 | 
				
			||||||
                    CommentAPI::new(comment, &Some(c.user_id.clone()))?,
 | 
					                    CommentAPI::new(comment, &Some(c.user_id().clone()))?,
 | 
				
			||||||
                ),
 | 
					                ),
 | 
				
			||||||
                None::<fn(&_) -> _>,
 | 
					                None::<fn(&_) -> _>,
 | 
				
			||||||
            )?;
 | 
					            )?;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -362,7 +362,7 @@ pub fn handle_event(e: &events_helper::Event) -> Res {
 | 
				
			|||||||
            user_ws_controller::send_message_to_specific_connections(
 | 
					            user_ws_controller::send_message_to_specific_connections(
 | 
				
			||||||
                |f| f.conversations.contains(&msg.conv_id),
 | 
					                |f| f.conversations.contains(&msg.conv_id),
 | 
				
			||||||
                |_| UserWsMessage::no_id_message("new_conv_message", ConversationMessageAPI::new(msg)),
 | 
					                |_| UserWsMessage::no_id_message("new_conv_message", ConversationMessageAPI::new(msg)),
 | 
				
			||||||
                Some(|conn: &UserWsConnection| conversations_helper::mark_user_seen(msg.conv_id, &conn.user_id)),
 | 
					                Some(|conn: &UserWsConnection| conversations_helper::mark_user_seen(msg.conv_id, conn.user_id())),
 | 
				
			||||||
            )?;
 | 
					            )?;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -15,12 +15,12 @@ use crate::api_data::res_get_ws_token::ResGetWsToken;
 | 
				
			|||||||
use crate::constants::{USER_LAST_ACTIVITY_REFRESH, WS_ACCESS_TOKEN_LENGTH};
 | 
					use crate::constants::{USER_LAST_ACTIVITY_REFRESH, WS_ACCESS_TOKEN_LENGTH};
 | 
				
			||||||
use crate::controllers::user_ws_controller::ws_connections_list::{add_connection, find_connection, get_ws_connections_list, remove_connection};
 | 
					use crate::controllers::user_ws_controller::ws_connections_list::{add_connection, find_connection, get_ws_connections_list, remove_connection};
 | 
				
			||||||
use crate::controllers::user_ws_routes::find_user_ws_route;
 | 
					use crate::controllers::user_ws_routes::find_user_ws_route;
 | 
				
			||||||
use crate::data::api_client::APIClient;
 | 
					 | 
				
			||||||
use crate::data::base_request_handler::BaseRequestHandler;
 | 
					use crate::data::base_request_handler::BaseRequestHandler;
 | 
				
			||||||
use crate::data::config::conf;
 | 
					use crate::data::config::conf;
 | 
				
			||||||
use crate::data::error::{ExecError, Res, ResultBoxError};
 | 
					use crate::data::error::{ExecError, Res, ResultBoxError};
 | 
				
			||||||
use crate::data::http_request_handler::HttpRequestHandler;
 | 
					use crate::data::http_request_handler::HttpRequestHandler;
 | 
				
			||||||
use crate::data::user::UserID;
 | 
					use crate::data::user::UserID;
 | 
				
			||||||
 | 
					use crate::data::user_token::UserAccessToken;
 | 
				
			||||||
use crate::data::user_ws_connection::UserWsConnection;
 | 
					use crate::data::user_ws_connection::UserWsConnection;
 | 
				
			||||||
use crate::data::user_ws_message::UserWsMessage;
 | 
					use crate::data::user_ws_message::UserWsMessage;
 | 
				
			||||||
use crate::data::user_ws_request_handler::{UserWsRequestHandler, UserWsResponseType};
 | 
					use crate::data::user_ws_request_handler::{UserWsRequestHandler, UserWsResponseType};
 | 
				
			||||||
@@ -41,15 +41,14 @@ mod ws_tokens_list {
 | 
				
			|||||||
    use std::sync::Mutex;
 | 
					    use std::sync::Mutex;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    use crate::constants::WS_ACCESS_TOKEN_LIFETIME;
 | 
					    use crate::constants::WS_ACCESS_TOKEN_LIFETIME;
 | 
				
			||||||
    use crate::data::user::UserID;
 | 
					    use crate::data::user_token::UserAccessToken;
 | 
				
			||||||
    use crate::utils::date_utils::time;
 | 
					    use crate::utils::date_utils::time;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #[derive(Debug)]
 | 
					    #[derive(Debug)]
 | 
				
			||||||
    pub struct WsToken {
 | 
					    pub struct WsToken {
 | 
				
			||||||
        pub time: u64,
 | 
					        pub time: u64,
 | 
				
			||||||
        pub client_id: u32,
 | 
					        pub user_token: UserAccessToken,
 | 
				
			||||||
        pub user_id: UserID,
 | 
					        pub ws_token: String,
 | 
				
			||||||
        pub token: String,
 | 
					 | 
				
			||||||
        pub incognito: bool,
 | 
					        pub incognito: bool,
 | 
				
			||||||
        pub remote_ip: String,
 | 
					        pub remote_ip: String,
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -89,7 +88,7 @@ mod ws_tokens_list {
 | 
				
			|||||||
        let list = get_list();
 | 
					        let list = get_list();
 | 
				
			||||||
        let mut list = list.lock().unwrap();
 | 
					        let mut list = list.lock().unwrap();
 | 
				
			||||||
        for i in 0..list.len() {
 | 
					        for i in 0..list.len() {
 | 
				
			||||||
            if list[i].token == t {
 | 
					            if list[i].ws_token == t {
 | 
				
			||||||
                return Some(list.remove(i));
 | 
					                return Some(list.remove(i));
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -178,10 +177,9 @@ pub fn get_token(r: &mut HttpRequestHandler) -> ResultBoxError {
 | 
				
			|||||||
    let access_token = rand_str(WS_ACCESS_TOKEN_LENGTH);
 | 
					    let access_token = rand_str(WS_ACCESS_TOKEN_LENGTH);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let token = ws_tokens_list::WsToken {
 | 
					    let token = ws_tokens_list::WsToken {
 | 
				
			||||||
        user_id: r.user_id()?,
 | 
					        user_token: r.some_or_internal_error(r.user_access_token().cloned(), "No access token!")?,
 | 
				
			||||||
        client_id: r.api_client().id,
 | 
					 | 
				
			||||||
        time: time(),
 | 
					        time: time(),
 | 
				
			||||||
        token: access_token.to_string(),
 | 
					        ws_token: access_token.to_string(),
 | 
				
			||||||
        incognito: r.post_bool_opt("incognito", false),
 | 
					        incognito: r.post_bool_opt("incognito", false),
 | 
				
			||||||
        remote_ip: r.remote_ip(),
 | 
					        remote_ip: r.remote_ip(),
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
@@ -195,10 +193,8 @@ pub fn get_token(r: &mut HttpRequestHandler) -> ResultBoxError {
 | 
				
			|||||||
pub struct WsSession {
 | 
					pub struct WsSession {
 | 
				
			||||||
    // NOTE : apart from hb, the values here won't change !
 | 
					    // NOTE : apart from hb, the values here won't change !
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    user_id: UserID,
 | 
					    // Information about user connection
 | 
				
			||||||
 | 
					    user_token: UserAccessToken,
 | 
				
			||||||
    // Client used for the connection
 | 
					 | 
				
			||||||
    client_id: u32,
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Remote IP address
 | 
					    // Remote IP address
 | 
				
			||||||
    remote_ip: String,
 | 
					    remote_ip: String,
 | 
				
			||||||
@@ -232,16 +228,16 @@ impl WsSession {
 | 
				
			|||||||
        });
 | 
					        });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// helper method that update user last activity at every specified amount of time
 | 
					    /// Helper method that update user last activity at every specified amount of time
 | 
				
			||||||
    fn user_activity(&self, ctx: &mut actix_web_actors::ws::WebsocketContext<Self>) {
 | 
					    fn user_activity(&self, ctx: &mut actix_web_actors::ws::WebsocketContext<Self>) {
 | 
				
			||||||
        if !self.incognito && account_helper::update_last_activity(&self.user_id).is_err() {
 | 
					        if !self.incognito && account_helper::update_last_activity(&self.user_token.user_id).is_err() {
 | 
				
			||||||
            eprintln!("Failed to do initial refresh of last activity for user {} !", self.user_id.id());
 | 
					            eprintln!("Failed to do initial refresh of last activity for user {} !", self.user_token.user_id.id());
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        ctx.run_interval(USER_LAST_ACTIVITY_REFRESH, |_, ctx| {
 | 
					        ctx.run_interval(USER_LAST_ACTIVITY_REFRESH, |_, ctx| {
 | 
				
			||||||
            if let Some(conn) = find_connection(ctx.address()) {
 | 
					            if let Some(conn) = find_connection(ctx.address()) {
 | 
				
			||||||
                if !conn.incognito && account_helper::update_last_activity(&conn.user_id).is_err() {
 | 
					                if !conn.incognito && account_helper::update_last_activity(conn.user_id()).is_err() {
 | 
				
			||||||
                    eprintln!("Failed to refresh last activity for user {} !", conn.user_id.id());
 | 
					                    eprintln!("Failed to refresh last activity for user {} !", conn.user_id().id());
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
@@ -312,8 +308,7 @@ impl Actor for WsSession {
 | 
				
			|||||||
        self.user_activity(ctx);
 | 
					        self.user_activity(ctx);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        add_connection(UserWsConnection {
 | 
					        add_connection(UserWsConnection {
 | 
				
			||||||
            user_id: self.user_id.clone(),
 | 
					            user_token: self.user_token.clone(),
 | 
				
			||||||
            client_id: self.client_id,
 | 
					 | 
				
			||||||
            remote_ip: self.remote_ip.clone(),
 | 
					            remote_ip: self.remote_ip.clone(),
 | 
				
			||||||
            session: ctx.address(),
 | 
					            session: ctx.address(),
 | 
				
			||||||
            incognito: self.incognito,
 | 
					            incognito: self.incognito,
 | 
				
			||||||
@@ -445,10 +440,9 @@ pub async fn ws_route(
 | 
				
			|||||||
    actix_web_actors::ws::start(
 | 
					    actix_web_actors::ws::start(
 | 
				
			||||||
        WsSession {
 | 
					        WsSession {
 | 
				
			||||||
            remote_ip: token.remote_ip,
 | 
					            remote_ip: token.remote_ip,
 | 
				
			||||||
            user_id: token.user_id,
 | 
					            user_token: token.user_token,
 | 
				
			||||||
            hb: std::time::Instant::now(),
 | 
					            hb: std::time::Instant::now(),
 | 
				
			||||||
            incognito: token.incognito,
 | 
					            incognito: token.incognito,
 | 
				
			||||||
            client_id: token.client_id,
 | 
					 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        &req,
 | 
					        &req,
 | 
				
			||||||
        stream,
 | 
					        stream,
 | 
				
			||||||
@@ -467,7 +461,7 @@ pub fn send_message_to_users(msg: &UserWsMessage, users: &Vec<UserID>) -> Res {
 | 
				
			|||||||
        .lock()
 | 
					        .lock()
 | 
				
			||||||
        .unwrap()
 | 
					        .unwrap()
 | 
				
			||||||
        .iter()
 | 
					        .iter()
 | 
				
			||||||
        .filter(|f| users.contains(&f.user_id))
 | 
					        .filter(|f| users.contains(f.user_id()))
 | 
				
			||||||
        .map(|f| f.session.clone())
 | 
					        .map(|f| f.session.clone())
 | 
				
			||||||
        .collect::<Vec<Addr<WsSession>>>();
 | 
					        .collect::<Vec<Addr<WsSession>>>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -484,7 +478,7 @@ pub fn send_message_to_user(msg: &UserWsMessage, user: &UserID) -> Res {
 | 
				
			|||||||
        .lock()
 | 
					        .lock()
 | 
				
			||||||
        .unwrap()
 | 
					        .unwrap()
 | 
				
			||||||
        .iter()
 | 
					        .iter()
 | 
				
			||||||
        .filter(|f| user == &f.user_id)
 | 
					        .filter(|f| user == f.user_id())
 | 
				
			||||||
        .map(|f| f.session.clone())
 | 
					        .map(|f| f.session.clone())
 | 
				
			||||||
        .collect::<Vec<Addr<WsSession>>>();
 | 
					        .collect::<Vec<Addr<WsSession>>>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -527,22 +521,22 @@ pub fn send_message_to_specific_connections<F, M, A>(filter: F, msg_generator: M
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/// Check out whether user is connected or not
 | 
					/// Check out whether user is connected or not
 | 
				
			||||||
pub fn is_user_connected(user_id: &UserID) -> bool {
 | 
					pub fn is_user_connected(user_id: &UserID) -> bool {
 | 
				
			||||||
    get_ws_connections_list().lock().unwrap().iter().any(|c| &c.user_id == user_id)
 | 
					    get_ws_connections_list().lock().unwrap().iter().any(|c| c.user_id() == user_id)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Check out whether user is connected or not and has at list one not incognito connection
 | 
					/// Check out whether user is connected or not and has at list one not incognito connection
 | 
				
			||||||
pub fn is_user_connected_not_incognito(user_id: &UserID) -> bool {
 | 
					pub fn is_user_connected_not_incognito(user_id: &UserID) -> bool {
 | 
				
			||||||
    get_ws_connections_list().lock().unwrap().iter().any(|c| &c.user_id == user_id && !c.incognito)
 | 
					    get_ws_connections_list().lock().unwrap().iter().any(|c| c.user_id() == user_id && !c.incognito)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Disconnect a user from all the WebSockets of a given client
 | 
					/// Disconnect a user from all the WebSockets of a given access token
 | 
				
			||||||
pub fn disconnect_user_from_client(user_id: &UserID, client: &APIClient) -> Res {
 | 
					pub fn disconnect_from_user_token(token: &UserAccessToken) -> Res {
 | 
				
			||||||
    let connections = get_ws_connections_list()
 | 
					    let connections = get_ws_connections_list()
 | 
				
			||||||
        .lock()
 | 
					        .lock()
 | 
				
			||||||
        .unwrap()
 | 
					        .unwrap()
 | 
				
			||||||
        .iter()
 | 
					        .iter()
 | 
				
			||||||
        .filter(|f| &f.user_id == user_id && f.client_id == client.id)
 | 
					        .filter(|f| &f.user_token == token)
 | 
				
			||||||
        .map(|f| f.session.clone())
 | 
					        .map(|f| f.session.clone())
 | 
				
			||||||
        .collect::<Vec<Addr<WsSession>>>();
 | 
					        .collect::<Vec<Addr<WsSession>>>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -559,7 +553,7 @@ pub fn disconnect_user_from_all_sockets(user_id: &UserID) -> Res {
 | 
				
			|||||||
        .lock()
 | 
					        .lock()
 | 
				
			||||||
        .unwrap()
 | 
					        .unwrap()
 | 
				
			||||||
        .iter()
 | 
					        .iter()
 | 
				
			||||||
        .filter(|f| &f.user_id == user_id)
 | 
					        .filter(|f| f.user_id() == user_id)
 | 
				
			||||||
        .map(|f| f.session.clone())
 | 
					        .map(|f| f.session.clone())
 | 
				
			||||||
        .collect::<Vec<Addr<WsSession>>>();
 | 
					        .collect::<Vec<Addr<WsSession>>>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -585,8 +579,8 @@ pub fn foreach_connection<F>(mut f: F) -> Res
 | 
				
			|||||||
/// Events handler
 | 
					/// Events handler
 | 
				
			||||||
pub fn handle_event(e: &events_helper::Event) -> Res {
 | 
					pub fn handle_event(e: &events_helper::Event) -> Res {
 | 
				
			||||||
    match e {
 | 
					    match e {
 | 
				
			||||||
        Event::DestroyedLoginToken(user_id, client) => {
 | 
					        Event::DestroyedLoginToken(token) => {
 | 
				
			||||||
            disconnect_user_from_client(user_id, client)?;
 | 
					            disconnect_from_user_token(token)?;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        _ => {}
 | 
					        _ => {}
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,11 +1,11 @@
 | 
				
			|||||||
/// API client information
 | 
					/// API client information
 | 
				
			||||||
///
 | 
					///
 | 
				
			||||||
/// @author Pierre HUBERT
 | 
					/// @author Pierre HUBERT
 | 
				
			||||||
 | 
					 | 
				
			||||||
#[derive(Debug)]
 | 
					#[derive(Debug)]
 | 
				
			||||||
pub struct APIClient {
 | 
					pub struct APIClient {
 | 
				
			||||||
    pub id: u32,
 | 
					    pub id: u64,
 | 
				
			||||||
    pub name: String,
 | 
					    pub name: String,
 | 
				
			||||||
    pub token: String,
 | 
					 | 
				
			||||||
    pub domain: Option<String>,
 | 
					    pub domain: Option<String>,
 | 
				
			||||||
 | 
					    pub comment: Option<String>,
 | 
				
			||||||
 | 
					    pub default_expiration_time: u64,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -15,11 +15,12 @@ use crate::controllers::routes::RequestResult;
 | 
				
			|||||||
use crate::data::comment::Comment;
 | 
					use crate::data::comment::Comment;
 | 
				
			||||||
use crate::data::conversation::ConvID;
 | 
					use crate::data::conversation::ConvID;
 | 
				
			||||||
use crate::data::custom_emoji::CustomEmoji;
 | 
					use crate::data::custom_emoji::CustomEmoji;
 | 
				
			||||||
use crate::data::error::{ExecError, ResultBoxError};
 | 
					use crate::data::error::{ExecError, Res, ResultBoxError};
 | 
				
			||||||
use crate::data::group::GroupAccessLevel;
 | 
					use crate::data::group::GroupAccessLevel;
 | 
				
			||||||
use crate::data::group_id::GroupID;
 | 
					use crate::data::group_id::GroupID;
 | 
				
			||||||
use crate::data::post::{Post, PostAccessLevel};
 | 
					use crate::data::post::{Post, PostAccessLevel};
 | 
				
			||||||
use crate::data::user::UserID;
 | 
					use crate::data::user::UserID;
 | 
				
			||||||
 | 
					use crate::data::user_token::UserAccessToken;
 | 
				
			||||||
use crate::helpers::{account_helper, comments_helper, conversations_helper, custom_emojies_helper, friends_helper, groups_helper, posts_helper, user_helper, virtual_directory_helper};
 | 
					use crate::helpers::{account_helper, comments_helper, conversations_helper, custom_emojies_helper, friends_helper, groups_helper, posts_helper, user_helper, virtual_directory_helper};
 | 
				
			||||||
use crate::helpers::virtual_directory_helper::VirtualDirType;
 | 
					use crate::helpers::virtual_directory_helper::VirtualDirType;
 | 
				
			||||||
use crate::utils::pdf_utils::is_valid_pdf;
 | 
					use crate::utils::pdf_utils::is_valid_pdf;
 | 
				
			||||||
@@ -58,8 +59,13 @@ pub trait BaseRequestHandler {
 | 
				
			|||||||
    /// Get remote IP address
 | 
					    /// Get remote IP address
 | 
				
			||||||
    fn remote_ip(&self) -> String;
 | 
					    fn remote_ip(&self) -> String;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Current user access token
 | 
				
			||||||
 | 
					    fn user_access_token(&self) -> Option<&UserAccessToken>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Current user ID
 | 
					    /// Current user ID
 | 
				
			||||||
    fn user_id_opt_ref(&self) -> Option<&UserID>;
 | 
					    fn user_id_opt_ref(&self) -> Option<&UserID> {
 | 
				
			||||||
 | 
					        self.user_access_token().map(|u| &u.user_id)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Success message
 | 
					    /// Success message
 | 
				
			||||||
@@ -144,6 +150,17 @@ pub trait BaseRequestHandler {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Unwrap an option, returning an error if none is returned
 | 
				
			||||||
 | 
					    fn some_or_internal_error<E>(&mut self, opt: Option<E>, msg: &str) -> Res<E> {
 | 
				
			||||||
 | 
					        match opt {
 | 
				
			||||||
 | 
					            None => {
 | 
				
			||||||
 | 
					                self.internal_error(ExecError::boxed_new(msg))?;
 | 
				
			||||||
 | 
					                unreachable!()
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            Some(e) => Ok(e)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Get a user ID, if available
 | 
					    /// Get a user ID, if available
 | 
				
			||||||
    fn user_id_opt(&self) -> Option<UserID> {
 | 
					    fn user_id_opt(&self) -> Option<UserID> {
 | 
				
			||||||
@@ -189,6 +206,18 @@ pub trait BaseRequestHandler {
 | 
				
			|||||||
        self.post_string_opt(name, 1, true)
 | 
					        self.post_string_opt(name, 1, true)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Get a post string with a given name. If the value is not found, attempt to get the value
 | 
				
			||||||
 | 
					    /// with another name
 | 
				
			||||||
 | 
					    ///
 | 
				
			||||||
 | 
					    /// This function is useful to upgrade system
 | 
				
			||||||
 | 
					    fn post_string_with_fallback(&mut self, name: &str, fallback: &str) -> Res<String> {
 | 
				
			||||||
 | 
					        if self.has_post_parameter(name) {
 | 
				
			||||||
 | 
					            self.post_string(name)
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            self.post_string(fallback)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Get a post string, specifying minimum length
 | 
					    /// Get a post string, specifying minimum length
 | 
				
			||||||
    fn post_string_opt(&mut self, name: &str, min_length: usize, required: bool)
 | 
					    fn post_string_opt(&mut self, name: &str, min_length: usize, required: bool)
 | 
				
			||||||
                       -> ResultBoxError<String> {
 | 
					                       -> ResultBoxError<String> {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -11,8 +11,8 @@ use crate::controllers::routes::RequestResult;
 | 
				
			|||||||
use crate::data::api_client::APIClient;
 | 
					use crate::data::api_client::APIClient;
 | 
				
			||||||
use crate::data::base_request_handler::{BaseRequestHandler, RequestValue};
 | 
					use crate::data::base_request_handler::{BaseRequestHandler, RequestValue};
 | 
				
			||||||
use crate::data::config::conf;
 | 
					use crate::data::config::conf;
 | 
				
			||||||
use crate::data::error::ResultBoxError;
 | 
					use crate::data::error::{Res, ResultBoxError};
 | 
				
			||||||
use crate::data::user::UserID;
 | 
					use crate::data::user_token::UserAccessToken;
 | 
				
			||||||
use crate::helpers::{account_helper, api_helper};
 | 
					use crate::helpers::{account_helper, api_helper};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Http request handler
 | 
					/// Http request handler
 | 
				
			||||||
@@ -25,7 +25,7 @@ pub struct HttpRequestHandler {
 | 
				
			|||||||
    response: Option<web::HttpResponse>,
 | 
					    response: Option<web::HttpResponse>,
 | 
				
			||||||
    headers: HashMap<String, String>,
 | 
					    headers: HashMap<String, String>,
 | 
				
			||||||
    client: Option<APIClient>,
 | 
					    client: Option<APIClient>,
 | 
				
			||||||
    curr_user_id: Option<UserID>,
 | 
					    curr_user_token: Option<UserAccessToken>,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl HttpRequestHandler {
 | 
					impl HttpRequestHandler {
 | 
				
			||||||
@@ -37,7 +37,7 @@ impl HttpRequestHandler {
 | 
				
			|||||||
            response: None,
 | 
					            response: None,
 | 
				
			||||||
            headers: HashMap::new(),
 | 
					            headers: HashMap::new(),
 | 
				
			||||||
            client: None,
 | 
					            client: None,
 | 
				
			||||||
            curr_user_id: None,
 | 
					            curr_user_token: None,
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -78,11 +78,10 @@ impl HttpRequestHandler {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    /// Check API client tokens
 | 
					    /// Check API client tokens
 | 
				
			||||||
    pub fn check_client_token(&mut self) -> RequestResult {
 | 
					    pub fn check_client_token(&mut self) -> RequestResult {
 | 
				
			||||||
        let api_name = self.post_string("serviceName")?;
 | 
					        let client_name = self.post_string_with_fallback("client", "serviceName")?;
 | 
				
			||||||
        let api_token = self.post_string("serviceToken")?;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let client = self.ok_or_bad_request(
 | 
					        let client = self.ok_or_bad_request(
 | 
				
			||||||
            api_helper::get_client(&api_name, &api_token),
 | 
					            api_helper::get_client(&client_name),
 | 
				
			||||||
            "Client not recognized!",
 | 
					            "Client not recognized!",
 | 
				
			||||||
        )?;
 | 
					        )?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -111,13 +110,17 @@ impl HttpRequestHandler {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Check login token
 | 
					    /// Check login token
 | 
				
			||||||
    pub fn check_user_token(&mut self) -> RequestResult {
 | 
					    pub fn check_user_token(&mut self) -> Res {
 | 
				
			||||||
        let token = self.post_string("userToken1")?;
 | 
					        let token = self.post_string("userToken1")?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Find user
 | 
					        // Find user
 | 
				
			||||||
        match account_helper::get_user_by_login_token(&token, self.api_client()) {
 | 
					        match account_helper::find_user_by_login_token(&token, self.api_client()) {
 | 
				
			||||||
            Ok(id) => {
 | 
					            Ok(token) => {
 | 
				
			||||||
                self.curr_user_id = Some(id);
 | 
					                if token.need_refresh() {
 | 
				
			||||||
 | 
					                    account_helper::refresh_access_token(&token)?;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                self.curr_user_token = Some(token);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                Ok(())
 | 
					                Ok(())
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@@ -177,7 +180,7 @@ impl BaseRequestHandler for HttpRequestHandler {
 | 
				
			|||||||
        ip
 | 
					        ip
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn user_id_opt_ref(&self) -> Option<&UserID> {
 | 
					    fn user_access_token(&self) -> Option<&UserAccessToken> {
 | 
				
			||||||
        self.curr_user_id.as_ref()
 | 
					        self.curr_user_token.as_ref()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -50,6 +50,12 @@ impl PartialEq<&UserID> for UserID {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl PartialEq<UserID> for &UserID {
 | 
				
			||||||
 | 
					    fn eq(&self, other: &UserID) -> bool {
 | 
				
			||||||
 | 
					        self.0 == other.0
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Debug, PartialEq)]
 | 
					#[derive(Debug, PartialEq)]
 | 
				
			||||||
pub enum UserPageStatus {
 | 
					pub enum UserPageStatus {
 | 
				
			||||||
    OPEN,
 | 
					    OPEN,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,11 +1,29 @@
 | 
				
			|||||||
 | 
					use crate::constants::USER_ACCESS_TOKEN_ACTIVITY_REFRESH;
 | 
				
			||||||
use crate::data::user::UserID;
 | 
					use crate::data::user::UserID;
 | 
				
			||||||
 | 
					use crate::utils::date_utils::time;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// User access token information
 | 
					/// User access token information
 | 
				
			||||||
///
 | 
					///
 | 
				
			||||||
/// Author : Pierre Hubert
 | 
					/// Author : Pierre Hubert
 | 
				
			||||||
#[derive(Debug)]
 | 
					#[derive(Debug, Clone)]
 | 
				
			||||||
pub struct UserAccessToken {
 | 
					pub struct UserAccessToken {
 | 
				
			||||||
 | 
					    pub id: u64,
 | 
				
			||||||
 | 
					    pub client_id: u64,
 | 
				
			||||||
    pub user_id: UserID,
 | 
					    pub user_id: UserID,
 | 
				
			||||||
    pub client_id: u32,
 | 
					    pub token: String,
 | 
				
			||||||
    pub token: String
 | 
					    pub last_refresh: u64,
 | 
				
			||||||
 | 
					    pub timeout: u64,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl UserAccessToken {
 | 
				
			||||||
 | 
					    /// Check out whether access token should be refreshed
 | 
				
			||||||
 | 
					    pub fn need_refresh(&self) -> bool {
 | 
				
			||||||
 | 
					        self.last_refresh + USER_ACCESS_TOKEN_ACTIVITY_REFRESH.as_secs() < time()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl PartialEq<UserAccessToken> for UserAccessToken {
 | 
				
			||||||
 | 
					    fn eq(&self, other: &UserAccessToken) -> bool {
 | 
				
			||||||
 | 
					        self.id == other.id
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -4,6 +4,7 @@ use crate::controllers::user_ws_controller::WsSession;
 | 
				
			|||||||
use crate::data::conversation::ConvID;
 | 
					use crate::data::conversation::ConvID;
 | 
				
			||||||
use crate::data::post::PostID;
 | 
					use crate::data::post::PostID;
 | 
				
			||||||
use crate::data::user::UserID;
 | 
					use crate::data::user::UserID;
 | 
				
			||||||
 | 
					use crate::data::user_token::UserAccessToken;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Clone, Debug)]
 | 
					#[derive(Clone, Debug)]
 | 
				
			||||||
pub struct ActiveCall {
 | 
					pub struct ActiveCall {
 | 
				
			||||||
@@ -14,8 +15,7 @@ pub struct ActiveCall {
 | 
				
			|||||||
/// This structure contains information about an active connection
 | 
					/// This structure contains information about an active connection
 | 
				
			||||||
#[derive(Clone, Debug)]
 | 
					#[derive(Clone, Debug)]
 | 
				
			||||||
pub struct UserWsConnection {
 | 
					pub struct UserWsConnection {
 | 
				
			||||||
    pub user_id: UserID,
 | 
					    pub user_token: UserAccessToken,
 | 
				
			||||||
    pub client_id: u32,
 | 
					 | 
				
			||||||
    pub remote_ip: String,
 | 
					    pub remote_ip: String,
 | 
				
			||||||
    pub session: actix::Addr<WsSession>,
 | 
					    pub session: actix::Addr<WsSession>,
 | 
				
			||||||
    pub incognito: bool,
 | 
					    pub incognito: bool,
 | 
				
			||||||
@@ -25,6 +25,11 @@ pub struct UserWsConnection {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl UserWsConnection {
 | 
					impl UserWsConnection {
 | 
				
			||||||
 | 
					    pub fn user_id(&self) -> &UserID {
 | 
				
			||||||
 | 
					        &self.user_token.user_id
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Check out whether a connection is being used to make a call in a specific conversation or not
 | 
					    /// Check out whether a connection is being used to make a call in a specific conversation or not
 | 
				
			||||||
    pub fn is_having_call_with_conversation(&self, conv_id: &ConvID) -> bool {
 | 
					    pub fn is_having_call_with_conversation(&self, conv_id: &ConvID) -> bool {
 | 
				
			||||||
        if let Some(call_info) = &self.active_call {
 | 
					        if let Some(call_info) = &self.active_call {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,7 +8,7 @@ use crate::api_data::http_error::HttpError;
 | 
				
			|||||||
use crate::controllers::routes::RequestResult;
 | 
					use crate::controllers::routes::RequestResult;
 | 
				
			||||||
use crate::data::base_request_handler::{BaseRequestHandler, RequestValue};
 | 
					use crate::data::base_request_handler::{BaseRequestHandler, RequestValue};
 | 
				
			||||||
use crate::data::error::ResultBoxError;
 | 
					use crate::data::error::ResultBoxError;
 | 
				
			||||||
use crate::data::user::UserID;
 | 
					use crate::data::user_token::UserAccessToken;
 | 
				
			||||||
use crate::data::user_ws_connection::UserWsConnection;
 | 
					use crate::data::user_ws_connection::UserWsConnection;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub enum UserWsResponseType {
 | 
					pub enum UserWsResponseType {
 | 
				
			||||||
@@ -88,11 +88,7 @@ impl BaseRequestHandler for UserWsRequestHandler {
 | 
				
			|||||||
        self.connection.remote_ip.to_string()
 | 
					        self.connection.remote_ip.to_string()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn user_id_opt_ref(&self) -> Option<&UserID> {
 | 
					    fn user_access_token(&self) -> Option<&UserAccessToken> {
 | 
				
			||||||
        Some(&self.connection.user_id)
 | 
					        Some(&self.connection.user_token)
 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    fn user_id(&self) -> ResultBoxError<UserID> {
 | 
					 | 
				
			||||||
        Ok(self.connection.user_id.clone())
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -13,7 +13,7 @@ use crate::data::security_settings::SecuritySettings;
 | 
				
			|||||||
use crate::data::user::{AccountImageVisibility, User, UserID, UserPageStatus};
 | 
					use crate::data::user::{AccountImageVisibility, User, UserID, UserPageStatus};
 | 
				
			||||||
use crate::data::user_token::UserAccessToken;
 | 
					use crate::data::user_token::UserAccessToken;
 | 
				
			||||||
use crate::helpers::{comments_helper, conversations_helper, custom_emojies_helper, database, events_helper, friends_helper, groups_helper, likes_helper, notifications_helper, posts_helper, survey_helper, user_helper};
 | 
					use crate::helpers::{comments_helper, conversations_helper, custom_emojies_helper, database, events_helper, friends_helper, groups_helper, likes_helper, notifications_helper, posts_helper, survey_helper, user_helper};
 | 
				
			||||||
use crate::helpers::database::{DeleteQuery, InsertQuery, QueryInfo};
 | 
					use crate::helpers::database::{DeleteQuery, InsertQuery, QueryInfo, UpdateInfo};
 | 
				
			||||||
use crate::helpers::events_helper::Event;
 | 
					use crate::helpers::events_helper::Event;
 | 
				
			||||||
use crate::helpers::likes_helper::LikeType;
 | 
					use crate::helpers::likes_helper::LikeType;
 | 
				
			||||||
use crate::utils::crypt_utils::{legacy_crypt_pass, rand_str};
 | 
					use crate::utils::crypt_utils::{legacy_crypt_pass, rand_str};
 | 
				
			||||||
@@ -47,56 +47,45 @@ pub fn login_user(email: &str, password: &str, client: &APIClient) -> ResultBoxE
 | 
				
			|||||||
        return Err(ExecError::boxed_new("The user gave an invalid 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
 | 
					    // Create new login tokens
 | 
				
			||||||
    let new_token = UserAccessToken {
 | 
					    let new_token = UserAccessToken {
 | 
				
			||||||
 | 
					        id: 0,
 | 
				
			||||||
        user_id: user.id.clone(),
 | 
					        user_id: user.id.clone(),
 | 
				
			||||||
        client_id: client.id,
 | 
					        client_id: client.id,
 | 
				
			||||||
        token: rand_str(150),
 | 
					        token: rand_str(150),
 | 
				
			||||||
 | 
					        last_refresh: time(),
 | 
				
			||||||
 | 
					        timeout: client.default_expiration_time,
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Save it
 | 
					    // Save it
 | 
				
			||||||
    database::insert(
 | 
					 | 
				
			||||||
    InsertQuery::new(USER_ACCESS_TOKENS_TABLE)
 | 
					    InsertQuery::new(USER_ACCESS_TOKENS_TABLE)
 | 
				
			||||||
 | 
					        .add_u64("client_id", client.id)
 | 
				
			||||||
        .add_user_id("user_id", &new_token.user_id)
 | 
					        .add_user_id("user_id", &new_token.user_id)
 | 
				
			||||||
            .add_u32("service_id", client.id)
 | 
					        .add_str("token", &new_token.token)
 | 
				
			||||||
            .add_str("token1", &new_token.token)
 | 
					        .add_u64("last_refresh", new_token.last_refresh)
 | 
				
			||||||
            .add_str("token2", "dummy_data")
 | 
					        .add_u64("timeout", new_token.timeout)
 | 
				
			||||||
    )?;
 | 
					        .insert_drop_result()?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Ok(new_token.token)
 | 
					    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", user_id)
 | 
					 | 
				
			||||||
            .cond_u32("service_id", client.id),
 | 
					 | 
				
			||||||
        |res| {
 | 
					 | 
				
			||||||
            Ok(UserAccessToken {
 | 
					 | 
				
			||||||
                user_id: res.get_user_id("user_id")?,
 | 
					 | 
				
			||||||
                client_id: res.get_int64("service_id")? as u32,
 | 
					 | 
				
			||||||
                token: res.get_str("token1")?,
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/// Find a user ID based on login token
 | 
					/// Find a user ID based on login token
 | 
				
			||||||
pub fn get_user_by_login_token(token: &str, client: &APIClient) -> ResultBoxError<UserID> {
 | 
					pub fn find_user_by_login_token(token: &str, client: &APIClient) -> ResultBoxError<UserAccessToken> {
 | 
				
			||||||
    database::query_row(
 | 
					 | 
				
			||||||
    QueryInfo::new(USER_ACCESS_TOKENS_TABLE)
 | 
					    QueryInfo::new(USER_ACCESS_TOKENS_TABLE)
 | 
				
			||||||
            .cond_u32("service_id", client.id)
 | 
					        .cond_u64("client_id", client.id)
 | 
				
			||||||
            .cond("token1", token)
 | 
					        .cond("token", token)
 | 
				
			||||||
            .add_field("user_id"),
 | 
					        .set_custom_where("last_refresh + timeout > ?")
 | 
				
			||||||
        |res| res.get_user_id("user_id"),
 | 
					        .add_custom_where_argument_u64(time())
 | 
				
			||||||
    )
 | 
					        .query_row(|res| {
 | 
				
			||||||
 | 
					            Ok(UserAccessToken {
 | 
				
			||||||
 | 
					                id: res.get_u64("id")?,
 | 
				
			||||||
 | 
					                client_id: res.get_u64("client_id")?,
 | 
				
			||||||
 | 
					                user_id: res.get_user_id("user_id")?,
 | 
				
			||||||
 | 
					                token: res.get_str("token")?,
 | 
				
			||||||
 | 
					                last_refresh: res.get_u64("last_refresh")?,
 | 
				
			||||||
 | 
					                timeout: res.get_u64("timeout")?,
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Check out whether an email address exists or not
 | 
					/// Check out whether an email address exists or not
 | 
				
			||||||
@@ -107,15 +96,22 @@ pub fn exists_mail(mail: &str) -> ResultBoxError<bool> {
 | 
				
			|||||||
        .map(|r| r > 0)
 | 
					        .map(|r| r > 0)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Refresh a user access token
 | 
				
			||||||
 | 
					pub fn refresh_access_token(token: &UserAccessToken) -> Res {
 | 
				
			||||||
 | 
					    UpdateInfo::new(USER_ACCESS_TOKENS_TABLE)
 | 
				
			||||||
 | 
					        .cond_u64("id", token.id)
 | 
				
			||||||
 | 
					        .set_u64("last_refresh", time())
 | 
				
			||||||
 | 
					        .exec()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Destroy a given user login tokens
 | 
					/// Destroy a given user login tokens
 | 
				
			||||||
pub fn destroy_login_tokens(id: &UserID, client: &APIClient) -> ResultBoxError<()> {
 | 
					pub fn destroy_login_tokens(access_tokens: &UserAccessToken) -> Res {
 | 
				
			||||||
    database::delete(DeleteQuery::new(USER_ACCESS_TOKENS_TABLE)
 | 
					    DeleteQuery::new(USER_ACCESS_TOKENS_TABLE)
 | 
				
			||||||
        .cond_u32("service_id", client.id)
 | 
					        .cond_u64("id", access_tokens.id)
 | 
				
			||||||
        .cond_user_id("user_id", id)
 | 
					        .exec()?;
 | 
				
			||||||
    )?;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Send an event (destroyed_login_tokens)
 | 
					    // Send an event (destroyed_login_tokens)
 | 
				
			||||||
    events_helper::propagate_event(&Event::DestroyedLoginToken(id.clone(), client))?;
 | 
					    events_helper::propagate_event(&Event::DestroyedLoginToken(access_tokens))?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Ok(())
 | 
					    Ok(())
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,27 +1,23 @@
 | 
				
			|||||||
 | 
					use crate::constants::database_tables_names::CLIENTS_TABLE;
 | 
				
			||||||
use crate::data::api_client::APIClient;
 | 
					use crate::data::api_client::APIClient;
 | 
				
			||||||
use crate::helpers::database;
 | 
					 | 
				
			||||||
use crate::helpers::database::QueryInfo;
 | 
					 | 
				
			||||||
use crate::constants::database_tables_names::SERVICES_TABLES;
 | 
					 | 
				
			||||||
use crate::data::error::ResultBoxError;
 | 
					use crate::data::error::ResultBoxError;
 | 
				
			||||||
 | 
					use crate::helpers::database::QueryInfo;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// API helper
 | 
					/// API helper
 | 
				
			||||||
///
 | 
					///
 | 
				
			||||||
/// @author Pierre Hubert
 | 
					/// @author Pierre Hubert
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Get information about a client
 | 
					/// Get information about a client
 | 
				
			||||||
pub fn get_client(name: &str, token: &str) -> ResultBoxError<APIClient> {
 | 
					pub fn get_client(name: &str) -> ResultBoxError<APIClient> {
 | 
				
			||||||
    database::query_row(
 | 
					    QueryInfo::new(CLIENTS_TABLE)
 | 
				
			||||||
        QueryInfo::new(SERVICES_TABLES)
 | 
					        .cond("name", name)
 | 
				
			||||||
            .cond("service_name", name)
 | 
					        .query_row(|res| {
 | 
				
			||||||
            .cond("token", token),
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            |res| {
 | 
					 | 
				
			||||||
            Ok(APIClient {
 | 
					            Ok(APIClient {
 | 
				
			||||||
                    id: res.get_int64("id")? as u32,
 | 
					                id: res.get_u64("id")?,
 | 
				
			||||||
                    name: res.get_str("service_name")?,
 | 
					                name: res.get_str("name")?,
 | 
				
			||||||
                    token: res.get_str("token")?,
 | 
					                domain: res.get_optional_str("domain")?,
 | 
				
			||||||
                    domain: res.get_optional_str("client_domain")?,
 | 
					                comment: res.get_optional_str("comment")?,
 | 
				
			||||||
 | 
					                default_expiration_time: res.get_u64("default_expiration_time")?,
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
        })
 | 
					        })
 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -5,13 +5,13 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use crate::controllers::{calls_controller, comments_controller, conversations_controller, notifications_controller, rtc_relay_controller, user_ws_controller};
 | 
					use crate::controllers::{calls_controller, comments_controller, conversations_controller, notifications_controller, rtc_relay_controller, user_ws_controller};
 | 
				
			||||||
use crate::data::api_client::APIClient;
 | 
					 | 
				
			||||||
use crate::data::call_signal::{CloseCallStream, NewRtcRelayMessage, NewUserCallSignal, UserCallOfferRequest};
 | 
					use crate::data::call_signal::{CloseCallStream, NewRtcRelayMessage, NewUserCallSignal, UserCallOfferRequest};
 | 
				
			||||||
use crate::data::comment::Comment;
 | 
					use crate::data::comment::Comment;
 | 
				
			||||||
use crate::data::conversation::ConvID;
 | 
					use crate::data::conversation::ConvID;
 | 
				
			||||||
use crate::data::conversation_message::ConversationMessage;
 | 
					use crate::data::conversation_message::ConversationMessage;
 | 
				
			||||||
use crate::data::error::Res;
 | 
					use crate::data::error::Res;
 | 
				
			||||||
use crate::data::user::UserID;
 | 
					use crate::data::user::UserID;
 | 
				
			||||||
 | 
					use crate::data::user_token::UserAccessToken;
 | 
				
			||||||
use crate::data::user_ws_connection::UserWsConnection;
 | 
					use crate::data::user_ws_connection::UserWsConnection;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub enum Event<'a> {
 | 
					pub enum Event<'a> {
 | 
				
			||||||
@@ -21,7 +21,7 @@ pub enum Event<'a> {
 | 
				
			|||||||
    UserWsClosed(&'a UserWsConnection),
 | 
					    UserWsClosed(&'a UserWsConnection),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Destroyed a login token
 | 
					    /// Destroyed a login token
 | 
				
			||||||
    DestroyedLoginToken(UserID, &'a APIClient),
 | 
					    DestroyedLoginToken(&'a UserAccessToken),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Updated the number of notifications of one of multiple users user
 | 
					    /// Updated the number of notifications of one of multiple users user
 | 
				
			||||||
    UpdatedNotificationsNumber(&'a Vec<UserID>),
 | 
					    UpdatedNotificationsNumber(&'a Vec<UserID>),
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user