feat(decision): add support to register api keys to proxy (#5168)

This commit is contained in:
Nishant Joshi
2024-07-09 13:05:20 +05:30
committed by GitHub
parent ffc79674e4
commit 071d5345b5
7 changed files with 329 additions and 2 deletions

View File

@ -28,7 +28,7 @@ use crate::{
},
db::StorageInterface,
routes::{metrics, SessionState},
services::{self, api as service_api},
services::{self, api as service_api, authentication},
types::{
self, api,
domain::{
@ -281,6 +281,25 @@ pub async fn create_merchant_account(
.await
.to_duplicate_response(errors::ApiErrorResponse::DuplicateMerchantAccount)?;
if let Some(api_key) = merchant_account.publishable_key.as_ref() {
let state = state.clone();
let api_key = api_key.clone();
let merchant_id = merchant_account.merchant_id.clone();
authentication::decision::spawn_tracked_job(
async move {
authentication::decision::add_publishable_key(
&state,
api_key.into(),
merchant_id,
None,
)
.await
},
authentication::decision::ADD,
);
}
db.insert_config(configs::ConfigNew {
key: format!("{}_requires_cvv", merchant_account.merchant_id),
config: "true".to_string(),
@ -650,6 +669,20 @@ pub async fn merchant_account_delete(
) -> RouterResponse<api::MerchantAccountDeleteResponse> {
let mut is_deleted = false;
let db = state.store.as_ref();
let merchant_key_store = db
.get_merchant_key_store_by_merchant_id(
&merchant_id,
&state.store.get_master_key().to_vec().into(),
)
.await
.to_not_found_response(errors::ApiErrorResponse::MerchantAccountNotFound)?;
let merchant_account = db
.find_merchant_account_by_merchant_id(&merchant_id, &merchant_key_store)
.await
.to_not_found_response(errors::ApiErrorResponse::MerchantAccountNotFound)?;
let is_merchant_account_deleted = db
.delete_merchant_account_by_merchant_id(&merchant_id)
.await
@ -662,6 +695,14 @@ pub async fn merchant_account_delete(
is_deleted = is_merchant_account_deleted && is_merchant_key_store_deleted;
}
if let Some(api_key) = merchant_account.publishable_key {
let state = state.clone();
authentication::decision::spawn_tracked_job(
async move { authentication::decision::revoke_api_key(&state, api_key.into()).await },
authentication::decision::REVOKE,
)
}
match db
.delete_config_by_key(format!("{}_requires_cvv", merchant_id).as_str())
.await

View File

@ -10,7 +10,7 @@ use crate::{
consts,
core::errors::{self, RouterResponse, StorageErrorExt},
routes::{metrics, SessionState},
services::ApplicationResponse,
services::{authentication, ApplicationResponse},
types::{api, storage, transformers::ForeignInto},
utils,
};
@ -148,6 +148,26 @@ pub async fn create_api_key(
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("Failed to insert new API key")?;
let state_inner = state.clone();
let hashed_api_key = api_key.hashed_api_key.clone();
let merchant_id_inner = merchant_id.clone();
let key_id = api_key.key_id.clone();
let expires_at = api_key.expires_at;
authentication::decision::spawn_tracked_job(
async move {
authentication::decision::add_api_key(
&state_inner,
hashed_api_key.into_inner().into(),
merchant_id_inner,
key_id,
expires_at.map(authentication::decision::convert_expiry),
)
.await
},
authentication::decision::ADD,
);
metrics::API_KEY_CREATED.add(
&metrics::CONTEXT,
1,
@ -277,6 +297,25 @@ pub async fn update_api_key(
.await
.to_not_found_response(errors::ApiErrorResponse::ApiKeyNotFound)?;
let state_inner = state.clone();
let hashed_api_key = api_key.hashed_api_key.clone();
let key_id_inner = api_key.key_id.clone();
let expires_at = api_key.expires_at;
authentication::decision::spawn_tracked_job(
async move {
authentication::decision::add_api_key(
&state_inner,
hashed_api_key.into_inner().into(),
merchant_id.clone(),
key_id_inner,
expires_at.map(authentication::decision::convert_expiry),
)
.await
},
authentication::decision::ADD,
);
#[cfg(feature = "email")]
{
let expiry_reminder_days = state.conf.api_keys.get_inner().expiry_reminder_days.clone();
@ -402,11 +441,30 @@ pub async fn revoke_api_key(
key_id: &str,
) -> RouterResponse<api::RevokeApiKeyResponse> {
let store = state.store.as_ref();
let api_key = store
.find_api_key_by_merchant_id_key_id_optional(merchant_id, key_id)
.await
.to_not_found_response(errors::ApiErrorResponse::ApiKeyNotFound)?;
let revoked = store
.revoke_api_key(merchant_id, key_id)
.await
.to_not_found_response(errors::ApiErrorResponse::ApiKeyNotFound)?;
if let Some(api_key) = api_key {
let hashed_api_key = api_key.hashed_api_key;
let state = state.clone();
authentication::decision::spawn_tracked_job(
async move {
authentication::decision::revoke_api_key(&state, hashed_api_key.into_inner().into())
.await
},
authentication::decision::REVOKE,
);
}
metrics::API_KEY_REVOKED.add(&metrics::CONTEXT, 1, &[]);
#[cfg(feature = "email")]

View File

@ -83,3 +83,6 @@ counter_metric!(
ROUTING_RETRIEVE_CONFIG_FOR_PROFILE_SUCCESS_RESPONSE,
GLOBAL_METER
);
counter_metric!(API_KEY_REQUEST_INITIATED, GLOBAL_METER);
counter_metric!(API_KEY_REQUEST_COMPLETED, GLOBAL_METER);