402 error

This commit is contained in:
dal 2025-04-21 17:25:38 -06:00
parent 7e866c54b1
commit 69c12b2144
No known key found for this signature in database
GPG Key ID: 16F4B0E1E9F61122
9 changed files with 94 additions and 5 deletions

View File

@ -338,6 +338,7 @@ pub struct Organization {
pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>,
pub deleted_at: Option<DateTime<Utc>>,
pub payment_required: bool,
}
#[derive(

View File

@ -433,6 +433,7 @@ diesel::table! {
created_at -> Timestamptz,
updated_at -> Timestamptz,
deleted_at -> Nullable<Timestamptz>,
payment_required -> Bool,
}
}

View File

@ -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)

View File

@ -85,16 +85,62 @@ pub async fn auth(mut req: Request, next: Next) -> Result<Response, StatusCode>
};
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::<bool>(&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)
}

View File

@ -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()
});
}
}
// 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()
// }
// }

View File

@ -0,0 +1,4 @@
-- This file should undo anything in `up.sql`
ALTER TABLE organizations
DROP COLUMN payment_required;

View File

@ -0,0 +1,3 @@
-- Your SQL goes here
ALTER TABLE organizations
ADD COLUMN payment_required BOOLEAN NOT NULL DEFAULT false;

View File

@ -119,6 +119,7 @@ pub async fn get_user_information(user_id: &Uuid) -> Result<UserInfoObject> {
organizations::created_at,
organizations::updated_at,
organizations::deleted_at,
organizations::payment_required,
)
.nullable(),
users_to_organizations::role.nullable(),

View File

@ -409,6 +409,7 @@ pub async fn get_user_information(user_id: &Uuid) -> Result<UserInfoObject> {
organizations::created_at,
organizations::updated_at,
organizations::deleted_at,
organizations::payment_required,
)
.nullable(),
users_to_organizations::role.nullable(),