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/form/admin_settings.rb20
-rw-r--r--app/models/relay.rb5
-rw-r--r--app/models/tag.rb22
-rw-r--r--app/models/user.rb1
-rw-r--r--app/models/webhook.rb1
5 files changed, 43 insertions, 6 deletions
diff --git a/app/models/form/admin_settings.rb b/app/models/form/admin_settings.rb
index b53a82db2..b595529f8 100644
--- a/app/models/form/admin_settings.rb
+++ b/app/models/form/admin_settings.rb
@@ -83,6 +83,7 @@ class Form::AdminSettings
   validates :show_domain_blocks_rationale, inclusion: { in: %w(disabled users all) }, if: -> { defined?(@show_domain_blocks_rationale) }
   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) }
   validates :site_short_description, length: { maximum: 200 }, if: -> { defined?(@site_short_description) }
+  validate :validate_site_uploads
 
   KEYS.each do |key|
     define_method(key) do
@@ -104,11 +105,16 @@ class Form::AdminSettings
     define_method("#{key}=") do |file|
       value = public_send(key)
       value.file = file
+    rescue Mastodon::DimensionsValidationError => e
+      errors.add(key.to_sym, e.message)
     end
   end
 
   def save
-    return false unless valid?
+    # 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?
 
     KEYS.each do |key|
       next if PSEUDO_KEYS.include?(key) || !instance_variable_defined?("@#{key}")
@@ -141,4 +147,16 @@ class Form::AdminSettings
       value
     end
   end
+
+  def validate_site_uploads
+    UPLOAD_KEYS.each do |key|
+      next unless instance_variable_defined?("@#{key}")
+      upload = instance_variable_get("@#{key}")
+      next if upload.valid?
+
+      upload.errors.each do |error|
+        errors.import(error, attribute: key)
+      end
+    end
+  end
 end
diff --git a/app/models/relay.rb b/app/models/relay.rb
index d6ddd30ed..c66bfe4ff 100644
--- a/app/models/relay.rb
+++ b/app/models/relay.rb
@@ -18,6 +18,7 @@ class Relay < ApplicationRecord
 
   scope :enabled, -> { accepted }
 
+  before_validation :strip_url
   before_destroy :ensure_disabled
 
   alias enabled? accepted?
@@ -74,4 +75,8 @@ class Relay < ApplicationRecord
   def ensure_disabled
     disable! if enabled?
   end
+
+  def strip_url
+    inbox_url&.strip!
+  end
 end
diff --git a/app/models/tag.rb b/app/models/tag.rb
index b66f85423..47a05d00a 100644
--- a/app/models/tag.rb
+++ b/app/models/tag.rb
@@ -26,8 +26,12 @@ class Tag < ApplicationRecord
   has_many :featured_tags, dependent: :destroy, inverse_of: :tag
   has_many :followers, through: :passive_relationships, source: :account
 
-  HASHTAG_SEPARATORS = "_\u00B7\u200c"
-  HASHTAG_NAME_PAT = "([[:word:]_][[:word:]#{HASHTAG_SEPARATORS}]*[[:alpha:]#{HASHTAG_SEPARATORS}][[:word:]#{HASHTAG_SEPARATORS}]*[[:word:]_])|([[:word:]_]*[[:alpha:]][[:word:]_]*)"
+  HASHTAG_SEPARATORS = "_\u00B7\u30FB\u200c"
+  HASHTAG_FIRST_SEQUENCE_CHUNK_ONE = "[[:word:]_][[:word:]#{HASHTAG_SEPARATORS}]*[[:alpha:]#{HASHTAG_SEPARATORS}]"
+  HASHTAG_FIRST_SEQUENCE_CHUNK_TWO = "[[:word:]#{HASHTAG_SEPARATORS}]*[[:word:]_]"
+  HASHTAG_FIRST_SEQUENCE = "(#{HASHTAG_FIRST_SEQUENCE_CHUNK_ONE}#{HASHTAG_FIRST_SEQUENCE_CHUNK_TWO})"
+  HASTAG_LAST_SEQUENCE = '([[:word:]_]*[[:alpha:]][[:word:]_]*)'
+  HASHTAG_NAME_PAT = "#{HASHTAG_FIRST_SEQUENCE}|#{HASTAG_LAST_SEQUENCE}"
 
   HASHTAG_RE = /(?:^|[^\/\)\w])#(#{HASHTAG_NAME_PAT})/i
   HASHTAG_NAME_RE = /\A(#{HASHTAG_NAME_PAT})\z/i
@@ -45,7 +49,11 @@ class Tag < ApplicationRecord
   scope :listable, -> { where(listable: [true, nil]) }
   scope :trendable, -> { Setting.trendable_by_default ? where(trendable: [true, nil]) : where(trendable: true) }
   scope :not_trendable, -> { where(trendable: false) }
-  scope :recently_used, ->(account) { joins(:statuses).where(statuses: { id: account.statuses.select(:id).limit(1000) }).group(:id).order(Arel.sql('count(*) desc')) }
+  scope :recently_used, ->(account) {
+                          joins(:statuses)
+                            .where(statuses: { id: account.statuses.select(:id).limit(1000) })
+                            .group(:id).order(Arel.sql('count(*) desc'))
+                        }
   scope :matches_name, ->(term) { where(arel_table[:name].lower.matches(arel_table.lower("#{sanitize_sql_like(Tag.normalize(term))}%"), nil, true)) } # Search with case-sensitive to use B-tree index
 
   update_index('tags', :self)
@@ -105,7 +113,8 @@ class Tag < ApplicationRecord
       names = Array(name_or_names).map { |str| [normalize(str), str] }.uniq(&:first)
 
       names.map do |(normalized_name, display_name)|
-        tag = matching_name(normalized_name).first || create(name: normalized_name, display_name: display_name.gsub(HASHTAG_INVALID_CHARS_RE, ''))
+        tag = matching_name(normalized_name).first || create(name: normalized_name,
+                                                             display_name: display_name.gsub(HASHTAG_INVALID_CHARS_RE, ''))
 
         yield tag if block_given?
 
@@ -154,6 +163,9 @@ class Tag < ApplicationRecord
   end
 
   def validate_display_name_change
-    errors.add(:display_name, I18n.t('tags.does_not_match_previous_name')) unless HashtagNormalizer.new.normalize(display_name).casecmp(name.mb_chars).zero?
+    unless HashtagNormalizer.new.normalize(display_name).casecmp(name.mb_chars).zero?
+      errors.add(:display_name,
+                 I18n.t('tags.does_not_match_previous_name'))
+    end
   end
 end
diff --git a/app/models/user.rb b/app/models/user.rb
index 4344da2ff..2e3c067ec 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -498,6 +498,7 @@ class User < ApplicationRecord
     BootstrapTimelineWorker.perform_async(account_id)
     ActivityTracker.increment('activity:accounts:local')
     UserMailer.welcome(self).deliver_later
+    TriggerWebhookWorker.perform_async('account.approved', 'Account', account_id)
   end
 
   def prepare_returning_user!
diff --git a/app/models/webhook.rb b/app/models/webhook.rb
index 431edd75d..4aafb1257 100644
--- a/app/models/webhook.rb
+++ b/app/models/webhook.rb
@@ -15,6 +15,7 @@
 
 class Webhook < ApplicationRecord
   EVENTS = %w(
+    account.approved
     account.created
     report.created
   ).freeze