summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorColin Reeder <vpzomtrrfrt@gmail.com>2020-09-26 13:53:24 -0600
committerColin Reeder <vpzomtrrfrt@gmail.com>2020-09-26 13:53:24 -0600
commitb6c67541127314c9d674083f595df059e8aa2c06 (patch)
treed42a6d7db89172c1f853b0b71ef6a44708726dbc
parente1683a89fd09948fa3931449e75af15a4398eb32 (diff)
Split forgot_password routes into module
-rw-r--r--src/routes/api/forgot_password.rs108
-rw-r--r--src/routes/api/mod.rs106
2 files changed, 110 insertions, 104 deletions
diff --git a/src/routes/api/forgot_password.rs b/src/routes/api/forgot_password.rs
new file mode 100644
index 0000000..8a8504e
--- /dev/null
+++ b/src/routes/api/forgot_password.rs
@@ -0,0 +1,108 @@
+use crate::UserLocalID;
+use lettre::Tokio02Transport;
+use rand::Rng;
+use serde_derive::Deserialize;
+use std::borrow::Cow;
+use std::sync::Arc;
+
+struct ForgotPasswordKey {
+ value: i32,
+}
+
+impl ForgotPasswordKey {
+ pub fn generate() -> Self {
+ Self {
+ value: rand::thread_rng().gen(),
+ }
+ }
+
+ pub fn as_int(&self) -> i32 {
+ self.value
+ }
+
+ pub fn to_str(&self) -> String {
+ bs58::encode(&self.value.to_be_bytes()).into_string()
+ }
+}
+
+async fn route_unstable_forgot_password_keys_create(
+ _: (),
+ ctx: Arc<crate::RouteContext>,
+ req: hyper::Request<hyper::Body>,
+) -> Result<hyper::Response<hyper::Body>, crate::Error> {
+ let lang = crate::get_lang_for_req(&req);
+
+ if ctx.mailer.is_none() {
+ return Err(crate::Error::UserError(crate::simple_response(
+ hyper::StatusCode::INTERNAL_SERVER_ERROR,
+ lang.tr("email_not_configured", None).into_owned(),
+ )));
+ }
+
+ #[derive(Deserialize)]
+ struct ForgotPasswordBody<'a> {
+ email_address: Cow<'a, str>,
+ }
+
+ let body = hyper::body::to_bytes(req.into_body()).await?;
+ let body: ForgotPasswordBody = serde_json::from_slice(&body)?;
+
+ let db = ctx.db_pool.get().await?;
+
+ let user_row = db.query_opt("SELECT id, username, email_address FROM person WHERE local AND LOWER(email_address) = LOWER($1)", &[&body.email_address]).await?
+ .ok_or_else(|| {
+ crate::Error::UserError(crate::simple_response(
+ hyper::StatusCode::BAD_REQUEST,
+ lang.tr("no_such_local_user_by_email", None).into_owned(),
+ ))
+ })?;
+
+ let user_id = UserLocalID(user_row.get(0));
+ let username: &str = user_row.get(1);
+ let user_email: &str = user_row.get(2);
+
+ let user_email = lettre::Mailbox::new(None, user_email.parse()?);
+
+ let key = ForgotPasswordKey::generate();
+ db.execute(
+ "INSERT INTO forgot_password_key (key, person, created) VALUES ($1, $2, current_timestamp)",
+ &[&key.as_int(), &user_id],
+ )
+ .await?;
+
+ let msg_body = lang
+ .tr(
+ "email_content_forgot_password",
+ Some(&fluent::fluent_args!["key" => key.to_str(), "username" => username]),
+ )
+ .into_owned();
+
+ let msg = lettre::Message::builder()
+ .date_now()
+ .subject("Forgot Password Request")
+ .from(ctx.mail_from.as_ref().unwrap().clone())
+ .to(user_email)
+ .singlepart(
+ lettre::message::SinglePart::binary()
+ .header(lettre::message::header::ContentType::text_utf8())
+ .body(msg_body),
+ )?;
+
+ crate::spawn_task(async move {
+ ctx.mailer.as_ref().unwrap().send(msg).await?;
+
+ Ok(())
+ });
+
+ Ok(hyper::Response::builder()
+ .header(hyper::header::CONTENT_TYPE, "application/json")
+ .body("{}".into())?)
+}
+
+pub fn route_forgot_password() -> crate::RouteNode<()> {
+ crate::RouteNode::new().with_child(
+ "keys",
+ crate::RouteNode::new()
+ .with_handler_async("POST", route_unstable_forgot_password_keys_create),
+ )
+}
diff --git a/src/routes/api/mod.rs b/src/routes/api/mod.rs
index af51521..88f64aa 100644
--- a/src/routes/api/mod.rs
+++ b/src/routes/api/mod.rs
@@ -1,7 +1,5 @@
use crate::routes::well_known::{FingerRequestQuery, FingerResponse};
use crate::{CommentLocalID, CommunityLocalID, PostLocalID, UserLocalID};
-use lettre::Tokio02Transport;
-use rand::Rng;
use serde_derive::{Deserialize, Serialize};
use std::borrow::Cow;
use std::collections::{HashMap, HashSet};
@@ -10,6 +8,7 @@ use std::sync::Arc;
mod comments;
mod communities;
+mod forgot_password;
mod posts;
mod users;
@@ -179,14 +178,7 @@ pub fn route_api() -> crate::RouteNode<()> {
.with_child("posts", posts::route_posts())
.with_child("comments", comments::route_comments())
.with_child("users", users::route_users())
- .with_child(
- "forgot_password",
- crate::RouteNode::new().with_child(
- "keys",
- crate::RouteNode::new()
- .with_handler_async("POST", route_unstable_forgot_password_keys_create),
- ),
- ),
+ .with_child("forgot_password", forgot_password::route_forgot_password()),
)
}
@@ -719,100 +711,6 @@ async fn route_unstable_misc_render_markdown(
.body(output.into())?)
}
-struct ForgotPasswordKey {
- value: i32,
-}
-
-impl ForgotPasswordKey {
- pub fn generate() -> Self {
- Self {
- value: rand::thread_rng().gen(),
- }
- }
-
- pub fn as_int(&self) -> i32 {
- self.value
- }
-
- pub fn to_str(&self) -> String {
- bs58::encode(&self.value.to_be_bytes()).into_string()
- }
-}
-
-async fn route_unstable_forgot_password_keys_create(
- _: (),
- ctx: Arc<crate::RouteContext>,
- req: hyper::Request<hyper::Body>,
-) -> Result<hyper::Response<hyper::Body>, crate::Error> {
- let lang = crate::get_lang_for_req(&req);
-
- if ctx.mailer.is_none() {
- return Err(crate::Error::UserError(crate::simple_response(
- hyper::StatusCode::INTERNAL_SERVER_ERROR,
- lang.tr("email_not_configured", None).into_owned(),
- )));
- }
-
- #[derive(Deserialize)]
- struct ForgotPasswordBody<'a> {
- email_address: Cow<'a, str>,
- }
-
- let body = hyper::body::to_bytes(req.into_body()).await?;
- let body: ForgotPasswordBody = serde_json::from_slice(&body)?;
-
- let db = ctx.db_pool.get().await?;
-
- let user_row = db.query_opt("SELECT id, username, email_address FROM person WHERE local AND LOWER(email_address) = LOWER($1)", &[&body.email_address]).await?
- .ok_or_else(|| {
- crate::Error::UserError(crate::simple_response(
- hyper::StatusCode::BAD_REQUEST,
- lang.tr("no_such_local_user_by_email", None).into_owned(),
- ))
- })?;
-
- let user_id = UserLocalID(user_row.get(0));
- let username: &str = user_row.get(1);
- let user_email: &str = user_row.get(2);
-
- let user_email = lettre::Mailbox::new(None, user_email.parse()?);
-
- let key = ForgotPasswordKey::generate();
- db.execute(
- "INSERT INTO forgot_password_key (key, person, created) VALUES ($1, $2, current_timestamp)",
- &[&key.as_int(), &user_id],
- )
- .await?;
-
- let msg_body = lang
- .tr(
- "email_content_forgot_password",
- Some(&fluent::fluent_args!["key" => key.to_str(), "username" => username]),
- )
- .into_owned();
-
- let msg = lettre::Message::builder()
- .date_now()
- .subject("Forgot Password Request")
- .from(ctx.mail_from.as_ref().unwrap().clone())
- .to(user_email)
- .singlepart(
- lettre::message::SinglePart::binary()
- .header(lettre::message::header::ContentType::text_utf8())
- .body(msg_body),
- )?;
-
- crate::spawn_task(async move {
- ctx.mailer.as_ref().unwrap().send(msg).await?;
-
- Ok(())
- });
-
- Ok(hyper::Response::builder()
- .header(hyper::header::CONTENT_TYPE, "application/json")
- .body("{}".into())?)
-}
-
async fn handle_common_posts_list(
stream: impl futures::stream::TryStream<Ok = tokio_postgres::Row, Error = tokio_postgres::Error>
+ Send,