Skip to content

Commit

Permalink
Merge branch 'main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
Himanshu-370 authored Oct 21, 2023
2 parents 4700955 + 31431e4 commit f4190cd
Show file tree
Hide file tree
Showing 12 changed files with 121 additions and 18 deletions.
19 changes: 19 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,25 @@ All notable changes to HyperSwitch will be documented here.

- - -

## 1.63.0 (2023-10-20)

### Features

- Add support for updating surcharge_applicable field intent ([#2647](https://github.com/juspay/hyperswitch/pull/2647)) ([`949937e`](https://github.com/juspay/hyperswitch/commit/949937e3644346f8b2b952944efb884f270645a8))

### Bug Fixes

- Kms decryption of redis_temp_locker_encryption_key ([#2650](https://github.com/juspay/hyperswitch/pull/2650)) ([`5a6601f`](https://github.com/juspay/hyperswitch/commit/5a6601fad4d11cd7d2f1322a6453504494d20c6f))

### Refactors

- **router:** [Nexi nets] Remove Default Case Handling ([#2639](https://github.com/juspay/hyperswitch/pull/2639)) ([`4b64c56`](https://github.com/juspay/hyperswitch/commit/4b64c563558d7c0a02b248c23921ed47ff294980))

**Full Changelog:** [`v1.62.0...v1.63.0`](https://github.com/juspay/hyperswitch/compare/v1.62.0...v1.63.0)

- - -


## 1.62.0 (2023-10-19)

### Features
Expand Down
13 changes: 11 additions & 2 deletions crates/common_utils/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,11 +77,20 @@ pub enum QrCodeError {
}

/// Api Models construction error
#[derive(Debug, Clone, thiserror::Error, PartialEq, Eq)]
pub enum ApiModelsError {
#[derive(Debug, Clone, thiserror::Error, PartialEq)]
pub enum PercentageError {
/// Percentage Value provided was invalid
#[error("Invalid Percentage value")]
InvalidPercentageValue,

/// Error occurred while calculating percentage
#[error("Failed apply percentage of {percentage} on {amount}")]
UnableToApplyPercentage {
/// percentage value
percentage: f32,
/// amount value
amount: i64,
},
}

/// Allows [error_stack::Report] to change between error contexts
Expand Down
36 changes: 29 additions & 7 deletions crates/common_utils/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
use error_stack::{IntoReport, ResultExt};
use serde::{de::Visitor, Deserialize, Deserializer};

use crate::errors::{ApiModelsError, CustomResult};
use crate::errors::{CustomResult, PercentageError};

/// Represents Percentage Value between 0 and 100 both inclusive
#[derive(Clone, Default, Debug, PartialEq, serde::Serialize)]
Expand All @@ -21,32 +21,54 @@ fn get_invalid_percentage_error_message(precision: u8) -> String {

impl<const PRECISION: u8> Percentage<PRECISION> {
/// construct percentage using a string representation of float value
pub fn from_string(value: String) -> CustomResult<Self, ApiModelsError> {
pub fn from_string(value: String) -> CustomResult<Self, PercentageError> {
if Self::is_valid_string_value(&value)? {
Ok(Self {
percentage: value
.parse()
.into_report()
.change_context(ApiModelsError::InvalidPercentageValue)?,
.change_context(PercentageError::InvalidPercentageValue)?,
})
} else {
Err(ApiModelsError::InvalidPercentageValue.into())
Err(PercentageError::InvalidPercentageValue.into())
.attach_printable(get_invalid_percentage_error_message(PRECISION))
}
}
/// function to get percentage value
pub fn get_percentage(&self) -> f32 {
self.percentage
}
fn is_valid_string_value(value: &str) -> CustomResult<bool, ApiModelsError> {

/// apply the percentage to amount and ceil the result
#[allow(clippy::as_conversions)]
pub fn apply_and_ceil_result(&self, amount: i64) -> CustomResult<i64, PercentageError> {
let max_amount = i64::MAX / 10000;
if amount > max_amount {
// value gets rounded off after i64::MAX/10000
Err(PercentageError::UnableToApplyPercentage {
percentage: self.percentage,
amount,
}
.into())
.attach_printable(format!(
"Cannot calculate percentage for amount greater than {}",
max_amount
))
} else {
let percentage_f64 = f64::from(self.percentage);
let result = (amount as f64 * (percentage_f64 / 100.0)).ceil() as i64;
Ok(result)
}
}
fn is_valid_string_value(value: &str) -> CustomResult<bool, PercentageError> {
let float_value = Self::is_valid_float_string(value)?;
Ok(Self::is_valid_range(float_value) && Self::is_valid_precision_length(value))
}
fn is_valid_float_string(value: &str) -> CustomResult<f32, ApiModelsError> {
fn is_valid_float_string(value: &str) -> CustomResult<f32, PercentageError> {
value
.parse()
.into_report()
.change_context(ApiModelsError::InvalidPercentageValue)
.change_context(PercentageError::InvalidPercentageValue)
}
fn is_valid_range(value: f32) -> bool {
(0.0..=100.0).contains(&value)
Expand Down
10 changes: 5 additions & 5 deletions crates/common_utils/tests/percentage.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#![allow(clippy::panic_in_result_fn)]
use common_utils::{errors::ApiModelsError, types::Percentage};
use common_utils::{errors::PercentageError, types::Percentage};
const PRECISION_2: u8 = 2;
const PRECISION_0: u8 = 0;

Expand All @@ -10,7 +10,7 @@ fn invalid_range_more_than_100() -> Result<(), Box<dyn std::error::Error + Send
if let Err(err) = percentage {
assert_eq!(
*err.current_context(),
ApiModelsError::InvalidPercentageValue
PercentageError::InvalidPercentageValue
)
}
Ok(())
Expand All @@ -22,7 +22,7 @@ fn invalid_range_less_than_0() -> Result<(), Box<dyn std::error::Error + Send +
if let Err(err) = percentage {
assert_eq!(
*err.current_context(),
ApiModelsError::InvalidPercentageValue
PercentageError::InvalidPercentageValue
)
}
Ok(())
Expand All @@ -35,7 +35,7 @@ fn invalid_string() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
if let Err(err) = percentage {
assert_eq!(
*err.current_context(),
ApiModelsError::InvalidPercentageValue
PercentageError::InvalidPercentageValue
)
}
Ok(())
Expand Down Expand Up @@ -92,7 +92,7 @@ fn invalid_precision() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
if let Err(err) = percentage {
assert_eq!(
*err.current_context(),
ApiModelsError::InvalidPercentageValue
PercentageError::InvalidPercentageValue
)
}
Ok(())
Expand Down
12 changes: 12 additions & 0 deletions crates/data_models/src/payments/payment_intent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,10 @@ pub enum PaymentIntentUpdate {
merchant_decision: Option<String>,
updated_by: String,
},
SurchargeApplicableUpdate {
surcharge_applicable: bool,
updated_by: String,
},
}

#[derive(Clone, Debug, Default)]
Expand Down Expand Up @@ -386,6 +390,14 @@ impl From<PaymentIntentUpdate> for PaymentIntentUpdateInternal {
updated_by,
..Default::default()
},
PaymentIntentUpdate::SurchargeApplicableUpdate {
surcharge_applicable,
updated_by,
} => Self {
surcharge_applicable: Some(surcharge_applicable),
updated_by,
..Default::default()
},
}
}
}
Expand Down
12 changes: 12 additions & 0 deletions crates/diesel_models/src/payment_intent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,10 @@ pub enum PaymentIntentUpdate {
merchant_decision: Option<String>,
updated_by: String,
},
SurchargeApplicableUpdate {
surcharge_applicable: Option<bool>,
updated_by: String,
},
}

#[derive(Clone, Debug, Default, AsChangeset, router_derive::DebugAsDisplay)]
Expand Down Expand Up @@ -408,6 +412,14 @@ impl From<PaymentIntentUpdate> for PaymentIntentUpdateInternal {
updated_by,
..Default::default()
},
PaymentIntentUpdate::SurchargeApplicableUpdate {
surcharge_applicable,
updated_by,
} => Self {
surcharge_applicable,
updated_by,
..Default::default()
},
}
}
}
10 changes: 9 additions & 1 deletion crates/external_services/src/kms.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,14 @@ pub enum KmsError {
/// The KMS client has not been initialized.
#[error("The KMS client has not been initialized")]
KmsClientNotInitialized,

/// The KMS client has not been initialized.
#[error("Hex decode failed")]
HexDecodeFailed,

/// The KMS client has not been initialized.
#[error("Utf8 decode failed")]
Utf8DecodeFailed,
}

impl KmsConfig {
Expand All @@ -140,7 +148,7 @@ impl KmsConfig {
/// A wrapper around a KMS value that can be decrypted.
#[derive(Clone, Debug, Default, serde::Deserialize, Eq, PartialEq)]
#[serde(transparent)]
pub struct KmsValue(Secret<String>);
pub struct KmsValue(pub Secret<String>);

impl common_utils::ext_traits::ConfigExt for KmsValue {
fn is_empty_after_trim(&self) -> bool {
Expand Down
16 changes: 15 additions & 1 deletion crates/router/src/configs/kms.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use common_utils::errors::CustomResult;
use external_services::kms::{decrypt::KmsDecrypt, KmsClient, KmsError};
use error_stack::{IntoReport, ResultExt};
use external_services::kms::{decrypt::KmsDecrypt, KmsClient, KmsError, KmsValue};
use masking::ExposeInterface;

use crate::configs::settings;
Expand Down Expand Up @@ -41,6 +42,19 @@ impl KmsDecrypt for settings::ActiveKmsSecrets {
kms_client: &KmsClient,
) -> CustomResult<Self::Output, KmsError> {
self.jwekey = self.jwekey.expose().decrypt_inner(kms_client).await?.into();
self.redis_temp_locker_encryption_key = hex::decode(
KmsValue(
String::from_utf8(self.redis_temp_locker_encryption_key.expose())
.into_report()
.change_context(KmsError::Utf8DecodeFailed)?
.into(),
)
.decrypt_inner(kms_client)
.await?,
)
.into_report()
.change_context(KmsError::HexDecodeFailed)?
.into();
Ok(self)
}
}
Expand Down
2 changes: 1 addition & 1 deletion crates/router/src/configs/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ pub enum Subcommand {
#[derive(Clone)]
pub struct ActiveKmsSecrets {
pub jwekey: masking::Secret<Jwekey>,
pub redis_temp_locker_encryption_key: masking::Secret<String>,
pub redis_temp_locker_encryption_key: masking::Secret<Vec<u8>>,
}

#[derive(Debug, Deserialize, Clone, Default)]
Expand Down
1 change: 0 additions & 1 deletion crates/router/src/core/payment_methods/vault.rs
Original file line number Diff line number Diff line change
Expand Up @@ -721,7 +721,6 @@ fn get_redis_temp_locker_encryption_key(state: &routes::AppState) -> RouterResul
.kms_secrets
.redis_temp_locker_encryption_key
.peek()
.as_bytes()
.to_owned();

#[cfg(not(feature = "kms"))]
Expand Down
1 change: 1 addition & 0 deletions crates/router/src/routes/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ impl AppState {
.locker
.redis_temp_locker_encryption_key
.clone()
.into_bytes()
.into(),
}
.decrypt_inner(kms_client)
Expand Down
7 changes: 7 additions & 0 deletions crates/storage_impl/src/payments/payment_intent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1009,6 +1009,13 @@ impl DataModelExt for PaymentIntentUpdate {
merchant_decision,
updated_by,
},
Self::SurchargeApplicableUpdate {
surcharge_applicable,
updated_by,
} => DieselPaymentIntentUpdate::SurchargeApplicableUpdate {
surcharge_applicable: Some(surcharge_applicable),
updated_by,
},
}
}

Expand Down

0 comments on commit f4190cd

Please sign in to comment.