Merge branch 'master' into glitch-soc/merge-upstream
Conflicts: - `app/models/public_feed.rb`: Upstream refactored a bit, glitch-soc had specific code for local-only statuses. Updated glitch-soc's specific code accordingly.
This commit is contained in:
		
						commit
						33d30632fb
					
				@ -2,7 +2,8 @@ require:
 | 
				
			|||||||
  - rubocop-rails
 | 
					  - rubocop-rails
 | 
				
			||||||
 | 
					
 | 
				
			||||||
AllCops:
 | 
					AllCops:
 | 
				
			||||||
  TargetRubyVersion: 2.4
 | 
					  TargetRubyVersion: 2.5
 | 
				
			||||||
 | 
					  NewCops: disable
 | 
				
			||||||
  Exclude:
 | 
					  Exclude:
 | 
				
			||||||
  - 'spec/**/*'
 | 
					  - 'spec/**/*'
 | 
				
			||||||
  - 'db/**/*'
 | 
					  - 'db/**/*'
 | 
				
			||||||
 | 
				
			|||||||
@ -1,7 +1,7 @@
 | 
				
			|||||||
FROM ubuntu:20.04 as build-dep
 | 
					FROM ubuntu:20.04 as build-dep
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Use bash for the shell
 | 
					# Use bash for the shell
 | 
				
			||||||
SHELL ["bash", "-c"]
 | 
					SHELL ["/usr/bin/bash", "-c"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Install Node v12 (LTS)
 | 
					# Install Node v12 (LTS)
 | 
				
			||||||
ENV NODE_VER="12.20.0"
 | 
					ENV NODE_VER="12.20.0"
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										2
									
								
								Gemfile
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								Gemfile
									
									
									
									
									
								
							@ -135,7 +135,7 @@ group :development do
 | 
				
			|||||||
  gem 'active_record_query_trace', '~> 1.8'
 | 
					  gem 'active_record_query_trace', '~> 1.8'
 | 
				
			||||||
  gem 'annotate', '~> 3.1'
 | 
					  gem 'annotate', '~> 3.1'
 | 
				
			||||||
  gem 'better_errors', '~> 2.9'
 | 
					  gem 'better_errors', '~> 2.9'
 | 
				
			||||||
  gem 'binding_of_caller', '~> 0.7'
 | 
					  gem 'binding_of_caller', '~> 1.0'
 | 
				
			||||||
  gem 'bullet', '~> 6.1'
 | 
					  gem 'bullet', '~> 6.1'
 | 
				
			||||||
  gem 'letter_opener', '~> 1.7'
 | 
					  gem 'letter_opener', '~> 1.7'
 | 
				
			||||||
  gem 'letter_opener_web', '~> 1.4'
 | 
					  gem 'letter_opener_web', '~> 1.4'
 | 
				
			||||||
 | 
				
			|||||||
@ -100,7 +100,7 @@ GEM
 | 
				
			|||||||
      erubi (>= 1.0.0)
 | 
					      erubi (>= 1.0.0)
 | 
				
			||||||
      rack (>= 0.9.0)
 | 
					      rack (>= 0.9.0)
 | 
				
			||||||
    bindata (2.4.8)
 | 
					    bindata (2.4.8)
 | 
				
			||||||
    binding_of_caller (0.8.0)
 | 
					    binding_of_caller (1.0.0)
 | 
				
			||||||
      debug_inspector (>= 0.0.1)
 | 
					      debug_inspector (>= 0.0.1)
 | 
				
			||||||
    blurhash (0.1.4)
 | 
					    blurhash (0.1.4)
 | 
				
			||||||
      ffi (~> 1.10.0)
 | 
					      ffi (~> 1.10.0)
 | 
				
			||||||
@ -165,7 +165,7 @@ GEM
 | 
				
			|||||||
    crass (1.0.6)
 | 
					    crass (1.0.6)
 | 
				
			||||||
    css_parser (1.7.1)
 | 
					    css_parser (1.7.1)
 | 
				
			||||||
      addressable
 | 
					      addressable
 | 
				
			||||||
    debug_inspector (0.0.3)
 | 
					    debug_inspector (1.0.0)
 | 
				
			||||||
    devise (4.7.3)
 | 
					    devise (4.7.3)
 | 
				
			||||||
      bcrypt (~> 3.0)
 | 
					      bcrypt (~> 3.0)
 | 
				
			||||||
      orm_adapter (~> 0.1)
 | 
					      orm_adapter (~> 0.1)
 | 
				
			||||||
@ -691,7 +691,7 @@ DEPENDENCIES
 | 
				
			|||||||
  annotate (~> 3.1)
 | 
					  annotate (~> 3.1)
 | 
				
			||||||
  aws-sdk-s3 (~> 1.87)
 | 
					  aws-sdk-s3 (~> 1.87)
 | 
				
			||||||
  better_errors (~> 2.9)
 | 
					  better_errors (~> 2.9)
 | 
				
			||||||
  binding_of_caller (~> 0.7)
 | 
					  binding_of_caller (~> 1.0)
 | 
				
			||||||
  blurhash (~> 0.1)
 | 
					  blurhash (~> 0.1)
 | 
				
			||||||
  bootsnap (~> 1.5)
 | 
					  bootsnap (~> 1.5)
 | 
				
			||||||
  brakeman (~> 4.10)
 | 
					  brakeman (~> 4.10)
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,4 @@
 | 
				
			|||||||
web: env PORT=3000 bundle exec puma -C config/puma.rb
 | 
					web: env PORT=3000 RAILS_ENV=development bundle exec puma -C config/puma.rb
 | 
				
			||||||
sidekiq: env PORT=3000 bundle exec sidekiq
 | 
					sidekiq: env PORT=3000 RAILS_ENV=development bundle exec sidekiq
 | 
				
			||||||
stream: env PORT=4000 yarn run start
 | 
					stream: env PORT=4000 yarn run start
 | 
				
			||||||
webpack: ./bin/webpack-dev-server --listen-host 0.0.0.0
 | 
					webpack: ./bin/webpack-dev-server --listen-host 0.0.0.0
 | 
				
			||||||
 | 
				
			|||||||
@ -5,7 +5,7 @@ class ActivityPub::InboxesController < ActivityPub::BaseController
 | 
				
			|||||||
  include JsonLdHelper
 | 
					  include JsonLdHelper
 | 
				
			||||||
  include AccountOwnedConcern
 | 
					  include AccountOwnedConcern
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  before_action :skip_unknown_actor_delete
 | 
					  before_action :skip_unknown_actor_activity
 | 
				
			||||||
  before_action :require_signature!
 | 
					  before_action :require_signature!
 | 
				
			||||||
  skip_before_action :authenticate_user!
 | 
					  skip_before_action :authenticate_user!
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -18,13 +18,13 @@ class ActivityPub::InboxesController < ActivityPub::BaseController
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  private
 | 
					  private
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def skip_unknown_actor_delete
 | 
					  def skip_unknown_actor_activity
 | 
				
			||||||
    head 202 if unknown_deleted_account?
 | 
					    head 202 if unknown_affected_account?
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def unknown_deleted_account?
 | 
					  def unknown_affected_account?
 | 
				
			||||||
    json = Oj.load(body, mode: :strict)
 | 
					    json = Oj.load(body, mode: :strict)
 | 
				
			||||||
    json.is_a?(Hash) && json['type'] == 'Delete' && json['actor'].present? && json['actor'] == value_or_id(json['object']) && !Account.where(uri: json['actor']).exists?
 | 
					    json.is_a?(Hash) && %w(Delete Update).include?(json['type']) && json['actor'].present? && json['actor'] == value_or_id(json['object']) && !Account.where(uri: json['actor']).exists?
 | 
				
			||||||
  rescue Oj::ParseError
 | 
					  rescue Oj::ParseError
 | 
				
			||||||
    false
 | 
					    false
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
				
			|||||||
@ -42,7 +42,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] || 0))
 | 
					    MuteService.new.call(current_user.account, @account, notifications: truthy_param?(:notifications), duration: (params[:duration]&.to_i || 0))
 | 
				
			||||||
    render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships
 | 
					    render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -12,7 +12,7 @@ class Api::V1::Crypto::Keys::ClaimsController < Api::BaseController
 | 
				
			|||||||
  private
 | 
					  private
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def set_claim_results
 | 
					  def set_claim_results
 | 
				
			||||||
    @claim_results = devices.map { |device_params| ::Keys::ClaimService.new.call(current_account, device_params[:account_id], device_params[:device_id]) }.compact
 | 
					    @claim_results = devices.filter_map { |device_params| ::Keys::ClaimService.new.call(current_account, device_params[:account_id], device_params[:device_id]) }
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def resource_params
 | 
					  def resource_params
 | 
				
			||||||
 | 
				
			|||||||
