mirror of
https://gitlab.com/comunic/comunicapiv3
synced 2024-11-26 07:19:22 +00:00
Check client tokens
This commit is contained in:
parent
665aa1683c
commit
505fa5adb3
@ -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/
|
||||||
|
@ -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)),
|
||||||
]
|
]
|
||||||
}
|
}
|
@ -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
|
/// 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(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -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(())
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -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")?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -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)?))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user