Merge commit '7d9b209fe84b00eff348ea9d54905cbfffa79788' into glitch-soc/merge-upstream
Conflicts: - `app/models/form/admin_settings.rb`: Upstream changed code style change, including on a line modified by glitch-soc. Kept glitch-soc's line but with the code style change applied.
This commit is contained in:
commit
30ee7339d3
33 changed files with 591 additions and 485 deletions
10
.github/renovate.json5
vendored
10
.github/renovate.json5
vendored
|
@ -99,6 +99,16 @@
|
||||||
matchUpdateTypes: ['patch', 'minor'],
|
matchUpdateTypes: ['patch', 'minor'],
|
||||||
groupName: 'eslint (non-major)',
|
groupName: 'eslint (non-major)',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
// Group actions/*-artifact in the same PR
|
||||||
|
matchManagers: ['github-actions'],
|
||||||
|
matchPackageNames: [
|
||||||
|
'actions/download-artifact',
|
||||||
|
'actions/upload-artifact',
|
||||||
|
],
|
||||||
|
matchUpdateTypes: ['major'],
|
||||||
|
groupName: 'artifact actions (major)',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
// Update @types/* packages every week, with one grouped PR
|
// Update @types/* packages every week, with one grouped PR
|
||||||
matchPackagePrefixes: '@types/',
|
matchPackagePrefixes: '@types/',
|
||||||
|
|
|
@ -1,33 +1,21 @@
|
||||||
# This configuration was generated by
|
# This configuration was generated by
|
||||||
# `haml-lint --auto-gen-config`
|
# `haml-lint --auto-gen-config`
|
||||||
# on 2023-10-26 09:32:34 -0400 using Haml-Lint version 0.51.0.
|
# on 2023-12-15 11:02:19 -0500 using Haml-Lint version 0.52.0.
|
||||||
# The point is for the user to remove these configuration records
|
# The point is for the user to remove these configuration records
|
||||||
# one by one as the lints are removed from the code base.
|
# one by one as the lints are removed from the code base.
|
||||||
# Note that changes in the inspected code, or installation of new
|
# Note that changes in the inspected code, or installation of new
|
||||||
# versions of Haml-Lint, may require this file to be generated again.
|
# versions of Haml-Lint, may require this file to be generated again.
|
||||||
|
|
||||||
linters:
|
linters:
|
||||||
# Offense count: 16
|
# Offense count: 11
|
||||||
LineLength:
|
LineLength:
|
||||||
exclude:
|
exclude:
|
||||||
- 'app/views/admin/account_actions/new.html.haml'
|
|
||||||
- 'app/views/admin/accounts/index.html.haml'
|
|
||||||
- 'app/views/admin/ip_blocks/new.html.haml'
|
|
||||||
- 'app/views/admin/roles/_form.html.haml'
|
- 'app/views/admin/roles/_form.html.haml'
|
||||||
- 'app/views/admin/settings/discovery/show.html.haml'
|
|
||||||
- 'app/views/auth/registrations/edit.html.haml'
|
- 'app/views/auth/registrations/edit.html.haml'
|
||||||
- 'app/views/auth/registrations/new.html.haml'
|
- 'app/views/auth/registrations/new.html.haml'
|
||||||
- 'app/views/filters/_filter_fields.html.haml'
|
|
||||||
- 'app/views/media/player.html.haml'
|
- 'app/views/media/player.html.haml'
|
||||||
- 'app/views/settings/applications/_fields.html.haml'
|
- 'app/views/settings/applications/_fields.html.haml'
|
||||||
- 'app/views/settings/imports/index.html.haml'
|
- 'app/views/settings/imports/index.html.haml'
|
||||||
- 'app/views/settings/preferences/appearance/show.html.haml'
|
- 'app/views/settings/preferences/appearance/show.html.haml'
|
||||||
- 'app/views/settings/preferences/notifications/show.html.haml'
|
- 'app/views/settings/preferences/notifications/show.html.haml'
|
||||||
- 'app/views/settings/preferences/other/show.html.haml'
|
- 'app/views/settings/preferences/other/show.html.haml'
|
||||||
|
|
||||||
# Offense count: 9
|
|
||||||
RuboCop:
|
|
||||||
exclude:
|
|
||||||
- 'app/views/admin/accounts/_buttons.html.haml'
|
|
||||||
- 'app/views/admin/accounts/_local_account.html.haml'
|
|
||||||
- 'app/views/admin/roles/_form.html.haml'
|
|
||||||
|
|
11
.rubocop.yml
11
.rubocop.yml
|
@ -109,6 +109,17 @@ Rails/SkipsModelValidations:
|
||||||
Exclude:
|
Exclude:
|
||||||
- 'db/*migrate/**/*'
|
- 'db/*migrate/**/*'
|
||||||
|
|
||||||
|
# Reason: We want to preserve the ability to migrate from arbitrary old versions,
|
||||||
|
# and cannot guarantee that every installation has run every migration as they upgrade.
|
||||||
|
# https://docs.rubocop.org/rubocop-rails/cops_rails.html#railsunusedignoredcolumns
|
||||||
|
Rails/UnusedIgnoredColumns:
|
||||||
|
Enabled: false
|
||||||
|
|
||||||
|
# Reason: Prevailing style choice
|
||||||
|
# https://docs.rubocop.org/rubocop-rails/cops_rails.html#railsnegateinclude
|
||||||
|
Rails/NegateInclude:
|
||||||
|
Enabled: false
|
||||||
|
|
||||||
# Reason: Some single letter camel case files shouldn't be split
|
# Reason: Some single letter camel case files shouldn't be split
|
||||||
# https://docs.rubocop.org/rubocop-rspec/cops_rspec.html#rspecfilepath
|
# https://docs.rubocop.org/rubocop-rspec/cops_rspec.html#rspecfilepath
|
||||||
RSpec/FilePath:
|
RSpec/FilePath:
|
||||||
|
|
|
@ -119,23 +119,6 @@ Rails/LexicallyScopedActionFilter:
|
||||||
- 'app/controllers/auth/passwords_controller.rb'
|
- 'app/controllers/auth/passwords_controller.rb'
|
||||||
- 'app/controllers/auth/registrations_controller.rb'
|
- 'app/controllers/auth/registrations_controller.rb'
|
||||||
|
|
||||||
# This cop supports unsafe autocorrection (--autocorrect-all).
|
|
||||||
Rails/NegateInclude:
|
|
||||||
Exclude:
|
|
||||||
- 'app/controllers/concerns/signature_verification.rb'
|
|
||||||
- 'app/helpers/jsonld_helper.rb'
|
|
||||||
- 'app/lib/activitypub/activity/create.rb'
|
|
||||||
- 'app/lib/activitypub/activity/move.rb'
|
|
||||||
- 'app/lib/feed_manager.rb'
|
|
||||||
- 'app/lib/link_details_extractor.rb'
|
|
||||||
- 'app/models/concerns/attachmentable.rb'
|
|
||||||
- 'app/models/concerns/remotable.rb'
|
|
||||||
- 'app/models/custom_filter.rb'
|
|
||||||
- 'app/services/activitypub/process_status_update_service.rb'
|
|
||||||
- 'app/services/fetch_link_card_service.rb'
|
|
||||||
- 'app/workers/web/push_notification_worker.rb'
|
|
||||||
- 'lib/paperclip/color_extractor.rb'
|
|
||||||
|
|
||||||
Rails/OutputSafety:
|
Rails/OutputSafety:
|
||||||
Exclude:
|
Exclude:
|
||||||
- 'config/initializers/simple_form.rb'
|
- 'config/initializers/simple_form.rb'
|
||||||
|
@ -196,19 +179,6 @@ Rails/UniqueValidationWithoutIndex:
|
||||||
- 'app/models/identity.rb'
|
- 'app/models/identity.rb'
|
||||||
- 'app/models/webauthn_credential.rb'
|
- 'app/models/webauthn_credential.rb'
|
||||||
|
|
||||||
# Configuration parameters: Include.
|
|
||||||
# Include: app/models/**/*.rb
|
|
||||||
Rails/UnusedIgnoredColumns:
|
|
||||||
Exclude:
|
|
||||||
- 'app/models/account.rb'
|
|
||||||
- 'app/models/account_stat.rb'
|
|
||||||
- 'app/models/admin/action_log.rb'
|
|
||||||
- 'app/models/custom_filter.rb'
|
|
||||||
- 'app/models/email_domain_block.rb'
|
|
||||||
- 'app/models/report.rb'
|
|
||||||
- 'app/models/status_edit.rb'
|
|
||||||
- 'app/models/user.rb'
|
|
||||||
|
|
||||||
# This cop supports unsafe autocorrection (--autocorrect-all).
|
# This cop supports unsafe autocorrection (--autocorrect-all).
|
||||||
# Configuration parameters: EnforcedStyle.
|
# Configuration parameters: EnforcedStyle.
|
||||||
# SupportedStyles: exists, where
|
# SupportedStyles: exists, where
|
||||||
|
@ -426,15 +396,6 @@ Style/RedundantFetchBlock:
|
||||||
- 'config/initializers/paperclip.rb'
|
- 'config/initializers/paperclip.rb'
|
||||||
- 'config/puma.rb'
|
- 'config/puma.rb'
|
||||||
|
|
||||||
# This cop supports safe autocorrection (--autocorrect).
|
|
||||||
# Configuration parameters: AllowMultipleReturnValues.
|
|
||||||
Style/RedundantReturn:
|
|
||||||
Exclude:
|
|
||||||
- 'app/controllers/api/v1/directories_controller.rb'
|
|
||||||
- 'app/controllers/auth/confirmations_controller.rb'
|
|
||||||
- 'app/lib/ostatus/tag_manager.rb'
|
|
||||||
- 'app/models/form/import.rb'
|
|
||||||
|
|
||||||
# This cop supports unsafe autocorrection (--autocorrect-all).
|
# This cop supports unsafe autocorrection (--autocorrect-all).
|
||||||
# Configuration parameters: ConvertCodeThatCanStartToReturnNil, AllowedMethods, MaxChainLength.
|
# Configuration parameters: ConvertCodeThatCanStartToReturnNil, AllowedMethods, MaxChainLength.
|
||||||
# AllowedMethods: present?, blank?, presence, try, try!
|
# AllowedMethods: present?, blank?, presence, try, try!
|
||||||
|
@ -455,11 +416,6 @@ Style/SingleArgumentDig:
|
||||||
Exclude:
|
Exclude:
|
||||||
- 'lib/webpacker/manifest_extensions.rb'
|
- 'lib/webpacker/manifest_extensions.rb'
|
||||||
|
|
||||||
# This cop supports safe autocorrection (--autocorrect).
|
|
||||||
Style/StderrPuts:
|
|
||||||
Exclude:
|
|
||||||
- 'config/boot.rb'
|
|
||||||
|
|
||||||
# This cop supports unsafe autocorrection (--autocorrect-all).
|
# This cop supports unsafe autocorrection (--autocorrect-all).
|
||||||
# Configuration parameters: Mode.
|
# Configuration parameters: Mode.
|
||||||
Style/StringConcatenation:
|
Style/StringConcatenation:
|
||||||
|
@ -478,13 +434,6 @@ Style/StringLiterals:
|
||||||
- 'config/initializers/webauthn.rb'
|
- 'config/initializers/webauthn.rb'
|
||||||
- 'config/routes.rb'
|
- 'config/routes.rb'
|
||||||
|
|
||||||
# This cop supports unsafe autocorrection (--autocorrect-all).
|
|
||||||
# Configuration parameters: AllowMethodsWithArguments, AllowedMethods, AllowedPatterns, AllowComments.
|
|
||||||
# AllowedMethods: define_method, mail, respond_to
|
|
||||||
Style/SymbolProc:
|
|
||||||
Exclude:
|
|
||||||
- 'config/initializers/3_omniauth.rb'
|
|
||||||
|
|
||||||
# This cop supports safe autocorrection (--autocorrect).
|
# This cop supports safe autocorrection (--autocorrect).
|
||||||
# Configuration parameters: EnforcedStyle, AllowSafeAssignment.
|
# Configuration parameters: EnforcedStyle, AllowSafeAssignment.
|
||||||
# SupportedStyles: require_parentheses, require_no_parentheses, require_parentheses_when_complex
|
# SupportedStyles: require_parentheses, require_no_parentheses, require_parentheses_when_complex
|
||||||
|
|
10
Gemfile.lock
10
Gemfile.lock
|
@ -515,7 +515,7 @@ GEM
|
||||||
openssl (> 2.0)
|
openssl (> 2.0)
|
||||||
orm_adapter (0.5.0)
|
orm_adapter (0.5.0)
|
||||||
ox (2.14.17)
|
ox (2.14.17)
|
||||||
parallel (1.23.0)
|
parallel (1.24.0)
|
||||||
parser (3.2.2.4)
|
parser (3.2.2.4)
|
||||||
ast (~> 2.4.1)
|
ast (~> 2.4.1)
|
||||||
racc
|
racc
|
||||||
|
@ -679,10 +679,10 @@ GEM
|
||||||
rubocop (~> 1.41)
|
rubocop (~> 1.41)
|
||||||
rubocop-factory_bot (2.24.0)
|
rubocop-factory_bot (2.24.0)
|
||||||
rubocop (~> 1.33)
|
rubocop (~> 1.33)
|
||||||
rubocop-performance (1.19.1)
|
rubocop-performance (1.20.0)
|
||||||
rubocop (>= 1.7.0, < 2.0)
|
rubocop (>= 1.48.1, < 2.0)
|
||||||
rubocop-ast (>= 0.4.0)
|
rubocop-ast (>= 1.30.0, < 2.0)
|
||||||
rubocop-rails (2.22.2)
|
rubocop-rails (2.23.0)
|
||||||
activesupport (>= 4.2.0)
|
activesupport (>= 4.2.0)
|
||||||
rack (>= 1.1)
|
rack (>= 1.1)
|
||||||
rubocop (>= 1.33.0, < 2.0)
|
rubocop (>= 1.33.0, < 2.0)
|
||||||
|
|
|
@ -25,6 +25,6 @@ class Api::V1::Accounts::NotesController < Api::BaseController
|
||||||
end
|
end
|
||||||
|
|
||||||
def relationships_presenter
|
def relationships_presenter
|
||||||
AccountRelationshipsPresenter.new([@account.id], current_user.account_id)
|
AccountRelationshipsPresenter.new([@account], current_user.account_id)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -25,6 +25,6 @@ class Api::V1::Accounts::PinsController < Api::BaseController
|
||||||
end
|
end
|
||||||
|
|
||||||
def relationships_presenter
|
def relationships_presenter
|
||||||
AccountRelationshipsPresenter.new([@account.id], current_user.account_id)
|
AccountRelationshipsPresenter.new([@account], current_user.account_id)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -5,7 +5,7 @@ class Api::V1::Accounts::RelationshipsController < Api::BaseController
|
||||||
before_action :require_user!
|
before_action :require_user!
|
||||||
|
|
||||||
def index
|
def index
|
||||||
@accounts = Account.where(id: account_ids).select('id')
|
@accounts = Account.where(id: account_ids).select(:id, :domain)
|
||||||
@accounts.merge!(Account.without_suspended) unless truthy_param?(:with_suspended)
|
@accounts.merge!(Account.without_suspended) unless truthy_param?(:with_suspended)
|
||||||
render json: @accounts, each_serializer: REST::RelationshipSerializer, relationships: relationships
|
render json: @accounts, each_serializer: REST::RelationshipSerializer, relationships: relationships
|
||||||
end
|
end
|
||||||
|
|
|
@ -88,7 +88,7 @@ class Api::V1::AccountsController < Api::BaseController
|
||||||
end
|
end
|
||||||
|
|
||||||
def relationships(**options)
|
def relationships(**options)
|
||||||
AccountRelationshipsPresenter.new([@account.id], current_user.account_id, **options)
|
AccountRelationshipsPresenter.new([@account], current_user.account_id, **options)
|
||||||
end
|
end
|
||||||
|
|
||||||
def account_params
|
def account_params
|
||||||
|
|
|
@ -12,7 +12,7 @@ class Api::V1::DirectoriesController < Api::BaseController
|
||||||
private
|
private
|
||||||
|
|
||||||
def require_enabled!
|
def require_enabled!
|
||||||
return not_found unless Setting.profile_directory
|
not_found unless Setting.profile_directory
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_accounts
|
def set_accounts
|
||||||
|
|
|
@ -25,11 +25,11 @@ class Api::V1::FollowRequestsController < Api::BaseController
|
||||||
private
|
private
|
||||||
|
|
||||||
def account
|
def account
|
||||||
Account.find(params[:id])
|
@account ||= Account.find(params[:id])
|
||||||
end
|
end
|
||||||
|
|
||||||
def relationships(**options)
|
def relationships(**options)
|
||||||
AccountRelationshipsPresenter.new([params[:id]], current_user.account_id, **options)
|
AccountRelationshipsPresenter.new([account], current_user.account_id, **options)
|
||||||
end
|
end
|
||||||
|
|
||||||
def load_accounts
|
def load_accounts
|
||||||
|
|
|
@ -63,7 +63,7 @@ class Auth::ConfirmationsController < Devise::ConfirmationsController
|
||||||
end
|
end
|
||||||
|
|
||||||
def captcha_user_bypass?
|
def captcha_user_bypass?
|
||||||
return true if @confirmation_user.nil? || @confirmation_user.confirmed?
|
@confirmation_user.nil? || @confirmation_user.confirmed?
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_pack
|
def set_pack
|
||||||
|
|
|
@ -34,7 +34,7 @@ class RelationshipsController < ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_relationships
|
def set_relationships
|
||||||
@relationships = AccountRelationshipsPresenter.new(@accounts.pluck(:id), current_user.account_id)
|
@relationships = AccountRelationshipsPresenter.new(@accounts, current_user.account_id)
|
||||||
end
|
end
|
||||||
|
|
||||||
def form_account_batch_params
|
def form_account_batch_params
|
||||||
|
|
|
@ -110,7 +110,7 @@ module ApplicationHelper
|
||||||
def can?(action, record)
|
def can?(action, record)
|
||||||
return false if record.nil?
|
return false if record.nil?
|
||||||
|
|
||||||
policy(record).public_send("#{action}?")
|
policy(record).public_send(:"#{action}?")
|
||||||
end
|
end
|
||||||
|
|
||||||
def fa_icon(icon, attributes = {})
|
def fa_icon(icon, attributes = {})
|
||||||
|
|
|
@ -52,7 +52,7 @@ class OStatus::TagManager
|
||||||
ActivityPub::TagManager.instance.uri_to_local_id(tag)
|
ActivityPub::TagManager.instance.uri_to_local_id(tag)
|
||||||
else
|
else
|
||||||
matches = Regexp.new("objectId=([\\d]+):objectType=#{expected_type}").match(tag)
|
matches = Regexp.new("objectId=([\\d]+):objectType=#{expected_type}").match(tag)
|
||||||
return matches[1] unless matches.nil?
|
matches[1] unless matches.nil?
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -455,8 +455,8 @@ class Account < ApplicationRecord
|
||||||
end
|
end
|
||||||
|
|
||||||
def inverse_alias(key, original_key)
|
def inverse_alias(key, original_key)
|
||||||
define_method("#{key}=") do |value|
|
define_method(:"#{key}=") do |value|
|
||||||
public_send("#{original_key}=", !ActiveModel::Type::Boolean.new.cast(value))
|
public_send(:"#{original_key}=", !ActiveModel::Type::Boolean.new.cast(value))
|
||||||
end
|
end
|
||||||
|
|
||||||
define_method(key) do
|
define_method(key) do
|
||||||
|
|
|
@ -18,16 +18,12 @@ class AccountDomainBlock < ApplicationRecord
|
||||||
belongs_to :account
|
belongs_to :account
|
||||||
validates :domain, presence: true, uniqueness: { scope: :account_id }, domain: true
|
validates :domain, presence: true, uniqueness: { scope: :account_id }, domain: true
|
||||||
|
|
||||||
after_commit :remove_blocking_cache
|
after_commit :invalidate_domain_blocking_cache
|
||||||
after_commit :remove_relationship_cache
|
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def remove_blocking_cache
|
def invalidate_domain_blocking_cache
|
||||||
Rails.cache.delete("exclude_domains_for:#{account_id}")
|
Rails.cache.delete("exclude_domains_for:#{account_id}")
|
||||||
end
|
Rails.cache.delete(['exclude_domains', account_id, domain])
|
||||||
|
|
||||||
def remove_relationship_cache
|
|
||||||
Rails.cache.delete_matched("relationship:#{account_id}:*")
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -60,12 +60,6 @@ module Account::Interactions
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def domain_blocking_map(target_account_ids, account_id)
|
|
||||||
accounts_map = Account.where(id: target_account_ids).select('id, domain').each_with_object({}) { |a, h| h[a.id] = a.domain }
|
|
||||||
blocked_domains = domain_blocking_map_by_domain(accounts_map.values.compact, account_id)
|
|
||||||
accounts_map.reduce({}) { |h, (id, domain)| h.merge(id => blocked_domains[domain]) }
|
|
||||||
end
|
|
||||||
|
|
||||||
def domain_blocking_map_by_domain(target_domains, account_id)
|
def domain_blocking_map_by_domain(target_domains, account_id)
|
||||||
follow_mapping(AccountDomainBlock.where(account_id: account_id, domain: target_domains), :domain)
|
follow_mapping(AccountDomainBlock.where(account_id: account_id, domain: target_domains), :domain)
|
||||||
end
|
end
|
||||||
|
|
|
@ -10,7 +10,7 @@ module RelationshipCacheable
|
||||||
private
|
private
|
||||||
|
|
||||||
def remove_relationship_cache
|
def remove_relationship_cache
|
||||||
Rails.cache.delete("relationship:#{account_id}:#{target_account_id}")
|
Rails.cache.delete(['relationship', account_id, target_account_id])
|
||||||
Rails.cache.delete("relationship:#{target_account_id}:#{account_id}")
|
Rails.cache.delete(['relationship', target_account_id, account_id])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -7,7 +7,7 @@ module Remotable
|
||||||
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"
|
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]
|
||||||
|
|
||||||
return if url.blank?
|
return if url.blank?
|
||||||
|
@ -24,29 +24,29 @@ module Remotable
|
||||||
Request.new(:get, url).perform do |response|
|
Request.new(:get, url).perform do |response|
|
||||||
raise Mastodon::UnexpectedResponseError, response unless (200...300).cover?(response.code)
|
raise Mastodon::UnexpectedResponseError, response unless (200...300).cover?(response.code)
|
||||||
|
|
||||||
public_send("#{attachment_name}=", ResponseWithLimit.new(response, limit))
|
public_send(:"#{attachment_name}=", ResponseWithLimit.new(response, limit))
|
||||||
end
|
end
|
||||||
rescue Mastodon::UnexpectedResponseError, HTTP::TimeoutError, HTTP::ConnectionError, OpenSSL::SSL::SSLError => e
|
rescue Mastodon::UnexpectedResponseError, HTTP::TimeoutError, HTTP::ConnectionError, OpenSSL::SSL::SSLError => e
|
||||||
Rails.logger.debug { "Error fetching remote #{attachment_name}: #{e}" }
|
Rails.logger.debug { "Error fetching remote #{attachment_name}: #{e}" }
|
||||||
public_send("#{attachment_name}=", nil) if public_send("#{attachment_name}_file_name").present?
|
public_send(:"#{attachment_name}=", nil) if public_send(:"#{attachment_name}_file_name").present?
|
||||||
raise e unless suppress_errors
|
raise e unless suppress_errors
|
||||||
rescue Paperclip::Errors::NotIdentifiedByImageMagickError, Addressable::URI::InvalidURIError, Mastodon::HostValidationError, Mastodon::LengthValidationError, Paperclip::Error, Mastodon::DimensionsValidationError, Mastodon::StreamValidationError => e
|
rescue Paperclip::Errors::NotIdentifiedByImageMagickError, Addressable::URI::InvalidURIError, Mastodon::HostValidationError, Mastodon::LengthValidationError, Paperclip::Error, Mastodon::DimensionsValidationError, Mastodon::StreamValidationError => e
|
||||||
Rails.logger.debug { "Error fetching remote #{attachment_name}: #{e}" }
|
Rails.logger.debug { "Error fetching remote #{attachment_name}: #{e}" }
|
||||||
public_send("#{attachment_name}=", nil) if public_send("#{attachment_name}_file_name").present?
|
public_send(:"#{attachment_name}=", nil) if public_send(:"#{attachment_name}_file_name").present?
|
||||||
end
|
end
|
||||||
|
|
||||||
nil
|
nil
|
||||||
end
|
end
|
||||||
|
|
||||||
define_method("#{attribute_name}=") do |url|
|
define_method(:"#{attribute_name}=") do |url|
|
||||||
return if self[attribute_name] == url && public_send("#{attachment_name}_file_name").present?
|
return if self[attribute_name] == url && public_send(:"#{attachment_name}_file_name").present?
|
||||||
|
|
||||||
self[attribute_name] = url if has_attribute?(attribute_name)
|
self[attribute_name] = url if has_attribute?(attribute_name)
|
||||||
|
|
||||||
public_send("download_#{attachment_name}!", url) if download_on_assign
|
public_send(:"download_#{attachment_name}!", url) if download_on_assign
|
||||||
end
|
end
|
||||||
|
|
||||||
alias_method("reset_#{attachment_name}!", "download_#{attachment_name}!")
|
alias_method(:"reset_#{attachment_name}!", "download_#{attachment_name}!")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -100,7 +100,7 @@ class Form::AdminSettings
|
||||||
|
|
||||||
KEYS.each do |key|
|
KEYS.each do |key|
|
||||||
define_method(key) do
|
define_method(key) do
|
||||||
return instance_variable_get("@#{key}") if instance_variable_defined?("@#{key}")
|
return instance_variable_get(:"@#{key}") if instance_variable_defined?(:"@#{key}")
|
||||||
|
|
||||||
stored_value = if UPLOAD_KEYS.include?(key)
|
stored_value = if UPLOAD_KEYS.include?(key)
|
||||||
SiteUpload.where(var: key).first_or_initialize(var: key)
|
SiteUpload.where(var: key).first_or_initialize(var: key)
|
||||||
|
@ -110,12 +110,12 @@ class Form::AdminSettings
|
||||||
Setting.public_send(key)
|
Setting.public_send(key)
|
||||||
end
|
end
|
||||||
|
|
||||||
instance_variable_set("@#{key}", stored_value)
|
instance_variable_set(:"@#{key}", stored_value)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
UPLOAD_KEYS.each do |key|
|
UPLOAD_KEYS.each do |key|
|
||||||
define_method("#{key}=") do |file|
|
define_method(:"#{key}=") do |file|
|
||||||
value = public_send(key)
|
value = public_send(key)
|
||||||
value.file = file
|
value.file = file
|
||||||
rescue Mastodon::DimensionsValidationError => e
|
rescue Mastodon::DimensionsValidationError => e
|
||||||
|
@ -130,13 +130,13 @@ class Form::AdminSettings
|
||||||
return false unless errors.empty? && valid?
|
return false unless errors.empty? && valid?
|
||||||
|
|
||||||
KEYS.each do |key|
|
KEYS.each do |key|
|
||||||
next if PSEUDO_KEYS.include?(key) || !instance_variable_defined?("@#{key}")
|
next if PSEUDO_KEYS.include?(key) || !instance_variable_defined?(:"@#{key}")
|
||||||
|
|
||||||
if UPLOAD_KEYS.include?(key)
|
if UPLOAD_KEYS.include?(key)
|
||||||
public_send(key).save
|
public_send(key).save
|
||||||
else
|
else
|
||||||
setting = Setting.where(var: key).first_or_initialize(var: key)
|
setting = Setting.where(var: key).first_or_initialize(var: key)
|
||||||
setting.update(value: typecast_value(key, instance_variable_get("@#{key}")))
|
setting.update(value: typecast_value(key, instance_variable_get(:"@#{key}")))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -163,9 +163,9 @@ class Form::AdminSettings
|
||||||
|
|
||||||
def validate_site_uploads
|
def validate_site_uploads
|
||||||
UPLOAD_KEYS.each do |key|
|
UPLOAD_KEYS.each do |key|
|
||||||
next unless instance_variable_defined?("@#{key}")
|
next unless instance_variable_defined?(:"@#{key}")
|
||||||
|
|
||||||
upload = instance_variable_get("@#{key}")
|
upload = instance_variable_get(:"@#{key}")
|
||||||
next if upload.valid?
|
next if upload.valid?
|
||||||
|
|
||||||
upload.errors.each do |error|
|
upload.errors.each do |error|
|
||||||
|
|
|
@ -43,14 +43,19 @@ class Form::Import
|
||||||
validate :validate_data
|
validate :validate_data
|
||||||
|
|
||||||
def guessed_type
|
def guessed_type
|
||||||
return :muting if csv_headers_match?('Hide notifications')
|
if csv_headers_match?('Hide notifications') || file_name_matches?('mutes') || file_name_matches?('muted_accounts')
|
||||||
return :following if csv_headers_match?('Show boosts') || csv_headers_match?('Notify on new posts') || csv_headers_match?('Languages')
|
:muting
|
||||||
return :following if file_name_matches?('follows') || file_name_matches?('following_accounts')
|
elsif csv_headers_match?('Show boosts') || csv_headers_match?('Notify on new posts') || csv_headers_match?('Languages') || file_name_matches?('follows') || file_name_matches?('following_accounts')
|
||||||
return :blocking if file_name_matches?('blocks') || file_name_matches?('blocked_accounts')
|
:following
|
||||||
return :muting if file_name_matches?('mutes') || file_name_matches?('muted_accounts')
|
elsif file_name_matches?('blocks') || file_name_matches?('blocked_accounts')
|
||||||
return :domain_blocking if file_name_matches?('domain_blocks') || file_name_matches?('blocked_domains')
|
:blocking
|
||||||
return :bookmarks if file_name_matches?('bookmarks')
|
elsif file_name_matches?('domain_blocks') || file_name_matches?('blocked_domains')
|
||||||
return :lists if file_name_matches?('lists')
|
:domain_blocking
|
||||||
|
elsif file_name_matches?('bookmarks')
|
||||||
|
:bookmarks
|
||||||
|
elsif file_name_matches?('lists')
|
||||||
|
:lists
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Whether the uploaded CSV file seems to correspond to a different import type than the one selected
|
# Whether the uploaded CSV file seems to correspond to a different import type than the one selected
|
||||||
|
|
|
@ -5,8 +5,9 @@ class AccountRelationshipsPresenter
|
||||||
:muting, :requested, :requested_by, :domain_blocking,
|
:muting, :requested, :requested_by, :domain_blocking,
|
||||||
:endorsed, :account_note
|
:endorsed, :account_note
|
||||||
|
|
||||||
def initialize(account_ids, current_account_id, **options)
|
def initialize(accounts, current_account_id, **options)
|
||||||
@account_ids = account_ids.map { |a| a.is_a?(Account) ? a.id : a.to_i }
|
@accounts = accounts.to_a
|
||||||
|
@account_ids = @accounts.pluck(:id)
|
||||||
@current_account_id = current_account_id
|
@current_account_id = current_account_id
|
||||||
|
|
||||||
@following = cached[:following].merge(Account.following_map(@uncached_account_ids, @current_account_id))
|
@following = cached[:following].merge(Account.following_map(@uncached_account_ids, @current_account_id))
|
||||||
|
@ -16,10 +17,11 @@ class AccountRelationshipsPresenter
|
||||||
@muting = cached[:muting].merge(Account.muting_map(@uncached_account_ids, @current_account_id))
|
@muting = cached[:muting].merge(Account.muting_map(@uncached_account_ids, @current_account_id))
|
||||||
@requested = cached[:requested].merge(Account.requested_map(@uncached_account_ids, @current_account_id))
|
@requested = cached[:requested].merge(Account.requested_map(@uncached_account_ids, @current_account_id))
|
||||||
@requested_by = cached[:requested_by].merge(Account.requested_by_map(@uncached_account_ids, @current_account_id))
|
@requested_by = cached[:requested_by].merge(Account.requested_by_map(@uncached_account_ids, @current_account_id))
|
||||||
@domain_blocking = cached[:domain_blocking].merge(Account.domain_blocking_map(@uncached_account_ids, @current_account_id))
|
|
||||||
@endorsed = cached[:endorsed].merge(Account.endorsed_map(@uncached_account_ids, @current_account_id))
|
@endorsed = cached[:endorsed].merge(Account.endorsed_map(@uncached_account_ids, @current_account_id))
|
||||||
@account_note = cached[:account_note].merge(Account.account_note_map(@uncached_account_ids, @current_account_id))
|
@account_note = cached[:account_note].merge(Account.account_note_map(@uncached_account_ids, @current_account_id))
|
||||||
|
|
||||||
|
@domain_blocking = domain_blocking_map
|
||||||
|
|
||||||
cache_uncached!
|
cache_uncached!
|
||||||
|
|
||||||
@following.merge!(options[:following_map] || {})
|
@following.merge!(options[:following_map] || {})
|
||||||
|
@ -36,6 +38,31 @@ class AccountRelationshipsPresenter
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
def domain_blocking_map
|
||||||
|
target_domains = @accounts.pluck(:domain).compact.uniq
|
||||||
|
blocks_by_domain = {}
|
||||||
|
|
||||||
|
# Fetch from cache
|
||||||
|
cache_keys = target_domains.map { |domain| domain_cache_key(domain) }
|
||||||
|
Rails.cache.read_multi(*cache_keys).each do |key, blocking|
|
||||||
|
blocks_by_domain[key.last] = blocking
|
||||||
|
end
|
||||||
|
|
||||||
|
uncached_domains = target_domains - blocks_by_domain.keys
|
||||||
|
|
||||||
|
# Read uncached values from database
|
||||||
|
AccountDomainBlock.where(account_id: @current_account_id, domain: uncached_domains).pluck(:domain).each do |domain|
|
||||||
|
blocks_by_domain[domain] = true
|
||||||
|
end
|
||||||
|
|
||||||
|
# Write database reads to cache
|
||||||
|
to_cache = uncached_domains.to_h { |domain| [domain_cache_key(domain), blocks_by_domain[domain]] }
|
||||||
|
Rails.cache.write_multi(to_cache, expires_in: 1.day)
|
||||||
|
|
||||||
|
# Return formatted value
|
||||||
|
@accounts.each_with_object({}) { |account, h| h[account.id] = blocks_by_domain[account.domain] }
|
||||||
|
end
|
||||||
|
|
||||||
def cached
|
def cached
|
||||||
return @cached if defined?(@cached)
|
return @cached if defined?(@cached)
|
||||||
|
|
||||||
|
@ -47,28 +74,23 @@ class AccountRelationshipsPresenter
|
||||||
muting: {},
|
muting: {},
|
||||||
requested: {},
|
requested: {},
|
||||||
requested_by: {},
|
requested_by: {},
|
||||||
domain_blocking: {},
|
|
||||||
endorsed: {},
|
endorsed: {},
|
||||||
account_note: {},
|
account_note: {},
|
||||||
}
|
}
|
||||||
|
|
||||||
@uncached_account_ids = []
|
@uncached_account_ids = @account_ids.uniq
|
||||||
|
|
||||||
@account_ids.each do |account_id|
|
cache_ids = @account_ids.map { |account_id| relationship_cache_key(account_id) }
|
||||||
maps_for_account = Rails.cache.read("relationship:#{@current_account_id}:#{account_id}")
|
Rails.cache.read_multi(*cache_ids).each do |key, maps_for_account|
|
||||||
|
|
||||||
if maps_for_account.is_a?(Hash)
|
|
||||||
@cached.deep_merge!(maps_for_account)
|
@cached.deep_merge!(maps_for_account)
|
||||||
else
|
@uncached_account_ids.delete(key.last)
|
||||||
@uncached_account_ids << account_id
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
@cached
|
@cached
|
||||||
end
|
end
|
||||||
|
|
||||||
def cache_uncached!
|
def cache_uncached!
|
||||||
@uncached_account_ids.each do |account_id|
|
to_cache = @uncached_account_ids.to_h do |account_id|
|
||||||
maps_for_account = {
|
maps_for_account = {
|
||||||
following: { account_id => following[account_id] },
|
following: { account_id => following[account_id] },
|
||||||
followed_by: { account_id => followed_by[account_id] },
|
followed_by: { account_id => followed_by[account_id] },
|
||||||
|
@ -77,12 +99,21 @@ class AccountRelationshipsPresenter
|
||||||
muting: { account_id => muting[account_id] },
|
muting: { account_id => muting[account_id] },
|
||||||
requested: { account_id => requested[account_id] },
|
requested: { account_id => requested[account_id] },
|
||||||
requested_by: { account_id => requested_by[account_id] },
|
requested_by: { account_id => requested_by[account_id] },
|
||||||
domain_blocking: { account_id => domain_blocking[account_id] },
|
|
||||||
endorsed: { account_id => endorsed[account_id] },
|
endorsed: { account_id => endorsed[account_id] },
|
||||||
account_note: { account_id => account_note[account_id] },
|
account_note: { account_id => account_note[account_id] },
|
||||||
}
|
}
|
||||||
|
|
||||||
Rails.cache.write("relationship:#{@current_account_id}:#{account_id}", maps_for_account, expires_in: 1.day)
|
[relationship_cache_key(account_id), maps_for_account]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
Rails.cache.write_multi(to_cache, expires_in: 1.day)
|
||||||
|
end
|
||||||
|
|
||||||
|
def domain_cache_key(domain)
|
||||||
|
['exclude_domains', @current_account_id, domain]
|
||||||
|
end
|
||||||
|
|
||||||
|
def relationship_cache_key(account_id)
|
||||||
|
['relationship', @current_account_id, account_id]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -6,8 +6,8 @@
|
||||||
%p.muted-hint= deletion_request.present? ? t('admin.accounts.suspension_reversible_hint_html', date: content_tag(:strong, l(deletion_request.due_at.to_date))) : t('admin.accounts.suspension_irreversible')
|
%p.muted-hint= deletion_request.present? ? t('admin.accounts.suspension_reversible_hint_html', date: content_tag(:strong, l(deletion_request.due_at.to_date))) : t('admin.accounts.suspension_irreversible')
|
||||||
= link_to t('admin.accounts.undo_suspension'), unsuspend_admin_account_path(account.id), method: :post, class: 'button' if can?(:unsuspend, account)
|
= link_to t('admin.accounts.undo_suspension'), unsuspend_admin_account_path(account.id), method: :post, class: 'button' if can?(:unsuspend, account)
|
||||||
= link_to t('admin.accounts.redownload'), redownload_admin_account_path(account.id), method: :post, class: 'button' if can?(:redownload, account) && account.suspension_origin_remote?
|
= link_to t('admin.accounts.redownload'), redownload_admin_account_path(account.id), method: :post, class: 'button' if can?(:redownload, account) && account.suspension_origin_remote?
|
||||||
- if deletion_request.present?
|
- if deletion_request.present? && can?(:destroy, account)
|
||||||
= link_to t('admin.accounts.delete'), admin_account_path(account.id), method: :delete, class: 'button button--destructive', data: { confirm: t('admin.accounts.are_you_sure') } if can?(:destroy, account)
|
= link_to t('admin.accounts.delete'), admin_account_path(account.id), method: :delete, class: 'button button--destructive', data: { confirm: t('admin.accounts.are_you_sure') }
|
||||||
- else
|
- else
|
||||||
.action-buttons
|
.action-buttons
|
||||||
%div
|
%div
|
||||||
|
@ -15,8 +15,8 @@
|
||||||
= link_to t('admin.accounts.warn'), new_admin_account_action_path(account.id, type: 'none'), class: 'button' if can?(:warn, account)
|
= link_to t('admin.accounts.warn'), new_admin_account_action_path(account.id, type: 'none'), class: 'button' if can?(:warn, account)
|
||||||
- if account.user_disabled?
|
- if account.user_disabled?
|
||||||
= link_to t('admin.accounts.enable'), enable_admin_account_path(account.id), method: :post, class: 'button' if can?(:enable, account.user)
|
= link_to t('admin.accounts.enable'), enable_admin_account_path(account.id), method: :post, class: 'button' if can?(:enable, account.user)
|
||||||
- else
|
- elsif can?(:disable, account.user)
|
||||||
= link_to t('admin.accounts.disable'), new_admin_account_action_path(account.id, type: 'disable'), class: 'button' if can?(:disable, account.user)
|
= link_to t('admin.accounts.disable'), new_admin_account_action_path(account.id, type: 'disable'), class: 'button'
|
||||||
- if account.sensitized?
|
- if account.sensitized?
|
||||||
= link_to t('admin.accounts.undo_sensitized'), unsensitive_admin_account_path(account.id), method: :post, class: 'button' if can?(:unsensitive, account)
|
= link_to t('admin.accounts.undo_sensitized'), unsensitive_admin_account_path(account.id), method: :post, class: 'button' if can?(:unsensitive, account)
|
||||||
- elsif !account.local? || account.user_approved?
|
- elsif !account.local? || account.user_approved?
|
||||||
|
@ -29,13 +29,13 @@
|
||||||
- if account.user_pending?
|
- if account.user_pending?
|
||||||
= link_to t('admin.accounts.approve'), approve_admin_account_path(account.id), method: :post, data: { confirm: t('admin.accounts.are_you_sure') }, class: 'button' if can?(:approve, account.user)
|
= link_to t('admin.accounts.approve'), approve_admin_account_path(account.id), method: :post, data: { confirm: t('admin.accounts.are_you_sure') }, class: 'button' if can?(:approve, account.user)
|
||||||
= link_to t('admin.accounts.reject'), reject_admin_account_path(account.id), method: :post, data: { confirm: t('admin.accounts.are_you_sure') }, class: 'button button--destructive' if can?(:reject, account.user)
|
= link_to t('admin.accounts.reject'), reject_admin_account_path(account.id), method: :post, data: { confirm: t('admin.accounts.are_you_sure') }, class: 'button button--destructive' if can?(:reject, account.user)
|
||||||
- unless account.user_confirmed?
|
- if !account.user_confirmed? && can?(:confirm, account.user)
|
||||||
= link_to t('admin.accounts.confirm'), admin_account_confirmation_path(account.id), method: :post, class: 'button' if can?(:confirm, account.user)
|
= link_to t('admin.accounts.confirm'), admin_account_confirmation_path(account.id), method: :post, class: 'button'
|
||||||
- if !account.local? || account.user_approved?
|
- if (!account.local? || account.user_approved?) && can?(:suspend, account)
|
||||||
= link_to t('admin.accounts.perform_full_suspension'), new_admin_account_action_path(account.id, type: 'suspend'), class: 'button' if can?(:suspend, account)
|
= link_to t('admin.accounts.perform_full_suspension'), new_admin_account_action_path(account.id, type: 'suspend'), class: 'button'
|
||||||
%div
|
%div
|
||||||
- if account.local?
|
- if account.local?
|
||||||
- if !account.memorial? && account.user_approved?
|
- if !account.memorial? && account.user_approved? && can?(:memorialize, account)
|
||||||
= link_to t('admin.accounts.memorialize'), memorialize_admin_account_path(account.id), method: :post, data: { confirm: t('admin.accounts.are_you_sure') }, class: 'button button--destructive' if can?(:memorialize, account)
|
= link_to t('admin.accounts.memorialize'), memorialize_admin_account_path(account.id), method: :post, data: { confirm: t('admin.accounts.are_you_sure') }, class: 'button button--destructive'
|
||||||
- else
|
- elsif can?(:redownload, account)
|
||||||
= link_to t('admin.accounts.redownload'), redownload_admin_account_path(account.id), method: :post, class: 'button' if can?(:redownload, account)
|
= link_to t('admin.accounts.redownload'), redownload_admin_account_path(account.id), method: :post, class: 'button'
|
||||||
|
|
|
@ -47,8 +47,8 @@
|
||||||
- else
|
- else
|
||||||
= t 'admin.accounts.security_measures.only_password'
|
= t 'admin.accounts.security_measures.only_password'
|
||||||
%td
|
%td
|
||||||
- if account.user&.two_factor_enabled?
|
- if account.user&.two_factor_enabled? && can?(:disable_2fa, account.user)
|
||||||
= table_link_to 'unlock', t('admin.accounts.disable_two_factor_authentication'), admin_user_two_factor_authentication_path(account.user.id), method: :delete if can?(:disable_2fa, account.user)
|
= table_link_to 'unlock', t('admin.accounts.disable_two_factor_authentication'), admin_user_two_factor_authentication_path(account.user.id), method: :delete
|
||||||
- if can?(:reset_password, account.user)
|
- if can?(:reset_password, account.user)
|
||||||
%tr
|
%tr
|
||||||
%td
|
%td
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
unless ENV.key?('RAILS_ENV')
|
unless ENV.key?('RAILS_ENV')
|
||||||
STDERR.puts 'ERROR: Missing RAILS_ENV environment variable, please set it to "production", "development", or "test".'
|
warn 'ERROR: Missing RAILS_ENV environment variable, please set it to "production", "development", or "test".'
|
||||||
exit 1
|
exit 1
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -79,7 +79,7 @@ Devise.setup do |config|
|
||||||
oidc_options[:client_auth_method] = ENV['OIDC_CLIENT_AUTH_METHOD'] if ENV['OIDC_CLIENT_AUTH_METHOD'] # OPTIONAL (default: basic)
|
oidc_options[:client_auth_method] = ENV['OIDC_CLIENT_AUTH_METHOD'] if ENV['OIDC_CLIENT_AUTH_METHOD'] # OPTIONAL (default: basic)
|
||||||
scope_string = ENV['OIDC_SCOPE'] if ENV['OIDC_SCOPE'] # NEED
|
scope_string = ENV['OIDC_SCOPE'] if ENV['OIDC_SCOPE'] # NEED
|
||||||
scopes = scope_string.split(',')
|
scopes = scope_string.split(',')
|
||||||
oidc_options[:scope] = scopes.map { |x| x.to_sym }
|
oidc_options[:scope] = scopes.map(&:to_sym)
|
||||||
oidc_options[:response_type] = ENV['OIDC_RESPONSE_TYPE'] if ENV['OIDC_RESPONSE_TYPE'] # OPTIONAL (default: code)
|
oidc_options[:response_type] = ENV['OIDC_RESPONSE_TYPE'] if ENV['OIDC_RESPONSE_TYPE'] # OPTIONAL (default: code)
|
||||||
oidc_options[:response_mode] = ENV['OIDC_RESPONSE_MODE'] if ENV['OIDC_RESPONSE_MODE'] # OPTIONAL (default: query)
|
oidc_options[:response_mode] = ENV['OIDC_RESPONSE_MODE'] if ENV['OIDC_RESPONSE_MODE'] # OPTIONAL (default: query)
|
||||||
oidc_options[:display] = ENV['OIDC_DISPLAY'] if ENV['OIDC_DISPLAY'] # OPTIONAL (default: page)
|
oidc_options[:display] = ENV['OIDC_DISPLAY'] if ENV['OIDC_DISPLAY'] # OPTIONAL (default: page)
|
||||||
|
|
5
spec/fabricators/custom_emoji_category_fabricator.rb
Normal file
5
spec/fabricators/custom_emoji_category_fabricator.rb
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
Fabricator(:custom_emoji_category) do
|
||||||
|
name { sequence(:name) { |i| "name_#{i}" } }
|
||||||
|
end
|
|
@ -178,11 +178,11 @@ RSpec.describe Remotable do
|
||||||
|
|
||||||
allow(foo).to receive(:public_send)
|
allow(foo).to receive(:public_send)
|
||||||
foo.hoge_remote_url = url
|
foo.hoge_remote_url = url
|
||||||
expect(foo).to have_received(:public_send).with("download_#{hoge}!", url)
|
expect(foo).to have_received(:public_send).with(:"download_#{hoge}!", url)
|
||||||
|
|
||||||
allow(foo).to receive(:public_send)
|
allow(foo).to receive(:public_send)
|
||||||
foo.download_hoge!(url)
|
foo.download_hoge!(url)
|
||||||
expect(foo).to have_received(:public_send).with("#{hoge}=", response_with_limit)
|
expect(foo).to have_received(:public_send).with(:"#{hoge}=", response_with_limit)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
118
spec/models/form/custom_emoji_batch_spec.rb
Normal file
118
spec/models/form/custom_emoji_batch_spec.rb
Normal file
|
@ -0,0 +1,118 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'rails_helper'
|
||||||
|
|
||||||
|
describe Form::CustomEmojiBatch do
|
||||||
|
describe '#save' do
|
||||||
|
subject { described_class.new({ current_account: account }.merge(options)) }
|
||||||
|
|
||||||
|
let(:options) { {} }
|
||||||
|
let(:account) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')).account }
|
||||||
|
|
||||||
|
context 'with empty custom_emoji_ids' do
|
||||||
|
let(:options) { { custom_emoji_ids: [] } }
|
||||||
|
|
||||||
|
it 'does nothing if custom_emoji_ids is empty' do
|
||||||
|
expect(subject.save).to be_nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'the update action' do
|
||||||
|
let(:custom_emoji) { Fabricate(:custom_emoji, category: Fabricate(:custom_emoji_category)) }
|
||||||
|
let(:custom_emoji_category) { Fabricate(:custom_emoji_category) }
|
||||||
|
|
||||||
|
context 'without anything to change' do
|
||||||
|
let(:options) { { action: 'update' } }
|
||||||
|
|
||||||
|
it 'silently exits without updating any custom emojis' do
|
||||||
|
expect { subject.save }.to_not change(Admin::ActionLog, :count)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with a category_id' do
|
||||||
|
let(:options) { { action: 'update', custom_emoji_ids: [custom_emoji.id], category_id: custom_emoji_category.id } }
|
||||||
|
|
||||||
|
it 'updates the category of the emoji' do
|
||||||
|
subject.save
|
||||||
|
|
||||||
|
expect(custom_emoji.reload.category).to eq(custom_emoji_category)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with a category_name' do
|
||||||
|
let(:options) { { action: 'update', custom_emoji_ids: [custom_emoji.id], category_name: custom_emoji_category.name } }
|
||||||
|
|
||||||
|
it 'updates the category of the emoji' do
|
||||||
|
subject.save
|
||||||
|
|
||||||
|
expect(custom_emoji.reload.category).to eq(custom_emoji_category)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'the list action' do
|
||||||
|
let(:custom_emoji) { Fabricate(:custom_emoji, visible_in_picker: false) }
|
||||||
|
let(:options) { { action: 'list', custom_emoji_ids: [custom_emoji.id] } }
|
||||||
|
|
||||||
|
it 'updates the picker visibility of the emoji' do
|
||||||
|
subject.save
|
||||||
|
|
||||||
|
expect(custom_emoji.reload.visible_in_picker).to be(true)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'the unlist action' do
|
||||||
|
let(:custom_emoji) { Fabricate(:custom_emoji, visible_in_picker: true) }
|
||||||
|
let(:options) { { action: 'unlist', custom_emoji_ids: [custom_emoji.id] } }
|
||||||
|
|
||||||
|
it 'updates the picker visibility of the emoji' do
|
||||||
|
subject.save
|
||||||
|
|
||||||
|
expect(custom_emoji.reload.visible_in_picker).to be(false)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'the enable action' do
|
||||||
|
let(:custom_emoji) { Fabricate(:custom_emoji, disabled: true) }
|
||||||
|
let(:options) { { action: 'enable', custom_emoji_ids: [custom_emoji.id] } }
|
||||||
|
|
||||||
|
it 'updates the disabled value of the emoji' do
|
||||||
|
subject.save
|
||||||
|
|
||||||
|
expect(custom_emoji.reload).to_not be_disabled
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'the disable action' do
|
||||||
|
let(:custom_emoji) { Fabricate(:custom_emoji, visible_in_picker: false) }
|
||||||
|
let(:options) { { action: 'disable', custom_emoji_ids: [custom_emoji.id] } }
|
||||||
|
|
||||||
|
it 'updates the disabled value of the emoji' do
|
||||||
|
subject.save
|
||||||
|
|
||||||
|
expect(custom_emoji.reload).to be_disabled
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'the copy action' do
|
||||||
|
let(:custom_emoji) { Fabricate(:custom_emoji) }
|
||||||
|
let(:options) { { action: 'copy', custom_emoji_ids: [custom_emoji.id] } }
|
||||||
|
|
||||||
|
it 'makes a copy of the emoji' do
|
||||||
|
expect { subject.save }
|
||||||
|
.to change(CustomEmoji, :count).by(1)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'the delete action' do
|
||||||
|
let(:custom_emoji) { Fabricate(:custom_emoji) }
|
||||||
|
let(:options) { { action: 'delete', custom_emoji_ids: [custom_emoji.id] } }
|
||||||
|
|
||||||
|
it 'destroys the emoji' do
|
||||||
|
subject.save
|
||||||
|
|
||||||
|
expect { custom_emoji.reload }.to raise_error(ActiveRecord::RecordNotFound)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -5,19 +5,18 @@ require 'rails_helper'
|
||||||
RSpec.describe AccountRelationshipsPresenter do
|
RSpec.describe AccountRelationshipsPresenter do
|
||||||
describe '.initialize' do
|
describe '.initialize' do
|
||||||
before do
|
before do
|
||||||
allow(Account).to receive(:following_map).with(account_ids, current_account_id).and_return(default_map)
|
allow(Account).to receive(:following_map).with(accounts.pluck(:id), current_account_id).and_return(default_map)
|
||||||
allow(Account).to receive(:followed_by_map).with(account_ids, current_account_id).and_return(default_map)
|
allow(Account).to receive(:followed_by_map).with(accounts.pluck(:id), current_account_id).and_return(default_map)
|
||||||
allow(Account).to receive(:blocking_map).with(account_ids, current_account_id).and_return(default_map)
|
allow(Account).to receive(:blocking_map).with(accounts.pluck(:id), current_account_id).and_return(default_map)
|
||||||
allow(Account).to receive(:muting_map).with(account_ids, current_account_id).and_return(default_map)
|
allow(Account).to receive(:muting_map).with(accounts.pluck(:id), current_account_id).and_return(default_map)
|
||||||
allow(Account).to receive(:requested_map).with(account_ids, current_account_id).and_return(default_map)
|
allow(Account).to receive(:requested_map).with(accounts.pluck(:id), current_account_id).and_return(default_map)
|
||||||
allow(Account).to receive(:requested_by_map).with(account_ids, current_account_id).and_return(default_map)
|
allow(Account).to receive(:requested_by_map).with(accounts.pluck(:id), current_account_id).and_return(default_map)
|
||||||
allow(Account).to receive(:domain_blocking_map).with(account_ids, current_account_id).and_return(default_map)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
let(:presenter) { described_class.new(account_ids, current_account_id, **options) }
|
let(:presenter) { described_class.new(accounts, current_account_id, **options) }
|
||||||
let(:current_account_id) { Fabricate(:account).id }
|
let(:current_account_id) { Fabricate(:account).id }
|
||||||
let(:account_ids) { [Fabricate(:account).id] }
|
let(:accounts) { [Fabricate(:account)] }
|
||||||
let(:default_map) { { 1 => true } }
|
let(:default_map) { { accounts[0].id => true } }
|
||||||
|
|
||||||
context 'when options are not set' do
|
context 'when options are not set' do
|
||||||
let(:options) { {} }
|
let(:options) { {} }
|
||||||
|
@ -29,7 +28,33 @@ RSpec.describe AccountRelationshipsPresenter do
|
||||||
blocking: default_map,
|
blocking: default_map,
|
||||||
muting: default_map,
|
muting: default_map,
|
||||||
requested: default_map,
|
requested: default_map,
|
||||||
domain_blocking: default_map
|
domain_blocking: { accounts[0].id => nil }
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with a warm cache' do
|
||||||
|
let(:options) { {} }
|
||||||
|
|
||||||
|
before do
|
||||||
|
described_class.new(accounts, current_account_id, **options)
|
||||||
|
|
||||||
|
allow(Account).to receive(:following_map).with([], current_account_id).and_return({})
|
||||||
|
allow(Account).to receive(:followed_by_map).with([], current_account_id).and_return({})
|
||||||
|
allow(Account).to receive(:blocking_map).with([], current_account_id).and_return({})
|
||||||
|
allow(Account).to receive(:muting_map).with([], current_account_id).and_return({})
|
||||||
|
allow(Account).to receive(:requested_map).with([], current_account_id).and_return({})
|
||||||
|
allow(Account).to receive(:requested_by_map).with([], current_account_id).and_return({})
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'sets returns expected values' do
|
||||||
|
expect(presenter).to have_attributes(
|
||||||
|
following: default_map,
|
||||||
|
followed_by: default_map,
|
||||||
|
blocking: default_map,
|
||||||
|
muting: default_map,
|
||||||
|
requested: default_map,
|
||||||
|
domain_blocking: { accounts[0].id => nil }
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -86,7 +111,7 @@ RSpec.describe AccountRelationshipsPresenter do
|
||||||
let(:options) { { domain_blocking_map: { 7 => true } } }
|
let(:options) { { domain_blocking_map: { 7 => true } } }
|
||||||
|
|
||||||
it 'sets @domain_blocking merged with default_map and options[:domain_blocking_map]' do
|
it 'sets @domain_blocking merged with default_map and options[:domain_blocking_map]' do
|
||||||
expect(presenter.domain_blocking).to eq default_map.merge(options[:domain_blocking_map])
|
expect(presenter.domain_blocking).to eq({ accounts[0].id => nil }.merge(options[:domain_blocking_map]))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -4,7 +4,7 @@ require 'rails_helper'
|
||||||
|
|
||||||
describe 'OmniAuth callbacks' do
|
describe 'OmniAuth callbacks' do
|
||||||
shared_examples 'omniauth provider callbacks' do |provider|
|
shared_examples 'omniauth provider callbacks' do |provider|
|
||||||
subject { post send "user_#{provider}_omniauth_callback_path" }
|
subject { post send :"user_#{provider}_omniauth_callback_path" }
|
||||||
|
|
||||||
context 'with full information in response' do
|
context 'with full information in response' do
|
||||||
before do
|
before do
|
||||||
|
|
Loading…
Reference in a new issue