From 69c12b2144f69f6316ce637a20ff9e0994c96a02 Mon Sep 17 00:00:00 2001 From: dal Date: Mon, 21 Apr 2025 17:25:38 -0600 Subject: [PATCH] 402 error --- api/libs/database/src/models.rs | 1 + api/libs/database/src/schema.rs | 1 + .../post_organization_handler.rs | 1 + api/libs/middleware/src/auth.rs | 54 +++++++++++++++++-- api/libs/middleware/src/error.rs | 33 +++++++++++- .../down.sql | 4 ++ .../up.sql | 3 ++ .../src/routes/rest/routes/users/get_user.rs | 1 + api/server/src/routes/ws/ws_utils.rs | 1 + 9 files changed, 94 insertions(+), 5 deletions(-) create mode 100644 api/migrations/2025-04-21-231239_add_payment_required_to_organizations/down.sql create mode 100644 api/migrations/2025-04-21-231239_add_payment_required_to_organizations/up.sql diff --git a/api/libs/database/src/models.rs b/api/libs/database/src/models.rs index 1aa358ca4..4be923736 100644 --- a/api/libs/database/src/models.rs +++ b/api/libs/database/src/models.rs @@ -338,6 +338,7 @@ pub struct Organization { pub created_at: DateTime, pub updated_at: DateTime, pub deleted_at: Option>, + pub payment_required: bool, } #[derive( diff --git a/api/libs/database/src/schema.rs b/api/libs/database/src/schema.rs index a07133a7f..58df68221 100644 --- a/api/libs/database/src/schema.rs +++ b/api/libs/database/src/schema.rs @@ -433,6 +433,7 @@ diesel::table! { created_at -> Timestamptz, updated_at -> Timestamptz, deleted_at -> Nullable, + payment_required -> Bool, } } diff --git a/api/libs/handlers/src/organizations/post_organization_handler.rs b/api/libs/handlers/src/organizations/post_organization_handler.rs index 40be25a0f..4d92775ca 100644 --- a/api/libs/handlers/src/organizations/post_organization_handler.rs +++ b/api/libs/handlers/src/organizations/post_organization_handler.rs @@ -33,6 +33,7 @@ pub async fn post_organization_handler( created_at: now, updated_at: now, deleted_at: None, + payment_required: true, }; insert_into(organizations::table) diff --git a/api/libs/middleware/src/auth.rs b/api/libs/middleware/src/auth.rs index ae8eb9c39..e6f34bcc5 100644 --- a/api/libs/middleware/src/auth.rs +++ b/api/libs/middleware/src/auth.rs @@ -85,16 +85,62 @@ pub async fn auth(mut req: Request, next: Next) -> Result }; let user = match authorize_current_user(&token).await { - Ok(user) => match user { - Some(user) => user, - None => return Err(StatusCode::UNAUTHORIZED), - }, + Ok(Some(user)) => user, + Ok(None) => return Err(StatusCode::UNAUTHORIZED), Err(e) => { tracing::error!("Authorization error: {}", e); return handle_auth_error("invalid jwt"); } }; + // --- Payment Required Check START --- + if let Some(org_membership) = user.organizations.get(0) { + let org_id = org_membership.id; + let pg_pool = get_pg_pool(); + let mut conn = match pg_pool.get().await { + Ok(conn) => conn, + Err(e) => { + tracing::error!("Failed to get DB connection for payment check: {}", e); + return Err(StatusCode::INTERNAL_SERVER_ERROR); + } + }; + + match database::schema::organizations::table + .filter(database::schema::organizations::id.eq(org_id)) + .select(database::schema::organizations::payment_required) + .first::(&mut conn) + .await + { + Ok(payment_required) => { + if payment_required { + tracing::warn!( + user_id = %user.id, + org_id = %org_id, + "Access denied due to payment requirement for organization." + ); + return Err(StatusCode::PAYMENT_REQUIRED); + } + } + Err(diesel::NotFound) => { + tracing::error!( + user_id = %user.id, + org_id = %org_id, + "Organization not found during payment check." + ); + return Err(StatusCode::INTERNAL_SERVER_ERROR); + } + Err(e) => { + tracing::error!( + user_id = %user.id, + org_id = %org_id, + "Database error during payment check: {}", e + ); + return Err(StatusCode::INTERNAL_SERVER_ERROR); + } + } + } + // --- Payment Required Check END --- + req.extensions_mut().insert(user); Ok(next.run(req).await) } diff --git a/api/libs/middleware/src/error.rs b/api/libs/middleware/src/error.rs index 0967d81e9..c260b36c1 100644 --- a/api/libs/middleware/src/error.rs +++ b/api/libs/middleware/src/error.rs @@ -10,6 +10,12 @@ use sentry::protocol::{Event, Level}; use tower::ServiceBuilder; use tracing::{error, warn}; use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, EnvFilter}; +use axum::{ + http::StatusCode, + response::{IntoResponse, Response}, + Json, +}; +use serde_json::json; /// Creates a Sentry layer for the Axum application /// @@ -189,4 +195,29 @@ pub fn capture_anyhow(err: &Error, msg: Option<&str>) { level: Level::Error, ..Default::default() }); -} \ No newline at end of file +} + +// Define a custom error type for authentication/authorization issues +// #[derive(Debug)] +// pub enum AuthError { +// Unauthorized, +// PaymentRequired, +// InternalError(String), +// } + +// Implement IntoResponse for AuthError to convert it into an HTTP response +// impl IntoResponse for AuthError { +// fn into_response(self) -> Response { +// let (status, error_message) = match self { +// AuthError::Unauthorized => (StatusCode::UNAUTHORIZED, "Unauthorized".to_string()), +// AuthError::PaymentRequired => { +// (StatusCode::PAYMENT_REQUIRED, "Payment Required".to_string()) +// } +// AuthError::InternalError(msg) => (StatusCode::INTERNAL_SERVER_ERROR, msg), +// }; +// +// let body = Json(json!({ "error": error_message })); +// +// (status, body).into_response() +// } +// } \ No newline at end of file diff --git a/api/migrations/2025-04-21-231239_add_payment_required_to_organizations/down.sql b/api/migrations/2025-04-21-231239_add_payment_required_to_organizations/down.sql new file mode 100644 index 000000000..1513b54a3 --- /dev/null +++ b/api/migrations/2025-04-21-231239_add_payment_required_to_organizations/down.sql @@ -0,0 +1,4 @@ +-- This file should undo anything in `up.sql` + +ALTER TABLE organizations +DROP COLUMN payment_required; diff --git a/api/migrations/2025-04-21-231239_add_payment_required_to_organizations/up.sql b/api/migrations/2025-04-21-231239_add_payment_required_to_organizations/up.sql new file mode 100644 index 000000000..9716a1086 --- /dev/null +++ b/api/migrations/2025-04-21-231239_add_payment_required_to_organizations/up.sql @@ -0,0 +1,3 @@ +-- Your SQL goes here +ALTER TABLE organizations +ADD COLUMN payment_required BOOLEAN NOT NULL DEFAULT false; diff --git a/api/server/src/routes/rest/routes/users/get_user.rs b/api/server/src/routes/rest/routes/users/get_user.rs index ea64a0a22..961a51a0e 100644 --- a/api/server/src/routes/rest/routes/users/get_user.rs +++ b/api/server/src/routes/rest/routes/users/get_user.rs @@ -119,6 +119,7 @@ pub async fn get_user_information(user_id: &Uuid) -> Result { organizations::created_at, organizations::updated_at, organizations::deleted_at, + organizations::payment_required, ) .nullable(), users_to_organizations::role.nullable(), diff --git a/api/server/src/routes/ws/ws_utils.rs b/api/server/src/routes/ws/ws_utils.rs index bb2d36d61..54d146b44 100644 --- a/api/server/src/routes/ws/ws_utils.rs +++ b/api/server/src/routes/ws/ws_utils.rs @@ -409,6 +409,7 @@ pub async fn get_user_information(user_id: &Uuid) -> Result { organizations::created_at, organizations::updated_at, organizations::deleted_at, + organizations::payment_required, ) .nullable(), users_to_organizations::role.nullable(),