-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(recon): add merchant and profile IDs in auth tokens (#5643)
Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com>
- Loading branch information
1 parent
36cd5c1
commit d9485a5
Showing
30 changed files
with
336 additions
and
336 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -133,7 +133,6 @@ bg_metrics_collection_interval_in_secs = 15 # Interval for collecting | |
master_enc_key = "sample_key" # Master Encryption key used to encrypt merchant wise encryption key. Should be 32-byte long. | ||
admin_api_key = "test_admin" # admin API key for admin authentication. | ||
jwt_secret = "secret" # JWT secret used for user authentication. | ||
recon_admin_api_key = "recon_test_admin" # recon_admin API key for recon authentication. | ||
|
||
# Locker settings contain details for accessing a card locker, a | ||
# PCI Compliant storage entity which stores payment method information | ||
|
@@ -722,4 +721,7 @@ public = { name = "hyperswitch", base_url = "http://localhost:8080", schema = "p | |
encryption_key = "" # Encryption key used for encrypting data in user_authentication_methods table | ||
|
||
[locker_based_open_banking_connectors] | ||
connector_list = "" | ||
connector_list = "" | ||
|
||
[recipient_emails] | ||
recon = "[email protected]" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -256,7 +256,6 @@ url = "http://localhost:5000" # URL of the encryption service | |
master_enc_key = "sample_key" # Master Encryption key used to encrypt merchant wise encryption key. Should be 32-byte long. | ||
admin_api_key = "test_admin" # admin API key for admin authentication. | ||
jwt_secret = "secret" # JWT secret used for user authentication. | ||
recon_admin_api_key = "recon_test_admin" # recon_admin API key for recon authentication. | ||
|
||
# Server configuration | ||
[server] | ||
|
@@ -300,3 +299,6 @@ public = { name = "hyperswitch", base_url = "http://localhost:8080", schema = "p | |
|
||
[user_auth_methods] | ||
encryption_key = "user_auth_table_encryption_key" # Encryption key used for encrypting data in user_authentication_methods table | ||
|
||
[recipient_emails] | ||
recon = "[email protected]" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -61,7 +61,6 @@ request_body_limit = 32768 | |
admin_api_key = "test_admin" | ||
master_enc_key = "73ad7bbbbc640c845a150f67d058b279849370cd2c1f3c67c4dd6c869213e13a" | ||
jwt_secret = "secret" | ||
recon_admin_api_key = "recon_test_admin" | ||
|
||
[applepay_merchant_configs] | ||
merchant_cert_key = "MERCHANT CERTIFICATE KEY" | ||
|
@@ -727,3 +726,6 @@ encryption_key = "A8EF32E029BC3342E54BF2E172A4D7AA43E8EF9D2C3A624A9F04E2EF79DC69 | |
|
||
[locker_based_open_banking_connectors] | ||
connector_list = "" | ||
|
||
[recipient_emails] | ||
recon = "[email protected]" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -50,7 +50,6 @@ pool_size = 5 | |
admin_api_key = "test_admin" | ||
jwt_secret = "secret" | ||
master_enc_key = "73ad7bbbbc640c845a150f67d058b279849370cd2c1f3c67c4dd6c869213e13a" | ||
recon_admin_api_key = "recon_test_admin" | ||
|
||
[user] | ||
password_validity_in_days = 90 | ||
|
@@ -586,3 +585,6 @@ ach = { country = "US", currency = "USD" } | |
|
||
[locker_based_open_banking_connectors] | ||
connector_list = "" | ||
|
||
[recipient_emails] | ||
recon = "[email protected]" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,172 @@ | ||
use api_models::recon as recon_api; | ||
use common_utils::ext_traits::AsyncExt; | ||
use error_stack::ResultExt; | ||
use masking::{ExposeInterface, PeekInterface, Secret}; | ||
|
||
use crate::{ | ||
consts, | ||
core::errors::{self, RouterResponse, UserErrors}, | ||
services::{api as service_api, authentication, email::types as email_types}, | ||
types::{ | ||
api::{self as api_types, enums}, | ||
domain, storage, | ||
transformers::ForeignTryFrom, | ||
}, | ||
SessionState, | ||
}; | ||
|
||
pub async fn send_recon_request( | ||
state: SessionState, | ||
user_with_auth_data: authentication::UserFromTokenWithAuthData, | ||
) -> RouterResponse<recon_api::ReconStatusResponse> { | ||
let user = user_with_auth_data.0; | ||
let user_in_db = &user_with_auth_data.1.user; | ||
let merchant_id = user.merchant_id; | ||
|
||
let user_email = user_in_db.email.clone(); | ||
let email_contents = email_types::ProFeatureRequest { | ||
feature_name: consts::RECON_FEATURE_TAG.to_string(), | ||
merchant_id: merchant_id.clone(), | ||
user_name: domain::UserName::new(user_in_db.name.clone()) | ||
.change_context(errors::ApiErrorResponse::InternalServerError) | ||
.attach_printable("Failed to form username")?, | ||
user_email: domain::UserEmail::from_pii_email(user_email.clone()) | ||
.change_context(errors::ApiErrorResponse::InternalServerError) | ||
.attach_printable("Failed to convert recipient's email to UserEmail")?, | ||
recipient_email: domain::UserEmail::from_pii_email( | ||
state.conf.recipient_emails.recon.clone(), | ||
) | ||
.change_context(errors::ApiErrorResponse::InternalServerError) | ||
.attach_printable("Failed to convert recipient's email to UserEmail")?, | ||
settings: state.conf.clone(), | ||
subject: format!( | ||
"Dashboard Pro Feature Request by {}", | ||
user_email.expose().peek() | ||
), | ||
}; | ||
|
||
state | ||
.email_client | ||
.compose_and_send_email( | ||
Box::new(email_contents), | ||
state.conf.proxy.https_url.as_ref(), | ||
) | ||
.await | ||
.change_context(errors::ApiErrorResponse::InternalServerError) | ||
.attach_printable("Failed to compose and send email for ProFeatureRequest [Recon]") | ||
.async_and_then(|_| async { | ||
let auth = user_with_auth_data.1; | ||
let updated_merchant_account = storage::MerchantAccountUpdate::ReconUpdate { | ||
recon_status: enums::ReconStatus::Requested, | ||
}; | ||
let db = &*state.store; | ||
let key_manager_state = &(&state).into(); | ||
|
||
let response = db | ||
.update_merchant( | ||
key_manager_state, | ||
auth.merchant_account, | ||
updated_merchant_account, | ||
&auth.key_store, | ||
) | ||
.await | ||
.change_context(errors::ApiErrorResponse::InternalServerError) | ||
.attach_printable_lazy(|| { | ||
format!("Failed while updating merchant's recon status: {merchant_id:?}") | ||
})?; | ||
|
||
Ok(service_api::ApplicationResponse::Json( | ||
recon_api::ReconStatusResponse { | ||
recon_status: response.recon_status, | ||
}, | ||
)) | ||
}) | ||
.await | ||
} | ||
|
||
pub async fn generate_recon_token( | ||
state: SessionState, | ||
user: authentication::UserFromToken, | ||
) -> RouterResponse<recon_api::ReconTokenResponse> { | ||
let token = authentication::AuthToken::new_token( | ||
user.user_id.clone(), | ||
user.merchant_id.clone(), | ||
user.role_id.clone(), | ||
&state.conf, | ||
user.org_id.clone(), | ||
user.profile_id.clone(), | ||
) | ||
.await | ||
.change_context(errors::ApiErrorResponse::InternalServerError) | ||
.attach_printable_lazy(|| { | ||
format!( | ||
"Failed to create recon token for params [user_id, org_id, mid, pid] [{}, {:?}, {:?}, {:?}]", | ||
user.user_id, user.org_id, user.merchant_id, user.profile_id, | ||
) | ||
})?; | ||
|
||
Ok(service_api::ApplicationResponse::Json( | ||
recon_api::ReconTokenResponse { | ||
token: token.into(), | ||
}, | ||
)) | ||
} | ||
|
||
pub async fn recon_merchant_account_update( | ||
state: SessionState, | ||
auth: authentication::AuthenticationData, | ||
req: recon_api::ReconUpdateMerchantRequest, | ||
) -> RouterResponse<api_types::MerchantAccountResponse> { | ||
let db = &*state.store; | ||
let key_manager_state = &(&state).into(); | ||
|
||
let updated_merchant_account = storage::MerchantAccountUpdate::ReconUpdate { | ||
recon_status: req.recon_status, | ||
}; | ||
let merchant_id = auth.merchant_account.get_id().clone(); | ||
|
||
let updated_merchant_account = db | ||
.update_merchant( | ||
key_manager_state, | ||
auth.merchant_account, | ||
updated_merchant_account, | ||
&auth.key_store, | ||
) | ||
.await | ||
.change_context(errors::ApiErrorResponse::InternalServerError) | ||
.attach_printable_lazy(|| { | ||
format!("Failed while updating merchant's recon status: {merchant_id:?}") | ||
})?; | ||
|
||
let user_email = &req.user_email.clone(); | ||
let email_contents = email_types::ReconActivation { | ||
recipient_email: domain::UserEmail::from_pii_email(user_email.clone()) | ||
.change_context(errors::ApiErrorResponse::InternalServerError) | ||
.attach_printable("Failed to convert recipient's email to UserEmail from pii::Email")?, | ||
user_name: domain::UserName::new(Secret::new("HyperSwitch User".to_string())) | ||
.change_context(errors::ApiErrorResponse::InternalServerError) | ||
.attach_printable("Failed to form username")?, | ||
settings: state.conf.clone(), | ||
subject: "Approval of Recon Request - Access Granted to Recon Dashboard", | ||
}; | ||
|
||
if req.recon_status == enums::ReconStatus::Active { | ||
let _ = state | ||
.email_client | ||
.compose_and_send_email( | ||
Box::new(email_contents), | ||
state.conf.proxy.https_url.as_ref(), | ||
) | ||
.await | ||
.change_context(UserErrors::InternalServerError) | ||
.attach_printable("Failed to compose and send email for ReconActivation") | ||
.is_ok(); | ||
} | ||
|
||
Ok(service_api::ApplicationResponse::Json( | ||
api_types::MerchantAccountResponse::foreign_try_from(updated_merchant_account) | ||
.change_context(errors::ApiErrorResponse::InvalidDataValue { | ||
field_name: "merchant_account", | ||
})?, | ||
)) | ||
} |
Oops, something went wrong.