Sign up method.
[recipes.git] / backend / src / main.rs
1 use std::fs::File;
2 use std::sync::Mutex;
3
4 use actix_files as fs;
5 use actix_web::{get, web, Responder, middleware, App, HttpServer, HttpRequest};
6 use askama_actix::Template;
7 use chrono::prelude::*;
8 use clap::Parser;
9 use ron::de::from_reader;
10 use serde::Deserialize;
11
12 mod consts;
13 mod db;
14 mod hash;
15 mod model;
16
17 #[derive(Template)]
18 #[template(path = "home.html")]
19 struct HomeTemplate {
20 recipes: Vec<(i32, String)>,
21 }
22
23 #[derive(Template)]
24 #[template(path = "view_recipe.html")]
25 struct ViewRecipeTemplate {
26 recipes: Vec<(i32, String)>,
27 current_recipe: model::Recipe,
28 }
29
30 #[derive(Deserialize)]
31 pub struct Request {
32 m: Option<String>
33 }
34
35 #[get("/")]
36 async fn home_page(req: HttpRequest, connection: web::Data<db::Connection>) -> impl Responder {
37 HomeTemplate { recipes: connection.get_all_recipe_titles().unwrap() } // TODO: unwrap.
38 }
39
40 #[get("/recipe/view/{id}")]
41 async fn view_recipe(req: HttpRequest, path: web::Path<(i32,)>, connection: web::Data<db::Connection>) -> impl Responder {
42 ViewRecipeTemplate {
43 recipes: connection.get_all_recipe_titles().unwrap(),
44 current_recipe: connection.get_recipe(path.0).unwrap(),
45 }
46 }
47
48 #[derive(Debug, Deserialize)]
49 struct Config {
50 port: u16
51 }
52
53 fn get_exe_name() -> String {
54 let first_arg = std::env::args().nth(0).unwrap();
55 let sep: &[_] = &['\\', '/'];
56 first_arg[first_arg.rfind(sep).unwrap()+1..].to_string()
57 }
58
59 #[actix_web::main]
60 async fn main() -> std::io::Result<()> {
61 if process_args() { return Ok(()) }
62
63 std::env::set_var("RUST_LOG", "actix_web=debug");
64 env_logger::init();
65
66 println!("Starting Recipes as web server...");
67
68 let config: Config = {
69 let f = File::open(consts::FILE_CONF).unwrap_or_else(|_| panic!("Failed to open configuration file {}", consts::FILE_CONF));
70 match from_reader(f) {
71 Ok(c) => c,
72 Err(e) => panic!("Failed to load config: {}", e)
73 }
74 };
75
76 println!("Configuration: {:?}", config);
77
78 let db_connection = web::Data::new(db::Connection::new().unwrap()); // TODO: remove unwrap.
79
80 std::env::set_var("RUST_LOG", "actix_web=info");
81
82 let mut server =
83 HttpServer::new(
84 move || {
85 App::new()
86 .wrap(middleware::Logger::default())
87 .wrap(middleware::Compress::default())
88 .app_data(db_connection.clone())
89 .service(home_page)
90 .service(view_recipe)
91 .service(fs::Files::new("/static", "static").show_files_listing())
92 }
93 );
94
95 server = server.bind(&format!("0.0.0.0:{}", config.port)).unwrap();
96
97 server.run().await
98 }
99
100 #[derive(Parser, Debug)]
101 struct Args {
102 #[arg(long)]
103 dbtest: bool
104 }
105
106 fn process_args() -> bool {
107 let args = Args::parse();
108
109 if args.dbtest {
110 match db::Connection::new() {
111 Ok(con) => {
112 if let Err(error) = con.execute_file("sql/data_test.sql") {
113 println!("Error: {:?}", error);
114 }
115 // Set the creation datetime to 'now'.
116 con.execute_sql("UPDATE [User] SET [creation_datetime] = ?1 WHERE [email] = 'paul@test.org'", [Utc::now()]).unwrap();
117 },
118 Err(error) => {
119 println!("Error: {:?}", error)
120 },
121 }
122
123 return true;
124 }
125
126 false
127
128 /*
129
130
131 fn print_usage() {
132 println!("Usage:");
133 println!(" {} [--help] [--test]", get_exe_name());
134 }
135
136 let args: Vec<String> = args().collect();
137
138 if args.iter().any(|arg| arg == "--help") {
139 print_usage();
140 return true
141 } else if args.iter().any(|arg| arg == "--test") {
142 match db::Connection::new() {
143 Ok(_) => (),
144 Err(error) => println!("Error: {:?}", error)
145 }
146 return true
147 }
148 false
149 */
150 }