use super::*;
use base64::Engine;
use rand::{distributions::Alphanumeric, Rng};
#[derive(Deserialize)]
pub struct Request {
pub email: String,
pub sender_name: String,
pub callback: String,
}
#[derive(Serialize, Queryable, Selectable)]
#[diesel(table_name = schema::user)]
pub struct Response {
pub id: i32,
}
#[derive(Serialize, Default)]
struct SendMail {
sender_name: String,
recipient: String,
subject: String,
base64_content: String,
}
#[post("")]
pub async fn route(
db: web::Data<Database>,
req: web::Json<Request>,
) -> Result<impl Responder, impl ResponseError> {
let req = req.into_inner();
let token: String = rand::thread_rng()
.sample_iter(&Alphanumeric)
.take(32)
.map(char::from)
.collect();
let token_moved = token.clone();
let email_moved = req.email.clone();
let returned: Result<i32, diesel::result::Error> = web::block(move || {
use diesel::dsl::*;
let mut conn = db.get_conn();
conn.transaction(|conn| {
let user_id: Result<i32, diesel::result::Error> = schema::user::table
.select(schema::user::id)
.filter(schema::user::email.eq(email_moved))
.first(conn);
if user_id.is_err() {
return user_id;
}
let user_id = user_id.unwrap();
delete(schema::reset::table.filter(schema::reset::user.eq(user_id)))
.execute(conn)
.unwrap();
let user_id = insert_into(schema::reset::table)
.values((
schema::reset::user.eq(user_id),
schema::reset::token.eq(token_moved),
))
.returning(schema::reset::user)
.get_result(conn);
user_id
})
})
.await
.unwrap();
let id = match returned {
Err(_) => return Err(ErrorCode::NotFound),
Ok(id) => id,
};
let body = format!(
"Please click the following link to reset your {} account password: {}?token={}",
req.sender_name, req.callback, token
);
let body = base64::engine::general_purpose::STANDARD.encode(body);
reqwest::Client::new()
.post(format!(
"{}/v1/send",
std::env::var("MAIL_SERVICE_HOST")
.expect("MAIL_SERVICE_HOST environment variable is not set")
))
.json(&SendMail {
sender_name: req.sender_name,
recipient: req.email,
subject: "Password Reset".to_owned(),
base64_content: body,
})
.send()
.await
.unwrap();
Ok(web::Json(Response { id }))
}