feat(api_keys): add api keys route to api v2 (#5709)

Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com>
This commit is contained in:
Narayan Bhat
2024-08-28 18:57:36 +05:30
committed by GitHub
parent c85b4a3a27
commit 089a95069b
20 changed files with 865 additions and 426 deletions

View File

@ -2705,7 +2705,8 @@ impl MerchantConnectorAccountCreateBridge for api::MerchantConnectorCreate {
pub async fn create_connector(
state: SessionState,
req: api::MerchantConnectorCreate,
merchant_id: &id_type::MerchantId,
merchant_account: domain::MerchantAccount,
key_store: domain::MerchantKeyStore,
) -> RouterResponse<api_models::admin::MerchantConnectorResponse> {
let store = state.store.as_ref();
let key_manager_state = &(&state).into();
@ -2716,27 +2717,13 @@ pub async fn create_connector(
.change_context(errors::ApiErrorResponse::InvalidRequestData {
message: "Invalid connector name".to_string(),
})?;
let key_store = store
.get_merchant_key_store_by_merchant_id(
key_manager_state,
merchant_id,
&state.store.get_master_key().to_vec().into(),
)
.await
.to_not_found_response(errors::ApiErrorResponse::MerchantAccountNotFound)?;
let connector_metadata = ConnectorMetadata {
connector_metadata: &req.metadata,
};
connector_metadata.validate_apple_pay_certificates_in_mca_metadata()?;
let merchant_id = merchant_account.get_id();
let merchant_account = state
.store
.find_merchant_account_by_merchant_id(key_manager_state, merchant_id, &key_store)
.await
.to_not_found_response(errors::ApiErrorResponse::MerchantAccountNotFound)?;
connector_metadata.validate_apple_pay_certificates_in_mca_metadata()?;
#[cfg(all(
any(feature = "v1", feature = "v2"),
@ -2956,19 +2943,14 @@ pub async fn retrieve_connector(
#[cfg(all(feature = "v2", feature = "merchant_connector_account_v2"))]
pub async fn retrieve_connector(
state: SessionState,
merchant_id: id_type::MerchantId,
merchant_account: domain::MerchantAccount,
key_store: domain::MerchantKeyStore,
id: id_type::MerchantConnectorAccountId,
) -> RouterResponse<api_models::admin::MerchantConnectorResponse> {
let store = state.store.as_ref();
let key_manager_state = &(&state).into();
let key_store = store
.get_merchant_key_store_by_merchant_id(
key_manager_state,
&merchant_id,
&store.get_master_key().to_vec().into(),
)
.await
.to_not_found_response(errors::ApiErrorResponse::MerchantAccountNotFound)?;
let merchant_id = merchant_account.get_id();
let mca = store
.find_merchant_connector_account_by_id(key_manager_state, &id, &key_store)
@ -2978,7 +2960,7 @@ pub async fn retrieve_connector(
})?;
// Validate if the merchant_id sent in the request is valid
if mca.merchant_id != merchant_id {
if mca.merchant_id != *merchant_id {
return Err(errors::ApiErrorResponse::InvalidRequestData {
message: format!(
"Invalid merchant_id {} provided for merchant_connector_account {:?}",
@ -3174,19 +3156,14 @@ pub async fn delete_connector(
#[cfg(all(feature = "v2", feature = "merchant_connector_account_v2"))]
pub async fn delete_connector(
state: SessionState,
merchant_id: id_type::MerchantId,
merchant_account: domain::MerchantAccount,
key_store: domain::MerchantKeyStore,
id: id_type::MerchantConnectorAccountId,
) -> RouterResponse<api::MerchantConnectorDeleteResponse> {
let db = state.store.as_ref();
let key_manager_state = &(&state).into();
let key_store = db
.get_merchant_key_store_by_merchant_id(
key_manager_state,
&merchant_id,
&db.get_master_key().to_vec().into(),
)
.await
.to_not_found_response(errors::ApiErrorResponse::MerchantAccountNotFound)?;
let merchant_id = merchant_account.get_id();
let mca = db
.find_merchant_connector_account_by_id(key_manager_state, &id, &key_store)
@ -3196,7 +3173,7 @@ pub async fn delete_connector(
})?;
// Validate if the merchant_id sent in the request is valid
if mca.merchant_id != merchant_id {
if mca.merchant_id != *merchant_id {
return Err(errors::ApiErrorResponse::InvalidRequestData {
message: format!(
"Invalid merchant_id {} provided for merchant_connector_account {:?}",
@ -3215,7 +3192,7 @@ pub async fn delete_connector(
})?;
let response = api::MerchantConnectorDeleteResponse {
merchant_id,
merchant_id: merchant_id.clone(),
id,
deleted: is_deleted,
};
@ -3678,25 +3655,11 @@ impl BusinessProfileCreateBridge for api::BusinessProfileCreate {
pub async fn create_business_profile(
state: SessionState,
request: api::BusinessProfileCreate,
merchant_id: &id_type::MerchantId,
merchant_account: domain::MerchantAccount,
key_store: domain::MerchantKeyStore,
) -> RouterResponse<api_models::admin::BusinessProfileResponse> {
let db = state.store.as_ref();
let key_manager_state = &(&state).into();
let key_store = db
.get_merchant_key_store_by_merchant_id(
key_manager_state,
merchant_id,
&db.get_master_key().to_vec().into(),
)
.await
.to_not_found_response(errors::ApiErrorResponse::MerchantAccountNotFound)?;
// Get the merchant account, if few fields are not passed, then they will be inherited from
// merchant account
let merchant_account = db
.find_merchant_account_by_merchant_id(key_manager_state, merchant_id, &key_store)
.await
.to_not_found_response(errors::ApiErrorResponse::MerchantAccountNotFound)?;
#[cfg(all(
any(feature = "v1", feature = "v2"),
@ -3780,17 +3743,10 @@ pub async fn list_business_profile(
pub async fn retrieve_business_profile(
state: SessionState,
profile_id: id_type::ProfileId,
merchant_id: id_type::MerchantId,
key_store: domain::MerchantKeyStore,
) -> RouterResponse<api_models::admin::BusinessProfileResponse> {
let db = state.store.as_ref();
let key_store = db
.get_merchant_key_store_by_merchant_id(
&(&state).into(),
&merchant_id,
&db.get_master_key().to_vec().into(),
)
.await
.to_not_found_response(errors::ApiErrorResponse::MerchantAccountNotFound)?;
let business_profile = db
.find_business_profile_by_profile_id(&(&state).into(), &key_store, &profile_id)
.await
@ -4042,19 +3998,10 @@ impl BusinessProfileUpdateBridge for api::BusinessProfileUpdate {
pub async fn update_business_profile(
state: SessionState,
profile_id: &id_type::ProfileId,
merchant_id: &id_type::MerchantId,
key_store: domain::MerchantKeyStore,
request: api::BusinessProfileUpdate,
) -> RouterResponse<api::BusinessProfileResponse> {
let db = state.store.as_ref();
let key_store = db
.get_merchant_key_store_by_merchant_id(
&(&state).into(),
merchant_id,
&state.store.get_master_key().to_vec().into(),
)
.await
.to_not_found_response(errors::ApiErrorResponse::MerchantAccountNotFound)
.attach_printable("Error while fetching the key store by merchant_id")?;
let key_manager_state = &(&state).into();
let business_profile = db
@ -4064,12 +4011,6 @@ pub async fn update_business_profile(
id: profile_id.get_string_repr().to_owned(),
})?;
if business_profile.merchant_id != *merchant_id {
Err(errors::ApiErrorResponse::AccessForbidden {
resource: profile_id.get_string_repr().to_owned(),
})?
}
let business_profile_update = request
.get_update_business_profile_object(&state, &key_store)
.await?;

View File

@ -9,6 +9,7 @@ use crate::{
configs::settings,
consts,
core::errors::{self, RouterResponse, StorageErrorExt},
db::domain,
routes::{metrics, SessionState},
services::{authentication, ApplicationResponse},
types::{api, storage, transformers::ForeignInto},
@ -112,22 +113,12 @@ impl PlaintextApiKey {
pub async fn create_api_key(
state: SessionState,
api_key: api::CreateApiKeyRequest,
merchant_id: common_utils::id_type::MerchantId,
key_store: domain::MerchantKeyStore,
) -> RouterResponse<api::CreateApiKeyResponse> {
let api_key_config = state.conf.api_keys.get_inner();
let store = state.store.as_ref();
// We are not fetching merchant account as the merchant key store is needed to search for a
// merchant account.
// Instead, we're only fetching merchant key store, as it is sufficient to identify
// non-existence of a merchant account.
store
.get_merchant_key_store_by_merchant_id(
&(&state).into(),
&merchant_id,
&store.get_master_key().to_vec().into(),
)
.await
.to_not_found_response(errors::ApiErrorResponse::MerchantAccountNotFound)?;
let merchant_id = key_store.merchant_id.clone();
let hash_key = api_key_config.get_hash_key()?;
let plaintext_api_key = PlaintextApiKey::new(consts::API_KEY_LENGTH);
@ -266,12 +257,12 @@ pub async fn add_api_key_expiry_task(
#[instrument(skip_all)]
pub async fn retrieve_api_key(
state: SessionState,
merchant_id: &common_utils::id_type::MerchantId,
merchant_id: common_utils::id_type::MerchantId,
key_id: &str,
) -> RouterResponse<api::RetrieveApiKeyResponse> {
let store = state.store.as_ref();
let api_key = store
.find_api_key_by_merchant_id_key_id_optional(merchant_id, key_id)
.find_api_key_by_merchant_id_key_id_optional(&merchant_id, key_id)
.await
.change_context(errors::ApiErrorResponse::InternalServerError) // If retrieve failed
.attach_printable("Failed to retrieve API key")?