102 lines
3.3 KiB
Rust

use actix_web::{error, web, HttpResponse};
use handlebars::Handlebars;
use lettre::{message::header::ContentType, Message, SmtpTransport, Transport};
use log::debug;
use rand::{distributions::Alphanumeric, thread_rng, Rng};
use serde_json::json;
use terminwahl_typen::{Nutzer, PlannedAppointment, RequestState};
use crate::db::{self, write::confirm_appointments, Pool};
pub async fn save_appointments_json(
pool: web::Data<Pool>,
mailer: web::Data<SmtpTransport>,
handlebars: web::Data<Handlebars<'_>>,
input: web::Json<(Vec<PlannedAppointment>, Nutzer)>,
) -> Result<HttpResponse, error::Error> {
debug!("Extracting data");
let (appointments, nutzer) = input.into_inner();
debug!("Saving user");
let nutzer_id = db::write::save_nutzer(&pool, &nutzer)
.await
.map_err(error::ErrorInternalServerError)?;
debug!("Saving appointments");
let validation_key: String = thread_rng()
.sample_iter(&Alphanumeric)
.take(30)
.map(char::from)
.collect();
db::write::save_appointments(&pool, &appointments, nutzer_id, &validation_key)
.await
.map_err(error::ErrorInternalServerError)?;
let mail_result = send_confirmation_request(&nutzer, &validation_key, &handlebars, &mailer);
Ok(HttpResponse::Ok().json(mail_result))
}
pub fn send_confirmation_request(
nutzer: &Nutzer,
validation_key: &str,
handlebars: &Handlebars,
mailer: &SmtpTransport,
) -> RequestState {
let data = json! {
{
"nutzer": nutzer,
"validation_key": validation_key
}};
debug!("{:?}", handlebars.get_templates());
if let Ok(email_text) = handlebars.render("email_confirm", &data) {
let email = match Message::builder()
.from(
"Franz Dietrich <franz.dietrich@uhlandshoehe.de>"
.parse()
.expect("Should not fail"),
)
.to(
match format!("{} <{}>", nutzer.name, nutzer.email).parse() {
Ok(v) => v,
Err(_) => return RequestState::Error,
},
)
.subject("Elternsprechtag: Bestätigen Sie Ihre Termine")
.header(ContentType::TEXT_PLAIN)
.body(
match lettre::message::Body::new_with_encoding(
email_text,
lettre::message::header::ContentTransferEncoding::Base64,
) {
Ok(body) => body,
Err(_) => return RequestState::Error,
},
) {
Ok(message) => message,
Err(_) => return RequestState::Error,
};
// Send the email
match mailer.send(&email) {
Ok(_) => RequestState::Success,
Err(e) => {
debug!("Failed to send: {e}");
RequestState::Error
}
}
} else {
RequestState::Error
}
}
pub async fn confirm_validation_key(
pool: web::Data<Pool>,
mailer: web::Data<SmtpTransport>,
handlebars: web::Data<Handlebars<'_>>,
validation_key: web::Path<String>,
) -> Result<HttpResponse, error::Error> {
match confirm_appointments(&pool, &validation_key).await {
Ok(_) => Ok(HttpResponse::Ok().json(RequestState::Success)),
Err(e) => Err(error::ErrorBadRequest(e)),
}
}