mission trip form now posts to nextcloud, skeleton of sqlx
This commit is contained in:
parent
f78e9ea162
commit
87c0d9cb01
819
Cargo.lock
generated
819
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -30,3 +30,5 @@ tracing-appender = "0.2.3"
|
|||
actix-files = "0.6.6"
|
||||
tracing-actix-web = "0.7.14"
|
||||
color-eyre = "0.6.3"
|
||||
pretty_assertions = "1.4.1"
|
||||
sqlx = { version = "0.8.2", features = ["sqlite"] }
|
||||
|
|
|
@ -1,12 +1,19 @@
|
|||
use std::fs;
|
||||
use std::{
|
||||
collections::{BTreeMap, HashMap},
|
||||
fs,
|
||||
};
|
||||
|
||||
use actix_multipart::form::{tempfile::TempFile, text::Text, MultipartForm};
|
||||
use actix_web::{post, HttpResponse};
|
||||
use actix_web::{post, web, HttpResponse};
|
||||
use color_eyre::{eyre::eyre, Result};
|
||||
use lettre::{
|
||||
message::{header::ContentType, Attachment, MultiPart, SinglePart},
|
||||
Message,
|
||||
};
|
||||
use maud::{html, PreEscaped, DOCTYPE};
|
||||
use reqwest::Client;
|
||||
use serde_json::json;
|
||||
use sqlx::SqliteConnection;
|
||||
use tracing::{error, info};
|
||||
|
||||
#[derive(Debug, MultipartForm)]
|
||||
|
@ -63,7 +70,51 @@ struct MtForm {
|
|||
final_agreement: Text<String>,
|
||||
registration: Text<String>,
|
||||
#[multipart(rename = "image")]
|
||||
file: TempFile,
|
||||
file: Option<TempFile>,
|
||||
}
|
||||
|
||||
impl From<&MtForm> for HashMap<i32, String> {
|
||||
fn from(form: &MtForm) -> Self {
|
||||
let mut map = HashMap::new();
|
||||
map.insert(106, format!("{} {}", form.first_name.0, form.last_name.0));
|
||||
map.insert(
|
||||
107,
|
||||
format!("{} {}", form.parent_first_name.0, form.parent_last_name.0),
|
||||
);
|
||||
map.insert(109, form.gender.0.clone());
|
||||
map.insert(110, form.birthdate.0.clone());
|
||||
map.insert(117, form.street.0.clone());
|
||||
map.insert(118, form.city.0.clone());
|
||||
map.insert(119, form.zip.0.to_string());
|
||||
map.insert(120, form.state.0.clone());
|
||||
map.insert(121, form.cellphone.0.clone());
|
||||
map.insert(122, form.email.0.clone());
|
||||
map.insert(123, form.parentphone.0.clone());
|
||||
map.insert(124, form.parentemail.0.clone());
|
||||
map.insert(125, form.school.0.clone());
|
||||
map.insert(126, form.grade.0.clone());
|
||||
map.insert(
|
||||
127,
|
||||
format!("{} {}", form.pastor_first_name.0, form.pastor_last_name.0),
|
||||
);
|
||||
map.insert(128, form.church_attendance.0.clone());
|
||||
map.insert(129, form.tfc_group.0.clone());
|
||||
map.insert(130, form.shirt.0.clone());
|
||||
map.insert(131, form.trip.0.clone());
|
||||
map.insert(132, form.trip_notes.0.clone());
|
||||
map.insert(133, form.relationship_with_jesus.0.clone());
|
||||
map.insert(134, form.testimony.0.clone());
|
||||
map.insert(135, form.involvement_with_group.0.clone());
|
||||
map.insert(136, form.reasons.0.clone());
|
||||
map.insert(137, form.strengths.0.clone());
|
||||
map.insert(138, form.weaknesses.0.clone());
|
||||
map.insert(139, form.previous_trip_info.0.clone());
|
||||
map.insert(140, form.attitude.0.clone());
|
||||
map.insert(141, form.relevant_notes.0.clone());
|
||||
map.insert(144, form.final_agreement.0.clone());
|
||||
map.insert(145, form.registration.0.clone());
|
||||
map
|
||||
}
|
||||
}
|
||||
|
||||
impl MtForm {
|
||||
|
@ -216,6 +267,33 @@ impl MtForm {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn store_form(&self) -> Result<()> {
|
||||
let client = Client::new();
|
||||
let map = HashMap::from(self);
|
||||
let mut json = HashMap::new();
|
||||
dbg!(&map);
|
||||
json.insert("data", map);
|
||||
let res = client
|
||||
.post("https://staff.tfcconnection.org/ocs/v2.php/apps/tables/api/2/tables/9/rows")
|
||||
.basic_auth("chris", Some("2VHeGxeC^Zf9KqFK^G@Pt!zu2q^6@b"))
|
||||
.header("OCS-APIRequest", "true")
|
||||
.header("Content-Type", "application/json")
|
||||
.json(&json)
|
||||
.send()
|
||||
.await?;
|
||||
dbg!(&res);
|
||||
if res.status().is_success() {
|
||||
let res = res.text().await.unwrap();
|
||||
dbg!(res);
|
||||
Ok(())
|
||||
} else {
|
||||
Err(eyre!(
|
||||
"Problem in storing data: {:?}",
|
||||
res.error_for_status()
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[post("/api/mt-form")]
|
||||
|
@ -229,22 +307,30 @@ pub async fn mt_form(MultipartForm(form): MultipartForm<MtForm>) -> HttpResponse
|
|||
let mut path = String::from("");
|
||||
let mut file_exists = false;
|
||||
let mut filename = String::from("");
|
||||
if let Some(file) = form.file.file_name {
|
||||
if let Some(ext) = file.rsplit('.').next() {
|
||||
filename = format!("{}.{}", filename_noext, ext);
|
||||
path = format!("./tmp/{}.{}", filename_noext, ext);
|
||||
} else {
|
||||
path = format!("./tmp/{}", file);
|
||||
}
|
||||
info!("saving to {}", path);
|
||||
match form.file.file.persist(&path) {
|
||||
Ok(f) => {
|
||||
if f.metadata().unwrap().len() > 0 {
|
||||
file_exists = true;
|
||||
}
|
||||
info!(?f, "File saved successfully");
|
||||
|
||||
match form.store_form().await {
|
||||
Ok(_) => info!("Successfully sent form to nextcloud!"),
|
||||
Err(e) => error!("There was an erroring sending form to nextcloud: {}", e),
|
||||
}
|
||||
|
||||
if let Some(file) = form.file {
|
||||
if let Some(file_str) = file.file_name {
|
||||
if let Some(ext) = file_str.rsplit('.').next() {
|
||||
filename = format!("{}.{}", filename_noext, ext);
|
||||
path = format!("./tmp/{}.{}", filename_noext, ext);
|
||||
} else {
|
||||
path = format!("./tmp/{}", file_str);
|
||||
}
|
||||
info!("saving to {}", path);
|
||||
match file.file.persist(&path) {
|
||||
Ok(f) => {
|
||||
if f.metadata().unwrap().len() > 0 {
|
||||
file_exists = true;
|
||||
}
|
||||
info!(?f, "File saved successfully");
|
||||
}
|
||||
Err(e) => info!("{:?}: Probably a missing image", e),
|
||||
}
|
||||
Err(e) => info!("{:?}: Probably a missing image", e),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -278,3 +364,68 @@ pub async fn mt_form(MultipartForm(form): MultipartForm<MtForm>) -> HttpResponse
|
|||
|
||||
HttpResponse::Ok().body("thankyou")
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use actix_web::test;
|
||||
use pretty_assertions::assert_eq;
|
||||
use sqlx::Connection;
|
||||
use tracing::debug;
|
||||
|
||||
use super::*;
|
||||
|
||||
fn form() -> MtForm {
|
||||
MtForm {
|
||||
first_name: Text(String::from("Frodo")),
|
||||
last_name: Text(String::from("Braggins")),
|
||||
parent_first_name: Text(String::from("Bilbo")),
|
||||
parent_last_name: Text(String::from("Braggins")),
|
||||
birthdate: Text(String::from("1845-09-12")),
|
||||
gender: Text(String::from("male")),
|
||||
street: Text(String::from("1234 Bag End")),
|
||||
city: Text(String::from("The Shire")),
|
||||
state: Text(String::from("Hobbiton")),
|
||||
zip: Text(88888),
|
||||
cellphone: Text(String::from("7868889797")),
|
||||
parentphone: Text(String::from("1234567898")),
|
||||
email: Text(String::from("frodo@hobbits.com")),
|
||||
parentemail: Text(String::from("bilbo@hobbits.com")),
|
||||
school: Text(String::from("Shire High")),
|
||||
grade: Text(String::from("junior")),
|
||||
pastor_first_name: Text(String::from("Gandalf")),
|
||||
pastor_last_name: Text(String::from("The White")),
|
||||
church_attendance: Text(String::from("often")),
|
||||
tfc_group: Text(String::from("Northern Valley")),
|
||||
shirt: Text(String::from("medium")),
|
||||
trip: Text(String::from("Mordor")),
|
||||
trip_notes: Text(String::from("If it must happen, I'll do it.")),
|
||||
relationship_with_jesus: Text(String::from("Cool beans")),
|
||||
testimony: Text(String::from("Nephew of Bilbo Braggins")),
|
||||
involvement_with_group: Text(String::from("Good friends with Gandalf")),
|
||||
reasons: Text(String::from("Want an adventure")),
|
||||
strengths: Text(String::from("Willing, brave, small, and curious")),
|
||||
weaknesses: Text(String::from("Not strong, or good with weapons")),
|
||||
previous_trip_info: Text(String::from("The edge of Hob Hill")),
|
||||
attitude: Text(String::from("Willing")),
|
||||
relevant_notes: Text(String::from("Willing to take the ring")),
|
||||
final_agreement: Text(String::from("yes")),
|
||||
registration: Text(String::from("later")),
|
||||
file: None,
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
async fn test_nc_post() {
|
||||
let form = form();
|
||||
assert!(!form.first_name.is_empty());
|
||||
dbg!(&form);
|
||||
// let conn = SqliteConnection::connect("file://./data.db")
|
||||
// .await
|
||||
// .expect("Couldn't connect sqlite db");
|
||||
let res = form.store_form().await;
|
||||
match res {
|
||||
Ok(_) => assert!(true, "passed storing test"),
|
||||
Err(e) => assert!(false, "Failed storing test: {}", e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
11
src/main.rs
11
src/main.rs
|
@ -5,7 +5,7 @@ use actix_files::Files;
|
|||
use actix_multipart::form::tempfile::TempFileConfig;
|
||||
use actix_web::body::MessageBody;
|
||||
use actix_web::dev::{ServiceRequest, ServiceResponse};
|
||||
use actix_web::{App, Error, HttpServer};
|
||||
use actix_web::{web, App, Error, HttpServer};
|
||||
use api::camp_form::camp_form;
|
||||
use api::church_form::church_form;
|
||||
use api::health_form::health_form;
|
||||
|
@ -15,6 +15,7 @@ use api::parent_form::parent_form;
|
|||
use api::teacher_form::teacher_form;
|
||||
use color_eyre::eyre::Context;
|
||||
use color_eyre::Result;
|
||||
use sqlx::{Connection, SqliteConnection};
|
||||
use tracing::level_filters::LevelFilter;
|
||||
use tracing::{info, Span};
|
||||
use tracing_actix_web::{RootSpanBuilder, TracingLogger};
|
||||
|
@ -76,8 +77,14 @@ async fn main() -> std::io::Result<()> {
|
|||
|
||||
info!("starting HTTP server at http://localhost:4242");
|
||||
|
||||
HttpServer::new(|| {
|
||||
let conn = SqliteConnection::connect("file://./data.db")
|
||||
.await
|
||||
.expect("Couldn't connect sqlite db");
|
||||
let data = web::Data::new(conn);
|
||||
|
||||
HttpServer::new(move || {
|
||||
App::new()
|
||||
.app_data(data.clone())
|
||||
.wrap(TracingLogger::<DomainRootSpanBuilder>::new())
|
||||
.app_data(TempFileConfig::default().directory("./tmp"))
|
||||
.service(mt_form)
|
||||
|
|
Loading…
Reference in a new issue