Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG] Add Create Merchant and Create Merchant Key Store in a DB transaction #1793

Closed
dracarys18 opened this issue Jul 26, 2023 · 9 comments · May be fixed by #2663
Closed

[BUG] Add Create Merchant and Create Merchant Key Store in a DB transaction #1793

dracarys18 opened this issue Jul 26, 2023 · 9 comments · May be fixed by #2663
Labels
A-framework Area: Framework C-bug Category: Bug C-refactor Category: Refactor good first issue Good for newcomers help wanted Extra attention is needed

Comments

@dracarys18
Copy link
Member

Currently MerchantAccount and MerchantKeyStore are getting inserted seperately. Since both of them are interdependent we need to make sure both are consistent with each other. If one of them fails other shouldn't get inserted.

We need to add this in a db_transaction

db.insert_merchant_key_store(key_store.clone(), &master_key.to_vec().into())
.await
.to_duplicate_response(errors::ApiErrorResponse::DuplicateMerchantAccount)?;
let parent_merchant_id = get_parent_merchant(
db,
req.sub_merchants_enabled,
req.parent_merchant_id,
&key_store,
)
.await?;
let merchant_account = async {
Ok(domain::MerchantAccount {
merchant_id: req.merchant_id,
merchant_name: req
.merchant_name
.async_lift(|inner| domain_types::encrypt_optional(inner, &key))
.await?,
merchant_details: merchant_details
.async_lift(|inner| domain_types::encrypt_optional(inner, &key))
.await?,
return_url: req.return_url.map(|a| a.to_string()),
webhook_details,
routing_algorithm: req.routing_algorithm,
sub_merchants_enabled: req.sub_merchants_enabled,
parent_merchant_id,
enable_payment_response_hash,
payment_response_hash_key,
redirect_to_merchant_with_http_post: req
.redirect_to_merchant_with_http_post
.unwrap_or_default(),
publishable_key,
locker_id: req.locker_id,
metadata: req.metadata,
storage_scheme: diesel_models::enums::MerchantStorageScheme::PostgresOnly,
primary_business_details,
created_at: date_time::now(),
modified_at: date_time::now(),
frm_routing_algorithm: req.frm_routing_algorithm,
intent_fulfillment_time: req.intent_fulfillment_time.map(i64::from),
payout_routing_algorithm: req.payout_routing_algorithm,
id: None,
organization_id: req.organization_id,
is_recon_enabled: false,
})
}
.await
.change_context(errors::ApiErrorResponse::InternalServerError)?;
let merchant_account = db
.insert_merchant(merchant_account, &key_store)
.await
.to_duplicate_response(errors::ApiErrorResponse::DuplicateMerchantAccount)?;

For reference of how to do it in a db transaction

  pool.transaction_async(|conn| async move {
        diesel::update(dsl::users)
            .filter(dsl::id.eq(0))
            .set(dsl::name.eq("Let's change the name again"))
            .execute_async(&conn)
            .await
            .map_err(|e| PoolError::Connection(e))
})
@dracarys18 dracarys18 added the good first issue Good for newcomers label Jul 26, 2023
@artech-git
Copy link

artech-git commented Aug 12, 2023

Hi @dracarys18 gonna take a look into this issue, also how can you tell me how should the conn.transaction_async() be performed should it be done undercreate_merchant_account itself, or should I modify the previous method insert_merchant_key_store under the trait MerchantKeyStoreInterface

I was experimenting with the logic and made changes in the following sections

impl MerchantKeyStoreInterface for Store {

    async fn insert_merchant_and_key_store(
        &self,
        merchant_account: domain::MerchantAccount,
        merchant_key_store: domain::MerchantKeyStore,
        key: &Secret<Vec<u8>>,
    ) -> CustomResult<domain::MerchantAccount, errors::StorageError> {
        let conn = connection::pg_connection_write(self).await?;
        
        let val = conn.transaction_async(|e| async move {
    
            merchant_key_store
                .construct_new()
                .await
                .change_context(errors::StorageError::EncryptionError)?
                .insert(&e)
                .await
                .map_err(Into::into)
                .into_report()?
                .convert(key)
                .await
                .change_context(errors::StorageError::DecryptionError);

            merchant_account
                .construct_new()
                .await
                .change_context(errors::StorageError::EncryptionError)?
                .insert(&e)
                .await
                .map_err(Into::into)
                .into_report()?
                .convert(merchant_key_store.key.get_inner())
                .await
                .change_context(errors::StorageError::DecryptionError)
        
        }).await;

        val
    }

do let me know your thoughts about the approach

@dracarys18
Copy link
Member Author

Hey @artech-git I would prefer keeping the Store interface seperate for MerchantKeyStore and MerchantAccount. i.e Store impl of MerchantKeystore will only insert into merchant_key_store table. So it would be better to do it in admin.rs as I mentioned in the issue.

@dracarys18
Copy link
Member Author

Hey @artech-git , Please let me know if you need any help in this

@dracarys18
Copy link
Member Author

Opening this issue for contributions because of inactivity.

@Azanul
Copy link
Contributor

Azanul commented Oct 17, 2023

May I take this up?

@SanchithHegde
Copy link
Member

Sure @Azanul, I'll assign this to you.

@SanchithHegde SanchithHegde added the hacktoberfest Issues that are up for grabs for Hacktoberfest participants label Oct 17, 2023
@Azanul
Copy link
Contributor

Azanul commented Oct 19, 2023

To do this in admin.rs, I think we would need access to the connection to underlying Store.
Is it exposed via a trait/method? I couldn't find it.

@dracarys18
Copy link
Member Author

Hey @Azanul in that case add it in MerchantAccountInterface in insert_merchant_account function. Since we don't want to insert MerchantAccount without inserting KeyStore.

@gorakhnathy7
Copy link
Collaborator

Closing this, as per inputs of @dracarys18

@SanchithHegde SanchithHegde removed the hacktoberfest Issues that are up for grabs for Hacktoberfest participants label Oct 6, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-framework Area: Framework C-bug Category: Bug C-refactor Category: Refactor good first issue Good for newcomers help wanted Extra attention is needed
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants