diff --git a/src/entities/bal.rs b/src/entities/bal.rs index 9e7516c..08ceb32 100644 --- a/src/entities/bal.rs +++ b/src/entities/bal.rs @@ -15,6 +15,12 @@ pub struct Model { pub enum Relation { #[sea_orm(has_many = "super::book_instance::Entity")] BookInstance, + #[sea_orm( + belongs_to = "super::user::Entity", + from = "Column::Id", + to = "super::user::Column::CurrentBalId" + )] + User, } impl Related for Entity { diff --git a/src/entities/user.rs b/src/entities/user.rs index f0b2ad0..25652fc 100644 --- a/src/entities/user.rs +++ b/src/entities/user.rs @@ -10,6 +10,7 @@ pub struct Model { #[sea_orm(unique)] pub username: String, pub hashed_password: String, + pub current_bal_id: Option, } impl Model { diff --git a/src/main.rs b/src/main.rs index dd7b8c1..4229796 100644 --- a/src/main.rs +++ b/src/main.rs @@ -195,6 +195,8 @@ async fn run_server(db: Arc, port: u16) { .routes(routes!(routes::bal::create_bal)) .routes(routes!(routes::bal::update_bal)) .routes(routes!(routes::bal::get_bals)) + .routes(routes!(routes::bal::get_current_bal)) + .routes(routes!(routes::bal::set_current_bal)) // Authentication .route_layer(middleware::from_fn_with_state(shared_state.clone(), routes::auth::auth_middleware)) .routes(routes!(routes::auth::auth)) diff --git a/src/routes/bal.rs b/src/routes/bal.rs index ceb9b69..c59402c 100644 --- a/src/routes/bal.rs +++ b/src/routes/bal.rs @@ -2,11 +2,11 @@ use std::sync::Arc; use axum::{extract::{Path, State}, Json}; use reqwest::{StatusCode}; -use sea_orm::{ActiveModelTrait, ActiveValue::{NotSet, Set}, ColumnTrait, EntityTrait, QueryFilter, TryIntoModel}; +use sea_orm::{ActiveModelTrait, ActiveValue::{NotSet, Set}, ColumnTrait, EntityTrait, IntoActiveModel, QueryFilter, TryIntoModel}; use serde::{Deserialize, Serialize}; use utoipa::IntoParams; -use crate::{entities::{bal, prelude::*}, routes::auth::Claims, AppState}; +use crate::{entities::{bal, prelude::*, user}, routes::auth::Claims, utils::auth::user_is_bal_owner, AppState}; #[derive(IntoParams)] @@ -159,3 +159,68 @@ pub async fn get_bals( (StatusCode::NOT_FOUND, Json(vec![])) } } + +#[axum::debug_handler] +#[utoipa::path( + get, + path = "/bal/current", + security(("jwt" = [])), + responses( + (status = OK, body = bal::Model, description = "Your current active BAL"), + (status = NOT_FOUND, description = "You don't have a currently active BAL"), + ), + summary = "Get your current active BAL", + description = "Get your current active BAL", + tag = "bal-api", +)] +pub async fn get_current_bal( + State(state): State>, + claims: Claims, +) -> (StatusCode, Json>) { + if let Ok(Some(user)) = User::find_by_id(claims.user_id).one(state.db_conn.as_ref()).await { + if let Some(bal_id) = user.current_bal_id { + (StatusCode::OK, Json(Some(Bal::find_by_id(bal_id).one(state.db_conn.as_ref()).await.unwrap().unwrap()))) + } else { + (StatusCode::NOT_FOUND, Json(None)) + } + } else { + (StatusCode::INTERNAL_SERVER_ERROR, Json(None)) + } +} + +#[derive(Deserialize, utoipa::ToSchema)] +pub struct BalIdParams{ + id: u32, +} + +#[axum::debug_handler] +#[utoipa::path( + post, + path = "/bal/current", + request_body = BalIdParams, + security(("jwt" = [])), + responses( + (status = OK, description = "Successfully set current active BAL"), + (status = UNAUTHORIZED, description = "Tried to set a BAL you don't own as your active BAL"), + ), + summary = "Set your current active BAL", + description = "Set your current active BAL", + tag = "bal-api", +)] +pub async fn set_current_bal( + State(state): State>, + claims: Claims, + Json(payload): Json, +) -> StatusCode { + if !user_is_bal_owner(claims.user_id, payload.id, state.db_conn.as_ref()).await { + return StatusCode::UNAUTHORIZED; + } + if let Ok(Some(user)) = User::find_by_id(claims.user_id).one(state.db_conn.as_ref()).await { + let mut user_active_model: user::ActiveModel = user.into_active_model(); + user_active_model.current_bal_id = Set(Some(payload.id)); + let _ = User::update(user_active_model).exec(state.db_conn.as_ref()).await; + StatusCode::OK + } else { + StatusCode::INTERNAL_SERVER_ERROR + } +} diff --git a/src/utils/cli.rs b/src/utils/cli.rs index 55722a6..2cb8b7e 100644 --- a/src/utils/cli.rs +++ b/src/utils/cli.rs @@ -64,7 +64,8 @@ pub async fn manage_users(db: Arc) { let new_user = user::ActiveModel { id: NotSet, username: Set(username), - hashed_password: Set(hash_password(password)) + hashed_password: Set(hash_password(password)), + current_bal_id: Set(None) }; let res = new_user.insert(db.as_ref()).await.unwrap();