docserver/src/handlers/users/invite_handlers.rs

346 lines
14 KiB
Rust
Raw Normal View History

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