pull/603/merge
Larron Armstead 4 days ago committed by GitHub
commit 156d39b2fd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -1,6 +1,12 @@
# frozen_string_literal: true # frozen_string_literal: true
class StorageSettingsController < ApplicationController class StorageSettingsController < ApplicationController
ENV_STORAGE_SERVICES = {
'S3_ATTACHMENTS_BUCKET' => ['aws_s3', 'AWS S3'],
'GCS_BUCKET' => ['google', 'GCP'],
'AZURE_CONTAINER' => ['azure', 'Azure']
}.freeze
before_action :load_encrypted_config before_action :load_encrypted_config
authorize_resource :encrypted_config, only: :index authorize_resource :encrypted_config, only: :index
authorize_resource :encrypted_config, parent: false, only: :create authorize_resource :encrypted_config, parent: false, only: :create
@ -8,6 +14,12 @@ class StorageSettingsController < ApplicationController
def index; end def index; end
def create def create
if @env_storage_service.present?
redirect_to settings_storage_index_path, alert: I18n.t('storage_settings_are_managed_by_environment_variables')
return
end
if @encrypted_config.update(storage_configs) if @encrypted_config.update(storage_configs)
LoadActiveStorageConfigs.reload LoadActiveStorageConfigs.reload
@ -22,6 +34,13 @@ class StorageSettingsController < ApplicationController
def load_encrypted_config def load_encrypted_config
@encrypted_config = @encrypted_config =
EncryptedConfig.find_or_initialize_by(account: current_account, key: EncryptedConfig::FILES_STORAGE_KEY) EncryptedConfig.find_or_initialize_by(account: current_account, key: EncryptedConfig::FILES_STORAGE_KEY)
@env_storage_env_var, @env_storage_service, @env_storage_service_label = env_storage_service
@storage_value =
if @env_storage_service.present?
{ 'service' => @env_storage_service }
else
@encrypted_config.value || { 'service' => 'disk' }
end
end end
def storage_configs def storage_configs
@ -31,4 +50,12 @@ class StorageSettingsController < ApplicationController
e.dig(:value, :configs)&.compact_blank! e.dig(:value, :configs)&.compact_blank!
end end
end end
def env_storage_service
ENV_STORAGE_SERVICES.each do |env_var, (service, label)|
return [env_var, service, label] if ENV[env_var].present?
end
nil
end
end end

@ -4,9 +4,25 @@
<h1 class="text-4xl font-bold mb-4"> <h1 class="text-4xl font-bold mb-4">
<%= t('storage') %> <%= t('storage') %>
</h1> </h1>
<% value = @encrypted_config.value || { 'service' => 'disk' } %> <% value = @storage_value %>
<% configs = value['configs'] || {} %> <% configs = value['configs'] || {} %>
<% if @env_storage_service.present? %>
<div class="alert my-4">
<%= svg_icon('info_circle', class: 'stroke-current flex-shrink-0 w-6 h-6') %>
<div>
<p class="font-bold">
<%= t('storage_settings_are_managed_by_environment_variables') %>
</p>
<p class="text-gray-700">
<%= t('storage_provider_is_configured_by_env_var_html', service: @env_storage_service_label, variable: @env_storage_env_var) %>
<br>
<%= t('update_environment_variables_and_restart_the_app_to_change_storage') %>
</p>
</div>
</div>
<% end %>
<%= form_for @encrypted_config, url: settings_storage_index_path, method: :post, html: { autocomplete: 'off', class: 'w-full' } do |f| %> <%= form_for @encrypted_config, url: settings_storage_index_path, method: :post, html: { autocomplete: 'off', class: 'w-full' } do |f| %>
<fieldset <%= 'disabled' if @env_storage_service.present? %>>
<% options = [%w[Disk disk], %w[AWS aws_s3], %w[GCP google], %w[Azure azure]] %> <% options = [%w[Disk disk], %w[AWS aws_s3], %w[GCP google], %w[Azure azure]] %>
<toggle-visible data-element-ids="<%= options.map(&:last).to_json %>" class="block relative"> <toggle-visible data-element-ids="<%= options.map(&:last).to_json %>" class="block relative">
<ul class="items-center w-full text-sm font-medium text-gray-900 space-y-2 sm:space-y-0 sm:flex sm:space-x-2"> <ul class="items-center w-full text-sm font-medium text-gray-900 space-y-2 sm:space-y-0 sm:flex sm:space-x-2">
@ -31,8 +47,9 @@
<%= render 'azure_form', f:, configs:, value: %> <%= render 'azure_form', f:, configs:, value: %>
</disable-hidden> </disable-hidden>
<div class="form-control"> <div class="form-control">
<%= f.button button_title(title: t('save'), disabled_with: t('saving')), class: 'base-button' %> <%= f.button button_title(title: t('save'), disabled_with: t('saving')), class: 'base-button', disabled: @env_storage_service.present? %>
</div> </div>
</fieldset>
<% end %> <% end %>
</div> </div>
<div class="w-0 md:w-52"></div> <div class="w-0 md:w-52"></div>

