diff --git a/app/models/theme_setting.rb b/app/models/theme_setting.rb index d6698746711..e97ac20a373 100644 --- a/app/models/theme_setting.rb +++ b/app/models/theme_setting.rb @@ -8,9 +8,12 @@ class ThemeSetting < ActiveRecord::Base TYPES_ENUM = Enum.new(integer: 0, float: 1, string: 2, bool: 3, list: 4, enum: 5, upload: 6, objects: 7) + MAXIMUM_JSON_VALUE_SIZE_BYTES = 0.5 * 1024 * 1024 # 0.5 MB + validates_presence_of :name, :theme before_validation :objects_type_enabled validates :data_type, inclusion: { in: TYPES_ENUM.values } + validate :json_value_size, if: -> { self.data_type == TYPES_ENUM[:objects] } validates :name, length: { maximum: 255 } after_save :clear_settings_cache @@ -52,6 +55,18 @@ class ThemeSetting < ActiveRecord::Base self.data_type = nil end end + + def json_value_size + if json_value.to_json.size > MAXIMUM_JSON_VALUE_SIZE_BYTES + errors.add( + :json_value, + I18n.t( + "theme_settings.errors.json_value.too_large", + max_size_megabytes: MAXIMUM_JSON_VALUE_SIZE_BYTES / 1024 / 1024, + ), + ) + end + end end # == Schema Information diff --git a/config/locales/server.en.yml b/config/locales/server.en.yml index 0eb40fc5f3c..45360ffed0f 100644 --- a/config/locales/server.en.yml +++ b/config/locales/server.en.yml @@ -74,6 +74,10 @@ en: enabled_filter: "Enabled" disabled_filter: "Disabled" updates_available_filter: "Updates Available" + theme_settings: + errors: + json_value: + too_large: "has exceeded the maximum size of %{max_size} bytes." themes: bad_color_scheme: "Can not update theme, invalid color palette" other_error: "Something went wrong updating theme" diff --git a/spec/models/theme_setting_spec.rb b/spec/models/theme_setting_spec.rb index 1bb52a558e9..64cdc4f8b9b 100644 --- a/spec/models/theme_setting_spec.rb +++ b/spec/models/theme_setting_spec.rb @@ -22,5 +22,33 @@ RSpec.describe ThemeSetting do expect(theme_setting.valid?).to eq(true) end + + it "should be invalid when json_value size is greater than the maximum allowed size" do + SiteSetting.experimental_objects_type_for_theme_settings = true + + json_value = { "key" => "value" } + bytesize = json_value.to_json.bytesize + + expect(bytesize).to eq(15) + + stub_const(ThemeSetting, "MAXIMUM_JSON_VALUE_SIZE_BYTES", bytesize - 1) do + theme_setting = + ThemeSetting.new( + name: "test", + data_type: ThemeSetting.types[:objects], + theme:, + json_value:, + ) + + expect(theme_setting.valid?).to eq(false) + + expect(theme_setting.errors[:json_value]).to contain_exactly( + I18n.t( + "theme_settings.errors.json_value.too_large", + max_size_megabytes: (bytesize - 1) / 1024 / 1024, + ), + ) + end + end end end