admin_settings.rb 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. # frozen_string_literal: true
  2. class Form::AdminSettings
  3. include ActiveModel::Model
  4. include AuthorizedFetchHelper
  5. KEYS = %i(
  6. site_contact_username
  7. site_contact_email
  8. site_title
  9. site_short_description
  10. site_extended_description
  11. site_terms
  12. registrations_mode
  13. closed_registrations_message
  14. timeline_preview
  15. bootstrap_timeline_accounts
  16. theme
  17. activity_api_enabled
  18. peers_api_enabled
  19. preview_sensitive_media
  20. custom_css
  21. profile_directory
  22. thumbnail
  23. mascot
  24. trends
  25. trends_as_landing_page
  26. trendable_by_default
  27. show_domain_blocks
  28. show_domain_blocks_rationale
  29. noindex
  30. require_invite_text
  31. media_cache_retention_period
  32. content_cache_retention_period
  33. backups_retention_period
  34. status_page_url
  35. captcha_enabled
  36. authorized_fetch
  37. app_icon
  38. favicon
  39. ).freeze
  40. INTEGER_KEYS = %i(
  41. media_cache_retention_period
  42. content_cache_retention_period
  43. backups_retention_period
  44. ).freeze
  45. BOOLEAN_KEYS = %i(
  46. timeline_preview
  47. activity_api_enabled
  48. peers_api_enabled
  49. preview_sensitive_media
  50. profile_directory
  51. trends
  52. trends_as_landing_page
  53. trendable_by_default
  54. noindex
  55. require_invite_text
  56. captcha_enabled
  57. authorized_fetch
  58. ).freeze
  59. UPLOAD_KEYS = %i(
  60. thumbnail
  61. mascot
  62. app_icon
  63. favicon
  64. ).freeze
  65. OVERRIDEN_SETTINGS = {
  66. authorized_fetch: :authorized_fetch_mode?,
  67. }.freeze
  68. DESCRIPTION_LIMIT = 200
  69. attr_accessor(*KEYS)
  70. validates :registrations_mode, inclusion: { in: %w(open approved none) }, if: -> { defined?(@registrations_mode) }
  71. validates :site_contact_email, :site_contact_username, presence: true, if: -> { defined?(@site_contact_username) || defined?(@site_contact_email) }
  72. validates :site_contact_username, existing_username: true, if: -> { defined?(@site_contact_username) }
  73. validates :bootstrap_timeline_accounts, existing_username: { multiple: true }, if: -> { defined?(@bootstrap_timeline_accounts) }
  74. validates :show_domain_blocks, inclusion: { in: %w(disabled users all) }, if: -> { defined?(@show_domain_blocks) }
  75. validates :show_domain_blocks_rationale, inclusion: { in: %w(disabled users all) }, if: -> { defined?(@show_domain_blocks_rationale) }
  76. 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) }
  77. validates :site_short_description, length: { maximum: DESCRIPTION_LIMIT }, if: -> { defined?(@site_short_description) }
  78. validates :status_page_url, url: true, allow_blank: true
  79. validate :validate_site_uploads
  80. KEYS.each do |key|
  81. define_method(key) do
  82. return instance_variable_get(:"@#{key}") if instance_variable_defined?(:"@#{key}")
  83. stored_value = if UPLOAD_KEYS.include?(key)
  84. SiteUpload.where(var: key).first_or_initialize(var: key)
  85. elsif OVERRIDEN_SETTINGS.include?(key)
  86. public_send(OVERRIDEN_SETTINGS[key])
  87. else
  88. Setting.public_send(key)
  89. end
  90. instance_variable_set(:"@#{key}", stored_value)
  91. end
  92. end
  93. UPLOAD_KEYS.each do |key|
  94. define_method(:"#{key}=") do |file|
  95. value = public_send(key)
  96. value.file = file
  97. rescue Mastodon::DimensionsValidationError => e
  98. errors.add(key.to_sym, e.message)
  99. end
  100. end
  101. def save
  102. # NOTE: Annoyingly, files are processed and can error out before
  103. # validations are called, and `valid?` clears errors…
  104. # So for now, return early if errors aren't empty.
  105. return false unless errors.empty? && valid?
  106. KEYS.each do |key|
  107. next unless instance_variable_defined?(:"@#{key}")
  108. if UPLOAD_KEYS.include?(key)
  109. public_send(key).save
  110. else
  111. setting = Setting.where(var: key).first_or_initialize(var: key)
  112. setting.update(value: typecast_value(key, instance_variable_get(:"@#{key}")))
  113. end
  114. end
  115. end
  116. private
  117. def typecast_value(key, value)
  118. if BOOLEAN_KEYS.include?(key)
  119. value == '1'
  120. elsif INTEGER_KEYS.include?(key)
  121. value.blank? ? value : Integer(value)
  122. else
  123. value
  124. end
  125. end
  126. def validate_site_uploads
  127. UPLOAD_KEYS.each do |key|
  128. next unless instance_variable_defined?(:"@#{key}")
  129. upload = instance_variable_get(:"@#{key}")
  130. next if upload.valid?
  131. upload.errors.each do |error|
  132. errors.import(error, attribute: key)
  133. end
  134. end
  135. end
  136. end