Merge remote-tracking branch 'upstream/main'
All checks were successful
continuous-integration/drone Build is passing
All checks were successful
continuous-integration/drone Build is passing
This commit is contained in:
commit
5082246ee5
71 changed files with 229 additions and 206 deletions
|
@ -107,25 +107,11 @@ Rails/ApplicationController:
|
||||||
# Include: app/models/**/*.rb
|
# Include: app/models/**/*.rb
|
||||||
Rails/HasAndBelongsToMany:
|
Rails/HasAndBelongsToMany:
|
||||||
Exclude:
|
Exclude:
|
||||||
- 'app/models/concerns/account_associations.rb'
|
- 'app/models/concerns/account/associations.rb'
|
||||||
- 'app/models/preview_card.rb'
|
- 'app/models/preview_card.rb'
|
||||||
- 'app/models/status.rb'
|
- 'app/models/status.rb'
|
||||||
- 'app/models/tag.rb'
|
- 'app/models/tag.rb'
|
||||||
|
|
||||||
# Configuration parameters: Include.
|
|
||||||
# Include: app/models/**/*.rb
|
|
||||||
Rails/HasManyOrHasOneDependent:
|
|
||||||
Exclude:
|
|
||||||
- 'app/models/concerns/account_counters.rb'
|
|
||||||
- 'app/models/conversation.rb'
|
|
||||||
- 'app/models/custom_emoji.rb'
|
|
||||||
- 'app/models/custom_emoji_category.rb'
|
|
||||||
- 'app/models/domain_block.rb'
|
|
||||||
- 'app/models/invite.rb'
|
|
||||||
- 'app/models/status.rb'
|
|
||||||
- 'app/models/user.rb'
|
|
||||||
- 'app/models/web/push_subscription.rb'
|
|
||||||
|
|
||||||
# Configuration parameters: Include.
|
# Configuration parameters: Include.
|
||||||
# Include: app/controllers/**/*.rb, app/mailers/**/*.rb
|
# Include: app/controllers/**/*.rb, app/mailers/**/*.rb
|
||||||
Rails/LexicallyScopedActionFilter:
|
Rails/LexicallyScopedActionFilter:
|
||||||
|
@ -172,7 +158,7 @@ Rails/SkipsModelValidations:
|
||||||
Exclude:
|
Exclude:
|
||||||
- 'app/controllers/admin/invites_controller.rb'
|
- 'app/controllers/admin/invites_controller.rb'
|
||||||
- 'app/controllers/concerns/session_tracking_concern.rb'
|
- 'app/controllers/concerns/session_tracking_concern.rb'
|
||||||
- 'app/models/concerns/account_merging.rb'
|
- 'app/models/concerns/account/merging.rb'
|
||||||
- 'app/models/concerns/expireable.rb'
|
- 'app/models/concerns/expireable.rb'
|
||||||
- 'app/models/status.rb'
|
- 'app/models/status.rb'
|
||||||
- 'app/models/trends/links.rb'
|
- 'app/models/trends/links.rb'
|
||||||
|
@ -252,7 +238,7 @@ Rails/WhereExists:
|
||||||
- 'app/lib/feed_manager.rb'
|
- 'app/lib/feed_manager.rb'
|
||||||
- 'app/lib/status_cache_hydrator.rb'
|
- 'app/lib/status_cache_hydrator.rb'
|
||||||
- 'app/lib/suspicious_sign_in_detector.rb'
|
- 'app/lib/suspicious_sign_in_detector.rb'
|
||||||
- 'app/models/concerns/account_interactions.rb'
|
- 'app/models/concerns/account/interactions.rb'
|
||||||
- 'app/models/featured_tag.rb'
|
- 'app/models/featured_tag.rb'
|
||||||
- 'app/models/poll.rb'
|
- 'app/models/poll.rb'
|
||||||
- 'app/models/session_activation.rb'
|
- 'app/models/session_activation.rb'
|
||||||
|
@ -342,8 +328,8 @@ Style/GuardClause:
|
||||||
- 'app/lib/request_pool.rb'
|
- 'app/lib/request_pool.rb'
|
||||||
- 'app/lib/webfinger.rb'
|
- 'app/lib/webfinger.rb'
|
||||||
- 'app/lib/webfinger_resource.rb'
|
- 'app/lib/webfinger_resource.rb'
|
||||||
- 'app/models/concerns/account_counters.rb'
|
- 'app/models/concerns/account/counters.rb'
|
||||||
- 'app/models/concerns/ldap_authenticable.rb'
|
- 'app/models/concerns/user/ldap_authenticable.rb'
|
||||||
- 'app/models/tag.rb'
|
- 'app/models/tag.rb'
|
||||||
- 'app/models/user.rb'
|
- 'app/models/user.rb'
|
||||||
- 'app/services/fan_out_on_write_service.rb'
|
- 'app/services/fan_out_on_write_service.rb'
|
||||||
|
@ -372,8 +358,8 @@ Style/HashAsLastArrayItem:
|
||||||
Exclude:
|
Exclude:
|
||||||
- 'app/controllers/admin/statuses_controller.rb'
|
- 'app/controllers/admin/statuses_controller.rb'
|
||||||
- 'app/controllers/api/v1/statuses_controller.rb'
|
- 'app/controllers/api/v1/statuses_controller.rb'
|
||||||
- 'app/models/concerns/account_counters.rb'
|
- 'app/models/concerns/account/counters.rb'
|
||||||
- 'app/models/concerns/status_threading_concern.rb'
|
- 'app/models/concerns/status/threading_concern.rb'
|
||||||
- 'app/models/status.rb'
|
- 'app/models/status.rb'
|
||||||
- 'app/services/batched_remove_status_service.rb'
|
- 'app/services/batched_remove_status_service.rb'
|
||||||
- 'app/services/notify_service.rb'
|
- 'app/services/notify_service.rb'
|
||||||
|
@ -486,7 +472,7 @@ Style/RedundantReturn:
|
||||||
# AllowedMethods: present?, blank?, presence, try, try!
|
# AllowedMethods: present?, blank?, presence, try, try!
|
||||||
Style/SafeNavigation:
|
Style/SafeNavigation:
|
||||||
Exclude:
|
Exclude:
|
||||||
- 'app/models/concerns/account_finder_concern.rb'
|
- 'app/models/concerns/account/finder_concern.rb'
|
||||||
|
|
||||||
# This cop supports safe autocorrection (--autocorrect).
|
# This cop supports safe autocorrection (--autocorrect).
|
||||||
# Configuration parameters: EnforcedStyle.
|
# Configuration parameters: EnforcedStyle.
|
||||||
|
|
|
@ -245,7 +245,7 @@ GEM
|
||||||
docile (1.4.0)
|
docile (1.4.0)
|
||||||
domain_name (0.5.20190701)
|
domain_name (0.5.20190701)
|
||||||
unf (>= 0.0.5, < 1.0.0)
|
unf (>= 0.0.5, < 1.0.0)
|
||||||
doorkeeper (5.6.7)
|
doorkeeper (5.6.8)
|
||||||
railties (>= 5)
|
railties (>= 5)
|
||||||
dotenv (2.8.1)
|
dotenv (2.8.1)
|
||||||
dotenv-rails (2.8.1)
|
dotenv-rails (2.8.1)
|
||||||
|
@ -617,7 +617,7 @@ GEM
|
||||||
redlock (1.3.2)
|
redlock (1.3.2)
|
||||||
redis (>= 3.0.0, < 6.0)
|
redis (>= 3.0.0, < 6.0)
|
||||||
regexp_parser (2.8.2)
|
regexp_parser (2.8.2)
|
||||||
reline (0.4.0)
|
reline (0.4.1)
|
||||||
io-console (~> 0.5)
|
io-console (~> 0.5)
|
||||||
request_store (1.5.1)
|
request_store (1.5.1)
|
||||||
rack (>= 1.4)
|
rack (>= 1.4)
|
||||||
|
|
|
@ -64,7 +64,7 @@ class Api::BaseController < ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
def doorkeeper_unauthorized_render_options(error: nil)
|
def doorkeeper_unauthorized_render_options(error: nil)
|
||||||
{ json: { error: (error.try(:description) || 'Not authorized') } }
|
{ json: { error: error.try(:description) || 'Not authorized' } }
|
||||||
end
|
end
|
||||||
|
|
||||||
def doorkeeper_forbidden_render_options(*)
|
def doorkeeper_forbidden_render_options(*)
|
||||||
|
|
|
@ -49,7 +49,7 @@ class Api::V1::AccountsController < Api::BaseController
|
||||||
end
|
end
|
||||||
|
|
||||||
def mute
|
def mute
|
||||||
MuteService.new.call(current_user.account, @account, notifications: truthy_param?(:notifications), duration: (params[:duration]&.to_i || 0))
|
MuteService.new.call(current_user.account, @account, notifications: truthy_param?(:notifications), duration: params[:duration].to_i)
|
||||||
render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships
|
render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -421,7 +421,7 @@ class FeedManager
|
||||||
check_for_blocks.push(status.in_reply_to_account) if status.reply? && !status.in_reply_to_account_id.nil?
|
check_for_blocks.push(status.in_reply_to_account) if status.reply? && !status.in_reply_to_account_id.nil?
|
||||||
|
|
||||||
should_filter = blocks_or_mutes?(receiver_id, check_for_blocks, :mentions) # Filter if it's from someone I blocked, in reply to someone I blocked, or mentioning someone I blocked (or muted)
|
should_filter = blocks_or_mutes?(receiver_id, check_for_blocks, :mentions) # Filter if it's from someone I blocked, in reply to someone I blocked, or mentioning someone I blocked (or muted)
|
||||||
should_filter ||= (status.account.silenced? && !Follow.where(account_id: receiver_id, target_account_id: status.account_id).exists?) # of if the account is silenced and I'm not following them
|
should_filter ||= status.account.silenced? && !Follow.where(account_id: receiver_id, target_account_id: status.account_id).exists? # of if the account is silenced and I'm not following them
|
||||||
|
|
||||||
should_filter
|
should_filter
|
||||||
end
|
end
|
||||||
|
|
|
@ -70,19 +70,20 @@ class Account < ApplicationRecord
|
||||||
URL_PREFIX_RE = %r{\Ahttp(s?)://[^/]+}
|
URL_PREFIX_RE = %r{\Ahttp(s?)://[^/]+}
|
||||||
USERNAME_ONLY_RE = /\A#{USERNAME_RE}\z/i
|
USERNAME_ONLY_RE = /\A#{USERNAME_RE}\z/i
|
||||||
|
|
||||||
include Attachmentable
|
include Attachmentable # Load prior to Avatar & Header concerns
|
||||||
include AccountAssociations
|
|
||||||
include AccountAvatar
|
include Account::Associations
|
||||||
include AccountFinderConcern
|
include Account::Avatar
|
||||||
include AccountHeader
|
include Account::Counters
|
||||||
include AccountInteractions
|
include Account::FinderConcern
|
||||||
include Paginable
|
include Account::Header
|
||||||
include AccountCounters
|
include Account::Interactions
|
||||||
include DomainNormalizable
|
include Account::Merging
|
||||||
|
include Account::Search
|
||||||
|
include Account::StatusesSearch
|
||||||
include DomainMaterializable
|
include DomainMaterializable
|
||||||
include AccountMerging
|
include DomainNormalizable
|
||||||
include AccountSearch
|
include Paginable
|
||||||
include AccountStatusesSearch
|
|
||||||
|
|
||||||
enum protocol: { ostatus: 0, activitypub: 1 }
|
enum protocol: { ostatus: 0, activitypub: 1 }
|
||||||
enum suspension_origin: { local: 0, remote: 1 }, _prefix: true
|
enum suspension_origin: { local: 0, remote: 1 }, _prefix: true
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module AccountAssociations
|
module Account::Associations
|
||||||
extend ActiveSupport::Concern
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
included do
|
included do
|
|
@ -1,6 +1,6 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module AccountAvatar
|
module Account::Avatar
|
||||||
extend ActiveSupport::Concern
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
IMAGE_MIME_TYPES = ['image/jpeg', 'image/png', 'image/gif', 'image/webp'].freeze
|
IMAGE_MIME_TYPES = ['image/jpeg', 'image/png', 'image/gif', 'image/webp'].freeze
|
|
@ -1,12 +1,12 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module AccountCounters
|
module Account::Counters
|
||||||
extend ActiveSupport::Concern
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
ALLOWED_COUNTER_KEYS = %i(statuses_count following_count followers_count).freeze
|
ALLOWED_COUNTER_KEYS = %i(statuses_count following_count followers_count).freeze
|
||||||
|
|
||||||
included do
|
included do
|
||||||
has_one :account_stat, inverse_of: :account
|
has_one :account_stat, inverse_of: :account, dependent: nil
|
||||||
after_save :save_account_stat
|
after_save :save_account_stat
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module AccountFinderConcern
|
module Account::FinderConcern
|
||||||
extend ActiveSupport::Concern
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
class_methods do
|
class_methods do
|
|
@ -1,6 +1,6 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module AccountHeader
|
module Account::Header
|
||||||
extend ActiveSupport::Concern
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
IMAGE_MIME_TYPES = ['image/jpeg', 'image/png', 'image/gif', 'image/webp'].freeze
|
IMAGE_MIME_TYPES = ['image/jpeg', 'image/png', 'image/gif', 'image/webp'].freeze
|
|
@ -1,6 +1,6 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module AccountInteractions
|
module Account::Interactions
|
||||||
extend ActiveSupport::Concern
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
class_methods do
|
class_methods do
|
|
@ -1,6 +1,6 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module AccountMerging
|
module Account::Merging
|
||||||
extend ActiveSupport::Concern
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
def merge_with!(other_account)
|
def merge_with!(other_account)
|
|
@ -1,6 +1,6 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module AccountSearch
|
module Account::Search
|
||||||
extend ActiveSupport::Concern
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
DISALLOWED_TSQUERY_CHARACTERS = /['?\\:‘’]/
|
DISALLOWED_TSQUERY_CHARACTERS = /['?\\:‘’]/
|
|
@ -1,6 +1,6 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module AccountStatusesSearch
|
module Account::StatusesSearch
|
||||||
extend ActiveSupport::Concern
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
included do
|
included do
|
|
@ -5,7 +5,7 @@ module Remotable
|
||||||
|
|
||||||
class_methods do
|
class_methods do
|
||||||
def remotable_attachment(attachment_name, limit, suppress_errors: true, download_on_assign: true, attribute_name: nil)
|
def remotable_attachment(attachment_name, limit, suppress_errors: true, download_on_assign: true, attribute_name: nil)
|
||||||
attribute_name ||= "#{attachment_name}_remote_url".to_sym
|
attribute_name ||= :"#{attachment_name}_remote_url"
|
||||||
|
|
||||||
define_method("download_#{attachment_name}!") do |url = nil|
|
define_method("download_#{attachment_name}!") do |url = nil|
|
||||||
url ||= self[attribute_name]
|
url ||= self[attribute_name]
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module StatusSafeReblogInsert
|
module Status::SafeReblogInsert
|
||||||
extend ActiveSupport::Concern
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
class_methods do
|
class_methods do
|
|
@ -1,6 +1,6 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module StatusSearchConcern
|
module Status::SearchConcern
|
||||||
extend ActiveSupport::Concern
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
included do
|
included do
|
|
@ -1,6 +1,6 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module StatusSnapshotConcern
|
module Status::SnapshotConcern
|
||||||
extend ActiveSupport::Concern
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
included do
|
included do
|
|
@ -1,6 +1,6 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module StatusThreadingConcern
|
module Status::ThreadingConcern
|
||||||
extend ActiveSupport::Concern
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
def ancestors(limit, account = nil)
|
def ancestors(limit, account = nil)
|
|
@ -1,6 +1,6 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module HasUserSettings
|
module User::HasSettings
|
||||||
extend ActiveSupport::Concern
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
included do
|
included do
|
|
@ -1,6 +1,6 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module LdapAuthenticable
|
module User::LdapAuthenticable
|
||||||
extend ActiveSupport::Concern
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
class_methods do
|
class_methods do
|
|
@ -1,6 +1,6 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module Omniauthable
|
module User::Omniauthable
|
||||||
extend ActiveSupport::Concern
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
TEMP_EMAIL_PREFIX = 'change@me'
|
TEMP_EMAIL_PREFIX = 'change@me'
|
|
@ -1,6 +1,6 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module PamAuthenticable
|
module User::PamAuthenticable
|
||||||
extend ActiveSupport::Concern
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
included do
|
included do
|
|
@ -13,7 +13,7 @@
|
||||||
class Conversation < ApplicationRecord
|
class Conversation < ApplicationRecord
|
||||||
validates :uri, uniqueness: true, if: :uri?
|
validates :uri, uniqueness: true, if: :uri?
|
||||||
|
|
||||||
has_many :statuses
|
has_many :statuses, dependent: nil
|
||||||
|
|
||||||
def local?
|
def local?
|
||||||
uri.nil?
|
uri.nil?
|
||||||
|
|
|
@ -37,7 +37,7 @@ class CustomEmoji < ApplicationRecord
|
||||||
|
|
||||||
belongs_to :category, class_name: 'CustomEmojiCategory', optional: true
|
belongs_to :category, class_name: 'CustomEmojiCategory', optional: true
|
||||||
|
|
||||||
has_one :local_counterpart, -> { where(domain: nil) }, class_name: 'CustomEmoji', primary_key: :shortcode, foreign_key: :shortcode, inverse_of: false
|
has_one :local_counterpart, -> { where(domain: nil) }, class_name: 'CustomEmoji', primary_key: :shortcode, foreign_key: :shortcode, inverse_of: false, dependent: nil
|
||||||
|
|
||||||
has_attached_file :image, styles: { static: { format: 'png', convert_options: '-coalesce +profile "!icc,*" +set date:modify +set date:create +set date:timestamp' } }, validate_media_type: false
|
has_attached_file :image, styles: { static: { format: 'png', convert_options: '-coalesce +profile "!icc,*" +set date:modify +set date:create +set date:timestamp' } }, validate_media_type: false
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
#
|
#
|
||||||
|
|
||||||
class CustomEmojiCategory < ApplicationRecord
|
class CustomEmojiCategory < ApplicationRecord
|
||||||
has_many :emojis, class_name: 'CustomEmoji', foreign_key: 'category_id', inverse_of: :category
|
has_many :emojis, class_name: 'CustomEmoji', foreign_key: 'category_id', inverse_of: :category, dependent: nil
|
||||||
|
|
||||||
validates :name, presence: true, uniqueness: true
|
validates :name, presence: true, uniqueness: true
|
||||||
end
|
end
|
||||||
|
|
|
@ -25,7 +25,7 @@ class DomainBlock < ApplicationRecord
|
||||||
|
|
||||||
validates :domain, presence: true, uniqueness: true, domain: true
|
validates :domain, presence: true, uniqueness: true, domain: true
|
||||||
|
|
||||||
has_many :accounts, foreign_key: :domain, primary_key: :domain, inverse_of: false
|
has_many :accounts, foreign_key: :domain, primary_key: :domain, inverse_of: false, dependent: nil
|
||||||
delegate :count, to: :accounts, prefix: true
|
delegate :count, to: :accounts, prefix: true
|
||||||
|
|
||||||
scope :matches_domain, ->(value) { where(arel_table[:domain].matches("%#{value}%")) }
|
scope :matches_domain, ->(value) { where(arel_table[:domain].matches("%#{value}%")) }
|
||||||
|
|
|
@ -20,7 +20,7 @@ class Invite < ApplicationRecord
|
||||||
include Expireable
|
include Expireable
|
||||||
|
|
||||||
belongs_to :user, inverse_of: :invites
|
belongs_to :user, inverse_of: :invites
|
||||||
has_many :users, inverse_of: :invite
|
has_many :users, inverse_of: :invite, dependent: nil
|
||||||
|
|
||||||
scope :available, -> { where(expires_at: nil).or(where('expires_at >= ?', Time.now.utc)) }
|
scope :available, -> { where(expires_at: nil).or(where('expires_at >= ?', Time.now.utc)) }
|
||||||
|
|
||||||
|
|
|
@ -30,14 +30,14 @@
|
||||||
#
|
#
|
||||||
|
|
||||||
class Status < ApplicationRecord
|
class Status < ApplicationRecord
|
||||||
|
include Cacheable
|
||||||
include Discard::Model
|
include Discard::Model
|
||||||
include Paginable
|
include Paginable
|
||||||
include Cacheable
|
|
||||||
include StatusThreadingConcern
|
|
||||||
include StatusSnapshotConcern
|
|
||||||
include RateLimitable
|
include RateLimitable
|
||||||
include StatusSafeReblogInsert
|
include Status::SafeReblogInsert
|
||||||
include StatusSearchConcern
|
include Status::SearchConcern
|
||||||
|
include Status::SnapshotConcern
|
||||||
|
include Status::ThreadingConcern
|
||||||
|
|
||||||
rate_limit by: :account, family: :statuses
|
rate_limit by: :account, family: :statuses
|
||||||
|
|
||||||
|
@ -66,12 +66,14 @@ class Status < ApplicationRecord
|
||||||
has_many :bookmarks, inverse_of: :status, dependent: :destroy
|
has_many :bookmarks, inverse_of: :status, dependent: :destroy
|
||||||
has_many :reblogs, foreign_key: 'reblog_of_id', class_name: 'Status', inverse_of: :reblog, dependent: :destroy
|
has_many :reblogs, foreign_key: 'reblog_of_id', class_name: 'Status', inverse_of: :reblog, dependent: :destroy
|
||||||
has_many :reblogged_by_accounts, through: :reblogs, class_name: 'Account', source: :account
|
has_many :reblogged_by_accounts, through: :reblogs, class_name: 'Account', source: :account
|
||||||
has_many :replies, foreign_key: 'in_reply_to_id', class_name: 'Status', inverse_of: :thread
|
has_many :replies, foreign_key: 'in_reply_to_id', class_name: 'Status', inverse_of: :thread, dependent: nil
|
||||||
has_many :mentions, dependent: :destroy, inverse_of: :status
|
has_many :mentions, dependent: :destroy, inverse_of: :status
|
||||||
has_many :mentioned_accounts, through: :mentions, source: :account, class_name: 'Account'
|
has_many :mentioned_accounts, through: :mentions, source: :account, class_name: 'Account'
|
||||||
has_many :active_mentions, -> { active }, class_name: 'Mention', inverse_of: :status
|
|
||||||
has_many :media_attachments, dependent: :nullify
|
has_many :media_attachments, dependent: :nullify
|
||||||
|
|
||||||
|
# The `dependent` option is enabled by the initial `mentions` association declaration
|
||||||
|
has_many :active_mentions, -> { active }, class_name: 'Mention', inverse_of: :status # rubocop:disable Rails/HasManyOrHasOneDependent
|
||||||
|
|
||||||
# Those associations are used for the private search index
|
# Those associations are used for the private search index
|
||||||
has_many :local_mentioned, -> { merge(Account.local) }, through: :active_mentions, source: :account
|
has_many :local_mentioned, -> { merge(Account.local) }, through: :active_mentions, source: :account
|
||||||
has_many :local_favorited, -> { merge(Account.local) }, through: :favourites, source: :account
|
has_many :local_favorited, -> { merge(Account.local) }, through: :favourites, source: :account
|
||||||
|
@ -80,11 +82,13 @@ class Status < ApplicationRecord
|
||||||
|
|
||||||
has_and_belongs_to_many :tags
|
has_and_belongs_to_many :tags
|
||||||
|
|
||||||
has_one :preview_cards_status, inverse_of: :status # Because of a composite primary key, the dependent option cannot be used
|
# Because of a composite primary key, the `dependent` option cannot be used on this association
|
||||||
|
has_one :preview_cards_status, inverse_of: :status # rubocop:disable Rails/HasManyOrHasOneDependent
|
||||||
|
|
||||||
has_one :notification, as: :activity, dependent: :destroy
|
has_one :notification, as: :activity, dependent: :destroy
|
||||||
has_one :status_stat, inverse_of: :status
|
has_one :status_stat, inverse_of: :status, dependent: nil
|
||||||
has_one :poll, inverse_of: :status, dependent: :destroy
|
has_one :poll, inverse_of: :status, dependent: :destroy
|
||||||
has_one :trend, class_name: 'StatusTrend', inverse_of: :status
|
has_one :trend, class_name: 'StatusTrend', inverse_of: :status, dependent: nil
|
||||||
|
|
||||||
validates :uri, uniqueness: true, presence: true, unless: :local?
|
validates :uri, uniqueness: true, presence: true, unless: :local?
|
||||||
validates :text, presence: true, unless: -> { with_media? || reblog? }
|
validates :text, presence: true, unless: -> { with_media? || reblog? }
|
||||||
|
|
|
@ -37,7 +37,7 @@ class Trends::History
|
||||||
end
|
end
|
||||||
|
|
||||||
def uses
|
def uses
|
||||||
with_redis { |redis| redis.get(key_for(:uses))&.to_i || 0 }
|
with_redis { |redis| redis.get(key_for(:uses)).to_i }
|
||||||
end
|
end
|
||||||
|
|
||||||
def add(account_id)
|
def add(account_id)
|
||||||
|
|
|
@ -53,9 +53,12 @@ class User < ApplicationRecord
|
||||||
filtered_languages
|
filtered_languages
|
||||||
)
|
)
|
||||||
|
|
||||||
include Redisable
|
|
||||||
include LanguagesHelper
|
include LanguagesHelper
|
||||||
include HasUserSettings
|
include Redisable
|
||||||
|
include User::HasSettings
|
||||||
|
include User::LdapAuthenticable
|
||||||
|
include User::Omniauthable
|
||||||
|
include User::PamAuthenticable
|
||||||
|
|
||||||
# The home and list feeds will be stored in Redis for this amount
|
# The home and list feeds will be stored in Redis for this amount
|
||||||
# of time, and status fan-out to followers will include only people
|
# of time, and status fan-out to followers will include only people
|
||||||
|
@ -75,22 +78,18 @@ class User < ApplicationRecord
|
||||||
devise :registerable, :recoverable, :validatable,
|
devise :registerable, :recoverable, :validatable,
|
||||||
:confirmable
|
:confirmable
|
||||||
|
|
||||||
include Omniauthable
|
|
||||||
include PamAuthenticable
|
|
||||||
include LdapAuthenticable
|
|
||||||
|
|
||||||
belongs_to :account, inverse_of: :user
|
belongs_to :account, inverse_of: :user
|
||||||
belongs_to :invite, counter_cache: :uses, optional: true
|
belongs_to :invite, counter_cache: :uses, optional: true
|
||||||
belongs_to :created_by_application, class_name: 'Doorkeeper::Application', optional: true
|
belongs_to :created_by_application, class_name: 'Doorkeeper::Application', optional: true
|
||||||
belongs_to :role, class_name: 'UserRole', optional: true
|
belongs_to :role, class_name: 'UserRole', optional: true
|
||||||
accepts_nested_attributes_for :account
|
accepts_nested_attributes_for :account
|
||||||
|
|
||||||
has_many :applications, class_name: 'Doorkeeper::Application', as: :owner
|
has_many :applications, class_name: 'Doorkeeper::Application', as: :owner, dependent: nil
|
||||||
has_many :backups, inverse_of: :user
|
has_many :backups, inverse_of: :user, dependent: nil
|
||||||
has_many :invites, inverse_of: :user
|
has_many :invites, inverse_of: :user, dependent: nil
|
||||||
has_many :markers, inverse_of: :user, dependent: :destroy
|
has_many :markers, inverse_of: :user, dependent: :destroy
|
||||||
has_many :webauthn_credentials, dependent: :destroy
|
has_many :webauthn_credentials, dependent: :destroy
|
||||||
has_many :ips, class_name: 'UserIp', inverse_of: :user
|
has_many :ips, class_name: 'UserIp', inverse_of: :user, dependent: nil
|
||||||
|
|
||||||
has_one :invite_request, class_name: 'UserInviteRequest', inverse_of: :user, dependent: :destroy
|
has_one :invite_request, class_name: 'UserInviteRequest', inverse_of: :user, dependent: :destroy
|
||||||
accepts_nested_attributes_for :invite_request, reject_if: ->(attributes) { attributes['text'].blank? && !Setting.require_invite_text }
|
accepts_nested_attributes_for :invite_request, reject_if: ->(attributes) { attributes['text'].blank? && !Setting.require_invite_text }
|
||||||
|
|
|
@ -62,7 +62,7 @@ class UserSettings::Setting
|
||||||
|
|
||||||
def key
|
def key
|
||||||
if namespace
|
if namespace
|
||||||
"#{namespace}.#{name}".to_sym
|
:"#{namespace}.#{name}"
|
||||||
else
|
else
|
||||||
name
|
name
|
||||||
end
|
end
|
||||||
|
|
|
@ -19,7 +19,7 @@ class Web::PushSubscription < ApplicationRecord
|
||||||
belongs_to :user, optional: true
|
belongs_to :user, optional: true
|
||||||
belongs_to :access_token, class_name: 'Doorkeeper::AccessToken', optional: true
|
belongs_to :access_token, class_name: 'Doorkeeper::AccessToken', optional: true
|
||||||
|
|
||||||
has_one :session_activation, foreign_key: 'web_push_subscription_id', inverse_of: :web_push_subscription
|
has_one :session_activation, foreign_key: 'web_push_subscription_id', inverse_of: :web_push_subscription, dependent: nil
|
||||||
|
|
||||||
validates :endpoint, presence: true
|
validates :endpoint, presence: true
|
||||||
validates :key_p256dh, presence: true
|
validates :key_p256dh, presence: true
|
||||||
|
|
|
@ -33,7 +33,7 @@
|
||||||
.fields-row
|
.fields-row
|
||||||
.fields-row__column.fields-row__column-6
|
.fields-row__column.fields-row__column-6
|
||||||
.fields-group
|
.fields-group
|
||||||
= f.input :avatar, wrapper: :with_block_label, input_html: { accept: AccountAvatar::IMAGE_MIME_TYPES.join(',') }, hint: t('simple_form.hints.defaults.avatar', dimensions: '400x400', size: number_to_human_size(AccountAvatar::LIMIT))
|
= f.input :avatar, wrapper: :with_block_label, input_html: { accept: Account::Avatar::IMAGE_MIME_TYPES.join(',') }, hint: t('simple_form.hints.defaults.avatar', dimensions: '400x400', size: number_to_human_size(Account::Avatar::LIMIT))
|
||||||
|
|
||||||
.fields-row__column.fields-row__column-6
|
.fields-row__column.fields-row__column-6
|
||||||
.fields-group
|
.fields-group
|
||||||
|
@ -46,7 +46,7 @@
|
||||||
.fields-row
|
.fields-row
|
||||||
.fields-row__column.fields-row__column-6
|
.fields-row__column.fields-row__column-6
|
||||||
.fields-group
|
.fields-group
|
||||||
= f.input :header, wrapper: :with_block_label, input_html: { accept: AccountHeader::IMAGE_MIME_TYPES.join(',') }, hint: t('simple_form.hints.defaults.header', dimensions: '1500x500', size: number_to_human_size(AccountHeader::LIMIT))
|
= f.input :header, wrapper: :with_block_label, input_html: { accept: Account::Header::IMAGE_MIME_TYPES.join(',') }, hint: t('simple_form.hints.defaults.header', dimensions: '1500x500', size: number_to_human_size(Account::Header::LIMIT))
|
||||||
|
|
||||||
.fields-row__column.fields-row__column-6
|
.fields-row__column.fields-row__column-6
|
||||||
.fields-group
|
.fields-group
|
||||||
|
|
|
@ -20,7 +20,7 @@ namespace :systemd do
|
||||||
SYSTEMD_SERVICES.each do |service|
|
SYSTEMD_SERVICES.each do |service|
|
||||||
SERVICE_ACTIONS.each do |action|
|
SERVICE_ACTIONS.each do |action|
|
||||||
desc "Perform a #{action} on #{service} service"
|
desc "Perform a #{action} on #{service} service"
|
||||||
task "#{service}:#{action}".to_sym do
|
task :"#{service}:#{action}" do
|
||||||
on roles(:app) do
|
on roles(:app) do
|
||||||
# runs e.g. "sudo restart mastodon-sidekiq.service"
|
# runs e.g. "sudo restart mastodon-sidekiq.service"
|
||||||
sudo :systemctl, action, "#{fetch(:application)}-#{service}.service"
|
sudo :systemctl, action, "#{fetch(:application)}-#{service}.service"
|
||||||
|
|
|
@ -6,6 +6,6 @@ UserRole.everyone
|
||||||
# Create default roles defined in config file
|
# Create default roles defined in config file
|
||||||
default_roles = YAML.load_file(Rails.root.join('config', 'roles.yml'))
|
default_roles = YAML.load_file(Rails.root.join('config', 'roles.yml'))
|
||||||
|
|
||||||
default_roles.each do |_, config|
|
default_roles.each_value do |config|
|
||||||
UserRole.create_with(position: config['position'], permissions_as_keys: config['permissions'], highlighted: true).find_or_create_by(name: config['name'])
|
UserRole.create_with(position: config['position'], permissions_as_keys: config['permissions'], highlighted: true).find_or_create_by(name: config['name'])
|
||||||
end
|
end
|
||||||
|
|
|
@ -59,7 +59,7 @@ services:
|
||||||
image: ghcr.io/mastodon/mastodon:v4.2.0
|
image: ghcr.io/mastodon/mastodon:v4.2.0
|
||||||
restart: always
|
restart: always
|
||||||
env_file: .env.production
|
env_file: .env.production
|
||||||
command: bash -c "rm -f /mastodon/tmp/pids/server.pid; bundle exec rails s -p 3000"
|
command: bundle exec puma -C config/puma.rb
|
||||||
networks:
|
networks:
|
||||||
- external_network
|
- external_network
|
||||||
- internal_network
|
- internal_network
|
||||||
|
|
|
@ -67,8 +67,8 @@ module Mastodon::CLI
|
||||||
local? ? username : "#{username}@#{domain}"
|
local? ? username : "#{username}@#{domain}"
|
||||||
end
|
end
|
||||||
|
|
||||||
# This is a duplicate of the AccountMerging concern because we need it to
|
# This is a duplicate of the Account::Merging concern because we need it
|
||||||
# be independent from code version.
|
# to be independent from code version.
|
||||||
def merge_with!(other_account)
|
def merge_with!(other_account)
|
||||||
# Since it's the same remote resource, the remote resource likely
|
# Since it's the same remote resource, the remote resource likely
|
||||||
# already believes we are following/blocking, so it's safe to
|
# already believes we are following/blocking, so it's safe to
|
||||||
|
|
|
@ -48,8 +48,8 @@ module Mastodon::CLI
|
||||||
next if account.avatar.blank? && account.header.blank?
|
next if account.avatar.blank? && account.header.blank?
|
||||||
next if options[:remove_headers] && account.header.blank?
|
next if options[:remove_headers] && account.header.blank?
|
||||||
|
|
||||||
size = (account.header_file_size || 0)
|
size = account.header_file_size || 0
|
||||||
size += (account.avatar_file_size || 0) if options[:prune_profiles]
|
size += account.avatar_file_size || 0 if options[:prune_profiles]
|
||||||
|
|
||||||
unless dry_run?
|
unless dry_run?
|
||||||
account.header.destroy
|
account.header.destroy
|
||||||
|
@ -265,6 +265,7 @@ module Mastodon::CLI
|
||||||
elsif options[:days].present?
|
elsif options[:days].present?
|
||||||
scope = MediaAttachment.remote
|
scope = MediaAttachment.remote
|
||||||
else
|
else
|
||||||
|
say('Specify the source of media attachments', :red)
|
||||||
exit(1)
|
exit(1)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -99,7 +99,7 @@ module Mastodon::Snowflake
|
||||||
def id_at(timestamp, with_random: true)
|
def id_at(timestamp, with_random: true)
|
||||||
id = timestamp.to_i * 1000
|
id = timestamp.to_i * 1000
|
||||||
id += rand(1000) if with_random
|
id += rand(1000) if with_random
|
||||||
id = id << 16
|
id <<= 16
|
||||||
id += rand(2**16) if with_random
|
id += rand(2**16) if with_random
|
||||||
id
|
id
|
||||||
end
|
end
|
||||||
|
|
|
@ -20,7 +20,7 @@ RSpec.describe Admin::AccountModerationNotesController do
|
||||||
|
|
||||||
it 'successfully creates a note' do
|
it 'successfully creates a note' do
|
||||||
expect { subject }.to change(AccountModerationNote, :count).by(1)
|
expect { subject }.to change(AccountModerationNote, :count).by(1)
|
||||||
expect(subject).to redirect_to admin_account_path(target_account.id)
|
expect(response).to redirect_to admin_account_path(target_account.id)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ RSpec.describe Admin::AccountModerationNotesController do
|
||||||
|
|
||||||
it 'falls to create a note' do
|
it 'falls to create a note' do
|
||||||
expect { subject }.to_not change(AccountModerationNote, :count)
|
expect { subject }.to_not change(AccountModerationNote, :count)
|
||||||
expect(subject).to render_template 'admin/accounts/show'
|
expect(response).to render_template 'admin/accounts/show'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -42,7 +42,7 @@ RSpec.describe Admin::AccountModerationNotesController do
|
||||||
|
|
||||||
it 'destroys note' do
|
it 'destroys note' do
|
||||||
expect { subject }.to change(AccountModerationNote, :count).by(-1)
|
expect { subject }.to change(AccountModerationNote, :count).by(-1)
|
||||||
expect(subject).to redirect_to admin_account_path(target_account.id)
|
expect(response).to redirect_to admin_account_path(target_account.id)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -12,24 +12,24 @@ describe Admin::CustomEmojisController do
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'GET #index' do
|
describe 'GET #index' do
|
||||||
subject { get :index }
|
|
||||||
|
|
||||||
before do
|
before do
|
||||||
Fabricate(:custom_emoji)
|
Fabricate(:custom_emoji)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'renders index page' do
|
it 'renders index page' do
|
||||||
expect(subject).to have_http_status 200
|
get :index
|
||||||
expect(subject).to render_template :index
|
|
||||||
|
expect(response).to have_http_status 200
|
||||||
|
expect(response).to render_template :index
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'GET #new' do
|
describe 'GET #new' do
|
||||||
subject { get :new }
|
|
||||||
|
|
||||||
it 'renders new page' do
|
it 'renders new page' do
|
||||||
expect(subject).to have_http_status 200
|
get :new
|
||||||
expect(subject).to render_template :new
|
|
||||||
|
expect(response).to have_http_status 200
|
||||||
|
expect(response).to render_template :new
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@ describe Admin::ReportNotesController do
|
||||||
it 'creates a report note and resolves report' do
|
it 'creates a report note and resolves report' do
|
||||||
expect { subject }.to change(ReportNote, :count).by(1)
|
expect { subject }.to change(ReportNote, :count).by(1)
|
||||||
expect(report.reload).to be_action_taken
|
expect(report.reload).to be_action_taken
|
||||||
expect(subject).to redirect_to admin_reports_path
|
expect(response).to redirect_to admin_reports_path
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@ describe Admin::ReportNotesController do
|
||||||
it 'creates a report note and does not resolve report' do
|
it 'creates a report note and does not resolve report' do
|
||||||
expect { subject }.to change(ReportNote, :count).by(1)
|
expect { subject }.to change(ReportNote, :count).by(1)
|
||||||
expect(report.reload).to_not be_action_taken
|
expect(report.reload).to_not be_action_taken
|
||||||
expect(subject).to redirect_to admin_report_path(report)
|
expect(response).to redirect_to admin_report_path(report)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -52,7 +52,7 @@ describe Admin::ReportNotesController do
|
||||||
it 'creates a report note and unresolves report' do
|
it 'creates a report note and unresolves report' do
|
||||||
expect { subject }.to change(ReportNote, :count).by(1)
|
expect { subject }.to change(ReportNote, :count).by(1)
|
||||||
expect(report.reload).to_not be_action_taken
|
expect(report.reload).to_not be_action_taken
|
||||||
expect(subject).to redirect_to admin_report_path(report)
|
expect(response).to redirect_to admin_report_path(report)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -62,7 +62,7 @@ describe Admin::ReportNotesController do
|
||||||
it 'creates a report note and does not unresolve report' do
|
it 'creates a report note and does not unresolve report' do
|
||||||
expect { subject }.to change(ReportNote, :count).by(1)
|
expect { subject }.to change(ReportNote, :count).by(1)
|
||||||
expect(report.reload).to be_action_taken
|
expect(report.reload).to be_action_taken
|
||||||
expect(subject).to redirect_to admin_report_path(report)
|
expect(response).to redirect_to admin_report_path(report)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -86,7 +86,7 @@ describe Admin::ReportNotesController do
|
||||||
|
|
||||||
it 'deletes note' do
|
it 'deletes note' do
|
||||||
expect { subject }.to change(ReportNote, :count).by(-1)
|
expect { subject }.to change(ReportNote, :count).by(-1)
|
||||||
expect(subject).to redirect_to admin_report_path(report_note.report)
|
expect(response).to redirect_to admin_report_path(report_note.report)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -6,6 +6,8 @@ require 'mastodon/cli/accounts'
|
||||||
describe Mastodon::CLI::Accounts do
|
describe Mastodon::CLI::Accounts do
|
||||||
let(:cli) { described_class.new }
|
let(:cli) { described_class.new }
|
||||||
|
|
||||||
|
it_behaves_like 'CLI Command'
|
||||||
|
|
||||||
# `parallelize_with_progress` cannot run in transactions, so instead,
|
# `parallelize_with_progress` cannot run in transactions, so instead,
|
||||||
# stub it with an alternative implementation that runs sequentially
|
# stub it with an alternative implementation that runs sequentially
|
||||||
# and can run in transactions.
|
# and can run in transactions.
|
||||||
|
@ -24,12 +26,6 @@ describe Mastodon::CLI::Accounts do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe '.exit_on_failure?' do
|
|
||||||
it 'returns true' do
|
|
||||||
expect(described_class.exit_on_failure?).to be true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
describe '#create' do
|
describe '#create' do
|
||||||
shared_examples 'a new user with given email address and username' do
|
shared_examples 'a new user with given email address and username' do
|
||||||
it 'creates a new user with the specified email address' do
|
it 'creates a new user with the specified email address' do
|
||||||
|
|
|
@ -6,11 +6,7 @@ require 'mastodon/cli/cache'
|
||||||
describe Mastodon::CLI::Cache do
|
describe Mastodon::CLI::Cache do
|
||||||
let(:cli) { described_class.new }
|
let(:cli) { described_class.new }
|
||||||
|
|
||||||
describe '.exit_on_failure?' do
|
it_behaves_like 'CLI Command'
|
||||||
it 'returns true' do
|
|
||||||
expect(described_class.exit_on_failure?).to be true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
describe '#clear' do
|
describe '#clear' do
|
||||||
before { allow(Rails.cache).to receive(:clear) }
|
before { allow(Rails.cache).to receive(:clear) }
|
||||||
|
|
|
@ -6,11 +6,7 @@ require 'mastodon/cli/canonical_email_blocks'
|
||||||
describe Mastodon::CLI::CanonicalEmailBlocks do
|
describe Mastodon::CLI::CanonicalEmailBlocks do
|
||||||
let(:cli) { described_class.new }
|
let(:cli) { described_class.new }
|
||||||
|
|
||||||
describe '.exit_on_failure?' do
|
it_behaves_like 'CLI Command'
|
||||||
it 'returns true' do
|
|
||||||
expect(described_class.exit_on_failure?).to be true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
describe '#find' do
|
describe '#find' do
|
||||||
let(:arguments) { ['user@example.com'] }
|
let(:arguments) { ['user@example.com'] }
|
||||||
|
|
|
@ -4,9 +4,5 @@ require 'rails_helper'
|
||||||
require 'mastodon/cli/domains'
|
require 'mastodon/cli/domains'
|
||||||
|
|
||||||
describe Mastodon::CLI::Domains do
|
describe Mastodon::CLI::Domains do
|
||||||
describe '.exit_on_failure?' do
|
it_behaves_like 'CLI Command'
|
||||||
it 'returns true' do
|
|
||||||
expect(described_class.exit_on_failure?).to be true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -4,9 +4,5 @@ require 'rails_helper'
|
||||||
require 'mastodon/cli/email_domain_blocks'
|
require 'mastodon/cli/email_domain_blocks'
|
||||||
|
|
||||||
describe Mastodon::CLI::EmailDomainBlocks do
|
describe Mastodon::CLI::EmailDomainBlocks do
|
||||||
describe '.exit_on_failure?' do
|
it_behaves_like 'CLI Command'
|
||||||
it 'returns true' do
|
|
||||||
expect(described_class.exit_on_failure?).to be true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -4,9 +4,5 @@ require 'rails_helper'
|
||||||
require 'mastodon/cli/emoji'
|
require 'mastodon/cli/emoji'
|
||||||
|
|
||||||
describe Mastodon::CLI::Emoji do
|
describe Mastodon::CLI::Emoji do
|
||||||
describe '.exit_on_failure?' do
|
it_behaves_like 'CLI Command'
|
||||||
it 'returns true' do
|
|
||||||
expect(described_class.exit_on_failure?).to be true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -6,11 +6,7 @@ require 'mastodon/cli/feeds'
|
||||||
describe Mastodon::CLI::Feeds do
|
describe Mastodon::CLI::Feeds do
|
||||||
let(:cli) { described_class.new }
|
let(:cli) { described_class.new }
|
||||||
|
|
||||||
describe '.exit_on_failure?' do
|
it_behaves_like 'CLI Command'
|
||||||
it 'returns true' do
|
|
||||||
expect(described_class.exit_on_failure?).to be true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
describe '#build' do
|
describe '#build' do
|
||||||
before { Fabricate(:account) }
|
before { Fabricate(:account) }
|
||||||
|
|
|
@ -6,11 +6,7 @@ require 'mastodon/cli/ip_blocks'
|
||||||
describe Mastodon::CLI::IpBlocks do
|
describe Mastodon::CLI::IpBlocks do
|
||||||
let(:cli) { described_class.new }
|
let(:cli) { described_class.new }
|
||||||
|
|
||||||
describe '.exit_on_failure?' do
|
it_behaves_like 'CLI Command'
|
||||||
it 'returns true' do
|
|
||||||
expect(described_class.exit_on_failure?).to be true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
describe '#add' do
|
describe '#add' do
|
||||||
let(:ip_list) do
|
let(:ip_list) do
|
||||||
|
|
|
@ -4,11 +4,7 @@ require 'rails_helper'
|
||||||
require 'mastodon/cli/main'
|
require 'mastodon/cli/main'
|
||||||
|
|
||||||
describe Mastodon::CLI::Main do
|
describe Mastodon::CLI::Main do
|
||||||
describe '.exit_on_failure?' do
|
it_behaves_like 'CLI Command'
|
||||||
it 'returns true' do
|
|
||||||
expect(described_class.exit_on_failure?).to be true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
describe 'version' do
|
describe 'version' do
|
||||||
it 'returns the Mastodon version' do
|
it 'returns the Mastodon version' do
|
||||||
|
|
|
@ -6,11 +6,7 @@ require 'mastodon/cli/maintenance'
|
||||||
describe Mastodon::CLI::Maintenance do
|
describe Mastodon::CLI::Maintenance do
|
||||||
let(:cli) { described_class.new }
|
let(:cli) { described_class.new }
|
||||||
|
|
||||||
describe '.exit_on_failure?' do
|
it_behaves_like 'CLI Command'
|
||||||
it 'returns true' do
|
|
||||||
expect(described_class.exit_on_failure?).to be true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
describe '#fix_duplicates' do
|
describe '#fix_duplicates' do
|
||||||
context 'when the database version is too old' do
|
context 'when the database version is too old' do
|
||||||
|
|
|
@ -6,11 +6,7 @@ require 'mastodon/cli/media'
|
||||||
describe Mastodon::CLI::Media do
|
describe Mastodon::CLI::Media do
|
||||||
let(:cli) { described_class.new }
|
let(:cli) { described_class.new }
|
||||||
|
|
||||||
describe '.exit_on_failure?' do
|
it_behaves_like 'CLI Command'
|
||||||
it 'returns true' do
|
|
||||||
expect(described_class.exit_on_failure?).to be true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
describe '#remove' do
|
describe '#remove' do
|
||||||
context 'with --prune-profiles and --remove-headers' do
|
context 'with --prune-profiles and --remove-headers' do
|
||||||
|
@ -78,4 +74,89 @@ describe Mastodon::CLI::Media do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe '#usage' do
|
||||||
|
context 'without options' do
|
||||||
|
let(:options) { {} }
|
||||||
|
|
||||||
|
it 'reports about storage size' do
|
||||||
|
expect { cli.invoke(:usage, [], options) }.to output(
|
||||||
|
a_string_including('0 Bytes')
|
||||||
|
).to_stdout
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#refresh' do
|
||||||
|
context 'without any options' do
|
||||||
|
let(:options) { {} }
|
||||||
|
|
||||||
|
it 'warns about usage and exits' do
|
||||||
|
expect { cli.invoke(:refresh, [], options) }.to output(
|
||||||
|
a_string_including('Specify the source')
|
||||||
|
).to_stdout.and raise_error(SystemExit)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with --status option' do
|
||||||
|
before do
|
||||||
|
media_attachment.update(file_file_name: nil)
|
||||||
|
end
|
||||||
|
|
||||||
|
let(:media_attachment) { Fabricate(:media_attachment, status: status, remote_url: 'https://host.example/asset.jpg') }
|
||||||
|
let(:options) { { status: status.id } }
|
||||||
|
let(:status) { Fabricate(:status) }
|
||||||
|
|
||||||
|
it 'redownloads the attachment file' do
|
||||||
|
expect { cli.invoke(:refresh, [], options) }.to output(
|
||||||
|
a_string_including('Downloaded 1 media')
|
||||||
|
).to_stdout
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with --account option' do
|
||||||
|
context 'when the account does not exist' do
|
||||||
|
let(:options) { { account: 'not-real-user@example.host' } }
|
||||||
|
|
||||||
|
it 'warns about usage and exits' do
|
||||||
|
expect { cli.invoke(:refresh, [], options) }.to output(
|
||||||
|
a_string_including('No such account')
|
||||||
|
).to_stdout.and raise_error(SystemExit)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when the account exists' do
|
||||||
|
before do
|
||||||
|
media_attachment.update(file_file_name: nil)
|
||||||
|
end
|
||||||
|
|
||||||
|
let(:media_attachment) { Fabricate(:media_attachment, account: account) }
|
||||||
|
let(:options) { { account: account.acct } }
|
||||||
|
let(:account) { Fabricate(:account) }
|
||||||
|
|
||||||
|
it 'redownloads the attachment file' do
|
||||||
|
expect { cli.invoke(:refresh, [], options) }.to output(
|
||||||
|
a_string_including('Downloaded 1 media')
|
||||||
|
).to_stdout
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with --domain option' do
|
||||||
|
before do
|
||||||
|
media_attachment.update(file_file_name: nil)
|
||||||
|
end
|
||||||
|
|
||||||
|
let(:domain) { 'example.host' }
|
||||||
|
let(:media_attachment) { Fabricate(:media_attachment, account: account) }
|
||||||
|
let(:options) { { domain: domain } }
|
||||||
|
let(:account) { Fabricate(:account, domain: domain) }
|
||||||
|
|
||||||
|
it 'redownloads the attachment file' do
|
||||||
|
expect { cli.invoke(:refresh, [], options) }.to output(
|
||||||
|
a_string_including('Downloaded 1 media')
|
||||||
|
).to_stdout
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -6,11 +6,7 @@ require 'mastodon/cli/preview_cards'
|
||||||
describe Mastodon::CLI::PreviewCards do
|
describe Mastodon::CLI::PreviewCards do
|
||||||
let(:cli) { described_class.new }
|
let(:cli) { described_class.new }
|
||||||
|
|
||||||
describe '.exit_on_failure?' do
|
it_behaves_like 'CLI Command'
|
||||||
it 'returns true' do
|
|
||||||
expect(described_class.exit_on_failure?).to be true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
describe '#remove' do
|
describe '#remove' do
|
||||||
context 'with relevant preview cards' do
|
context 'with relevant preview cards' do
|
||||||
|
|
|
@ -4,9 +4,5 @@ require 'rails_helper'
|
||||||
require 'mastodon/cli/search'
|
require 'mastodon/cli/search'
|
||||||
|
|
||||||
describe Mastodon::CLI::Search do
|
describe Mastodon::CLI::Search do
|
||||||
describe '.exit_on_failure?' do
|
it_behaves_like 'CLI Command'
|
||||||
it 'returns true' do
|
|
||||||
expect(described_class.exit_on_failure?).to be true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -4,11 +4,7 @@ require 'rails_helper'
|
||||||
require 'mastodon/cli/settings'
|
require 'mastodon/cli/settings'
|
||||||
|
|
||||||
describe Mastodon::CLI::Settings do
|
describe Mastodon::CLI::Settings do
|
||||||
describe '.exit_on_failure?' do
|
it_behaves_like 'CLI Command'
|
||||||
it 'returns true' do
|
|
||||||
expect(described_class.exit_on_failure?).to be true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
describe 'subcommand "registrations"' do
|
describe 'subcommand "registrations"' do
|
||||||
let(:cli) { Mastodon::CLI::Registrations.new }
|
let(:cli) { Mastodon::CLI::Registrations.new }
|
||||||
|
|
|
@ -6,11 +6,7 @@ require 'mastodon/cli/statuses'
|
||||||
describe Mastodon::CLI::Statuses do
|
describe Mastodon::CLI::Statuses do
|
||||||
let(:cli) { described_class.new }
|
let(:cli) { described_class.new }
|
||||||
|
|
||||||
describe '.exit_on_failure?' do
|
it_behaves_like 'CLI Command'
|
||||||
it 'returns true' do
|
|
||||||
expect(described_class.exit_on_failure?).to be true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
describe '#remove', use_transactional_tests: false do
|
describe '#remove', use_transactional_tests: false do
|
||||||
context 'with small batch size' do
|
context 'with small batch size' do
|
||||||
|
|
|
@ -4,9 +4,5 @@ require 'rails_helper'
|
||||||
require 'mastodon/cli/upgrade'
|
require 'mastodon/cli/upgrade'
|
||||||
|
|
||||||
describe Mastodon::CLI::Upgrade do
|
describe Mastodon::CLI::Upgrade do
|
||||||
describe '.exit_on_failure?' do
|
it_behaves_like 'CLI Command'
|
||||||
it 'returns true' do
|
|
||||||
expect(described_class.exit_on_failure?).to be true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -451,7 +451,7 @@ RSpec.describe Account do
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'limits via constant by default' do
|
it 'limits via constant by default' do
|
||||||
stub_const('AccountSearch::DEFAULT_LIMIT', 1)
|
stub_const('Account::Search::DEFAULT_LIMIT', 1)
|
||||||
2.times.each { Fabricate(:account, display_name: 'Display Name') }
|
2.times.each { Fabricate(:account, display_name: 'Display Name') }
|
||||||
results = described_class.search_for('display')
|
results = described_class.search_for('display')
|
||||||
expect(results.size).to eq 1
|
expect(results.size).to eq 1
|
||||||
|
@ -595,7 +595,7 @@ RSpec.describe Account do
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'limits by 10 by default' do
|
it 'limits by 10 by default' do
|
||||||
stub_const('AccountSearch::DEFAULT_LIMIT', 1)
|
stub_const('Account::Search::DEFAULT_LIMIT', 1)
|
||||||
2.times { Fabricate(:account, display_name: 'Display Name') }
|
2.times { Fabricate(:account, display_name: 'Display Name') }
|
||||||
results = described_class.advanced_search_for('display', account)
|
results = described_class.advanced_search_for('display', account)
|
||||||
expect(results.size).to eq 1
|
expect(results.size).to eq 1
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
require 'rails_helper'
|
require 'rails_helper'
|
||||||
|
|
||||||
describe AccountCounters do
|
describe Account::Counters do
|
||||||
let!(:account) { Fabricate(:account) }
|
let!(:account) { Fabricate(:account) }
|
||||||
|
|
||||||
describe '#increment_count!' do
|
describe '#increment_count!' do
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
require 'rails_helper'
|
require 'rails_helper'
|
||||||
|
|
||||||
describe AccountFinderConcern do
|
describe Account::FinderConcern do
|
||||||
describe 'local finders' do
|
describe 'local finders' do
|
||||||
let!(:account) { Fabricate(:account, username: 'Alice') }
|
let!(:account) { Fabricate(:account, username: 'Alice') }
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
require 'rails_helper'
|
require 'rails_helper'
|
||||||
|
|
||||||
describe AccountInteractions do
|
describe Account::Interactions do
|
||||||
let(:account) { Fabricate(:account, username: 'account') }
|
let(:account) { Fabricate(:account, username: 'account') }
|
||||||
let(:account_id) { account.id }
|
let(:account_id) { account.id }
|
||||||
let(:account_ids) { [account_id] }
|
let(:account_ids) { [account_id] }
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
require 'rails_helper'
|
require 'rails_helper'
|
||||||
|
|
||||||
describe AccountStatusesSearch do
|
describe Account::StatusesSearch do
|
||||||
let(:account) { Fabricate(:account, indexable: indexable) }
|
let(:account) { Fabricate(:account, indexable: indexable) }
|
||||||
|
|
||||||
before do
|
before do
|
|
@ -31,7 +31,7 @@ RSpec.describe Remotable do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
let(:attribute_name) { "#{hoge}_remote_url".to_sym }
|
let(:attribute_name) { :"#{hoge}_remote_url" }
|
||||||
let(:code) { 200 }
|
let(:code) { 200 }
|
||||||
let(:file) { 'filename="foo.txt"' }
|
let(:file) { 'filename="foo.txt"' }
|
||||||
let(:foo) { foo_class.new }
|
let(:foo) { foo_class.new }
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
require 'rails_helper'
|
require 'rails_helper'
|
||||||
|
|
||||||
describe StatusThreadingConcern do
|
describe Status::ThreadingConcern do
|
||||||
describe '#ancestors' do
|
describe '#ancestors' do
|
||||||
let!(:alice) { Fabricate(:account, username: 'alice') }
|
let!(:alice) { Fabricate(:account, username: 'alice') }
|
||||||
let!(:bob) { Fabricate(:account, username: 'bob', domain: 'example.com') }
|
let!(:bob) { Fabricate(:account, username: 'bob', domain: 'example.com') }
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
require 'rails_helper'
|
require 'rails_helper'
|
||||||
|
|
||||||
describe AccountSearch do
|
describe Account::Search do
|
||||||
describe 'a non-discoverable account becoming discoverable' do
|
describe 'a non-discoverable account becoming discoverable' do
|
||||||
let(:account) { Account.find_by(username: 'search_test_account_1') }
|
let(:account) { Account.find_by(username: 'search_test_account_1') }
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
require 'rails_helper'
|
require 'rails_helper'
|
||||||
|
|
||||||
describe AccountStatusesSearch do
|
describe Account::StatusesSearch do
|
||||||
describe 'a non-indexable account becoming indexable' do
|
describe 'a non-indexable account becoming indexable' do
|
||||||
let(:account) { Account.find_by(username: 'search_test_account_1') }
|
let(:account) { Account.find_by(username: 'search_test_account_1') }
|
||||||
|
|
11
spec/support/examples/cli.rb
Normal file
11
spec/support/examples/cli.rb
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
shared_examples 'CLI Command' do
|
||||||
|
it 'configures Thor to exit on failure' do
|
||||||
|
expect(described_class.exit_on_failure?).to be true
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'descends from the CLI base class' do
|
||||||
|
expect(described_class.new).to be_a(Mastodon::CLI::Base)
|
||||||
|
end
|
||||||
|
end
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
module SignedRequestHelpers
|
module SignedRequestHelpers
|
||||||
def get(path, headers: nil, sign_with: nil, **args)
|
def get(path, headers: nil, sign_with: nil, **args)
|
||||||
return super path, headers: headers, **args if sign_with.nil?
|
return super(path, headers: headers, **args) if sign_with.nil?
|
||||||
|
|
||||||
headers ||= {}
|
headers ||= {}
|
||||||
headers['Date'] = Time.now.utc.httpdate
|
headers['Date'] = Time.now.utc.httpdate
|
||||||
|
@ -16,6 +16,6 @@ module SignedRequestHelpers
|
||||||
|
|
||||||
headers['Signature'] = "keyId=\"#{key_id}\",algorithm=\"rsa-sha256\",headers=\"#{signed_headers.keys.join(' ').downcase}\",signature=\"#{signature}\""
|
headers['Signature'] = "keyId=\"#{key_id}\",algorithm=\"rsa-sha256\",headers=\"#{signed_headers.keys.join(' ').downcase}\",signature=\"#{signature}\""
|
||||||
|
|
||||||
super path, headers: headers, **args
|
super(path, headers: headers, **args)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue