mirror of
https://github.com/we-promise/sure.git
synced 2026-04-13 17:14:05 +00:00
Add support for dynamic config UI (#256)
* Add support for dynamic config UI
* Add support for section description
* Better dynamic class settings
Added dynamic_fields hash field - Stores all undeclared settings
[] method - Checks declared fields first, then falls back to dynamic hash
[]= method - Updates declared fields normally, stores others in hash
No runtime field declaration - Fields are never dynamically created on the class
* FIX proper lookup for provider keys
- Also validate configurable values properly.
- Change Provider factory to use Rails autoloading (Zeitwerk)
* Fix factory
The derive_adapter_name method relies on string manipulation ("PlaidAccount".sub(/Account$/, "") + "Adapter" → "PlaidAdapter"), but we already have explicit registration in place.
* Make updates atomic, field-aware, and handle blanks explicitly
* Small UX detail
* Add support for PlaidEU in UI also
- This looks like partial support atm
This commit is contained in:
108
app/controllers/settings/providers_controller.rb
Normal file
108
app/controllers/settings/providers_controller.rb
Normal file
@@ -0,0 +1,108 @@
|
||||
class Settings::ProvidersController < ApplicationController
|
||||
layout "settings"
|
||||
|
||||
guard_feature unless: -> { self_hosted? }
|
||||
|
||||
before_action :ensure_admin, only: [ :show, :update ]
|
||||
|
||||
def show
|
||||
@breadcrumbs = [
|
||||
[ "Home", root_path ],
|
||||
[ "Bank Sync Providers", nil ]
|
||||
]
|
||||
|
||||
# Load all provider configurations
|
||||
Provider::Factory.ensure_adapters_loaded
|
||||
@provider_configurations = Provider::ConfigurationRegistry.all
|
||||
end
|
||||
|
||||
def update
|
||||
# Build index of valid configurable fields with their metadata
|
||||
Provider::Factory.ensure_adapters_loaded
|
||||
valid_fields = {}
|
||||
Provider::ConfigurationRegistry.all.each do |config|
|
||||
config.fields.each do |field|
|
||||
valid_fields[field.setting_key.to_s] = field
|
||||
end
|
||||
end
|
||||
|
||||
updated_fields = []
|
||||
|
||||
# Perform all updates within a transaction for consistency
|
||||
Setting.transaction do
|
||||
provider_params.each do |param_key, param_value|
|
||||
# Only process keys that exist in the configuration registry
|
||||
field = valid_fields[param_key.to_s]
|
||||
next unless field
|
||||
|
||||
# Clean the value and convert blank/empty strings to nil
|
||||
value = param_value.to_s.strip
|
||||
value = nil if value.empty?
|
||||
|
||||
# For secret fields only, skip placeholder values to prevent accidental overwrite
|
||||
if field.secret && value == "********"
|
||||
next
|
||||
end
|
||||
|
||||
# Set the value using dynamic hash-style access
|
||||
Setting[field.setting_key] = value
|
||||
updated_fields << param_key
|
||||
end
|
||||
end
|
||||
|
||||
if updated_fields.any?
|
||||
# Reload provider configurations if needed
|
||||
reload_provider_configs(updated_fields)
|
||||
|
||||
redirect_to settings_providers_path, notice: "Provider settings updated successfully"
|
||||
else
|
||||
redirect_to settings_providers_path, notice: "No changes were made"
|
||||
end
|
||||
rescue => error
|
||||
Rails.logger.error("Failed to update provider settings: #{error.message}")
|
||||
flash.now[:alert] = "Failed to update provider settings: #{error.message}"
|
||||
render :show, status: :unprocessable_entity
|
||||
end
|
||||
|
||||
private
|
||||
def provider_params
|
||||
# Dynamically permit all provider configuration fields
|
||||
Provider::Factory.ensure_adapters_loaded
|
||||
permitted_fields = []
|
||||
|
||||
Provider::ConfigurationRegistry.all.each do |config|
|
||||
config.fields.each do |field|
|
||||
permitted_fields << field.setting_key
|
||||
end
|
||||
end
|
||||
|
||||
params.require(:setting).permit(*permitted_fields)
|
||||
end
|
||||
|
||||
def ensure_admin
|
||||
redirect_to settings_providers_path, alert: "Not authorized" unless Current.user.admin?
|
||||
end
|
||||
|
||||
# Reload provider configurations after settings update
|
||||
def reload_provider_configs(updated_fields)
|
||||
# Build a set of provider keys that had fields updated
|
||||
updated_provider_keys = Set.new
|
||||
|
||||
# Look up the provider key directly from the configuration registry
|
||||
updated_fields.each do |field_key|
|
||||
Provider::ConfigurationRegistry.all.each do |config|
|
||||
field = config.fields.find { |f| f.setting_key.to_s == field_key.to_s }
|
||||
if field
|
||||
updated_provider_keys.add(field.provider_key)
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Reload configuration for each updated provider
|
||||
updated_provider_keys.each do |provider_key|
|
||||
adapter_class = Provider::ConfigurationRegistry.get_adapter_class(provider_key)
|
||||
adapter_class&.reload_configuration
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user