@ -17,7 +17,7 @@ class Api::V1::Crypto::Keys::QueriesController < Api::BaseController
 | 
				
			|||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def set_query_results
 | 
					  def set_query_results
 | 
				
			||||||
    @query_results = @accounts.map { |account| ::Keys::QueryService.new.call(account) }.compact
 | 
					    @query_results = @accounts.filter_map { |account| ::Keys::QueryService.new.call(account) }
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def account_ids
 | 
					  def account_ids
 | 
				
			||||||
 | 
				
			|||||||
@ -45,7 +45,7 @@ module CacheConcern
 | 
				
			|||||||
      end
 | 
					      end
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    raw.map { |item| cached_keys_with_value[item.id] || uncached[item.id] }.compact
 | 
					    raw.filter_map { |item| cached_keys_with_value[item.id] || uncached[item.id] }
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def cache_collection_paginated_by_id(raw, klass, limit, options)
 | 
					  def cache_collection_paginated_by_id(raw, klass, limit, options)
 | 
				
			||||||
 | 
				
			|||||||
@ -227,7 +227,7 @@ class FocalPointModal extends ImmutablePureComponent {
 | 
				
			|||||||
      const worker = createWorker({
 | 
					      const worker = createWorker({
 | 
				
			||||||
        workerPath: tesseractWorkerPath,
 | 
					        workerPath: tesseractWorkerPath,
 | 
				
			||||||
        corePath: tesseractCorePath,
 | 
					        corePath: tesseractCorePath,
 | 
				
			||||||
        langPath: assetHost,
 | 
					        langPath: `${assetHost}/ocr/lang-data/`,
 | 
				
			||||||
        logger: ({ status, progress }) => {
 | 
					        logger: ({ status, progress }) => {
 | 
				
			||||||
          if (status === 'recognizing text') {
 | 
					          if (status === 'recognizing text') {
 | 
				
			||||||
            this.setState({ ocrStatus: 'detecting', progress });
 | 
					            this.setState({ ocrStatus: 'detecting', progress });
 | 
				
			||||||
 | 
				
			|||||||
@ -4,8 +4,8 @@ class ActivityPub::Activity::Flag < ActivityPub::Activity
 | 
				
			|||||||
  def perform
 | 
					  def perform
 | 
				
			||||||
    return if skip_reports?
 | 
					    return if skip_reports?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    target_accounts            = object_uris.map { |uri| account_from_uri(uri) }.compact.select(&:local?)
 | 
					    target_accounts            = object_uris.filter_map { |uri| account_from_uri(uri) }.select(&:local?)
 | 
				
			||||||
    target_statuses_by_account = object_uris.map { |uri| status_from_uri(uri) }.compact.select(&:local?).group_by(&:account_id)
 | 
					    target_statuses_by_account = object_uris.filter_map { |uri| status_from_uri(uri) }.select(&:local?).group_by(&:account_id)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    target_accounts.each do |target_account|
 | 
					    target_accounts.each do |target_account|
 | 
				
			||||||
      target_statuses = target_statuses_by_account[target_account.id]
 | 
					      target_statuses = target_statuses_by_account[target_account.id]
 | 
				
			||||||
 | 
				
			|||||||
@ -29,7 +29,7 @@ class EntityCache
 | 
				
			|||||||
      uncached.each_value { |item| Rails.cache.write(to_key(:emoji, item.shortcode, domain), item, expires_in: MAX_EXPIRATION) }
 | 
					      uncached.each_value { |item| Rails.cache.write(to_key(:emoji, item.shortcode, domain), item, expires_in: MAX_EXPIRATION) }
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    shortcodes.map { |shortcode| cached[to_key(:emoji, shortcode, domain)] || uncached[shortcode] }.compact
 | 
					    shortcodes.filter_map { |shortcode| cached[to_key(:emoji, shortcode, domain)] || uncached[shortcode] }
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def to_key(type, *ids)
 | 
					  def to_key(type, *ids)
 | 
				
			||||||
 | 
				
			|||||||
@ -186,9 +186,9 @@ class SpamCheck
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  def matching_status_ids
 | 
					  def matching_status_ids
 | 
				
			||||||
    if nilsimsa?
 | 
					    if nilsimsa?
 | 
				
			||||||
      other_digests.select { |record| record.start_with?('nilsimsa') && nilsimsa_compare_value(digest, record.split(':')[1]) >= NILSIMSA_COMPARE_THRESHOLD }.map { |record| record.split(':')[2] }.compact
 | 
					      other_digests.select { |record| record.start_with?('nilsimsa') && nilsimsa_compare_value(digest, record.split(':')[1]) >= NILSIMSA_COMPARE_THRESHOLD }.filter_map { |record| record.split(':')[2] }
 | 
				
			||||||
    else
 | 
					    else
 | 
				
			||||||
      other_digests.select { |record| record.start_with?('md5') && record.split(':')[1] == digest }.map { |record| record.split(':')[2] }.compact
 | 
					      other_digests.select { |record| record.start_with?('md5') && record.split(':')[1] == digest }.filter_map { |record| record.split(':')[2] }
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -387,15 +387,17 @@ class Account < ApplicationRecord
 | 
				
			|||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  class Field < ActiveModelSerializers::Model
 | 
					  class Field < ActiveModelSerializers::Model
 | 
				
			||||||
    attributes :name, :value, :verified_at, :account, :errors
 | 
					    attributes :name, :value, :verified_at, :account
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def initialize(account, attributes)
 | 
					    def initialize(account, attributes)
 | 
				
			||||||
      @account     = account
 | 
					      @original_field = attributes
 | 
				
			||||||
      @attributes  = attributes
 | 
					      string_limit = account.local? ? 255 : 2047
 | 
				
			||||||
      @name        = attributes['name'].strip[0, string_limit]
 | 
					      super(
 | 
				
			||||||
      @value       = attributes['value'].strip[0, string_limit]
 | 
					        account:     account,
 | 
				
			||||||
      @verified_at = attributes['verified_at']&.to_datetime
 | 
					        name:        attributes['name'].strip[0, string_limit],
 | 
				
			||||||
      @errors      = {}
 | 
					        value:       attributes['value'].strip[0, string_limit],
 | 
				
			||||||
 | 
					        verified_at: attributes['verified_at']&.to_datetime,
 | 
				
			||||||
 | 
					      )
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def verified?
 | 
					    def verified?
 | 
				
			||||||
@ -417,22 +419,12 @@ class Account < ApplicationRecord
 | 
				
			|||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def mark_verified!
 | 
					    def mark_verified!
 | 
				
			||||||
      @verified_at = Time.now.utc
 | 
					      self.verified_at = Time.now.utc
 | 
				
			||||||
      @attributes['verified_at'] = @verified_at
 | 
					      @original_field['verified_at'] = verified_at
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def to_h
 | 
					    def to_h
 | 
				
			||||||
      { name: @name, value: @value, verified_at: @verified_at }
 | 
					      { name: name, value: value, verified_at: verified_at }
 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def string_limit
 | 
					 | 
				
			||||||
      if account.local?
 | 
					 | 
				
			||||||
        255
 | 
					 | 
				
			||||||
      else
 | 
					 | 
				
			||||||
        2047
 | 
					 | 
				
			||||||
      end
 | 
					 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -518,7 +510,7 @@ class Account < ApplicationRecord
 | 
				
			|||||||
    def from_text(text)
 | 
					    def from_text(text)
 | 
				
			||||||
      return [] if text.blank?
 | 
					      return [] if text.blank?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      text.scan(MENTION_RE).map { |match| match.first.split('@', 2) }.uniq.map do |(username, domain)|
 | 
					      text.scan(MENTION_RE).map { |match| match.first.split('@', 2) }.uniq.filter_map do |(username, domain)|
 | 
				
			||||||
        domain = begin
 | 
					        domain = begin
 | 
				
			||||||
          if TagManager.instance.local_domain?(domain)
 | 
					          if TagManager.instance.local_domain?(domain)
 | 
				
			||||||
            nil
 | 
					            nil
 | 
				
			||||||
@ -527,7 +519,7 @@ class Account < ApplicationRecord
 | 
				
			|||||||
          end
 | 
					          end
 | 
				
			||||||
        end
 | 
					        end
 | 
				
			||||||
        EntityCache.instance.mention(username, domain)
 | 
					        EntityCache.instance.mention(username, domain)
 | 
				
			||||||
      end.compact
 | 
					      end
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private
 | 
					    private
 | 
				
			||||||
 | 
				
			|||||||
@ -83,7 +83,7 @@ module StatusThreadingConcern
 | 
				
			|||||||
  def find_statuses_from_tree_path(ids, account, promote: false)
 | 
					  def find_statuses_from_tree_path(ids, account, promote: false)
 | 
				
			||||||
    statuses    = Status.with_accounts(ids).to_a
 | 
					    statuses    = Status.with_accounts(ids).to_a
 | 
				
			||||||
    account_ids = statuses.map(&:account_id).uniq
 | 
					    account_ids = statuses.map(&:account_id).uniq
 | 
				
			||||||
    domains     = statuses.map(&:account_domain).compact.uniq
 | 
					    domains     = statuses.filter_map(&:account_domain).uniq
 | 
				
			||||||
    relations   = relations_map_for_account(account, account_ids, domains)
 | 
					    relations   = relations_map_for_account(account, account_ids, domains)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    statuses.reject! { |status| StatusFilter.new(status, account, relations).filtered? }
 | 
					    statuses.reject! { |status| StatusFilter.new(status, account, relations).filtered? }
 | 
				
			||||||
 | 
				
			|||||||
@ -46,7 +46,7 @@ class CustomFilter < ApplicationRecord
 | 
				
			|||||||
  private
 | 
					  private
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def clean_up_contexts
 | 
					  def clean_up_contexts
 | 
				
			||||||
    self.context = Array(context).map(&:strip).map(&:presence).compact
 | 
					    self.context = Array(context).map(&:strip).filter_map(&:presence)
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def remove_cache
 | 
					  def remove_cache
 | 
				
			||||||
 | 
				
			|||||||
@ -2,12 +2,11 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
class HomeFeed < Feed
 | 
					class HomeFeed < Feed
 | 
				
			||||||
  def initialize(account)
 | 
					  def initialize(account)
 | 
				
			||||||
    @type    = :home
 | 
					 | 
				
			||||||
    @id      = account.id
 | 
					 | 
				
			||||||
    @account = account
 | 
					    @account = account
 | 
				
			||||||
 | 
					    super(:home, account.id)
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def regenerating?
 | 
					  def regenerating?
 | 
				
			||||||
    redis.exists?("account:#{@id}:regeneration")
 | 
					    redis.exists?("account:#{@account.id}:regeneration")
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
				
			|||||||
@ -2,7 +2,6 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
class ListFeed < Feed
 | 
					class ListFeed < Feed
 | 
				
			||||||
  def initialize(list)
 | 
					  def initialize(list)
 | 
				
			||||||
    @type    = :list
 | 
					    super(:list, list.id)
 | 
				
			||||||
    @id      = list.id
 | 
					 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
				
			|||||||
@ -92,7 +92,7 @@ class Notification < ApplicationRecord
 | 
				
			|||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def reload_stale_associations!(cached_items)
 | 
					    def reload_stale_associations!(cached_items)
 | 
				
			||||||
      account_ids = (cached_items.map(&:from_account_id) + cached_items.map { |item| item.target_status&.account_id }.compact).uniq
 | 
					      account_ids = (cached_items.map(&:from_account_id) + cached_items.filter_map { |item| item.target_status&.account_id }).uniq
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      return if account_ids.empty?
 | 
					      return if account_ids.empty?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -73,10 +73,12 @@ class Poll < ApplicationRecord
 | 
				
			|||||||
    attributes :id, :title, :votes_count, :poll
 | 
					    attributes :id, :title, :votes_count, :poll
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def initialize(poll, id, title, votes_count)
 | 
					    def initialize(poll, id, title, votes_count)
 | 
				
			||||||
      @poll        = poll
 | 
					      super(
 | 
				
			||||||
      @id          = id
 | 
					        poll:        poll,
 | 
				
			||||||
      @title       = title
 | 
					        id:          id,
 | 
				
			||||||
      @votes_count = votes_count
 | 
					        title:       title,
 | 
				
			||||||
 | 
					        votes_count: votes_count,
 | 
				
			||||||
 | 
					      )
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,6 +1,6 @@
 | 
				
			|||||||
# frozen_string_literal: true
 | 
					# frozen_string_literal: true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class PublicFeed < Feed
 | 
					class PublicFeed
 | 
				
			||||||
  # @param [Account] account
 | 
					  # @param [Account] account
 | 
				
			||||||
  # @param [Hash] options
 | 
					  # @param [Hash] options
 | 
				
			||||||
  # @option [Boolean] :with_replies
 | 
					  # @option [Boolean] :with_replies
 | 
				
			||||||
@ -35,36 +35,38 @@ class PublicFeed < Feed
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  private
 | 
					  private
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  attr_reader :account, :options
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def allow_local_only?
 | 
					  def allow_local_only?
 | 
				
			||||||
    local_account? && (local_only? || @options[:allow_local_only])
 | 
					    local_account? && (local_only? || options[:allow_local_only])
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def with_reblogs?
 | 
					  def with_reblogs?
 | 
				
			||||||
    @options[:with_reblogs]
 | 
					    options[:with_reblogs]
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def with_replies?
 | 
					  def with_replies?
 | 
				
			||||||
    @options[:with_replies]
 | 
					    options[:with_replies]
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def local_only?
 | 
					  def local_only?
 | 
				
			||||||
    @options[:local]
 | 
					    options[:local]
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def remote_only?
 | 
					  def remote_only?
 | 
				
			||||||
    @options[:remote]
 | 
					    options[:remote]
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def account?
 | 
					  def account?
 | 
				
			||||||
    @account.present?
 | 
					    account.present?
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def local_account?
 | 
					  def local_account?
 | 
				
			||||||
    @account&.local?
 | 
					    account&.local?
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def media_only?
 | 
					  def media_only?
 | 
				
			||||||
    @options[:only_media]
 | 
					    options[:only_media]
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def public_scope
 | 
					  def public_scope
 | 
				
			||||||
@ -96,9 +98,9 @@ class PublicFeed < Feed
 | 
				
			|||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def account_filters_scope
 | 
					  def account_filters_scope
 | 
				
			||||||
    Status.not_excluded_by_account(@account).tap do |scope|
 | 
					    Status.not_excluded_by_account(account).tap do |scope|
 | 
				
			||||||
      scope.merge!(Status.not_domain_blocked_by_account(@account)) unless local_only?
 | 
					      scope.merge!(Status.not_domain_blocked_by_account(account)) unless local_only?
 | 
				
			||||||
      scope.merge!(Status.in_chosen_languages(@account)) if @account.chosen_languages.present?
 | 
					      scope.merge!(Status.in_chosen_languages(account)) if account.chosen_languages.present?
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
				
			|||||||
@ -387,7 +387,7 @@ class Status < ApplicationRecord
 | 
				
			|||||||
    def from_text(text)
 | 
					    def from_text(text)
 | 
				
			||||||
      return [] if text.blank?
 | 
					      return [] if text.blank?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      text.scan(FetchLinkCardService::URL_PATTERN).map(&:first).uniq.map do |url|
 | 
					      text.scan(FetchLinkCardService::URL_PATTERN).map(&:first).uniq.filter_map do |url|
 | 
				
			||||||
        status = begin
 | 
					        status = begin
 | 
				
			||||||
          if TagManager.instance.local_url?(url)
 | 
					          if TagManager.instance.local_url?(url)
 | 
				
			||||||
            ActivityPub::TagManager.instance.uri_to_resource(url, Status)
 | 
					            ActivityPub::TagManager.instance.uri_to_resource(url, Status)
 | 
				
			||||||
@ -396,7 +396,7 @@ class Status < ApplicationRecord
 | 
				
			|||||||
          end
 | 
					          end
 | 
				
			||||||
        end
 | 
					        end
 | 
				
			||||||
        status&.distributable? ? status : nil
 | 
					        status&.distributable? ? status : nil
 | 
				
			||||||
      end.compact
 | 
					      end
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -13,9 +13,8 @@ class TagFeed < PublicFeed
 | 
				
			|||||||
  # @option [Boolean] :remote
 | 
					  # @option [Boolean] :remote
 | 
				
			||||||
  # @option [Boolean] :only_media
 | 
					  # @option [Boolean] :only_media
 | 
				
			||||||
  def initialize(tag, account, options = {})
 | 
					  def initialize(tag, account, options = {})
 | 
				
			||||||
    @tag     = tag
 | 
					    @tag = tag
 | 
				
			||||||
    @account = account
 | 
					    super(account, options)
 | 
				
			||||||
    @options = options
 | 
					 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  # @param [Integer] limit
 | 
					  # @param [Integer] limit
 | 
				
			||||||
@ -41,15 +40,15 @@ class TagFeed < PublicFeed
 | 
				
			|||||||
  private
 | 
					  private
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def tagged_with_any_scope
 | 
					  def tagged_with_any_scope
 | 
				
			||||||
    Status.group(:id).tagged_with(tags_for(Array(@tag.name) | Array(@options[:any])))
 | 
					    Status.group(:id).tagged_with(tags_for(Array(@tag.name) | Array(options[:any])))
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def tagged_with_all_scope
 | 
					  def tagged_with_all_scope
 | 
				
			||||||
    Status.group(:id).tagged_with_all(tags_for(@options[:all]))
 | 
					    Status.group(:id).tagged_with_all(tags_for(options[:all]))
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def tagged_with_none_scope
 | 
					  def tagged_with_none_scope
 | 
				
			||||||
    Status.group(:id).tagged_with_none(tags_for(@options[:none]))
 | 
					    Status.group(:id).tagged_with_none(tags_for(options[:none]))
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def tags_for(names)
 | 
					  def tags_for(names)
 | 
				
			||||||
 | 
				
			|||||||
@ -14,7 +14,7 @@ class StatusRelationshipsPresenter
 | 
				
			|||||||
    else
 | 
					    else
 | 
				
			||||||
      statuses            = statuses.compact
 | 
					      statuses            = statuses.compact
 | 
				
			||||||
      status_ids          = statuses.flat_map { |s| [s.id, s.reblog_of_id] }.uniq.compact
 | 
					      status_ids          = statuses.flat_map { |s| [s.id, s.reblog_of_id] }.uniq.compact
 | 
				
			||||||
      conversation_ids    = statuses.map(&:conversation_id).compact.uniq
 | 
					      conversation_ids    = statuses.filter_map(&:conversation_id).uniq
 | 
				
			||||||
      pinnable_status_ids = statuses.map(&:proper).select { |s| s.account_id == current_account_id && %w(public unlisted).include?(s.visibility) }.map(&:id)
 | 
					      pinnable_status_ids = statuses.map(&:proper).select { |s| s.account_id == current_account_id && %w(public unlisted).include?(s.visibility) }.map(&:id)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      @reblogs_map     = Status.reblogs_map(status_ids, current_account_id).merge(options[:reblogs_map] || {})
 | 
					      @reblogs_map     = Status.reblogs_map(status_ids, current_account_id).merge(options[:reblogs_map] || {})
 | 
				
			||||||
 | 
				
			|||||||
@ -24,8 +24,7 @@ class ActivityPub::FetchFeaturedCollectionService < BaseService
 | 
				
			|||||||
  def process_items(items)
 | 
					  def process_items(items)
 | 
				
			||||||
    status_ids = items.map { |item| value_or_id(item) }
 | 
					    status_ids = items.map { |item| value_or_id(item) }
 | 
				
			||||||
                      .reject { |uri| ActivityPub::TagManager.instance.local_uri?(uri) }
 | 
					                      .reject { |uri| ActivityPub::TagManager.instance.local_uri?(uri) }
 | 
				
			||||||
                      .map { |uri| ActivityPub::FetchRemoteStatusService.new.call(uri) }
 | 
					                      .filter_map { |uri| ActivityPub::FetchRemoteStatusService.new.call(uri) }
 | 
				
			||||||
                      .compact
 | 
					 | 
				
			||||||
                      .select { |status| status.account_id == @account.id }
 | 
					                      .select { |status| status.account_id == @account.id }
 | 
				
			||||||
                      .map(&:id)
 | 
					                      .map(&:id)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -37,7 +37,7 @@ class ActivityPub::ProcessCollectionService < BaseService
 | 
				
			|||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def process_items(items)
 | 
					  def process_items(items)
 | 
				
			||||||
    items.reverse_each.map { |item| process_item(item) }.compact
 | 
					    items.reverse_each.filter_map { |item| process_item(item) }
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def supported_context?
 | 
					  def supported_context?
 | 
				
			||||||
 | 
				
			|||||||
@ -30,7 +30,7 @@ class ActivityPub::ProcessPollService < BaseService
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    voters_count = @json['votersCount']
 | 
					    voters_count = @json['votersCount']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    latest_options = items.map { |item| item['name'].presence || item['content'] }.compact
 | 
					    latest_options = items.filter_map { |item| item['name'].presence || item['content'] }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # If for some reasons the options were changed, it invalidates all previous
 | 
					    # If for some reasons the options were changed, it invalidates all previous
 | 
				
			||||||
    # votes, so we need to remove them
 | 
					    # votes, so we need to remove them
 | 
				
			||||||
 | 
				
			|||||||
@ -14,7 +14,7 @@ class ActivityPub::SynchronizeFollowersService < BaseService
 | 
				
			|||||||
    # should never happen in practice, since in almost all cases we keep an
 | 
					    # should never happen in practice, since in almost all cases we keep an
 | 
				
			||||||
    # Account record, and should we not do that, we should have sent a Delete.
 | 
					    # Account record, and should we not do that, we should have sent a Delete.
 | 
				
			||||||
    # In any case there is not much we can do if that occurs.
 | 
					    # In any case there is not much we can do if that occurs.
 | 
				
			||||||
    @expected_followers = items.map { |uri| ActivityPub::TagManager.instance.uri_to_resource(uri, Account) }.compact
 | 
					    @expected_followers = items.filter_map { |uri| ActivityPub::TagManager.instance.uri_to_resource(uri, Account) }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    remove_unexpected_local_followers!
 | 
					    remove_unexpected_local_followers!
 | 
				
			||||||
    handle_unexpected_outgoing_follows!
 | 
					    handle_unexpected_outgoing_follows!
 | 
				
			||||||
 | 
				
			|||||||
@ -67,7 +67,7 @@ class FetchLinkCardService < BaseService
 | 
				
			|||||||
    else
 | 
					    else
 | 
				
			||||||
      html  = Nokogiri::HTML(@status.text)
 | 
					      html  = Nokogiri::HTML(@status.text)
 | 
				
			||||||
      links = html.css('a')
 | 
					      links = html.css('a')
 | 
				
			||||||
      urls  = links.map { |a| Addressable::URI.parse(a['href']) unless skip_link?(a) }.compact.map(&:normalize).compact
 | 
					      urls  = links.filter_map { |a| Addressable::URI.parse(a['href']) unless skip_link?(a) }.filter_map(&:normalize)
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    urls.reject { |uri| bad_url?(uri) }.first
 | 
					    urls.reject { |uri| bad_url?(uri) }.first
 | 
				
			||||||
 | 
				
			|||||||
@ -107,12 +107,12 @@ class ImportService < BaseService
 | 
				
			|||||||
      end
 | 
					      end
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    statuses = items.map do |uri|
 | 
					    statuses = items.filter_map do |uri|
 | 
				
			||||||
      status = ActivityPub::TagManager.instance.uri_to_resource(uri, Status)
 | 
					      status = ActivityPub::TagManager.instance.uri_to_resource(uri, Status)
 | 
				
			||||||
      next if status.nil? && ActivityPub::TagManager.instance.local_uri?(uri)
 | 
					      next if status.nil? && ActivityPub::TagManager.instance.local_uri?(uri)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      status || ActivityPub::FetchRemoteStatusService.new.call(uri)
 | 
					      status || ActivityPub::FetchRemoteStatusService.new.call(uri)
 | 
				
			||||||
    end.compact
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    account_ids         = statuses.map(&:account_id)
 | 
					    account_ids         = statuses.map(&:account_id)
 | 
				
			||||||
    preloaded_relations = relations_map_for_account(@account, account_ids)
 | 
					    preloaded_relations = relations_map_for_account(@account, account_ids)
 | 
				
			||||||
 | 
				
			|||||||
@ -8,11 +8,13 @@ class Keys::ClaimService < BaseService
 | 
				
			|||||||
               :key, :signature
 | 
					               :key, :signature
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def initialize(account, device_id, key_attributes = {})
 | 
					    def initialize(account, device_id, key_attributes = {})
 | 
				
			||||||
      @account   = account
 | 
					      super(
 | 
				
			||||||
      @device_id = device_id
 | 
					        account:   account,
 | 
				
			||||||
      @key_id    = key_attributes[:key_id]
 | 
					        device_id: device_id,
 | 
				
			||||||
      @key       = key_attributes[:key]
 | 
					        key_id:    key_attributes[:key_id],
 | 
				
			||||||
      @signature = key_attributes[:signature]
 | 
					        key:       key_attributes[:key],
 | 
				
			||||||
 | 
					        signature: key_attributes[:signature],
 | 
				
			||||||
 | 
					      )
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -7,8 +7,10 @@ class Keys::QueryService < BaseService
 | 
				
			|||||||
    attributes :account, :devices
 | 
					    attributes :account, :devices
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def initialize(account, devices)
 | 
					    def initialize(account, devices)
 | 
				
			||||||
      @account = account
 | 
					      super(
 | 
				
			||||||
      @devices = devices || []
 | 
					        account: account,
 | 
				
			||||||
 | 
					        devices: devices || [],
 | 
				
			||||||
 | 
					      )
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def find(device_id)
 | 
					    def find(device_id)
 | 
				
			||||||
@ -20,11 +22,13 @@ class Keys::QueryService < BaseService
 | 
				
			|||||||
    attributes :device_id, :name, :identity_key, :fingerprint_key
 | 
					    attributes :device_id, :name, :identity_key, :fingerprint_key
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def initialize(attributes = {})
 | 
					    def initialize(attributes = {})
 | 
				
			||||||
      @device_id       = attributes[:device_id]
 | 
					      super(
 | 
				
			||||||
      @name            = attributes[:name]
 | 
					        device_id:       attributes[:device_id],
 | 
				
			||||||
      @identity_key    = attributes[:identity_key]
 | 
					        name:            attributes[:name],
 | 
				
			||||||
      @fingerprint_key = attributes[:fingerprint_key]
 | 
					        identity_key:    attributes[:identity_key],
 | 
				
			||||||
      @claim_url       = attributes[:claim_url]
 | 
					        fingerprint_key: attributes[:fingerprint_key],
 | 
				
			||||||
 | 
					      )
 | 
				
			||||||
 | 
					      @claim_url = attributes[:claim_url]
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def valid_claim_url?
 | 
					    def valid_claim_url?
 | 
				
			||||||
 | 
				
			|||||||
@ -5,7 +5,7 @@ class ExistingUsernameValidator < ActiveModel::EachValidator
 | 
				
			|||||||
    return if value.blank?
 | 
					    return if value.blank?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if options[:multiple]
 | 
					    if options[:multiple]
 | 
				
			||||||
      missing_usernames = value.split(',').map { |username| username.strip.gsub(/\A@/, '') }.map { |username| username unless Account.find_local(username) }.compact
 | 
					      missing_usernames = value.split(',').map { |username| username.strip.gsub(/\A@/, '') }.filter_map { |username| username unless Account.find_local(username) }
 | 
				
			||||||
      record.errors.add(attribute, I18n.t('existing_username_validator.not_found_multiple', usernames: missing_usernames.join(', '))) if missing_usernames.any?
 | 
					      record.errors.add(attribute, I18n.t('existing_username_validator.not_found_multiple', usernames: missing_usernames.join(', '))) if missing_usernames.any?
 | 
				
			||||||
    else
 | 
					    else
 | 
				
			||||||
      record.errors.add(attribute, I18n.t('existing_username_validator.not_found')) unless Account.find_local(value.strip.gsub(/\A@/, ''))
 | 
					      record.errors.add(attribute, I18n.t('existing_username_validator.not_found')) unless Account.find_local(value.strip.gsub(/\A@/, ''))
 | 
				
			||||||
 | 
				
			|||||||
@ -7,6 +7,7 @@ require 'rails/all'
 | 
				
			|||||||
Bundler.require(*Rails.groups)
 | 
					Bundler.require(*Rails.groups)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
require_relative '../app/lib/exceptions'
 | 
					require_relative '../app/lib/exceptions'
 | 
				
			||||||
 | 
					require_relative '../lib/enumerable'
 | 
				
			||||||
require_relative '../lib/redis/namespace_extensions'
 | 
					require_relative '../lib/redis/namespace_extensions'
 | 
				
			||||||
require_relative '../lib/paperclip/url_generator_extensions'
 | 
					require_relative '../lib/paperclip/url_generator_extensions'
 | 
				
			||||||
require_relative '../lib/paperclip/attachment_extensions'
 | 
					require_relative '../lib/paperclip/attachment_extensions'
 | 
				
			||||||
 | 
				
			|||||||
@ -60,6 +60,7 @@ Devise.setup do |config|
 | 
				
			|||||||
    saml_options[:attribute_statements][:verified] = [ENV['SAML_ATTRIBUTES_STATEMENTS_VERIFIED']] if ENV['SAML_ATTRIBUTES_STATEMENTS_VERIFIED']
 | 
					    saml_options[:attribute_statements][:verified] = [ENV['SAML_ATTRIBUTES_STATEMENTS_VERIFIED']] if ENV['SAML_ATTRIBUTES_STATEMENTS_VERIFIED']
 | 
				
			||||||
    saml_options[:attribute_statements][:verified_email] = [ENV['SAML_ATTRIBUTES_STATEMENTS_VERIFIED_EMAIL']] if ENV['SAML_ATTRIBUTES_STATEMENTS_VERIFIED_EMAIL']
 | 
					    saml_options[:attribute_statements][:verified_email] = [ENV['SAML_ATTRIBUTES_STATEMENTS_VERIFIED_EMAIL']] if ENV['SAML_ATTRIBUTES_STATEMENTS_VERIFIED_EMAIL']
 | 
				
			||||||
    saml_options[:uid_attribute] = ENV['SAML_UID_ATTRIBUTE'] if ENV['SAML_UID_ATTRIBUTE']
 | 
					    saml_options[:uid_attribute] = ENV['SAML_UID_ATTRIBUTE'] if ENV['SAML_UID_ATTRIBUTE']
 | 
				
			||||||
 | 
					    saml_options[:allowed_clock_drift] = ENV['SAML_ALLOWED_CLOCK_DRIFT'] if ENV['SAML_ALLOWED_CLOCK_DRIFT']
 | 
				
			||||||
    config.omniauth :saml, saml_options
 | 
					    config.omniauth :saml, saml_options
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
				
			|||||||
@ -68,7 +68,7 @@ en:
 | 
				
			|||||||
        deleted:
 | 
					        deleted:
 | 
				
			||||||
          explanation: The following security key has been deleted from your account
 | 
					          explanation: The following security key has been deleted from your account
 | 
				
			||||||
          subject: 'Mastodon: Security key deleted'
 | 
					          subject: 'Mastodon: Security key deleted'
 | 
				
			||||||
          title: One of you security keys has been deleted
 | 
					          title: One of your security keys has been deleted
 | 
				
			||||||
      webauthn_disabled:
 | 
					      webauthn_disabled:
 | 
				
			||||||
        explanation: Authentication with security keys has been disabled for your account. Login is now possible using only the token generated by the paired TOTP app.
 | 
					        explanation: Authentication with security keys has been disabled for your account. Login is now possible using only the token generated by the paired TOTP app.
 | 
				
			||||||
        subject: 'Mastodon: Authentication with security keys disabled'
 | 
					        subject: 'Mastodon: Authentication with security keys disabled'
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										26
									
								
								lib/enumerable.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								lib/enumerable.rb
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,26 @@
 | 
				
			|||||||
 | 
					# frozen_string_literal: true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module Enumerable
 | 
				
			||||||
 | 
					  # TODO: Remove this once stop to support Ruby 2.6
 | 
				
			||||||
 | 
					  if RUBY_VERSION < '2.7.0'
 | 
				
			||||||
 | 
					    def filter_map
 | 
				
			||||||
 | 
					      if block_given?
 | 
				
			||||||
 | 
					        result = []
 | 
				
			||||||
 | 
					        each do |element|
 | 
				
			||||||
 | 
					          res = yield element
 | 
				
			||||||
 | 
					          result << res if res
 | 
				
			||||||
 | 
					        end
 | 
				
			||||||
 | 
					        result
 | 
				
			||||||
 | 
					      else
 | 
				
			||||||
 | 
					        Enumerator.new do |yielder|
 | 
				
			||||||
 | 
					          result = []
 | 
				
			||||||
 | 
					          each do |element|
 | 
				
			||||||
 | 
					            res = yielder.yield element
 | 
				
			||||||
 | 
					            result << res if res
 | 
				
			||||||
 | 
					          end
 | 
				
			||||||
 | 
					          result
 | 
				
			||||||
 | 
					        end
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
@ -160,6 +160,7 @@ module Mastodon
 | 
				
			|||||||
      deduplicate_tags!
 | 
					      deduplicate_tags!
 | 
				
			||||||
      deduplicate_webauthn_credentials!
 | 
					      deduplicate_webauthn_credentials!
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      Scenic.database.refresh_materialized_view('instances', concurrently: true, cascade: false) if ActiveRecord::Migrator.current_version >= 2020_12_06_004238
 | 
				
			||||||
      Rails.cache.clear
 | 
					      Rails.cache.clear
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      @prompt.say 'Finished!'
 | 
					      @prompt.say 'Finished!'
 | 
				
			||||||
@ -188,6 +189,11 @@ module Mastodon
 | 
				
			|||||||
      else
 | 
					      else
 | 
				
			||||||
        ActiveRecord::Base.connection.add_index :accounts, "lower (username), COALESCE(lower(domain), '')", name: 'index_accounts_on_username_and_domain_lower', unique: true
 | 
					        ActiveRecord::Base.connection.add_index :accounts, "lower (username), COALESCE(lower(domain), '')", name: 'index_accounts_on_username_and_domain_lower', unique: true
 | 
				
			||||||
      end
 | 
					      end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      @prompt.say 'Reindexing textual indexes on accounts…'
 | 
				
			||||||
 | 
					      ActiveRecord::Base.connection.execute('REINDEX INDEX search_index;')
 | 
				
			||||||
 | 
					      ActiveRecord::Base.connection.execute('REINDEX INDEX index_accounts_on_uri;')
 | 
				
			||||||
 | 
					      ActiveRecord::Base.connection.execute('REINDEX INDEX index_accounts_on_url;')
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def deduplicate_users!
 | 
					    def deduplicate_users!
 | 
				
			||||||
 | 
				
			|||||||
@ -27,7 +27,7 @@ module Paperclip
 | 
				
			|||||||
      return true  if original_filename == other_filename
 | 
					      return true  if original_filename == other_filename
 | 
				
			||||||
      return false if original_filename.nil?
 | 
					      return false if original_filename.nil?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      formats = styles.values.map(&:format).compact
 | 
					      formats = styles.values.filter_map(&:format)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      return false if formats.empty?
 | 
					      return false if formats.empty?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -142,7 +142,7 @@ module Paperclip
 | 
				
			|||||||
      g = 0.0
 | 
					      g = 0.0
 | 
				
			||||||
      b = 0.0
 | 
					      b = 0.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      if s == 0.0
 | 
					      if s.zero?
 | 
				
			||||||
        r = l.to_f
 | 
					        r = l.to_f
 | 
				
			||||||
        g = l.to_f
 | 
					        g = l.to_f
 | 
				
			||||||
        b = l.to_f # achromatic
 | 
					        b = l.to_f # achromatic
 | 
				
			||||||
 | 
				
			|||||||
@ -167,7 +167,7 @@
 | 
				
			|||||||
    "tiny-queue": "^0.2.1",
 | 
					    "tiny-queue": "^0.2.1",
 | 
				
			||||||
    "uuid": "^8.3.1",
 | 
					    "uuid": "^8.3.1",
 | 
				
			||||||
    "webpack": "^4.44.2",
 | 
					    "webpack": "^4.44.2",
 | 
				
			||||||
    "webpack-assets-manifest": "^3.1.1",
 | 
					    "webpack-assets-manifest": "^4.0.0",
 | 
				
			||||||
    "webpack-bundle-analyzer": "^4.3.0",
 | 
					    "webpack-bundle-analyzer": "^4.3.0",
 | 
				
			||||||
    "webpack-cli": "^3.3.12",
 | 
					    "webpack-cli": "^3.3.12",
 | 
				
			||||||
    "webpack-merge": "^5.7.3",
 | 
					    "webpack-merge": "^5.7.3",
 | 
				
			||||||
 | 
				
			|||||||
@ -268,6 +268,34 @@ RSpec.describe Api::V1::AccountsController, type: :controller do
 | 
				
			|||||||
    it_behaves_like 'forbidden for wrong scope', 'read:accounts'
 | 
					    it_behaves_like 'forbidden for wrong scope', 'read:accounts'
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  describe 'POST #mute with nonzero duration set' do
 | 
				
			||||||
 | 
					    let(:scopes) { 'write:mutes' }
 | 
				
			||||||
 | 
					    let(:other_account) { Fabricate(:user, email: 'bob@example.com', account: Fabricate(:account, username: 'bob')).account }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    before do
 | 
				
			||||||
 | 
					      user.account.follow!(other_account)
 | 
				
			||||||
 | 
					      post :mute, params: { id: other_account.id, duration: 300 }
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    it 'returns http success' do
 | 
				
			||||||
 | 
					      expect(response).to have_http_status(200)
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    it 'does not remove the following relation between user and target user' do
 | 
				
			||||||
 | 
					      expect(user.account.following?(other_account)).to be true
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    it 'creates a muting relation' do
 | 
				
			||||||
 | 
					      expect(user.account.muting?(other_account)).to be true
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    it 'mutes notifications' do
 | 
				
			||||||
 | 
					      expect(user.account.muting_notifications?(other_account)).to be true
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    it_behaves_like 'forbidden for wrong scope', 'read:accounts'
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  describe 'POST #unmute' do
 | 
					  describe 'POST #unmute' do
 | 
				
			||||||
    let(:scopes) { 'write:mutes' }
 | 
					    let(:scopes) { 'write:mutes' }
 | 
				
			||||||
    let(:other_account) { Fabricate(:user, email: 'bob@example.com', account: Fabricate(:account, username: 'bob')).account }
 | 
					    let(:other_account) { Fabricate(:user, email: 'bob@example.com', account: Fabricate(:account, username: 'bob')).account }
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										47
									
								
								yarn.lock
									
									
									
									
									
								
							
							
						
						
									
										47
									
								
								yarn.lock
									
									
									
									
									
								
							@ -2798,7 +2798,7 @@ chalk@^1.0.0, chalk@^1.1.1, chalk@^1.1.3:
 | 
				
			|||||||
    strip-ansi "^3.0.0"
 | 
					    strip-ansi "^3.0.0"
 | 
				
			||||||
    supports-color "^2.0.0"
 | 
					    supports-color "^2.0.0"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
chalk@^2.0, chalk@^2.0.0, chalk@^2.3.2, chalk@^2.4.1, chalk@^2.4.2:
 | 
					chalk@^2.0.0, chalk@^2.3.2, chalk@^2.4.1, chalk@^2.4.2:
 | 
				
			||||||
  version "2.4.2"
 | 
					  version "2.4.2"
 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
 | 
					  resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
 | 
				
			||||||
  integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
 | 
					  integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
 | 
				
			||||||
@ -2815,7 +2815,7 @@ chalk@^3.0.0:
 | 
				
			|||||||
    ansi-styles "^4.1.0"
 | 
					    ansi-styles "^4.1.0"
 | 
				
			||||||
    supports-color "^7.1.0"
 | 
					    supports-color "^7.1.0"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
chalk@^4.0.0, chalk@^4.1.0:
 | 
					chalk@^4.0, chalk@^4.0.0, chalk@^4.1.0:
 | 
				
			||||||
  version "4.1.0"
 | 
					  version "4.1.0"
 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.0.tgz#4e14870a618d9e2edd97dd8345fd9d9dc315646a"
 | 
					  resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.0.tgz#4e14870a618d9e2edd97dd8345fd9d9dc315646a"
 | 
				
			||||||
  integrity sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==
 | 
					  integrity sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==
 | 
				
			||||||
@ -6831,6 +6831,13 @@ locate-path@^5.0.0:
 | 
				
			|||||||
  dependencies:
 | 
					  dependencies:
 | 
				
			||||||
    p-locate "^4.1.0"
 | 
					    p-locate "^4.1.0"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					lockfile@^1.0.4:
 | 
				
			||||||
 | 
					  version "1.0.4"
 | 
				
			||||||
 | 
					  resolved "https://registry.yarnpkg.com/lockfile/-/lockfile-1.0.4.tgz#07f819d25ae48f87e538e6578b6964a4981a5609"
 | 
				
			||||||
 | 
					  integrity sha512-cvbTwETRfsFh4nHsL1eGWapU1XFi5Ot9E85sWAwia7Y7EgB7vfqcZhTKZ+l7hCGxSPoushMv5GKhT5PdLv03WA==
 | 
				
			||||||
 | 
					  dependencies:
 | 
				
			||||||
 | 
					    signal-exit "^3.0.2"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
lodash.capitalize@^4.1.0:
 | 
					lodash.capitalize@^4.1.0:
 | 
				
			||||||
  version "4.2.1"
 | 
					  version "4.2.1"
 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/lodash.capitalize/-/lodash.capitalize-4.2.1.tgz#f826c9b4e2a8511d84e3aca29db05e1a4f3b72a9"
 | 
					  resolved "https://registry.yarnpkg.com/lodash.capitalize/-/lodash.capitalize-4.2.1.tgz#f826c9b4e2a8511d84e3aca29db05e1a4f3b72a9"
 | 
				
			||||||
@ -6841,6 +6848,11 @@ lodash.defaults@^4.0.1:
 | 
				
			|||||||
  resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c"
 | 
					  resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c"
 | 
				
			||||||
  integrity sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=
 | 
					  integrity sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					lodash.escaperegexp@^4.0:
 | 
				
			||||||
 | 
					  version "4.1.2"
 | 
				
			||||||
 | 
					  resolved "https://registry.yarnpkg.com/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz#64762c48618082518ac3df4ccf5d5886dae20347"
 | 
				
			||||||
 | 
					  integrity sha1-ZHYsSGGAglGKw99Mz11YhtriA0c=
 | 
				
			||||||
 | 
					
 | 
				
			||||||
lodash.get@^4.0:
 | 
					lodash.get@^4.0:
 | 
				
			||||||
  version "4.4.2"
 | 
					  version "4.4.2"
 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99"
 | 
					  resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99"
 | 
				
			||||||
@ -7199,14 +7211,14 @@ mixin-deep@^1.2.0:
 | 
				
			|||||||
    for-in "^1.0.2"
 | 
					    for-in "^1.0.2"
 | 
				
			||||||
    is-extendable "^1.0.1"
 | 
					    is-extendable "^1.0.1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
mkdirp@^0.5, mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@^0.5.3, mkdirp@^0.5.5, mkdirp@~0.5.1:
 | 
					mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@^0.5.3, mkdirp@^0.5.5, mkdirp@~0.5.1:
 | 
				
			||||||
  version "0.5.5"
 | 
					  version "0.5.5"
 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def"
 | 
					  resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def"
 | 
				
			||||||
  integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==
 | 
					  integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==
 | 
				
			||||||
  dependencies:
 | 
					  dependencies:
 | 
				
			||||||
    minimist "^1.2.5"
 | 
					    minimist "^1.2.5"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
mkdirp@^1.0.3, mkdirp@^1.0.4:
 | 
					mkdirp@^1.0, mkdirp@^1.0.3, mkdirp@^1.0.4:
 | 
				
			||||||
  version "1.0.4"
 | 
					  version "1.0.4"
 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e"
 | 
					  resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e"
 | 
				
			||||||
  integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==
 | 
					  integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==
 | 
				
			||||||
@ -9561,7 +9573,7 @@ schema-utils@^2.2.0, schema-utils@^2.6.5:
 | 
				
			|||||||
    ajv "^6.12.4"
 | 
					    ajv "^6.12.4"
 | 
				
			||||||
    ajv-keywords "^3.5.2"
 | 
					    ajv-keywords "^3.5.2"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
schema-utils@^3.0.0:
 | 
					schema-utils@^3.0, schema-utils@^3.0.0:
 | 
				
			||||||
  version "3.0.0"
 | 
					  version "3.0.0"
 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.0.0.tgz#67502f6aa2b66a2d4032b4279a2944978a0913ef"
 | 
					  resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.0.0.tgz#67502f6aa2b66a2d4032b4279a2944978a0913ef"
 | 
				
			||||||
  integrity sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA==
 | 
					  integrity sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA==
 | 
				
			||||||
@ -10377,7 +10389,7 @@ table@^6.0.4:
 | 
				
			|||||||
    slice-ansi "^4.0.0"
 | 
					    slice-ansi "^4.0.0"
 | 
				
			||||||
    string-width "^4.2.0"
 | 
					    string-width "^4.2.0"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
tapable@^1.0.0, tapable@^1.1.3:
 | 
					tapable@^1.0, tapable@^1.0.0, tapable@^1.1.3:
 | 
				
			||||||
  version "1.1.3"
 | 
					  version "1.1.3"
 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2"
 | 
					  resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2"
 | 
				
			||||||
  integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==
 | 
					  integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==
 | 
				
			||||||
@ -11051,18 +11063,21 @@ webidl-conversions@^6.1.0:
 | 
				
			|||||||
  resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-6.1.0.tgz#9111b4d7ea80acd40f5270d666621afa78b69514"
 | 
					  resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-6.1.0.tgz#9111b4d7ea80acd40f5270d666621afa78b69514"
 | 
				
			||||||
  integrity sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==
 | 
					  integrity sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==
 | 
				
			||||||
 | 
					
 | 
				
			||||||
webpack-assets-manifest@^3.1.1:
 | 
					webpack-assets-manifest@^4.0.0:
 | 
				
			||||||
  version "3.1.1"
 | 
					  version "4.0.0"
 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/webpack-assets-manifest/-/webpack-assets-manifest-3.1.1.tgz#39bbc3bf2ee57fcd8ba07cda51c9ba4a3c6ae1de"
 | 
					  resolved "https://registry.yarnpkg.com/webpack-assets-manifest/-/webpack-assets-manifest-4.0.0.tgz#6c906f6a77945aa326822e158f22d172ccc59f0f"
 | 
				
			||||||
  integrity sha512-JV9V2QKc5wEWQptdIjvXDUL1ucbPLH2f27toAY3SNdGZp+xSaStAgpoMcvMZmqtFrBc9a5pTS1058vxyMPOzRQ==
 | 
					  integrity sha512-zbozd1Cr6gS5XMWWHfISusocOO2bO05ktpJXWdoYtv12/FSXsNqyVjNwLE9ehBXDsEOwRtqd3kPDdTZKFjjD/w==
 | 
				
			||||||
  dependencies:
 | 
					  dependencies:
 | 
				
			||||||
    chalk "^2.0"
 | 
					    chalk "^4.0"
 | 
				
			||||||
 | 
					    deepmerge "^4.2.2"
 | 
				
			||||||
 | 
					    lockfile "^1.0.4"
 | 
				
			||||||
 | 
					    lodash.escaperegexp "^4.0"
 | 
				
			||||||
    lodash.get "^4.0"
 | 
					    lodash.get "^4.0"
 | 
				
			||||||
    lodash.has "^4.0"
 | 
					    lodash.has "^4.0"
 | 
				
			||||||
    mkdirp "^0.5"
 | 
					    mkdirp "^1.0"
 | 
				
			||||||
    schema-utils "^1.0.0"
 | 
					    schema-utils "^3.0"
 | 
				
			||||||
    tapable "^1.0.0"
 | 
					    tapable "^1.0"
 | 
				
			||||||
    webpack-sources "^1.0.0"
 | 
					    webpack-sources "^1.0"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
webpack-bundle-analyzer@^4.3.0:
 | 
					webpack-bundle-analyzer@^4.3.0:
 | 
				
			||||||
  version "4.3.0"
 | 
					  version "4.3.0"
 | 
				
			||||||
@ -11162,7 +11177,7 @@ webpack-merge@^5.7.3:
 | 
				
			|||||||
    clone-deep "^4.0.1"
 | 
					    clone-deep "^4.0.1"
 | 
				
			||||||
    wildcard "^2.0.0"
 | 
					    wildcard "^2.0.0"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
webpack-sources@^1.0.0, webpack-sources@^1.1.0, webpack-sources@^1.4.0, webpack-sources@^1.4.1, webpack-sources@^1.4.3:
 | 
					webpack-sources@^1.0, webpack-sources@^1.1.0, webpack-sources@^1.4.0, webpack-sources@^1.4.1, webpack-sources@^1.4.3:
 | 
				
			||||||
  version "1.4.3"
 | 
					  version "1.4.3"
 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.4.3.tgz#eedd8ec0b928fbf1cbfe994e22d2d890f330a933"
 | 
					  resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.4.3.tgz#eedd8ec0b928fbf1cbfe994e22d2d890f330a933"
 | 
				
			||||||
  integrity sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==
 | 
					  integrity sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user