From 115ab2869b2742f0cc68116a8c03359d220fd608 Mon Sep 17 00:00:00 2001 From: Partho Ghosh Date: Tue, 3 Jan 2023 17:12:48 -0800 Subject: Fix ・ detection in hashtag regex to construct hashtag correctly (#22888) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fix ・ detection in hashtag regex to construct hashtag correctly * Fixed rubocop liniting issues * More rubocop linting fix --- app/models/tag.rb | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) (limited to 'app/models') 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 -- cgit From 8eb29741b440e3eeac297ec89a49a3fb1c9deb8d Mon Sep 17 00:00:00 2001 From: Alexander Ivanov Date: Thu, 5 Jan 2023 20:29:49 +0800 Subject: Add webhook `account.approved` (#22938) * Webhook `account.approved` when preparing new user * Update Webhook.EVENTS --- app/models/user.rb | 1 + app/models/webhook.rb | 1 + 2 files changed, 2 insertions(+) (limited to 'app/models') diff --git a/app/models/user.rb b/app/models/user.rb index ca98a0afa..2a42ffaa1 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -489,6 +489,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 -- cgit From 3654c945832405267e80fe24b14f7e1d74c395ba Mon Sep 17 00:00:00 2001 From: Claire Date: Thu, 5 Jan 2023 13:33:33 +0100 Subject: Strip spaces around URL when adding a relay (#22655) * Strip spaces around URL when adding a relay Fixes #22650 * Gracefuly handle URL parsing errors in URL validator --- app/models/relay.rb | 5 +++++ app/validators/url_validator.rb | 2 ++ 2 files changed, 7 insertions(+) (limited to 'app/models') 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/validators/url_validator.rb b/app/validators/url_validator.rb index 75d1edb87..a90fb6958 100644 --- a/app/validators/url_validator.rb +++ b/app/validators/url_validator.rb @@ -10,5 +10,7 @@ class URLValidator < ActiveModel::EachValidator def compliant?(url) parsed_url = Addressable::URI.parse(url) parsed_url && %w(http https).include?(parsed_url.scheme) && parsed_url.host + rescue Addressable::URI::InvalidURIError + false end end -- cgit From acec1fb745456dd3093ac31291c3757e55f39160 Mon Sep 17 00:00:00 2001 From: Claire Date: Thu, 5 Jan 2023 13:42:03 +0100 Subject: Fix site upload validations (#22479) * Fix site settings media upload handling of DimensionsValidationError Fixes #22234 * Fix underlying validations not being performed for site uploads --- app/models/form/admin_settings.rb | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) (limited to 'app/models') diff --git a/app/models/form/admin_settings.rb b/app/models/form/admin_settings.rb index 431d33bcd..dc6cc5ed3 100644 --- a/app/models/form/admin_settings.rb +++ b/app/models/form/admin_settings.rb @@ -66,6 +66,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 @@ -87,11 +88,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 unless instance_variable_defined?("@#{key}") @@ -116,4 +122,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 -- cgit