diff --git a/Gemfile b/Gemfile index 6a683d586..7b1084d9d 100644 --- a/Gemfile +++ b/Gemfile @@ -5,10 +5,10 @@ ruby '>= 2.5.0', '< 3.0.0' gem 'pkg-config', '~> 1.4' -gem 'puma', '~> 4.3' -gem 'rails', '~> 5.2.4.3' +gem 'puma', '~> 5.0' +gem 'rails', '~> 5.2.4.4' gem 'sprockets', '~> 3.7.2' -gem 'thor', '~> 0.20' +gem 'thor', '~> 1.0' gem 'rack', '~> 2.2.3' gem 'thwait', '~> 0.2.0' @@ -20,7 +20,7 @@ gem 'makara', '~> 0.4' gem 'pghero', '~> 2.7' gem 'dotenv-rails', '~> 2.7' -gem 'aws-sdk-s3', '~> 1.79', require: false +gem 'aws-sdk-s3', '~> 1.81', require: false gem 'fog-core', '<= 2.1.0' gem 'fog-openstack', '~> 0.3', require: false gem 'paperclip', '~> 6.0' @@ -121,27 +121,27 @@ end group :test do gem 'capybara', '~> 3.33' gem 'climate_control', '~> 0.2' - gem 'faker', '~> 2.13' + gem 'faker', '~> 2.14' gem 'microformats', '~> 4.2' gem 'rails-controller-testing', '~> 1.0' gem 'rspec-sidekiq', '~> 3.1' gem 'simplecov', '~> 0.19', require: false - gem 'webmock', '~> 3.8' - gem 'parallel_tests', '~> 3.2' + gem 'webmock', '~> 3.9' + gem 'parallel_tests', '~> 3.3' gem 'rspec_junit_formatter', '~> 0.4' end group :development do gem 'active_record_query_trace', '~> 1.7' gem 'annotate', '~> 3.1' - gem 'better_errors', '~> 2.7' + gem 'better_errors', '~> 2.8' gem 'binding_of_caller', '~> 0.7' gem 'bullet', '~> 6.1' gem 'letter_opener', '~> 1.7' gem 'letter_opener_web', '~> 1.4' gem 'memory_profiler' - gem 'rubocop', '~> 0.88', require: false - gem 'rubocop-rails', '~> 2.6', require: false + gem 'rubocop', '~> 0.91', require: false + gem 'rubocop-rails', '~> 2.8', require: false gem 'brakeman', '~> 4.9', require: false gem 'bundler-audit', '~> 0.7', require: false diff --git a/Gemfile.lock b/Gemfile.lock index 1e289c30a..cdbb310c4 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -16,25 +16,25 @@ GIT GEM remote: https://rubygems.org/ specs: - actioncable (5.2.4.3) - actionpack (= 5.2.4.3) + actioncable (5.2.4.4) + actionpack (= 5.2.4.4) nio4r (~> 2.0) websocket-driver (>= 0.6.1) - actionmailer (5.2.4.3) - actionpack (= 5.2.4.3) - actionview (= 5.2.4.3) - activejob (= 5.2.4.3) + actionmailer (5.2.4.4) + actionpack (= 5.2.4.4) + actionview (= 5.2.4.4) + activejob (= 5.2.4.4) mail (~> 2.5, >= 2.5.4) rails-dom-testing (~> 2.0) - actionpack (5.2.4.3) - actionview (= 5.2.4.3) - activesupport (= 5.2.4.3) + actionpack (5.2.4.4) + actionview (= 5.2.4.4) + activesupport (= 5.2.4.4) rack (~> 2.0, >= 2.0.8) rack-test (>= 0.6.3) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.0.2) - actionview (5.2.4.3) - activesupport (= 5.2.4.3) + actionview (5.2.4.4) + activesupport (= 5.2.4.4) builder (~> 3.1) erubi (~> 1.4) rails-dom-testing (~> 2.0) @@ -45,20 +45,20 @@ GEM case_transform (>= 0.2) jsonapi-renderer (>= 0.1.1.beta1, < 0.3) active_record_query_trace (1.7) - activejob (5.2.4.3) - activesupport (= 5.2.4.3) + activejob (5.2.4.4) + activesupport (= 5.2.4.4) globalid (>= 0.3.6) - activemodel (5.2.4.3) - activesupport (= 5.2.4.3) - activerecord (5.2.4.3) - activemodel (= 5.2.4.3) - activesupport (= 5.2.4.3) + activemodel (5.2.4.4) + activesupport (= 5.2.4.4) + activerecord (5.2.4.4) + activemodel (= 5.2.4.4) + activesupport (= 5.2.4.4) arel (>= 9.0) - activestorage (5.2.4.3) - actionpack (= 5.2.4.3) - activerecord (= 5.2.4.3) + activestorage (5.2.4.4) + actionpack (= 5.2.4.4) + activerecord (= 5.2.4.4) marcel (~> 0.3.1) - activesupport (5.2.4.3) + activesupport (5.2.4.4) concurrent-ruby (~> 1.0, >= 1.0.2) i18n (>= 0.7, < 2) minitest (~> 5.1) @@ -79,23 +79,23 @@ GEM cocaine (~> 0.5.3) awrence (1.1.1) aws-eventstream (1.1.0) - aws-partitions (1.363.0) - aws-sdk-core (3.105.0) + aws-partitions (1.373.0) + aws-sdk-core (3.107.0) aws-eventstream (~> 1, >= 1.0.2) aws-partitions (~> 1, >= 1.239.0) aws-sigv4 (~> 1.1) jmespath (~> 1.0) - aws-sdk-kms (1.37.0) + aws-sdk-kms (1.38.0) aws-sdk-core (~> 3, >= 3.99.0) aws-sigv4 (~> 1.1) - aws-sdk-s3 (1.79.1) + aws-sdk-s3 (1.81.0) aws-sdk-core (~> 3, >= 3.104.3) aws-sdk-kms (~> 1) aws-sigv4 (~> 1.1) aws-sigv4 (1.2.2) aws-eventstream (~> 1, >= 1.0.2) - bcrypt (3.1.15) - better_errors (2.7.1) + bcrypt (3.1.16) + better_errors (2.8.1) coderay (>= 1.0.0) erubi (>= 1.0.0) rack (>= 0.9.0) @@ -106,7 +106,7 @@ GEM ffi (~> 1.10.0) bootsnap (1.4.8) msgpack (~> 1.0) - brakeman (4.9.0) + brakeman (4.9.1) browser (4.2.0) builder (3.2.4) bullet (6.1.0) @@ -160,13 +160,12 @@ GEM cose (1.0.0) cbor (~> 0.5.9) openssl-signature_algorithm (~> 0.4.0) - crack (0.4.3) - safe_yaml (~> 1.0.0) + crack (0.4.4) crass (1.0.6) css_parser (1.7.1) addressable debug_inspector (0.0.3) - devise (4.7.2) + devise (4.7.3) bcrypt (~> 3.0) orm_adapter (~> 0.1) railties (>= 4.1.0) @@ -210,7 +209,7 @@ GEM tzinfo excon (0.76.0) fabrication (2.21.1) - faker (2.13.0) + faker (2.14.0) i18n (>= 1.6, < 2) faraday (1.0.1) multipart-post (>= 1.2, < 3) @@ -233,7 +232,7 @@ GEM fog-json (>= 1.0) ipaddress (>= 0.8) formatador (0.2.5) - fugit (1.3.8) + fugit (1.3.9) et-orbi (~> 1.1, >= 1.1.8) raabro (~> 1.3) fuubar (2.5.0) @@ -355,7 +354,7 @@ GEM mimemagic (0.3.5) mini_mime (1.0.2) mini_portile2 (2.4.0) - minitest (5.14.1) + minitest (5.14.2) msgpack (1.3.3) multi_json (1.15.0) multipart-post (2.1.1) @@ -363,7 +362,7 @@ GEM net-scp (3.0.0) net-ssh (>= 2.6.5, < 7.0.0) net-ssh (6.1.0) - nio4r (2.5.2) + nio4r (2.5.4) nokogiri (1.10.10) mini_portile2 (~> 2.4.0) nokogumbo (2.0.2) @@ -373,7 +372,7 @@ GEM concurrent-ruby (~> 1.0, >= 1.0.2) sidekiq (>= 3.5) statsd-ruby (~> 1.4, >= 1.4.0) - oj (3.10.13) + oj (3.10.14) omniauth (1.9.1) hashie (>= 3.4.6) rack (>= 1.6.2, < 3) @@ -387,7 +386,7 @@ GEM openssl (2.2.0) openssl-signature_algorithm (0.4.0) orm_adapter (0.5.0) - ox (2.13.2) + ox (2.13.4) paperclip (6.0.0) activemodel (>= 4.2.0) activesupport (>= 4.2.0) @@ -398,7 +397,7 @@ GEM av (~> 0.9.0) paperclip (>= 2.5.2) parallel (1.19.2) - parallel_tests (3.2.0) + parallel_tests (3.3.0) parallel parser (2.7.1.4) ast (~> 2.4.1) @@ -406,11 +405,11 @@ GEM pastel (0.8.0) tty-color (~> 0.5) pg (1.2.3) - pghero (2.7.0) + pghero (2.7.2) activerecord (>= 5) - pkg-config (1.4.2) + pkg-config (1.4.3) posix-spawn (0.3.15) - premailer (1.13.1) + premailer (1.14.2) addressable css_parser (>= 1.6.0) htmlentities (>= 4.0.0) @@ -426,8 +425,8 @@ GEM pry (~> 0.13.0) pry-rails (0.3.9) pry (>= 0.10.4) - public_suffix (4.0.5) - puma (4.3.5) + public_suffix (4.0.6) + puma (5.0.0) nio4r (~> 2.0) pundit (2.1.0) activesupport (>= 3.0.0) @@ -441,18 +440,18 @@ GEM rack rack-test (1.1.0) rack (>= 1.0, < 3) - rails (5.2.4.3) - actioncable (= 5.2.4.3) - actionmailer (= 5.2.4.3) - actionpack (= 5.2.4.3) - actionview (= 5.2.4.3) - activejob (= 5.2.4.3) - activemodel (= 5.2.4.3) - activerecord (= 5.2.4.3) - activestorage (= 5.2.4.3) - activesupport (= 5.2.4.3) + rails (5.2.4.4) + actioncable (= 5.2.4.4) + actionmailer (= 5.2.4.4) + actionpack (= 5.2.4.4) + actionview (= 5.2.4.4) + activejob (= 5.2.4.4) + activemodel (= 5.2.4.4) + activerecord (= 5.2.4.4) + activestorage (= 5.2.4.4) + activesupport (= 5.2.4.4) bundler (>= 1.3.0) - railties (= 5.2.4.3) + railties (= 5.2.4.4) sprockets-rails (>= 2.0.0) rails-controller-testing (1.0.5) actionpack (>= 5.0.1.rc1) @@ -468,20 +467,20 @@ GEM railties (>= 5.0, < 6) rails-settings-cached (0.6.6) rails (>= 4.2.0) - railties (5.2.4.3) - actionpack (= 5.2.4.3) - activesupport (= 5.2.4.3) + railties (5.2.4.4) + actionpack (= 5.2.4.4) + activesupport (= 5.2.4.4) method_source rake (>= 0.8.7) thor (>= 0.19.0, < 2.0) rainbow (3.0.0) rake (13.0.1) - rdf (3.1.5) + rdf (3.1.6) hamster (~> 3.0) link_header (~> 0.0, >= 0.0.8) rdf-normalize (0.4.0) rdf (~> 3.1) - redis (4.2.1) + redis (4.2.2) redis-actionpack (5.2.0) actionpack (>= 5, < 7) redis-rack (>= 2.1.0, < 3) @@ -500,7 +499,7 @@ GEM redis-store (>= 1.2, < 2) redis-store (1.9.0) redis (>= 4, < 5) - regexp_parser (1.7.1) + regexp_parser (1.8.0) request_store (1.5.0) rack (>= 1.4) responders (3.0.1) @@ -535,27 +534,26 @@ GEM rspec-support (3.9.3) rspec_junit_formatter (0.4.1) rspec-core (>= 2, < 4, != 2.12.0) - rubocop (0.88.0) + rubocop (0.91.0) parallel (~> 1.10) parser (>= 2.7.1.1) rainbow (>= 2.2.2, < 4.0) regexp_parser (>= 1.7) rexml - rubocop-ast (>= 0.1.0, < 1.0) + rubocop-ast (>= 0.4.0, < 1.0) ruby-progressbar (~> 1.7) unicode-display_width (>= 1.4.0, < 2.0) - rubocop-ast (0.3.0) + rubocop-ast (0.4.2) parser (>= 2.7.1.4) - rubocop-rails (2.6.0) + rubocop-rails (2.8.1) activesupport (>= 4.2.0) rack (>= 1.1) - rubocop (>= 0.82.0) + rubocop (>= 0.87.0) ruby-progressbar (1.10.1) ruby-saml (1.11.0) nokogiri (>= 1.5.10) rufus-scheduler (3.6.0) fugit (~> 1.1, >= 1.1.6) - safe_yaml (1.0.5) safety_net_attestation (0.4.0) jwt (~> 2.0) sanitize (5.2.1) @@ -564,7 +562,7 @@ GEM nokogumbo (~> 2.0) securecompare (1.0.0) semantic_range (2.3.0) - sidekiq (6.1.1) + sidekiq (6.1.2) connection_pool (>= 2.2.2) rack (~> 2.0) redis (>= 4.2.0) @@ -577,10 +575,10 @@ GEM sidekiq (>= 3) thwait tilt (>= 1.4.0) - sidekiq-unique-jobs (6.0.22) + sidekiq-unique-jobs (6.0.23) concurrent-ruby (~> 1.0, >= 1.0.5) sidekiq (>= 4.0, < 7.0) - thor (~> 0) + thor (>= 0.20, < 2.0) simple-navigation (4.1.0) activesupport (>= 2.3.2) simple_form (5.0.2) @@ -593,7 +591,7 @@ GEM sprockets (3.7.2) concurrent-ruby (~> 1.0) rack (> 1, < 3) - sprockets-rails (3.2.1) + sprockets-rails (3.2.2) actionpack (>= 4.0) activesupport (>= 4.0) sprockets (>= 3.0.0) @@ -612,7 +610,7 @@ GEM unicode-display_width (~> 1.1, >= 1.1.1) terrapin (0.6.0) climate_control (>= 0.0.3, < 1.0) - thor (0.20.3) + thor (1.0.1) thread_safe (0.3.6) thwait (0.2.0) e2mmap @@ -641,8 +639,8 @@ GEM unf_ext (0.0.7.7) unicode-display_width (1.7.0) uniform_notifier (1.13.0) - warden (1.2.8) - rack (>= 2.0.6) + warden (1.2.9) + rack (>= 2.0.9) webauthn (3.0.0.alpha1) android_key_attestation (~> 0.3.0) awrence (~> 1.1) @@ -653,7 +651,7 @@ GEM safety_net_attestation (~> 0.4.0) securecompare (~> 1.0) tpm-key_attestation (~> 0.9.0) - webmock (3.8.3) + webmock (3.9.1) addressable (>= 2.3.6) crack (>= 0.3.2) hashdiff (>= 0.4.0, < 2.0.0) @@ -680,8 +678,8 @@ DEPENDENCIES active_record_query_trace (~> 1.7) addressable (~> 2.7) annotate (~> 3.1) - aws-sdk-s3 (~> 1.79) - better_errors (~> 2.7) + aws-sdk-s3 (~> 1.81) + better_errors (~> 2.8) binding_of_caller (~> 0.7) blurhash (~> 0.1) bootsnap (~> 1.4) @@ -710,7 +708,7 @@ DEPENDENCIES e2mmap (~> 0.1.0) ed25519 (~> 1.2) fabrication (~> 2.21) - faker (~> 2.13) + faker (~> 2.14) fast_blank (~> 1.0) fastimage fog-core (<= 2.1.0) @@ -751,7 +749,7 @@ DEPENDENCIES paperclip (~> 6.0) paperclip-av-transcoder (~> 0.6) parallel (~> 1.19) - parallel_tests (~> 3.2) + parallel_tests (~> 3.3) parslet pg (~> 1.2) pghero (~> 2.7) @@ -761,12 +759,12 @@ DEPENDENCIES private_address_check (~> 0.5) pry-byebug (~> 3.9) pry-rails (~> 0.3) - puma (~> 4.3) + puma (~> 5.0) pundit (~> 2.1) rack (~> 2.2.3) rack-attack (~> 6.3) rack-cors (~> 1.1) - rails (~> 5.2.4.3) + rails (~> 5.2.4.4) rails-controller-testing (~> 1.0) rails-i18n (~> 5.1) rails-settings-cached (~> 0.6) @@ -778,8 +776,8 @@ DEPENDENCIES rspec-rails (~> 4.0) rspec-sidekiq (~> 3.1) rspec_junit_formatter (~> 0.4) - rubocop (~> 0.88) - rubocop-rails (~> 2.6) + rubocop (~> 0.91) + rubocop-rails (~> 2.8) ruby-progressbar (~> 1.10) sanitize (~> 5.2) sidekiq (~> 6.1) @@ -795,12 +793,12 @@ DEPENDENCIES stoplight (~> 2.2.1) streamio-ffmpeg (~> 3.0) strong_migrations (~> 0.7) - thor (~> 0.20) + thor (~> 1.0) thwait (~> 0.2.0) tty-prompt (~> 0.22) twitter-text (~> 1.14) tzinfo-data (~> 1.2020) webauthn (~> 3.0.0.alpha1) - webmock (~> 3.8) + webmock (~> 3.9) webpacker (~> 5.2) webpush diff --git a/app/controllers/accounts_controller.rb b/app/controllers/accounts_controller.rb index d97d88fd9..6d711afd0 100644 --- a/app/controllers/accounts_controller.rb +++ b/app/controllers/accounts_controller.rb @@ -7,6 +7,7 @@ class AccountsController < ApplicationController include AccountControllerConcern include SignatureAuthentication + before_action :require_signature!, if: -> { request.format == :json && authorized_fetch_mode? } before_action :set_cache_headers before_action :set_body_classes @@ -48,7 +49,7 @@ class AccountsController < ApplicationController format.json do expires_in 3.minutes, public: !(authorized_fetch_mode? && signed_request_account.present?) - render_with_cache json: @account, content_type: 'application/activity+json', serializer: ActivityPub::ActorSerializer, adapter: ActivityPub::Adapter, fields: restrict_fields_to + render_with_cache json: @account, content_type: 'application/activity+json', serializer: ActivityPub::ActorSerializer, adapter: ActivityPub::Adapter end end end @@ -153,12 +154,4 @@ class AccountsController < ApplicationController def params_slice(*keys) params.slice(*keys).permit(*keys) end - - def restrict_fields_to - if signed_request_account.present? || public_fetch_mode? - # Return all fields - else - %i(id type preferred_username inbox public_key endpoints) - end - end end diff --git a/app/controllers/activitypub/outboxes_controller.rb b/app/controllers/activitypub/outboxes_controller.rb index e066860bf..5fd735ad6 100644 --- a/app/controllers/activitypub/outboxes_controller.rb +++ b/app/controllers/activitypub/outboxes_controller.rb @@ -57,9 +57,8 @@ class ActivityPub::OutboxesController < ActivityPub::BaseController def set_statuses return unless page_requested? - @statuses = @account.statuses.permitted_for(@account, signed_request_account) @statuses = cache_collection_paginated_by_id( - @statuses, + @account.statuses.permitted_for(@account, signed_request_account), Status, LIMIT, params_slice(:max_id, :min_id, :since_id) diff --git a/app/controllers/admin/accounts_controller.rb b/app/controllers/admin/accounts_controller.rb index 7b1783542..b9b75727d 100644 --- a/app/controllers/admin/accounts_controller.rb +++ b/app/controllers/admin/accounts_controller.rb @@ -2,7 +2,7 @@ module Admin class AccountsController < BaseController - before_action :set_account, only: [:show, :redownload, :remove_avatar, :remove_header, :enable, :unsilence, :unsuspend, :memorialize, :approve, :reject] + before_action :set_account, except: [:index] before_action :require_remote_account!, only: [:redownload] before_action :require_local_account!, only: [:enable, :memorialize, :approve, :reject] @@ -14,49 +14,58 @@ module Admin def show authorize @account, :show? + @deletion_request = @account.deletion_request @account_moderation_note = current_account.account_moderation_notes.new(target_account: @account) @moderation_notes = @account.targeted_moderation_notes.latest @warnings = @account.targeted_account_warnings.latest.custom + @domain_block = DomainBlock.rule_for(@account.domain) end def memorialize authorize @account, :memorialize? @account.memorialize! log_action :memorialize, @account - redirect_to admin_account_path(@account.id) + redirect_to admin_account_path(@account.id), notice: I18n.t('admin.accounts.memorialized_msg', username: @account.acct) end def enable authorize @account.user, :enable? @account.user.enable! log_action :enable, @account.user - redirect_to admin_account_path(@account.id) + redirect_to admin_account_path(@account.id), notice: I18n.t('admin.accounts.enabled_msg', username: @account.acct) end def approve authorize @account.user, :approve? @account.user.approve! - redirect_to admin_pending_accounts_path + redirect_to admin_pending_accounts_path, notice: I18n.t('admin.accounts.approved_msg', username: @account.acct) end def reject authorize @account.user, :reject? - SuspendAccountService.new.call(@account, reserve_email: false, reserve_username: false) - redirect_to admin_pending_accounts_path + DeleteAccountService.new.call(@account, reserve_email: false, reserve_username: false) + redirect_to admin_pending_accounts_path, notice: I18n.t('admin.accounts.rejected_msg', username: @account.acct) + end + + def destroy + authorize @account, :destroy? + Admin::AccountDeletionWorker.perform_async(@account.id) + redirect_to admin_account_path(@account.id), notice: I18n.t('admin.accounts.destroyed_msg', username: @account.acct) end def unsilence authorize @account, :unsilence? @account.unsilence! log_action :unsilence, @account - redirect_to admin_account_path(@account.id) + redirect_to admin_account_path(@account.id), notice: I18n.t('admin.accounts.unsilenced_msg', username: @account.acct) end def unsuspend authorize @account, :unsuspend? @account.unsuspend! + Admin::UnsuspensionWorker.perform_async(@account.id) log_action :unsuspend, @account - redirect_to admin_account_path(@account.id) + redirect_to admin_account_path(@account.id), notice: I18n.t('admin.accounts.unsuspended_msg', username: @account.acct) end def redownload @@ -65,7 +74,7 @@ module Admin @account.update!(last_webfingered_at: nil) ResolveAccountService.new.call(@account) - redirect_to admin_account_path(@account.id) + redirect_to admin_account_path(@account.id), notice: I18n.t('admin.accounts.redownloaded_msg', username: @account.acct) end def remove_avatar @@ -76,7 +85,7 @@ module Admin log_action :remove_avatar, @account.user - redirect_to admin_account_path(@account.id) + redirect_to admin_account_path(@account.id), notice: I18n.t('admin.accounts.removed_avatar_msg', username: @account.acct) end def remove_header @@ -87,7 +96,7 @@ module Admin log_action :remove_header, @account.user - redirect_to admin_account_path(@account.id) + redirect_to admin_account_path(@account.id), notice: I18n.t('admin.accounts.removed_header_msg', username: @account.acct) end private diff --git a/app/controllers/api/base_controller.rb b/app/controllers/api/base_controller.rb index 467225547..e962c4e97 100644 --- a/app/controllers/api/base_controller.rb +++ b/app/controllers/api/base_controller.rb @@ -96,12 +96,12 @@ class Api::BaseController < ApplicationController def require_user! if !current_user render json: { error: 'This method requires an authenticated user' }, status: 422 - elsif current_user.disabled? - render json: { error: 'Your login is currently disabled' }, status: 403 elsif !current_user.confirmed? render json: { error: 'Your login is missing a confirmed e-mail address' }, status: 403 elsif !current_user.approved? render json: { error: 'Your login is currently pending approval' }, status: 403 + elsif !current_user.functional? + render json: { error: 'Your login is currently disabled' }, status: 403 else set_user_activity end diff --git a/app/controllers/api/v1/accounts/featured_tags_controller.rb b/app/controllers/api/v1/accounts/featured_tags_controller.rb index d6277261d..014d71956 100644 --- a/app/controllers/api/v1/accounts/featured_tags_controller.rb +++ b/app/controllers/api/v1/accounts/featured_tags_controller.rb @@ -17,6 +17,6 @@ class Api::V1::Accounts::FeaturedTagsController < Api::BaseController end def set_featured_tags - @featured_tags = @account.featured_tags + @featured_tags = @account.suspended? ? @account.featured_tags : [] end end diff --git a/app/controllers/api/v1/accounts/follower_accounts_controller.rb b/app/controllers/api/v1/accounts/follower_accounts_controller.rb index 2277067c9..a665863eb 100644 --- a/app/controllers/api/v1/accounts/follower_accounts_controller.rb +++ b/app/controllers/api/v1/accounts/follower_accounts_controller.rb @@ -25,7 +25,7 @@ class Api::V1::Accounts::FollowerAccountsController < Api::BaseController end def hide_results? - (@account.hides_followers? && current_account&.id != @account.id) || (current_account && @account.blocking?(current_account)) + @account.suspended? || (@account.hides_followers? && current_account&.id != @account.id) || (current_account && @account.blocking?(current_account)) end def default_accounts diff --git a/app/controllers/api/v1/accounts/following_accounts_controller.rb b/app/controllers/api/v1/accounts/following_accounts_controller.rb index 93d4bd3a4..7d885a212 100644 --- a/app/controllers/api/v1/accounts/following_accounts_controller.rb +++ b/app/controllers/api/v1/accounts/following_accounts_controller.rb @@ -25,7 +25,7 @@ class Api::V1::Accounts::FollowingAccountsController < Api::BaseController end def hide_results? - (@account.hides_following? && current_account&.id != @account.id) || (current_account && @account.blocking?(current_account)) + @account.suspended? || (@account.hides_following? && current_account&.id != @account.id) || (current_account && @account.blocking?(current_account)) end def default_accounts diff --git a/app/controllers/api/v1/accounts/identity_proofs_controller.rb b/app/controllers/api/v1/accounts/identity_proofs_controller.rb index 8dad6fee9..4b5f6902c 100644 --- a/app/controllers/api/v1/accounts/identity_proofs_controller.rb +++ b/app/controllers/api/v1/accounts/identity_proofs_controller.rb @@ -5,7 +5,7 @@ class Api::V1::Accounts::IdentityProofsController < Api::BaseController before_action :set_account def index - @proofs = @account.identity_proofs.active + @proofs = @account.suspended? ? [] : @account.identity_proofs.active render json: @proofs, each_serializer: REST::IdentityProofSerializer end diff --git a/app/controllers/api/v1/accounts/lists_controller.rb b/app/controllers/api/v1/accounts/lists_controller.rb index ccb751f8f..c92f1f8a0 100644 --- a/app/controllers/api/v1/accounts/lists_controller.rb +++ b/app/controllers/api/v1/accounts/lists_controller.rb @@ -6,7 +6,7 @@ class Api::V1::Accounts::ListsController < Api::BaseController before_action :set_account def index - @lists = @account.lists.where(account: current_account) + @lists = @account.suspended? ? [] : @account.lists.where(account: current_account) render json: @lists, each_serializer: REST::ListSerializer end diff --git a/app/controllers/api/v1/accounts/relationships_controller.rb b/app/controllers/api/v1/accounts/relationships_controller.rb index 1d3992a28..503f85c97 100644 --- a/app/controllers/api/v1/accounts/relationships_controller.rb +++ b/app/controllers/api/v1/accounts/relationships_controller.rb @@ -5,7 +5,7 @@ class Api::V1::Accounts::RelationshipsController < Api::BaseController before_action :require_user! def index - accounts = Account.where(id: account_ids).select('id') + accounts = Account.without_suspended.where(id: account_ids).select('id') # .where doesn't guarantee that our results are in the same order # we requested them, so return the "right" order to the requestor. @accounts = accounts.index_by(&:id).values_at(*account_ids).compact diff --git a/app/controllers/api/v1/accounts/statuses_controller.rb b/app/controllers/api/v1/accounts/statuses_controller.rb index 85a9133e3..92ccb8061 100644 --- a/app/controllers/api/v1/accounts/statuses_controller.rb +++ b/app/controllers/api/v1/accounts/statuses_controller.rb @@ -18,7 +18,7 @@ class Api::V1::Accounts::StatusesController < Api::BaseController end def load_statuses - cached_account_statuses + @account.suspended? ? [] : cached_account_statuses end def cached_account_statuses diff --git a/app/controllers/api/v1/accounts_controller.rb b/app/controllers/api/v1/accounts_controller.rb index 0080faf33..aef51a647 100644 --- a/app/controllers/api/v1/accounts_controller.rb +++ b/app/controllers/api/v1/accounts_controller.rb @@ -9,7 +9,6 @@ class Api::V1::AccountsController < Api::BaseController before_action :require_user!, except: [:show, :create] before_action :set_account, except: [:create] - before_action :check_account_suspension, only: [:show] before_action :check_enabled_registrations, only: [:create] skip_before_action :require_authenticated_user!, only: :create @@ -31,9 +30,8 @@ class Api::V1::AccountsController < Api::BaseController end def follow - FollowService.new.call(current_user.account, @account, reblogs: truthy_param?(:reblogs), with_rate_limit: true) - - options = @account.locked? || current_user.account.silenced? ? {} : { following_map: { @account.id => { reblogs: truthy_param?(:reblogs) } }, requested_map: { @account.id => false } } + follow = FollowService.new.call(current_user.account, @account, reblogs: params.key?(:reblogs) ? truthy_param?(:reblogs) : nil, notify: params.key?(:notify) ? truthy_param?(:notify) : nil, with_rate_limit: true) + options = @account.locked? || current_user.account.silenced? ? {} : { following_map: { @account.id => { reblogs: follow.show_reblogs?, notify: follow.notify? } }, requested_map: { @account.id => false } } render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships(options) end @@ -73,10 +71,6 @@ class Api::V1::AccountsController < Api::BaseController AccountRelationshipsPresenter.new([@account.id], current_user.account_id, options) end - def check_account_suspension - gone if @account.suspended? - end - def account_params params.permit(:username, :email, :password, :agreement, :locale, :reason) end diff --git a/app/controllers/api/v1/admin/accounts_controller.rb b/app/controllers/api/v1/admin/accounts_controller.rb index 24c7fbef1..3af572f25 100644 --- a/app/controllers/api/v1/admin/accounts_controller.rb +++ b/app/controllers/api/v1/admin/accounts_controller.rb @@ -58,7 +58,13 @@ class Api::V1::Admin::AccountsController < Api::BaseController def reject authorize @account.user, :reject? - SuspendAccountService.new.call(@account, reserve_email: false, reserve_username: false) + DeleteAccountService.new.call(@account, reserve_email: false, reserve_username: false) + render json: @account, serializer: REST::Admin::AccountSerializer + end + + def destroy + authorize @account, :destroy? + Admin::AccountDeletionWorker.perform_async(@account.id) render json: @account, serializer: REST::Admin::AccountSerializer end @@ -72,6 +78,7 @@ class Api::V1::Admin::AccountsController < Api::BaseController def unsuspend authorize @account, :unsuspend? @account.unsuspend! + Admin::UnsuspensionWorker.perform_async(@account.id) log_action :unsuspend, @account render json: @account, serializer: REST::Admin::AccountSerializer end diff --git a/app/controllers/api/v1/blocks_controller.rb b/app/controllers/api/v1/blocks_controller.rb index a2baeef90..586cdfca9 100644 --- a/app/controllers/api/v1/blocks_controller.rb +++ b/app/controllers/api/v1/blocks_controller.rb @@ -18,6 +18,8 @@ class Api::V1::BlocksController < Api::BaseController def paginated_blocks @paginated_blocks ||= Block.eager_load(target_account: :account_stat) + .joins(:target_account) + .merge(Account.without_suspended) .where(account: current_account) .paginate_by_max_id( limit_param(DEFAULT_ACCOUNTS_LIMIT), diff --git a/app/controllers/api/v1/endorsements_controller.rb b/app/controllers/api/v1/endorsements_controller.rb index c87dbc4ce..9e80f468a 100644 --- a/app/controllers/api/v1/endorsements_controller.rb +++ b/app/controllers/api/v1/endorsements_controller.rb @@ -25,7 +25,7 @@ class Api::V1::EndorsementsController < Api::BaseController end def endorsed_accounts - current_account.endorsed_accounts.includes(:account_stat) + current_account.endorsed_accounts.includes(:account_stat).without_suspended end def insert_pagination_headers diff --git a/app/controllers/api/v1/featured_tags/suggestions_controller.rb b/app/controllers/api/v1/featured_tags/suggestions_controller.rb index 8c1b81a0f..75545d3c7 100644 --- a/app/controllers/api/v1/featured_tags/suggestions_controller.rb +++ b/app/controllers/api/v1/featured_tags/suggestions_controller.rb @@ -3,15 +3,15 @@ class Api::V1::FeaturedTags::SuggestionsController < Api::BaseController before_action -> { doorkeeper_authorize! :read, :'read:accounts' }, only: :index before_action :require_user! - before_action :set_most_used_tags, only: :index + before_action :set_recently_used_tags, only: :index def index - render json: @most_used_tags, each_serializer: REST::TagSerializer + render json: @recently_used_tags, each_serializer: REST::TagSerializer end private - def set_most_used_tags - @most_used_tags = Tag.most_used(current_account).where.not(id: current_account.featured_tags).limit(10) + def set_recently_used_tags + @recently_used_tags = Tag.recently_used(current_account).where.not(id: current_account.featured_tags).limit(10) end end diff --git a/app/controllers/api/v1/follow_requests_controller.rb b/app/controllers/api/v1/follow_requests_controller.rb index 0ee6e531f..b34c76f29 100644 --- a/app/controllers/api/v1/follow_requests_controller.rb +++ b/app/controllers/api/v1/follow_requests_controller.rb @@ -13,7 +13,7 @@ class Api::V1::FollowRequestsController < Api::BaseController def authorize AuthorizeFollowService.new.call(account, current_account) - NotifyService.new.call(current_account, Follow.find_by(account: account, target_account: current_account)) + NotifyService.new.call(current_account, :follow, Follow.find_by(account: account, target_account: current_account)) render json: account, serializer: REST::RelationshipSerializer, relationships: relationships end @@ -37,7 +37,7 @@ class Api::V1::FollowRequestsController < Api::BaseController end def default_accounts - Account.includes(:follow_requests, :account_stat).references(:follow_requests) + Account.without_suspended.includes(:follow_requests, :account_stat).references(:follow_requests) end def paginated_follow_requests diff --git a/app/controllers/api/v1/lists/accounts_controller.rb b/app/controllers/api/v1/lists/accounts_controller.rb index 23078263e..b66ea9bfe 100644 --- a/app/controllers/api/v1/lists/accounts_controller.rb +++ b/app/controllers/api/v1/lists/accounts_controller.rb @@ -37,9 +37,9 @@ class Api::V1::Lists::AccountsController < Api::BaseController def load_accounts if unlimited? - @list.accounts.includes(:account_stat).all + @list.accounts.without_suspended.includes(:account_stat).all else - @list.accounts.includes(:account_stat).paginate_by_max_id(limit_param(DEFAULT_ACCOUNTS_LIMIT), params[:max_id], params[:since_id]) + @list.accounts.without_suspended.includes(:account_stat).paginate_by_max_id(limit_param(DEFAULT_ACCOUNTS_LIMIT), params[:max_id], params[:since_id]) end end diff --git a/app/controllers/api/v1/mutes_controller.rb b/app/controllers/api/v1/mutes_controller.rb index 65439fe9b..805d0dee2 100644 --- a/app/controllers/api/v1/mutes_controller.rb +++ b/app/controllers/api/v1/mutes_controller.rb @@ -18,6 +18,8 @@ class Api::V1::MutesController < Api::BaseController def paginated_mutes @paginated_mutes ||= Mute.eager_load(:target_account) + .joins(:target_account) + .merge(Account.without_suspended) .where(account: current_account) .paginate_by_max_id( limit_param(DEFAULT_ACCOUNTS_LIMIT), diff --git a/app/controllers/api/v1/notifications_controller.rb b/app/controllers/api/v1/notifications_controller.rb index 9d03cb879..522c35ba5 100644 --- a/app/controllers/api/v1/notifications_controller.rb +++ b/app/controllers/api/v1/notifications_controller.rb @@ -14,7 +14,7 @@ class Api::V1::NotificationsController < Api::BaseController end def show - @notification = current_account.notifications.find(params[:id]) + @notification = current_account.notifications.without_suspended.find(params[:id]) render json: @notification, serializer: REST::NotificationSerializer end @@ -40,7 +40,7 @@ class Api::V1::NotificationsController < Api::BaseController end def browserable_account_notifications - current_account.notifications.browserable(exclude_types, from_account) + current_account.notifications.without_suspended.browserable(exclude_types, from_account) end def target_statuses_from_notifications diff --git a/app/controllers/api/v1/push/subscriptions_controller.rb b/app/controllers/api/v1/push/subscriptions_controller.rb index d34b333eb..0918c61e9 100644 --- a/app/controllers/api/v1/push/subscriptions_controller.rb +++ b/app/controllers/api/v1/push/subscriptions_controller.rb @@ -52,6 +52,6 @@ class Api::V1::Push::SubscriptionsController < Api::BaseController def data_params return {} if params[:data].blank? - params.require(:data).permit(alerts: [:follow, :follow_request, :favourite, :reblog, :mention, :poll]) + params.require(:data).permit(alerts: [:follow, :follow_request, :favourite, :reblog, :mention, :poll, :status]) end end diff --git a/app/controllers/api/v1/statuses/favourited_by_accounts_controller.rb b/app/controllers/api/v1/statuses/favourited_by_accounts_controller.rb index 8229786d6..2b614a837 100644 --- a/app/controllers/api/v1/statuses/favourited_by_accounts_controller.rb +++ b/app/controllers/api/v1/statuses/favourited_by_accounts_controller.rb @@ -22,6 +22,7 @@ class Api::V1::Statuses::FavouritedByAccountsController < Api::BaseController def default_accounts Account + .without_suspended .includes(:favourites, :account_stat) .references(:favourites) .where(favourites: { status_id: @status.id }) diff --git a/app/controllers/api/v1/statuses/reblogged_by_accounts_controller.rb b/app/controllers/api/v1/statuses/reblogged_by_accounts_controller.rb index 6c9e49d90..24db30fcc 100644 --- a/app/controllers/api/v1/statuses/reblogged_by_accounts_controller.rb +++ b/app/controllers/api/v1/statuses/reblogged_by_accounts_controller.rb @@ -21,7 +21,7 @@ class Api::V1::Statuses::RebloggedByAccountsController < Api::BaseController end def default_accounts - Account.includes(:statuses, :account_stat).references(:statuses) + Account.without_suspended.includes(:statuses, :account_stat).references(:statuses) end def paginated_statuses diff --git a/app/controllers/api/v1/timelines/public_controller.rb b/app/controllers/api/v1/timelines/public_controller.rb index 26d877b00..d253b744f 100644 --- a/app/controllers/api/v1/timelines/public_controller.rb +++ b/app/controllers/api/v1/timelines/public_controller.rb @@ -20,26 +20,25 @@ class Api::V1::Timelines::PublicController < Api::BaseController end def cached_public_statuses_page - cache_collection_paginated_by_id( - public_statuses, - Status, - limit_param(DEFAULT_STATUSES_LIMIT), - params_slice(:max_id, :since_id, :min_id) - ) + cache_collection(public_statuses, Status) end def public_statuses - statuses = public_timeline_statuses - - if truthy_param?(:only_media) - statuses.joins(:media_attachments).group(:id) - else - statuses - end + public_feed.get( + limit_param(DEFAULT_STATUSES_LIMIT), + params[:max_id], + params[:since_id], + params[:min_id] + ) end - def public_timeline_statuses - Status.as_public_timeline(current_account, truthy_param?(:remote) ? :remote : truthy_param?(:local)) + def public_feed + PublicFeed.new( + current_account, + local: truthy_param?(:local), + remote: truthy_param?(:remote), + only_media: truthy_param?(:only_media) + ) end def insert_pagination_headers diff --git a/app/controllers/api/v1/timelines/tag_controller.rb b/app/controllers/api/v1/timelines/tag_controller.rb index 76f7d3590..64a1db58d 100644 --- a/app/controllers/api/v1/timelines/tag_controller.rb +++ b/app/controllers/api/v1/timelines/tag_controller.rb @@ -20,23 +20,29 @@ class Api::V1::Timelines::TagController < Api::BaseController end def cached_tagged_statuses - if @tag.nil? - [] - else - statuses = tag_timeline_statuses - statuses = statuses.joins(:media_attachments) if truthy_param?(:only_media) - - cache_collection_paginated_by_id( - statuses, - Status, - limit_param(DEFAULT_STATUSES_LIMIT), - params_slice(:max_id, :since_id, :min_id) - ) - end + @tag.nil? ? [] : cache_collection(tag_timeline_statuses, Status) end def tag_timeline_statuses - HashtagQueryService.new.call(@tag, params.slice(:any, :all, :none), current_account, truthy_param?(:local)) + tag_feed.get( + limit_param(DEFAULT_STATUSES_LIMIT), + params[:max_id], + params[:since_id], + params[:min_id] + ) + end + + def tag_feed + TagFeed.new( + @tag, + current_account, + any: params[:any], + all: params[:all], + none: params[:none], + local: truthy_param?(:local), + remote: truthy_param?(:remote), + only_media: truthy_param?(:only_media) + ) end def insert_pagination_headers diff --git a/app/controllers/api/web/push_subscriptions_controller.rb b/app/controllers/api/web/push_subscriptions_controller.rb index 7916b82fa..1dce3e70f 100644 --- a/app/controllers/api/web/push_subscriptions_controller.rb +++ b/app/controllers/api/web/push_subscriptions_controller.rb @@ -22,6 +22,7 @@ class Api::Web::PushSubscriptionsController < Api::Web::BaseController reblog: alerts_enabled, mention: alerts_enabled, poll: alerts_enabled, + status: alerts_enabled, }, } @@ -57,6 +58,6 @@ class Api::Web::PushSubscriptionsController < Api::Web::BaseController end def data_params - @data_params ||= params.require(:data).permit(alerts: [:follow, :follow_request, :favourite, :reblog, :mention, :poll]) + @data_params ||= params.require(:data).permit(alerts: [:follow, :follow_request, :favourite, :reblog, :mention, :poll, :status]) end end diff --git a/app/controllers/concerns/export_controller_concern.rb b/app/controllers/concerns/export_controller_concern.rb index bfe990c82..24cfc7a01 100644 --- a/app/controllers/concerns/export_controller_concern.rb +++ b/app/controllers/concerns/export_controller_concern.rb @@ -5,7 +5,6 @@ module ExportControllerConcern included do before_action :authenticate_user! - before_action :require_not_suspended! before_action :load_export skip_before_action :require_functional! @@ -30,8 +29,4 @@ module ExportControllerConcern def export_filename "#{controller_name}.csv" end - - def require_not_suspended! - forbidden if current_account.suspended? - end end diff --git a/app/controllers/oauth/authorized_applications_controller.rb b/app/controllers/oauth/authorized_applications_controller.rb index fb8389034..45151cdd7 100644 --- a/app/controllers/oauth/authorized_applications_controller.rb +++ b/app/controllers/oauth/authorized_applications_controller.rb @@ -5,6 +5,7 @@ class Oauth::AuthorizedApplicationsController < Doorkeeper::AuthorizedApplicatio before_action :store_current_location before_action :authenticate_resource_owner! + before_action :require_not_suspended!, only: :destroy before_action :set_body_classes skip_before_action :require_functional! @@ -25,4 +26,8 @@ class Oauth::AuthorizedApplicationsController < Doorkeeper::AuthorizedApplicatio def store_current_location store_location_for(:user, request.url) end + + def require_not_suspended! + forbidden if current_account.suspended? + end end diff --git a/app/controllers/settings/aliases_controller.rb b/app/controllers/settings/aliases_controller.rb index b7c9a409d..a421b8ede 100644 --- a/app/controllers/settings/aliases_controller.rb +++ b/app/controllers/settings/aliases_controller.rb @@ -1,9 +1,9 @@ # frozen_string_literal: true class Settings::AliasesController < Settings::BaseController - layout 'admin' + skip_before_action :require_functional! - before_action :authenticate_user! + before_action :require_not_suspended! before_action :set_aliases, except: :destroy before_action :set_alias, only: :destroy diff --git a/app/controllers/settings/applications_controller.rb b/app/controllers/settings/applications_controller.rb index ed3f82a8e..d3ac268d8 100644 --- a/app/controllers/settings/applications_controller.rb +++ b/app/controllers/settings/applications_controller.rb @@ -1,9 +1,6 @@ # frozen_string_literal: true class Settings::ApplicationsController < Settings::BaseController - layout 'admin' - - before_action :authenticate_user! before_action :set_application, only: [:show, :update, :destroy, :regenerate] before_action :prepare_scopes, only: [:create, :update] diff --git a/app/controllers/settings/base_controller.rb b/app/controllers/settings/base_controller.rb index 3c404cfff..8311538a5 100644 --- a/app/controllers/settings/base_controller.rb +++ b/app/controllers/settings/base_controller.rb @@ -1,6 +1,9 @@ # frozen_string_literal: true class Settings::BaseController < ApplicationController + layout 'admin' + + before_action :authenticate_user! before_action :set_body_classes before_action :set_cache_headers @@ -13,4 +16,8 @@ class Settings::BaseController < ApplicationController def set_cache_headers response.headers['Cache-Control'] = 'no-cache, no-store, max-age=0, must-revalidate' end + + def require_not_suspended! + forbidden if current_account.suspended? + end end diff --git a/app/controllers/settings/deletes_controller.rb b/app/controllers/settings/deletes_controller.rb index 15a59c999..f96c83b80 100644 --- a/app/controllers/settings/deletes_controller.rb +++ b/app/controllers/settings/deletes_controller.rb @@ -1,14 +1,11 @@ # frozen_string_literal: true class Settings::DeletesController < Settings::BaseController - layout 'admin' - - before_action :check_enabled_deletion - before_action :authenticate_user! - before_action :require_not_suspended! - skip_before_action :require_functional! + before_action :require_not_suspended! + before_action :check_enabled_deletion + def show @confirmation = Form::DeleteConfirmation.new end @@ -46,7 +43,7 @@ class Settings::DeletesController < Settings::BaseController def destroy_account! current_account.suspend! - Admin::SuspensionWorker.perform_async(current_user.account_id, true) + AccountDeletionWorker.perform_async(current_user.account_id) sign_out end end diff --git a/app/controllers/settings/exports/blocked_accounts_controller.rb b/app/controllers/settings/exports/blocked_accounts_controller.rb index 2092104e0..2190caa36 100644 --- a/app/controllers/settings/exports/blocked_accounts_controller.rb +++ b/app/controllers/settings/exports/blocked_accounts_controller.rb @@ -2,7 +2,7 @@ module Settings module Exports - class BlockedAccountsController < ApplicationController + class BlockedAccountsController < BaseController include ExportControllerConcern def index diff --git a/app/controllers/settings/exports/blocked_domains_controller.rb b/app/controllers/settings/exports/blocked_domains_controller.rb index 6676ce340..bee4b2431 100644 --- a/app/controllers/settings/exports/blocked_domains_controller.rb +++ b/app/controllers/settings/exports/blocked_domains_controller.rb @@ -2,7 +2,7 @@ module Settings module Exports - class BlockedDomainsController < ApplicationController + class BlockedDomainsController < BaseController include ExportControllerConcern def index diff --git a/app/controllers/settings/exports/following_accounts_controller.rb b/app/controllers/settings/exports/following_accounts_controller.rb index 74281ddca..acefcb15d 100644 --- a/app/controllers/settings/exports/following_accounts_controller.rb +++ b/app/controllers/settings/exports/following_accounts_controller.rb @@ -2,7 +2,7 @@ module Settings module Exports - class FollowingAccountsController < ApplicationController + class FollowingAccountsController < BaseController include ExportControllerConcern def index diff --git a/app/controllers/settings/exports/lists_controller.rb b/app/controllers/settings/exports/lists_controller.rb index cf5a9de44..bc65f56a0 100644 --- a/app/controllers/settings/exports/lists_controller.rb +++ b/app/controllers/settings/exports/lists_controller.rb @@ -2,7 +2,7 @@ module Settings module Exports - class ListsController < ApplicationController + class ListsController < BaseController include ExportControllerConcern def index diff --git a/app/controllers/settings/exports/muted_accounts_controller.rb b/app/controllers/settings/exports/muted_accounts_controller.rb index e511619ca..50b7bf1f7 100644 --- a/app/controllers/settings/exports/muted_accounts_controller.rb +++ b/app/controllers/settings/exports/muted_accounts_controller.rb @@ -2,7 +2,7 @@ module Settings module Exports - class MutedAccountsController < ApplicationController + class MutedAccountsController < BaseController include ExportControllerConcern def index diff --git a/app/controllers/settings/exports_controller.rb b/app/controllers/settings/exports_controller.rb index 0e93d07a9..30138d29e 100644 --- a/app/controllers/settings/exports_controller.rb +++ b/app/controllers/settings/exports_controller.rb @@ -3,11 +3,6 @@ class Settings::ExportsController < Settings::BaseController include Authorization - layout 'admin' - - before_action :authenticate_user! - before_action :require_not_suspended! - skip_before_action :require_functional! def show @@ -16,8 +11,6 @@ class Settings::ExportsController < Settings::BaseController end def create - raise Mastodon::NotPermittedError unless user_signed_in? - backup = nil RedisLock.acquire(lock_options) do |lock| @@ -37,8 +30,4 @@ class Settings::ExportsController < Settings::BaseController def lock_options { redis: Redis.current, key: "backup:#{current_user.id}" } end - - def require_not_suspended! - forbidden if current_account.suspended? - end end diff --git a/app/controllers/settings/featured_tags_controller.rb b/app/controllers/settings/featured_tags_controller.rb index 3a3241425..e805527d0 100644 --- a/app/controllers/settings/featured_tags_controller.rb +++ b/app/controllers/settings/featured_tags_controller.rb @@ -1,12 +1,9 @@ # frozen_string_literal: true class Settings::FeaturedTagsController < Settings::BaseController - layout 'admin' - - before_action :authenticate_user! before_action :set_featured_tags, only: :index before_action :set_featured_tag, except: [:index, :create] - before_action :set_most_used_tags, only: :index + before_action :set_recently_used_tags, only: :index def index @featured_tag = FeaturedTag.new @@ -20,7 +17,7 @@ class Settings::FeaturedTagsController < Settings::BaseController redirect_to settings_featured_tags_path else set_featured_tags - set_most_used_tags + set_recently_used_tags render :index end @@ -41,8 +38,8 @@ class Settings::FeaturedTagsController < Settings::BaseController @featured_tags = current_account.featured_tags.order(statuses_count: :desc).reject(&:new_record?) end - def set_most_used_tags - @most_used_tags = Tag.most_used(current_account).where.not(id: @featured_tags.map(&:id)).limit(10) + def set_recently_used_tags + @recently_used_tags = Tag.recently_used(current_account).where.not(id: @featured_tags.map(&:id)).limit(10) end def featured_tag_params diff --git a/app/controllers/settings/identity_proofs_controller.rb b/app/controllers/settings/identity_proofs_controller.rb index 3a90b7c4d..bf2899da6 100644 --- a/app/controllers/settings/identity_proofs_controller.rb +++ b/app/controllers/settings/identity_proofs_controller.rb @@ -1,9 +1,6 @@ # frozen_string_literal: true class Settings::IdentityProofsController < Settings::BaseController - layout 'admin' - - before_action :authenticate_user! before_action :check_required_params, only: :new def index diff --git a/app/controllers/settings/imports_controller.rb b/app/controllers/settings/imports_controller.rb index 7b8c4ae23..d4516526e 100644 --- a/app/controllers/settings/imports_controller.rb +++ b/app/controllers/settings/imports_controller.rb @@ -1,9 +1,6 @@ # frozen_string_literal: true class Settings::ImportsController < Settings::BaseController - layout 'admin' - - before_action :authenticate_user! before_action :set_account def show diff --git a/app/controllers/settings/migration/redirects_controller.rb b/app/controllers/settings/migration/redirects_controller.rb index 97193ade0..6d469f384 100644 --- a/app/controllers/settings/migration/redirects_controller.rb +++ b/app/controllers/settings/migration/redirects_controller.rb @@ -1,13 +1,10 @@ # frozen_string_literal: true class Settings::Migration::RedirectsController < Settings::BaseController - layout 'admin' - - before_action :authenticate_user! - before_action :require_not_suspended! - skip_before_action :require_functional! + before_action :require_not_suspended! + def new @redirect = Form::Redirect.new end @@ -38,8 +35,4 @@ class Settings::Migration::RedirectsController < Settings::BaseController def resource_params params.require(:form_redirect).permit(:acct, :current_password, :current_username) end - - def require_not_suspended! - forbidden if current_account.suspended? - end end diff --git a/app/controllers/settings/migrations_controller.rb b/app/controllers/settings/migrations_controller.rb index 68304bb51..62603aba8 100644 --- a/app/controllers/settings/migrations_controller.rb +++ b/app/controllers/settings/migrations_controller.rb @@ -1,15 +1,12 @@ # frozen_string_literal: true class Settings::MigrationsController < Settings::BaseController - layout 'admin' + skip_before_action :require_functional! - before_action :authenticate_user! before_action :require_not_suspended! before_action :set_migrations before_action :set_cooldown - skip_before_action :require_functional! - def show @migration = current_account.migrations.build end @@ -44,8 +41,4 @@ class Settings::MigrationsController < Settings::BaseController def on_cooldown? @cooldown.present? end - - def require_not_suspended! - forbidden if current_account.suspended? - end end diff --git a/app/controllers/settings/pictures_controller.rb b/app/controllers/settings/pictures_controller.rb index df2a6eed3..28df65f8f 100644 --- a/app/controllers/settings/pictures_controller.rb +++ b/app/controllers/settings/pictures_controller.rb @@ -2,7 +2,6 @@ module Settings class PicturesController < BaseController - before_action :authenticate_user! before_action :set_account before_action :set_picture diff --git a/app/controllers/settings/preferences_controller.rb b/app/controllers/settings/preferences_controller.rb index bac9b329d..be4dc904d 100644 --- a/app/controllers/settings/preferences_controller.rb +++ b/app/controllers/settings/preferences_controller.rb @@ -1,10 +1,6 @@ # frozen_string_literal: true class Settings::PreferencesController < Settings::BaseController - layout 'admin' - - before_action :authenticate_user! - def show; end def update diff --git a/app/controllers/settings/profiles_controller.rb b/app/controllers/settings/profiles_controller.rb index 19a7ce157..0c15447a6 100644 --- a/app/controllers/settings/profiles_controller.rb +++ b/app/controllers/settings/profiles_controller.rb @@ -1,9 +1,6 @@ # frozen_string_literal: true class Settings::ProfilesController < Settings::BaseController - layout 'admin' - - before_action :authenticate_user! before_action :set_account def show diff --git a/app/controllers/settings/sessions_controller.rb b/app/controllers/settings/sessions_controller.rb index df5ace803..ee2fc5dc8 100644 --- a/app/controllers/settings/sessions_controller.rb +++ b/app/controllers/settings/sessions_controller.rb @@ -1,11 +1,11 @@ # frozen_string_literal: true class Settings::SessionsController < Settings::BaseController - before_action :authenticate_user! - before_action :set_session, only: :destroy - skip_before_action :require_functional! + before_action :require_not_suspended! + before_action :set_session, only: :destroy + def destroy @session.destroy! flash[:notice] = I18n.t('sessions.revoke_success') diff --git a/app/controllers/settings/two_factor_authentication/confirmations_controller.rb b/app/controllers/settings/two_factor_authentication/confirmations_controller.rb index 9f23011a7..1a0afe58b 100644 --- a/app/controllers/settings/two_factor_authentication/confirmations_controller.rb +++ b/app/controllers/settings/two_factor_authentication/confirmations_controller.rb @@ -5,14 +5,11 @@ module Settings class ConfirmationsController < BaseController include ChallengableConcern - layout 'admin' + skip_before_action :require_functional! - before_action :authenticate_user! before_action :require_challenge! before_action :ensure_otp_secret - skip_before_action :require_functional! - def new prepare_two_factor_form end diff --git a/app/controllers/settings/two_factor_authentication/otp_authentication_controller.rb b/app/controllers/settings/two_factor_authentication/otp_authentication_controller.rb index 6836f7ef6..cbba842a9 100644 --- a/app/controllers/settings/two_factor_authentication/otp_authentication_controller.rb +++ b/app/controllers/settings/two_factor_authentication/otp_authentication_controller.rb @@ -5,14 +5,11 @@ module Settings class OtpAuthenticationController < BaseController include ChallengableConcern - layout 'admin' + skip_before_action :require_functional! - before_action :authenticate_user! before_action :verify_otp_not_enabled, only: [:show] before_action :require_challenge!, only: [:create] - skip_before_action :require_functional! - def show @confirmation = Form::TwoFactorConfirmation.new end diff --git a/app/controllers/settings/two_factor_authentication/recovery_codes_controller.rb b/app/controllers/settings/two_factor_authentication/recovery_codes_controller.rb index 0c4f5bff7..6ec53224d 100644 --- a/app/controllers/settings/two_factor_authentication/recovery_codes_controller.rb +++ b/app/controllers/settings/two_factor_authentication/recovery_codes_controller.rb @@ -5,13 +5,10 @@ module Settings class RecoveryCodesController < BaseController include ChallengableConcern - layout 'admin' - - before_action :authenticate_user! - before_action :require_challenge!, on: :create - skip_before_action :require_functional! + before_action :require_challenge!, on: :create + def create @recovery_codes = current_user.generate_otp_backup_codes! current_user.save! diff --git a/app/controllers/settings/two_factor_authentication/webauthn_credentials_controller.rb b/app/controllers/settings/two_factor_authentication/webauthn_credentials_controller.rb index a19c604f3..1c557092b 100644 --- a/app/controllers/settings/two_factor_authentication/webauthn_credentials_controller.rb +++ b/app/controllers/settings/two_factor_authentication/webauthn_credentials_controller.rb @@ -3,9 +3,8 @@ module Settings module TwoFactorAuthentication class WebauthnCredentialsController < BaseController - layout 'admin' + skip_before_action :require_functional! - before_action :authenticate_user! before_action :require_otp_enabled before_action :require_webauthn_enabled, only: [:index, :destroy] diff --git a/app/controllers/settings/two_factor_authentication_methods_controller.rb b/app/controllers/settings/two_factor_authentication_methods_controller.rb index 224d3a45c..205933ea8 100644 --- a/app/controllers/settings/two_factor_authentication_methods_controller.rb +++ b/app/controllers/settings/two_factor_authentication_methods_controller.rb @@ -4,14 +4,11 @@ module Settings class TwoFactorAuthenticationMethodsController < BaseController include ChallengableConcern - layout 'admin' + skip_before_action :require_functional! - before_action :authenticate_user! before_action :require_challenge!, only: :disable before_action :require_otp_enabled - skip_before_action :require_functional! - def index; end def disable diff --git a/app/controllers/tags_controller.rb b/app/controllers/tags_controller.rb index 6426a7d69..6616ba107 100644 --- a/app/controllers/tags_controller.rb +++ b/app/controllers/tags_controller.rb @@ -10,8 +10,9 @@ class TagsController < ApplicationController before_action :require_signature!, if: -> { request.format == :json && authorized_fetch_mode? } before_action :authenticate_user!, if: :whitelist_mode? - before_action :set_tag before_action :set_local + before_action :set_tag + before_action :set_statuses before_action :set_body_classes before_action :set_instance_presenter @@ -25,20 +26,11 @@ class TagsController < ApplicationController format.rss do expires_in 0, public: true - - limit = params[:limit].present? ? [params[:limit].to_i, PAGE_SIZE_MAX].min : PAGE_SIZE - @statuses = HashtagQueryService.new.call(@tag, filter_params, nil, @local).limit(limit) - @statuses = cache_collection(@statuses, Status) - render xml: RSS::TagSerializer.render(@tag, @statuses) end format.json do expires_in 3.minutes, public: public_fetch_mode? - - @statuses = HashtagQueryService.new.call(@tag, filter_params, current_account, @local).paginate_by_max_id(PAGE_SIZE, params[:max_id]) - @statuses = cache_collection(@statuses, Status) - render json: collection_presenter, serializer: ActivityPub::CollectionSerializer, adapter: ActivityPub::Adapter, content_type: 'application/activity+json' end end @@ -54,6 +46,15 @@ class TagsController < ApplicationController @local = truthy_param?(:local) end + def set_statuses + case request.format&.to_sym + when :json + @statuses = cache_collection(TagFeed.new(@tag, current_account, local: @local).get(PAGE_SIZE, params[:max_id], params[:since_id], params[:min_id]), Status) + when :rss + @statuses = cache_collection(TagFeed.new(@tag, nil, local: @local).get(limit_param), Status) + end + end + def set_body_classes @body_classes = 'with-modals' end @@ -62,16 +63,16 @@ class TagsController < ApplicationController @instance_presenter = InstancePresenter.new end + def limit_param + params[:limit].present? ? [params[:limit].to_i, PAGE_SIZE_MAX].min : PAGE_SIZE + end + def collection_presenter ActivityPub::CollectionPresenter.new( - id: tag_url(@tag, filter_params), + id: tag_url(@tag), type: :ordered, size: @tag.statuses.count, items: @statuses.map { |s| ActivityPub::TagManager.instance.uri_for(s) } ) end - - def filter_params - params.slice(:any, :all, :none).permit(:any, :all, :none) - end end diff --git a/app/javascript/mastodon/actions/accounts.js b/app/javascript/mastodon/actions/accounts.js index d28f7dad8..723c04e55 100644 --- a/app/javascript/mastodon/actions/accounts.js +++ b/app/javascript/mastodon/actions/accounts.js @@ -109,14 +109,14 @@ export function fetchAccountFail(id, error) { }; }; -export function followAccount(id, reblogs = true) { +export function followAccount(id, options = { reblogs: true }) { return (dispatch, getState) => { const alreadyFollowing = getState().getIn(['relationships', id, 'following']); const locked = getState().getIn(['accounts', id, 'locked'], false); dispatch(followAccountRequest(id, locked)); - api(getState).post(`/api/v1/accounts/${id}/follow`, { reblogs }).then(response => { + api(getState).post(`/api/v1/accounts/${id}/follow`, options).then(response => { dispatch(followAccountSuccess(response.data, alreadyFollowing)); }).catch(error => { dispatch(followAccountFail(error, locked)); diff --git a/app/javascript/mastodon/actions/markers.js b/app/javascript/mastodon/actions/markers.js index 37d1ddccf..6cb09fe96 100644 --- a/app/javascript/mastodon/actions/markers.js +++ b/app/javascript/mastodon/actions/markers.js @@ -57,7 +57,7 @@ export const synchronouslySubmitMarkers = () => (dispatch, getState) => { const _buildParams = (state) => { const params = {}; - const lastHomeId = state.getIn(['timelines', 'home', 'items', 0]); + const lastHomeId = state.getIn(['timelines', 'home', 'items']).find(item => item !== null); const lastNotificationId = state.getIn(['notifications', 'items', 0, 'id']); if (lastHomeId && compareId(lastHomeId, state.getIn(['markers', 'home'])) > 0) { diff --git a/app/javascript/mastodon/actions/notifications.js b/app/javascript/mastodon/actions/notifications.js index a26844f84..099e42f6c 100644 --- a/app/javascript/mastodon/actions/notifications.js +++ b/app/javascript/mastodon/actions/notifications.js @@ -59,7 +59,7 @@ export function updateNotifications(notification, intlMessages, intlLocale) { let filtered = false; - if (notification.type === 'mention') { + if (['mention', 'status'].includes(notification.type)) { const dropRegex = filters[0]; const regex = filters[1]; const searchIndex = searchTextFromRawStatus(notification.status); diff --git a/app/javascript/mastodon/components/error_boundary.js b/app/javascript/mastodon/components/error_boundary.js index ca3012276..ca4a2cfe1 100644 --- a/app/javascript/mastodon/components/error_boundary.js +++ b/app/javascript/mastodon/components/error_boundary.js @@ -66,17 +66,31 @@ export default class ErrorBoundary extends React.PureComponent { } render() { - const { hasError, copied } = this.state; + const { hasError, copied, errorMessage } = this.state; if (!hasError) { return this.props.children; } + const likelyBrowserAddonIssue = errorMessage && errorMessage.includes('NotFoundError'); + return (
-

