about summary refs log tree commit diff
path: root/app/models
diff options
context:
space:
mode:
Diffstat (limited to 'app/models')
-rw-r--r--app/models/account.rb2
-rw-r--r--app/models/account_identity_proof.rb2
-rw-r--r--app/models/follow_request.rb2
-rw-r--r--app/models/form/admin_settings.rb149
-rw-r--r--app/models/instance.rb6
-rw-r--r--app/models/notification.rb2
-rw-r--r--app/models/status.rb19
-rw-r--r--app/models/user.rb12
8 files changed, 128 insertions, 66 deletions
diff --git a/app/models/account.rb b/app/models/account.rb
index 6b539f004..a82251d2e 100644
--- a/app/models/account.rb
+++ b/app/models/account.rb
@@ -98,7 +98,7 @@ class Account < ApplicationRecord
   scope :matches_display_name, ->(value) { where(arel_table[:display_name].matches("#{value}%")) }
   scope :matches_domain, ->(value) { where(arel_table[:domain].matches("%#{value}%")) }
   scope :searchable, -> { without_suspended.where(moved_to_account_id: nil) }
-  scope :discoverable, -> { searchable.without_silenced.where(discoverable: true).joins(:account_stat).where(AccountStat.arel_table[:followers_count].gteq(MIN_FOLLOWERS_DISCOVERY)).by_recent_status }
+  scope :discoverable, -> { searchable.without_silenced.where(discoverable: true).joins(:account_stat).where(AccountStat.arel_table[:followers_count].gteq(MIN_FOLLOWERS_DISCOVERY)) }
   scope :tagged_with, ->(tag) { joins(:accounts_tags).where(accounts_tags: { tag_id: tag }) }
   scope :by_recent_status, -> { order(Arel.sql('(case when account_stats.last_status_at is null then 1 else 0 end) asc, account_stats.last_status_at desc')) }
   scope :popular, -> { order('account_stats.followers_count desc') }
diff --git a/app/models/account_identity_proof.rb b/app/models/account_identity_proof.rb
index e7a3f97e5..1ac234735 100644
--- a/app/models/account_identity_proof.rb
+++ b/app/models/account_identity_proof.rb
@@ -26,7 +26,7 @@ class AccountIdentityProof < ApplicationRecord
 
   scope :active, -> { where(verified: true, live: true) }
 
-  after_create_commit :queue_worker
+  after_commit :queue_worker, if: :saved_change_to_token?
 
   delegate :refresh!, :on_success_path, :badge, to: :provider_instance
 
diff --git a/app/models/follow_request.rb b/app/models/follow_request.rb
index c5451a050..96ac7eaa5 100644
--- a/app/models/follow_request.rb
+++ b/app/models/follow_request.rb
@@ -26,7 +26,7 @@ class FollowRequest < ApplicationRecord
 
   def authorize!
     account.follow!(target_account, reblogs: show_reblogs, uri: uri)
-    MergeWorker.perform_async(target_account.id, account.id)
+    MergeWorker.perform_async(target_account.id, account.id) if account.local?
     destroy!
   end
 
diff --git a/app/models/form/admin_settings.rb b/app/models/form/admin_settings.rb
index 929c65793..0fcbd0605 100644
--- a/app/models/form/admin_settings.rb
+++ b/app/models/form/admin_settings.rb
@@ -3,57 +3,108 @@
 class Form::AdminSettings
   include ActiveModel::Model
 
