diff options
Diffstat (limited to 'rust/app/src')
| -rw-r--r-- | rust/app/src/databases.rs | 11 | ||||
| -rw-r--r-- | rust/app/src/main.rs | 51 | ||||
| -rw-r--r-- | rust/app/src/routes/account.rs | 50 | ||||
| -rw-r--r-- | rust/app/src/routes/balance.rs | 17 | ||||
| -rw-r--r-- | rust/app/src/routes/budget.rs | 20 | ||||
| -rw-r--r-- | rust/app/src/routes/budget_update.rs | 20 | ||||
| -rw-r--r-- | rust/app/src/routes/category.rs | 18 | ||||
| -rw-r--r-- | rust/app/src/routes/mod.rs | 5 |
8 files changed, 192 insertions, 0 deletions
diff --git a/rust/app/src/databases.rs b/rust/app/src/databases.rs new file mode 100644 index 0000000..7202e78 --- /dev/null +++ b/rust/app/src/databases.rs @@ -0,0 +1,11 @@ +use rocket_sync_db_pools::{database, diesel}; + +cfg_if::cfg_if! { + if #[cfg(test)] { + #[database("user_data.test")] + pub struct UserDataDb(diesel::SqliteConnection); + } else { + #[database("user_data")] + pub struct UserDataDb(diesel::SqliteConnection); + } +} diff --git a/rust/app/src/main.rs b/rust/app/src/main.rs new file mode 100644 index 0000000..dca6096 --- /dev/null +++ b/rust/app/src/main.rs @@ -0,0 +1,51 @@ +use budgeting_app_core::MIGRATIONS; +use diesel::SqliteConnection; +use diesel_migrations::MigrationHarness; +use rocket::fairing::AdHoc; +use rocket::http::ContentType; +use rocket::{launch, routes, Build, Rocket}; + +use crate::databases::UserDataDb; + +pub mod databases; +pub mod routes; + +fn run_database_migrations(connection: &mut SqliteConnection) { + connection + .run_pending_migrations(MIGRATIONS) + .expect("Error running database migrations"); +} + +#[launch] +async fn rocket() -> Rocket<Build> { + rocket::build() + .attach(UserDataDb::fairing()) + .attach(AdHoc::on_liftoff("Database Migration", |rocket| { + Box::pin(async move { + let user_data_db = UserDataDb::get_one(rocket).await.expect( + "Failed to get connection to user data database in order to run migrations", + ); + user_data_db.run(run_database_migrations).await; + }) + })) + .attach(AdHoc::on_response("Add CORS headers", |_req, res| { + Box::pin(async move { + res.set_header(ContentType::JSON); + res.set_header(rocket::http::Header::new( + "Access-Control-Allow-Origin", + "http://localhost:5173", + )); + }) + })) + .mount( + "/", + routes![ + routes::account::get_all_accounts, + routes::account::create_account, + routes::balance::get_all_category_balances, + routes::budget::get_current_category_budget_per_category, + routes::budget_update::get_all_budget_updates, + routes::category::get_all_categories, + ], + ) +} diff --git a/rust/app/src/routes/account.rs b/rust/app/src/routes/account.rs new file mode 100644 index 0000000..96f1f38 --- /dev/null +++ b/rust/app/src/routes/account.rs @@ -0,0 +1,50 @@ +use budgeting_app_core::{ + models::account::Account, + queries::accounts::{get_all_accounts as get_all_accounts_query, insert_accounts}, +}; +use rocket::http::Status; +use rocket::serde::json::Json; +use rocket::{get, post, Responder}; + +use crate::databases::UserDataDb; + +#[get("/account")] +pub async fn get_all_accounts(user_data_db: UserDataDb) -> Result<Json<Vec<Account>>, (Status, String)> { + user_data_db + .run(get_all_accounts_query) + .await + .map(Json) + .map_err(|err| (Status::InternalServerError, err.to_string())) +} + +#[derive(Responder)] +pub enum CreateAccountResponder { + #[response(status = 500, content_type = "text")] + InternalServerError(String), + + #[response(status = 202, content_type = "json")] + Created(Json<Account>), + + #[response(status = 400, content_type = "text")] + BadRequest(String), +} + +#[post("/account", data = "<account>", format = "json")] +pub async fn create_account( + account: Json<Account>, + user_data_db: UserDataDb, +) -> CreateAccountResponder { + let account = account.into_inner(); + let accounts_vec = vec![account.clone()]; + + let num_rows_inserted = user_data_db + .run(move |connection| insert_accounts(&accounts_vec, connection)) + .await; + + match num_rows_inserted { + Ok(_) => CreateAccountResponder::Created(Json(account)), + Err(err) => CreateAccountResponder::InternalServerError(format!( + "Error creating account: {err}" + )), + } +} diff --git a/rust/app/src/routes/balance.rs b/rust/app/src/routes/balance.rs new file mode 100644 index 0000000..21adb3b --- /dev/null +++ b/rust/app/src/routes/balance.rs @@ -0,0 +1,17 @@ +use budgeting_app_core::{ + models::category_balance::CategoryBalance, + queries::categories::get_all_category_balances as get_all_category_balances_query, +}; +use rocket::{get, http::Status, serde::json::Json}; + +use crate::databases::UserDataDb; +#[get("/balance/category")] +pub async fn get_all_category_balances( + user_data_db: UserDataDb, +) -> Result<Json<Vec<CategoryBalance>>, Status> { + user_data_db + .run(get_all_category_balances_query) + .await + .map(Json) + .map_err(|_| Status { code: 500 }) +} diff --git a/rust/app/src/routes/budget.rs b/rust/app/src/routes/budget.rs new file mode 100644 index 0000000..dc0802a --- /dev/null +++ b/rust/app/src/routes/budget.rs @@ -0,0 +1,20 @@ +use budgeting_app_core::{ + models::category_budget::CategoryBudget, + queries::categories::get_most_recent_category_budget_per_category_id as get_most_recent_category_budget_per_category_id_query, +}; +use rocket::get; +use rocket::http::Status; +use rocket::serde::json::Json; + +use crate::databases::UserDataDb; + +#[get("/budget/category?current")] +pub async fn get_current_category_budget_per_category( + user_data_db: UserDataDb, +) -> Result<Json<Vec<CategoryBudget>>, Status> { + user_data_db + .run(get_most_recent_category_budget_per_category_id_query) + .await + .map(Json) + .map_err(|_| Status { code: 500 }) +} diff --git a/rust/app/src/routes/budget_update.rs b/rust/app/src/routes/budget_update.rs new file mode 100644 index 0000000..86dda9f --- /dev/null +++ b/rust/app/src/routes/budget_update.rs @@ -0,0 +1,20 @@ +use budgeting_app_core::{ + models::budget_update::BudgetUpdate, + queries::budget_updates::get_all_budget_updates as get_all_budget_updates_query, +}; +use rocket::get; +use rocket::http::Status; +use rocket::serde::json::Json; + +use crate::databases::UserDataDb; + +#[get("/budget-update")] +pub async fn get_all_budget_updates( + user_data_db: UserDataDb, +) -> Result<Json<Vec<BudgetUpdate>>, Status> { + user_data_db + .run(get_all_budget_updates_query) + .await + .map(Json) + .map_err(|_| Status { code: 500 }) +} diff --git a/rust/app/src/routes/category.rs b/rust/app/src/routes/category.rs new file mode 100644 index 0000000..ca021fc --- /dev/null +++ b/rust/app/src/routes/category.rs @@ -0,0 +1,18 @@ +use budgeting_app_core::{ + models::category::Category, + queries::categories::get_all_categories as get_all_categories_query, +}; +use rocket::get; +use rocket::http::Status; +use rocket::serde::json::Json; + +use crate::databases::UserDataDb; + +#[get("/category")] +pub async fn get_all_categories(user_data_db: UserDataDb) -> Result<Json<Vec<Category>>, Status> { + user_data_db + .run(get_all_categories_query) + .await + .map(Json) + .map_err(|_| Status { code: 500 }) +} diff --git a/rust/app/src/routes/mod.rs b/rust/app/src/routes/mod.rs new file mode 100644 index 0000000..bf0ab4a --- /dev/null +++ b/rust/app/src/routes/mod.rs @@ -0,0 +1,5 @@ +pub mod account; +pub mod balance; +pub mod budget; +pub mod budget_update; +pub mod category; |
