Skip to content

Commit

Permalink
Configuration api improvements (#826)
Browse files Browse the repository at this point in the history
* Adding configuration_hash and enabled to configuration response

* Test for new fields

* Use model-level hash

* Addressing PR comments

* docs on key reset
  • Loading branch information
mbianco-stripe authored Oct 3, 2022
1 parent 1bff76f commit d8cff8b
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 7 deletions.
5 changes: 2 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -361,9 +361,8 @@ TODO this may not be applicable anymore since we've removed the `.sfdx` folder f

## Resetting Salesforce Org Keys

- Debug console
- Anon Apex
- maintenanceUtilities.resetServiceConnection();
- Debug console > Debug > Open Execute Anonmous Window
- `maintenanceUtilities.resetServiceConnection();` or `QaStripeConnect.maintenanceUtilities.resetServiceConnection();` if in a packaged environment

# Development

Expand Down
7 changes: 7 additions & 0 deletions app/controllers/api/configurations_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -178,11 +178,14 @@ def update
private def user_configuration_json
{
salesforce_account_id: @user.salesforce_account_id,

field_mappings: @user.field_mappings,
field_defaults: @user.field_defaults,
default_mappings: @user.default_mappings,
required_mappings: @user.required_mappings,

feature_flags: @user.feature_flags,

connection_status: {
# TODO use dynamic connection status
salesforce: @user.salesforce_token.present?,
Expand All @@ -191,7 +194,11 @@ def update
last_synced: Time.now.to_i,
stripe_account_id: @user.stripe_account_id,
},

settings: @user.connector_settings,

enabled: @user.enabled,
configuration_hash: @user.configuration_hash,
}
end

Expand Down
16 changes: 16 additions & 0 deletions lib/stripe-force/db/user.rb
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,22 @@ def stripe_credentials(forced_livemode: nil)
}
end

# this hash is used to prevent same-time editing via the SF UI
def configuration_hash
mappings_as_string = self.field_defaults.to_json + self.field_mappings.to_json

# take into account all configuration options which are set via the UI
selective_configuration_json = self.connector_settings.slice(*DEFAULT_CONNECTOR_SETTINGS.keys).to_json

Digest::SHA1.hexdigest(mappings_as_string + selective_configuration_json)
end

# used for the idempotency key generation
def mapping_hash
mappings_as_string = self.field_defaults.to_json + self.field_mappings.to_json
Digest::SHA1.hexdigest(mappings_as_string)
end

protected def kms_encryption_context(field=nil)
{
# NOTE that the account is the SF organization instance ID
Expand Down
5 changes: 1 addition & 4 deletions lib/stripe-force/translate/utilities/stripe_util.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,8 @@ def self.billing_frequency_of_price_in_months(stripe_price)

sig { params(user: StripeForce::User, sf_object: Restforce::SObject, action: T.nilable(Symbol)).returns(Hash) }
def self.generate_idempotency_key_with_credentials(user, sf_object, action=nil)
mappings_as_string = user.field_defaults.to_json + user.field_mappings.to_json
mapping_uid = Digest::SHA1.hexdigest(mappings_as_string)

last_modified_as_timestamp = DateTime.parse(sf_object[SF_LAST_MODIFIED_DATE]).to_i
key = "#{mapping_uid}-#{sf_object[SF_ID]}-#{last_modified_as_timestamp}"
key = "#{user.mapping_hash}-#{sf_object[SF_ID]}-#{last_modified_as_timestamp}"

if action
key = "#{key}-#{action}"
Expand Down
28 changes: 28 additions & 0 deletions test/controllers/test_configurations_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -196,13 +196,41 @@ class Critic::ConfigurationsControllerTest < ApplicationIntegrationTest
assert_equal(10_000, result['settings']['sync_record_retention'])
assert_equal('USD', result['settings']['default_currency'])
assert_nil(result['settings']['sync_start_date'])
assert_equal(40, result['configuration_hash'].size)
assert(result['enabled'])

refute_nil(result['settings']['filters'])
assert_equal("Status = 'Activated'", result['settings']['filters'][SF_ORDER])
assert_nil(result['settings']['filters'][SF_ACCOUNT])
assert_nil(result['settings']['filters'][SF_PRODUCT])
end

it 'updates the configuration_hash when mappings change' do
get api_configuration_path, headers: authentication_headers
assert_response :success
result = parsed_json

initial_hash = result['configuration_hash']

get api_configuration_path, headers: authentication_headers
assert_response :success
result = parsed_json

# hash should remain the same when something doesn't change
assert_equal(initial_hash, result['configuration_hash'])

@user.field_mappings['price'] = {'special' => 'mapping'}
@user.save

get api_configuration_path, headers: authentication_headers
assert_response :success
result = parsed_json

# if mappings change, hash should be different
refute_equal(initial_hash, result['configuration_hash'])
assert_equal(40, result['configuration_hash'].size)
end

it 'updates settings' do
future_time = Time.now.to_i + 3600

Expand Down

0 comments on commit d8cff8b

Please sign in to comment.