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