mirror of
				https://gitlab.com/comunic/comunicapiv3
				synced 2025-10-30 23:24:42 +00:00 
			
		
		
		
	Check client tokens
This commit is contained in:
		| @@ -15,7 +15,7 @@ server-port: 3000 | ||||
| proxy: none | ||||
|  | ||||
| # If set to true Access-Control-Allow-Origin will be set for https | ||||
| force-https: false | ||||
| force-https: true | ||||
|  | ||||
| # User data storage | ||||
| storage-url: https://devweb.local/comunic/current/user_data/ | ||||
|   | ||||
| @@ -61,6 +61,6 @@ pub fn get_routes() -> Vec<Route> { | ||||
|  | ||||
|         // Account controller | ||||
|         Route::post_without_login("/account/login", Box::new(account_controller::login_user)), | ||||
|         Route::post_without_login("/account/connectUSER", Box::new(account_controller::login_user)), | ||||
|         Route::post_without_login("/user/connectUSER", Box::new(account_controller::login_user)), | ||||
|     ] | ||||
| } | ||||
| @@ -172,7 +172,14 @@ async fn process_request(custom_req: CustomRequest) -> HttpResponse { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     request.response() | ||||
|     // Send the response | ||||
|     match request.response() { | ||||
|         Ok(s) => s, | ||||
|         Err(e) => { | ||||
|             println!("Error while getting response: {}", e); | ||||
|             HttpResponse::InternalServerError().body("Response error") | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -3,36 +3,45 @@ use serde::Serialize; | ||||
| /// HTTP request error | ||||
| /// | ||||
| /// @author Pierre Hubert | ||||
|  | ||||
| #[derive(Serialize)] | ||||
| pub struct HttpError { | ||||
| pub struct InnerHTTPError { | ||||
|     pub code: u16, | ||||
|     pub message: String, | ||||
| } | ||||
|  | ||||
| impl HttpError { | ||||
| #[derive(Serialize)] | ||||
| pub struct HttpError { | ||||
|     pub error: InnerHTTPError | ||||
| } | ||||
|  | ||||
| impl HttpError { | ||||
|     /// Generate a 404 error | ||||
|     pub fn not_found(message: &str) -> HttpError { | ||||
|         HttpError { | ||||
|             code: 404, | ||||
|             message: message.to_string() | ||||
|             error: InnerHTTPError { | ||||
|                 code: 404, | ||||
|                 message: message.to_string(), | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /// Generate a 500 error | ||||
|     pub fn internal_error(message: &str) -> HttpError { | ||||
|         HttpError { | ||||
|             code: 500, | ||||
|             message: message.to_string() | ||||
|             error: InnerHTTPError { | ||||
|                 code: 500, | ||||
|                 message: message.to_string(), | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /// Generate a 401 error | ||||
|     pub fn bad_request(message: &str) -> HttpError { | ||||
|         HttpError { | ||||
|             code: 401, | ||||
|             message: message.to_string() | ||||
|             error: InnerHTTPError { | ||||
|                 code: 401, | ||||
|                 message: message.to_string(), | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -6,6 +6,10 @@ use serde::Serialize; | ||||
| use crate::data::error::{ResultBoxError, ExecError}; | ||||
| use std::collections::HashMap; | ||||
| use crate::helpers::api_helper; | ||||
| use actix_web::http::{HeaderName, HeaderValue}; | ||||
| use std::str::FromStr; | ||||
| use crate::data::config::conf; | ||||
| use crate::data::api_client::APIClient; | ||||
|  | ||||
| /// Http request handler | ||||
| /// | ||||
| @@ -34,6 +38,8 @@ pub struct HttpRequestHandler { | ||||
|     request: web::HttpRequest, | ||||
|     body: HashMap<String, RequestValue>, | ||||
|     response: Option<web::HttpResponse>, | ||||
|     headers: HashMap<String, String>, | ||||
|     client: Option<APIClient>, | ||||
| } | ||||
|  | ||||
| impl HttpRequestHandler { | ||||
| @@ -43,6 +49,8 @@ impl HttpRequestHandler { | ||||
|             request: req, | ||||
|             body, | ||||
|             response: None, | ||||
|             headers: HashMap::new(), | ||||
|             client: None, | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -57,8 +65,17 @@ impl HttpRequestHandler { | ||||
|     } | ||||
|  | ||||
|     /// Take the response from this struct | ||||
|     pub fn response(self) -> HttpResponse { | ||||
|         self.response.unwrap() | ||||
|     pub fn response(self) -> ResultBoxError<HttpResponse> { | ||||
|         let mut response = self.response.unwrap(); | ||||
|  | ||||
|         // Put additional headers if required | ||||
|         for (k, v) in &self.headers { | ||||
|             response.headers_mut().insert(HeaderName::from_str(k)?, | ||||
|                                           HeaderValue::from_str(v)?, | ||||
|             ); | ||||
|         } | ||||
|  | ||||
|         Ok(response) | ||||
|     } | ||||
|  | ||||
|     /// Success message | ||||
| @@ -91,7 +108,7 @@ impl HttpRequestHandler { | ||||
|                 println!("Error leading to bad request: {}", err); | ||||
|                 self.bad_request(msg.to_string())?; | ||||
|                 unreachable!() | ||||
|             }, | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -133,11 +150,30 @@ impl HttpRequestHandler { | ||||
|  | ||||
|         let client = self.ok_or_bad_request( | ||||
|             api_helper::get_client(&api_name, &api_token), | ||||
|             "Client not recognized!" | ||||
|             "Client not recognized!", | ||||
|         )?; | ||||
|  | ||||
|         // TODO  : continue here | ||||
|         println!("{:#?}", client); | ||||
|  | ||||
|         if let Some(domain) = &client.domain { | ||||
|             let allowed_origin =  match conf().force_https { | ||||
|                 true => format!("https://{}", domain), | ||||
|                 false => format!("http://{}", domain) | ||||
|             }; | ||||
|  | ||||
|             match self.request.headers().get("Referer") { | ||||
|                 None => self.bad_request("Unknown origin!".to_string())?, | ||||
|                 Some(s) => { | ||||
|                     if !s.to_str()?.starts_with(&allowed_origin) { | ||||
|                         self.bad_request("Use of this client is prohibited from this domain!".to_string())?; | ||||
|                     } | ||||
|                 }, | ||||
|             } | ||||
|  | ||||
|             self.headers.insert("Access-Control-Allow-Origin".to_string(), allowed_origin); | ||||
|         } | ||||
|  | ||||
|         self.client = Some(client); | ||||
|  | ||||
|         Ok(()) | ||||
|     } | ||||
| } | ||||
| @@ -20,7 +20,7 @@ pub fn get_client(name: &str, token: &str) -> ResultBoxError<APIClient> { | ||||
|                     id: res.get_int64("id")? as u32, | ||||
|                     name: res.get_str("service_name")?, | ||||
|                     token: res.get_str("token")?, | ||||
|                     domain: res.get_optional_str("domain")?, | ||||
|                     domain: res.get_optional_str("client_domain")?, | ||||
|                 }) | ||||
|             } | ||||
|     ) | ||||
|   | ||||
| @@ -3,11 +3,11 @@ use std::error::Error; | ||||
| use std::ops::Add; | ||||
| use std::sync::{Arc, Mutex}; | ||||
|  | ||||
| use mysql::{Binary, Pool, ResultSet}; | ||||
| use mysql::{Binary, Pool, ResultSet, Value}; | ||||
| use mysql::prelude::Queryable; | ||||
|  | ||||
| use crate::data::config::DatabaseConfig; | ||||
| use crate::data::error::ExecError; | ||||
| use crate::data::error::{ExecError, ResultBoxError}; | ||||
|  | ||||
| /// Database access helper | ||||
| /// | ||||
| @@ -107,30 +107,43 @@ impl<'a> RowResult<'a> { | ||||
|     } | ||||
|  | ||||
|     /// Find an integer included in the request | ||||
|     pub fn get_int64(&self, name: &str) -> Result<i64, ExecError> { | ||||
|         let value: Option<i64> = self.row.get(self.find_col(name)?); | ||||
|     pub fn get_int64(&self, name: &str) -> Result<i64, Box<dyn Error>> { | ||||
|         let value = self.row.get_opt(self.find_col(name)?); | ||||
|  | ||||
|         match value { | ||||
|             None => Err(ExecError(format!("Could not extract integer field {} !", name))), | ||||
|             Some(s) => Ok(s) | ||||
|             None => Err(ExecError::boxed_string( | ||||
|                 format!("Could not extract integer field {} !", name))), | ||||
|             Some(s) => Ok(s?) | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /// Find a string included in the request | ||||
|     pub fn get_str(&self, name: &str) -> Result<String, ExecError> { | ||||
|         let value: Option<String> = self.row.get(self.find_col(name)?); | ||||
|     pub fn get_str(&self, name: &str) -> Result<String, Box<dyn Error>> { | ||||
|         let value = self.row.get_opt(self.find_col(name)?); | ||||
|  | ||||
|         match value { | ||||
|             None => Err(ExecError(format!("Could not extract string field {} !", name))), | ||||
|             Some(s) => Ok(s) | ||||
|             None => Err(ExecError::boxed_string( | ||||
|                 format!("Could not extract string field {} !", name))), | ||||
|             Some(s) => Ok(s?) | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /// Get an optional string | ||||
|     pub fn get_optional_str(&self, name: &str) -> Result<Option<String>, ExecError> { | ||||
|         match self.find_col(name) { | ||||
|             Ok(col) => Ok(self.row.get(col)), | ||||
|             Err(_) => Ok(None), | ||||
|     /// Check out whether a given value is null or not | ||||
|     pub fn is_null(&self, name: &str) -> ResultBoxError<bool> { | ||||
|         let value = self.row.get_opt(self.find_col(name)?); | ||||
|  | ||||
|         match value { | ||||
|             None => Ok(true), | ||||
|             Some(Ok(Value::NULL)) => Ok(true), | ||||
|             _ => Ok(false) | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /// Get an optional string => Set to None if string is null | ||||
|     pub fn get_optional_str(&self, name: &str) -> ResultBoxError<Option<String>> { | ||||
|         match self.is_null(name)? { | ||||
|             true => Ok(None), | ||||
|             false => Ok(Some(self.get_str(name)?)) | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user