From d2035a6a3f2a1902b5275718b5945b9265674bc6 Mon Sep 17 00:00:00 2001 From: Pierre HUBERT Date: Sat, 23 May 2020 19:17:48 +0200 Subject: [PATCH] Ready to implement password check --- src/controllers/account_controller.rs | 32 +++++++++++++++++++++++++-- src/data/http_error.rs | 12 +++++++++- src/data/http_request_handler.rs | 22 ++++++++++++++++-- src/data/mod.rs | 4 +++- src/data/user.rs | 11 +++++++++ src/database_structure.rs | 5 ++++- src/helpers/account_helper.rs | 21 ++++++++++++++++++ src/helpers/mod.rs | 4 +++- src/helpers/user_helper.rs | 27 ++++++++++++++++++++++ 9 files changed, 130 insertions(+), 8 deletions(-) create mode 100644 src/data/user.rs create mode 100644 src/helpers/account_helper.rs create mode 100644 src/helpers/user_helper.rs diff --git a/src/controllers/account_controller.rs b/src/controllers/account_controller.rs index 1b7f546..08d08a1 100644 --- a/src/controllers/account_controller.rs +++ b/src/controllers/account_controller.rs @@ -1,10 +1,23 @@ +use serde::{Deserialize, Serialize}; use crate::data::http_request_handler::HttpRequestHandler; use crate::controllers::routes::RequestResult; +use crate::helpers::account_helper; /// Account controller /// /// @author Pierre Hubert +#[derive(Serialize, Deserialize)] +struct LoginTokens { + token1: String, + token2: String, +} + +#[derive(Serialize, Deserialize)] +struct LoginSuccess { + tokens: LoginTokens +} + /// Sign in user pub fn login_user(request: &mut HttpRequestHandler) -> RequestResult { let email = request.post_email("userMail")?; @@ -13,7 +26,22 @@ pub fn login_user(request: &mut HttpRequestHandler) -> RequestResult { // TODO : limit request // Authenticate user + let token = account_helper::login_user( + &email, &password, request.api_client()); - - request.success("") + match token { + Ok(t) => { + request.set_response(LoginSuccess { + tokens: LoginTokens { + token1: t, + token2: "dummy_data".to_string() + } + }) + }, + Err(e) => { + // TODO : limit request + println!("Error on login: {}", e); + request.forbidden("Invalid email address / password!".to_string()) + }, + } } \ No newline at end of file diff --git a/src/data/http_error.rs b/src/data/http_error.rs index 1334a54..3e63f7a 100644 --- a/src/data/http_error.rs +++ b/src/data/http_error.rs @@ -35,8 +35,18 @@ impl HttpError { } } - /// Generate a 401 error + /// Generate a 400 error pub fn bad_request(message: &str) -> HttpError { + HttpError { + error: InnerHTTPError { + code: 400, + message: message.to_string(), + } + } + } + + /// Generate a 401 error + pub fn forbidden(message: &str) -> HttpError { HttpError { error: InnerHTTPError { code: 401, diff --git a/src/data/http_request_handler.rs b/src/data/http_request_handler.rs index ea03ec0..fb9a486 100644 --- a/src/data/http_request_handler.rs +++ b/src/data/http_request_handler.rs @@ -78,6 +78,12 @@ impl HttpRequestHandler { Ok(response) } + /// Set request response + pub fn set_response(&mut self, data: T) -> RequestResult { + self.response = Some(HttpResponse::Ok().json(data)); + Ok(()) + } + /// Success message pub fn success(&mut self, message: &str) -> RequestResult { self.response = Some(HttpResponse::Ok().json(SuccessMessage { @@ -86,20 +92,27 @@ impl HttpRequestHandler { Ok(()) } - /// Internal error message + /// Internal error response (500) pub fn internal_error(&mut self, error: Box) -> RequestResult { self.response = Some(HttpResponse::InternalServerError().json( HttpError::internal_error("Internal server error."))); Err(error) } - /// Bad request + /// Bad request (400) pub fn bad_request(&mut self, message: String) -> RequestResult { self.response = Some(HttpResponse::BadRequest().json( HttpError::bad_request(&message))); Err(Box::new(ExecError::new(&message))) } + /// Forbidden (401) + pub fn forbidden(&mut self, message: String) -> RequestResult { + self.response = Some(HttpResponse::Forbidden().json( + HttpError::forbidden(&message))); + Err(Box::new(ExecError::new(&message))) + } + /// If result is not OK, return a bad request pub fn ok_or_bad_request(&mut self, res: ResultBoxError, msg: &str) -> ResultBoxError { match res { @@ -117,6 +130,11 @@ impl HttpRequestHandler { self.request.path().to_string() } + /// Get information about the client which made the request + pub fn api_client(&self) -> &APIClient { + self.client.as_ref().unwrap() + } + /// Check if a POST parameter was present in the request or not pub fn has_post_parameter(&self, name: &str) -> bool { self.body.contains_key(name) diff --git a/src/data/mod.rs b/src/data/mod.rs index d1c73c4..07dc607 100644 --- a/src/data/mod.rs +++ b/src/data/mod.rs @@ -3,4 +3,6 @@ pub mod config; pub mod http_error; pub mod http_request_handler; -pub mod api_client; \ No newline at end of file +pub mod api_client; + +pub mod user; \ No newline at end of file diff --git a/src/data/user.rs b/src/data/user.rs new file mode 100644 index 0000000..b446001 --- /dev/null +++ b/src/data/user.rs @@ -0,0 +1,11 @@ +/// User information +/// +/// @author Pierre Hubert +#[derive(Debug)] +pub struct User { + pub id: i64, + pub email: String, + pub password: String, + pub first_name: String, + pub last_name: String, +} \ No newline at end of file diff --git a/src/database_structure.rs b/src/database_structure.rs index 7e2adc9..cd17142 100644 --- a/src/database_structure.rs +++ b/src/database_structure.rs @@ -3,4 +3,7 @@ /// @author Pierre Hubert /// API services tokens table -pub const SERVICES_TABLES : &str = "comunic_api_services_tokens"; \ No newline at end of file +pub const SERVICES_TABLES : &str = "comunic_api_services_tokens"; + +/// User table +pub const USERS_TABLE : &str = "utilisateurs"; \ No newline at end of file diff --git a/src/helpers/account_helper.rs b/src/helpers/account_helper.rs new file mode 100644 index 0000000..3e835dc --- /dev/null +++ b/src/helpers/account_helper.rs @@ -0,0 +1,21 @@ +use crate::data::api_client::APIClient; +use crate::data::error::ResultBoxError; +use crate::helpers::user_helper; + +/// Account helper +/// +/// @author Pierre Hubert + +/// Attempt to sign-in user +/// +/// In this version of the api, we consider that there is only one login token required +/// This is why I returns just a simple string, the token created for the user in case of success +pub fn login_user(email: &str, password: &str, client: &APIClient) -> ResultBoxError { + let user = user_helper::find_user_by_email(email)?; + + // TODO : check user password + + println!("{:#?}", user); + + Ok("d".to_string()) +} \ No newline at end of file diff --git a/src/helpers/mod.rs b/src/helpers/mod.rs index 52decd0..c05dac7 100644 --- a/src/helpers/mod.rs +++ b/src/helpers/mod.rs @@ -1,3 +1,5 @@ pub mod database; -pub mod api_helper; \ No newline at end of file +pub mod api_helper; +pub mod account_helper; +pub mod user_helper; \ No newline at end of file diff --git a/src/helpers/user_helper.rs b/src/helpers/user_helper.rs new file mode 100644 index 0000000..bbc0c71 --- /dev/null +++ b/src/helpers/user_helper.rs @@ -0,0 +1,27 @@ +use crate::data::error::ResultBoxError; +use crate::data::user::User; +use crate::helpers::database; +use crate::database_structure::USERS_TABLE; + +/// User helper +/// +/// @author Pierre Hubert + +/// Get & return information about a user based on his email +pub fn find_user_by_email(email: &str) -> ResultBoxError { + exec_get_user_query( + database::QueryInfo::new(USERS_TABLE).cond("mail", email)) +} + +/// Execute query & return result +fn exec_get_user_query(query : database::QueryInfo) -> ResultBoxError { + database::query_row(query, |res|{ + Ok(User { + id: res.get_int64("ID")?, + email: res.get_str("mail")?, + password: res.get_str("password")?, + first_name: res.get_str("prenom")?, + last_name: res.get_str("nom")? + }) + }) +} \ No newline at end of file