Line data Source code
1 : use axum::Router;
2 : use axum::extract::FromRef;
3 : use axum::routing::{get, post};
4 : use axum_extra::extract::cookie::Key;
5 : use minijinja::{Environment, path_loader};
6 : use rusqlite::Connection;
7 : use std::path::{Path, PathBuf};
8 : use std::sync::{Arc, Mutex};
9 : use tower_http::services::ServeDir;
10 : use tower_http::trace::TraceLayer;
11 :
12 : mod article;
13 : pub mod db;
14 : // TODO: Revisit module name. It holds the code to work with the media files we
15 : // store in SQLite. files is a bit too generic a name, media a bit too
16 : // specific. 🤔
17 : mod files;
18 : mod handler;
19 : mod markdown_filter;
20 : mod responders;
21 : mod session;
22 : pub mod user;
23 :
24 : #[derive(Clone)]
25 : pub(crate) struct WebContext {
26 : templates: Environment<'static>,
27 : upload_dir: PathBuf,
28 : db: Arc<Mutex<Connection>>,
29 : key: Key,
30 : }
31 :
32 : impl FromRef<WebContext> for Key {
33 11 : fn from_ref(state: &WebContext) -> Self {
34 11 : state.key.clone()
35 11 : }
36 : }
37 :
38 : impl FromRef<WebContext> for Arc<Mutex<Connection>> {
39 3 : fn from_ref(state: &WebContext) -> Self {
40 3 : state.db.clone()
41 3 : }
42 : }
43 :
44 9 : pub fn new<P: AsRef<Path>>(
45 9 : db: Arc<Mutex<Connection>>,
46 9 : template_dir: P,
47 9 : asset_dir: P,
48 9 : upload_dir: P,
49 9 : key: Key,
50 9 : ) -> Router {
51 9 : let source = path_loader(template_dir);
52 9 : let mut env = Environment::new();
53 9 : env.set_loader(source);
54 9 : env.add_filter("tomarkdown", markdown_filter::to_markdown);
55 9 : let ctx = WebContext { templates: env, upload_dir: upload_dir.as_ref().to_path_buf(), db, key };
56 9 : Router::new()
57 9 : .route("/", get(handler::index))
58 9 : .route("/sign-in/", get(handler::new_sign_in))
59 9 : .route("/sign-in/", post(handler::sign_in))
60 9 : .route("/article/new", get(handler::new_article))
61 9 : .route("/article/", post(handler::article_create))
62 9 : .route("/article/{page_id}/", get(handler::article_show))
63 9 : .route("/article/{page_id}/edit/", get(handler::article_edit))
64 9 : .route("/article/{page_id}/edit/", post(handler::article_update))
65 9 : .route("/upload/", post(handler::upload))
66 9 : .route("/media/{file_id}", get(handler::media_show))
67 9 : .nest_service("/public", ServeDir::new(asset_dir))
68 9 : .with_state(ctx)
69 9 : .layer(TraceLayer::new_for_http())
70 9 : }
|