1
0
mirror of https://gitlab.com/comunic/comunicapiv3 synced 2024-11-26 07:19:22 +00:00

Check client tokens

This commit is contained in:
Pierre HUBERT 2020-05-23 14:08:22 +02:00
parent 665aa1683c
commit 505fa5adb3
7 changed files with 99 additions and 34 deletions

View File

@ -15,7 +15,7 @@ server-port: 3000
proxy: none proxy: none
# If set to true Access-Control-Allow-Origin will be set for https # If set to true Access-Control-Allow-Origin will be set for https
force-https: false force-https: true
# User data storage # User data storage
storage-url: https://devweb.local/comunic/current/user_data/ storage-url: https://devweb.local/comunic/current/user_data/

View File

@ -61,6 +61,6 @@ pub fn get_routes() -> Vec<Route> {
// Account controller // Account controller
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("/account/connectUSER", Box::new(account_controller::login_user)), Route::post_without_login("/user/connectUSER", Box::new(account_controller::login_user)),
] ]
} }

View File

@ -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")
}
}
} }

View File

@ -3,36 +3,45 @@ use serde::Serialize;
/// HTTP request error /// HTTP request error
/// ///
/// @author Pierre Hubert /// @author Pierre Hubert
#[derive(Serialize)] #[derive(Serialize)]
pub struct HttpError { pub struct InnerHTTPError {
pub code: u16, pub code: u16,
pub message: String, pub message: String,
} }
impl HttpError { #[derive(Serialize)]
pub struct HttpError {
pub error: InnerHTTPError
}
impl HttpError {
/// Generate a 404 error /// Generate a 404 error
pub fn not_found(message: &str) -> HttpError { pub fn not_found(message: &str) -> HttpError {
HttpError { HttpError {
code: 404, error: InnerHTTPError {
message: message.to_string() code: 404,
message: message.to_string(),
}
} }
} }
/// Generate a 500 error /// Generate a 500 error
pub fn internal_error(message: &str) -> HttpError { pub fn internal_error(message: &str) -> HttpError {
HttpError { HttpError {
code: 500, error: InnerHTTPError {
message: message.to_string() code: 500,
message: message.to_string(),
}
} }
} }
/// Generate a 401 error /// Generate a 401 error
pub fn bad_request(message: &str) -> HttpError { pub fn bad_request(message: &str) -> HttpError {
HttpError { HttpError {
code: 401, error: InnerHTTPError {
message: message.to_string() code: 401,
message: message.to_string(),
}
} }
} }
} }

View File

@ -6,6 +6,10 @@ use serde::Serialize;
use crate::data::error::{ResultBoxError, ExecError}; use crate::data::error::{ResultBoxError, ExecError};
use std::collections::HashMap; use std::collections::HashMap;
use crate::helpers::api_helper; 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 /// Http request handler
/// ///
@ -34,6 +38,8 @@ pub struct HttpRequestHandler {
request: web::HttpRequest, request: web::HttpRequest,
body: HashMap<String, RequestValue>, body: HashMap<String, RequestValue>,
response: Option<web::HttpResponse>, response: Option<web::HttpResponse>,
headers: HashMap<String, String>,
client: Option<APIClient>,
} }
impl HttpRequestHandler { impl HttpRequestHandler {
@ -43,6 +49,8 @@ impl HttpRequestHandler {
request: req, request: req,
body, body,
response: None, response: None,
headers: HashMap::new(),
client: None,
} }
} }
@ -57,8 +65,17 @@ impl HttpRequestHandler {
} }
/// Take the response from this struct /// Take the response from this struct
pub fn response(self) -> HttpResponse { pub fn response(self) -> ResultBoxError<HttpResponse> {
self.response.unwrap() 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 /// Success message
@ -91,7 +108,7 @@ impl HttpRequestHandler {
println!("Error leading to bad request: {}", err); println!("Error leading to bad request: {}", err);
self.bad_request(msg.to_string())?; self.bad_request(msg.to_string())?;
unreachable!() unreachable!()
}, }
} }
} }
@ -133,11 +150,30 @@ impl HttpRequestHandler {
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(&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(()) Ok(())
} }
} }

View File

@ -20,7 +20,7 @@ pub fn get_client(name: &str, token: &str) -> ResultBoxError<APIClient> {
id: res.get_int64("id")? as u32, id: res.get_int64("id")? as u32,
name: res.get_str("service_name")?, name: res.get_str("service_name")?,
token: res.get_str("token")?, token: res.get_str("token")?,
domain: res.get_optional_str("domain")?, domain: res.get_optional_str("client_domain")?,
}) })
} }
) )

View File

@ -3,11 +3,11 @@ use std::error::Error;
use std::ops::Add; use std::ops::Add;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use mysql::{Binary, Pool, ResultSet}; use mysql::{Binary, Pool, ResultSet, Value};
use mysql::prelude::Queryable; use mysql::prelude::Queryable;
use crate::data::config::DatabaseConfig; use crate::data::config::DatabaseConfig;
use crate::data::error::ExecError; use crate::data::error::{ExecError, ResultBoxError};
/// Database access helper /// Database access helper
/// ///
@ -107,30 +107,43 @@ impl<'a> RowResult<'a> {
} }
/// Find an integer included in the request /// Find an integer included in the request
pub fn get_int64(&self, name: &str) -> Result<i64, ExecError> { pub fn get_int64(&self, name: &str) -> Result<i64, Box<dyn Error>> {
let value: Option<i64> = self.row.get(self.find_col(name)?); let value = self.row.get_opt(self.find_col(name)?);
match value { match value {
None => Err(ExecError(format!("Could not extract integer field {} !", name))), None => Err(ExecError::boxed_string(
Some(s) => Ok(s) format!("Could not extract integer field {} !", name))),
Some(s) => Ok(s?)
} }
} }
/// Find a string included in the request /// Find a string included in the request
pub fn get_str(&self, name: &str) -> Result<String, ExecError> { pub fn get_str(&self, name: &str) -> Result<String, Box<dyn Error>> {
let value: Option<String> = self.row.get(self.find_col(name)?); let value = self.row.get_opt(self.find_col(name)?);
match value { match value {
None => Err(ExecError(format!("Could not extract string field {} !", name))), None => Err(ExecError::boxed_string(
Some(s) => Ok(s) format!("Could not extract string field {} !", name))),
Some(s) => Ok(s?)
} }
} }
/// Get an optional string /// Check out whether a given value is null or not
pub fn get_optional_str(&self, name: &str) -> Result<Option<String>, ExecError> { pub fn is_null(&self, name: &str) -> ResultBoxError<bool> {
match self.find_col(name) { let value = self.row.get_opt(self.find_col(name)?);
Ok(col) => Ok(self.row.get(col)),
Err(_) => Ok(None), 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)?))
} }
} }
} }