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, mailer: web::Data, handlebars: web::Data>, input: web::Json<(Vec, Nutzer)>, ) -> Result { 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 " .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, mailer: web::Data, handlebars: web::Data>, validation_key: web::Path, ) -> Result { match confirm_appointments(&pool, &validation_key).await { Ok(_) => Ok(HttpResponse::Ok().json(RequestState::Success)), Err(e) => Err(error::ErrorBadRequest(e)), } }