-  delegate(
-    :site_contact_username,
-    :site_contact_username=,
-    :site_contact_email,
-    :site_contact_email=,
-    :site_title,
-    :site_title=,
-    :site_short_description,
-    :site_short_description=,
-    :site_description,
-    :site_description=,
-    :site_extended_description,
-    :site_extended_description=,
-    :site_terms,
-    :site_terms=,
-    :registrations_mode,
-    :registrations_mode=,
-    :closed_registrations_message,
-    :closed_registrations_message=,
-    :open_deletion,
-    :open_deletion=,
-    :timeline_preview,
-    :timeline_preview=,
-    :show_staff_badge,
-    :show_staff_badge=,
-    :bootstrap_timeline_accounts,
-    :bootstrap_timeline_accounts=,
-    :hide_followers_count,
-    :hide_followers_count=,
-    :flavour,
-    :flavour=,
-    :skin,
-    :skin=,
-    :min_invite_role,
-    :min_invite_role=,
-    :activity_api_enabled,
-    :activity_api_enabled=,
-    :peers_api_enabled,
-    :peers_api_enabled=,
-    :show_known_fediverse_at_about_page,
-    :show_known_fediverse_at_about_page=,
-    :preview_sensitive_media,
-    :preview_sensitive_media=,
-    :custom_css,
-    :custom_css=,
-    :profile_directory,
-    :profile_directory=,
-    to: Setting
-  )
+  KEYS = %i(
+    site_contact_username
+    site_contact_email
+    site_title
+    site_short_description
+    site_description
+    site_extended_description
+    site_terms
+    registrations_mode
+    closed_registrations_message
+    open_deletion
+    timeline_preview
+    show_staff_badge
+    bootstrap_timeline_accounts
+    flavour
+    skin
+    min_invite_role
+    activity_api_enabled
+    peers_api_enabled
+    show_known_fediverse_at_about_page
+    preview_sensitive_media
+    custom_css
+    profile_directory
+    hide_followers_count
+    flavour_and_skin
+  ).freeze
+
+  BOOLEAN_KEYS = %i(
+    open_deletion
+    timeline_preview
+    show_staff_badge
+    activity_api_enabled
+    peers_api_enabled
+    show_known_fediverse_at_about_page
+    preview_sensitive_media
+    profile_directory
+    hide_followers_count
+  ).freeze
+
+  UPLOAD_KEYS = %i(
+    thumbnail
+    hero
+    mascot
+  ).freeze
+
+  PSEUDO_KEYS = %i(
+    flavour_and_skin
+  ).freeze
+
+  attr_accessor(*KEYS)
+
+  validates :site_short_description, :site_description, :site_extended_description, :site_terms, :closed_registrations_message, html: true
+  validates :registrations_mode, inclusion: { in: %w(open approved none) }
+  validates :min_invite_role, inclusion: { in: %w(disabled user moderator admin) }
+  validates :site_contact_email, :site_contact_username, presence: true
+  validates :site_contact_username, existing_username: true
+  validates :bootstrap_timeline_accounts, existing_username: { multiple: true }
+
+  def initialize(_attributes = {})
+    super
+    initialize_attributes
+  end
+
+  def save
+    return false unless valid?
+
+    KEYS.each do |key|
+      next if PSEUDO_KEYS.include?(key)
+      value = instance_variable_get("@#{key}")
+
+      if UPLOAD_KEYS.include?(key)
+        upload = SiteUpload.where(var: key).first_or_initialize(var: key)
+        upload.update(file: value)
+      else
+        setting = Setting.where(var: key).first_or_initialize(var: key)
+        setting.update(value: typecast_value(key, value))
+      end
+    end
+  end
 
   def flavour_and_skin
     "#{Setting.flavour}/#{Setting.skin}"
   end
+
+  def flavour_and_skin=(value)
+    @flavour, @skin = value.split('/', 2)
+  end
+
+  private
+
+  def initialize_attributes
+    KEYS.each do |key|
+      next if PSEUDO_KEYS.include?(key)
+      instance_variable_set("@#{key}", Setting.public_send(key)) if instance_variable_get("@#{key}").nil?
+    end
+  end
+
+  def typecast_value(key, value)
+    if BOOLEAN_KEYS.include?(key)
+      value == '1'
+    else
+      value
+    end
+  end
 end
diff --git a/app/models/instance.rb b/app/models/instance.rb
index 7448d465c..7bf000d40 100644
--- a/app/models/instance.rb
+++ b/app/models/instance.rb
@@ -7,7 +7,7 @@ class Instance
 
   def initialize(resource)
     @domain         = resource.domain
-    @accounts_count = resource.accounts_count
+    @accounts_count = resource.is_a?(DomainBlock) ? nil : resource.accounts_count
     @domain_block   = resource.is_a?(DomainBlock) ? resource : DomainBlock.find_by(domain: domain)
   end
 
@@ -15,6 +15,10 @@ class Instance
     Rails.cache.fetch("#{cache_key}/sample_accounts", expires_in: 12.hours) { Account.where(domain: domain).searchable.joins(:account_stat).popular.limit(3) }
   end
 
+  def cached_accounts_count
+    @accounts_count || Rails.cache.fetch("#{cache_key}/count", expires_in: 12.hours) { Account.where(domain: domain).count }
+  end
+
   def to_param
     domain
   end
diff --git a/app/models/notification.rb b/app/models/notification.rb
index 982136c05..300269e24 100644
--- a/app/models/notification.rb
+++ b/app/models/notification.rb
@@ -25,7 +25,7 @@ class Notification < ApplicationRecord
     poll:           'Poll',
   }.freeze
 
