chore: trusted single sign-on, preload and redirect_url per opeind conf. Move print to log and error macros
This commit is contained in:
parent
cb5437d1e1
commit
3807582ba5
@ -25,6 +25,9 @@ use crate::defs::Config;
|
|||||||
fn default_empty() -> String { String::from("") }
|
fn default_empty() -> String { String::from("") }
|
||||||
fn default_expire_in() -> u64 { 0 }
|
fn default_expire_in() -> u64 { 0 }
|
||||||
fn default_algorithm() -> String { String::from("RS256") }
|
fn default_algorithm() -> String { String::from("RS256") }
|
||||||
|
fn default_preload() -> bool { false }
|
||||||
|
fn default_trusted() -> bool { false }
|
||||||
|
fn default_signature() -> bool { false }
|
||||||
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
|
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
|
||||||
pub struct OpenidClaims {
|
pub struct OpenidClaims {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
@ -59,9 +62,15 @@ pub struct OpenidData {
|
|||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize,Default)]
|
#[derive(Debug, Clone, Serialize, Deserialize,Default)]
|
||||||
pub struct OpenidConf {
|
pub struct OpenidConf {
|
||||||
|
pub redirect_url: String,
|
||||||
|
#[serde(default = "default_preload")]
|
||||||
|
pub preload: bool,
|
||||||
|
#[serde(default = "default_trusted")]
|
||||||
|
pub trusted: bool,
|
||||||
#[serde(default = "default_algorithm")]
|
#[serde(default = "default_algorithm")]
|
||||||
pub algorithm: String,
|
pub algorithm: String,
|
||||||
pub access_token_url: String,
|
pub access_token_url: String,
|
||||||
|
#[serde(default = "default_signature")]
|
||||||
pub disable_signature: bool,
|
pub disable_signature: bool,
|
||||||
pub endpoint: String,
|
pub endpoint: String,
|
||||||
pub client_id: String,
|
pub client_id: String,
|
||||||
@ -95,12 +104,12 @@ fn handle_error<T: std::error::Error>(fail: &T, msg: &'static str) {
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
impl OpenidConf {
|
impl OpenidConf {
|
||||||
pub async fn client(&self, return_url: String) -> BoxResult<OpenidCli> {
|
pub async fn client(&self) -> BoxResult<OpenidCli> {
|
||||||
let app_client_id = ClientId::new(self.client_id.to_owned());
|
let app_client_id = ClientId::new(self.client_id.to_owned());
|
||||||
let app_client_secret = ClientSecret::new(self.client_secret.to_owned());
|
let app_client_secret = ClientSecret::new(self.client_secret.to_owned());
|
||||||
let issuer_url = IssuerUrl::new(self.endpoint.to_owned())?;
|
let issuer_url = IssuerUrl::new(self.endpoint.to_owned())?;
|
||||||
let provider_metadata = CoreProviderMetadata::discover_async(issuer_url, async_http_client).await?;
|
let provider_metadata = CoreProviderMetadata::discover_async(issuer_url, async_http_client).await?;
|
||||||
let redirect_url = RedirectUrl::new(return_url.to_owned())?;
|
let redirect_url = RedirectUrl::new(self.redirect_url.to_owned())?;
|
||||||
let (pk_challenge, pk_verifier) = PkceCodeChallenge::new_random_sha256();
|
let (pk_challenge, pk_verifier) = PkceCodeChallenge::new_random_sha256();
|
||||||
// Set up the config for the App OAuth2 process.
|
// Set up the config for the App OAuth2 process.
|
||||||
Ok( OpenidCli {
|
Ok( OpenidCli {
|
||||||
@ -114,24 +123,7 @@ impl OpenidConf {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
pub async fn get_auth(&self, openid_cli: &OpenidCli) -> BoxResult<OpenidClient> {
|
|
||||||
// Generate the authorization URL to which we'll redirect the user.
|
|
||||||
//let pk_challenge = openid_cli.pk_challenge.clone();
|
|
||||||
let (url, token, nonce) =
|
|
||||||
openid_cli.client
|
|
||||||
.authorize_url(
|
|
||||||
AuthenticationFlow::<CoreResponseType>::AuthorizationCode,
|
|
||||||
CsrfToken::new_random,
|
|
||||||
Nonce::new_random,
|
|
||||||
)
|
|
||||||
// This example is requesting access to the the user's profile including email.
|
|
||||||
.add_scope(Scope::new("name".to_string()))
|
|
||||||
.add_scope(Scope::new("email".to_string()))
|
|
||||||
// Set the PKCE code challenge.
|
|
||||||
// .set_pkce_challenge(pk_challenge)
|
|
||||||
.url();
|
|
||||||
Ok(OpenidClient { url, token, nonce })
|
|
||||||
}
|
|
||||||
pub async fn get_token(&self, _openid_cli: &OpenidCli, auth_code: String, _str_nonce: String) -> BoxResult<OpenidClaims> {
|
pub async fn get_token(&self, _openid_cli: &OpenidCli, auth_code: String, _str_nonce: String) -> BoxResult<OpenidClaims> {
|
||||||
// let nonce = Nonce::new(str_nonce);
|
// let nonce = Nonce::new(str_nonce);
|
||||||
// this is because PkceCodeVerifier des not have clone derive
|
// this is because PkceCodeVerifier des not have clone derive
|
||||||
@ -176,10 +168,37 @@ impl OpenidConf {
|
|||||||
Ok(res.claims)
|
Ok(res.claims)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub async fn collect_openid_clients(config: Config, return_url: &str) -> HashMap<String,OpenidCli> {
|
impl OpenidCli {
|
||||||
|
pub fn get_auth(&self) -> OpenidClient {
|
||||||
|
// Generate the authorization URL to which we'll redirect the user.
|
||||||
|
//let pk_challenge = openid_cli.pk_challenge.clone();
|
||||||
|
let (url, token, nonce) =
|
||||||
|
self.client
|
||||||
|
.authorize_url(
|
||||||
|
AuthenticationFlow::<CoreResponseType>::AuthorizationCode,
|
||||||
|
CsrfToken::new_random,
|
||||||
|
Nonce::new_random,
|
||||||
|
)
|
||||||
|
// This example is requesting access to the the user's profile including email.
|
||||||
|
.add_scope(Scope::new("name".to_string()))
|
||||||
|
.add_scope(Scope::new("email".to_string()))
|
||||||
|
// Set the PKCE code challenge.
|
||||||
|
// .set_pkce_challenge(pk_challenge)
|
||||||
|
.url();
|
||||||
|
OpenidClient { url, token, nonce }
|
||||||
|
}
|
||||||
|
pub fn get_data(&self, conf_key: &str) -> (String,String) {
|
||||||
|
let openid = self.get_auth();
|
||||||
|
(
|
||||||
|
format!("{}|{}|{}", &conf_key, openid.token.secret(), openid.nonce.secret()),
|
||||||
|
openid.url.to_string()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub async fn collect_openid_clients(config: Config) -> HashMap<String,OpenidCli> {
|
||||||
let mut clients = HashMap::new();
|
let mut clients = HashMap::new();
|
||||||
for (key, openid_conf) in config.openid_auths.clone().into_iter() {
|
for (key, openid_conf) in config.openid_auths.clone().into_iter() {
|
||||||
match openid_conf.client(return_url.to_owned()).await {
|
match openid_conf.client().await {
|
||||||
Ok(cli) => {
|
Ok(cli) => {
|
||||||
clients.insert(key.to_owned(),cli);
|
clients.insert(key.to_owned(),cli);
|
||||||
println!("OpenID {} added", key)
|
println!("OpenID {} added", key)
|
||||||
|
@ -5,7 +5,7 @@ mod admin_handlers;
|
|||||||
mod users;
|
mod users;
|
||||||
|
|
||||||
pub(crate) use users_handlers::users_router_handlers;
|
pub(crate) use users_handlers::users_router_handlers;
|
||||||
pub(crate) use admin_handlers::admin_router_handlers;
|
pub(crate) use admin_handlers::{ admin_router_handlers, is_allowed};
|
||||||
pub(crate) use pages_handlers::pages_router_handlers;
|
pub(crate) use pages_handlers::pages_router_handlers;
|
||||||
pub(crate) use users::{
|
pub(crate) use users::{
|
||||||
login_user,
|
login_user,
|
||||||
|
@ -22,6 +22,7 @@ use crate::{
|
|||||||
ReqHandler,
|
ReqHandler,
|
||||||
ReqHeaderMap,
|
ReqHeaderMap,
|
||||||
AppConnectInfo, TraceData,
|
AppConnectInfo, TraceData,
|
||||||
|
AuthState,
|
||||||
},
|
},
|
||||||
users::{
|
users::{
|
||||||
User,
|
User,
|
||||||
@ -36,6 +37,13 @@ use crate::{
|
|||||||
};
|
};
|
||||||
use crate::users::OpenidUser;
|
use crate::users::OpenidUser;
|
||||||
|
|
||||||
|
pub fn is_allowed(auth_state: &AuthState,auth_roles: &Vec<String>, req_handler: &ReqHandler) -> bool {
|
||||||
|
if ! auth_state.has_auth_role(&auth_roles) {
|
||||||
|
let _ = req_handler.trace_req(format!("Req: {} User '{}' not have role 'dev'", &req_handler.req_name, &auth_state.user_id()));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}
|
||||||
pub fn admin_router_handlers() -> Router {
|
pub fn admin_router_handlers() -> Router {
|
||||||
async fn users_handler(
|
async fn users_handler(
|
||||||
header: HeaderMap,
|
header: HeaderMap,
|
||||||
@ -604,8 +612,7 @@ pub fn admin_router_handlers() -> Router {
|
|||||||
let _ = req_handler.trace_req(format!("No user found"));
|
let _ = req_handler.trace_req(format!("No user found"));
|
||||||
return Redirect::temporary( &format!("/login?o={}",uri.path().to_string())).into_response();
|
return Redirect::temporary( &format!("/login?o={}",uri.path().to_string())).into_response();
|
||||||
}
|
}
|
||||||
if !auth_state.is_admin() {
|
if ! is_allowed(&auth_state,&app_dbs.config.auth_roles,&req_handler) {
|
||||||
let _ = req_handler.trace_req(format!("User: {} is not admin",auth_state.user_id()));
|
|
||||||
return Redirect::temporary( &format!("/login?o={}",uri.path().to_string())).into_response();
|
return Redirect::temporary( &format!("/login?o={}",uri.path().to_string())).into_response();
|
||||||
}
|
}
|
||||||
let mut res_headers = HeaderMap::new();
|
let mut res_headers = HeaderMap::new();
|
||||||
@ -657,8 +664,7 @@ pub fn admin_router_handlers() -> Router {
|
|||||||
let _ = req_handler.trace_req(format!("No user found"));
|
let _ = req_handler.trace_req(format!("No user found"));
|
||||||
return Redirect::temporary( &format!("/login?o={}",uri.path().to_string())).into_response();
|
return Redirect::temporary( &format!("/login?o={}",uri.path().to_string())).into_response();
|
||||||
}
|
}
|
||||||
if !auth_state.is_admin() {
|
if ! is_allowed(&auth_state,&app_dbs.config.auth_roles,&req_handler) {
|
||||||
let _ = req_handler.trace_req(format!("User: {} is not admin",auth_state.user_id()));
|
|
||||||
return Redirect::temporary( &format!("/login?o={}",uri.path().to_string())).into_response();
|
return Redirect::temporary( &format!("/login?o={}",uri.path().to_string())).into_response();
|
||||||
}
|
}
|
||||||
let user_sel = User::select("id", &userid, true,&app_dbs.user_store).await.unwrap_or_default();
|
let user_sel = User::select("id", &userid, true,&app_dbs.user_store).await.unwrap_or_default();
|
||||||
@ -725,8 +731,7 @@ pub fn admin_router_handlers() -> Router {
|
|||||||
"Error"
|
"Error"
|
||||||
).into_response();
|
).into_response();
|
||||||
}
|
}
|
||||||
if !auth_state.is_admin() {
|
if ! is_allowed(&auth_state,&app_dbs.config.auth_roles,&req_handler) {
|
||||||
let _ = req_handler.trace_req(format!("User: {} is not admin",auth_state.user_id()));
|
|
||||||
return (
|
return (
|
||||||
StatusCode::UNAUTHORIZED,
|
StatusCode::UNAUTHORIZED,
|
||||||
res_headers,
|
res_headers,
|
||||||
|
@ -8,6 +8,7 @@ use axum::{
|
|||||||
response::{IntoResponse,Response,Redirect},
|
response::{IntoResponse,Response,Redirect},
|
||||||
};
|
};
|
||||||
use tower_cookies::Cookies;
|
use tower_cookies::Cookies;
|
||||||
|
use log::{trace,error};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
defs::{
|
defs::{
|
||||||
@ -30,8 +31,39 @@ use crate::{
|
|||||||
get_auth_state,
|
get_auth_state,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use crate::users::OpenidUser;
|
use crate::users::{OpenidUser, UserStore};
|
||||||
|
|
||||||
|
pub async fn add_openid_user<'a>(openid_user: OpenidUser, curr_id: i64, curr_name: &str, user_store: &UserStore, req_handler: &ReqHandler<'a>) -> bool {
|
||||||
|
let info_add = format!("user {}/{} ({}) -> {} created -> {}",
|
||||||
|
&openid_user.application,
|
||||||
|
&openid_user.appkey,
|
||||||
|
&openid_user.name,
|
||||||
|
&openid_user.userid,
|
||||||
|
&curr_id
|
||||||
|
);
|
||||||
|
let data_add = format!("{}|{}|{}|{}|{}",
|
||||||
|
&curr_id,
|
||||||
|
&openid_user.application,
|
||||||
|
&openid_user.appkey,
|
||||||
|
&openid_user.name,
|
||||||
|
&openid_user.userid,
|
||||||
|
);
|
||||||
|
match openid_user.add(&user_store).await {
|
||||||
|
Ok(id) => {
|
||||||
|
trace!("{} - {}",&info_add,id);
|
||||||
|
let _ = req_handler.trace_req(format!("user '{}', openid link {} ",
|
||||||
|
&curr_name,
|
||||||
|
&data_add
|
||||||
|
));
|
||||||
|
true
|
||||||
|
},
|
||||||
|
Err(e) => {
|
||||||
|
let _ = req_handler.trace_req(format!("{} error: {}", &info_add, e));
|
||||||
|
error!("{} error -> {:#}",&info_add,e);
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
pub async fn login_user (
|
pub async fn login_user (
|
||||||
header: HeaderMap,
|
header: HeaderMap,
|
||||||
uri: Uri,
|
uri: Uri,
|
||||||
@ -77,23 +109,42 @@ pub async fn login_user (
|
|||||||
"Error openid auth"
|
"Error openid auth"
|
||||||
).into_response();
|
).into_response();
|
||||||
};
|
};
|
||||||
let openid_user = OpenidUser::app_select(&openid_conf.signup_application, &field, &user_login.name, false, &app_dbs.user_store).await.unwrap_or_else(|e| {
|
let mut openid_user = OpenidUser::app_select(&openid_conf.signup_application, &field, &user_login.name, false, &app_dbs.user_store).await.unwrap_or_else(|e| {
|
||||||
println!("Error openid {}/{} select: {}", &openid_conf.signup_application, &user_login.name, e);
|
error!("Error openid {}/{} select: {}", &openid_conf.signup_application, &user_login.name, e);
|
||||||
OpenidUser::default()
|
OpenidUser::default()
|
||||||
});
|
});
|
||||||
|
if openid_user.name.is_empty() && openid_conf.trusted {
|
||||||
|
let user_sel = User::select("name", &user_login.name, false, &app_dbs.user_store).await.unwrap_or_else(|e| {
|
||||||
|
error!("Error select: {}", e);
|
||||||
|
User::default()
|
||||||
|
});
|
||||||
|
if !user_sel.name.is_empty() && user_sel.id > 0 {
|
||||||
|
openid_user = OpenidUser {
|
||||||
|
id: 0,
|
||||||
|
name: user_login.name.to_owned(),
|
||||||
|
application: openid_conf.signup_application.to_owned(),
|
||||||
|
appkey: user_data[0].to_owned(),
|
||||||
|
userid: user_sel.id,
|
||||||
|
description: String::from("created from user"),
|
||||||
|
created: chrono::Utc::now().timestamp().to_string(),
|
||||||
|
lastaccess: String::from(""),
|
||||||
|
};
|
||||||
|
let _ = add_openid_user(openid_user.to_owned(), user_sel.id, &user_login.name, &app_dbs.user_store, &req_handler).await;
|
||||||
|
}
|
||||||
|
}
|
||||||
if openid_user.name.is_empty() {
|
if openid_user.name.is_empty() {
|
||||||
let str_user_data = format!("openid|{}|{}|{}|{}|{}|", &user_data[0], &user_data[1], &user_data[2], &openid_conf.signup_application, &user_login.name);
|
let str_user_data = format!("openid|{}|{}|{}|{}|{}|", &user_data[0], &user_data[1], &user_data[2], &openid_conf.signup_application, &user_login.name);
|
||||||
let session_token = req_handler.new_token();
|
let session_token = req_handler.new_token();
|
||||||
let session_cookie = add_session_cookie(true,&cookies, &session_token, &str_user_data, 0, &app_dbs, "/").await;
|
let session_cookie = add_session_cookie(true, &cookies, &session_token, &str_user_data, 0, &app_dbs, "/").await;
|
||||||
if app_dbs.config.verbose > 1 { println!("session cookie: {}", &session_cookie) };
|
if app_dbs.config.verbose > 1 { println!("session cookie: {}", &session_cookie) };
|
||||||
let _new_auth_state = AuthState::from_cookie(session_cookie.to_string(), &app_dbs).await;
|
let _new_auth_state = AuthState::from_cookie(session_cookie.to_string(), &app_dbs).await;
|
||||||
let _ = req_handler.trace_req(format!("No openid name '{}' found",&openid_user.name));
|
let _ = req_handler.trace_req(format!("No openid name '{}' found", &openid_user.name));
|
||||||
// User not exists
|
// User not exists
|
||||||
return Redirect::temporary( &format!("/login")).into_response();
|
return Redirect::temporary(&format!("/login")).into_response();
|
||||||
}
|
}
|
||||||
(
|
(
|
||||||
User::select("id",&openid_user.userid.to_string(), false, &app_dbs.user_store).await.unwrap_or_else(|e|{
|
User::select("id",&openid_user.userid.to_string(), false, &app_dbs.user_store).await.unwrap_or_else(|e|{
|
||||||
println!("Error select: {}", e);
|
error!("Error select: {}", e);
|
||||||
User::default()
|
User::default()
|
||||||
}),
|
}),
|
||||||
openid_user
|
openid_user
|
||||||
@ -101,7 +152,7 @@ pub async fn login_user (
|
|||||||
} else {
|
} else {
|
||||||
(
|
(
|
||||||
User::select( &field, &user_login.name, false, &app_dbs.user_store).await.unwrap_or_else( | e |{
|
User::select( &field, &user_login.name, false, &app_dbs.user_store).await.unwrap_or_else( | e |{
|
||||||
println ! ("Error select: {}", e);
|
error!("Error select: {}", e);
|
||||||
User::default()
|
User::default()
|
||||||
}),
|
}),
|
||||||
OpenidUser::default()
|
OpenidUser::default()
|
||||||
@ -129,7 +180,7 @@ pub async fn login_user (
|
|||||||
} else {
|
} else {
|
||||||
if verify_password(&user_login.password, &user_sel.password).is_err() {
|
if verify_password(&user_login.password, &user_sel.password).is_err() {
|
||||||
let _ = req_handler.trace_req(format!("user '{}' not valid password: {}", &user_login.name, &user_sel.password));
|
let _ = req_handler.trace_req(format!("user '{}' not valid password: {}", &user_login.name, &user_sel.password));
|
||||||
println!("password NOT valid");
|
error!("password NOT valid");
|
||||||
// TODO
|
// TODO
|
||||||
//return Err(error_page(&SignupError::PasswordsDoNotMatch))
|
//return Err(error_page(&SignupError::PasswordsDoNotMatch))
|
||||||
return (
|
return (
|
||||||
@ -164,7 +215,7 @@ pub async fn login_user (
|
|||||||
},
|
},
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
let _ = req_handler.trace_req(format!("user '{}' TOTP check error: {}", &user_login.name, e));
|
let _ = req_handler.trace_req(format!("user '{}' TOTP check error: {}", &user_login.name, e));
|
||||||
println!("TOTP check: {}", e);
|
error!("TOTP check: {}", e);
|
||||||
return (
|
return (
|
||||||
StatusCode::UNAUTHORIZED,
|
StatusCode::UNAUTHORIZED,
|
||||||
req_handler.req_header.header,
|
req_handler.req_header.header,
|
||||||
@ -196,8 +247,8 @@ pub async fn login_user (
|
|||||||
&openid_user.userid,
|
&openid_user.userid,
|
||||||
);
|
);
|
||||||
match openid_user.update(&app_dbs.user_store).await {
|
match openid_user.update(&app_dbs.user_store).await {
|
||||||
Ok(_) => println!("{}d !", &info_update),
|
Ok(_) => trace!("{}d !", &info_update),
|
||||||
Err(e) => println!("{} error: {}", &info_update, e)
|
Err(e) => error!("{} error: {}", &info_update, e)
|
||||||
}
|
}
|
||||||
return Redirect::temporary( &format!("/")).into_response();
|
return Redirect::temporary( &format!("/")).into_response();
|
||||||
} else if session_user_data.len() > 4 && session_user_data[0] == "openid" && !session_user_data[4].is_empty() && !session_user_data[5].is_empty() {
|
} else if session_user_data.len() > 4 && session_user_data[0] == "openid" && !session_user_data[4].is_empty() && !session_user_data[5].is_empty() {
|
||||||
@ -211,39 +262,13 @@ pub async fn login_user (
|
|||||||
created: chrono::Utc::now().timestamp().to_string(),
|
created: chrono::Utc::now().timestamp().to_string(),
|
||||||
lastaccess: String::from(""),
|
lastaccess: String::from(""),
|
||||||
};
|
};
|
||||||
let info_add = format!("user {}/{} ({}) -> {} created -> {}",
|
if ! add_openid_user(openid_user, curr_id, &user_login.name, &app_dbs.user_store, &req_handler).await {
|
||||||
&openid_user.application,
|
return (
|
||||||
&openid_user.appkey,
|
StatusCode::NOT_FOUND,
|
||||||
&openid_user.name,
|
req_handler.req_header.header,
|
||||||
&openid_user.userid,
|
"Error create openid"
|
||||||
&curr_id
|
).into_response();
|
||||||
);
|
}
|
||||||
let data_add = format!("{}|{}|{}|{}|{}",
|
|
||||||
&curr_id,
|
|
||||||
&openid_user.application,
|
|
||||||
&openid_user.appkey,
|
|
||||||
&openid_user.name,
|
|
||||||
&openid_user.userid,
|
|
||||||
);
|
|
||||||
let str_openid_user_data = match openid_user.add(&app_dbs.user_store).await {
|
|
||||||
Ok(id) => {
|
|
||||||
println!("{} - {}",&info_add,id);
|
|
||||||
data_add
|
|
||||||
},
|
|
||||||
Err(e) => {
|
|
||||||
let _ = req_handler.trace_req(format!("{} error: {}", &info_add, e));
|
|
||||||
println!("{} error -> {:#}",&info_add,e);
|
|
||||||
return (
|
|
||||||
StatusCode::NOT_FOUND,
|
|
||||||
req_handler.req_header.header,
|
|
||||||
"Error create openid"
|
|
||||||
).into_response();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let _ = req_handler.trace_req(format!("user '{}', openid link {} ",
|
|
||||||
&user_login.name,
|
|
||||||
str_openid_user_data
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
req_handler = ReqHandler::new(
|
req_handler = ReqHandler::new(
|
||||||
req_handler.req_header,
|
req_handler.req_header,
|
||||||
|
@ -14,6 +14,7 @@ use axum::{
|
|||||||
Router,
|
Router,
|
||||||
};
|
};
|
||||||
use tower_cookies::{Cookie, Cookies};
|
use tower_cookies::{Cookie, Cookies};
|
||||||
|
use log::{trace,error};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
SESSION_COOKIE_NAME,
|
SESSION_COOKIE_NAME,
|
||||||
@ -45,7 +46,15 @@ use crate::{
|
|||||||
login_user,
|
login_user,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
use crate::users::UserStore;
|
||||||
|
|
||||||
pub fn users_login_router_handlers() -> Router {
|
pub fn users_login_router_handlers() -> Router {
|
||||||
|
async fn get_total_users(store: &UserStore) -> i64 {
|
||||||
|
User::count(store).await.unwrap_or_else(|e|{
|
||||||
|
trace!("Count error: {}",e);
|
||||||
|
0
|
||||||
|
})
|
||||||
|
}
|
||||||
async fn signup_handler(
|
async fn signup_handler(
|
||||||
header: HeaderMap,
|
header: HeaderMap,
|
||||||
uri: Uri,
|
uri: Uri,
|
||||||
@ -64,20 +73,13 @@ pub fn users_login_router_handlers() -> Router {
|
|||||||
"signup_handler"
|
"signup_handler"
|
||||||
);
|
);
|
||||||
if !auth_state.is_admin() {
|
if !auth_state.is_admin() {
|
||||||
let total_users = User::count(&app_dbs.user_store).await.unwrap_or_else(|e|{
|
let total_users = get_total_users(&app_dbs.user_store).await;
|
||||||
println!("Count error: {}",e);
|
|
||||||
0
|
|
||||||
});
|
|
||||||
if ! app_dbs.config.signup_mode.contains("open") && total_users != 0 {
|
if ! app_dbs.config.signup_mode.contains("open") && total_users != 0 {
|
||||||
let msg = format!("Config signup mode not open: {}", app_dbs.config.signup_mode);
|
let msg = format!("Config signup mode not open: {}", app_dbs.config.signup_mode);
|
||||||
println!("{}",&msg);
|
trace!("{}",&msg);
|
||||||
let _ = req_handler.trace_req(msg);
|
let _ = req_handler.trace_req(msg);
|
||||||
return Redirect::temporary( &format!("/")).into_response();
|
return Redirect::temporary( &format!("/")).into_response();
|
||||||
}
|
}
|
||||||
let total_users = User::count(&app_dbs.user_store).await.unwrap_or_else(|e|{
|
|
||||||
println!("Count error: {}",e);
|
|
||||||
-1
|
|
||||||
});
|
|
||||||
// Fake to insert firt time admin user ...
|
// Fake to insert firt time admin user ...
|
||||||
if total_users < 1 {
|
if total_users < 1 {
|
||||||
let isadmin= String::from("TRUE");
|
let isadmin= String::from("TRUE");
|
||||||
@ -101,7 +103,7 @@ pub fn users_login_router_handlers() -> Router {
|
|||||||
req_handler.context.insert("totp_algorithm",&format!("{}",&app_dbs.config.totp_algorithm));
|
req_handler.context.insert("totp_algorithm",&format!("{}",&app_dbs.config.totp_algorithm));
|
||||||
},
|
},
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
println!("Error TOTP generartor: {}",e);
|
error!("Error TOTP generartor: {}",e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -198,7 +200,7 @@ pub fn users_login_router_handlers() -> Router {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
println!("TOTP check: {}", e);
|
error!("TOTP check: {}", e);
|
||||||
let _ = req_handler.trace_req(format!("User '{}' TOTP check error: {}",&user_data.name,e));
|
let _ = req_handler.trace_req(format!("User '{}' TOTP check error: {}",&user_data.name,e));
|
||||||
return (
|
return (
|
||||||
StatusCode::UNAUTHORIZED,
|
StatusCode::UNAUTHORIZED,
|
||||||
@ -229,12 +231,7 @@ pub fn users_login_router_handlers() -> Router {
|
|||||||
} else {
|
} else {
|
||||||
DEFAULT_ROLES.to_owned()
|
DEFAULT_ROLES.to_owned()
|
||||||
};
|
};
|
||||||
let total_users = User::count(&app_dbs.user_store).await.unwrap_or_else(|e|{
|
let is_admin = if user_data.id == "A" || get_total_users(&app_dbs.user_store).await < 1 {
|
||||||
let _ = req_handler.trace_req( format!("Users count error: {}",e));
|
|
||||||
println!("Count error: {}",e);
|
|
||||||
-1
|
|
||||||
});
|
|
||||||
let isadmin = if user_data.id == "A" || total_users < 1 {
|
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
@ -258,7 +255,7 @@ pub fn users_login_router_handlers() -> Router {
|
|||||||
lastaccess: String::from(""),
|
lastaccess: String::from(""),
|
||||||
status: UserStatus::Created,
|
status: UserStatus::Created,
|
||||||
items: User::json_items(new_items),
|
items: User::json_items(new_items),
|
||||||
isadmin,
|
isadmin: is_admin,
|
||||||
roles,
|
roles,
|
||||||
};
|
};
|
||||||
let usr_sel = User::select("name", &user_data.name, false, &app_dbs.user_store).await.unwrap_or_default();
|
let usr_sel = User::select("name", &user_data.name, false, &app_dbs.user_store).await.unwrap_or_default();
|
||||||
@ -273,12 +270,12 @@ pub fn users_login_router_handlers() -> Router {
|
|||||||
}
|
}
|
||||||
let str_user_data = match user.add(&app_dbs.user_store).await {
|
let str_user_data = match user.add(&app_dbs.user_store).await {
|
||||||
Ok(id) => {
|
Ok(id) => {
|
||||||
println!("user {} created -> {}", &user_data.name, id);
|
trace!("user {} created -> {}", &user_data.name, id);
|
||||||
format!("{}|{}|{}",id, &user_data.name, &user_data.roles)
|
format!("{}|{}|{}",id, &user_data.name, &user_data.roles)
|
||||||
},
|
},
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
let _ = req_handler.trace_req(format!("User '{}' create error: {}",&user_data.name,e));
|
let _ = req_handler.trace_req(format!("User '{}' create error: {}",&user_data.name,e));
|
||||||
println!("user {} error -> {:#}", &user_data.name, e);
|
error!("user {} error -> {:#}", &user_data.name, e);
|
||||||
return (
|
return (
|
||||||
StatusCode::NOT_FOUND,
|
StatusCode::NOT_FOUND,
|
||||||
req_handler.req_header.header,
|
req_handler.req_header.header,
|
||||||
@ -313,12 +310,7 @@ pub fn users_login_router_handlers() -> Router {
|
|||||||
&random,
|
&random,
|
||||||
"login_handler"
|
"login_handler"
|
||||||
);
|
);
|
||||||
let total_users = User::count(&app_dbs.user_store).await.unwrap_or_else(|e|{
|
if get_total_users(&app_dbs.user_store).await < 1 {
|
||||||
let _ = req_handler.trace_req( format!("Users count error: {}",e));
|
|
||||||
println!("Count error: {}",e);
|
|
||||||
-1
|
|
||||||
});
|
|
||||||
if total_users < 1 {
|
|
||||||
let _ = req_handler.trace_req(String::from("No users found"));
|
let _ = req_handler.trace_req(String::from("No users found"));
|
||||||
return Redirect::temporary( &format!("/signup")).into_response();
|
return Redirect::temporary( &format!("/signup")).into_response();
|
||||||
}
|
}
|
||||||
@ -370,12 +362,7 @@ pub fn users_login_router_handlers() -> Router {
|
|||||||
&random,
|
&random,
|
||||||
"login_handler"
|
"login_handler"
|
||||||
);
|
);
|
||||||
let total_users = User::count(&app_dbs.user_store).await.unwrap_or_else(|e|{
|
if get_total_users(&app_dbs.user_store).await < 1 {
|
||||||
let _ = req_handler.trace_req( format!("Users count error: {}",e));
|
|
||||||
println!("Count error: {}",e);
|
|
||||||
-1
|
|
||||||
});
|
|
||||||
if total_users < 1 {
|
|
||||||
let _ = req_handler.trace_req(String::from("No users found"));
|
let _ = req_handler.trace_req(String::from("No users found"));
|
||||||
return Redirect::temporary( &format!("/signup")).into_response();
|
return Redirect::temporary( &format!("/signup")).into_response();
|
||||||
}
|
}
|
||||||
@ -383,34 +370,24 @@ pub fn users_login_router_handlers() -> Router {
|
|||||||
return Redirect::temporary( &format!("/login")).into_response();
|
return Redirect::temporary( &format!("/login")).into_response();
|
||||||
}
|
}
|
||||||
let (str_user_data,url) = if let Some(openid_conf) = app_dbs.config.openid_auths.get(&data) {
|
let (str_user_data,url) = if let Some(openid_conf) = app_dbs.config.openid_auths.get(&data) {
|
||||||
if let Some(openid_cli) = openid_clients.get(&data) {
|
if openid_conf.preload {
|
||||||
match openid_conf.get_auth(openid_cli).await {
|
if let Some(openid_cli) = openid_clients.get(&data) {
|
||||||
Ok(openid) => {
|
openid_cli.get_data(&data)
|
||||||
//let _ = req_handler.trace_req(format!("User '{}' created",&user_data.name));
|
} else {
|
||||||
let str_user_data = format!("{}|{}|{}", &data, openid.token.secret(), openid.nonce.secret());
|
error!("Error openid login handler: {}", &data);
|
||||||
//let session_cookie = add_session_cookie(true,&cookies, &session_token, &str_user_data, 0, &app_dbs, "/").await;
|
(String::from(""), String::from("/login"))
|
||||||
//if app_dbs.config.verbose > 1 { println!("session cookie: {}", &session_cookie) };
|
}
|
||||||
//let _new_auth_state = AuthState::from_cookie(session_cookie.to_string(), &app_dbs).await;
|
} else {
|
||||||
/*req_handler = ReqHandler::new(
|
match openid_conf.client().await {
|
||||||
req_handler.req_header,
|
Ok(openid_cli) => openid_cli.get_data(&data),
|
||||||
&app_dbs,
|
|
||||||
&uri,
|
|
||||||
&new_auth_state,
|
|
||||||
&random,
|
|
||||||
"post_login_handler"
|
|
||||||
);*/
|
|
||||||
//let _ = req_handler.trace_req(format!("user '{}', new token: '{}', cookie: '{}' ",&user_login.name, &session_token, &session_cookie));
|
|
||||||
(str_user_data, format!("{}", openid.url.to_string()))
|
|
||||||
},
|
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
println!("Error openid login handler: {}", e);
|
error!("Error openid client data found for {} handler: {}", &data, e);
|
||||||
(String::from(""), String::from("/login"))
|
(String::from(""), String::from("/login"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
(String::from(""), String::from("/login"))
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
error!("Error no openid client found for: {}", &data);
|
||||||
(String::from(""), String::from("/login"))
|
(String::from(""), String::from("/login"))
|
||||||
};
|
};
|
||||||
let session_token = req_handler.new_token();
|
let session_token = req_handler.new_token();
|
||||||
@ -461,7 +438,7 @@ pub fn users_login_router_handlers() -> Router {
|
|||||||
println!("State {} not found=", data.state);
|
println!("State {} not found=", data.state);
|
||||||
return Redirect::temporary(&format!("/login")).into_response();
|
return Redirect::temporary(&format!("/login")).into_response();
|
||||||
}
|
}
|
||||||
println!("OK State {} == {}", user_data[1], data.state);
|
// println!("OK State {} == {}", user_data[1], data.state);
|
||||||
let mut user_login = UserLogin::default();
|
let mut user_login = UserLogin::default();
|
||||||
if let Some(openid_conf) = app_dbs.config.openid_auths.get(&user_data[0]) {
|
if let Some(openid_conf) = app_dbs.config.openid_auths.get(&user_data[0]) {
|
||||||
if let Some(openid_cli) = openid_clients.get(&user_data[0]) {
|
if let Some(openid_cli) = openid_clients.get(&user_data[0]) {
|
||||||
@ -475,7 +452,7 @@ pub fn users_login_router_handlers() -> Router {
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
println!("Error openid login handler: {}", e);
|
error!("Error openid login handler: {}", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@ use axum::{
|
|||||||
Router,
|
Router,
|
||||||
};
|
};
|
||||||
use tower_cookies::Cookies;
|
use tower_cookies::Cookies;
|
||||||
|
use log::{trace,error};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
route,
|
route,
|
||||||
@ -34,6 +35,7 @@ use crate::{
|
|||||||
handlers::{
|
handlers::{
|
||||||
add_session_cookie,
|
add_session_cookie,
|
||||||
get_auth_state,
|
get_auth_state,
|
||||||
|
is_allowed,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -56,7 +58,7 @@ pub fn users_settings_router_handlers() -> Router {
|
|||||||
// let uri_path = format!("{}",&uri.path().to_string());
|
// let uri_path = format!("{}",&uri.path().to_string());
|
||||||
// let file = "hello.html";
|
// let file = "hello.html";
|
||||||
// let result = app_dbs.tera.render(&file, &app_dbs.context).unwrap_or_else(|e|{
|
// let result = app_dbs.tera.render(&file, &app_dbs.context).unwrap_or_else(|e|{
|
||||||
// println!("Error render {}: {}",&file,e);
|
// error!("Error render {}: {}",&file,e);
|
||||||
// String::from("")
|
// String::from("")
|
||||||
// });
|
// });
|
||||||
// req_handler.context.insert("with_menu", "1");
|
// req_handler.context.insert("with_menu", "1");
|
||||||
@ -106,7 +108,7 @@ pub fn users_settings_router_handlers() -> Router {
|
|||||||
return Redirect::temporary( &format!("/")).into_response();
|
return Redirect::temporary( &format!("/")).into_response();
|
||||||
}
|
}
|
||||||
let openid_sel = OpenidUser::list_selection("userid", &user_sel.id.to_string(), &app_dbs.user_store, true,false, "|").await.unwrap_or_else(|e| {
|
let openid_sel = OpenidUser::list_selection("userid", &user_sel.id.to_string(), &app_dbs.user_store, true,false, "|").await.unwrap_or_else(|e| {
|
||||||
println!("Error list selection {}: {}", &user_sel.name, e);
|
error!("Error list selection {}: {}", &user_sel.name, e);
|
||||||
Vec::new()
|
Vec::new()
|
||||||
});
|
});
|
||||||
req_handler.context.insert("openid_sel", &openid_sel);
|
req_handler.context.insert("openid_sel", &openid_sel);
|
||||||
@ -173,7 +175,7 @@ pub fn users_settings_router_handlers() -> Router {
|
|||||||
return Redirect::temporary( &format!("/")).into_response();
|
return Redirect::temporary( &format!("/")).into_response();
|
||||||
}
|
}
|
||||||
let openid_sel = OpenidUser::list_selection("userid", &user_sel.id.to_string(), &app_dbs.user_store, true,false, "|").await.unwrap_or_else(|e| {
|
let openid_sel = OpenidUser::list_selection("userid", &user_sel.id.to_string(), &app_dbs.user_store, true,false, "|").await.unwrap_or_else(|e| {
|
||||||
println!("Error list selection {}: {}", &user_sel.name, e);
|
error!("Error list selection {}: {}", &user_sel.name, e);
|
||||||
Vec::new()
|
Vec::new()
|
||||||
});
|
});
|
||||||
req_handler.context.insert("openid_sel", &openid_sel);
|
req_handler.context.insert("openid_sel", &openid_sel);
|
||||||
@ -193,7 +195,7 @@ pub fn users_settings_router_handlers() -> Router {
|
|||||||
req_handler.context.insert("otp_qr", &totp.get_qr_base64().unwrap_or_default());
|
req_handler.context.insert("otp_qr", &totp.get_qr_base64().unwrap_or_default());
|
||||||
},
|
},
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
println!("User settings error totp: {}",e);
|
error!("User settings error totp: {}",e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -204,7 +206,7 @@ pub fn users_settings_router_handlers() -> Router {
|
|||||||
req_handler.context.insert("otp_qr", &totp.get_qr_base64().unwrap_or_default());
|
req_handler.context.insert("otp_qr", &totp.get_qr_base64().unwrap_or_default());
|
||||||
},
|
},
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
println!("Error TOTP generartor: {}",e);
|
error!("Error TOTP generartor: {}",e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -278,7 +280,7 @@ pub fn users_settings_router_handlers() -> Router {
|
|||||||
user_sel.password = generate_hash(&user_data.password);
|
user_sel.password = generate_hash(&user_data.password);
|
||||||
}
|
}
|
||||||
//let openid_sel = OpenidUser::list_selection("userid", &user_sel.id.to_string(), &app_dbs.user_store, true,false, "|").await.unwrap_or_else(|e| {
|
//let openid_sel = OpenidUser::list_selection("userid", &user_sel.id.to_string(), &app_dbs.user_store, true,false, "|").await.unwrap_or_else(|e| {
|
||||||
// println!("Error list selection {}: {}", &user_sel.name, e);
|
// error!("Error list selection {}: {}", &user_sel.name, e);
|
||||||
// Vec::new()
|
// Vec::new()
|
||||||
//});
|
//});
|
||||||
//let openid_sel_appkeys = openid_sel.iter().map(|id| id.appkey.to_string()).collect::<Vec<String>>().join(",");
|
//let openid_sel_appkeys = openid_sel.iter().map(|id| id.appkey.to_string()).collect::<Vec<String>>().join(",");
|
||||||
@ -299,7 +301,7 @@ pub fn users_settings_router_handlers() -> Router {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
println!("TOTP check: {}", e);
|
error!("TOTP check: {}", e);
|
||||||
let _ = req_handler.trace_req(format!("User '{}' TOTP check error: {}",&user_id,e));
|
let _ = req_handler.trace_req(format!("User '{}' TOTP check error: {}",&user_id,e));
|
||||||
return (
|
return (
|
||||||
StatusCode::UNAUTHORIZED,
|
StatusCode::UNAUTHORIZED,
|
||||||
@ -361,7 +363,7 @@ pub fn users_settings_router_handlers() -> Router {
|
|||||||
Extension(cookies): Extension<Cookies>,
|
Extension(cookies): Extension<Cookies>,
|
||||||
Extension(random): Extension<Random>,
|
Extension(random): Extension<Random>,
|
||||||
ConnectInfo(app_connect_info): ConnectInfo<AppConnectInfo>,
|
ConnectInfo(app_connect_info): ConnectInfo<AppConnectInfo>,
|
||||||
Json(_user_item): Json<UserItem>,
|
Json(user_item): Json<UserItem>,
|
||||||
//_auth_state: AuthState,
|
//_auth_state: AuthState,
|
||||||
//axum::extract::Path(data): axum::extract::Path<String>,
|
//axum::extract::Path(data): axum::extract::Path<String>,
|
||||||
) -> Response {
|
) -> Response {
|
||||||
@ -374,7 +376,8 @@ pub fn users_settings_router_handlers() -> Router {
|
|||||||
&random,
|
&random,
|
||||||
"update_user_item_handler"
|
"update_user_item_handler"
|
||||||
);
|
);
|
||||||
if ! auth_state.has_auth_role(&app_dbs.config.auth_roles) {
|
trace!("user_item: {} = {}",&user_item.name,&user_item.value);
|
||||||
|
if ! is_allowed(&auth_state,&app_dbs.config.auth_roles,&req_handler) {
|
||||||
let _ = req_handler.trace_req(format!("User '{}' not have role 'dev'",&auth_state.user_id()));
|
let _ = req_handler.trace_req(format!("User '{}' not have role 'dev'",&auth_state.user_id()));
|
||||||
return Redirect::temporary( &format!("/login?o={}",uri.path().to_string())).into_response();
|
return Redirect::temporary( &format!("/login?o={}",uri.path().to_string())).into_response();
|
||||||
// return (
|
// return (
|
||||||
|
@ -267,7 +267,7 @@ async fn main() {
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
let openid_clients = Arc::new(
|
let openid_clients = Arc::new(
|
||||||
collect_openid_clients(config.to_owned(), "https://tiicl.tls13.io:8800/from_openid?response_type=code").await
|
collect_openid_clients(config.to_owned()).await
|
||||||
);
|
);
|
||||||
let middleware =
|
let middleware =
|
||||||
axum::middleware::from_fn_with_state(app_dbs.clone(),rewrite_request_uri);
|
axum::middleware::from_fn_with_state(app_dbs.clone(),rewrite_request_uri);
|
||||||
|
Loading…
Reference in New Issue
Block a user