-

+

+ { likelyBrowserAddonIssue ? ( + + ) : ( + + )} +

+

+ { likelyBrowserAddonIssue ? ( + + ) : ( + + )} +

Mastodon v{version} · ·

diff --git a/app/javascript/mastodon/features/account/components/header.js b/app/javascript/mastodon/features/account/components/header.js index 61ecf045d..2b97af4e6 100644 --- a/app/javascript/mastodon/features/account/components/header.js +++ b/app/javascript/mastodon/features/account/components/header.js @@ -7,6 +7,7 @@ import ImmutablePureComponent from 'react-immutable-pure-component'; import { autoPlayGif, me, isStaff } from 'mastodon/initial_state'; import classNames from 'classnames'; import Icon from 'mastodon/components/icon'; +import IconButton from 'mastodon/components/icon_button'; import Avatar from 'mastodon/components/avatar'; import { counterRenderer } from 'mastodon/components/common_counter'; import ShortNumber from 'mastodon/components/short_number'; @@ -35,6 +36,8 @@ const messages = defineMessages({ unblockDomain: { id: 'account.unblock_domain', defaultMessage: 'Unblock domain {domain}' }, hideReblogs: { id: 'account.hide_reblogs', defaultMessage: 'Hide boosts from @{name}' }, showReblogs: { id: 'account.show_reblogs', defaultMessage: 'Show boosts from @{name}' }, + enableNotifications: { id: 'account.enable_notifications', defaultMessage: 'Notify me when @{name} posts' }, + disableNotifications: { id: 'account.disable_notifications', defaultMessage: 'Stop notifying me when @{name} posts' }, pins: { id: 'navigation_bar.pins', defaultMessage: 'Pinned toots' }, preferences: { id: 'navigation_bar.preferences', defaultMessage: 'Preferences' }, follow_requests: { id: 'navigation_bar.follow_requests', defaultMessage: 'Follow requests' }, @@ -68,8 +71,9 @@ class Header extends ImmutablePureComponent { onBlock: PropTypes.func.isRequired, onMention: PropTypes.func.isRequired, onDirect: PropTypes.func.isRequired, - onReport: PropTypes.func.isRequired, onReblogToggle: PropTypes.func.isRequired, + onNotifyToggle: PropTypes.func.isRequired, + onReport: PropTypes.func.isRequired, onMute: PropTypes.func.isRequired, onBlockDomain: PropTypes.func.isRequired, onUnblockDomain: PropTypes.func.isRequired, @@ -140,8 +144,11 @@ class Header extends ImmutablePureComponent { return null; } + const suspended = account.get('suspended'); + let info = []; let actionBtn = ''; + let bellBtn = ''; let lockedIcon = ''; let menu = []; @@ -171,6 +178,10 @@ class Header extends ImmutablePureComponent { actionBtn = +