2024-02-12 14:04:03 +01:00
|
|
|
use std::net::SocketAddr;
|
|
|
|
|
use std::sync::Arc;
|
|
|
|
|
|
|
|
|
|
use sqlx::SqlitePool;
|
|
|
|
|
|
|
|
|
|
use axum::{
|
|
|
|
|
extract::FromRef,
|
|
|
|
|
routing::{get, post},
|
|
|
|
|
Router,
|
|
|
|
|
};
|
|
|
|
|
use hyper::StatusCode;
|
2024-02-19 23:51:18 +01:00
|
|
|
use tera::Tera;
|
2024-02-12 14:04:03 +01:00
|
|
|
|
|
|
|
|
mod routes;
|
|
|
|
|
mod users;
|
|
|
|
|
|
|
|
|
|
const DB_URL: &str = "sqlite://sqlite.db";
|
|
|
|
|
|
|
|
|
|
#[tokio::main]
|
|
|
|
|
async fn main() {
|
|
|
|
|
let db = accounters::create_db(DB_URL).await.unwrap();
|
|
|
|
|
|
2024-02-19 23:51:18 +01:00
|
|
|
let mut tmpls = Tera::new("templates/*").unwrap();
|
|
|
|
|
tmpls.autoescape_on(vec!["html"]);
|
|
|
|
|
|
|
|
|
|
let state = AppState {
|
|
|
|
|
db: Arc::new(db),
|
|
|
|
|
tmpls: Arc::new(tmpls),
|
|
|
|
|
};
|
2024-02-12 14:04:03 +01:00
|
|
|
|
2024-05-21 22:59:26 +02:00
|
|
|
let exec_id: u32 = rand::random();
|
|
|
|
|
|
2024-02-12 14:04:03 +01:00
|
|
|
let app = Router::new()
|
2024-02-19 23:51:18 +01:00
|
|
|
.nest(
|
|
|
|
|
"/",
|
|
|
|
|
Router::new()
|
|
|
|
|
.route("/", get(routes::ui::index))
|
2024-05-22 19:11:54 +02:00
|
|
|
.route("/accounts/id/:id", get(routes::ui::account::show))
|
2024-03-18 23:04:48 +01:00
|
|
|
.route(
|
|
|
|
|
"/accounts/id/:id/transactions/add",
|
|
|
|
|
get(routes::ui::account::add_transactions_view),
|
|
|
|
|
)
|
|
|
|
|
.route(
|
|
|
|
|
"/accounts/id/:id/transactions/add",
|
|
|
|
|
post(routes::ui::account::add_transactions_action),
|
|
|
|
|
)
|
2024-05-22 19:11:54 +02:00
|
|
|
.route(
|
|
|
|
|
"/accounts/id/:id/transactions",
|
|
|
|
|
get(routes::ui::account::list_transactions),
|
|
|
|
|
)
|
2024-04-24 23:20:37 +02:00
|
|
|
.route("/transaction/:id", get(routes::ui::transaction::view))
|
|
|
|
|
.route("/transaction/:id", post(routes::ui::transaction::update))
|
2024-03-20 20:49:22 +01:00
|
|
|
.route(
|
|
|
|
|
"/classifiers",
|
|
|
|
|
get(routes::ui::classifier::view_classifiers),
|
|
|
|
|
)
|
|
|
|
|
.route(
|
|
|
|
|
"/classifiers/new_rule",
|
|
|
|
|
get(routes::ui::classifier::rules_new_view),
|
|
|
|
|
)
|
|
|
|
|
.route(
|
|
|
|
|
"/classifiers/new_rule",
|
|
|
|
|
post(routes::ui::classifier::rules_new_action),
|
|
|
|
|
)
|
|
|
|
|
.route(
|
|
|
|
|
"/classifiers/new_category",
|
|
|
|
|
get(routes::ui::classifier::category_new_view),
|
|
|
|
|
)
|
|
|
|
|
.route(
|
|
|
|
|
"/classifiers/new_category",
|
|
|
|
|
post(routes::ui::classifier::category_new_action),
|
|
|
|
|
)
|
2024-02-19 23:51:18 +01:00
|
|
|
.nest(
|
|
|
|
|
"/static",
|
2024-03-18 23:04:48 +01:00
|
|
|
Router::new()
|
|
|
|
|
.route("/styles.css", get(routes::static_routes::styles))
|
|
|
|
|
.route("/csv.js", get(routes::static_routes::csv)),
|
2024-05-21 22:59:26 +02:00
|
|
|
)
|
|
|
|
|
.route(
|
|
|
|
|
"/execution",
|
|
|
|
|
get(move || async move { format!("{exec_id}") }),
|
2024-02-19 23:51:18 +01:00
|
|
|
),
|
|
|
|
|
)
|
2024-02-12 14:04:03 +01:00
|
|
|
.nest(
|
|
|
|
|
"/api/v1",
|
|
|
|
|
Router::new()
|
2024-02-19 23:51:18 +01:00
|
|
|
.route("/user", post(routes::api::create_user))
|
|
|
|
|
.route("/login", post(routes::api::login))
|
|
|
|
|
.route("/accounts", post(routes::api::accounts::account_create))
|
|
|
|
|
.route("/accounts", get(routes::api::accounts::account_list))
|
|
|
|
|
.route("/accounts/id/:id", get(routes::api::accounts::account_get))
|
2024-02-12 14:04:03 +01:00
|
|
|
.route(
|
|
|
|
|
"/accounts/id/:id/transaction",
|
2024-02-19 23:51:18 +01:00
|
|
|
post(routes::api::transactions::create),
|
2024-02-12 14:04:03 +01:00
|
|
|
)
|
|
|
|
|
.route(
|
|
|
|
|
"/accounts/id/:id/transaction",
|
2024-02-19 23:51:18 +01:00
|
|
|
get(routes::api::transactions::list),
|
2024-02-12 14:04:03 +01:00
|
|
|
)
|
|
|
|
|
.route(
|
|
|
|
|
"/accounts/id/:id/recategorize",
|
2024-02-19 23:51:18 +01:00
|
|
|
post(routes::api::accounts::recategorize),
|
2024-02-12 14:04:03 +01:00
|
|
|
)
|
2024-02-19 23:51:18 +01:00
|
|
|
.route("/categories", post(routes::api::categories::create))
|
|
|
|
|
.route("/categories", get(routes::api::categories::list))
|
|
|
|
|
.route("/rules", post(routes::api::rules::create))
|
|
|
|
|
.route("/rules", get(routes::api::rules::list)),
|
2024-02-12 14:04:03 +01:00
|
|
|
)
|
|
|
|
|
.with_state(state);
|
|
|
|
|
|
|
|
|
|
let addr = SocketAddr::from(([0, 0, 0, 0], 3000));
|
2024-05-22 19:11:25 +02:00
|
|
|
let server = axum::Server::bind(&addr).serve(app.into_make_service());
|
|
|
|
|
|
|
|
|
|
let wv_task = tokio::task::spawn_blocking(|| {
|
|
|
|
|
web_view::builder()
|
|
|
|
|
.title("Test")
|
|
|
|
|
.content(web_view::Content::Url("http://localhost:3000"))
|
|
|
|
|
.user_data(())
|
|
|
|
|
.invoke_handler(|_wv, _arg| Ok(()))
|
|
|
|
|
.run()
|
|
|
|
|
.unwrap();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
tokio::select! {
|
|
|
|
|
_ = wv_task => {
|
|
|
|
|
println!("WebView finished");
|
|
|
|
|
}
|
|
|
|
|
e = server => {
|
|
|
|
|
println!("Axum finished with result {e:?}");
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-02-12 14:04:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Clone)]
|
|
|
|
|
pub struct AppState {
|
|
|
|
|
db: Arc<SqlitePool>,
|
2024-02-19 23:51:18 +01:00
|
|
|
tmpls: Arc<Tera>,
|
2024-02-12 14:04:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl FromRef<AppState> for Arc<SqlitePool> {
|
|
|
|
|
fn from_ref(state: &AppState) -> Arc<SqlitePool> {
|
|
|
|
|
state.db.clone()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-02-19 23:51:18 +01:00
|
|
|
impl FromRef<AppState> for Arc<Tera> {
|
|
|
|
|
fn from_ref(state: &AppState) -> Arc<Tera> {
|
|
|
|
|
state.tmpls.clone()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-02-12 14:04:03 +01:00
|
|
|
async fn index() -> (StatusCode, String) {
|
|
|
|
|
(StatusCode::OK, String::from("Hello, World!"))
|
|
|
|
|
}
|