use crate::routes::{ fetch_base_data, for_client, get_cookie_map_for_headers, get_cookie_map_for_req, html_response, res_to_error, CookieMap, HTPage, }; use serde_derive::Deserialize; use std::borrow::Cow; use std::sync::Arc; async fn page_forgot_password( _: (), ctx: Arc, req: hyper::Request, ) -> Result, crate::Error> { let cookies = get_cookie_map_for_req(&req)?; page_forgot_password_inner(ctx, req.headers(), &cookies, None).await } async fn page_forgot_password_inner( ctx: Arc, headers: &hyper::header::HeaderMap, cookies: &CookieMap<'_>, display_error: Option, ) -> Result, crate::Error> { let lang = crate::get_lang_for_headers(headers); let base_data = fetch_base_data(&ctx.backend_host, &ctx.http_client, headers, &cookies).await?; let title = lang.tr("forgot_password", None); Ok(html_response(render::html! {

{title.as_ref()}

{lang.tr("forgot_password_info", None)}

{ display_error.map(|msg| { render::rsx! {
{msg}
} }) }
})) } async fn page_forgot_password_code( _: (), ctx: Arc, req: hyper::Request, ) -> Result, crate::Error> { let cookies = get_cookie_map_for_req(&req)?; page_forgot_password_code_inner(ctx, req.headers(), &cookies, None).await } async fn page_forgot_password_code_inner( ctx: Arc, headers: &hyper::header::HeaderMap, cookies: &CookieMap<'_>, display_error: Option, ) -> Result, crate::Error> { let lang = crate::get_lang_for_headers(headers); let base_data = fetch_base_data(&ctx.backend_host, &ctx.http_client, headers, &cookies).await?; let title = lang.tr("forgot_password", None); Ok(html_response(render::html! {

{title.as_ref()}

{lang.tr("forgot_password_code_info", None)}

{ display_error.map(|msg| { render::rsx! {
{msg}
} }) }
})) } async fn page_forgot_password_code_reset_inner( key: &str, ctx: Arc, headers: &hyper::header::HeaderMap, cookies: &CookieMap<'_>, display_error: Option, ) -> Result, crate::Error> { let lang = crate::get_lang_for_headers(headers); let base_data = fetch_base_data(&ctx.backend_host, &ctx.http_client, headers, &cookies).await?; let title = lang.tr("forgot_password", None); Ok(html_response(render::html! {

{title.as_ref()}

{ display_error.map(|msg| { render::rsx! {
{msg}
} }) }
})) } async fn handler_forgot_password_code_submit( _: (), ctx: Arc, req: hyper::Request, ) -> Result, crate::Error> { #[derive(Deserialize)] struct CodeSubmitBody<'a> { key: Cow<'a, str>, new_password: Option>, } let (req_parts, body) = req.into_parts(); let cookies = get_cookie_map_for_headers(&req_parts.headers)?; let body = hyper::body::to_bytes(body).await?; let body: CodeSubmitBody = serde_urlencoded::from_bytes(&body)?; if let Some(new_password) = body.new_password { let api_res = res_to_error( ctx.http_client .request(for_client( hyper::Request::post(format!( "{}/api/unstable/forgot_password/keys/{}/reset", ctx.backend_host, urlencoding::encode(&body.key), )) .body( serde_json::to_vec(&serde_json::json!({ "new_password": new_password }))? .into(), )?, &req_parts.headers, &cookies, )?) .await?, ) .await; match api_res { Ok(_) => { let base_data = fetch_base_data( &ctx.backend_host, &ctx.http_client, &req_parts.headers, &cookies, ) .await?; let lang = crate::get_lang_for_headers(&req_parts.headers); let title = lang.tr("forgot_password", None); Ok(html_response(render::html! {

{title.as_ref()}

{lang.tr("forgot_password_complete", None)}{" "} {lang.tr("login", None)}

})) } Err(crate::Error::RemoteError((_, message))) => { page_forgot_password_code_reset_inner( &body.key, ctx, &req_parts.headers, &cookies, Some(message), ) .await } Err(other) => Err(other), } } else { let api_res = res_to_error( ctx.http_client .request(for_client( hyper::Request::get(format!( "{}/api/unstable/forgot_password/keys/{}", ctx.backend_host, urlencoding::encode(&body.key), )) .body(Default::default())?, &req_parts.headers, &cookies, )?) .await?, ) .await; match api_res { Ok(_) => { page_forgot_password_code_reset_inner( &body.key, ctx, &req_parts.headers, &cookies, None, ) .await } Err(crate::Error::RemoteError((_, message))) => { page_forgot_password_code_inner(ctx, &req_parts.headers, &cookies, Some(message)) .await } Err(other) => Err(other), } } } async fn handler_forgot_password_submit( _: (), ctx: Arc, req: hyper::Request, ) -> Result, crate::Error> { let (req_parts, body) = req.into_parts(); let cookies = get_cookie_map_for_headers(&req_parts.headers)?; let body = hyper::body::to_bytes(body).await?; let body: serde_json::Value = serde_urlencoded::from_bytes(&body)?; let api_res = res_to_error( ctx.http_client .request(for_client( hyper::Request::post(format!( "{}/api/unstable/forgot_password/keys", ctx.backend_host, )) .body(serde_json::to_vec(&body)?.into())?, &req_parts.headers, &cookies, )?) .await?, ) .await; match api_res { Ok(_) => Ok(hyper::Response::builder() .status(hyper::StatusCode::SEE_OTHER) .header(hyper::header::LOCATION, "/forgot_password/code") .body("Request submitted.".into())?), Err(crate::Error::RemoteError((_, message))) => { page_forgot_password_inner(ctx, &req_parts.headers, &cookies, Some(message)).await } Err(other) => Err(other), } } pub fn route_forgot_password() -> crate::RouteNode<()> { crate::RouteNode::new() .with_handler_async("GET", page_forgot_password) .with_child( "code", crate::RouteNode::new() .with_handler_async("GET", page_forgot_password_code) .with_child( "submit", crate::RouteNode::new() .with_handler_async("POST", handler_forgot_password_code_submit), ), ) .with_child( "submit", crate::RouteNode::new().with_handler_async("POST", handler_forgot_password_submit), ) }