chore: refactoring handlers add code to handle opendid and single sign-on
This commit is contained in:
parent
1f5c4bad4f
commit
03215df72a
@ -2,10 +2,18 @@ mod users_handlers;
|
||||
mod other_handlers;
|
||||
mod pages_handlers;
|
||||
mod admin_handlers;
|
||||
mod users;
|
||||
|
||||
pub(crate) use users_handlers::users_router_handlers;
|
||||
pub(crate) use admin_handlers::admin_router_handlers;
|
||||
pub(crate) use pages_handlers::pages_router_handlers;
|
||||
pub(crate) use users::{
|
||||
login_user,
|
||||
users_login_router_handlers,
|
||||
users_password_router_handlers,
|
||||
users_settings_router_handlers,
|
||||
users_invite_router_handlers,
|
||||
};
|
||||
|
||||
pub(crate) use other_handlers::{
|
||||
rewrite_request_uri,
|
||||
|
@ -27,12 +27,15 @@ use crate::{
|
||||
User,
|
||||
UserItem,
|
||||
UserStatus,
|
||||
AllUserData,
|
||||
},
|
||||
handlers::{
|
||||
add_session_cookie,
|
||||
get_auth_state,
|
||||
},
|
||||
};
|
||||
use crate::users::OpenidUser;
|
||||
|
||||
pub fn admin_router_handlers() -> Router {
|
||||
async fn users_handler(
|
||||
header: HeaderMap,
|
||||
@ -55,7 +58,7 @@ pub fn admin_router_handlers() -> Router {
|
||||
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();
|
||||
}
|
||||
let usrs = match User::list(&app_dbs.user_store, true, false, "").await {
|
||||
let users = match User::list(&app_dbs.user_store, true, false, "").await {
|
||||
Ok(data) => data,
|
||||
Err(e) => {
|
||||
let _ = req_handler.trace_req(format!("Error list users: {}",e));
|
||||
@ -63,8 +66,19 @@ pub fn admin_router_handlers() -> Router {
|
||||
Vec::new()
|
||||
},
|
||||
};
|
||||
req_handler.context.insert("usrs", &usrs);
|
||||
req_handler.context.insert("total_usrs", &usrs.len());
|
||||
req_handler.context.insert("users", &users);
|
||||
let mut users_openids = Vec::new();
|
||||
for usr in users.iter() {
|
||||
let openid_sel = OpenidUser::list_selection(
|
||||
"userid", &usr.id.to_string(), &app_dbs.user_store, true,false, "|"
|
||||
).await.unwrap_or_else(|e| {
|
||||
println!("Error list selection {}: {}", &usr.name, e);
|
||||
Vec::new()
|
||||
});
|
||||
users_openids.push(openid_sel.iter().map(|id| id.appkey.to_string()).collect::<Vec<String>>().join(","));
|
||||
}
|
||||
req_handler.context.insert("users_openids", &users_openids);
|
||||
req_handler.context.insert("total_usrs", &users.len());
|
||||
req_handler.context.insert("with_menu", "1");
|
||||
let mut res_headers = HeaderMap::new();
|
||||
if req_handler.req_header.is_browser() {
|
||||
@ -138,13 +152,21 @@ pub fn admin_router_handlers() -> Router {
|
||||
}
|
||||
user_sel.password = String::from("");
|
||||
user_sel.otp_base32 = String::from("");
|
||||
let result = serde_json::to_string(&user_sel).unwrap_or_else(|e|{
|
||||
let msg = format!("Error to convert user items to json: {}",e);
|
||||
println!("{}", &msg);
|
||||
let _ = req_handler.trace_req(msg);
|
||||
String::from("")
|
||||
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);
|
||||
Vec::new()
|
||||
});
|
||||
let user_openids = openid_sel.iter().map(|id| id.appkey.to_string()).collect::<Vec<String>>().join(",");
|
||||
let str_user = serde_json::to_string(&user_sel).unwrap_or_else(|e|{
|
||||
let msg = format!("Error to convert user data items to json: {}",e);
|
||||
println!("{}", &msg);
|
||||
let _ = req_handler.trace_req(msg);
|
||||
String::from("")
|
||||
});
|
||||
let _ = req_handler.trace_req(format!("User: {} get data", &user_sel.id));
|
||||
let result = format!("{{\"user\": {}, \"openids\": \"{}\"}}",str_user, user_openids);
|
||||
(
|
||||
res_headers,
|
||||
result.to_owned()
|
||||
@ -157,7 +179,7 @@ pub fn admin_router_handlers() -> Router {
|
||||
Extension(cookies): Extension<Cookies>,
|
||||
Extension(random): Extension<Random>,
|
||||
ConnectInfo(app_connect_info): ConnectInfo<AppConnectInfo>,
|
||||
Json(new_user): Json<User>,
|
||||
Json(new_user): Json<AllUserData>,
|
||||
) -> Response {
|
||||
let auth_state = get_auth_state(true, &cookies, &app_dbs).await;
|
||||
let req_handler = ReqHandler::new(
|
||||
@ -194,7 +216,7 @@ pub fn admin_router_handlers() -> Router {
|
||||
"Error"
|
||||
).into_response();
|
||||
}
|
||||
let mut user_sel = User::select("id", &format!("{}",&new_user.id), false,&app_dbs.user_store).await.unwrap_or_default();
|
||||
let mut user_sel = User::select("id", &format!("{}",&new_user.user.id), false,&app_dbs.user_store).await.unwrap_or_default();
|
||||
if user_sel.name.is_empty() {
|
||||
// User not exists
|
||||
return (
|
||||
@ -203,7 +225,8 @@ pub fn admin_router_handlers() -> Router {
|
||||
"Error"
|
||||
).into_response();
|
||||
}
|
||||
user_sel.from_user(new_user);
|
||||
let new_id = new_user.user.id;
|
||||
user_sel.from_user(new_user.user);
|
||||
let user_data = user_sel.session_data();
|
||||
if user_sel.update(&app_dbs.user_store).await.is_err() {
|
||||
return (
|
||||
@ -215,6 +238,7 @@ pub fn admin_router_handlers() -> Router {
|
||||
let session_token = req_handler.new_token();
|
||||
let session_cookie = add_session_cookie(true,&cookies, &session_token, &user_data, 0, &app_dbs, "/").await;
|
||||
if app_dbs.config.verbose > 1 { println!("session cookie: {}", &session_cookie) };
|
||||
OpenidUser::sync_ids(&new_id.to_string(), &new_user.openids, &app_dbs.user_store).await;
|
||||
let result = String::from("Ok");
|
||||
(
|
||||
res_headers,
|
||||
@ -277,9 +301,11 @@ pub fn admin_router_handlers() -> Router {
|
||||
"Error"
|
||||
).into_response();
|
||||
}
|
||||
|
||||
let result = match User::delete(user_sel.id,&app_dbs.user_store).await {
|
||||
Ok(val) => if val {
|
||||
let _ = req_handler.trace_req(format!("User '{}' delete",&user_id));
|
||||
OpenidUser::sync_ids(&user_sel.id.to_string(), "", &app_dbs.user_store).await;
|
||||
format!("Ok")
|
||||
} else {
|
||||
let _ = req_handler.trace_req(format!("Error delete user '{}'" ,&user_id));
|
||||
|
11
src/handlers/users.rs
Normal file
11
src/handlers/users.rs
Normal file
@ -0,0 +1,11 @@
|
||||
mod login_handlers;
|
||||
mod password_handlers;
|
||||
mod settings_handlers;
|
||||
mod invite_handlers;
|
||||
mod login;
|
||||
|
||||
pub(crate) use login::login_user;
|
||||
pub(crate) use login_handlers::users_login_router_handlers;
|
||||
pub(crate) use password_handlers::users_password_router_handlers;
|
||||
pub(crate) use invite_handlers::users_invite_router_handlers;
|
||||
pub(crate) use settings_handlers::users_settings_router_handlers;
|
345
src/handlers/users/invite_handlers.rs
Normal file
345
src/handlers/users/invite_handlers.rs
Normal file
@ -0,0 +1,345 @@
|
||||
use std::sync::Arc;
|
||||
use urlencoding::{encode,decode};
|
||||
use axum::{
|
||||
http::{
|
||||
StatusCode,
|
||||
Uri,
|
||||
header::HeaderMap,
|
||||
},
|
||||
Json,
|
||||
routing::{get,post},
|
||||
Extension,
|
||||
extract::ConnectInfo,
|
||||
response::{IntoResponse,Response,Redirect},
|
||||
Router,
|
||||
};
|
||||
use tower_cookies::Cookies;
|
||||
|
||||
use crate::{
|
||||
route,
|
||||
defs::{
|
||||
AppDBs,
|
||||
AuthState,
|
||||
ReqHandler,
|
||||
ReqHeaderMap,
|
||||
MailMessage,
|
||||
Random,
|
||||
AppConnectInfo,
|
||||
},
|
||||
users::{
|
||||
User,
|
||||
UserStatus,
|
||||
UserInvitation,
|
||||
},
|
||||
handlers::{
|
||||
add_session_cookie,
|
||||
get_auth_state,
|
||||
},
|
||||
};
|
||||
pub fn users_invite_router_handlers() -> Router {
|
||||
async fn invite_signup_handler(
|
||||
header: HeaderMap,
|
||||
uri: Uri,
|
||||
Extension(app_dbs): Extension<Arc<AppDBs>>,
|
||||
Extension(cookies): Extension<Cookies>,
|
||||
Extension(random): Extension<Random>,
|
||||
ConnectInfo(app_connect_info): ConnectInfo<AppConnectInfo>,
|
||||
axum::extract::Path(data): axum::extract::Path<String>,
|
||||
// auth_state: AuthState,
|
||||
) -> Response {
|
||||
let auth_state = get_auth_state(true, &cookies, &app_dbs).await;
|
||||
let mut req_handler = ReqHandler::new(
|
||||
ReqHeaderMap::new(header, &format!("{}",&uri.path().to_string()), &app_connect_info),
|
||||
&app_dbs,
|
||||
&uri,
|
||||
&auth_state,
|
||||
&random,
|
||||
"invite_signup_handler"
|
||||
);
|
||||
if ! app_dbs.config.signup_mode.contains("invitation") {
|
||||
let msg = format!("Config signup mode not invitation: {}",
|
||||
app_dbs.config.signup_mode
|
||||
);
|
||||
println!("{}", &msg);
|
||||
let _ = req_handler.trace_req(msg);
|
||||
return Redirect::temporary( &format!("/")).into_response();
|
||||
}
|
||||
// println!("root_handler: {}",&session_cookie);
|
||||
let session_cookie = decode(&data).unwrap_or_default().to_string();
|
||||
let auth_state = AuthState::from_cookie(session_cookie.to_owned(), &app_dbs).await;
|
||||
if auth_state.session.is_none() {
|
||||
// TODO make it prettier
|
||||
let _ = req_handler.trace_req(format!("No session found"));
|
||||
return (
|
||||
StatusCode::NOT_FOUND,
|
||||
req_handler.req_header.header,
|
||||
"No valid invitation found"
|
||||
).into_response();
|
||||
}
|
||||
//let user_data = auth_state.user_data();
|
||||
let mut usr = User::default();
|
||||
usr.roles = auth_state.user_roles();
|
||||
usr.email = auth_state.user_email();
|
||||
let usr_id = auth_state.user_id();
|
||||
let invite_id = if usr_id == "0" {
|
||||
usr_id
|
||||
} else {
|
||||
usr.email.to_owned()
|
||||
};
|
||||
// let _uri_path = format!("{}",&uri.path().to_string());
|
||||
// let file = "hello.html";
|
||||
// let result = app_dbs.tera.render(&file, &app_dbs.context).unwrap_or_else(|e|{
|
||||
// println!("Error render {}: {}",&file,e);
|
||||
// String::from("")
|
||||
// });
|
||||
|
||||
let mut res_headers = HeaderMap::new();
|
||||
if req_handler.req_header.is_browser() {
|
||||
res_headers.append(axum::http::header::CONTENT_TYPE,"text/html; charset=utf-8".parse().unwrap());
|
||||
}
|
||||
req_handler.context.insert("user", &usr);
|
||||
req_handler.context.insert("isadmin", "");
|
||||
req_handler.context.insert("totp_mode", &format!("{}",&app_dbs.config.totp_mode));
|
||||
req_handler.context.insert("invite_key", &data);
|
||||
req_handler.context.insert("invite_id", &invite_id);
|
||||
req_handler.context.insert("admin_fields", &app_dbs.config.admin_fields);
|
||||
let result = if let Some(tpl) = app_dbs.config.tpls.get("signup") {
|
||||
req_handler.render_template(&tpl,"signup")
|
||||
} else {
|
||||
String::from("signup")
|
||||
};
|
||||
let _ = req_handler.trace_req(format!("Invite to '{}' data: {}",&invite_id, &data));
|
||||
(
|
||||
res_headers,
|
||||
result.to_owned()
|
||||
).into_response()
|
||||
}
|
||||
async fn post_invite_handler(
|
||||
header: HeaderMap,
|
||||
uri: Uri,
|
||||
Extension(app_dbs): Extension<Arc<AppDBs>>,
|
||||
Extension(cookies): Extension<Cookies>,
|
||||
Extension(random): Extension<Random>,
|
||||
ConnectInfo(app_connect_info): ConnectInfo<AppConnectInfo>,
|
||||
Json(user_invite): Json<UserInvitation>,
|
||||
) -> Response {
|
||||
let auth_state = get_auth_state(true, &cookies, &app_dbs).await;
|
||||
let mut req_handler = ReqHandler::new(
|
||||
ReqHeaderMap::new(header, &format!("{}",&uri.path().to_string()), &app_connect_info),
|
||||
&app_dbs,
|
||||
&uri,
|
||||
&auth_state,
|
||||
&random,
|
||||
"post_invite_handler"
|
||||
);
|
||||
if ! app_dbs.config.signup_mode.contains("invitation") {
|
||||
let msg = format!("Config signup mode not invitation: {}",
|
||||
app_dbs.config.signup_mode
|
||||
);
|
||||
println!("{}", &msg);
|
||||
let _ = req_handler.trace_req(msg);
|
||||
return Redirect::temporary( &format!("/")).into_response();
|
||||
}
|
||||
if ! auth_state.has_auth_role(&app_dbs.config.auth_roles) {
|
||||
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 (
|
||||
// StatusCode::UNAUTHORIZED,
|
||||
// header,
|
||||
// "Error authorization"
|
||||
// ).into_response();
|
||||
}
|
||||
if ! user_invite.email.contains("@") {
|
||||
let _ = req_handler.trace_req(format!("Invite email '{}' not contains '@'",&user_invite.email));
|
||||
return (
|
||||
StatusCode::BAD_REQUEST,
|
||||
req_handler.req_header.header,
|
||||
"Error invitation data"
|
||||
).into_response();
|
||||
}
|
||||
let session_token = req_handler.new_token();
|
||||
let mut usr = User::default();
|
||||
usr.email = user_invite.email.to_owned();
|
||||
usr.roles = user_invite.roles.to_owned();
|
||||
usr.isadmin = user_invite.isadmin;
|
||||
usr.status = UserStatus::Pending;
|
||||
let user_data = usr.session_data();
|
||||
let session_cookie = add_session_cookie(false,&cookies, &session_token, &user_data, user_invite.expire, &app_dbs, "invitation").await;
|
||||
let session_encoded_key = encode(session_cookie.as_str());
|
||||
let body=format!("This is an invitation to docserver service");
|
||||
let subject = format!("DocServer Invitation");
|
||||
let signup_url= format!(
|
||||
"{}://{}/signup",
|
||||
&app_dbs.config.protocol,
|
||||
&app_dbs.config.hostport,
|
||||
);
|
||||
let invite_expiration = format!("{} minutes",
|
||||
(&app_dbs.config.session_expire/60)
|
||||
);
|
||||
req_handler.context.insert("signup_url", &signup_url);
|
||||
req_handler.context.insert("invite_expiration", &invite_expiration);
|
||||
req_handler.context.insert("email_body",&body);
|
||||
req_handler.context.insert("invite_key",&session_encoded_key);
|
||||
req_handler.context.insert("email_subject",&subject);
|
||||
let (status, result) = if app_dbs.config.use_mail && user_invite.send_email {
|
||||
let mail_content= if let Some(tpl) = app_dbs.config.tpls.get("invite_mail_txt") {
|
||||
req_handler.render_template(tpl, "invite")
|
||||
} else {
|
||||
format!("{}\n{}\n{}/signup/{}\n",&subject,&body,&signup_url,&session_cookie)
|
||||
};
|
||||
let mail_html_content = if let Some(tpl) = app_dbs.config.tpls.get("invite_mail_html") {
|
||||
req_handler.render_template(tpl, "invite")
|
||||
} else {
|
||||
format!("{}\n{}\n{}/signup/{}\n",&subject,&body,&signup_url,&session_cookie)
|
||||
};
|
||||
let mail_check = MailMessage::check(&app_dbs);
|
||||
if ! mail_check.is_empty() {
|
||||
(
|
||||
StatusCode::BAD_REQUEST,
|
||||
mail_check
|
||||
)
|
||||
} else {
|
||||
//"jesus.perezlorenzo@gmail.com",
|
||||
// "jesus@librecloud.online",
|
||||
match MailMessage::new(
|
||||
&app_dbs.config.mail_from,
|
||||
&user_invite.email,
|
||||
&app_dbs.config.mail_reply_to,
|
||||
) {
|
||||
Ok(mail_message) => {
|
||||
//match mail_message.send_message(
|
||||
match mail_message.send_html_message(
|
||||
&subject,
|
||||
&mail_content,
|
||||
&mail_html_content,
|
||||
&app_dbs
|
||||
).await {
|
||||
Ok(_) => {
|
||||
let _ = req_handler.trace_req(format!(
|
||||
"Invitation mail sent to: '{}' reset url: {} roles: {}, isadmin: {}, expiration: {} cookie: {}",
|
||||
&user_invite.email, &invite_expiration, user_invite.roles, user_invite.isadmin, &signup_url,&session_cookie
|
||||
));
|
||||
(StatusCode::OK, format!("Mail sent to {}",&user_invite.email))
|
||||
},
|
||||
Err(e) => {
|
||||
println!("Invitation to: {} Error mail message send: {}",&user_invite.email, e);
|
||||
(
|
||||
StatusCode::INTERNAL_SERVER_ERROR,
|
||||
String::from("Error")
|
||||
)
|
||||
}
|
||||
}
|
||||
},
|
||||
Err(e) => {
|
||||
println!("Invitation to: {} Error mail message creation: {}",&user_invite.email, e);
|
||||
(
|
||||
StatusCode::BAD_REQUEST,
|
||||
String::from("Error")
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let _ = req_handler.trace_req(format!(
|
||||
"Created invitation: '{}' reset url: {} roles: {}, isadmin: {}, expiration: {} cookie: {}",
|
||||
&user_invite.email, &invite_expiration, user_invite.roles, user_invite.isadmin, &signup_url,&session_cookie
|
||||
));
|
||||
(StatusCode::OK, format!("No mail sent to {}",&user_invite.email))
|
||||
};
|
||||
req_handler.prepare_response();
|
||||
req_handler.context.insert("email_result",&result);
|
||||
let response = if let Some(tpl) = app_dbs.config.tpls.get("invite_output") {
|
||||
req_handler.render_template(tpl, "invite")
|
||||
} else {
|
||||
format!("{}\n{}\n{}/signup/{}\n",&subject,&body,&signup_url,&session_cookie)
|
||||
};
|
||||
(
|
||||
status,
|
||||
req_handler.req_header.header,
|
||||
response,
|
||||
).into_response()
|
||||
}
|
||||
async fn invite_handler(
|
||||
header: HeaderMap,
|
||||
uri: Uri,
|
||||
Extension(app_dbs): Extension<Arc<AppDBs>>,
|
||||
Extension(cookies): Extension<Cookies>,
|
||||
Extension(random): Extension<Random>,
|
||||
ConnectInfo(app_connect_info): ConnectInfo<AppConnectInfo>,
|
||||
) -> Response {
|
||||
let auth_state = get_auth_state(true, &cookies, &app_dbs).await;
|
||||
let mut req_handler = ReqHandler::new(
|
||||
ReqHeaderMap::new(header, &format!("{}",&uri.path().to_string()), &app_connect_info),
|
||||
&app_dbs,
|
||||
&uri,
|
||||
&auth_state,
|
||||
&random,
|
||||
"invite_handler"
|
||||
);
|
||||
if ! app_dbs.config.signup_mode.contains("invitation") {
|
||||
let msg = format!("Config signup mode not invitation: {}",
|
||||
app_dbs.config.signup_mode
|
||||
);
|
||||
println!("{}",&msg);
|
||||
let _ = req_handler.trace_req(msg);
|
||||
return Redirect::temporary( &format!("/")).into_response();
|
||||
}
|
||||
if ! auth_state.has_auth_role(&app_dbs.config.auth_roles) {
|
||||
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 (
|
||||
// StatusCode::UNAUTHORIZED,
|
||||
// header,
|
||||
// "Error authorization"
|
||||
// ).into_response();
|
||||
}
|
||||
|
||||
let title = format!("DocServer Invitation");
|
||||
let invite_url= format!(
|
||||
"{}://{}/invite",
|
||||
&app_dbs.config.protocol,
|
||||
&app_dbs.config.hostport,
|
||||
);
|
||||
let invite_expire = format!("{} minutes",
|
||||
(&app_dbs.config.invite_expire/60)
|
||||
);
|
||||
req_handler.context.insert("target_url", &invite_url);
|
||||
req_handler.context.insert("invite_expire", &invite_expire);
|
||||
if app_dbs.config.use_mail {
|
||||
req_handler.context.insert("use_mail", &app_dbs.config.use_mail);
|
||||
}
|
||||
req_handler.prepare_response();
|
||||
req_handler.context.insert("with_menu", "1");
|
||||
let response = if let Some(tpl) = app_dbs.config.tpls.get("invite_create") {
|
||||
req_handler.render_template(tpl, "invite create")
|
||||
} else {
|
||||
format!("{} invite",&title)
|
||||
};
|
||||
let _ = req_handler.trace_req(format!(
|
||||
"Invitation: url: {}, expiration: {}",
|
||||
&invite_url, &invite_expire,
|
||||
));
|
||||
(
|
||||
req_handler.req_header.header,
|
||||
response,
|
||||
).into_response()
|
||||
// let uri_path = format!("{}",&uri.path().to_string());
|
||||
// let file = "hello.html";
|
||||
// let result = app_dbs.tera.render(&file, &app_dbs.context).unwrap_or_else(|e|{
|
||||
// println!("Error render {}: {}",&file,e);
|
||||
// String::from("")
|
||||
// });
|
||||
// let mut new_header = header.to_owned();
|
||||
//new_header.append("Set-Cookie", "session_token=_; Max-Age=0".parse().unwrap());
|
||||
// cookies.remove(Cookie::new(SESSION_COOKIE_NAME, ""));
|
||||
// (
|
||||
// header,
|
||||
// result.to_owned()
|
||||
// ).into_response()
|
||||
// "Hello, World!"
|
||||
}
|
||||
route(
|
||||
"/signup/:data", get(invite_signup_handler))
|
||||
.route("/invite", get(invite_handler))
|
||||
.route("/invite", post(post_invite_handler))
|
||||
}
|
281
src/handlers/users/login.rs
Normal file
281
src/handlers/users/login.rs
Normal file
@ -0,0 +1,281 @@
|
||||
use std::sync::Arc;
|
||||
use axum::{
|
||||
http::{
|
||||
StatusCode,
|
||||
Uri,
|
||||
header::HeaderMap,
|
||||
},
|
||||
response::{IntoResponse,Response,Redirect},
|
||||
};
|
||||
use tower_cookies::Cookies;
|
||||
|
||||
use crate::{
|
||||
defs::{
|
||||
AppDBs,
|
||||
AuthState,
|
||||
ReqHandler,
|
||||
ReqHeaderMap,
|
||||
TotpMode,
|
||||
Random,
|
||||
AppConnectInfo,
|
||||
},
|
||||
users::{
|
||||
User,
|
||||
UserLogin,
|
||||
UserStatus,
|
||||
},
|
||||
login_password::verify_password,
|
||||
handlers::{
|
||||
add_session_cookie,
|
||||
get_auth_state,
|
||||
},
|
||||
};
|
||||
use crate::users::OpenidUser;
|
||||
|
||||
pub async fn login_user (
|
||||
header: HeaderMap,
|
||||
uri: Uri,
|
||||
app_dbs: Arc<AppDBs>,
|
||||
cookies: Cookies,
|
||||
random: Random,
|
||||
app_connect_info: AppConnectInfo,
|
||||
user_login: UserLogin,
|
||||
source: &str,
|
||||
) -> Response {
|
||||
let auth_state = get_auth_state(true, &cookies, &app_dbs).await;
|
||||
let mut req_handler = ReqHandler::new(
|
||||
ReqHeaderMap::new(header, &format!("{}",&uri.path().to_string()), &app_connect_info),
|
||||
&app_dbs,
|
||||
&uri,
|
||||
&auth_state,
|
||||
&random,
|
||||
"post_login_handler"
|
||||
);
|
||||
if user_login.name.is_empty() || source != "from_login_openid" && user_login.password.is_empty() {
|
||||
let _ = req_handler.trace_req(String::from("Empty name or password"));
|
||||
// return Err(error_page(&SignupError::MissingDetails));
|
||||
return (
|
||||
StatusCode::BAD_REQUEST,
|
||||
req_handler.req_header.header,
|
||||
"Error"
|
||||
).into_response();
|
||||
}
|
||||
let field = if user_login.name.contains("@") {
|
||||
"email"
|
||||
} else {
|
||||
"name"
|
||||
};
|
||||
let (mut user_sel, mut openid_user) = if source == "from_login_openid" {
|
||||
let user_data = auth_state.user_data();
|
||||
dbg!(&user_data);
|
||||
let openid_conf = if let Some(openid_conf) = app_dbs.config.openid_auths.get(&user_data[0]) {
|
||||
openid_conf
|
||||
} else {
|
||||
let _ = req_handler.trace_req(format!("No name openid conf for '{}' found",&user_login.name));
|
||||
return (
|
||||
StatusCode::BAD_REQUEST,
|
||||
req_handler.req_header.header,
|
||||
"Error openid auth"
|
||||
).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| {
|
||||
println!("Error openid {}/{} select: {}", &openid_conf.signup_application, &user_login.name, e);
|
||||
OpenidUser::default()
|
||||
});
|
||||
dbg!(&openid_user);
|
||||
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 session_token = req_handler.new_token();
|
||||
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) };
|
||||
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));
|
||||
// User not exists
|
||||
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|{
|
||||
println!("Error select: {}", e);
|
||||
User::default()
|
||||
}),
|
||||
openid_user
|
||||
)
|
||||
} else {
|
||||
(
|
||||
User::select( &field, &user_login.name, false, &app_dbs.user_store).await.unwrap_or_else( | e |{
|
||||
println ! ("Error select: {}", e);
|
||||
User::default()
|
||||
}),
|
||||
OpenidUser::default()
|
||||
)
|
||||
};
|
||||
if user_sel.name.is_empty() {
|
||||
let _ = req_handler.trace_req(format!("No name '{}' found",&user_login.name));
|
||||
// User not exists
|
||||
return (
|
||||
StatusCode::BAD_REQUEST,
|
||||
req_handler.req_header.header,
|
||||
"Error data"
|
||||
).into_response();
|
||||
}
|
||||
if user_sel.status != UserStatus::Active && user_sel.status != UserStatus::Created {
|
||||
let _ = req_handler.trace_req(format!("user '{}' in not valid status: {}",&user_login.name, &user_sel.status));
|
||||
return (
|
||||
StatusCode::UNAUTHORIZED,
|
||||
req_handler.req_header.header,
|
||||
"Error status"
|
||||
).into_response();
|
||||
}
|
||||
let result = if source == "from_login_openid" {
|
||||
format!("{}:true", "OK")
|
||||
} else {
|
||||
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));
|
||||
println!("password NOT valid");
|
||||
// TODO
|
||||
//return Err(error_page(&SignupError::PasswordsDoNotMatch))
|
||||
return (
|
||||
StatusCode::BAD_REQUEST,
|
||||
req_handler.req_header.header,
|
||||
"Error data"
|
||||
).into_response();
|
||||
}
|
||||
let result = format!("{}:{}", "OK", &user_sel.otp_verified);
|
||||
if app_dbs.config.totp_mode != TotpMode::No {
|
||||
if user_login.otp_auth.is_empty()
|
||||
&& (app_dbs.config.totp_mode == TotpMode::Mandatory || user_sel.otp_enabled)
|
||||
{
|
||||
let _ = req_handler.trace_req(format!("user '{}' not valid Totp: {}", &user_login.name, &user_sel.otp_enabled));
|
||||
return (
|
||||
req_handler.req_header.header,
|
||||
result
|
||||
).into_response();
|
||||
} else if user_sel.otp_enabled && user_sel.otp_verified
|
||||
&& !user_sel.otp_base32.is_empty() && !user_sel.otp_defs.is_empty()
|
||||
{
|
||||
match req_handler.otp_check(&user_sel.otp_base32, &user_login.otp_auth, &user_sel.otp_defs) {
|
||||
Ok(val) => {
|
||||
if !val {
|
||||
let _ = req_handler.trace_req(format!("user '{}' not valid TOTP code", &user_login.name));
|
||||
return (
|
||||
StatusCode::UNAUTHORIZED,
|
||||
req_handler.req_header.header,
|
||||
"Error"
|
||||
).into_response();
|
||||
}
|
||||
},
|
||||
Err(e) => {
|
||||
let _ = req_handler.trace_req(format!("user '{}' TOTP check error: {}", &user_login.name, e));
|
||||
println!("TOTP check: {}", e);
|
||||
return (
|
||||
StatusCode::UNAUTHORIZED,
|
||||
req_handler.req_header.header,
|
||||
"Error"
|
||||
).into_response();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
result
|
||||
};
|
||||
let session_user_data = auth_state.user_data();
|
||||
user_sel.lastaccess = chrono::Utc::now().timestamp().to_string();
|
||||
if user_sel.status != UserStatus::Active { user_sel.status = UserStatus::Active }
|
||||
let user_data = user_sel.session_data();
|
||||
let curr_id = user_sel.id;
|
||||
match user_sel.update(&app_dbs.user_store).await {
|
||||
Ok(_) => {
|
||||
let session_token = req_handler.new_token();
|
||||
let session_cookie = add_session_cookie(true,&cookies, &session_token, &user_data, 0, &app_dbs, "/").await;
|
||||
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;
|
||||
if openid_user.userid == curr_id {
|
||||
openid_user.lastaccess = chrono::Utc::now().timestamp().to_string();
|
||||
let info_update = format!("User '{}/{} ({})' -> {} update",
|
||||
&openid_user.application,
|
||||
&openid_user.appkey,
|
||||
&openid_user.name,
|
||||
&openid_user.userid,
|
||||
);
|
||||
match openid_user.update(&app_dbs.user_store).await {
|
||||
Ok(_) => println!("{}d !", &info_update),
|
||||
Err(e) => println!("{} error: {}", &info_update, e)
|
||||
}
|
||||
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() {
|
||||
let openid_user = OpenidUser {
|
||||
id: 0,
|
||||
name: session_user_data[5].to_owned(),
|
||||
application: session_user_data[4].to_owned(),
|
||||
appkey: session_user_data[1].to_owned(),
|
||||
userid: curr_id,
|
||||
description: String::from("created from user"),
|
||||
created: chrono::Utc::now().timestamp().to_string(),
|
||||
lastaccess: String::from(""),
|
||||
};
|
||||
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,
|
||||
);
|
||||
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.req_header,
|
||||
&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));
|
||||
// TODO Is this a bug ??
|
||||
// http -> tokio-runtime-worker' panicked at 'payload claims content-length of 10, custom content-length header claims 34
|
||||
if app_dbs.config.protocol == "https" {
|
||||
(
|
||||
req_handler.req_header.header,
|
||||
result
|
||||
).into_response()
|
||||
} else {
|
||||
(
|
||||
result
|
||||
).into_response()
|
||||
}
|
||||
},
|
||||
Err(e) => {
|
||||
let _ = req_handler.trace_req(format!("user '{}' update error: {}",&user_login.name,e));
|
||||
(
|
||||
StatusCode::BAD_REQUEST,
|
||||
req_handler.req_header.header,
|
||||
"Error"
|
||||
).into_response()
|
||||
}
|
||||
}
|
||||
}
|
601
src/handlers/users/login_handlers.rs
Normal file
601
src/handlers/users/login_handlers.rs
Normal file
@ -0,0 +1,601 @@
|
||||
use std::collections::HashMap;
|
||||
use std::sync::Arc;
|
||||
use axum::{
|
||||
http::{
|
||||
StatusCode,
|
||||
Uri,
|
||||
header::HeaderMap,
|
||||
},
|
||||
Json,
|
||||
routing::{get,post},
|
||||
Extension,
|
||||
extract::ConnectInfo,
|
||||
response::{IntoResponse,Response,Redirect},
|
||||
Router,
|
||||
};
|
||||
use tower_cookies::{Cookie, Cookies};
|
||||
|
||||
use crate::{
|
||||
SESSION_COOKIE_NAME,
|
||||
DEFAULT_ROLES,
|
||||
route,
|
||||
defs::{
|
||||
AppDBs,
|
||||
AuthState,
|
||||
SessionStoreDB,
|
||||
ReqHandler,
|
||||
ReqHeaderMap,
|
||||
TotpMode,
|
||||
Random,
|
||||
AppConnectInfo,
|
||||
OpenidData,
|
||||
OpenidCli,
|
||||
},
|
||||
users::{
|
||||
User,
|
||||
UserData,
|
||||
UserLogin,
|
||||
UserItem,
|
||||
UserStatus,
|
||||
},
|
||||
login_password::generate_hash,
|
||||
handlers::{
|
||||
add_session_cookie,
|
||||
get_auth_state,
|
||||
login_user,
|
||||
},
|
||||
};
|
||||
pub fn users_login_router_handlers() -> Router {
|
||||
async fn signup_handler(
|
||||
header: HeaderMap,
|
||||
uri: Uri,
|
||||
Extension(app_dbs): Extension<Arc<AppDBs>>,
|
||||
Extension(cookies): Extension<Cookies>,
|
||||
Extension(random): Extension<Random>,
|
||||
ConnectInfo(app_connect_info): ConnectInfo<AppConnectInfo>,
|
||||
) -> Response {
|
||||
let auth_state = get_auth_state(true, &cookies, &app_dbs).await;
|
||||
let mut req_handler = ReqHandler::new(
|
||||
ReqHeaderMap::new(header, &format!("{}",&uri.path().to_string()), &app_connect_info),
|
||||
&app_dbs,
|
||||
&uri,
|
||||
&auth_state,
|
||||
&random,
|
||||
"signup_handler"
|
||||
);
|
||||
if !auth_state.is_admin() {
|
||||
let total_users = User::count(&app_dbs.user_store).await.unwrap_or_else(|e|{
|
||||
println!("Count error: {}",e);
|
||||
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);
|
||||
println!("{}",&msg);
|
||||
let _ = req_handler.trace_req(msg);
|
||||
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 ...
|
||||
if total_users < 1 {
|
||||
let isadmin= String::from("TRUE");
|
||||
req_handler.context.insert("isadmin", &isadmin);
|
||||
}
|
||||
}
|
||||
let mut res_headers = HeaderMap::new();
|
||||
if req_handler.req_header.is_browser() {
|
||||
res_headers.append(axum::http::header::CONTENT_TYPE,"text/html; charset=utf-8".parse().unwrap());
|
||||
}
|
||||
req_handler.context.insert("password_score", &app_dbs.config.password_score);
|
||||
req_handler.context.insert("totp_mode", &format!("{}",&app_dbs.config.totp_mode));
|
||||
// req_handler.context.insert("with_menu", "1");
|
||||
if app_dbs.config.totp_mode != TotpMode::No {
|
||||
match req_handler.otp_generate() {
|
||||
Ok(totp) => {
|
||||
req_handler.context.insert("otp_code", &totp.get_secret_base32());
|
||||
req_handler.context.insert("otp_url", &totp.get_url());
|
||||
req_handler.context.insert("otp_qr", &totp.get_qr_base64().unwrap_or_default());
|
||||
req_handler.context.insert("totp_digits", &app_dbs.config.totp_digits);
|
||||
req_handler.context.insert("totp_algorithm",&format!("{}",&app_dbs.config.totp_algorithm));
|
||||
},
|
||||
Err(e) => {
|
||||
println!("Error TOTP generartor: {}",e);
|
||||
}
|
||||
}
|
||||
}
|
||||
req_handler.context.insert("admin_fields", &app_dbs.config.admin_fields);
|
||||
let result = if let Some(tpl) = app_dbs.config.tpls.get("signup") {
|
||||
req_handler.render_template(&tpl,"signup")
|
||||
} else {
|
||||
String::from("signup")
|
||||
};
|
||||
let _ = req_handler.trace_req(format!("Signup request"));
|
||||
(
|
||||
res_headers,
|
||||
result.to_owned()
|
||||
).into_response()
|
||||
}
|
||||
|
||||
async fn post_signup_handler(
|
||||
header: HeaderMap,
|
||||
uri: Uri,
|
||||
Extension(app_dbs): Extension<Arc<AppDBs>>,
|
||||
Extension(random): Extension<Random>,
|
||||
Extension(cookies): Extension<Cookies>,
|
||||
ConnectInfo(app_connect_info): ConnectInfo<AppConnectInfo>,
|
||||
Json(user_data): Json<UserData>,
|
||||
) -> Response {
|
||||
let auth_state = get_auth_state(true, &cookies, &app_dbs).await;
|
||||
let req_handler = ReqHandler::new(
|
||||
ReqHeaderMap::new(header, &format!("{}",&uri.path().to_string()), &app_connect_info),
|
||||
&app_dbs,
|
||||
&uri,
|
||||
&auth_state,
|
||||
&random,
|
||||
"post_signup_handler"
|
||||
);
|
||||
if user_data.name.is_empty() {
|
||||
let _ = req_handler.trace_req(format!("No name found"));
|
||||
return (
|
||||
StatusCode::BAD_REQUEST,
|
||||
req_handler.req_header.header,
|
||||
"Error"
|
||||
).into_response();
|
||||
}
|
||||
if user_data.password.is_empty() {
|
||||
let _ = req_handler.trace_req(format!("user '{}' no password found",&user_data.name));
|
||||
return (
|
||||
StatusCode::BAD_REQUEST,
|
||||
req_handler.req_header.header,
|
||||
"Error"
|
||||
).into_response();
|
||||
}
|
||||
let passwd_score = User::password_score(&user_data.password);
|
||||
if passwd_score < app_dbs.config.password_score {
|
||||
let _ = req_handler.trace_req(format!("User '{}' password '{}' score: {} under {}"
|
||||
,&user_data.name,&user_data.password, passwd_score,app_dbs.config.password_score)
|
||||
);
|
||||
return (
|
||||
StatusCode::UNAUTHORIZED,
|
||||
req_handler.req_header.header,
|
||||
"Error"
|
||||
).into_response();
|
||||
}
|
||||
let new_hash = generate_hash(&user_data.password);
|
||||
// println!("password: {}", &new_hash);
|
||||
// // if user_data.password.is_empty() {
|
||||
// // return Err(error_page(&SignupError::MissingDetails));
|
||||
// // }
|
||||
// match verify_password(&user_data.password, &new_hash) {
|
||||
// Ok(_) => {
|
||||
// println!("Is valid!");
|
||||
// },
|
||||
// Err(e) => {
|
||||
// println!("NOT valid {}",e);
|
||||
// //return Err(error_page(&SignupError::PasswordsDoNotMatch))
|
||||
// }
|
||||
// }
|
||||
let otp_enabled: bool;
|
||||
let otp_verified: bool;
|
||||
let otp_base32: String;
|
||||
let otp_auth_url: String;
|
||||
let otp_defs: String;
|
||||
if app_dbs.config.totp_mode != TotpMode::No && !user_data.otp_auth.is_empty() {
|
||||
match req_handler.otp_check(&user_data.otp_code,&user_data.otp_auth, "") {
|
||||
Ok(val) => {
|
||||
if val {
|
||||
otp_enabled = true;
|
||||
} else {
|
||||
let _ = req_handler.trace_req(format!("User '{}' not valid TOTP code",&user_data.name));
|
||||
// otp_enabled = false;
|
||||
return (
|
||||
StatusCode::UNAUTHORIZED,
|
||||
req_handler.req_header.header,
|
||||
"Error"
|
||||
).into_response();
|
||||
}
|
||||
},
|
||||
Err(e) => {
|
||||
println!("TOTP check: {}", e);
|
||||
let _ = req_handler.trace_req(format!("User '{}' TOTP check error: {}",&user_data.name,e));
|
||||
return (
|
||||
StatusCode::UNAUTHORIZED,
|
||||
req_handler.req_header.header,
|
||||
"Error"
|
||||
).into_response();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
otp_enabled = false;
|
||||
}
|
||||
if otp_enabled {
|
||||
otp_verified= true;
|
||||
otp_base32 = user_data.otp_code.to_owned();
|
||||
otp_auth_url = user_data.otp_url.to_owned();
|
||||
otp_defs = format!("{},{}",
|
||||
&app_dbs.config.totp_digits,
|
||||
format!("{}",&app_dbs.config.totp_algorithm),
|
||||
);
|
||||
} else {
|
||||
otp_verified = false;
|
||||
otp_base32 = String::from("");
|
||||
otp_auth_url = String::from("");
|
||||
otp_defs = String::from("");
|
||||
}
|
||||
let roles = if ! user_data.roles.is_empty() {
|
||||
user_data.roles.to_owned()
|
||||
} else {
|
||||
DEFAULT_ROLES.to_owned()
|
||||
};
|
||||
let total_users = User::count(&app_dbs.user_store).await.unwrap_or_else(|e|{
|
||||
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
|
||||
} else {
|
||||
false
|
||||
};
|
||||
let mut new_items = user_data.items.to_owned();
|
||||
new_items.remove("invite_key");
|
||||
new_items.remove("invite_id");
|
||||
let user = User{
|
||||
id: 0,
|
||||
name: user_data.name.to_owned(),
|
||||
fullname: user_data.name.to_owned(),
|
||||
email: user_data.email.to_owned(),
|
||||
description: user_data.description.to_owned(),
|
||||
password: new_hash,
|
||||
otp_enabled,
|
||||
otp_verified,
|
||||
otp_base32,
|
||||
otp_auth_url,
|
||||
otp_defs,
|
||||
created: chrono::Utc::now().timestamp().to_string(),
|
||||
lastaccess: String::from(""),
|
||||
status: UserStatus::Created,
|
||||
items: User::json_items(new_items),
|
||||
isadmin,
|
||||
roles,
|
||||
};
|
||||
let usr_sel = User::select("name", &user_data.name, false, &app_dbs.user_store).await.unwrap_or_default();
|
||||
if usr_sel.name == user_data.name {
|
||||
// User already exists
|
||||
let _ = req_handler.trace_req(format!("User 'name' = '{}' already exists",&user_data.name));
|
||||
return (
|
||||
StatusCode::BAD_REQUEST,
|
||||
req_handler.req_header.header,
|
||||
"Error"
|
||||
).into_response();
|
||||
}
|
||||
let str_user_data = match user.add(&app_dbs.user_store).await {
|
||||
Ok(id) => {
|
||||
println!("user {} created -> {}", &user_data.name, id);
|
||||
format!("{}|{}|{}",id, &user_data.name, &user_data.roles)
|
||||
},
|
||||
Err(e) => {
|
||||
let _ = req_handler.trace_req(format!("User '{}' create error: {}",&user_data.name,e));
|
||||
println!("user {} error -> {:#}", &user_data.name, e);
|
||||
return (
|
||||
StatusCode::NOT_FOUND,
|
||||
req_handler.req_header.header,
|
||||
"Error"
|
||||
).into_response();
|
||||
}
|
||||
};
|
||||
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 _ = req_handler.trace_req(format!("User '{}' created",&user_data.name));
|
||||
if app_dbs.config.verbose > 1 { println!("session cookie: {}", &session_cookie); }
|
||||
(
|
||||
req_handler.req_header.header,
|
||||
"Ok"
|
||||
).into_response()
|
||||
}
|
||||
async fn login_handler(
|
||||
header: HeaderMap,
|
||||
uri: Uri,
|
||||
Extension(app_dbs): Extension<Arc<AppDBs>>,
|
||||
Extension(cookies): Extension<Cookies>,
|
||||
Extension(random): Extension<Random>,
|
||||
ConnectInfo(app_connect_info): ConnectInfo<AppConnectInfo>,
|
||||
) -> Response {
|
||||
SessionStoreDB::cleanup_data(&app_dbs).await;
|
||||
let auth_state = get_auth_state(true, &cookies, &app_dbs).await;
|
||||
dbg!(&header);
|
||||
dbg!(&auth_state);
|
||||
let mut req_handler = ReqHandler::new(
|
||||
ReqHeaderMap::new(header, &format!("{}",&uri.path().to_string()), &app_connect_info),
|
||||
&app_dbs,
|
||||
&uri,
|
||||
&auth_state,
|
||||
&random,
|
||||
"login_handler"
|
||||
);
|
||||
let total_users = User::count(&app_dbs.user_store).await.unwrap_or_else(|e|{
|
||||
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"));
|
||||
return Redirect::temporary( &format!("/signup")).into_response();
|
||||
}
|
||||
let user_data = auth_state.user_data();
|
||||
if user_data.len() > 4 && user_data[0] == "openid" {
|
||||
req_handler.context.insert("login_text", &format!("Login {} / {}", &user_data[1], &user_data[5]));
|
||||
req_handler.context.insert("signin_target", &user_data[1]);
|
||||
}
|
||||
let mut res_headers = HeaderMap::new();
|
||||
if req_handler.req_header.is_browser() {
|
||||
res_headers.append(axum::http::header::CONTENT_TYPE,"text/html; charset=utf-8".parse().unwrap());
|
||||
}
|
||||
req_handler.context.insert("openid_auths", &app_dbs.config.openid_auths.clone().into_keys().collect::<Vec<String>>());
|
||||
// req_handler.context.insert("with_menu", "1");
|
||||
req_handler.context.insert("use_mail", &app_dbs.config.use_mail);
|
||||
req_handler.context.insert("totp_mode", &format!("{}",&app_dbs.config.totp_mode));
|
||||
if app_dbs.config.totp_mode != TotpMode::No {
|
||||
req_handler.context.insert("with_totp", "1");
|
||||
req_handler.context.insert("totp_digits", &app_dbs.config.totp_digits);
|
||||
}
|
||||
let _ = req_handler.trace_req(String::from("login request"));
|
||||
let result = if let Some(tpl) = app_dbs.config.tpls.get("login") {
|
||||
req_handler.render_template(&tpl,"login")
|
||||
} else {
|
||||
String::from("login")
|
||||
};
|
||||
(
|
||||
res_headers,
|
||||
result.to_owned()
|
||||
).into_response()
|
||||
}
|
||||
async fn openid_login_handler(
|
||||
header: HeaderMap,
|
||||
uri: Uri,
|
||||
Extension(app_dbs): Extension<Arc<AppDBs>>,
|
||||
Extension(cookies): Extension<Cookies>,
|
||||
Extension(random): Extension<Random>,
|
||||
Extension(openid_clients): Extension<Arc<HashMap<String,OpenidCli>>>,
|
||||
ConnectInfo(app_connect_info): ConnectInfo<AppConnectInfo>,
|
||||
axum::extract::Path(data): axum::extract::Path<String>,
|
||||
) -> Response {
|
||||
SessionStoreDB::cleanup_data(&app_dbs).await;
|
||||
let auth_state = get_auth_state(true, &cookies, &app_dbs).await;
|
||||
let req_handler = ReqHandler::new(
|
||||
ReqHeaderMap::new(header, &format!("{}",&uri.path().to_string()), &app_connect_info),
|
||||
&app_dbs,
|
||||
&uri,
|
||||
&auth_state,
|
||||
&random,
|
||||
"login_handler"
|
||||
);
|
||||
let total_users = User::count(&app_dbs.user_store).await.unwrap_or_else(|e|{
|
||||
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"));
|
||||
return Redirect::temporary( &format!("/signup")).into_response();
|
||||
}
|
||||
if data.is_empty() {
|
||||
return Redirect::temporary( &format!("/login")).into_response();
|
||||
}
|
||||
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) {
|
||||
match openid_conf.get_auth(openid_cli).await {
|
||||
Ok(openid) => {
|
||||
//let _ = req_handler.trace_req(format!("User '{}' created",&user_data.name));
|
||||
let str_user_data = format!("{}|{}|{}", &data, openid.token.secret(), openid.nonce.secret());
|
||||
//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) };
|
||||
//let _new_auth_state = AuthState::from_cookie(session_cookie.to_string(), &app_dbs).await;
|
||||
/*req_handler = ReqHandler::new(
|
||||
req_handler.req_header,
|
||||
&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) => {
|
||||
println!("Error openid login handler: {}", e);
|
||||
(String::from(""), String::from("/login"))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
(String::from(""), String::from("/login"))
|
||||
}
|
||||
} else {
|
||||
(String::from(""), String::from("/login"))
|
||||
};
|
||||
let session_token = req_handler.new_token();
|
||||
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) };
|
||||
let _new_auth_state = AuthState::from_cookie(session_cookie.to_string(), &app_dbs).await;
|
||||
return Redirect::temporary(&format!("{}",url)).into_response()
|
||||
}
|
||||
async fn post_login_handler(
|
||||
header: HeaderMap,
|
||||
uri: Uri,
|
||||
Extension(app_dbs): Extension<Arc<AppDBs>>,
|
||||
Extension(cookies): Extension<Cookies>,
|
||||
Extension(random): Extension<Random>,
|
||||
ConnectInfo(app_connect_info): ConnectInfo<AppConnectInfo>,
|
||||
Json(user_login): Json<UserLogin>,
|
||||
) -> Response {
|
||||
login_user ( header, uri,
|
||||
app_dbs, cookies, random,
|
||||
app_connect_info,
|
||||
user_login,
|
||||
"post_login"
|
||||
).await
|
||||
}
|
||||
async fn openid_from_login_handler(
|
||||
header: HeaderMap,
|
||||
uri: Uri,
|
||||
Extension(app_dbs): Extension<Arc<AppDBs>>,
|
||||
Extension(cookies): Extension<Cookies>,
|
||||
Extension(random): Extension<Random>,
|
||||
ConnectInfo(app_connect_info): ConnectInfo<AppConnectInfo>,
|
||||
Extension(openid_clients): Extension<Arc<HashMap<String,OpenidCli>>>,
|
||||
//axum::extract::Path(data): axum::extract::Path<String>,
|
||||
data: axum::extract::Query<OpenidData>,
|
||||
// Json(user_login): Json<UserLogin>,
|
||||
) -> Response {
|
||||
dbg!(&header);
|
||||
dbg!(&uri);
|
||||
let auth_state = get_auth_state(true, &cookies, &app_dbs).await;
|
||||
let user_data = auth_state.user_data();
|
||||
//let _req_handler = ReqHandler::new(
|
||||
// ReqHeaderMap::new(header, &format!("{}",&uri.path().to_string()), &app_connect_info),
|
||||
// &app_dbs,
|
||||
// &uri,
|
||||
// &auth_state,
|
||||
// &random,
|
||||
// "post_login_handler"
|
||||
//);
|
||||
if user_data.len() < 1 || user_data[1] != data.state {
|
||||
println!("State {} not found=", data.state);
|
||||
return Redirect::temporary(&format!("/login")).into_response();
|
||||
}
|
||||
println!("OK State {} == {}", user_data[1], data.state);
|
||||
let mut user_login = UserLogin::default();
|
||||
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]) {
|
||||
match openid_conf.get_token(openid_cli, data.code.to_owned(), user_data[2].to_owned()).await {
|
||||
Ok(data) => {
|
||||
user_login = UserLogin {
|
||||
name: data.name.to_owned(),
|
||||
password: String::from(""),
|
||||
otp_auth: String::from(""),
|
||||
email: data.email.to_owned(),
|
||||
};
|
||||
},
|
||||
Err(e) => {
|
||||
println!("Error openid login handler: {}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ! user_login.name.is_empty() {
|
||||
let res = login_user(header, uri,
|
||||
app_dbs, cookies, random,
|
||||
app_connect_info,
|
||||
user_login,
|
||||
"from_login_openid"
|
||||
).await;
|
||||
res
|
||||
} else {
|
||||
let url="/login"; // https://tiicl.tls13.io:8800";
|
||||
Redirect::temporary(&format!("{}",url)).into_response()
|
||||
}
|
||||
}
|
||||
async fn logout_handler(
|
||||
header: HeaderMap,
|
||||
uri: Uri,
|
||||
Extension(app_dbs): Extension<Arc<AppDBs>>,
|
||||
Extension(cookies): Extension<Cookies>,
|
||||
Extension(random): Extension<Random>,
|
||||
ConnectInfo(app_connect_info): ConnectInfo<AppConnectInfo>,
|
||||
) -> Response {
|
||||
let auth_state = get_auth_state(true, &cookies, &app_dbs).await;
|
||||
let mut req_handler = ReqHandler::new(
|
||||
ReqHeaderMap::new(header, &format!("{}",&uri.path().to_string()), &app_connect_info),
|
||||
&app_dbs,
|
||||
&uri,
|
||||
&auth_state,
|
||||
&random,
|
||||
"logout_handler"
|
||||
);
|
||||
let id = auth_state.id();
|
||||
let res = auth_state.destroy();
|
||||
cookies.remove(Cookie::new(SESSION_COOKIE_NAME, ""));
|
||||
if app_dbs.config.verbose > 1 { println!("Session: {} destroyed: {}",&id, &res); }
|
||||
let _ = req_handler.trace_req(format!("Session '{}' logout",&id));
|
||||
let auth_state = AuthState::default();
|
||||
req_handler = ReqHandler::new(
|
||||
req_handler.req_header,
|
||||
&app_dbs,
|
||||
&uri,
|
||||
&auth_state,
|
||||
&random,
|
||||
"logout_handler"
|
||||
);
|
||||
let mut res_headers = HeaderMap::new();
|
||||
if req_handler.req_header.is_browser() {
|
||||
res_headers.append(axum::http::header::CONTENT_TYPE,"text/html; charset=utf-8".parse().unwrap());
|
||||
}
|
||||
// these is to use user_items like color_theme
|
||||
// let user_items = User::hash_items(&auth_state.user_items());
|
||||
// req_handler.context.insert("usr_items", &user_items);
|
||||
req_handler.context.insert("with_menu", "1");
|
||||
let result = if let Some(tpl) = app_dbs.config.tpls.get("logout") {
|
||||
req_handler.render_template(&tpl,"logout")
|
||||
} else {
|
||||
String::from("logout")
|
||||
};
|
||||
(
|
||||
res_headers,
|
||||
result.to_owned()
|
||||
).into_response()
|
||||
}
|
||||
async fn check_item_handler(
|
||||
header: HeaderMap,
|
||||
uri: Uri,
|
||||
Extension(app_dbs): Extension<Arc<AppDBs>>,
|
||||
Extension(cookies): Extension<Cookies>,
|
||||
Extension(random): Extension<Random>,
|
||||
ConnectInfo(app_connect_info): ConnectInfo<AppConnectInfo>,
|
||||
Json(user_item): Json<UserItem>,
|
||||
) -> Response {
|
||||
let auth_state = get_auth_state(true, &cookies, &app_dbs).await;
|
||||
let req_handler = ReqHandler::new(
|
||||
ReqHeaderMap::new(header, &format!("{}",&uri.path().to_string()), &app_connect_info),
|
||||
&app_dbs,
|
||||
&uri,
|
||||
&auth_state,
|
||||
&random,
|
||||
"logout_handler"
|
||||
);
|
||||
let result = if user_item.name == "password" {
|
||||
let _ = req_handler.trace_req(format!("Password estimate"));
|
||||
User::estimate_password(&user_item.value)
|
||||
} else {
|
||||
let user_sel = User::select(&user_item.name, &user_item.value, false,&app_dbs.user_store).await.unwrap_or_default();
|
||||
if !user_sel.name.is_empty() {
|
||||
let _ = req_handler.trace_req(format!("User '{}' = '{}' not found",&user_item.name,&user_item.value));
|
||||
// User not exists
|
||||
return (
|
||||
StatusCode::BAD_REQUEST,
|
||||
req_handler.req_header.header,
|
||||
"Error"
|
||||
).into_response();
|
||||
}
|
||||
String::from("OK")
|
||||
};
|
||||
(
|
||||
req_handler.req_header.header,
|
||||
result.to_owned()
|
||||
).into_response()
|
||||
}
|
||||
route(
|
||||
"/login", get(login_handler))
|
||||
.route("/login", post(post_login_handler))
|
||||
|
||||
.route("/openid/:data", get(openid_login_handler))
|
||||
.route("/from_openid", get(openid_from_login_handler))
|
||||
|
||||
.route("/signup", get(signup_handler))
|
||||
.route("/signup", post(post_signup_handler))
|
||||
|
||||
.route("/logout", get(logout_handler))
|
||||
|
||||
.route("/check", post(check_item_handler))
|
||||
}
|
395
src/handlers/users/password_handlers.rs
Normal file
395
src/handlers/users/password_handlers.rs
Normal file
@ -0,0 +1,395 @@
|
||||
use std::sync::Arc;
|
||||
use urlencoding::{encode,decode};
|
||||
use axum::{
|
||||
http::{
|
||||
StatusCode,
|
||||
Uri,
|
||||
header::HeaderMap,
|
||||
},
|
||||
Json,
|
||||
routing::{get,post},
|
||||
Extension,
|
||||
extract::ConnectInfo,
|
||||
response::{IntoResponse,Response,Redirect},
|
||||
Router,
|
||||
};
|
||||
use tower_cookies::Cookies;
|
||||
|
||||
use crate::{
|
||||
route,
|
||||
defs::{
|
||||
AppDBs,
|
||||
AuthState,
|
||||
ReqHandler,
|
||||
ReqHeaderMap,
|
||||
MailMessage,
|
||||
TotpMode,
|
||||
Random,
|
||||
AppConnectInfo,
|
||||
},
|
||||
users::{
|
||||
User,
|
||||
UserData,
|
||||
UserItem,
|
||||
UserStatus,
|
||||
},
|
||||
login_password::generate_hash,
|
||||
handlers::{
|
||||
add_session_cookie,
|
||||
get_auth_state,
|
||||
},
|
||||
};
|
||||
pub fn users_password_router_handlers() -> Router {
|
||||
async fn post_reset_password_handler(
|
||||
header: HeaderMap,
|
||||
uri: Uri,
|
||||
Extension(app_dbs): Extension<Arc<AppDBs>>,
|
||||
Extension(cookies): Extension<Cookies>,
|
||||
Extension(random): Extension<Random>,
|
||||
ConnectInfo(app_connect_info): ConnectInfo<AppConnectInfo>,
|
||||
Json(user_item): Json<UserItem>,
|
||||
) -> Response {
|
||||
let auth_state = get_auth_state(true, &cookies, &app_dbs).await;
|
||||
let mut req_handler = ReqHandler::new(
|
||||
ReqHeaderMap::new(header, &format!("{}",&uri.path().to_string()), &app_connect_info),
|
||||
&app_dbs,
|
||||
&uri,
|
||||
&auth_state,
|
||||
&random,
|
||||
"post_reset_password_handler"
|
||||
);
|
||||
if ! app_dbs.config.use_mail {
|
||||
let _ = req_handler.trace_req(format!("Mail disabled in config, user '{}' password can not be reset",&user_item.name));
|
||||
return (
|
||||
StatusCode::BAD_REQUEST,
|
||||
req_handler.req_header.header,
|
||||
"Error no service"
|
||||
).into_response();
|
||||
}
|
||||
if user_item.name.is_empty() {
|
||||
let _ = req_handler.trace_req(format!("No user name"));
|
||||
return (
|
||||
StatusCode::BAD_REQUEST,
|
||||
req_handler.req_header.header,
|
||||
"Error"
|
||||
).into_response();
|
||||
}
|
||||
let field = if user_item.name.contains("@") {
|
||||
"email"
|
||||
} else {
|
||||
"name"
|
||||
};
|
||||
let mut user_sel = User::select(&field, &user_item.name, false, &app_dbs.user_store).await.unwrap_or_else(|e|{
|
||||
println!("Error select: {}", e);
|
||||
User::default()
|
||||
});
|
||||
if user_sel.name.is_empty() {
|
||||
let _ = req_handler.trace_req(format!("User '{}' = '{}' not found",&field,&user_item.name));
|
||||
// User not exists
|
||||
return (
|
||||
StatusCode::BAD_REQUEST,
|
||||
req_handler.req_header.header,
|
||||
"Error data"
|
||||
).into_response();
|
||||
}
|
||||
if user_sel.status != UserStatus::Active && user_sel.status != UserStatus::Created {
|
||||
let _ = req_handler.trace_req(format!("user '{}' in not valid status: {}",&user_item.name, &user_sel.status));
|
||||
return (
|
||||
StatusCode::UNAUTHORIZED,
|
||||
req_handler.req_header.header,
|
||||
"Error status"
|
||||
).into_response();
|
||||
}
|
||||
if app_dbs.config.totp_mode != TotpMode::No {
|
||||
if user_sel.otp_base32.is_empty()
|
||||
&& (app_dbs.config.totp_mode == TotpMode::Mandatory || user_sel.otp_enabled)
|
||||
{
|
||||
let _ = req_handler.trace_req(format!("user '{}' not valid Totp: {}",&user_sel.name, &user_sel.otp_enabled));
|
||||
return (
|
||||
StatusCode::UNAUTHORIZED,
|
||||
req_handler.req_header.header,
|
||||
"Error data"
|
||||
).into_response();
|
||||
} else if user_sel.otp_enabled && user_sel.otp_verified
|
||||
&& !user_sel.otp_base32.is_empty() && !user_sel.otp_defs.is_empty()
|
||||
{
|
||||
match req_handler.otp_check(&user_sel.otp_base32,&user_item.value, &user_sel.otp_defs) {
|
||||
Ok(val) => {
|
||||
if !val {
|
||||
let _ = req_handler.trace_req(format!("User '{}' not valid TOTP code",&user_item.name));
|
||||
return (
|
||||
StatusCode::UNAUTHORIZED,
|
||||
req_handler.req_header.header,
|
||||
"Error"
|
||||
).into_response();
|
||||
}
|
||||
},
|
||||
Err(e) => {
|
||||
println!("TOTP check: {}", e);
|
||||
let _ = req_handler.trace_req(format!("User '{}' TOTP check error: {}",&user_item.name,e));
|
||||
return (
|
||||
StatusCode::UNAUTHORIZED,
|
||||
req_handler.req_header.header,
|
||||
"Error"
|
||||
).into_response();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
let session_token = req_handler.new_token();
|
||||
user_sel.status = UserStatus::Pending;
|
||||
let user_data = user_sel.session_data();
|
||||
let session_cookie = add_session_cookie(false,&cookies, &session_token, &user_data, app_dbs.config.session_expire, &app_dbs, "invitation").await;
|
||||
let session_encoded_key = encode(session_cookie.as_str());
|
||||
let body=format!("This is a user password reset request for docserver service");
|
||||
let subject = format!("DocServer password reset");
|
||||
let reset_url= format!(
|
||||
"{}://{}/reset",
|
||||
&app_dbs.config.protocol,
|
||||
&app_dbs.config.hostport,
|
||||
);
|
||||
let reset_expiration = format!("{} minutes",(&app_dbs.config.session_expire/60));
|
||||
req_handler.context.insert("reset_url", &reset_url);
|
||||
req_handler.context.insert("reset_expiration", &reset_expiration);
|
||||
req_handler.context.insert("email_body",&body);
|
||||
req_handler.context.insert("reset_key",&session_encoded_key);
|
||||
req_handler.context.insert("email_subject",&subject);
|
||||
let mail_content= if let Some(tpl) = app_dbs.config.tpls.get("reset_password_mail_txt") {
|
||||
req_handler.render_template(tpl, "reset password")
|
||||
} else {
|
||||
format!("{}\n{}\n{}/{}\n",&subject,&body,&reset_url,&session_cookie)
|
||||
};
|
||||
let mail_html_content = if let Some(tpl) = app_dbs.config.tpls.get("reset_password_mail_html") {
|
||||
req_handler.render_template(tpl, "invite")
|
||||
} else {
|
||||
format!("{}\n{}\n{}/{}\n",&subject,&body,&reset_url,&session_cookie)
|
||||
};
|
||||
let mail_check = MailMessage::check(&app_dbs);
|
||||
if ! mail_check.is_empty() {
|
||||
let _ = req_handler.trace_req(format!("Mail service check error: {}",&mail_check));
|
||||
(
|
||||
StatusCode::BAD_REQUEST,
|
||||
req_handler.req_header.header,
|
||||
"Error service"
|
||||
).into_response()
|
||||
} else {
|
||||
match MailMessage::new(
|
||||
&app_dbs.config.mail_from,
|
||||
&user_sel.email,
|
||||
&app_dbs.config.mail_reply_to,
|
||||
) {
|
||||
Ok(mail_message) => {
|
||||
match mail_message.send_html_message(
|
||||
&subject,
|
||||
&mail_content,
|
||||
&mail_html_content,
|
||||
&app_dbs
|
||||
).await {
|
||||
Ok(_) => {
|
||||
let _ = req_handler.trace_req(format!("Mail sent to: '{}' reset url: {} cookie: {}",
|
||||
&user_sel.name, &reset_url,&session_cookie
|
||||
));
|
||||
(
|
||||
StatusCode::OK,
|
||||
format!("Mail sent to {}",&user_sel.name)
|
||||
).into_response()
|
||||
},
|
||||
Err(e) => {
|
||||
let _ = req_handler.trace_req(format!("Mail message send to: '{}' Error: {} ",&user_sel.name,e));
|
||||
println!("Error mail message send: {}",e);
|
||||
(
|
||||
StatusCode::INTERNAL_SERVER_ERROR,
|
||||
req_handler.req_header.header,
|
||||
"Error service"
|
||||
).into_response()
|
||||
}
|
||||
}
|
||||
},
|
||||
Err(e) => {
|
||||
let _ = req_handler.trace_req(format!("Mail message send to: '{}' Creation error: {} ",&user_sel.name,e));
|
||||
println!("Error mail message creation: {}",e);
|
||||
(
|
||||
StatusCode::BAD_REQUEST,
|
||||
req_handler.req_header.header,
|
||||
"Error service"
|
||||
).into_response()
|
||||
}
|
||||
}
|
||||
}
|
||||
//let result=format!("{}","OK");
|
||||
// if ! auth_state.has_auth_role(&app_dbs.config.auth_roles) {
|
||||
// return Redirect::temporary( &format!("/login?o={}",uri.path().to_string())).into_response();
|
||||
// // return (
|
||||
// // StatusCode::UNAUTHORIZED,
|
||||
// // header,
|
||||
// // "Error authorization"
|
||||
// // ).into_response();
|
||||
// }
|
||||
// (
|
||||
// //status,
|
||||
// req_handler.req_header.header,
|
||||
// result,
|
||||
// ).into_response()
|
||||
}
|
||||
async fn reset_password_handler(
|
||||
header: HeaderMap,
|
||||
uri: Uri,
|
||||
Extension(app_dbs): Extension<Arc<AppDBs>>,
|
||||
Extension(cookies): Extension<Cookies>,
|
||||
Extension(random): Extension<Random>,
|
||||
ConnectInfo(app_connect_info): ConnectInfo<AppConnectInfo>,
|
||||
// Query(req_params): Query<ReqParams>,
|
||||
axum::extract::Path(data): axum::extract::Path<String>,
|
||||
) -> Response {
|
||||
let session_cookie = decode(&data).unwrap_or_default().to_string();
|
||||
let auth_state = AuthState::from_cookie(session_cookie.to_owned(), &app_dbs).await;
|
||||
let mut req_handler = ReqHandler::new(
|
||||
ReqHeaderMap::new(header, &format!("{}",&uri.path().to_string()), &app_connect_info),
|
||||
&app_dbs,
|
||||
&uri,
|
||||
&auth_state,
|
||||
&random,
|
||||
"reset_password_handler"
|
||||
);
|
||||
let user_id = auth_state.user_id();
|
||||
if user_id.is_empty() {
|
||||
let _ = req_handler.trace_req(format!("No user found"));
|
||||
return (
|
||||
StatusCode::BAD_REQUEST,
|
||||
req_handler.req_header.header,
|
||||
"Error"
|
||||
).into_response();
|
||||
}
|
||||
let user_sel = User::select("id", &user_id, false, &app_dbs.user_store).await.unwrap_or_else(|e|{
|
||||
println!("Error select: {}", e);
|
||||
User::default()
|
||||
});
|
||||
if user_sel.name.is_empty() {
|
||||
let _ = req_handler.trace_req(format!("User 'id' = '{}' not found",&user_id));
|
||||
// User not exists
|
||||
return (
|
||||
StatusCode::BAD_REQUEST,
|
||||
req_handler.req_header.header,
|
||||
"Error data"
|
||||
).into_response();
|
||||
}
|
||||
if user_sel.status != UserStatus::Active {
|
||||
let _ = req_handler.trace_req(format!("user '{}' in not valid status: {}",&user_id, &user_sel.status));
|
||||
return (
|
||||
StatusCode::BAD_REQUEST,
|
||||
req_handler.req_header.header,
|
||||
"Error status"
|
||||
).into_response();
|
||||
}
|
||||
let mut res_headers = HeaderMap::new();
|
||||
if req_handler.req_header.is_browser() {
|
||||
res_headers.append(axum::http::header::CONTENT_TYPE,"text/html; charset=utf-8".parse().unwrap());
|
||||
}
|
||||
req_handler.context.insert("with_menu", "1");
|
||||
req_handler.context.insert("user", &user_sel);
|
||||
req_handler.context.insert("edit_target", "password");
|
||||
req_handler.context.insert("edit_reset", "password");
|
||||
req_handler.context.remove("web_menu_items");
|
||||
let result = if let Some(tpl) = app_dbs.config.tpls.get("user_settings") {
|
||||
req_handler.render_template(&tpl,"user setting")
|
||||
} else {
|
||||
String::from("user settings")
|
||||
};
|
||||
let user_data = user_sel.session_data();
|
||||
let session_token = req_handler.new_token();
|
||||
let session_cookie = add_session_cookie(true,&cookies, &session_token, &user_data, 0, &app_dbs, "/").await;
|
||||
if app_dbs.config.verbose > 1 { println!("session cookie: {}", &session_cookie) };
|
||||
let _ = req_handler.trace_req(format!("user '{}' reset password",&user_id));
|
||||
(
|
||||
res_headers,
|
||||
result.to_owned()
|
||||
).into_response()
|
||||
}
|
||||
async fn post_user_password_handler(
|
||||
header: HeaderMap,
|
||||
uri: Uri,
|
||||
Extension(app_dbs): Extension<Arc<AppDBs>>,
|
||||
Extension(cookies): Extension<Cookies>,
|
||||
Extension(random): Extension<Random>,
|
||||
ConnectInfo(app_connect_info): ConnectInfo<AppConnectInfo>,
|
||||
Json(user_data): Json<UserData>,
|
||||
) -> Response {
|
||||
let auth_state = get_auth_state(true, &cookies, &app_dbs).await;
|
||||
let req_handler = ReqHandler::new(
|
||||
ReqHeaderMap::new(header, &format!("{}",&uri.path().to_string()), &app_connect_info),
|
||||
&app_dbs,
|
||||
&uri,
|
||||
&auth_state,
|
||||
&random,
|
||||
"post_reset_password_handler"
|
||||
);
|
||||
if user_data.password.is_empty() {
|
||||
let _ = req_handler.trace_req(format!("No passwordfound"));
|
||||
return (
|
||||
StatusCode::BAD_REQUEST,
|
||||
req_handler.req_header.header,
|
||||
"Error"
|
||||
).into_response();
|
||||
}
|
||||
if auth_state.session.is_none() {
|
||||
let _ = req_handler.trace_req(format!("No session found for user '{}'",&user_data.id));
|
||||
return Redirect::temporary( &format!("/login?o={}",uri.path().to_string())).into_response();
|
||||
}
|
||||
let user_id = auth_state.user_id();
|
||||
if user_id.is_empty() {
|
||||
let _ = req_handler.trace_req(format!("No user found"));
|
||||
return (
|
||||
StatusCode::BAD_REQUEST,
|
||||
req_handler.req_header.header,
|
||||
"Error"
|
||||
).into_response();
|
||||
}
|
||||
let mut user_sel = User::select("id", &user_id, false,&app_dbs.user_store).await.unwrap_or_default();
|
||||
if user_sel.name.is_empty() {
|
||||
let _ = req_handler.trace_req(format!("User '{}' not found",&user_id));
|
||||
return (
|
||||
StatusCode::BAD_REQUEST,
|
||||
req_handler.req_header.header,
|
||||
"Error"
|
||||
).into_response();
|
||||
}
|
||||
let passwd_score = User::password_score(&user_data.password);
|
||||
if passwd_score < app_dbs.config.password_score {
|
||||
let _ = req_handler.trace_req(format!("User '{}' password '{}' score: {} under {}"
|
||||
,&user_id,&user_data.password, passwd_score,app_dbs.config.password_score)
|
||||
);
|
||||
return (
|
||||
StatusCode::UNAUTHORIZED,
|
||||
req_handler.req_header.header,
|
||||
"Error"
|
||||
).into_response();
|
||||
}
|
||||
user_sel.password = generate_hash(&user_data.password);
|
||||
let user_data = user_sel.session_data();
|
||||
match user_sel.update(&app_dbs.user_store).await {
|
||||
Ok(_) => {
|
||||
let session_token = auth_state.id();
|
||||
let session_cookie = add_session_cookie(true,&cookies, &session_token, &user_data, 0, &app_dbs, "/").await;
|
||||
if app_dbs.config.verbose > 1 { println!("session cookie: {}", &session_cookie) };
|
||||
let _ = req_handler.trace_req(format!("user '{}' reset password OK",&user_id));
|
||||
let result =String::from("OK");
|
||||
(
|
||||
req_handler.req_header.header,
|
||||
result.to_owned()
|
||||
).into_response()
|
||||
},
|
||||
Err(e) => {
|
||||
let _ = req_handler.trace_req(format!("Error user '{}' reset password: {}",&user_id,e));
|
||||
(
|
||||
StatusCode::BAD_REQUEST,
|
||||
req_handler.req_header.header,
|
||||
"Error"
|
||||
).into_response()
|
||||
},
|
||||
}
|
||||
}
|
||||
route(
|
||||
"/reset/:data", get(reset_password_handler))
|
||||
.route("/reset", post(post_reset_password_handler))
|
||||
.route("/resetup", post(post_user_password_handler))
|
||||
}
|
400
src/handlers/users/settings_handlers.rs
Normal file
400
src/handlers/users/settings_handlers.rs
Normal file
@ -0,0 +1,400 @@
|
||||
use std::sync::Arc;
|
||||
use axum::{
|
||||
http::{
|
||||
StatusCode,
|
||||
Uri,
|
||||
header::HeaderMap,
|
||||
},
|
||||
Json,
|
||||
routing::{get,post},
|
||||
Extension,
|
||||
extract::ConnectInfo,
|
||||
response::{IntoResponse,Response,Redirect},
|
||||
Router,
|
||||
};
|
||||
use tower_cookies::Cookies;
|
||||
|
||||
use crate::{
|
||||
route,
|
||||
defs::{
|
||||
AppDBs,
|
||||
ReqHandler,
|
||||
ReqHeaderMap,
|
||||
TotpMode,
|
||||
Random,
|
||||
AppConnectInfo,
|
||||
},
|
||||
users::{
|
||||
User,
|
||||
UserData,
|
||||
UserItem,
|
||||
OpenidUser,
|
||||
},
|
||||
login_password::generate_hash,
|
||||
handlers::{
|
||||
add_session_cookie,
|
||||
get_auth_state,
|
||||
},
|
||||
};
|
||||
|
||||
pub fn users_settings_router_handlers() -> Router {
|
||||
// async fn edit_user_handler(
|
||||
// header: HeaderMap,
|
||||
// uri: Uri,
|
||||
// Extension(app_dbs): Extension<Arc<AppDBs>>,
|
||||
// Extension(cookies): Extension<Cookies>,
|
||||
// //_auth_state: AuthState,
|
||||
// ) -> Response {
|
||||
// let auth_state = get_auth_state(true, &cookies, &app_dbs).await;
|
||||
// let mut req_handler = ReqHandler::new(
|
||||
// ReqHeaderMap::new(header, &format!("{}",&uri.path().to_string())),
|
||||
// &app_dbs,
|
||||
// &uri,
|
||||
// &auth_state,
|
||||
// "root_handler"
|
||||
// );
|
||||
// let uri_path = format!("{}",&uri.path().to_string());
|
||||
// let file = "hello.html";
|
||||
// let result = app_dbs.tera.render(&file, &app_dbs.context).unwrap_or_else(|e|{
|
||||
// println!("Error render {}: {}",&file,e);
|
||||
// String::from("")
|
||||
// });
|
||||
// req_handler.context.insert("with_menu", "1");
|
||||
// // let mut new_header = header.to_owned();
|
||||
// //new_header.append("Set-Cookie", "session_token=_; Max-Age=0".parse().unwrap());
|
||||
// // cookies.remove(Cookie::new(SESSION_COOKIE_NAME, ""));
|
||||
// (
|
||||
// req_handler.req_header.header,
|
||||
// result.to_owned()
|
||||
// ).into_response()
|
||||
// // "Hello, World!"
|
||||
// }
|
||||
async fn user_settings_handler(
|
||||
header: HeaderMap,
|
||||
uri: Uri,
|
||||
Extension(app_dbs): Extension<Arc<AppDBs>>,
|
||||
Extension(cookies): Extension<Cookies>,
|
||||
Extension(random): Extension<Random>,
|
||||
ConnectInfo(app_connect_info): ConnectInfo<AppConnectInfo>,
|
||||
) -> Response {
|
||||
let auth_state = get_auth_state(true, &cookies, &app_dbs).await;
|
||||
if auth_state.session.is_none() {
|
||||
return Redirect::temporary( &format!("/login?o={}",uri.path().to_string())).into_response();
|
||||
}
|
||||
let mut req_handler = ReqHandler::new(
|
||||
ReqHeaderMap::new(header, &format!("{}",&uri.path().to_string()), &app_connect_info),
|
||||
&app_dbs,
|
||||
&uri,
|
||||
&auth_state,
|
||||
&random,
|
||||
"user_settings_handler"
|
||||
);
|
||||
let mut res_headers = HeaderMap::new();
|
||||
if req_handler.req_header.is_browser() {
|
||||
res_headers.append(axum::http::header::CONTENT_TYPE,"text/html; charset=utf-8".parse().unwrap());
|
||||
}
|
||||
let user_id = auth_state.user_id();
|
||||
if user_id.is_empty() {
|
||||
let _ = req_handler.trace_req(format!("user not id found"));
|
||||
// User not exists
|
||||
return Redirect::temporary( &format!("/")).into_response();
|
||||
}
|
||||
let user_sel = User::select("id", &user_id, true, &app_dbs.user_store).await.unwrap_or_default();
|
||||
if user_sel.name.is_empty() {
|
||||
let _ = req_handler.trace_req(format!("Edit user id '{}' not found ",&user_id));
|
||||
// User not exists
|
||||
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| {
|
||||
println!("Error list selection {}: {}", &user_sel.name, e);
|
||||
Vec::new()
|
||||
});
|
||||
req_handler.context.insert("openid_sel", &openid_sel);
|
||||
let openid_sel_appkeys = openid_sel.iter().map(|id| id.appkey.to_string()).collect::<Vec<String>>().join(",");
|
||||
req_handler.context.insert("openid_sel_appkeys", &openid_sel_appkeys);
|
||||
req_handler.context.insert("with_menu", "1");
|
||||
req_handler.context.insert("user", &user_sel);
|
||||
req_handler.context.insert("admin_fields", &app_dbs.config.admin_fields);
|
||||
req_handler.context.insert("totp_mode", &format!("{}",&app_dbs.config.totp_mode));
|
||||
// let user_items = User::hash_items(&user_sel.items);
|
||||
// req_handler.context.insert("usr_items", &user_items);
|
||||
req_handler.context.insert("no_edit", "true");
|
||||
req_handler.context.insert("edit_target", "main");
|
||||
let result = if let Some(tpl) = app_dbs.config.tpls.get("user_settings") {
|
||||
req_handler.render_template(&tpl,"user setting")
|
||||
} else {
|
||||
String::from("user settings")
|
||||
};
|
||||
let _ = req_handler.trace_req(format!("User '{}' settings",&user_sel.id));
|
||||
(
|
||||
res_headers,
|
||||
result.to_owned()
|
||||
).into_response()
|
||||
}
|
||||
async fn user_settings_edit_handler(
|
||||
header: HeaderMap,
|
||||
uri: Uri,
|
||||
Extension(app_dbs): Extension<Arc<AppDBs>>,
|
||||
Extension(cookies): Extension<Cookies>,
|
||||
Extension(random): Extension<Random>,
|
||||
ConnectInfo(app_connect_info): ConnectInfo<AppConnectInfo>,
|
||||
axum::extract::Path(data): axum::extract::Path<String>,
|
||||
) -> Response {
|
||||
let auth_state = get_auth_state(true, &cookies, &app_dbs).await;
|
||||
if auth_state.session.is_none() {
|
||||
return Redirect::temporary( &format!("/login?o={}",uri.path().to_string())).into_response();
|
||||
}
|
||||
let mut req_handler = ReqHandler::new(
|
||||
ReqHeaderMap::new(header, &format!("{}",&uri.path().to_string()), &app_connect_info),
|
||||
&app_dbs,
|
||||
&uri,
|
||||
&auth_state,
|
||||
&random,
|
||||
"user_settings_edit_handler"
|
||||
);
|
||||
let mut res_headers = HeaderMap::new();
|
||||
if req_handler.req_header.is_browser() {
|
||||
res_headers.append(axum::http::header::CONTENT_TYPE,"text/html; charset=utf-8".parse().unwrap());
|
||||
}
|
||||
if data != "main" && data != "password" && data != "totp" {
|
||||
let _ = req_handler.trace_req(format!("Edit user not data section '{}' ",&data));
|
||||
return Redirect::temporary( &format!("/")).into_response();
|
||||
}
|
||||
let user_id = auth_state.user_id();
|
||||
if user_id.is_empty() {
|
||||
// User not exists
|
||||
let _ = req_handler.trace_req(format!("Edit user not id "));
|
||||
return Redirect::temporary( &format!("/")).into_response();
|
||||
}
|
||||
let user_sel = User::select("id", &user_id, true, &app_dbs.user_store).await.unwrap_or_default();
|
||||
if user_sel.name.is_empty() {
|
||||
let _ = req_handler.trace_req(format!("Edit user id '{}' not found ",&user_id));
|
||||
// User not exists
|
||||
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| {
|
||||
println!("Error list selection {}: {}", &user_sel.name, e);
|
||||
Vec::new()
|
||||
});
|
||||
req_handler.context.insert("openid_sel", &openid_sel);
|
||||
let openid_sel_appkeys = openid_sel.iter().map(|id| id.appkey.to_string()).collect::<Vec<String>>().join(",");
|
||||
req_handler.context.insert("openid_sel_appkeys", &openid_sel_appkeys);
|
||||
req_handler.context.insert("with_menu", "1");
|
||||
req_handler.context.insert("user", &user_sel);
|
||||
req_handler.context.insert("edit_target", &data);
|
||||
req_handler.context.insert("admin_fields", &app_dbs.config.admin_fields);
|
||||
req_handler.context.insert("totp_mode", &format!("{}",&app_dbs.config.totp_mode));
|
||||
if data == "totp" && app_dbs.config.totp_mode != TotpMode::No {
|
||||
if !user_sel.otp_base32.is_empty() {
|
||||
match req_handler.otp_make(&user_sel.otp_base32, &user_sel.otp_defs) {
|
||||
Ok(totp) => {
|
||||
req_handler.context.insert("otp_code", &user_sel.otp_base32);
|
||||
req_handler.context.insert("otp_url", &user_sel.otp_auth_url);
|
||||
req_handler.context.insert("otp_qr", &totp.get_qr_base64().unwrap_or_default());
|
||||
},
|
||||
Err(e) => {
|
||||
println!("User settings error totp: {}",e);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
match req_handler.otp_generate() {
|
||||
Ok(totp) => {
|
||||
req_handler.context.insert("otp_code", &totp.get_secret_base32());
|
||||
req_handler.context.insert("otp_url", &totp.get_url());
|
||||
req_handler.context.insert("otp_qr", &totp.get_qr_base64().unwrap_or_default());
|
||||
},
|
||||
Err(e) => {
|
||||
println!("Error TOTP generartor: {}",e);
|
||||
}
|
||||
}
|
||||
}
|
||||
req_handler.context.insert("totp_digits", &app_dbs.config.totp_digits);
|
||||
req_handler.context.insert("totp_algorithm",&format!("{}",&app_dbs.config.totp_algorithm));
|
||||
}
|
||||
let _ = req_handler.trace_req(format!("Edit user '{}' settings",&user_id));
|
||||
// req_handler.context.insert("no_edit", "true");
|
||||
let result = if let Some(tpl) = app_dbs.config.tpls.get("user_settings") {
|
||||
req_handler.render_template(&tpl,"user setting")
|
||||
} else {
|
||||
String::from("user settings")
|
||||
};
|
||||
(
|
||||
res_headers,
|
||||
result.to_owned()
|
||||
).into_response()
|
||||
}
|
||||
async fn post_user_settings_handler(
|
||||
header: HeaderMap,
|
||||
uri: Uri,
|
||||
Extension(app_dbs): Extension<Arc<AppDBs>>,
|
||||
Extension(cookies): Extension<Cookies>,
|
||||
Extension(random): Extension<Random>,
|
||||
ConnectInfo(app_connect_info): ConnectInfo<AppConnectInfo>,
|
||||
Json(user_data): Json<UserData>,
|
||||
) -> Response {
|
||||
let auth_state = get_auth_state(true, &cookies, &app_dbs).await;
|
||||
let req_handler = ReqHandler::new(
|
||||
ReqHeaderMap::new(header, &format!("{}",&uri.path().to_string()), &app_connect_info),
|
||||
&app_dbs,
|
||||
&uri,
|
||||
&auth_state,
|
||||
&random,
|
||||
"post_user_settings_handler"
|
||||
);
|
||||
if auth_state.session.is_none() {
|
||||
let _ = req_handler.trace_req(format!("No session found for user '{}'",&user_data.id));
|
||||
return Redirect::temporary( &format!("/login?o={}",uri.path().to_string())).into_response();
|
||||
}
|
||||
let user_id = auth_state.user_id();
|
||||
if user_id.is_empty() {
|
||||
let _ = req_handler.trace_req(format!("No user found"));
|
||||
return (
|
||||
StatusCode::BAD_REQUEST,
|
||||
req_handler.req_header.header,
|
||||
"Error"
|
||||
).into_response();
|
||||
}
|
||||
let mut user_sel = User::select("id", &user_id, false,&app_dbs.user_store).await.unwrap_or_default();
|
||||
if user_sel.name.is_empty() {
|
||||
let _ = req_handler.trace_req(format!("User '{}' not found",&user_id));
|
||||
return (
|
||||
StatusCode::BAD_REQUEST,
|
||||
req_handler.req_header.header,
|
||||
"Error"
|
||||
).into_response();
|
||||
}
|
||||
if !user_data.password.is_empty() {
|
||||
let passwd_score = User::password_score(&user_data.password);
|
||||
if passwd_score < app_dbs.config.password_score {
|
||||
let _ = req_handler.trace_req(format!("User '{}' password '{}' score: {} under {}"
|
||||
,&user_id,&user_data.password, passwd_score,app_dbs.config.password_score
|
||||
));
|
||||
return (
|
||||
StatusCode::UNAUTHORIZED,
|
||||
req_handler.req_header.header,
|
||||
"Error"
|
||||
).into_response();
|
||||
}
|
||||
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| {
|
||||
// println!("Error list selection {}: {}", &user_sel.name, e);
|
||||
// Vec::new()
|
||||
//});
|
||||
//let openid_sel_appkeys = openid_sel.iter().map(|id| id.appkey.to_string()).collect::<Vec<String>>().join(",");
|
||||
let otp_enabled: bool;
|
||||
if app_dbs.config.totp_mode != TotpMode::No && !user_data.otp_auth.is_empty() {
|
||||
match req_handler.otp_check(&user_data.otp_code,&user_data.otp_auth, "") {
|
||||
Ok(val) => {
|
||||
if val {
|
||||
otp_enabled = true;
|
||||
} else {
|
||||
// otp_enabled = fasle;
|
||||
let _ = req_handler.trace_req(format!("User '{}' not valid TOTP code",&user_id));
|
||||
return (
|
||||
StatusCode::UNAUTHORIZED,
|
||||
req_handler.req_header.header,
|
||||
"Error"
|
||||
).into_response();
|
||||
}
|
||||
},
|
||||
Err(e) => {
|
||||
println!("TOTP check: {}", e);
|
||||
let _ = req_handler.trace_req(format!("User '{}' TOTP check error: {}",&user_id,e));
|
||||
return (
|
||||
StatusCode::UNAUTHORIZED,
|
||||
req_handler.req_header.header,
|
||||
"Error"
|
||||
).into_response();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
otp_enabled = false;
|
||||
}
|
||||
if otp_enabled {
|
||||
user_sel.otp_enabled= true;
|
||||
user_sel.otp_verified= true;
|
||||
user_sel.otp_base32 = user_data.otp_code.to_owned();
|
||||
user_sel.otp_auth_url = user_data.otp_url.to_owned();
|
||||
user_sel.otp_defs = format!("{},{}",
|
||||
&app_dbs.config.totp_digits,
|
||||
format!("{}",&app_dbs.config.totp_algorithm),
|
||||
);
|
||||
} else {
|
||||
user_sel.otp_enabled= false;
|
||||
user_sel.otp_verified = false;
|
||||
user_sel.otp_base32 = String::from("");
|
||||
user_sel.otp_auth_url = String::from("");
|
||||
user_sel.otp_defs = String::from("");
|
||||
}
|
||||
let user_openids = user_data.opendis.to_owned();
|
||||
user_sel.from_data(user_data);
|
||||
let new_id= user_sel.id.to_string();
|
||||
let user_data = user_sel.session_data();
|
||||
match user_sel.update(&app_dbs.user_store).await {
|
||||
Ok(_) => {
|
||||
let session_token = auth_state.id();
|
||||
let session_cookie = add_session_cookie(true,&cookies, &session_token, &user_data, 0, &app_dbs, "/").await;
|
||||
if app_dbs.config.verbose > 1 { println!("session cookie: {}", &session_cookie) };
|
||||
let _ = req_handler.trace_req(format!("User '{}' updated",&user_id));
|
||||
OpenidUser::sync_ids(&new_id, &user_openids, &app_dbs.user_store).await;
|
||||
let result =String::from("OK");
|
||||
(
|
||||
req_handler.req_header.header,
|
||||
result.to_owned()
|
||||
).into_response()
|
||||
},
|
||||
Err(e) => {
|
||||
let _ = req_handler.trace_req(format!("User '{}' update error: {}",&user_id,e));
|
||||
(
|
||||
StatusCode::BAD_REQUEST,
|
||||
req_handler.req_header.header,
|
||||
"Error"
|
||||
).into_response()
|
||||
}
|
||||
}
|
||||
}
|
||||
async fn update_user_item_handler(
|
||||
header: HeaderMap,
|
||||
uri: Uri,
|
||||
Extension(app_dbs): Extension<Arc<AppDBs>>,
|
||||
Extension(cookies): Extension<Cookies>,
|
||||
Extension(random): Extension<Random>,
|
||||
ConnectInfo(app_connect_info): ConnectInfo<AppConnectInfo>,
|
||||
Json(user_item): Json<UserItem>,
|
||||
//_auth_state: AuthState,
|
||||
//axum::extract::Path(data): axum::extract::Path<String>,
|
||||
) -> Response {
|
||||
let auth_state = get_auth_state(true, &cookies, &app_dbs).await;
|
||||
let req_handler = ReqHandler::new(
|
||||
ReqHeaderMap::new(header, &format!("{}",&uri.path().to_string()), &app_connect_info),
|
||||
&app_dbs,
|
||||
&uri,
|
||||
&auth_state,
|
||||
&random,
|
||||
"update_user_item_handler"
|
||||
);
|
||||
if ! auth_state.has_auth_role(&app_dbs.config.auth_roles) {
|
||||
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 (
|
||||
// StatusCode::UNAUTHORIZED,
|
||||
// header,
|
||||
// "Error authorization"
|
||||
// ).into_response();
|
||||
}
|
||||
dbg!("{}",&user_item);
|
||||
let result="";
|
||||
(
|
||||
//status,
|
||||
req_handler.req_header.header,
|
||||
result,
|
||||
).into_response()
|
||||
}
|
||||
route(
|
||||
"/settings", get(user_settings_handler))
|
||||
.route("/settings/:item", get(user_settings_edit_handler))
|
||||
// .route("/update", post(update_user_handler))
|
||||
.route("/settings", post(post_user_settings_handler))
|
||||
.route("/update_item", post(update_user_item_handler))
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -107,7 +107,9 @@ static PKG_FULLNAME: Lazy<String> = Lazy::new(|| {
|
||||
});
|
||||
|
||||
pub const USERS_TABLENAME: &str = "users";
|
||||
pub const OPENID_USERS_TABLENAME: &str = "openid_users";
|
||||
pub const USERS_FILESTORE: &str = "users";
|
||||
pub const OPENID_USERS_FILESTORE: &str = "openid_users";
|
||||
pub const DEFAULT_ROLES: &str = "user";
|
||||
|
||||
|
||||
|
@ -480,11 +480,11 @@ impl User {
|
||||
)
|
||||
}
|
||||
pub fn hash_items(items: &str) -> HashMap<String,String> {
|
||||
if items.is_empty() {
|
||||
if items.is_empty() || ! items.starts_with("{") {
|
||||
HashMap::new()
|
||||
} else {
|
||||
serde_json::from_str(items).unwrap_or_else(|e|{
|
||||
println!("Error to convert user items to json: {}",e);
|
||||
println!("Error to pars string to user items: {}",e);
|
||||
HashMap::new()
|
||||
})
|
||||
}
|
||||
|
@ -1,7 +1,8 @@
|
||||
use std::collections::HashMap;
|
||||
use serde::{Deserialize,Serialize};
|
||||
use serde::{Deserialize,Serialize, Deserializer};
|
||||
|
||||
// use crate::defs::AppDBs;
|
||||
use crate::users::User;
|
||||
|
||||
fn default_empty() -> String {
|
||||
"".to_string()
|
||||
@ -21,9 +22,19 @@ fn default_isadmin() -> bool {
|
||||
fn default_otp_empty() -> String {
|
||||
String::from("")
|
||||
}
|
||||
fn deserialize_id<'de, D>(deserializer: D) -> Result<String, D::Error>
|
||||
where D: Deserializer<'de> {
|
||||
Ok(String::deserialize(deserializer)?)
|
||||
}
|
||||
|
||||
#[derive(Default,Deserialize,Serialize,Debug,Clone)]
|
||||
pub struct AllUserData {
|
||||
pub user: User,
|
||||
pub openids: String,
|
||||
}
|
||||
#[derive(Default,Deserialize,Serialize,Debug,Clone)]
|
||||
pub struct UserData {
|
||||
#[serde(default = "default_empty")]
|
||||
#[serde(default = "default_empty",deserialize_with = "deserialize_id")]
|
||||
pub id: String,
|
||||
#[serde(default = "default_empty")]
|
||||
pub name: String,
|
||||
@ -45,6 +56,8 @@ pub struct UserData {
|
||||
pub roles: String,
|
||||
#[serde(default = "default_items")]
|
||||
pub items: HashMap<String,String>,
|
||||
#[serde(default = "default_empty")]
|
||||
pub opendis: String,
|
||||
}
|
||||
// impl UserData {
|
||||
// pub fn from_id(id: String, _app_dbs: &AppDBs) -> Self {
|
||||
|
Loading…
Reference in New Issue
Block a user