X-Git-Url: http://git.euphorik.ch/?a=blobdiff_plain;f=backend%2Fsrc%2Fmain.rs;h=951fd782ce26bb9e0b9831a988eb74f7e7563f9f;hb=adcf4a5a5d982489a7e91d4988401eb4512839a3;hp=daeed7afe7f280872d1b1c5a6d674bcf960d0f2d;hpb=a080d19cb9076780db9e86325b2ab617886e2a5f;p=recipes.git diff --git a/backend/src/main.rs b/backend/src/main.rs index daeed7a..951fd78 100644 --- a/backend/src/main.rs +++ b/backend/src/main.rs @@ -1,117 +1,114 @@ -use std::io::prelude::*; -use std::{fs::File, env::args}; +use std::path::Path; use actix_files as fs; -use actix_web::{get, web, Responder, middleware, App, HttpServer, HttpResponse, HttpRequest, web::Query}; +use actix_web::{middleware, web, App, HttpServer}; +use chrono::prelude::*; +use clap::Parser; -use askama::Template; -use listenfd::ListenFd; -use ron::de::from_reader; -use serde::Deserialize; - -use itertools::Itertools; +use data::db; +mod config; mod consts; -mod db; - -#[derive(Template)] -#[template(path = "home.html")] -struct HomeTemplate { - recipes: Vec -} - -#[derive(Template)] -#[template(path = "view_recipe.html")] -struct ViewRecipeTemplate { - recipes: Vec, - current_recipe: db::Recipe -} - -#[derive(Deserialize)] -pub struct Request { - m: Option -} - -#[get("/")] -async fn home_page(req: HttpRequest) -> impl Responder { - HomeTemplate { recipes: vec![ db::Recipe { title: String::from("Saumon en croûte feuilletée"), id: 1 }, db::Recipe { title: String::from("Croissant au jambon"), id: 2 } ] } -} - -#[get("/recipe/view/{id}")] -async fn view_page(req: HttpRequest, path: web::Path<(i32,)>) -> impl Responder { - ViewRecipeTemplate { recipes: vec![ db::Recipe { title: String::from("Saumon en croûte feuilletée"), id: 1 }, db::Recipe { title: String::from("Croissant au jambon"), id: 2 } ], current_recipe: db::Recipe { title: String::from("Saumon en croûte feuilletée"), id: 1 } } -} - -#[derive(Debug, Deserialize)] -struct Config { - port: u16 -} - -fn get_exe_name() -> String { - let first_arg = std::env::args().nth(0).unwrap(); - let sep: &[_] = &['\\', '/']; - first_arg[first_arg.rfind(sep).unwrap()+1..].to_string() -} - -#[actix_rt::main] +mod data; +mod email; +mod hash; +mod model; +mod services; +mod user; +mod utils; + +#[actix_web::main] async fn main() -> std::io::Result<()> { - if process_args() { return Ok(()) } + if process_args() { + return Ok(()); + } + + std::env::set_var("RUST_LOG", "info,actix_web=info"); + env_logger::init(); println!("Starting Recipes as web server..."); - let config: Config = { - let f = File::open(consts::FILE_CONF).unwrap_or_else(|_| panic!("Failed to open configuration file {}", consts::FILE_CONF)); - match from_reader(f) { - Ok(c) => c, - Err(e) => panic!("Failed to load config: {}", e) - } - }; + let config = web::Data::new(config::load()); + let port = config.as_ref().port; println!("Configuration: {:?}", config); - // let database_connection = db::create_or_update(); - - std::env::set_var("RUST_LOG", "actix_web=info"); - - let mut listenfd = ListenFd::from_env(); - let mut server = - HttpServer::new( - || { - App::new() - .wrap(middleware::Compress::default()) - .service(home_page) - .service(view_page) - .service(fs::Files::new("/static", "static").show_files_listing()) - } - ); - - server = - if let Some(l) = listenfd.take_tcp_listener(0).unwrap() { - server.listen(l).unwrap() - } else { - server.bind(&format!("0.0.0.0:{}", config.port)).unwrap() - }; + let db_connection = web::Data::new(db::Connection::new().unwrap()); + + let server = HttpServer::new(move || { + App::new() + .wrap(middleware::Logger::default()) + .wrap(middleware::Compress::default()) + .app_data(db_connection.clone()) + .app_data(config.clone()) + .service(services::home_page) + .service(services::sign_up_get) + .service(services::sign_up_post) + .service(services::sign_up_check_email) + .service(services::sign_up_validation) + .service(services::sign_in_get) + .service(services::sign_in_post) + .service(services::sign_out) + .service(services::view_recipe) + .service(services::edit_recipe) + .service(fs::Files::new("/static", "static")) + .default_service(web::to(services::not_found)) + }); + //.workers(1); + + server.bind(&format!("0.0.0.0:{}", port))?.run().await +} - server.run().await +#[derive(Parser, Debug)] +struct Args { + /// Will clear the database and insert some test data. (A backup is made first). + #[arg(long)] + dbtest: bool, } fn process_args() -> bool { - fn print_usage() { - println!("Usage:"); - println!(" {} [--help] [--test]", get_exe_name()); - } - - let args: Vec = args().collect(); + let args = Args::parse(); + + if args.dbtest { + // Make a backup of the database. + let db_path = Path::new(consts::DB_DIRECTORY).join(consts::DB_FILENAME); + if db_path.exists() { + let db_path_bckup = (1..) + .find_map(|n| { + let p = db_path.with_extension(format!("sqlite.bckup{:03}", n)); + if p.exists() { + None + } else { + Some(p) + } + }) + .unwrap(); + std::fs::copy(&db_path, &db_path_bckup).expect(&format!( + "Unable to make backup of {:?} to {:?}", + &db_path, &db_path_bckup + )); + std::fs::remove_file(&db_path) + .expect(&format!("Unable to remove db file: {:?}", &db_path)); + } - if args.iter().any(|arg| arg == "--help") { - print_usage(); - return true - } else if args.iter().any(|arg| arg == "--test") { match db::Connection::new() { - Ok(_) => (), - Err(error) => println!("Error: {:?}", error) + Ok(con) => { + if let Err(error) = con.execute_file("sql/data_test.sql") { + eprintln!("{}", error); + } + // Set the creation datetime to 'now'. + con.execute_sql( + "UPDATE [User] SET [creation_datetime] = ?1 WHERE [email] = 'paul@test.org'", + [Utc::now()], + ) + .unwrap(); + } + Err(error) => { + eprintln!("{}", error); + } } - return true + + return true; } false