mirror of
https://gitlab.com/comunic/comunicapiv3
synced 2024-11-26 15:29:21 +00:00
Can authenticate admin with reset token
This commit is contained in:
parent
25830fe6d1
commit
d8ec093786
18
src/api_data/admin/admin_auth_success.rs
Normal file
18
src/api_data/admin/admin_auth_success.rs
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
//! # Admin authentication success
|
||||||
|
//!
|
||||||
|
//! Structure returned when an administrator successfully authenticate
|
||||||
|
//!
|
||||||
|
//! @author Pierre Hubert
|
||||||
|
|
||||||
|
use serde::Serialize;
|
||||||
|
|
||||||
|
#[derive(Serialize)]
|
||||||
|
pub struct AdminAuthSuccess {
|
||||||
|
token: String
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AdminAuthSuccess {
|
||||||
|
pub fn new(t: String) -> Self {
|
||||||
|
Self { token: t }
|
||||||
|
}
|
||||||
|
}
|
@ -3,3 +3,4 @@
|
|||||||
//! @author Pierre Hubert
|
//! @author Pierre Hubert
|
||||||
|
|
||||||
pub mod admin_auth_options;
|
pub mod admin_auth_options;
|
||||||
|
pub mod admin_auth_success;
|
@ -160,9 +160,15 @@ pub const PASSWORD_RESET_TOKEN_LIFETIME: u64 = 60 * 60 * 6;
|
|||||||
/// Length of admin reset tokens
|
/// Length of admin reset tokens
|
||||||
pub const ADMIN_RESET_TOKEN_LENGTH: usize = 255;
|
pub const ADMIN_RESET_TOKEN_LENGTH: usize = 255;
|
||||||
|
|
||||||
/// Duration of the validity of a password reset token (1 hour)
|
/// Duration of the validity of an admin password reset token (1 hour)
|
||||||
pub const ADMIN_RESET_TOKEN_LIFETIME: u64 = 60 * 60;
|
pub const ADMIN_RESET_TOKEN_LIFETIME: u64 = 60 * 60;
|
||||||
|
|
||||||
|
/// Length of an admin access token
|
||||||
|
pub const ADMIN_ACCESS_TOKEN_LENGTH: usize = 300;
|
||||||
|
|
||||||
|
/// Duration of the validation of an admin access token without refresh
|
||||||
|
pub const ADMIN_ACCESS_TOKEN_LIFETIME: u64 = 60 * 10;
|
||||||
|
|
||||||
/// Minimum password length
|
/// Minimum password length
|
||||||
pub const PASSWORD_MIN_LENGTH: usize = 3;
|
pub const PASSWORD_MIN_LENGTH: usize = 3;
|
||||||
|
|
||||||
|
@ -3,10 +3,12 @@
|
|||||||
//! @author Pierre Hubert
|
//! @author Pierre Hubert
|
||||||
|
|
||||||
use crate::api_data::admin::admin_auth_options::AdminAuthOptions;
|
use crate::api_data::admin::admin_auth_options::AdminAuthOptions;
|
||||||
|
use crate::api_data::admin::admin_auth_success::AdminAuthSuccess;
|
||||||
use crate::data::base_request_handler::BaseRequestHandler;
|
use crate::data::base_request_handler::BaseRequestHandler;
|
||||||
use crate::data::http_request_handler::HttpRequestHandler;
|
use crate::data::http_request_handler::HttpRequestHandler;
|
||||||
use crate::helpers::admin_account_helper;
|
use crate::helpers::{admin_access_token_helper, admin_account_helper};
|
||||||
use crate::routes::RequestResult;
|
use crate::routes::RequestResult;
|
||||||
|
use crate::utils::date_utils::time;
|
||||||
|
|
||||||
/// Get admin auth options
|
/// Get admin auth options
|
||||||
pub fn get_auth_options(r: &mut HttpRequestHandler) -> RequestResult {
|
pub fn get_auth_options(r: &mut HttpRequestHandler) -> RequestResult {
|
||||||
@ -15,3 +17,22 @@ pub fn get_auth_options(r: &mut HttpRequestHandler) -> RequestResult {
|
|||||||
|
|
||||||
r.set_response(AdminAuthOptions::new(&admin))
|
r.set_response(AdminAuthOptions::new(&admin))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Login admin using a reset token
|
||||||
|
pub fn auth_with_reset_token(r: &mut HttpRequestHandler) -> RequestResult {
|
||||||
|
let reset_token = r.post_string("token")?;
|
||||||
|
let admin = admin_account_helper::find_admin_by_email(&r.post_email("mail")?)?;
|
||||||
|
|
||||||
|
let token = r.some_or_internal_error(
|
||||||
|
admin.reset_token,
|
||||||
|
"Specified user has not valid reset token for now!",
|
||||||
|
)?;
|
||||||
|
|
||||||
|
if !token.token.eq(&reset_token) || time() > token.expire {
|
||||||
|
return r.forbidden("Specified reset token is invalid!".to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
let token = admin_access_token_helper::create(admin.id)?;
|
||||||
|
|
||||||
|
r.set_response(AdminAuthSuccess::new(token))
|
||||||
|
}
|
@ -2,7 +2,7 @@
|
|||||||
//!
|
//!
|
||||||
//! @author Pierre Hubert
|
//! @author Pierre Hubert
|
||||||
|
|
||||||
#[derive(Copy, Clone, Eq, PartialEq)]
|
#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash)]
|
||||||
pub struct AdminID(u64);
|
pub struct AdminID(u64);
|
||||||
|
|
||||||
impl AdminID {
|
impl AdminID {
|
||||||
@ -39,3 +39,13 @@ pub struct AdminKey {
|
|||||||
pub name: String,
|
pub name: String,
|
||||||
pub key: String,
|
pub key: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Admin access token
|
||||||
|
///
|
||||||
|
/// Used to store authentication of an admin
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct AdminAccessToken {
|
||||||
|
pub token: String,
|
||||||
|
pub id: AdminID,
|
||||||
|
pub last_refresh: u64
|
||||||
|
}
|
80
src/helpers/admin_access_token_helper.rs
Normal file
80
src/helpers/admin_access_token_helper.rs
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
//! # Admin access token helper
|
||||||
|
//!
|
||||||
|
//! @author Pierre Hubert
|
||||||
|
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
|
use crate::constants::{ADMIN_ACCESS_TOKEN_LENGTH, ADMIN_ACCESS_TOKEN_LIFETIME};
|
||||||
|
use crate::data::admin::{AdminAccessToken, AdminID};
|
||||||
|
use crate::data::error::{ExecError, Res};
|
||||||
|
use crate::utils::crypt_utils::rand_str;
|
||||||
|
use crate::utils::date_utils::time;
|
||||||
|
|
||||||
|
static mut CACHE: Option<Arc<Mutex<HashMap<AdminID, AdminAccessToken>>>> = None;
|
||||||
|
|
||||||
|
/// Initialize this helper
|
||||||
|
pub fn init() {
|
||||||
|
unsafe {
|
||||||
|
let map = HashMap::new();
|
||||||
|
CACHE = Some(Arc::new(Mutex::new(map)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create and return a new access token for an admin
|
||||||
|
pub fn create(id: AdminID) -> Res<String> {
|
||||||
|
let map = unsafe {
|
||||||
|
CACHE.as_ref().unwrap().lock()
|
||||||
|
};
|
||||||
|
|
||||||
|
let token = AdminAccessToken {
|
||||||
|
token: rand_str(ADMIN_ACCESS_TOKEN_LENGTH),
|
||||||
|
id,
|
||||||
|
last_refresh: time(),
|
||||||
|
};
|
||||||
|
|
||||||
|
map?.insert(id, token.clone());
|
||||||
|
|
||||||
|
Ok(token.token)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Remove an access token from the list
|
||||||
|
pub fn destroy(id: AdminID) -> Res {
|
||||||
|
let map = unsafe {
|
||||||
|
CACHE.as_ref().unwrap().lock()
|
||||||
|
};
|
||||||
|
|
||||||
|
map?.remove(&id);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Find an admin by its access token
|
||||||
|
pub fn find_by_token(t: &str) -> Res<AdminAccessToken> {
|
||||||
|
let map = unsafe {
|
||||||
|
CACHE.as_ref().unwrap().lock()
|
||||||
|
};
|
||||||
|
let mut map = map?;
|
||||||
|
|
||||||
|
let token = map.iter()
|
||||||
|
.filter(|p| p.1.token.eq(t))
|
||||||
|
.next();
|
||||||
|
|
||||||
|
let mut token = match token {
|
||||||
|
None => {
|
||||||
|
return Err(ExecError::boxed_new("The token was not recognized as an admin token!"));
|
||||||
|
}
|
||||||
|
Some(t) => t.1
|
||||||
|
}.clone();
|
||||||
|
|
||||||
|
|
||||||
|
if token.last_refresh + ADMIN_ACCESS_TOKEN_LIFETIME < time() {
|
||||||
|
return Err(ExecError::boxed_new("The token has expired!"));
|
||||||
|
}
|
||||||
|
|
||||||
|
token.last_refresh = time();
|
||||||
|
|
||||||
|
map.insert(token.id, token.clone());
|
||||||
|
|
||||||
|
Ok(token)
|
||||||
|
}
|
@ -23,3 +23,4 @@ pub mod independent_push_notifications_service_helper;
|
|||||||
pub mod firebase_notifications_helper;
|
pub mod firebase_notifications_helper;
|
||||||
pub mod forez_presence_helper;
|
pub mod forez_presence_helper;
|
||||||
pub mod admin_account_helper;
|
pub mod admin_account_helper;
|
||||||
|
pub mod admin_access_token_helper;
|
@ -337,5 +337,6 @@ pub fn get_routes() -> Vec<Route> {
|
|||||||
|
|
||||||
// Admin accounts controller
|
// Admin accounts controller
|
||||||
Route::limited_admin_post_without_login("/admin/accounts/auth_options", Box::new(admin_account_controller::get_auth_options), LimitPolicy::FAILURE(5)),
|
Route::limited_admin_post_without_login("/admin/accounts/auth_options", Box::new(admin_account_controller::get_auth_options), LimitPolicy::FAILURE(5)),
|
||||||
|
Route::limited_admin_post_without_login("/admin/accounts/auth_with_reset_token", Box::new(admin_account_controller::auth_with_reset_token), LimitPolicy::FAILURE(5)),
|
||||||
]
|
]
|
||||||
}
|
}
|
@ -17,7 +17,7 @@ use crate::controllers::{rtc_relay_controller, user_ws_controller};
|
|||||||
use crate::data::base_request_handler::{BaseRequestHandler, PostFile, RequestValue};
|
use crate::data::base_request_handler::{BaseRequestHandler, PostFile, RequestValue};
|
||||||
use crate::data::config::Config;
|
use crate::data::config::Config;
|
||||||
use crate::data::http_request_handler::HttpRequestHandler;
|
use crate::data::http_request_handler::HttpRequestHandler;
|
||||||
use crate::helpers::{api_helper, requests_limit_helper};
|
use crate::helpers::{api_helper, requests_limit_helper, admin_access_token_helper};
|
||||||
use crate::routes::{get_routes, RequestResult, Route, RouteScope};
|
use crate::routes::{get_routes, RequestResult, Route, RouteScope};
|
||||||
use crate::routes::Method::{GET, POST};
|
use crate::routes::Method::{GET, POST};
|
||||||
use crate::utils::user_data_utils::user_data_path;
|
use crate::utils::user_data_utils::user_data_path;
|
||||||
@ -352,6 +352,8 @@ pub async fn start_server(conf: &Config) -> std::io::Result<()> {
|
|||||||
// Initialize limit helper
|
// Initialize limit helper
|
||||||
requests_limit_helper::init();
|
requests_limit_helper::init();
|
||||||
|
|
||||||
|
admin_access_token_helper::init();
|
||||||
|
|
||||||
let addr = conf.server_listen_address();
|
let addr = conf.server_listen_address();
|
||||||
println!("Start to listen on http://{}/", addr);
|
println!("Start to listen on http://{}/", addr);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user