2017-07-12 03:24:04 +02:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
|
|
|
|
|
class Form::AdminSettings
|
|
|
|
|
include ActiveModel::Model
|
|
|
|
|
|
2023-09-01 15:41:10 +02:00
|
|
|
include AuthorizedFetchHelper
|
|
|
|
|
|
2019-03-23 14:07:04 +01:00
|
|
|
KEYS = %i(
|
|
|
|
|
site_contact_username
|
|
|
|
|
site_contact_email
|
|
|
|
|
site_title
|
|
|
|
|
site_short_description
|
|
|
|
|
site_extended_description
|
|
|
|
|
site_terms
|
|
|
|
|
registrations_mode
|
|
|
|
|
closed_registrations_message
|
|
|
|
|
bootstrap_timeline_accounts
|
2019-03-23 22:10:51 +01:00
|
|
|
flavour
|
|
|
|
|
skin
|
2019-03-23 14:07:04 +01:00
|
|
|
activity_api_enabled
|
|
|
|
|
peers_api_enabled
|
|
|
|
|
preview_sensitive_media
|
|
|
|
|
custom_css
|
|
|
|
|
profile_directory
|
2019-03-23 22:10:51 +01:00
|
|
|
hide_followers_count
|
|
|
|
|
flavour_and_skin
|
2019-03-30 20:03:56 -07:00
|
|
|
thumbnail
|
|
|
|
|
mascot
|
2019-04-30 21:51:24 +02:00
|
|
|
show_reblogs_in_public_timelines
|
|
|
|
|
show_replies_in_public_timelines
|
2019-08-06 17:57:52 +02:00
|
|
|
trends
|
2019-10-09 00:30:15 +02:00
|
|
|
trendable_by_default
|
2022-02-26 10:45:44 +01:00
|
|
|
trending_status_cw
|
2019-08-19 11:35:48 +02:00
|
|
|
show_domain_blocks
|
|
|
|
|
show_domain_blocks_rationale
|
2025-05-19 15:13:22 +02:00
|
|
|
allow_referrer_origin
|
2019-09-11 07:44:58 +01:00
|
|
|
noindex
|
2020-05-30 16:47:17 +02:00
|
|
|
outgoing_spoilers
|
2020-12-14 10:03:09 +01:00
|
|
|
require_invite_text
|
2022-09-27 03:08:19 +02:00
|
|
|
media_cache_retention_period
|
|
|
|
|
content_cache_retention_period
|
|
|
|
|
backups_retention_period
|
2023-02-04 04:56:06 +01:00
|
|
|
status_page_url
|
2023-05-16 23:27:35 +02:00
|
|
|
captcha_enabled
|
2023-09-01 15:41:10 +02:00
|
|
|
authorized_fetch
|
2024-05-06 18:06:52 +03:00
|
|
|
app_icon
|
|
|
|
|
favicon
|
2025-03-14 15:07:29 +01:00
|
|
|
min_age
|
2025-10-06 10:34:05 +02:00
|
|
|
local_live_feed_access
|
|
|
|
|
remote_live_feed_access
|
|
|
|
|
local_topic_feed_access
|
|
|
|
|
remote_topic_feed_access
|
2025-10-27 11:16:59 +01:00
|
|
|
landing_page
|
2019-03-23 14:07:04 +01:00
|
|
|
).freeze
|
|
|
|
|
|
2022-10-26 20:14:07 +00:00
|
|
|
INTEGER_KEYS = %i(
|
|
|
|
|
media_cache_retention_period
|
|
|
|
|
content_cache_retention_period
|
|
|
|
|
backups_retention_period
|
2025-03-14 15:07:29 +01:00
|
|
|
min_age
|
2022-10-26 20:14:07 +00:00
|
|
|
).freeze
|
|
|
|
|
|
2019-03-23 14:07:04 +01:00
|
|
|
BOOLEAN_KEYS = %i(
|
2025-05-19 15:13:22 +02:00
|
|
|
allow_referrer_origin
|
2019-03-23 14:07:04 +01:00
|
|
|
timeline_preview
|
|
|
|
|
activity_api_enabled
|
|
|
|
|
peers_api_enabled
|
|
|
|
|
preview_sensitive_media
|
|
|
|
|
profile_directory
|
2019-03-23 22:10:51 +01:00
|
|
|
hide_followers_count
|
2019-04-30 21:51:24 +02:00
|
|
|
show_reblogs_in_public_timelines
|
|
|
|
|
show_replies_in_public_timelines
|
2019-08-06 17:57:52 +02:00
|
|
|
trends
|
2019-10-09 00:30:15 +02:00
|
|
|
trendable_by_default
|
2022-02-26 10:45:44 +01:00
|
|
|
trending_status_cw
|
2019-09-11 07:44:58 +01:00
|
|
|
noindex
|
2020-12-14 10:03:09 +01:00
|
|
|
require_invite_text
|
2022-01-25 23:56:57 +01:00
|
|
|
captcha_enabled
|
2023-09-01 15:41:10 +02:00
|
|
|
authorized_fetch
|
2019-03-23 14:07:04 +01:00
|
|
|
).freeze
|
|
|
|
|
|
|
|
|
|
UPLOAD_KEYS = %i(
|
|
|
|
|
thumbnail
|
|
|
|
|
mascot
|
2024-05-06 18:06:52 +03:00
|
|
|
app_icon
|
|
|
|
|
favicon
|
2019-03-23 14:07:04 +01:00
|
|
|
).freeze
|
|
|
|
|
|
2019-03-23 22:10:51 +01:00
|
|
|
PSEUDO_KEYS = %i(
|
|
|
|
|
flavour_and_skin
|
|
|
|
|
).freeze
|
|
|
|
|
|
2025-01-08 03:48:45 -05:00
|
|
|
DIGEST_KEYS = %i(
|
|
|
|
|
custom_css
|
|
|
|
|
).freeze
|
|
|
|
|
|
2023-09-01 15:41:10 +02:00
|
|
|
OVERRIDEN_SETTINGS = {
|
|
|
|
|
authorized_fetch: :authorized_fetch_mode?,
|
|
|
|
|
}.freeze
|
|
|
|
|
|
2024-09-27 04:21:27 -04:00
|
|
|
DESCRIPTION_LIMIT = 200
|
2025-09-26 04:21:03 -04:00
|
|
|
DOMAIN_BLOCK_AUDIENCES = %w(disabled users all).freeze
|
|
|
|
|
REGISTRATION_MODES = %w(open approved none).freeze
|
2025-10-23 10:37:05 +02:00
|
|
|
FEED_ACCESS_MODES = %w(public authenticated disabled).freeze
|
2025-11-04 11:37:43 +01:00
|
|
|
ALTERNATE_FEED_ACCESS_MODES = %w(public authenticated).freeze
|
2025-10-27 11:16:59 +01:00
|
|
|
LANDING_PAGE = %w(trends about local_feed).freeze
|
2024-09-27 04:21:27 -04:00
|
|
|
|
2019-03-23 14:07:04 +01:00
|
|
|
attr_accessor(*KEYS)
|
|
|
|
|
|
2025-09-26 04:21:03 -04:00
|
|
|
validates :registrations_mode, inclusion: { in: REGISTRATION_MODES }, if: -> { defined?(@registrations_mode) }
|
2022-10-22 11:44:41 +02:00
|
|
|
validates :site_contact_email, :site_contact_username, presence: true, if: -> { defined?(@site_contact_username) || defined?(@site_contact_email) }
|
|
|
|
|
validates :site_contact_username, existing_username: true, if: -> { defined?(@site_contact_username) }
|
|
|
|
|
validates :bootstrap_timeline_accounts, existing_username: { multiple: true }, if: -> { defined?(@bootstrap_timeline_accounts) }
|
2025-09-26 04:21:03 -04:00
|
|
|
validates :show_domain_blocks, inclusion: { in: DOMAIN_BLOCK_AUDIENCES }, if: -> { defined?(@show_domain_blocks) }
|
|
|
|
|
validates :show_domain_blocks_rationale, inclusion: { in: DOMAIN_BLOCK_AUDIENCES }, if: -> { defined?(@show_domain_blocks_rationale) }
|
2025-10-06 10:34:05 +02:00
|
|
|
validates :local_live_feed_access, inclusion: { in: FEED_ACCESS_MODES }, if: -> { defined?(@local_live_feed_access) }
|
|
|
|
|
validates :remote_live_feed_access, inclusion: { in: FEED_ACCESS_MODES }, if: -> { defined?(@remote_live_feed_access) }
|
2025-11-04 11:37:43 +01:00
|
|
|
validates :local_topic_feed_access, inclusion: { in: ALTERNATE_FEED_ACCESS_MODES }, if: -> { defined?(@local_topic_feed_access) }
|
2025-10-06 10:34:05 +02:00
|
|
|
validates :remote_topic_feed_access, inclusion: { in: FEED_ACCESS_MODES }, if: -> { defined?(@remote_topic_feed_access) }
|
2022-10-22 11:44:41 +02:00
|
|
|
validates :media_cache_retention_period, :content_cache_retention_period, :backups_retention_period, numericality: { only_integer: true }, allow_blank: true, if: -> { defined?(@media_cache_retention_period) || defined?(@content_cache_retention_period) || defined?(@backups_retention_period) }
|
2025-03-14 15:07:29 +01:00
|
|
|
validates :min_age, numericality: { only_integer: true }, allow_blank: true, if: -> { defined?(@min_age) }
|
2024-09-27 04:21:27 -04:00
|
|
|
validates :site_short_description, length: { maximum: DESCRIPTION_LIMIT }, if: -> { defined?(@site_short_description) }
|
2023-02-10 10:20:43 +01:00
|
|
|
validates :status_page_url, url: true, allow_blank: true
|
2023-01-05 13:42:03 +01:00
|
|
|
validate :validate_site_uploads
|
2025-10-27 11:16:59 +01:00
|
|
|
validates :landing_page, inclusion: { in: LANDING_PAGE }, if: -> { defined?(@landing_page) }
|
2019-03-23 14:07:04 +01:00
|
|
|
|
2022-10-22 11:44:41 +02:00
|
|
|
KEYS.each do |key|
|
|
|
|
|
define_method(key) do
|
2023-12-18 05:26:09 -05:00
|
|
|
return instance_variable_get(:"@#{key}") if instance_variable_defined?(:"@#{key}")
|
2022-10-22 11:44:41 +02:00
|
|
|
|
2023-02-18 17:09:40 -05:00
|
|
|
stored_value = if UPLOAD_KEYS.include?(key)
|
|
|
|
|
SiteUpload.where(var: key).first_or_initialize(var: key)
|
2023-09-01 15:41:10 +02:00
|
|
|
elsif OVERRIDEN_SETTINGS.include?(key)
|
|
|
|
|
public_send(OVERRIDEN_SETTINGS[key])
|
2023-02-18 17:09:40 -05:00
|
|
|
else
|
|
|
|
|
Setting.public_send(key)
|
|
|
|
|
end
|
2022-10-22 11:44:41 +02:00
|
|
|
|
2023-12-18 05:26:09 -05:00
|
|
|
instance_variable_set(:"@#{key}", stored_value)
|
2022-10-22 11:44:41 +02:00
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
UPLOAD_KEYS.each do |key|
|
2023-12-18 05:26:09 -05:00
|
|
|
define_method(:"#{key}=") do |file|
|
2022-10-22 11:44:41 +02:00
|
|
|
value = public_send(key)
|
|
|
|
|
value.file = file
|
2023-01-05 13:42:03 +01:00
|
|
|
rescue Mastodon::DimensionsValidationError => e
|
|
|
|
|
errors.add(key.to_sym, e.message)
|
2022-10-22 11:44:41 +02:00
|
|
|
end
|
2019-03-23 14:07:04 +01:00
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def save
|
2023-01-05 13:42:03 +01:00
|
|
|
# NOTE: Annoyingly, files are processed and can error out before
|
|
|
|
|
# validations are called, and `valid?` clears errors…
|
|
|
|
|
# So for now, return early if errors aren't empty.
|
|
|
|
|
return false unless errors.empty? && valid?
|
2019-03-23 14:07:04 +01:00
|
|
|
|
|
|
|
|
KEYS.each do |key|
|
2023-12-21 19:29:59 +01:00
|
|
|
next if PSEUDO_KEYS.include?(key) || !instance_variable_defined?(:"@#{key}")
|
2019-03-23 14:07:04 +01:00
|
|
|
|
2025-01-08 03:48:45 -05:00
|
|
|
cache_digest_value(key) if DIGEST_KEYS.include?(key)
|
|
|
|
|
|
2022-10-22 11:44:41 +02:00
|
|
|
if UPLOAD_KEYS.include?(key)
|
|
|
|
|
public_send(key).save
|
2019-03-23 14:07:04 +01:00
|
|
|
else
|
|
|
|
|
setting = Setting.where(var: key).first_or_initialize(var: key)
|
2023-12-18 05:26:09 -05:00
|
|
|
setting.update(value: typecast_value(key, instance_variable_get(:"@#{key}")))
|
2019-03-23 14:07:04 +01:00
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
2018-10-08 15:00:27 +02:00
|
|
|
|
|
|
|
|
def flavour_and_skin
|
|
|
|
|
"#{Setting.flavour}/#{Setting.skin}"
|
|
|
|
|
end
|
2019-03-23 22:10:51 +01:00
|
|
|
|
|
|
|
|
def flavour_and_skin=(value)
|
|
|
|
|
@flavour, @skin = value.split('/', 2)
|
|
|
|
|
end
|
|
|
|
|
|
2019-03-23 14:07:04 +01:00
|
|
|
private
|
|
|
|
|
|
2025-01-08 03:48:45 -05:00
|
|
|
def cache_digest_value(key)
|
|
|
|
|
Rails.cache.delete(:"setting_digest_#{key}")
|
|
|
|
|
|
|
|
|
|
key_value = instance_variable_get(:"@#{key}")
|
|
|
|
|
if key_value.present?
|
|
|
|
|
Rails.cache.write(
|
|
|
|
|
:"setting_digest_#{key}",
|
|
|
|
|
Digest::SHA256.hexdigest(key_value)
|
|
|
|
|
)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2019-03-23 14:07:04 +01:00
|
|
|
def typecast_value(key, value)
|
|
|
|
|
if BOOLEAN_KEYS.include?(key)
|
|
|
|
|
value == '1'
|
2022-10-26 20:14:07 +00:00
|
|
|
elsif INTEGER_KEYS.include?(key)
|
|
|
|
|
value.blank? ? value : Integer(value)
|
2019-03-23 14:07:04 +01:00
|
|
|
else
|
|
|
|
|
value
|
|
|
|
|
end
|
|
|
|
|
end
|
2023-01-05 13:42:03 +01:00
|
|
|
|
|
|
|
|
def validate_site_uploads
|
|
|
|
|
UPLOAD_KEYS.each do |key|
|
2023-12-18 05:26:09 -05:00
|
|
|
next unless instance_variable_defined?(:"@#{key}")
|
2023-02-20 00:58:28 -05:00
|
|
|
|
2023-12-18 05:26:09 -05:00
|
|
|
upload = instance_variable_get(:"@#{key}")
|
2023-01-05 13:42:03 +01:00
|
|
|
next if upload.valid?
|
|
|
|
|
|
|
|
|
|
upload.errors.each do |error|
|
|
|
|
|
errors.import(error, attribute: key)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
2017-07-12 03:24:04 +02:00
|
|
|
end
|