diff options
Diffstat (limited to 'app/models')
-rw-r--r-- | app/models/account.rb | 44 | ||||
-rw-r--r-- | app/models/concerns/account_associations.rb | 1 | ||||
-rw-r--r-- | app/models/concerns/account_finder_concern.rb | 2 | ||||
-rw-r--r-- | app/models/concerns/streamable.rb | 43 | ||||
-rw-r--r-- | app/models/form/admin_settings.rb | 2 | ||||
-rw-r--r-- | app/models/media_attachment.rb | 16 | ||||
-rw-r--r-- | app/models/remote_profile.rb | 57 | ||||
-rw-r--r-- | app/models/status.rb | 13 | ||||
-rw-r--r-- | app/models/stream_entry.rb | 59 | ||||
-rw-r--r-- | app/models/tag.rb | 2 | ||||
-rw-r--r-- | app/models/user.rb | 2 |
11 files changed, 38 insertions, 203 deletions
diff --git a/app/models/account.rb b/app/models/account.rb index 3d7b0dda3..3370fbc5e 100644 --- a/app/models/account.rb +++ b/app/models/account.rb @@ -45,6 +45,7 @@ # also_known_as :string is an Array # silenced_at :datetime # suspended_at :datetime +# trust_level :integer # class Account < ApplicationRecord @@ -66,6 +67,11 @@ class Account < ApplicationRecord MAX_NOTE_LENGTH = (ENV['MAX_BIO_CHARS'] || 500).to_i MAX_FIELDS = (ENV['MAX_PROFILE_FIELDS'] || 4).to_i + TRUST_LEVELS = { + untrusted: 0, + trusted: 1, + }.freeze + enum protocol: [:ostatus, :activitypub] validates :username, presence: true @@ -75,7 +81,7 @@ class Account < ApplicationRecord validates :username, format: { with: /\A#{USERNAME_RE}\z/i }, if: -> { !local? && will_save_change_to_username? } # Local user validations - validates :username, format: { with: /\A[a-z0-9_]+\z/i }, length: { maximum: 30 }, if: -> { local? && will_save_change_to_username? } + validates :username, format: { with: /\A[a-z0-9_]+\z/i }, length: { maximum: 30 }, if: -> { local? && will_save_change_to_username? && actor_type != 'Application' } validates_with UniqueUsernameValidator, if: -> { local? && will_save_change_to_username? } validates_with UnreservedUsernameValidator, if: -> { local? && will_save_change_to_username? } validates :display_name, length: { maximum: MAX_DISPLAY_NAME_LENGTH }, if: -> { local? && will_save_change_to_display_name? } @@ -137,6 +143,10 @@ class Account < ApplicationRecord %w(Application Service).include? actor_type end + def instance_actor? + id == -99 + end + alias bot bot? def bot=(val) @@ -167,30 +177,31 @@ class Account < ApplicationRecord last_webfingered_at.nil? || last_webfingered_at <= 1.day.ago end + def trust_level + self[:trust_level] || 0 + end + def refresh! - return if local? - ResolveAccountService.new.call(acct) + ResolveAccountService.new.call(acct) unless local? end def silenced? silenced_at.present? end - def silence!(date = nil) - date ||= Time.now.utc + def silence!(date = Time.now.utc) update!(silenced_at: date) end def unsilence! - update!(silenced_at: nil) + update!(silenced_at: nil, trust_level: trust_level == TRUST_LEVELS[:untrusted] ? TRUST_LEVELS[:trusted] : trust_level) end def suspended? suspended_at.present? end - def suspend!(date = nil) - date ||= Time.now.utc + def suspend!(date = Time.now.utc) transaction do user&.disable! if local? update!(suspended_at: date) @@ -296,21 +307,6 @@ class Account < ApplicationRecord self.fields = tmp end - def magic_key - modulus, exponent = [keypair.public_key.n, keypair.public_key.e].map do |component| - result = [] - - until component.zero? - result << [component % 256].pack('C') - component >>= 8 - end - - result.reverse.join - end - - (['RSA'] + [modulus, exponent].map { |n| Base64.urlsafe_encode64(n) }).join('.') - end - def subscription(webhook_url) @subscription ||= OStatus2::Subscription.new(remote_url, secret: secret, webhook: webhook_url, hub: hub_url) end @@ -508,7 +504,7 @@ class Account < ApplicationRecord end def generate_keys - return unless local? && !Rails.env.test? + return unless local? && private_key.blank? && public_key.blank? keypair = OpenSSL::PKey::RSA.new(2048) self.private_key = keypair.to_pem diff --git a/app/models/concerns/account_associations.rb b/app/models/concerns/account_associations.rb index ecccaf35e..2877b9c25 100644 --- a/app/models/concerns/account_associations.rb +++ b/app/models/concerns/account_associations.rb @@ -11,7 +11,6 @@ module AccountAssociations has_many :identity_proofs, class_name: 'AccountIdentityProof', dependent: :destroy, inverse_of: :account # Timelines - has_many :stream_entries, inverse_of: :account, dependent: :destroy has_many :statuses, inverse_of: :account, dependent: :destroy has_many :favourites, inverse_of: :account, dependent: :destroy has_many :bookmarks, inverse_of: :account, dependent: :destroy diff --git a/app/models/concerns/account_finder_concern.rb b/app/models/concerns/account_finder_concern.rb index ccd7bfa12..a54c2174d 100644 --- a/app/models/concerns/account_finder_concern.rb +++ b/app/models/concerns/account_finder_concern.rb @@ -13,7 +13,7 @@ module AccountFinderConcern end def representative - find_local(Setting.site_contact_username.strip.gsub(/\A@/, '')) || Account.local.without_suspended.first + Account.find(-99) end def find_local(username) diff --git a/app/models/concerns/streamable.rb b/app/models/concerns/streamable.rb deleted file mode 100644 index 7c9edb8ef..000000000 --- a/app/models/concerns/streamable.rb +++ /dev/null @@ -1,43 +0,0 @@ -# frozen_string_literal: true - -module Streamable - extend ActiveSupport::Concern - - included do - has_one :stream_entry, as: :activity - - after_create do - account.stream_entries.create!(activity: self, hidden: hidden?) if needs_stream_entry? - end - end - - def title - super - end - - def content - title - end - - def target - super - end - - def object_type - :activity - end - - def thread - super - end - - def hidden? - false - end - - private - - def needs_stream_entry? - account.local? - end -end diff --git a/app/models/form/admin_settings.rb b/app/models/form/admin_settings.rb index 0e9bfb265..ecaed44f6 100644 --- a/app/models/form/admin_settings.rb +++ b/app/models/form/admin_settings.rb @@ -34,6 +34,7 @@ class Form::AdminSettings mascot show_reblogs_in_public_timelines show_replies_in_public_timelines + spam_check_enabled ).freeze BOOLEAN_KEYS = %i( @@ -49,6 +50,7 @@ class Form::AdminSettings enable_keybase show_reblogs_in_public_timelines show_replies_in_public_timelines + spam_check_enabled ).freeze UPLOAD_KEYS = %i( diff --git a/app/models/media_attachment.rb b/app/models/media_attachment.rb index 815ac0258..189d80e77 100644 --- a/app/models/media_attachment.rb +++ b/app/models/media_attachment.rb @@ -26,14 +26,14 @@ class MediaAttachment < ApplicationRecord enum type: [:image, :gifv, :video, :unknown, :audio] - IMAGE_FILE_EXTENSIONS = ['.jpg', '.jpeg', '.png', '.gif', '.webp'].freeze - VIDEO_FILE_EXTENSIONS = ['.webm', '.mp4', '.m4v', '.mov'].freeze - AUDIO_FILE_EXTENSIONS = ['.ogg', '.oga', '.mp3', '.m4a', '.wav', '.flac', '.opus'].freeze - - IMAGE_MIME_TYPES = ['image/jpeg', 'image/png', 'image/gif', 'image/webp'].freeze - VIDEO_MIME_TYPES = ['video/webm', 'video/mp4', 'video/quicktime', 'video/ogg'].freeze - VIDEO_CONVERTIBLE_MIME_TYPES = ['video/webm', 'video/quicktime'].freeze - AUDIO_MIME_TYPES = ['audio/wave', 'audio/wav', 'audio/x-wav', 'audio/x-wave', 'audio/vdn.wav', 'audio/x-pn-wave', 'audio/ogg', 'audio/mpeg', 'audio/mp3', 'audio/mp4', 'audio/webm', 'audio/flac'].freeze + IMAGE_FILE_EXTENSIONS = %w(.jpg .jpeg .png .gif .webp).freeze + VIDEO_FILE_EXTENSIONS = %w(.webm .mp4 .m4v .mov).freeze + AUDIO_FILE_EXTENSIONS = %w(.ogg .oga .mp3 .wav .flac .opus .aac .m4a .3gp).freeze + + IMAGE_MIME_TYPES = %w(image/jpeg image/png image/gif image/webp).freeze + VIDEO_MIME_TYPES = %w(video/webm video/mp4 video/quicktime video/ogg).freeze + VIDEO_CONVERTIBLE_MIME_TYPES = %w(video/webm video/quicktime).freeze + AUDIO_MIME_TYPES = %w(audio/wave audio/wav audio/x-wav audio/x-pn-wave audio/ogg audio/mpeg audio/mp3 audio/webm audio/flac audio/aac audio/m4a audio/3gpp).freeze BLURHASH_OPTIONS = { x_comp: 4, diff --git a/app/models/remote_profile.rb b/app/models/remote_profile.rb deleted file mode 100644 index 742d2b56f..000000000 --- a/app/models/remote_profile.rb +++ /dev/null @@ -1,57 +0,0 @@ -# frozen_string_literal: true - -class RemoteProfile - include ActiveModel::Model - - attr_reader :document - - def initialize(body) - @document = Nokogiri::XML.parse(body, nil, 'utf-8') - end - - def root - @root ||= document.at_xpath('/atom:feed|/atom:entry', atom: OStatus::TagManager::XMLNS) - end - - def author - @author ||= root.at_xpath('./atom:author|./dfrn:owner', atom: OStatus::TagManager::XMLNS, dfrn: OStatus::TagManager::DFRN_XMLNS) - end - - def hub_link - @hub_link ||= link_href_from_xml(root, 'hub') - end - - def display_name - @display_name ||= author.at_xpath('./poco:displayName', poco: OStatus::TagManager::POCO_XMLNS)&.content - end - - def note - @note ||= author.at_xpath('./atom:summary|./poco:note', atom: OStatus::TagManager::XMLNS, poco: OStatus::TagManager::POCO_XMLNS)&.content - end - - def scope - @scope ||= author.at_xpath('./mastodon:scope', mastodon: OStatus::TagManager::MTDN_XMLNS)&.content - end - - def avatar - @avatar ||= link_href_from_xml(author, 'avatar') - end - - def header - @header ||= link_href_from_xml(author, 'header') - end - - def emojis - @emojis ||= author.xpath('./xmlns:link[@rel="emoji"]', xmlns: OStatus::TagManager::XMLNS) - end - - def locked? - scope == 'private' - end - - private - - def link_href_from_xml(xml, type) - xml.at_xpath(%(./atom:link[@rel="#{type}"]/@href), atom: OStatus::TagManager::XMLNS)&.content - end -end diff --git a/app/models/status.rb b/app/models/status.rb index 5adccb722..642d3cf5e 100644 --- a/app/models/status.rb +++ b/app/models/status.rb @@ -31,7 +31,6 @@ class Status < ApplicationRecord before_destroy :unlink_from_conversations include Paginable - include Streamable include Cacheable include StatusThreadingConcern @@ -65,7 +64,6 @@ class Status < ApplicationRecord has_and_belongs_to_many :preview_cards 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 :poll, inverse_of: :status, dependent: :destroy @@ -113,13 +111,11 @@ class Status < ApplicationRecord :status_stat, :tags, :preview_cards, - :stream_entry, :preloadable_poll, account: :account_stat, active_mentions: { account: :account_stat }, reblog: [ :application, - :stream_entry, :tags, :preview_cards, :media_attachments, @@ -204,7 +200,7 @@ class Status < ApplicationRecord end def hidden? - private_visibility? || direct_visibility? || limited_visibility? + !distributable? end def distributable? @@ -523,7 +519,8 @@ class Status < ApplicationRecord end def update_statistics - return unless public_visibility? || unlisted_visibility? + return unless distributable? + ActivityTracker.increment('activity:statuses:local') end @@ -532,7 +529,7 @@ class Status < ApplicationRecord account&.increment_count!(:statuses_count) reblog&.increment_count!(:reblogs_count) if reblog? - thread&.increment_count!(:replies_count) if in_reply_to_id.present? && (public_visibility? || unlisted_visibility?) + thread&.increment_count!(:replies_count) if in_reply_to_id.present? && distributable? end def decrement_counter_caches @@ -540,7 +537,7 @@ class Status < ApplicationRecord account&.decrement_count!(:statuses_count) reblog&.decrement_count!(:reblogs_count) if reblog? - thread&.decrement_count!(:replies_count) if in_reply_to_id.present? && (public_visibility? || unlisted_visibility?) + thread&.decrement_count!(:replies_count) if in_reply_to_id.present? && distributable? end def unlink_from_conversations diff --git a/app/models/stream_entry.rb b/app/models/stream_entry.rb deleted file mode 100644 index edd30487e..000000000 --- a/app/models/stream_entry.rb +++ /dev/null @@ -1,59 +0,0 @@ -# frozen_string_literal: true -# == Schema Information -# -# Table name: stream_entries -# -# id :bigint(8) not null, primary key -# activity_id :bigint(8) -# activity_type :string -# created_at :datetime not null -# updated_at :datetime not null -# hidden :boolean default(FALSE), not null -# account_id :bigint(8) -# - -class StreamEntry < ApplicationRecord - include Paginable - - belongs_to :account, inverse_of: :stream_entries - belongs_to :activity, polymorphic: true - belongs_to :status, foreign_type: 'Status', foreign_key: 'activity_id', inverse_of: :stream_entry - - validates :account, :activity, presence: true - - STATUS_INCLUDES = [:account, :stream_entry, :conversation, :media_attachments, :tags, mentions: :account, reblog: [:stream_entry, :account, :conversation, :media_attachments, :tags, mentions: :account], thread: [:stream_entry, :account]].freeze - - default_scope { where(activity_type: 'Status') } - scope :recent, -> { reorder(id: :desc) } - scope :with_includes, -> { includes(:account, status: STATUS_INCLUDES) } - - delegate :target, :title, :content, :thread, :local_only?, - to: :status, - allow_nil: true - - def object_type - orphaned? || targeted? ? :activity : status.object_type - end - - def verb - orphaned? ? :delete : status.verb - end - - def targeted? - [:follow, :request_friend, :authorize, :reject, :unfollow, :block, :unblock, :share, :favorite].include? verb - end - - def threaded? - (verb == :favorite || object_type == :comment) && !thread.nil? - end - - def mentions - orphaned? ? [] : status.active_mentions.map(&:account) - end - - private - - def orphaned? - status.nil? - end -end diff --git a/app/models/tag.rb b/app/models/tag.rb index 7db76d157..01bace2bb 100644 --- a/app/models/tag.rb +++ b/app/models/tag.rb @@ -17,7 +17,7 @@ class Tag < ApplicationRecord has_many :featured_tags, dependent: :destroy, inverse_of: :tag has_one :account_tag_stat, dependent: :destroy - HASHTAG_NAME_RE = '[[:word:]_]*[[:alpha:]_·][[:word:]_]*' + HASHTAG_NAME_RE = '[[:word:]_][[:word:]_]*[[:alpha:]_·]*[[:word:]_·]*[[:word:]_]' HASHTAG_RE = /(?:^|[^\/\)\w])#(#{HASHTAG_NAME_RE})/i validates :name, presence: true, uniqueness: true, format: { with: /\A#{HASHTAG_NAME_RE}\z/i } diff --git a/app/models/user.rb b/app/models/user.rb index bb903a45c..72fc92195 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -106,7 +106,7 @@ class User < ApplicationRecord delegate :auto_play_gif, :default_sensitive, :unfollow_modal, :boost_modal, :favourite_modal, :delete_modal, :reduce_motion, :system_font_ui, :noindex, :flavour, :skin, :display_media, :hide_network, :hide_followers_count, :expand_spoilers, :default_language, :aggregate_reblogs, :show_application, - :advanced_layout, :default_content_type, :use_blurhash, :use_pending_items, to: :settings, prefix: :setting, allow_nil: false + :advanced_layout, :default_content_type, :use_blurhash, :use_pending_items, :use_pending_items, to: :settings, prefix: :setting, allow_nil: false attr_reader :invite_code attr_writer :external |