-use std::io::prelude::*;
-use std::{fs::File, env::args};
+use std::path::Path;
use actix_files as fs;
-use actix_web::{web, middleware, App, HttpServer, HttpResponse, Result, web::Query, middleware::Logger};
+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 env_logger;
-
-use itertools::Itertools;
+use data::db;
+mod config;
mod consts;
-mod db;
-
-#[derive(Template)]
-#[template(path = "main.html")]
-struct MainTemplate<'a> {
- test: &'a str,
-}
+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(());
+ }
-#[derive(Deserialize)]
-pub struct Request {
- m: Option<String>
-}
+ std::env::set_var("RUST_LOG", "info,actix_web=info");
+ env_logger::init();
-fn main_page(query: Query<Request>) -> Result<HttpResponse> {
+ println!("Starting Recipes as web server...");
- let main_template = MainTemplate { test: &"* test *" };
+ let config = web::Data::new(config::load());
+ let port = config.as_ref().port;
- let s = main_template.render().unwrap();
- Ok(HttpResponse::Ok().content_type("text/html").body(s))
-}
+ println!("Configuration: {:?}", config);
-#[derive(Debug, Deserialize)]
-struct Config {
- port: u16
+ 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
}
-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()
+#[derive(Parser, Debug)]
+struct Args {
+ /// Will clear the database and insert some test data. (A backup is made first).
+ #[arg(long)]
+ dbtest: bool,
}
-fn main() -> std::io::Result<()> {
- if process_args() { return Ok(()) }
-
- println!("Starting RUP 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)
+fn process_args() -> bool {
+ 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));
}
- };
-
- println!("Configuration: {:?}", config);
- // let database_connection = db::create_or_update();
-
- std::env::set_var("RUST_LOG", "actix_web=info");
- env_logger::init();
-
- let mut listenfd = ListenFd::from_env();
- let mut server =
- HttpServer::new(
- || {
- App::new()
- .wrap(middleware::Compress::default())
- .wrap(Logger::default())
- .wrap(Logger::new("%a %{User-Agent}i"))
- .service(web::resource("/").to(main_page))
- .service(fs::Files::new("/static", "static").show_files_listing())
+ match db::Connection::new() {
+ 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();
}
- );
-
- 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()
- };
-
- server.run()
-}
-
-fn process_args() -> bool {
- fn print_usage() {
- println!("Usage:");
- println!(" {} [--help] [--test]", get_exe_name());
- }
-
- let args: Vec<String> = args().collect();
+ Err(error) => {
+ eprintln!("{}", error);
+ }
+ }
- if args.iter().any(|arg| arg == "--help") {
- print_usage();
- return true
- } else if args.iter().any(|arg| arg == "--test") {
- let database_connection = db::create_or_update();
- return true
+ return true;
}
false