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

Can sign out user

This commit is contained in:
Pierre HUBERT 2020-05-24 19:19:07 +02:00
parent 89d5eac02b
commit 97d9adcc03
4 changed files with 87 additions and 7 deletions

View File

@ -31,6 +31,16 @@ pub fn login_user(request: &mut HttpRequestHandler) -> RequestResult {
} }
} }
/// Sign out user
pub fn logout_user(request: &mut HttpRequestHandler) -> RequestResult {
account_helper::destroy_login_tokens(
request.user_id()?,
request.api_client()
)?;
request.success("User disconnected.")
}
/// Get current user ID /// Get current user ID
pub fn user_id(request: &mut HttpRequestHandler) -> RequestResult { pub fn user_id(request: &mut HttpRequestHandler) -> RequestResult {
request.set_response(CurrentUserID::new(request.user_id()?)) request.set_response(CurrentUserID::new(request.user_id()?))

View File

@ -72,6 +72,9 @@ pub fn get_routes() -> Vec<Route> {
Route::post_without_login("/account/login", Box::new(account_controller::login_user)), Route::post_without_login("/account/login", Box::new(account_controller::login_user)),
Route::post_without_login("/user/connectUSER", Box::new(account_controller::login_user)), Route::post_without_login("/user/connectUSER", Box::new(account_controller::login_user)),
Route::post("/account/logout", Box::new(account_controller::logout_user)),
Route::post("/user/disconnectUSER", Box::new(account_controller::logout_user)),
Route::post("/account/id", Box::new(account_controller::user_id)), Route::post("/account/id", Box::new(account_controller::user_id)),
Route::post("/user/getCurrentUserID", Box::new(account_controller::user_id)), Route::post("/user/getCurrentUserID", Box::new(account_controller::user_id)),
] ]

View File

@ -4,7 +4,7 @@ use crate::data::user::UserID;
use crate::data::user_token::UserAccessToken; use crate::data::user_token::UserAccessToken;
use crate::database_structure::USER_ACCESS_TOKENS_TABLE; use crate::database_structure::USER_ACCESS_TOKENS_TABLE;
use crate::helpers::{database, user_helper}; use crate::helpers::{database, user_helper};
use crate::helpers::database::{QueryInfo, InsertQuery}; use crate::helpers::database::{QueryInfo, InsertQuery, DeleteQuery};
use crate::utils::crypt_utils::{crypt_pass, rand_str}; use crate::utils::crypt_utils::{crypt_pass, rand_str};
/// Account helper /// Account helper
@ -74,4 +74,15 @@ pub fn get_user_by_login_token(token: &str, client: &APIClient) -> ResultBoxErro
.add_field("user_id"), .add_field("user_id"),
|res| res.get_int64("user_id"), |res| res.get_int64("user_id"),
) )
}
/// Destroy a given user login tokens
pub fn destroy_login_tokens(id: UserID, client: &APIClient) -> ResultBoxError<()> {
database::delete(DeleteQuery::new(USER_ACCESS_TOKENS_TABLE)
.cond_u32("service_id", client.id)
.cond_i64("user_id", id)
)?;
Ok(())
} }

View File

@ -162,7 +162,7 @@ impl<'a> RowResult<'a> {
pub fn get_optional_str(&self, name: &str) -> ResultBoxError<Option<String>> { pub fn get_optional_str(&self, name: &str) -> ResultBoxError<Option<String>> {
match self.is_null(name)? { match self.is_null(name)? {
true => Ok(None), true => Ok(None),
false => Ok(Some(self.get_str(name)?).map_or(None, |d|{ false => Ok(Some(self.get_str(name)?).map_or(None, |d| {
match d.is_empty() { match d.is_empty() {
true => None, true => None,
false => Some(d) false => Some(d)
@ -247,17 +247,16 @@ pub fn query<E, F: Fn(&RowResult) -> ProcessRowResult<E>>(info: QueryInfo, proce
/// Structure used to execute a insert query /// Structure used to execute a insert query
pub struct InsertQuery { pub struct InsertQuery {
pub table : String, pub table: String,
pub values: HashMap<String, mysql::Value>, pub values: HashMap<String, mysql::Value>,
} }
impl InsertQuery { impl InsertQuery {
/// Construct a new InsertQuery instance /// Construct a new InsertQuery instance
pub fn new(table: &str) -> InsertQuery { pub fn new(table: &str) -> InsertQuery {
InsertQuery { InsertQuery {
table: table.to_string(), table: table.to_string(),
values: HashMap::new() values: HashMap::new(),
} }
} }
@ -285,7 +284,7 @@ pub fn insert(query: InsertQuery) -> ResultBoxError<()> {
// Collect keys // Collect keys
let keys = query.values let keys = query.values
.keys() .keys()
.map(|f|f.to_string()) .map(|f| f.to_string())
.collect::<Vec<String>>(); .collect::<Vec<String>>();
let query_sql = format!( let query_sql = format!(
@ -297,7 +296,64 @@ pub fn insert(query: InsertQuery) -> ResultBoxError<()> {
get_connection()?.exec_drop( get_connection()?.exec_drop(
query_sql, query_sql,
query.values.values().collect::<Vec<&mysql::Value>>() query.values.values().collect::<Vec<&mysql::Value>>(),
)?;
Ok(())
}
/// Structure used to build delete queries
pub struct DeleteQuery {
table: String,
conditions: HashMap<String, Value>,
}
impl DeleteQuery {
/// Construct a new delete table query
pub fn new(table: &str) -> DeleteQuery {
DeleteQuery {
table: table.to_string(),
conditions: HashMap::new(),
}
}
/// Add a string condition
pub fn cond_str(mut self, key: &str, value: &str) -> DeleteQuery {
self.conditions.insert(key.to_string(), Value::from(value));
self
}
/// Add an integer condition
pub fn cond_u32(mut self, key: &str, value: u32) -> DeleteQuery {
self.conditions.insert(key.to_string(), Value::from(value));
self
}
pub fn cond_i64(mut self, key: &str, value: i64) -> DeleteQuery {
self.conditions.insert(key.to_string(), Value::from(value));
self
}
}
/// Delete an entry from the database
pub fn delete(query: DeleteQuery) -> ResultBoxError<()> {
if query.conditions.is_empty() {
return Err(ExecError::boxed_new("DELETE without WHERE condition blocked for security reasons!"));
}
let query_sql = format!(
"DELETE FROM {} WHERE {}",
query.table,
query.conditions.keys()
.map(|f| format!("{} = ?", f))
.collect::<Vec<String>>()
.join(" AND ")
);
get_connection()?.exec_drop(
query_sql,
query.conditions.values().collect::<Vec<&Value>>()
)?; )?;
Ok(()) Ok(())