@ -396,6 +396,9 @@ en: &en
for_aws_s3_compatible_apis_like_minio: For AWS S3 compatible APIs like Minio. for_aws_s3_compatible_apis_like_minio: For AWS S3 compatible APIs like Minio.
store_all_files_on_disk: Store all files on disk store_all_files_on_disk: Store all files on disk
no_configs_are_needed_but_make_sure_your_disk_is_persistent: No configs are needed but make sure your disk is persistent no_configs_are_needed_but_make_sure_your_disk_is_persistent: No configs are needed but make sure your disk is persistent
storage_settings_are_managed_by_environment_variables: Storage settings are managed by environment variables.
storage_provider_is_configured_by_env_var_html: 'Current provider: <b>%{service}</b> via <code>%{variable}</code>.'
update_environment_variables_and_restart_the_app_to_change_storage: Update environment variables and restart the app to change storage.
not_suitable_for_heroku_and_other_paas: Not suitable for Heroku and other PaaS not_suitable_for_heroku_and_other_paas: Not suitable for Heroku and other PaaS
bulk_send_from_excel_xlsx_or_csv: Bulk send from Excel XLSX or CSV bulk_send_from_excel_xlsx_or_csv: Bulk send from Excel XLSX or CSV
add_new: Add New add_new: Add New

@ -0,0 +1,50 @@
# frozen_string_literal: true
RSpec.describe 'StorageSettingsController', type: :request do
let(:account) { create(:account) }
let(:user) { create(:user, account:) }
def with_env(overrides)
previous_values = {}
overrides.each_key { |key| previous_values[key] = ENV[key] }
overrides.each { |key, value| ENV[key] = value }
yield
ensure
previous_values.each do |key, value|
value.nil? ? ENV.delete(key) : ENV[key] = value
end
end
before do
sign_in(user)
end
describe 'POST /settings/storage' do
it 'does not update storage settings when environment variables manage storage' do
encrypted_config = create(:encrypted_config, account:, key: EncryptedConfig::FILES_STORAGE_KEY, value: {
service: 'aws_s3',
configs: {
access_key_id: 'db_access_key',
secret_access_key: 'db_secret_key',
region: 'us-east-1',
bucket: 'db-bucket'
}
})
with_env('S3_ATTACHMENTS_BUCKET' => 'env-bucket') do
expect do
post settings_storage_index_path, params: {
encrypted_config: {
value: {
service: 'disk',
configs: {}
}
}
}
end.not_to(change { encrypted_config.reload.value })
expect(response).to redirect_to(settings_storage_index_path)
end
end
end
end

@ -8,6 +8,17 @@ RSpec.describe 'Storage Settings' do
sign_in(user) sign_in(user)
end end
def with_env(overrides)
previous_values = {}
overrides.each_key { |key| previous_values[key] = ENV[key] }
overrides.each { |key, value| ENV[key] = value }
yield
ensure
previous_values.each do |key, value|
value.nil? ? ENV.delete(key) : ENV[key] = value
end
end
context 'when storage settings are not set' do context 'when storage settings are not set' do
before do before do
visit settings_storage_index_path visit settings_storage_index_path
@ -93,6 +104,19 @@ RSpec.describe 'Storage Settings' do
end end
end end
context 'when storage is configured via environment variables' do
it 'shows the env-managed provider and disables updates' do
with_env('S3_ATTACHMENTS_BUCKET' => 'env-bucket') do
visit settings_storage_index_path
expect(page).to have_content('Storage settings are managed by environment variables.')
expect(page).to have_content('Current provider: AWS S3 via S3_ATTACHMENTS_BUCKET.')
expect(page).to have_checked_field('AWS')
expect(page).to have_button('Save', disabled: true)
end
end
end
context 'when storage settings are set' do context 'when storage settings are set' do
context 'when updates the same storage settings' do context 'when updates the same storage settings' do
context 'when AWS S3' do context 'when AWS S3' do

Loading…
Cancel
Save