mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-10-30 09:38:33 +08:00
refactor(router): Introduce ApiKeyId id type (#6324)
This commit is contained in:
@ -1,5 +1,8 @@
|
|||||||
[default]
|
[default]
|
||||||
check-filename = true
|
check-filename = true
|
||||||
|
extend-ignore-identifiers-re = [
|
||||||
|
"UE_[0-9]{3,4}", # Unified error codes
|
||||||
|
]
|
||||||
|
|
||||||
[default.extend-identifiers]
|
[default.extend-identifiers]
|
||||||
ABD = "ABD" # Aberdeenshire, UK ISO 3166-2 code
|
ABD = "ABD" # Aberdeenshire, UK ISO 3166-2 code
|
||||||
@ -38,7 +41,6 @@ ws2ipdef = "ws2ipdef" # WinSock Extension
|
|||||||
ws2tcpip = "ws2tcpip" # WinSock Extension
|
ws2tcpip = "ws2tcpip" # WinSock Extension
|
||||||
ZAR = "ZAR" # South African Rand currency code
|
ZAR = "ZAR" # South African Rand currency code
|
||||||
JOD = "JOD" # Jordan currency code
|
JOD = "JOD" # Jordan currency code
|
||||||
UE_000 = "UE_000" #default unified error code
|
|
||||||
|
|
||||||
|
|
||||||
[default.extend-words]
|
[default.extend-words]
|
||||||
|
|||||||
@ -29,8 +29,8 @@ pub struct CreateApiKeyRequest {
|
|||||||
#[derive(Debug, Serialize, ToSchema)]
|
#[derive(Debug, Serialize, ToSchema)]
|
||||||
pub struct CreateApiKeyResponse {
|
pub struct CreateApiKeyResponse {
|
||||||
/// The identifier for the API Key.
|
/// The identifier for the API Key.
|
||||||
#[schema(max_length = 64, example = "5hEEqkgJUyuxgSKGArHA4mWSnX")]
|
#[schema(max_length = 64, example = "5hEEqkgJUyuxgSKGArHA4mWSnX", value_type = String)]
|
||||||
pub key_id: String,
|
pub key_id: common_utils::id_type::ApiKeyId,
|
||||||
|
|
||||||
/// The identifier for the Merchant Account.
|
/// The identifier for the Merchant Account.
|
||||||
#[schema(max_length = 64, example = "y3oqhf46pyzuxjbcn2giaqnb44", value_type = String)]
|
#[schema(max_length = 64, example = "y3oqhf46pyzuxjbcn2giaqnb44", value_type = String)]
|
||||||
@ -72,8 +72,8 @@ pub struct CreateApiKeyResponse {
|
|||||||
#[derive(Debug, Serialize, ToSchema)]
|
#[derive(Debug, Serialize, ToSchema)]
|
||||||
pub struct RetrieveApiKeyResponse {
|
pub struct RetrieveApiKeyResponse {
|
||||||
/// The identifier for the API Key.
|
/// The identifier for the API Key.
|
||||||
#[schema(max_length = 64, example = "5hEEqkgJUyuxgSKGArHA4mWSnX")]
|
#[schema(max_length = 64, example = "5hEEqkgJUyuxgSKGArHA4mWSnX", value_type = String)]
|
||||||
pub key_id: String,
|
pub key_id: common_utils::id_type::ApiKeyId,
|
||||||
|
|
||||||
/// The identifier for the Merchant Account.
|
/// The identifier for the Merchant Account.
|
||||||
#[schema(max_length = 64, example = "y3oqhf46pyzuxjbcn2giaqnb44", value_type = String)]
|
#[schema(max_length = 64, example = "y3oqhf46pyzuxjbcn2giaqnb44", value_type = String)]
|
||||||
@ -131,7 +131,8 @@ pub struct UpdateApiKeyRequest {
|
|||||||
pub expiration: Option<ApiKeyExpiration>,
|
pub expiration: Option<ApiKeyExpiration>,
|
||||||
|
|
||||||
#[serde(skip_deserializing)]
|
#[serde(skip_deserializing)]
|
||||||
pub key_id: String,
|
#[schema(value_type = String)]
|
||||||
|
pub key_id: common_utils::id_type::ApiKeyId,
|
||||||
|
|
||||||
#[serde(skip_deserializing)]
|
#[serde(skip_deserializing)]
|
||||||
#[schema(value_type = String)]
|
#[schema(value_type = String)]
|
||||||
@ -146,8 +147,8 @@ pub struct RevokeApiKeyResponse {
|
|||||||
pub merchant_id: common_utils::id_type::MerchantId,
|
pub merchant_id: common_utils::id_type::MerchantId,
|
||||||
|
|
||||||
/// The identifier for the API Key.
|
/// The identifier for the API Key.
|
||||||
#[schema(max_length = 64, example = "5hEEqkgJUyuxgSKGArHA4mWSnX")]
|
#[schema(max_length = 64, example = "5hEEqkgJUyuxgSKGArHA4mWSnX", value_type = String)]
|
||||||
pub key_id: String,
|
pub key_id: common_utils::id_type::ApiKeyId,
|
||||||
/// Indicates whether the API key was revoked or not.
|
/// Indicates whether the API key was revoked or not.
|
||||||
#[schema(example = "true")]
|
#[schema(example = "true")]
|
||||||
pub revoked: bool,
|
pub revoked: bool,
|
||||||
|
|||||||
@ -45,6 +45,9 @@ pub enum ApiEventsType {
|
|||||||
BusinessProfile {
|
BusinessProfile {
|
||||||
profile_id: id_type::ProfileId,
|
profile_id: id_type::ProfileId,
|
||||||
},
|
},
|
||||||
|
ApiKey {
|
||||||
|
key_id: id_type::ApiKeyId,
|
||||||
|
},
|
||||||
User {
|
User {
|
||||||
user_id: String,
|
user_id: String,
|
||||||
},
|
},
|
||||||
@ -130,10 +133,6 @@ impl_api_event_type!(
|
|||||||
(
|
(
|
||||||
String,
|
String,
|
||||||
id_type::MerchantId,
|
id_type::MerchantId,
|
||||||
(id_type::MerchantId, String),
|
|
||||||
(id_type::MerchantId, &String),
|
|
||||||
(&id_type::MerchantId, &String),
|
|
||||||
(&String, &String),
|
|
||||||
(Option<i64>, Option<i64>, String),
|
(Option<i64>, Option<i64>, String),
|
||||||
(Option<i64>, Option<i64>, id_type::MerchantId),
|
(Option<i64>, Option<i64>, id_type::MerchantId),
|
||||||
bool
|
bool
|
||||||
|
|||||||
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
use std::{borrow::Cow, fmt::Debug};
|
use std::{borrow::Cow, fmt::Debug};
|
||||||
|
|
||||||
|
mod api_key;
|
||||||
mod customer;
|
mod customer;
|
||||||
mod merchant;
|
mod merchant;
|
||||||
mod merchant_connector_account;
|
mod merchant_connector_account;
|
||||||
@ -14,6 +15,7 @@ mod routing;
|
|||||||
#[cfg(feature = "v2")]
|
#[cfg(feature = "v2")]
|
||||||
mod global_id;
|
mod global_id;
|
||||||
|
|
||||||
|
pub use api_key::ApiKeyId;
|
||||||
pub use customer::CustomerId;
|
pub use customer::CustomerId;
|
||||||
use diesel::{
|
use diesel::{
|
||||||
backend::Backend,
|
backend::Backend,
|
||||||
|
|||||||
46
crates/common_utils/src/id_type/api_key.rs
Normal file
46
crates/common_utils/src/id_type/api_key.rs
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
crate::id_type!(
|
||||||
|
ApiKeyId,
|
||||||
|
"A type for key_id that can be used for API key IDs"
|
||||||
|
);
|
||||||
|
crate::impl_id_type_methods!(ApiKeyId, "key_id");
|
||||||
|
|
||||||
|
// This is to display the `ApiKeyId` as ApiKeyId(abcd)
|
||||||
|
crate::impl_debug_id_type!(ApiKeyId);
|
||||||
|
crate::impl_try_from_cow_str_id_type!(ApiKeyId, "key_id");
|
||||||
|
|
||||||
|
crate::impl_serializable_secret_id_type!(ApiKeyId);
|
||||||
|
crate::impl_queryable_id_type!(ApiKeyId);
|
||||||
|
crate::impl_to_sql_from_sql_id_type!(ApiKeyId);
|
||||||
|
|
||||||
|
impl ApiKeyId {
|
||||||
|
/// Generate Api Key Id from prefix
|
||||||
|
pub fn generate_key_id(prefix: &'static str) -> Self {
|
||||||
|
Self(crate::generate_ref_id_with_default_length(prefix))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl crate::events::ApiEventMetric for ApiKeyId {
|
||||||
|
fn get_api_event_type(&self) -> Option<crate::events::ApiEventsType> {
|
||||||
|
Some(crate::events::ApiEventsType::ApiKey {
|
||||||
|
key_id: self.clone(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl crate::events::ApiEventMetric for (super::MerchantId, ApiKeyId) {
|
||||||
|
fn get_api_event_type(&self) -> Option<crate::events::ApiEventsType> {
|
||||||
|
Some(crate::events::ApiEventsType::ApiKey {
|
||||||
|
key_id: self.1.clone(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl crate::events::ApiEventMetric for (&super::MerchantId, &ApiKeyId) {
|
||||||
|
fn get_api_event_type(&self) -> Option<crate::events::ApiEventsType> {
|
||||||
|
Some(crate::events::ApiEventsType::ApiKey {
|
||||||
|
key_id: self.1.clone(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
crate::impl_default_id_type!(ApiKeyId, "key");
|
||||||
@ -9,7 +9,7 @@ use crate::schema::api_keys;
|
|||||||
)]
|
)]
|
||||||
#[diesel(table_name = api_keys, primary_key(key_id), check_for_backend(diesel::pg::Pg))]
|
#[diesel(table_name = api_keys, primary_key(key_id), check_for_backend(diesel::pg::Pg))]
|
||||||
pub struct ApiKey {
|
pub struct ApiKey {
|
||||||
pub key_id: String,
|
pub key_id: common_utils::id_type::ApiKeyId,
|
||||||
pub merchant_id: common_utils::id_type::MerchantId,
|
pub merchant_id: common_utils::id_type::MerchantId,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub description: Option<String>,
|
pub description: Option<String>,
|
||||||
@ -23,7 +23,7 @@ pub struct ApiKey {
|
|||||||
#[derive(Debug, Insertable)]
|
#[derive(Debug, Insertable)]
|
||||||
#[diesel(table_name = api_keys)]
|
#[diesel(table_name = api_keys)]
|
||||||
pub struct ApiKeyNew {
|
pub struct ApiKeyNew {
|
||||||
pub key_id: String,
|
pub key_id: common_utils::id_type::ApiKeyId,
|
||||||
pub merchant_id: common_utils::id_type::MerchantId,
|
pub merchant_id: common_utils::id_type::MerchantId,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub description: Option<String>,
|
pub description: Option<String>,
|
||||||
@ -141,7 +141,7 @@ mod diesel_impl {
|
|||||||
// Tracking data by process_tracker
|
// Tracking data by process_tracker
|
||||||
#[derive(Default, Debug, Deserialize, Serialize, Clone)]
|
#[derive(Default, Debug, Deserialize, Serialize, Clone)]
|
||||||
pub struct ApiKeyExpiryTrackingData {
|
pub struct ApiKeyExpiryTrackingData {
|
||||||
pub key_id: String,
|
pub key_id: common_utils::id_type::ApiKeyId,
|
||||||
pub merchant_id: common_utils::id_type::MerchantId,
|
pub merchant_id: common_utils::id_type::MerchantId,
|
||||||
pub api_key_name: String,
|
pub api_key_name: String,
|
||||||
pub prefix: String,
|
pub prefix: String,
|
||||||
|
|||||||
@ -18,7 +18,7 @@ impl ApiKey {
|
|||||||
pub async fn update_by_merchant_id_key_id(
|
pub async fn update_by_merchant_id_key_id(
|
||||||
conn: &PgPooledConn,
|
conn: &PgPooledConn,
|
||||||
merchant_id: common_utils::id_type::MerchantId,
|
merchant_id: common_utils::id_type::MerchantId,
|
||||||
key_id: String,
|
key_id: common_utils::id_type::ApiKeyId,
|
||||||
api_key_update: ApiKeyUpdate,
|
api_key_update: ApiKeyUpdate,
|
||||||
) -> StorageResult<Self> {
|
) -> StorageResult<Self> {
|
||||||
match generics::generic_update_with_unique_predicate_get_result::<
|
match generics::generic_update_with_unique_predicate_get_result::<
|
||||||
@ -57,7 +57,7 @@ impl ApiKey {
|
|||||||
pub async fn revoke_by_merchant_id_key_id(
|
pub async fn revoke_by_merchant_id_key_id(
|
||||||
conn: &PgPooledConn,
|
conn: &PgPooledConn,
|
||||||
merchant_id: &common_utils::id_type::MerchantId,
|
merchant_id: &common_utils::id_type::MerchantId,
|
||||||
key_id: &str,
|
key_id: &common_utils::id_type::ApiKeyId,
|
||||||
) -> StorageResult<bool> {
|
) -> StorageResult<bool> {
|
||||||
generics::generic_delete::<<Self as HasTable>::Table, _>(
|
generics::generic_delete::<<Self as HasTable>::Table, _>(
|
||||||
conn,
|
conn,
|
||||||
@ -71,7 +71,7 @@ impl ApiKey {
|
|||||||
pub async fn find_optional_by_merchant_id_key_id(
|
pub async fn find_optional_by_merchant_id_key_id(
|
||||||
conn: &PgPooledConn,
|
conn: &PgPooledConn,
|
||||||
merchant_id: &common_utils::id_type::MerchantId,
|
merchant_id: &common_utils::id_type::MerchantId,
|
||||||
key_id: &str,
|
key_id: &common_utils::id_type::ApiKeyId,
|
||||||
) -> StorageResult<Option<Self>> {
|
) -> StorageResult<Option<Self>> {
|
||||||
generics::generic_find_one_optional::<<Self as HasTable>::Table, _, _>(
|
generics::generic_find_one_optional::<<Self as HasTable>::Table, _, _>(
|
||||||
conn,
|
conn,
|
||||||
|
|||||||
@ -13,7 +13,6 @@ use crate::{
|
|||||||
routes::{metrics, SessionState},
|
routes::{metrics, SessionState},
|
||||||
services::{authentication, ApplicationResponse},
|
services::{authentication, ApplicationResponse},
|
||||||
types::{api, storage, transformers::ForeignInto},
|
types::{api, storage, transformers::ForeignInto},
|
||||||
utils,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(feature = "email")]
|
#[cfg(feature = "email")]
|
||||||
@ -63,9 +62,9 @@ impl PlaintextApiKey {
|
|||||||
Self(format!("{env}_{key}").into())
|
Self(format!("{env}_{key}").into())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_key_id() -> String {
|
pub fn new_key_id() -> common_utils::id_type::ApiKeyId {
|
||||||
let env = router_env::env::prefix_for_env();
|
let env = router_env::env::prefix_for_env();
|
||||||
utils::generate_id(consts::ID_LENGTH, env)
|
common_utils::id_type::ApiKeyId::generate_key_id(env)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn prefix(&self) -> String {
|
pub fn prefix(&self) -> String {
|
||||||
@ -223,7 +222,7 @@ pub async fn add_api_key_expiry_task(
|
|||||||
expiry_reminder_days: expiry_reminder_days.clone(),
|
expiry_reminder_days: expiry_reminder_days.clone(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let process_tracker_id = generate_task_id_for_api_key_expiry_workflow(api_key.key_id.as_str());
|
let process_tracker_id = generate_task_id_for_api_key_expiry_workflow(&api_key.key_id);
|
||||||
let process_tracker_entry = storage::ProcessTrackerNew::new(
|
let process_tracker_entry = storage::ProcessTrackerNew::new(
|
||||||
process_tracker_id,
|
process_tracker_id,
|
||||||
API_KEY_EXPIRY_NAME,
|
API_KEY_EXPIRY_NAME,
|
||||||
@ -241,7 +240,7 @@ pub async fn add_api_key_expiry_task(
|
|||||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||||
.attach_printable_lazy(|| {
|
.attach_printable_lazy(|| {
|
||||||
format!(
|
format!(
|
||||||
"Failed while inserting API key expiry reminder to process_tracker: api_key_id: {}",
|
"Failed while inserting API key expiry reminder to process_tracker: {:?}",
|
||||||
api_key.key_id
|
api_key.key_id
|
||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
@ -258,11 +257,11 @@ pub async fn add_api_key_expiry_task(
|
|||||||
pub async fn retrieve_api_key(
|
pub async fn retrieve_api_key(
|
||||||
state: SessionState,
|
state: SessionState,
|
||||||
merchant_id: common_utils::id_type::MerchantId,
|
merchant_id: common_utils::id_type::MerchantId,
|
||||||
key_id: &str,
|
key_id: common_utils::id_type::ApiKeyId,
|
||||||
) -> RouterResponse<api::RetrieveApiKeyResponse> {
|
) -> RouterResponse<api::RetrieveApiKeyResponse> {
|
||||||
let store = state.store.as_ref();
|
let store = state.store.as_ref();
|
||||||
let api_key = store
|
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
|
.await
|
||||||
.change_context(errors::ApiErrorResponse::InternalServerError) // If retrieve failed
|
.change_context(errors::ApiErrorResponse::InternalServerError) // If retrieve failed
|
||||||
.attach_printable("Failed to retrieve API key")?
|
.attach_printable("Failed to retrieve API key")?
|
||||||
@ -388,7 +387,7 @@ pub async fn update_api_key_expiry_task(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let task_id = generate_task_id_for_api_key_expiry_workflow(api_key.key_id.as_str());
|
let task_id = generate_task_id_for_api_key_expiry_workflow(&api_key.key_id);
|
||||||
|
|
||||||
let task_ids = vec![task_id.clone()];
|
let task_ids = vec![task_id.clone()];
|
||||||
|
|
||||||
@ -430,7 +429,7 @@ pub async fn update_api_key_expiry_task(
|
|||||||
pub async fn revoke_api_key(
|
pub async fn revoke_api_key(
|
||||||
state: SessionState,
|
state: SessionState,
|
||||||
merchant_id: &common_utils::id_type::MerchantId,
|
merchant_id: &common_utils::id_type::MerchantId,
|
||||||
key_id: &str,
|
key_id: &common_utils::id_type::ApiKeyId,
|
||||||
) -> RouterResponse<api::RevokeApiKeyResponse> {
|
) -> RouterResponse<api::RevokeApiKeyResponse> {
|
||||||
let store = state.store.as_ref();
|
let store = state.store.as_ref();
|
||||||
|
|
||||||
@ -496,7 +495,7 @@ pub async fn revoke_api_key(
|
|||||||
#[instrument(skip_all)]
|
#[instrument(skip_all)]
|
||||||
pub async fn revoke_api_key_expiry_task(
|
pub async fn revoke_api_key_expiry_task(
|
||||||
store: &dyn crate::db::StorageInterface,
|
store: &dyn crate::db::StorageInterface,
|
||||||
key_id: &str,
|
key_id: &common_utils::id_type::ApiKeyId,
|
||||||
) -> Result<(), errors::ProcessTrackerError> {
|
) -> Result<(), errors::ProcessTrackerError> {
|
||||||
let task_id = generate_task_id_for_api_key_expiry_workflow(key_id);
|
let task_id = generate_task_id_for_api_key_expiry_workflow(key_id);
|
||||||
let task_ids = vec![task_id];
|
let task_ids = vec![task_id];
|
||||||
@ -535,8 +534,13 @@ pub async fn list_api_keys(
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "email")]
|
#[cfg(feature = "email")]
|
||||||
fn generate_task_id_for_api_key_expiry_workflow(key_id: &str) -> String {
|
fn generate_task_id_for_api_key_expiry_workflow(
|
||||||
format!("{API_KEY_EXPIRY_RUNNER}_{API_KEY_EXPIRY_NAME}_{key_id}")
|
key_id: &common_utils::id_type::ApiKeyId,
|
||||||
|
) -> String {
|
||||||
|
format!(
|
||||||
|
"{API_KEY_EXPIRY_RUNNER}_{API_KEY_EXPIRY_NAME}_{}",
|
||||||
|
key_id.get_string_repr()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&str> for PlaintextApiKey {
|
impl From<&str> for PlaintextApiKey {
|
||||||
|
|||||||
@ -20,20 +20,20 @@ pub trait ApiKeyInterface {
|
|||||||
async fn update_api_key(
|
async fn update_api_key(
|
||||||
&self,
|
&self,
|
||||||
merchant_id: common_utils::id_type::MerchantId,
|
merchant_id: common_utils::id_type::MerchantId,
|
||||||
key_id: String,
|
key_id: common_utils::id_type::ApiKeyId,
|
||||||
api_key: storage::ApiKeyUpdate,
|
api_key: storage::ApiKeyUpdate,
|
||||||
) -> CustomResult<storage::ApiKey, errors::StorageError>;
|
) -> CustomResult<storage::ApiKey, errors::StorageError>;
|
||||||
|
|
||||||
async fn revoke_api_key(
|
async fn revoke_api_key(
|
||||||
&self,
|
&self,
|
||||||
merchant_id: &common_utils::id_type::MerchantId,
|
merchant_id: &common_utils::id_type::MerchantId,
|
||||||
key_id: &str,
|
key_id: &common_utils::id_type::ApiKeyId,
|
||||||
) -> CustomResult<bool, errors::StorageError>;
|
) -> CustomResult<bool, errors::StorageError>;
|
||||||
|
|
||||||
async fn find_api_key_by_merchant_id_key_id_optional(
|
async fn find_api_key_by_merchant_id_key_id_optional(
|
||||||
&self,
|
&self,
|
||||||
merchant_id: &common_utils::id_type::MerchantId,
|
merchant_id: &common_utils::id_type::MerchantId,
|
||||||
key_id: &str,
|
key_id: &common_utils::id_type::ApiKeyId,
|
||||||
) -> CustomResult<Option<storage::ApiKey>, errors::StorageError>;
|
) -> CustomResult<Option<storage::ApiKey>, errors::StorageError>;
|
||||||
|
|
||||||
async fn find_api_key_by_hash_optional(
|
async fn find_api_key_by_hash_optional(
|
||||||
@ -67,7 +67,7 @@ impl ApiKeyInterface for Store {
|
|||||||
async fn update_api_key(
|
async fn update_api_key(
|
||||||
&self,
|
&self,
|
||||||
merchant_id: common_utils::id_type::MerchantId,
|
merchant_id: common_utils::id_type::MerchantId,
|
||||||
key_id: String,
|
key_id: common_utils::id_type::ApiKeyId,
|
||||||
api_key: storage::ApiKeyUpdate,
|
api_key: storage::ApiKeyUpdate,
|
||||||
) -> CustomResult<storage::ApiKey, errors::StorageError> {
|
) -> CustomResult<storage::ApiKey, errors::StorageError> {
|
||||||
let conn = connection::pg_connection_write(self).await?;
|
let conn = connection::pg_connection_write(self).await?;
|
||||||
@ -99,7 +99,8 @@ impl ApiKeyInterface for Store {
|
|||||||
.await
|
.await
|
||||||
.map_err(|error| report!(errors::StorageError::from(error)))?
|
.map_err(|error| report!(errors::StorageError::from(error)))?
|
||||||
.ok_or(report!(errors::StorageError::ValueNotFound(format!(
|
.ok_or(report!(errors::StorageError::ValueNotFound(format!(
|
||||||
"ApiKey of {_key_id} not found"
|
"ApiKey of {} not found",
|
||||||
|
_key_id.get_string_repr()
|
||||||
))))?;
|
))))?;
|
||||||
|
|
||||||
cache::publish_and_redact(
|
cache::publish_and_redact(
|
||||||
@ -115,7 +116,7 @@ impl ApiKeyInterface for Store {
|
|||||||
async fn revoke_api_key(
|
async fn revoke_api_key(
|
||||||
&self,
|
&self,
|
||||||
merchant_id: &common_utils::id_type::MerchantId,
|
merchant_id: &common_utils::id_type::MerchantId,
|
||||||
key_id: &str,
|
key_id: &common_utils::id_type::ApiKeyId,
|
||||||
) -> CustomResult<bool, errors::StorageError> {
|
) -> CustomResult<bool, errors::StorageError> {
|
||||||
let conn = connection::pg_connection_write(self).await?;
|
let conn = connection::pg_connection_write(self).await?;
|
||||||
let delete_call = || async {
|
let delete_call = || async {
|
||||||
@ -141,7 +142,8 @@ impl ApiKeyInterface for Store {
|
|||||||
.await
|
.await
|
||||||
.map_err(|error| report!(errors::StorageError::from(error)))?
|
.map_err(|error| report!(errors::StorageError::from(error)))?
|
||||||
.ok_or(report!(errors::StorageError::ValueNotFound(format!(
|
.ok_or(report!(errors::StorageError::ValueNotFound(format!(
|
||||||
"ApiKey of {key_id} not found"
|
"ApiKey of {} not found",
|
||||||
|
key_id.get_string_repr()
|
||||||
))))?;
|
))))?;
|
||||||
|
|
||||||
cache::publish_and_redact(
|
cache::publish_and_redact(
|
||||||
@ -157,7 +159,7 @@ impl ApiKeyInterface for Store {
|
|||||||
async fn find_api_key_by_merchant_id_key_id_optional(
|
async fn find_api_key_by_merchant_id_key_id_optional(
|
||||||
&self,
|
&self,
|
||||||
merchant_id: &common_utils::id_type::MerchantId,
|
merchant_id: &common_utils::id_type::MerchantId,
|
||||||
key_id: &str,
|
key_id: &common_utils::id_type::ApiKeyId,
|
||||||
) -> CustomResult<Option<storage::ApiKey>, errors::StorageError> {
|
) -> CustomResult<Option<storage::ApiKey>, errors::StorageError> {
|
||||||
let conn = connection::pg_connection_read(self).await?;
|
let conn = connection::pg_connection_read(self).await?;
|
||||||
storage::ApiKey::find_optional_by_merchant_id_key_id(&conn, merchant_id, key_id)
|
storage::ApiKey::find_optional_by_merchant_id_key_id(&conn, merchant_id, key_id)
|
||||||
@ -240,7 +242,7 @@ impl ApiKeyInterface for MockDb {
|
|||||||
async fn update_api_key(
|
async fn update_api_key(
|
||||||
&self,
|
&self,
|
||||||
merchant_id: common_utils::id_type::MerchantId,
|
merchant_id: common_utils::id_type::MerchantId,
|
||||||
key_id: String,
|
key_id: common_utils::id_type::ApiKeyId,
|
||||||
api_key: storage::ApiKeyUpdate,
|
api_key: storage::ApiKeyUpdate,
|
||||||
) -> CustomResult<storage::ApiKey, errors::StorageError> {
|
) -> CustomResult<storage::ApiKey, errors::StorageError> {
|
||||||
let mut locked_api_keys = self.api_keys.lock().await;
|
let mut locked_api_keys = self.api_keys.lock().await;
|
||||||
@ -282,13 +284,13 @@ impl ApiKeyInterface for MockDb {
|
|||||||
async fn revoke_api_key(
|
async fn revoke_api_key(
|
||||||
&self,
|
&self,
|
||||||
merchant_id: &common_utils::id_type::MerchantId,
|
merchant_id: &common_utils::id_type::MerchantId,
|
||||||
key_id: &str,
|
key_id: &common_utils::id_type::ApiKeyId,
|
||||||
) -> CustomResult<bool, errors::StorageError> {
|
) -> CustomResult<bool, errors::StorageError> {
|
||||||
let mut locked_api_keys = self.api_keys.lock().await;
|
let mut locked_api_keys = self.api_keys.lock().await;
|
||||||
// find the key to remove, if it exists
|
// find the key to remove, if it exists
|
||||||
if let Some(pos) = locked_api_keys
|
if let Some(pos) = locked_api_keys
|
||||||
.iter()
|
.iter()
|
||||||
.position(|k| k.merchant_id == *merchant_id && k.key_id == key_id)
|
.position(|k| k.merchant_id == *merchant_id && k.key_id == *key_id)
|
||||||
{
|
{
|
||||||
// use `remove` instead of `swap_remove` so we have a consistent order, which might
|
// use `remove` instead of `swap_remove` so we have a consistent order, which might
|
||||||
// matter to someone using limit/offset in `list_api_keys_by_merchant_id`
|
// matter to someone using limit/offset in `list_api_keys_by_merchant_id`
|
||||||
@ -302,14 +304,14 @@ impl ApiKeyInterface for MockDb {
|
|||||||
async fn find_api_key_by_merchant_id_key_id_optional(
|
async fn find_api_key_by_merchant_id_key_id_optional(
|
||||||
&self,
|
&self,
|
||||||
merchant_id: &common_utils::id_type::MerchantId,
|
merchant_id: &common_utils::id_type::MerchantId,
|
||||||
key_id: &str,
|
key_id: &common_utils::id_type::ApiKeyId,
|
||||||
) -> CustomResult<Option<storage::ApiKey>, errors::StorageError> {
|
) -> CustomResult<Option<storage::ApiKey>, errors::StorageError> {
|
||||||
Ok(self
|
Ok(self
|
||||||
.api_keys
|
.api_keys
|
||||||
.lock()
|
.lock()
|
||||||
.await
|
.await
|
||||||
.iter()
|
.iter()
|
||||||
.find(|k| k.merchant_id == *merchant_id && k.key_id == key_id)
|
.find(|k| k.merchant_id == *merchant_id && k.key_id == *key_id)
|
||||||
.cloned())
|
.cloned())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -397,9 +399,16 @@ mod tests {
|
|||||||
let merchant_id =
|
let merchant_id =
|
||||||
common_utils::id_type::MerchantId::try_from(Cow::from("merchant1")).unwrap();
|
common_utils::id_type::MerchantId::try_from(Cow::from("merchant1")).unwrap();
|
||||||
|
|
||||||
|
let key_id1 = common_utils::id_type::ApiKeyId::try_from(Cow::from("key_id1")).unwrap();
|
||||||
|
|
||||||
|
let key_id2 = common_utils::id_type::ApiKeyId::try_from(Cow::from("key_id2")).unwrap();
|
||||||
|
|
||||||
|
let non_existent_key_id =
|
||||||
|
common_utils::id_type::ApiKeyId::try_from(Cow::from("does_not_exist")).unwrap();
|
||||||
|
|
||||||
let key1 = mockdb
|
let key1 = mockdb
|
||||||
.insert_api_key(storage::ApiKeyNew {
|
.insert_api_key(storage::ApiKeyNew {
|
||||||
key_id: "key_id1".into(),
|
key_id: key_id1.clone(),
|
||||||
merchant_id: merchant_id.clone(),
|
merchant_id: merchant_id.clone(),
|
||||||
name: "Key 1".into(),
|
name: "Key 1".into(),
|
||||||
description: None,
|
description: None,
|
||||||
@ -414,7 +423,7 @@ mod tests {
|
|||||||
|
|
||||||
mockdb
|
mockdb
|
||||||
.insert_api_key(storage::ApiKeyNew {
|
.insert_api_key(storage::ApiKeyNew {
|
||||||
key_id: "key_id2".into(),
|
key_id: key_id2.clone(),
|
||||||
merchant_id: merchant_id.clone(),
|
merchant_id: merchant_id.clone(),
|
||||||
name: "Key 2".into(),
|
name: "Key 2".into(),
|
||||||
description: None,
|
description: None,
|
||||||
@ -428,13 +437,13 @@ mod tests {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let found_key1 = mockdb
|
let found_key1 = mockdb
|
||||||
.find_api_key_by_merchant_id_key_id_optional(&merchant_id, "key_id1")
|
.find_api_key_by_merchant_id_key_id_optional(&merchant_id, &key_id1)
|
||||||
.await
|
.await
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_eq!(found_key1.key_id, key1.key_id);
|
assert_eq!(found_key1.key_id, key1.key_id);
|
||||||
assert!(mockdb
|
assert!(mockdb
|
||||||
.find_api_key_by_merchant_id_key_id_optional(&merchant_id, "does_not_exist")
|
.find_api_key_by_merchant_id_key_id_optional(&merchant_id, &non_existent_key_id)
|
||||||
.await
|
.await
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.is_none());
|
.is_none());
|
||||||
@ -442,7 +451,7 @@ mod tests {
|
|||||||
mockdb
|
mockdb
|
||||||
.update_api_key(
|
.update_api_key(
|
||||||
merchant_id.clone(),
|
merchant_id.clone(),
|
||||||
"key_id1".into(),
|
key_id1.clone(),
|
||||||
storage::ApiKeyUpdate::LastUsedUpdate {
|
storage::ApiKeyUpdate::LastUsedUpdate {
|
||||||
last_used: datetime!(2023-02-04 1:11),
|
last_used: datetime!(2023-02-04 1:11),
|
||||||
},
|
},
|
||||||
@ -450,7 +459,7 @@ mod tests {
|
|||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let updated_key1 = mockdb
|
let updated_key1 = mockdb
|
||||||
.find_api_key_by_merchant_id_key_id_optional(&merchant_id, "key_id1")
|
.find_api_key_by_merchant_id_key_id_optional(&merchant_id, &key_id1)
|
||||||
.await
|
.await
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@ -464,10 +473,7 @@ mod tests {
|
|||||||
.len(),
|
.len(),
|
||||||
2
|
2
|
||||||
);
|
);
|
||||||
mockdb
|
mockdb.revoke_api_key(&merchant_id, &key_id1).await.unwrap();
|
||||||
.revoke_api_key(&merchant_id, "key_id1")
|
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
mockdb
|
mockdb
|
||||||
.list_api_keys_by_merchant_id(&merchant_id, None, None)
|
.list_api_keys_by_merchant_id(&merchant_id, None, None)
|
||||||
@ -495,8 +501,10 @@ mod tests {
|
|||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
let test_key = common_utils::id_type::ApiKeyId::try_from(Cow::from("test_ey")).unwrap();
|
||||||
|
|
||||||
let api = storage::ApiKeyNew {
|
let api = storage::ApiKeyNew {
|
||||||
key_id: "test_key".into(),
|
key_id: test_key.clone(),
|
||||||
merchant_id: merchant_id.clone(),
|
merchant_id: merchant_id.clone(),
|
||||||
name: "My test key".into(),
|
name: "My test key".into(),
|
||||||
description: None,
|
description: None,
|
||||||
|
|||||||
@ -226,7 +226,7 @@ impl ApiKeyInterface for KafkaStore {
|
|||||||
async fn update_api_key(
|
async fn update_api_key(
|
||||||
&self,
|
&self,
|
||||||
merchant_id: id_type::MerchantId,
|
merchant_id: id_type::MerchantId,
|
||||||
key_id: String,
|
key_id: id_type::ApiKeyId,
|
||||||
api_key: storage::ApiKeyUpdate,
|
api_key: storage::ApiKeyUpdate,
|
||||||
) -> CustomResult<storage::ApiKey, errors::StorageError> {
|
) -> CustomResult<storage::ApiKey, errors::StorageError> {
|
||||||
self.diesel_store
|
self.diesel_store
|
||||||
@ -237,7 +237,7 @@ impl ApiKeyInterface for KafkaStore {
|
|||||||
async fn revoke_api_key(
|
async fn revoke_api_key(
|
||||||
&self,
|
&self,
|
||||||
merchant_id: &id_type::MerchantId,
|
merchant_id: &id_type::MerchantId,
|
||||||
key_id: &str,
|
key_id: &id_type::ApiKeyId,
|
||||||
) -> CustomResult<bool, errors::StorageError> {
|
) -> CustomResult<bool, errors::StorageError> {
|
||||||
self.diesel_store.revoke_api_key(merchant_id, key_id).await
|
self.diesel_store.revoke_api_key(merchant_id, key_id).await
|
||||||
}
|
}
|
||||||
@ -245,7 +245,7 @@ impl ApiKeyInterface for KafkaStore {
|
|||||||
async fn find_api_key_by_merchant_id_key_id_optional(
|
async fn find_api_key_by_merchant_id_key_id_optional(
|
||||||
&self,
|
&self,
|
||||||
merchant_id: &id_type::MerchantId,
|
merchant_id: &id_type::MerchantId,
|
||||||
key_id: &str,
|
key_id: &id_type::ApiKeyId,
|
||||||
) -> CustomResult<Option<storage::ApiKey>, errors::StorageError> {
|
) -> CustomResult<Option<storage::ApiKey>, errors::StorageError> {
|
||||||
self.diesel_store
|
self.diesel_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)
|
||||||
|
|||||||
@ -79,7 +79,7 @@ pub async fn api_key_create(
|
|||||||
pub async fn api_key_retrieve(
|
pub async fn api_key_retrieve(
|
||||||
state: web::Data<AppState>,
|
state: web::Data<AppState>,
|
||||||
req: HttpRequest,
|
req: HttpRequest,
|
||||||
path: web::Path<String>,
|
path: web::Path<common_utils::id_type::ApiKeyId>,
|
||||||
) -> impl Responder {
|
) -> impl Responder {
|
||||||
let flow = Flow::ApiKeyRetrieve;
|
let flow = Flow::ApiKeyRetrieve;
|
||||||
let key_id = path.into_inner();
|
let key_id = path.into_inner();
|
||||||
@ -93,7 +93,7 @@ pub async fn api_key_retrieve(
|
|||||||
api_keys::retrieve_api_key(
|
api_keys::retrieve_api_key(
|
||||||
state,
|
state,
|
||||||
auth_data.merchant_account.get_id().to_owned(),
|
auth_data.merchant_account.get_id().to_owned(),
|
||||||
key_id,
|
key_id.to_owned(),
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
auth::auth_type(
|
auth::auth_type(
|
||||||
@ -114,7 +114,10 @@ pub async fn api_key_retrieve(
|
|||||||
pub async fn api_key_retrieve(
|
pub async fn api_key_retrieve(
|
||||||
state: web::Data<AppState>,
|
state: web::Data<AppState>,
|
||||||
req: HttpRequest,
|
req: HttpRequest,
|
||||||
path: web::Path<(common_utils::id_type::MerchantId, String)>,
|
path: web::Path<(
|
||||||
|
common_utils::id_type::MerchantId,
|
||||||
|
common_utils::id_type::ApiKeyId,
|
||||||
|
)>,
|
||||||
) -> impl Responder {
|
) -> impl Responder {
|
||||||
let flow = Flow::ApiKeyRetrieve;
|
let flow = Flow::ApiKeyRetrieve;
|
||||||
let (merchant_id, key_id) = path.into_inner();
|
let (merchant_id, key_id) = path.into_inner();
|
||||||
@ -123,7 +126,7 @@ pub async fn api_key_retrieve(
|
|||||||
flow,
|
flow,
|
||||||
state,
|
state,
|
||||||
&req,
|
&req,
|
||||||
(merchant_id.clone(), &key_id),
|
(merchant_id.clone(), key_id.clone()),
|
||||||
|state, _, (merchant_id, key_id), _| api_keys::retrieve_api_key(state, merchant_id, key_id),
|
|state, _, (merchant_id, key_id), _| api_keys::retrieve_api_key(state, merchant_id, key_id),
|
||||||
auth::auth_type(
|
auth::auth_type(
|
||||||
&auth::AdminApiAuth,
|
&auth::AdminApiAuth,
|
||||||
@ -144,7 +147,10 @@ pub async fn api_key_retrieve(
|
|||||||
pub async fn api_key_update(
|
pub async fn api_key_update(
|
||||||
state: web::Data<AppState>,
|
state: web::Data<AppState>,
|
||||||
req: HttpRequest,
|
req: HttpRequest,
|
||||||
path: web::Path<(common_utils::id_type::MerchantId, String)>,
|
path: web::Path<(
|
||||||
|
common_utils::id_type::MerchantId,
|
||||||
|
common_utils::id_type::ApiKeyId,
|
||||||
|
)>,
|
||||||
json_payload: web::Json<api_types::UpdateApiKeyRequest>,
|
json_payload: web::Json<api_types::UpdateApiKeyRequest>,
|
||||||
) -> impl Responder {
|
) -> impl Responder {
|
||||||
let flow = Flow::ApiKeyUpdate;
|
let flow = Flow::ApiKeyUpdate;
|
||||||
@ -177,7 +183,7 @@ pub async fn api_key_update(
|
|||||||
pub async fn api_key_update(
|
pub async fn api_key_update(
|
||||||
state: web::Data<AppState>,
|
state: web::Data<AppState>,
|
||||||
req: HttpRequest,
|
req: HttpRequest,
|
||||||
key_id: web::Path<String>,
|
key_id: web::Path<common_utils::id_type::ApiKeyId>,
|
||||||
json_payload: web::Json<api_types::UpdateApiKeyRequest>,
|
json_payload: web::Json<api_types::UpdateApiKeyRequest>,
|
||||||
) -> impl Responder {
|
) -> impl Responder {
|
||||||
let flow = Flow::ApiKeyUpdate;
|
let flow = Flow::ApiKeyUpdate;
|
||||||
@ -212,7 +218,10 @@ pub async fn api_key_update(
|
|||||||
pub async fn api_key_revoke(
|
pub async fn api_key_revoke(
|
||||||
state: web::Data<AppState>,
|
state: web::Data<AppState>,
|
||||||
req: HttpRequest,
|
req: HttpRequest,
|
||||||
path: web::Path<(common_utils::id_type::MerchantId, String)>,
|
path: web::Path<(
|
||||||
|
common_utils::id_type::MerchantId,
|
||||||
|
common_utils::id_type::ApiKeyId,
|
||||||
|
)>,
|
||||||
) -> impl Responder {
|
) -> impl Responder {
|
||||||
let flow = Flow::ApiKeyRevoke;
|
let flow = Flow::ApiKeyRevoke;
|
||||||
let (merchant_id, key_id) = path.into_inner();
|
let (merchant_id, key_id) = path.into_inner();
|
||||||
@ -242,7 +251,10 @@ pub async fn api_key_revoke(
|
|||||||
pub async fn api_key_revoke(
|
pub async fn api_key_revoke(
|
||||||
state: web::Data<AppState>,
|
state: web::Data<AppState>,
|
||||||
req: HttpRequest,
|
req: HttpRequest,
|
||||||
path: web::Path<(common_utils::id_type::MerchantId, String)>,
|
path: web::Path<(
|
||||||
|
common_utils::id_type::MerchantId,
|
||||||
|
common_utils::id_type::ApiKeyId,
|
||||||
|
)>,
|
||||||
) -> impl Responder {
|
) -> impl Responder {
|
||||||
let flow = Flow::ApiKeyRevoke;
|
let flow = Flow::ApiKeyRevoke;
|
||||||
let (merchant_id, key_id) = path.into_inner();
|
let (merchant_id, key_id) = path.into_inner();
|
||||||
|
|||||||
@ -89,7 +89,7 @@ pub struct AuthenticationDataWithUser {
|
|||||||
pub enum AuthenticationType {
|
pub enum AuthenticationType {
|
||||||
ApiKey {
|
ApiKey {
|
||||||
merchant_id: id_type::MerchantId,
|
merchant_id: id_type::MerchantId,
|
||||||
key_id: String,
|
key_id: id_type::ApiKeyId,
|
||||||
},
|
},
|
||||||
AdminApiKey,
|
AdminApiKey,
|
||||||
AdminApiAuthWithMerchantId {
|
AdminApiAuthWithMerchantId {
|
||||||
|
|||||||
@ -67,7 +67,7 @@ pub enum Identifiers {
|
|||||||
/// [`ApiKey`] is an authentication method that uses an API key. This is used with [`ApiKey`]
|
/// [`ApiKey`] is an authentication method that uses an API key. This is used with [`ApiKey`]
|
||||||
ApiKey {
|
ApiKey {
|
||||||
merchant_id: common_utils::id_type::MerchantId,
|
merchant_id: common_utils::id_type::MerchantId,
|
||||||
key_id: String,
|
key_id: common_utils::id_type::ApiKeyId,
|
||||||
},
|
},
|
||||||
/// [`PublishableKey`] is an authentication method that uses a publishable key. This is used with [`PublishableKey`]
|
/// [`PublishableKey`] is an authentication method that uses a publishable key. This is used with [`PublishableKey`]
|
||||||
PublishableKey { merchant_id: String },
|
PublishableKey { merchant_id: String },
|
||||||
@ -80,7 +80,7 @@ pub async fn add_api_key(
|
|||||||
state: &SessionState,
|
state: &SessionState,
|
||||||
api_key: Secret<String>,
|
api_key: Secret<String>,
|
||||||
merchant_id: common_utils::id_type::MerchantId,
|
merchant_id: common_utils::id_type::MerchantId,
|
||||||
key_id: String,
|
key_id: common_utils::id_type::ApiKeyId,
|
||||||
expiry: Option<u64>,
|
expiry: Option<u64>,
|
||||||
) -> CustomResult<(), ApiClientError> {
|
) -> CustomResult<(), ApiClientError> {
|
||||||
let decision_config = if let Some(config) = &state.conf.decision {
|
let decision_config = if let Some(config) = &state.conf.decision {
|
||||||
|
|||||||
@ -1,7 +1,10 @@
|
|||||||
use std::{borrow::Cow, string::ToString};
|
use std::{borrow::Cow, string::ToString};
|
||||||
|
|
||||||
use actix_web::http::header::HeaderMap;
|
use actix_web::http::header::HeaderMap;
|
||||||
use common_utils::{crypto::VerifySignature, id_type::MerchantId};
|
use common_utils::{
|
||||||
|
crypto::VerifySignature,
|
||||||
|
id_type::{ApiKeyId, MerchantId},
|
||||||
|
};
|
||||||
use error_stack::ResultExt;
|
use error_stack::ResultExt;
|
||||||
use hyperswitch_domain_models::errors::api_error_response::ApiErrorResponse;
|
use hyperswitch_domain_models::errors::api_error_response::ApiErrorResponse;
|
||||||
|
|
||||||
@ -16,7 +19,7 @@ const HEADER_CHECKSUM: &str = "x-checksum";
|
|||||||
pub struct ExtractedPayload {
|
pub struct ExtractedPayload {
|
||||||
pub payload_type: PayloadType,
|
pub payload_type: PayloadType,
|
||||||
pub merchant_id: Option<MerchantId>,
|
pub merchant_id: Option<MerchantId>,
|
||||||
pub key_id: Option<String>,
|
pub key_id: Option<ApiKeyId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(strum::EnumString, strum::Display, PartialEq, Debug)]
|
#[derive(strum::EnumString, strum::Display, PartialEq, Debug)]
|
||||||
@ -61,13 +64,19 @@ impl ExtractedPayload {
|
|||||||
message: format!("`{}` header not present", HEADER_AUTH_TYPE),
|
message: format!("`{}` header not present", HEADER_AUTH_TYPE),
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
|
let key_id = headers
|
||||||
|
.get(HEADER_KEY_ID)
|
||||||
|
.and_then(|value| value.to_str().ok())
|
||||||
|
.map(|key_id| ApiKeyId::try_from(Cow::from(key_id.to_string())))
|
||||||
|
.transpose()
|
||||||
|
.change_context(ApiErrorResponse::InvalidRequestData {
|
||||||
|
message: format!("`{}` header is invalid or not present", HEADER_KEY_ID),
|
||||||
|
})?;
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
payload_type: auth_type,
|
payload_type: auth_type,
|
||||||
merchant_id: Some(merchant_id),
|
merchant_id: Some(merchant_id),
|
||||||
key_id: headers
|
key_id,
|
||||||
.get(HEADER_KEY_ID)
|
|
||||||
.and_then(|v| v.to_str().ok())
|
|
||||||
.map(|v| v.to_string()),
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,7 +104,7 @@ impl ExtractedPayload {
|
|||||||
&self
|
&self
|
||||||
.merchant_id
|
.merchant_id
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|inner| append_option(inner.get_string_repr(), &self.key_id)),
|
.map(|inner| append_api_key(inner.get_string_repr(), &self.key_id)),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -107,3 +116,11 @@ fn append_option(prefix: &str, data: &Option<String>) -> String {
|
|||||||
None => prefix.to_string(),
|
None => prefix.to_string(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn append_api_key(prefix: &str, data: &Option<ApiKeyId>) -> String {
|
||||||
|
match data {
|
||||||
|
Some(inner) => format!("{}:{}", prefix, inner.get_string_repr()),
|
||||||
|
None => prefix.to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user