-  STATUS_INCLUDES = [:account, :application, :media_attachments, :tags, active_mentions: :account, reblog: [:account, :application, :media_attachments, :tags, active_mentions: :account]].freeze
+  STATUS_INCLUDES = [:account, :application, :preloadable_poll, :media_attachments, :tags, active_mentions: :account, reblog: [:account, :application, :preloadable_poll, :media_attachments, :tags, active_mentions: :account]].freeze
 
   belongs_to :account, optional: true
   belongs_to :from_account, class_name: 'Account', optional: true
diff --git a/app/models/status.rb b/app/models/status.rb
index c049401e8..e7fa0220b 100644
--- a/app/models/status.rb
+++ b/app/models/status.rb
@@ -47,7 +47,7 @@ class Status < ApplicationRecord
   belongs_to :account, inverse_of: :statuses
   belongs_to :in_reply_to_account, foreign_key: 'in_reply_to_account_id', class_name: 'Account', optional: true
   belongs_to :conversation, optional: true
-  belongs_to :poll, optional: true
+  belongs_to :preloadable_poll, class_name: 'Poll', foreign_key: 'poll_id', optional: true
 
   belongs_to :thread, foreign_key: 'in_reply_to_id', class_name: 'Status', inverse_of: :replies, optional: true
   belongs_to :reblog, foreign_key: 'reblog_of_id', class_name: 'Status', inverse_of: :reblogs, optional: true
@@ -66,7 +66,7 @@ class Status < ApplicationRecord
   has_one :notification, as: :activity, dependent: :destroy
   has_one :stream_entry, as: :activity, inverse_of: :status
   has_one :status_stat, inverse_of: :status
-  has_one :owned_poll, class_name: 'Poll', inverse_of: :status, dependent: :destroy
+  has_one :poll, inverse_of: :status, dependent: :destroy
 
   validates :uri, uniqueness: true, presence: true, unless: :local?
   validates :text, presence: true, unless: -> { with_media? || reblog? }
@@ -75,7 +75,7 @@ class Status < ApplicationRecord
   validates :reblog, uniqueness: { scope: :account }, if: :reblog?
   validates :visibility, exclusion: { in: %w(direct limited) }, if: :reblog?
 
-  accepts_nested_attributes_for :owned_poll
+  accepts_nested_attributes_for :poll
 
   default_scope { recent }
 
@@ -112,7 +112,7 @@ class Status < ApplicationRecord
                    :tags,
                    :preview_cards,
                    :stream_entry,
-                   :poll,
+                   :preloadable_poll,
                    account: :account_stat,
                    active_mentions: { account: :account_stat },
                    reblog: [
@@ -123,7 +123,7 @@ class Status < ApplicationRecord
                      :media_attachments,
                      :conversation,
                      :status_stat,
-                     :poll,
+                     :preloadable_poll,
                      account: :account_stat,
                      active_mentions: { account: :account_stat },
                    ],
@@ -219,10 +219,11 @@ class Status < ApplicationRecord
 
   def emojis
     return @emojis if defined?(@emojis)
-    fields = [spoiler_text, text]
-    fields += owned_poll.options unless owned_poll.nil?
+
+    fields  = [spoiler_text, text]
+    fields += preloadable_poll.options unless preloadable_poll.nil?
+
     @emojis = CustomEmoji.from_text(fields.join(' '), account.domain)
-    @emojis
   end
 
   def mark_for_mass_destruction!
@@ -473,7 +474,7 @@ class Status < ApplicationRecord
   end
 
   def set_poll_id
-    update_column(:poll_id, owned_poll.id) unless owned_poll.nil?
+    update_column(:poll_id, poll.id) unless poll.nil?
   end
 
   def set_visibility
diff --git a/app/models/user.rb b/app/models/user.rb
index 47657a670..66c1543ff 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -124,7 +124,8 @@ class User < ApplicationRecord
   end
 
   def confirm
-    new_user = !confirmed?
+    new_user      = !confirmed?
+    self.approved = true if open_registrations?
 
     super
 
@@ -136,7 +137,8 @@ class User < ApplicationRecord
   end
 
   def confirm!
-    new_user = !confirmed?
+    new_user      = !confirmed?
+    self.approved = true if open_registrations?
 
     skip_confirmation!
     save!
@@ -264,7 +266,11 @@ class User < ApplicationRecord
   private
 
   def set_approved
-    self.approved = Setting.registrations_mode == 'open' || invited?
+    self.approved = open_registrations? || invited?
+  end
+
+  def open_registrations?
+    Setting.registrations_mode == 'open'
   end
 
   def sanitize_languages