Skip to content

Commit

Permalink
Merge branch 'multitenancy' of https://github.com/juspay/hyperswitch
Browse files Browse the repository at this point in the history
…into multitenancy-users
  • Loading branch information
jagan-jaya committed May 27, 2024
2 parents 2a4bb9b + 18a75c0 commit a1d7413
Show file tree
Hide file tree
Showing 13 changed files with 91 additions and 53 deletions.
12 changes: 5 additions & 7 deletions crates/analytics/src/sqlx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@ use api_models::{
analytics::refunds::RefundType,
enums::{DisputeStage, DisputeStatus},
};
use common_utils::errors::{CustomResult, ParsingError};
use common_utils::{
errors::{CustomResult, ParsingError},
DbConnectionParams,
};
use diesel_models::enums::{
AttemptStatus, AuthenticationType, Currency, PaymentMethod, RefundStatus,
};
use error_stack::ResultExt;
use masking::PeekInterface;
use sqlx::{
postgres::{PgArgumentBuffer, PgPoolOptions, PgRow, PgTypeInfo, PgValueRef},
Decode, Encode,
Expand Down Expand Up @@ -50,11 +52,7 @@ impl Default for SqlxClient {

impl SqlxClient {
pub async fn from_conf(conf: &Database, schema: &str) -> Self {
let password = &conf.password.peek();
let database_url = format!(
"postgres://{}:{}@{}:{}/{}?application_name={}&options=-c search_path%3D{}",
conf.username, password, conf.host, conf.port, conf.dbname, schema, schema
);
let database_url = conf.get_database_url(schema);
#[allow(clippy::expect_used)]
let pool = PgPoolOptions::new()
.max_connections(conf.pool_size)
Expand Down
23 changes: 23 additions & 0 deletions crates/common_utils/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
#![warn(missing_docs, missing_debug_implementations)]
#![doc = include_str!(concat!(env!("CARGO_MANIFEST_DIR" ), "/", "README.md"))]

use masking::{PeekInterface, Secret};

pub mod access_token;
pub mod consts;
pub mod crypto;
Expand Down Expand Up @@ -205,3 +207,24 @@ pub fn generate_id_with_default_len(prefix: &str) -> String {
pub fn generate_time_ordered_id(prefix: &str) -> String {
format!("{prefix}_{}", uuid::Uuid::now_v7().as_simple())
}

#[allow(missing_docs)]
pub trait DbConnectionParams {
fn get_username(&self) -> &str;
fn get_password(&self) -> Secret<String>;
fn get_host(&self) -> &str;
fn get_port(&self) -> u16;
fn get_dbname(&self) -> &str;
fn get_database_url(&self, schema: &str) -> String {
format!(
"postgres://{}:{}@{}:{}/{}?application_name={}&options=-c search_path%3D{}",
self.get_username(),
self.get_password().peek(),
self.get_host(),
self.get_port(),
self.get_dbname(),
schema,
schema,
)
}
}
13 changes: 2 additions & 11 deletions crates/drainer/src/connection.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use bb8::PooledConnection;
use common_utils::DbConnectionParams;
use diesel::PgConnection;
use masking::PeekInterface;

use crate::{settings::Database, Settings};

Expand All @@ -23,16 +23,7 @@ pub async fn diesel_make_pg_pool(
_test_transaction: bool,
schema: &str,
) -> PgPool {
let database_url = format!(
"postgres://{}:{}@{}:{}/{}?application_name={}&options=-c search_path%3D{}",
database.username,
database.password.peek(),
database.host,
database.port,
database.dbname,
schema,
schema
);
let database_url = database.get_database_url(schema);
let manager = async_bb8_diesel::ConnectionManager::<PgConnection>::new(database_url);
let pool = bb8::Pool::builder()
.max_size(database.pool_size)
Expand Down
24 changes: 21 additions & 3 deletions crates/drainer/src/settings.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::{collections::HashMap, path::PathBuf, sync::Arc};

use common_utils::ext_traits::ConfigExt;
use common_utils::{ext_traits::ConfigExt, DbConnectionParams};
use config::{Environment, File};
use external_services::managers::{
encryption_management::EncryptionManagementConfig, secrets_management::SecretsManagementConfig,
Expand Down Expand Up @@ -88,6 +88,24 @@ pub struct Database {
pub connection_timeout: u64,
}

impl DbConnectionParams for Database {
fn get_username(&self) -> &str {
&self.username
}
fn get_password(&self) -> Secret<String> {
self.password.clone()
}
fn get_host(&self) -> &str {
&self.host
}
fn get_port(&self) -> u16 {
self.port
}
fn get_dbname(&self) -> &str {
&self.dbname
}
}

#[derive(Debug, Clone, Deserialize)]
#[serde(default)]
pub struct DrainerSettings {
Expand All @@ -104,8 +122,8 @@ pub struct Multitenancy {
pub tenants: TenantConfig,
}
impl Multitenancy {
pub fn get_tenants(&self) -> HashMap<String, Tenant> {
self.tenants.0.clone()
pub fn get_tenants(&self) -> &HashMap<String, Tenant> {
&self.tenants.0
}
pub fn get_tenant_names(&self) -> Vec<String> {
self.tenants.0.keys().cloned().collect()
Expand Down
2 changes: 1 addition & 1 deletion crates/router/src/compatibility/stripe/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,7 @@ pub enum StripeErrorCode {
PaymentMethodDeleteFailed,
#[error(error_type = StripeErrorType::InvalidRequestError, code = "", message = "Extended card info does not exist")]
ExtendedCardInfoNotFound,
#[error(error_type = StripeErrorType::InvalidRequestError, code = "IR_27", message = "Invalid tenant")]
#[error(error_type = StripeErrorType::InvalidRequestError, code = "IR_28", message = "Invalid tenant")]
InvalidTenant,
// [#216]: https://github.com/juspay/hyperswitch/issues/216
// Implement the remaining stripe error codes
Expand Down
1 change: 0 additions & 1 deletion crates/router/src/configs/defaults.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ impl Default for super::settings::Server {
workers: num_cpus::get_physical(),
host: "localhost".into(),
request_body_limit: 16 * 1024, // POST request body is limited to 16KiB
// base_url: "http://localhost:8080".into(),
shutdown_timeout: 30,
}
}
Expand Down
5 changes: 2 additions & 3 deletions crates/router/src/configs/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,8 +131,8 @@ pub struct Multitenancy {
}

impl Multitenancy {
pub fn get_tenants(&self) -> HashMap<String, Tenant> {
self.tenants.0.clone()
pub fn get_tenants(&self) -> &HashMap<String, Tenant> {
&self.tenants.0
}
pub fn get_tenant_names(&self) -> Vec<String> {
self.tenants.0.keys().cloned().collect()
Expand Down Expand Up @@ -475,7 +475,6 @@ pub struct Server {
pub workers: usize,
pub host: String,
pub request_body_limit: usize,
// pub base_url: String,
pub shutdown_timeout: u64,
}

Expand Down
4 changes: 2 additions & 2 deletions crates/router/src/core/payment_methods/cards.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1909,7 +1909,7 @@ pub async fn list_payment_methods(
#[cfg(not(feature = "business_profile_routing"))]
let key = { format!("pm_filters_cgraph_{}", &merchant_account.merchant_id) };

if let Some(graph) = get_merchant_pm_filter_graph(&key, state.tenant.to_string()).await {
if let Some(graph) = get_merchant_pm_filter_graph(&key, state.tenant.clone()).await {
// Derivation of PM_FILTER_CGRAPH from MokaCache successful
for mca in &filtered_mcas {
let payment_methods = match &mca.payment_methods_enabled {
Expand Down Expand Up @@ -1952,7 +1952,7 @@ pub async fn list_payment_methods(
}

// Refreshing our CGraph cache
let graph = refresh_pm_filters_cache(&key, state.tenant.to_string(), builder.build()).await;
let graph = refresh_pm_filters_cache(&key, state.tenant.clone(), builder.build()).await;

for mca in &filtered_mcas {
let payment_methods = match &mca.payment_methods_enabled {
Expand Down
2 changes: 1 addition & 1 deletion crates/router/src/routes/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ pub struct AppState {
}
impl scheduler::SchedulerAppState for AppState {
fn get_tenants(&self) -> Vec<String> {
self.conf.multitenancy.get_tenant_names().clone()
self.conf.multitenancy.get_tenant_names()
}
}
pub trait AppStateInfo {
Expand Down
24 changes: 12 additions & 12 deletions crates/router/src/services/api.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
pub mod client;
pub mod request;
use std::{
collections::HashMap,
collections::{HashMap, HashSet},
error::Error,
fmt::Debug,
future::Future,
Expand Down Expand Up @@ -1010,7 +1010,12 @@ where
.change_context(errors::ApiErrorResponse::InternalServerError.switch())?;

let mut event_type = payload.get_api_event_type();

let tenants: HashSet<_> = state
.conf
.multitenancy
.get_tenant_names()
.into_iter()
.collect();
let tenant_id = if !state.conf.multitenancy.enabled {
common_utils::consts::DEFAULT_TENANT.to_string()
} else {
Expand All @@ -1023,23 +1028,18 @@ where
}
.switch()
})
.map(|tenant_id| {
if !state
.conf
.multitenancy
.get_tenant_names()
.contains(&tenant_id.to_string())
{
.map(|req_tenant_id| {
if !tenants.contains(&req_tenant_id.to_string()) {
Err(errors::ApiErrorResponse::InvalidTenant {
tenant_id: tenant_id.to_string(),
tenant_id: req_tenant_id.to_string(),
}
.switch())
} else {
Ok(tenant_id.to_string())
Ok(req_tenant_id.to_string())
}
})??
};
// let tenant_id = "public";
// let tenant_id = "public".to_string();
let mut session_state =
Arc::new(app_state.clone()).get_session_state(tenant_id.as_str(), || {
errors::ApiErrorResponse::InvalidTenant {
Expand Down
19 changes: 19 additions & 0 deletions crates/storage_impl/src/config.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use common_utils::DbConnectionParams;
use masking::Secret;

#[derive(Debug, Clone, serde::Deserialize)]
Expand All @@ -14,6 +15,24 @@ pub struct Database {
pub max_lifetime: Option<u64>,
}

impl DbConnectionParams for Database {
fn get_username(&self) -> &str {
&self.username
}
fn get_password(&self) -> Secret<String> {
self.password.clone()
}
fn get_host(&self) -> &str {
&self.host
}
fn get_port(&self) -> u16 {
self.port
}
fn get_dbname(&self) -> &str {
&self.dbname
}
}

#[derive(Debug, serde::Deserialize, Clone, Copy, Default)]
#[serde(rename_all = "PascalCase")]
pub enum QueueStrategy {
Expand Down
13 changes: 2 additions & 11 deletions crates/storage_impl/src/database/store.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
use async_bb8_diesel::{AsyncConnection, ConnectionError};
use bb8::CustomizeConnection;
use common_utils::DbConnectionParams;
use diesel::PgConnection;
use error_stack::ResultExt;
use hyperswitch_domain_models::errors::{StorageError, StorageResult};
use masking::PeekInterface;

use crate::config::Database;

Expand Down Expand Up @@ -83,16 +83,7 @@ pub async fn diesel_make_pg_pool(
schema: &str,
test_transaction: bool,
) -> StorageResult<PgPool> {
let database_url = format!(
"postgres://{}:{}@{}:{}/{}?application_name={}&options=-c search_path%3D{}",
database.username,
database.password.peek(),
database.host,
database.port,
database.dbname,
schema,
schema,
);
let database_url = database.get_database_url(schema);
let manager = async_bb8_diesel::ConnectionManager::<PgConnection>::new(database_url);
let mut pool = bb8::Pool::builder()
.max_size(database.pool_size)
Expand Down
2 changes: 1 addition & 1 deletion crates/storage_impl/src/redis/cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ impl From<CacheKey> for String {
if val.prefix.is_empty() {
val.key
} else {
format!("{}:{}", val.prefix.clone(), val.key.clone())
format!("{}:{}", val.prefix, val.key)
}
}
}
Expand Down

0 comments on commit a1d7413

Please sign in to comment.