diff --git a/.circleci/config.yml b/.circleci/config.yml
index 3ba027d95..a343fc654 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -6,6 +6,7 @@ aliases:
- image: circleci/ruby:2.7-buster-node
environment: &ruby_environment
BUNDLE_APP_CONFIG: ./.bundle/
+ BUNDLE_PATH: ./vendor/bundle/
DB_HOST: localhost
DB_USER: root
RAILS_ENV: test
diff --git a/Gemfile b/Gemfile
index 07959fd3d..f6c705765 100644
--- a/Gemfile
+++ b/Gemfile
@@ -49,7 +49,7 @@ gem 'omniauth-saml', '~> 1.10'
gem 'omniauth', '~> 1.9'
gem 'discard', '~> 1.1'
-gem 'doorkeeper', '~> 5.2'
+gem 'doorkeeper', '~> 5.3'
gem 'fast_blank', '~> 1.0'
gem 'fastimage'
gem 'goldfinger', '~> 2.1'
@@ -92,7 +92,7 @@ gem 'simple-navigation', '~> 4.1'
gem 'simple_form', '~> 5.0'
gem 'sprockets-rails', '~> 3.2', require: 'sprockets/railtie'
gem 'stoplight', '~> 2.2.0'
-gem 'strong_migrations', '~> 0.5'
+gem 'strong_migrations', '~> 0.6'
gem 'tty-command', '~> 0.9', require: false
gem 'tty-prompt', '~> 0.20', require: false
gem 'twitter-text', '~> 1.14'
diff --git a/Gemfile.lock b/Gemfile.lock
index bd0d0430d..fda4d5dd0 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -195,21 +195,21 @@ GEM
docile (1.3.2)
domain_name (0.5.20190701)
unf (>= 0.0.5, < 1.0.0)
- doorkeeper (5.2.3)
+ doorkeeper (5.3.1)
railties (>= 5)
dotenv (2.7.5)
dotenv-rails (2.7.5)
dotenv (= 2.7.5)
railties (>= 3.2, < 6.1)
e2mmap (0.1.0)
- elasticsearch (7.3.0)
- elasticsearch-api (= 7.3.0)
- elasticsearch-transport (= 7.3.0)
- elasticsearch-api (7.3.0)
+ elasticsearch (7.5.0)
+ elasticsearch-api (= 7.5.0)
+ elasticsearch-transport (= 7.5.0)
+ elasticsearch-api (7.5.0)
multi_json
elasticsearch-dsl (0.1.8)
- elasticsearch-transport (7.3.0)
- faraday
+ elasticsearch-transport (7.5.0)
+ faraday (>= 0.14, < 1)
multi_json
encryptor (3.0.0)
equatable (0.6.1)
@@ -220,7 +220,7 @@ GEM
fabrication (2.21.0)
faker (2.10.1)
i18n (>= 1.6, < 2)
- faraday (1.0.0)
+ faraday (0.17.3)
multipart-post (>= 1.2, < 3)
fast_blank (1.0.0)
fastimage (2.1.7)
@@ -311,7 +311,7 @@ GEM
multi_json (~> 1.14)
rack (~> 2.0)
rdf (~> 3.1)
- json-ld-preloaded (3.1.0)
+ json-ld-preloaded (3.1.1)
json-ld (~> 3.1)
rdf (~> 3.1)
jsonapi-renderer (0.2.2)
@@ -383,7 +383,7 @@ GEM
concurrent-ruby (~> 1.0, >= 1.0.2)
sidekiq (>= 3.5)
statsd-ruby (~> 1.4, >= 1.4.0)
- oj (3.10.1)
+ oj (3.10.3)
omniauth (1.9.0)
hashie (>= 3.4.6, < 3.7.0)
rack (>= 1.6.2, < 3)
@@ -435,7 +435,7 @@ GEM
pry-rails (0.3.9)
pry (>= 0.10.4)
public_suffix (4.0.3)
- puma (4.3.1)
+ puma (4.3.3)
nio4r (~> 2.0)
pundit (2.1.0)
activesupport (>= 3.0.0)
@@ -602,7 +602,7 @@ GEM
stoplight (2.2.0)
streamio-ffmpeg (3.0.2)
multi_json (~> 1.8)
- strong_migrations (0.5.1)
+ strong_migrations (0.6.2)
activerecord (>= 5)
temple (0.8.2)
terminal-table (1.8.0)
@@ -689,7 +689,7 @@ DEPENDENCIES
devise-two-factor (~> 3.1)
devise_pam_authenticatable2 (~> 9.2)
discard (~> 1.1)
- doorkeeper (~> 5.2)
+ doorkeeper (~> 5.3)
dotenv-rails (~> 2.7)
e2mmap (~> 0.1.0)
fabrication (~> 2.21)
@@ -777,7 +777,7 @@ DEPENDENCIES
stackprof
stoplight (~> 2.2.0)
streamio-ffmpeg (~> 3.0)
- strong_migrations (~> 0.5)
+ strong_migrations (~> 0.6)
thor (~> 0.20)
thwait (~> 0.1.0)
tty-command (~> 0.9)
diff --git a/app/controllers/account_follow_controller.rb b/app/controllers/account_follow_controller.rb
index 185a355f8..33394074d 100644
--- a/app/controllers/account_follow_controller.rb
+++ b/app/controllers/account_follow_controller.rb
@@ -6,7 +6,7 @@ class AccountFollowController < ApplicationController
before_action :authenticate_user!
def create
- FollowService.new.call(current_user.account, @account.acct)
+ FollowService.new.call(current_user.account, @account, with_rate_limit: true)
redirect_to account_path(@account)
end
end
diff --git a/app/controllers/admin/site_uploads_controller.rb b/app/controllers/admin/site_uploads_controller.rb
new file mode 100644
index 000000000..cacecedb0
--- /dev/null
+++ b/app/controllers/admin/site_uploads_controller.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+module Admin
+ class SiteUploadsController < BaseController
+ before_action :set_site_upload
+
+ def destroy
+ authorize :settings, :destroy?
+
+ @site_upload.destroy!
+
+ redirect_to edit_admin_settings_path, notice: I18n.t('admin.site_uploads.destroyed_msg')
+ end
+
+ private
+
+ def set_site_upload
+ @site_upload = SiteUpload.find(params[:id])
+ end
+ end
+end
diff --git a/app/controllers/api/base_controller.rb b/app/controllers/api/base_controller.rb
index 68bf425f4..153ade253 100644
--- a/app/controllers/api/base_controller.rb
+++ b/app/controllers/api/base_controller.rb
@@ -44,6 +44,10 @@ class Api::BaseController < ApplicationController
render json: { error: 'There was a temporary problem serving your request, please try again' }, status: 503
end
+ rescue_from Mastodon::RateLimitExceededError do
+ render json: { error: I18n.t('errors.429') }, status: 429
+ end
+
rescue_from ActionController::ParameterMissing do |e|
render json: { error: e.to_s }, status: 400
end
diff --git a/app/controllers/api/v1/accounts/follower_accounts_controller.rb b/app/controllers/api/v1/accounts/follower_accounts_controller.rb
index e360b8a92..850702cca 100644
--- a/app/controllers/api/v1/accounts/follower_accounts_controller.rb
+++ b/app/controllers/api/v1/accounts/follower_accounts_controller.rb
@@ -5,8 +5,6 @@ class Api::V1::Accounts::FollowerAccountsController < Api::BaseController
before_action :set_account
after_action :insert_pagination_headers
- respond_to :json
-
def index
@accounts = load_accounts
render json: @accounts, each_serializer: REST::AccountSerializer
diff --git a/app/controllers/api/v1/accounts/following_accounts_controller.rb b/app/controllers/api/v1/accounts/following_accounts_controller.rb
index a405b365f..830dcd8a1 100644
--- a/app/controllers/api/v1/accounts/following_accounts_controller.rb
+++ b/app/controllers/api/v1/accounts/following_accounts_controller.rb
@@ -5,8 +5,6 @@ class Api::V1::Accounts::FollowingAccountsController < Api::BaseController
before_action :set_account
after_action :insert_pagination_headers
- respond_to :json
-
def index
@accounts = load_accounts
render json: @accounts, each_serializer: REST::AccountSerializer
diff --git a/app/controllers/api/v1/accounts/identity_proofs_controller.rb b/app/controllers/api/v1/accounts/identity_proofs_controller.rb
index bea51ae11..8dad6fee9 100644
--- a/app/controllers/api/v1/accounts/identity_proofs_controller.rb
+++ b/app/controllers/api/v1/accounts/identity_proofs_controller.rb
@@ -4,8 +4,6 @@ class Api::V1::Accounts::IdentityProofsController < Api::BaseController
before_action :require_user!
before_action :set_account
- respond_to :json
-
def index
@proofs = @account.identity_proofs.active
render json: @proofs, each_serializer: REST::IdentityProofSerializer
diff --git a/app/controllers/api/v1/accounts/lists_controller.rb b/app/controllers/api/v1/accounts/lists_controller.rb
index 72392453c..ccb751f8f 100644
--- a/app/controllers/api/v1/accounts/lists_controller.rb
+++ b/app/controllers/api/v1/accounts/lists_controller.rb
@@ -5,8 +5,6 @@ class Api::V1::Accounts::ListsController < Api::BaseController
before_action :require_user!
before_action :set_account
- respond_to :json
-
def index
@lists = @account.lists.where(account: current_account)
render json: @lists, each_serializer: REST::ListSerializer
diff --git a/app/controllers/api/v1/accounts/pins_controller.rb b/app/controllers/api/v1/accounts/pins_controller.rb
index 0a0239c42..3915b5669 100644
--- a/app/controllers/api/v1/accounts/pins_controller.rb
+++ b/app/controllers/api/v1/accounts/pins_controller.rb
@@ -7,8 +7,6 @@ class Api::V1::Accounts::PinsController < Api::BaseController
before_action :require_user!
before_action :set_account
- respond_to :json
-
def create
AccountPin.create!(account: current_account, target_account: @account)
render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships_presenter
diff --git a/app/controllers/api/v1/accounts/relationships_controller.rb b/app/controllers/api/v1/accounts/relationships_controller.rb
index ab8a0461f..1d3992a28 100644
--- a/app/controllers/api/v1/accounts/relationships_controller.rb
+++ b/app/controllers/api/v1/accounts/relationships_controller.rb
@@ -4,8 +4,6 @@ class Api::V1::Accounts::RelationshipsController < Api::BaseController
before_action -> { doorkeeper_authorize! :read, :'read:follows' }
before_action :require_user!
- respond_to :json
-
def index
accounts = Account.where(id: account_ids).select('id')
# .where doesn't guarantee that our results are in the same order
diff --git a/app/controllers/api/v1/accounts/search_controller.rb b/app/controllers/api/v1/accounts/search_controller.rb
index 4217b527a..3061fcb7e 100644
--- a/app/controllers/api/v1/accounts/search_controller.rb
+++ b/app/controllers/api/v1/accounts/search_controller.rb
@@ -4,8 +4,6 @@ class Api::V1::Accounts::SearchController < Api::BaseController
before_action -> { doorkeeper_authorize! :read, :'read:accounts' }
before_action :require_user!
- respond_to :json
-
def show
@accounts = account_search
render json: @accounts, each_serializer: REST::AccountSerializer
diff --git a/app/controllers/api/v1/accounts/statuses_controller.rb b/app/controllers/api/v1/accounts/statuses_controller.rb
index 333db9618..114ee0a82 100644
--- a/app/controllers/api/v1/accounts/statuses_controller.rb
+++ b/app/controllers/api/v1/accounts/statuses_controller.rb
@@ -6,8 +6,6 @@ class Api::V1::Accounts::StatusesController < Api::BaseController
after_action :insert_pagination_headers, unless: -> { truthy_param?(:pinned) }
- respond_to :json
-
def index
@statuses = load_statuses
render json: @statuses, each_serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new(@statuses, current_user&.account_id)
diff --git a/app/controllers/api/v1/accounts_controller.rb b/app/controllers/api/v1/accounts_controller.rb
index d68d2715f..0080faf33 100644
--- a/app/controllers/api/v1/accounts_controller.rb
+++ b/app/controllers/api/v1/accounts_controller.rb
@@ -14,7 +14,7 @@ class Api::V1::AccountsController < Api::BaseController
skip_before_action :require_authenticated_user!, only: :create
- respond_to :json
+ override_rate_limit_headers :follow, family: :follows
def show
render json: @account, serializer: REST::AccountSerializer
@@ -31,7 +31,7 @@ class Api::V1::AccountsController < Api::BaseController
end
def follow
- FollowService.new.call(current_user.account, @account, reblogs: truthy_param?(:reblogs))
+ 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 } }
diff --git a/app/controllers/api/v1/apps/credentials_controller.rb b/app/controllers/api/v1/apps/credentials_controller.rb
index 8b63d0490..0475b2d4a 100644
--- a/app/controllers/api/v1/apps/credentials_controller.rb
+++ b/app/controllers/api/v1/apps/credentials_controller.rb
@@ -3,8 +3,6 @@
class Api::V1::Apps::CredentialsController < Api::BaseController
before_action -> { doorkeeper_authorize! :read }
- respond_to :json
-
def show
render json: doorkeeper_token.application, serializer: REST::ApplicationSerializer, fields: %i(name website vapid_key)
end
diff --git a/app/controllers/api/v1/blocks_controller.rb b/app/controllers/api/v1/blocks_controller.rb
index 4cff04cad..a2baeef90 100644
--- a/app/controllers/api/v1/blocks_controller.rb
+++ b/app/controllers/api/v1/blocks_controller.rb
@@ -5,8 +5,6 @@ class Api::V1::BlocksController < Api::BaseController
before_action :require_user!
after_action :insert_pagination_headers
- respond_to :json
-
def index
@accounts = load_accounts
render json: @accounts, each_serializer: REST::AccountSerializer
diff --git a/app/controllers/api/v1/bookmarks_controller.rb b/app/controllers/api/v1/bookmarks_controller.rb
index e1b244e76..c15212f0a 100644
--- a/app/controllers/api/v1/bookmarks_controller.rb
+++ b/app/controllers/api/v1/bookmarks_controller.rb
@@ -5,8 +5,6 @@ class Api::V1::BookmarksController < Api::BaseController
before_action :require_user!
after_action :insert_pagination_headers
- respond_to :json
-
def index
@statuses = load_statuses
render json: @statuses, each_serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new(@statuses, current_user&.account_id)
diff --git a/app/controllers/api/v1/conversations_controller.rb b/app/controllers/api/v1/conversations_controller.rb
index b19f27ebf..bc8013379 100644
--- a/app/controllers/api/v1/conversations_controller.rb
+++ b/app/controllers/api/v1/conversations_controller.rb
@@ -9,8 +9,6 @@ class Api::V1::ConversationsController < Api::BaseController
before_action :set_conversation, except: :index
after_action :insert_pagination_headers, only: :index
- respond_to :json
-
def index
@conversations = paginated_conversations
render json: @conversations, each_serializer: REST::ConversationSerializer
diff --git a/app/controllers/api/v1/custom_emojis_controller.rb b/app/controllers/api/v1/custom_emojis_controller.rb
index 4e6d5d7c6..08b3474cc 100644
--- a/app/controllers/api/v1/custom_emojis_controller.rb
+++ b/app/controllers/api/v1/custom_emojis_controller.rb
@@ -1,8 +1,6 @@
# frozen_string_literal: true
class Api::V1::CustomEmojisController < Api::BaseController
- respond_to :json
-
skip_before_action :set_cache_headers
def index
diff --git a/app/controllers/api/v1/domain_blocks_controller.rb b/app/controllers/api/v1/domain_blocks_controller.rb
index af9e7a20f..5bb02d834 100644
--- a/app/controllers/api/v1/domain_blocks_controller.rb
+++ b/app/controllers/api/v1/domain_blocks_controller.rb
@@ -8,8 +8,6 @@ class Api::V1::DomainBlocksController < Api::BaseController
before_action :require_user!
after_action :insert_pagination_headers, only: :show
- respond_to :json
-
def show
@blocks = load_domain_blocks
render json: @blocks.map(&:domain)
diff --git a/app/controllers/api/v1/endorsements_controller.rb b/app/controllers/api/v1/endorsements_controller.rb
index 2770c7aef..c87dbc4ce 100644
--- a/app/controllers/api/v1/endorsements_controller.rb
+++ b/app/controllers/api/v1/endorsements_controller.rb
@@ -5,8 +5,6 @@ class Api::V1::EndorsementsController < Api::BaseController
before_action :require_user!
after_action :insert_pagination_headers
- respond_to :json
-
def index
@accounts = load_accounts
render json: @accounts, each_serializer: REST::AccountSerializer
diff --git a/app/controllers/api/v1/favourites_controller.rb b/app/controllers/api/v1/favourites_controller.rb
index db827f9d4..3e242905d 100644
--- a/app/controllers/api/v1/favourites_controller.rb
+++ b/app/controllers/api/v1/favourites_controller.rb
@@ -5,8 +5,6 @@ class Api::V1::FavouritesController < Api::BaseController
before_action :require_user!
after_action :insert_pagination_headers
- respond_to :json
-
def index
@statuses = load_statuses
render json: @statuses, each_serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new(@statuses, current_user&.account_id)
diff --git a/app/controllers/api/v1/featured_tags/suggestions_controller.rb b/app/controllers/api/v1/featured_tags/suggestions_controller.rb
index fb27ef88b..8c1b81a0f 100644
--- a/app/controllers/api/v1/featured_tags/suggestions_controller.rb
+++ b/app/controllers/api/v1/featured_tags/suggestions_controller.rb
@@ -2,12 +2,9 @@
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
- respond_to :json
-
def index
render json: @most_used_tags, each_serializer: REST::TagSerializer
end
diff --git a/app/controllers/api/v1/filters_controller.rb b/app/controllers/api/v1/filters_controller.rb
index e5ebaff4d..b0ace3af0 100644
--- a/app/controllers/api/v1/filters_controller.rb
+++ b/app/controllers/api/v1/filters_controller.rb
@@ -7,8 +7,6 @@ class Api::V1::FiltersController < Api::BaseController
before_action :set_filters, only: :index
before_action :set_filter, only: [:show, :update, :destroy]
- respond_to :json
-
def index
render json: @filters, each_serializer: REST::FilterSerializer
end
diff --git a/app/controllers/api/v1/instances/activity_controller.rb b/app/controllers/api/v1/instances/activity_controller.rb
index b30e8464c..4f6b4bcbf 100644
--- a/app/controllers/api/v1/instances/activity_controller.rb
+++ b/app/controllers/api/v1/instances/activity_controller.rb
@@ -6,8 +6,6 @@ class Api::V1::Instances::ActivityController < Api::BaseController
skip_before_action :set_cache_headers
skip_before_action :require_authenticated_user!, unless: :whitelist_mode?
- respond_to :json
-
def show
expires_in 1.day, public: true
render_with_cache json: :activity, expires_in: 1.day
diff --git a/app/controllers/api/v1/instances/peers_controller.rb b/app/controllers/api/v1/instances/peers_controller.rb
index cc00d8a6b..9fa440935 100644
--- a/app/controllers/api/v1/instances/peers_controller.rb
+++ b/app/controllers/api/v1/instances/peers_controller.rb
@@ -6,8 +6,6 @@ class Api::V1::Instances::PeersController < Api::BaseController
skip_before_action :set_cache_headers
skip_before_action :require_authenticated_user!, unless: :whitelist_mode?
- respond_to :json
-
def index
expires_in 1.day, public: true
render_with_cache(expires_in: 1.day) { Account.remote.domains }
diff --git a/app/controllers/api/v1/instances_controller.rb b/app/controllers/api/v1/instances_controller.rb
index c323b60b4..5b5058a7b 100644
--- a/app/controllers/api/v1/instances_controller.rb
+++ b/app/controllers/api/v1/instances_controller.rb
@@ -1,8 +1,6 @@
# frozen_string_literal: true
class Api::V1::InstancesController < Api::BaseController
- respond_to :json
-
skip_before_action :set_cache_headers
skip_before_action :require_authenticated_user!, unless: :whitelist_mode?
diff --git a/app/controllers/api/v1/media_controller.rb b/app/controllers/api/v1/media_controller.rb
index 81825db15..d87d7b946 100644
--- a/app/controllers/api/v1/media_controller.rb
+++ b/app/controllers/api/v1/media_controller.rb
@@ -4,8 +4,6 @@ class Api::V1::MediaController < Api::BaseController
before_action -> { doorkeeper_authorize! :write, :'write:media' }
before_action :require_user!
- respond_to :json
-
def create
@media = current_account.media_attachments.create!(media_params)
render json: @media, serializer: REST::MediaAttachmentSerializer
diff --git a/app/controllers/api/v1/mutes_controller.rb b/app/controllers/api/v1/mutes_controller.rb
index df6c8e86c..65439fe9b 100644
--- a/app/controllers/api/v1/mutes_controller.rb
+++ b/app/controllers/api/v1/mutes_controller.rb
@@ -5,8 +5,6 @@ class Api::V1::MutesController < Api::BaseController
before_action :require_user!
after_action :insert_pagination_headers
- respond_to :json
-
def index
@accounts = load_accounts
render json: @accounts, each_serializer: REST::AccountSerializer
diff --git a/app/controllers/api/v1/notifications_controller.rb b/app/controllers/api/v1/notifications_controller.rb
index bf3002e79..8ac227765 100644
--- a/app/controllers/api/v1/notifications_controller.rb
+++ b/app/controllers/api/v1/notifications_controller.rb
@@ -6,8 +6,6 @@ class Api::V1::NotificationsController < Api::BaseController
before_action :require_user!
after_action :insert_pagination_headers, only: :index
- respond_to :json
-
DEFAULT_NOTIFICATIONS_LIMIT = 15
def index
diff --git a/app/controllers/api/v1/polls/votes_controller.rb b/app/controllers/api/v1/polls/votes_controller.rb
index 3fa0b6a76..e1d26106a 100644
--- a/app/controllers/api/v1/polls/votes_controller.rb
+++ b/app/controllers/api/v1/polls/votes_controller.rb
@@ -7,8 +7,6 @@ class Api::V1::Polls::VotesController < Api::BaseController
before_action :require_user!
before_action :set_poll
- respond_to :json
-
def create
VoteService.new.call(current_account, @poll, vote_params[:choices])
render json: @poll, serializer: REST::PollSerializer
diff --git a/app/controllers/api/v1/polls_controller.rb b/app/controllers/api/v1/polls_controller.rb
index 031e6d42d..744baf7bb 100644
--- a/app/controllers/api/v1/polls_controller.rb
+++ b/app/controllers/api/v1/polls_controller.rb
@@ -7,8 +7,6 @@ class Api::V1::PollsController < Api::BaseController
before_action :set_poll
before_action :refresh_poll
- respond_to :json
-
def show
render json: @poll, serializer: REST::PollSerializer, include_results: true
end
diff --git a/app/controllers/api/v1/preferences_controller.rb b/app/controllers/api/v1/preferences_controller.rb
index 077d39f5d..1640a8224 100644
--- a/app/controllers/api/v1/preferences_controller.rb
+++ b/app/controllers/api/v1/preferences_controller.rb
@@ -4,8 +4,6 @@ class Api::V1::PreferencesController < Api::BaseController
before_action -> { doorkeeper_authorize! :read, :'read:accounts' }
before_action :require_user!
- respond_to :json
-
def index
render json: current_account, serializer: REST::PreferencesSerializer
end
diff --git a/app/controllers/api/v1/reports_controller.rb b/app/controllers/api/v1/reports_controller.rb
index 1b0b4b05b..66c40f6f4 100644
--- a/app/controllers/api/v1/reports_controller.rb
+++ b/app/controllers/api/v1/reports_controller.rb
@@ -4,8 +4,6 @@ class Api::V1::ReportsController < Api::BaseController
before_action -> { doorkeeper_authorize! :write, :'write:reports' }, only: [:create]
before_action :require_user!
- respond_to :json
-
def create
@report = ReportService.new.call(
current_account,
diff --git a/app/controllers/api/v1/statuses/bookmarks_controller.rb b/app/controllers/api/v1/statuses/bookmarks_controller.rb
index a7f1eed00..3954af3c9 100644
--- a/app/controllers/api/v1/statuses/bookmarks_controller.rb
+++ b/app/controllers/api/v1/statuses/bookmarks_controller.rb
@@ -7,8 +7,6 @@ class Api::V1::Statuses::BookmarksController < Api::BaseController
before_action :require_user!
before_action :set_status
- respond_to :json
-
def create
current_account.bookmarks.find_or_create_by!(account: current_account, status: @status)
render json: @status, serializer: REST::StatusSerializer
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 05f4acc33..8229786d6 100644
--- a/app/controllers/api/v1/statuses/favourited_by_accounts_controller.rb
+++ b/app/controllers/api/v1/statuses/favourited_by_accounts_controller.rb
@@ -7,8 +7,6 @@ class Api::V1::Statuses::FavouritedByAccountsController < Api::BaseController
before_action :set_status
after_action :insert_pagination_headers
- respond_to :json
-
def index
@accounts = load_accounts
render json: @accounts, each_serializer: REST::AccountSerializer
diff --git a/app/controllers/api/v1/statuses/favourites_controller.rb b/app/controllers/api/v1/statuses/favourites_controller.rb
index f18ace996..7afa822ed 100644
--- a/app/controllers/api/v1/statuses/favourites_controller.rb
+++ b/app/controllers/api/v1/statuses/favourites_controller.rb
@@ -7,8 +7,6 @@ class Api::V1::Statuses::FavouritesController < Api::BaseController
before_action :require_user!
before_action :set_status
- respond_to :json
-
def create
FavouriteService.new.call(current_account, @status)
render json: @status, serializer: REST::StatusSerializer
diff --git a/app/controllers/api/v1/statuses/mutes_controller.rb b/app/controllers/api/v1/statuses/mutes_controller.rb
index b02469b4f..43c7a525a 100644
--- a/app/controllers/api/v1/statuses/mutes_controller.rb
+++ b/app/controllers/api/v1/statuses/mutes_controller.rb
@@ -8,8 +8,6 @@ class Api::V1::Statuses::MutesController < Api::BaseController
before_action :set_status
before_action :set_conversation
- respond_to :json
-
def create
current_account.mute_conversation!(@conversation)
@mutes_map = { @conversation.id => true }
diff --git a/app/controllers/api/v1/statuses/pins_controller.rb b/app/controllers/api/v1/statuses/pins_controller.rb
index 4118a8ce4..51b1621b6 100644
--- a/app/controllers/api/v1/statuses/pins_controller.rb
+++ b/app/controllers/api/v1/statuses/pins_controller.rb
@@ -7,8 +7,6 @@ class Api::V1::Statuses::PinsController < Api::BaseController
before_action :require_user!
before_action :set_status
- respond_to :json
-
def create
StatusPin.create!(account: current_account, status: @status)
distribute_add_activity!
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 fa60e7d84..6c9e49d90 100644
--- a/app/controllers/api/v1/statuses/reblogged_by_accounts_controller.rb
+++ b/app/controllers/api/v1/statuses/reblogged_by_accounts_controller.rb
@@ -7,8 +7,6 @@ class Api::V1::Statuses::RebloggedByAccountsController < Api::BaseController
before_action :set_status
after_action :insert_pagination_headers
- respond_to :json
-
def index
@accounts = load_accounts
render json: @accounts, each_serializer: REST::AccountSerializer
diff --git a/app/controllers/api/v1/statuses/reblogs_controller.rb b/app/controllers/api/v1/statuses/reblogs_controller.rb
index 67106ccbe..7fa774a4d 100644
--- a/app/controllers/api/v1/statuses/reblogs_controller.rb
+++ b/app/controllers/api/v1/statuses/reblogs_controller.rb
@@ -7,10 +7,11 @@ class Api::V1::Statuses::ReblogsController < Api::BaseController
before_action :require_user!
before_action :set_reblog
- respond_to :json
+ override_rate_limit_headers :create, family: :statuses
def create
@status = ReblogService.new.call(current_account, @reblog, reblog_params)
+
render json: @status, serializer: REST::StatusSerializer
end
diff --git a/app/controllers/api/v1/statuses_controller.rb b/app/controllers/api/v1/statuses_controller.rb
index bba3c0651..2f55e95fd 100644
--- a/app/controllers/api/v1/statuses_controller.rb
+++ b/app/controllers/api/v1/statuses_controller.rb
@@ -8,7 +8,7 @@ class Api::V1::StatusesController < Api::BaseController
before_action :require_user!, except: [:show, :context]
before_action :set_status, only: [:show, :context]
- respond_to :json
+ override_rate_limit_headers :create, family: :statuses
# This API was originally unlimited, pagination cannot be introduced without
# breaking backwards-compatibility. Arbitrarily high number to cover most
@@ -44,7 +44,8 @@ class Api::V1::StatusesController < Api::BaseController
scheduled_at: status_params[:scheduled_at],
application: doorkeeper_token.application,
poll: status_params[:poll],
- idempotency: request.headers['Idempotency-Key'])
+ idempotency: request.headers['Idempotency-Key'],
+ with_rate_limit: true)
render json: @status, serializer: @status.is_a?(ScheduledStatus) ? REST::ScheduledStatusSerializer : REST::StatusSerializer
end
diff --git a/app/controllers/api/v1/streaming_controller.rb b/app/controllers/api/v1/streaming_controller.rb
index ebb17608c..7cd60615a 100644
--- a/app/controllers/api/v1/streaming_controller.rb
+++ b/app/controllers/api/v1/streaming_controller.rb
@@ -1,8 +1,6 @@
# frozen_string_literal: true
class Api::V1::StreamingController < Api::BaseController
- respond_to :json
-
def index
if Rails.configuration.x.streaming_api_base_url != request.host
redirect_to streaming_api_url, status: 301
diff --git a/app/controllers/api/v1/suggestions_controller.rb b/app/controllers/api/v1/suggestions_controller.rb
index 9da2b60ae..52054160d 100644
--- a/app/controllers/api/v1/suggestions_controller.rb
+++ b/app/controllers/api/v1/suggestions_controller.rb
@@ -7,8 +7,6 @@ class Api::V1::SuggestionsController < Api::BaseController
before_action :require_user!
before_action :set_accounts
- respond_to :json
-
def index
render json: @accounts, each_serializer: REST::AccountSerializer
end
diff --git a/app/controllers/api/v1/timelines/home_controller.rb b/app/controllers/api/v1/timelines/home_controller.rb
index ff5ede138..ae6dbcb8b 100644
--- a/app/controllers/api/v1/timelines/home_controller.rb
+++ b/app/controllers/api/v1/timelines/home_controller.rb
@@ -5,8 +5,6 @@ class Api::V1::Timelines::HomeController < Api::BaseController
before_action :require_user!, only: [:show]
after_action :insert_pagination_headers, unless: -> { @statuses.empty? }
- respond_to :json
-
def show
@statuses = load_statuses
diff --git a/app/controllers/api/v1/timelines/public_controller.rb b/app/controllers/api/v1/timelines/public_controller.rb
index ccc10f966..581befef1 100644
--- a/app/controllers/api/v1/timelines/public_controller.rb
+++ b/app/controllers/api/v1/timelines/public_controller.rb
@@ -4,8 +4,6 @@ class Api::V1::Timelines::PublicController < Api::BaseController
before_action :require_user!, only: [:show], if: :require_auth?
after_action :insert_pagination_headers, unless: -> { @statuses.empty? }
- respond_to :json
-
def show
@statuses = load_statuses
render json: @statuses, each_serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new(@statuses, current_user&.account_id)
diff --git a/app/controllers/api/v1/timelines/tag_controller.rb b/app/controllers/api/v1/timelines/tag_controller.rb
index 9adc4ad29..2d6ad5a80 100644
--- a/app/controllers/api/v1/timelines/tag_controller.rb
+++ b/app/controllers/api/v1/timelines/tag_controller.rb
@@ -4,8 +4,6 @@ class Api::V1::Timelines::TagController < Api::BaseController
before_action :load_tag
after_action :insert_pagination_headers, unless: -> { @statuses.empty? }
- respond_to :json
-
def show
@statuses = load_statuses
render json: @statuses, each_serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new(@statuses, current_user&.account_id)
diff --git a/app/controllers/api/v1/trends_controller.rb b/app/controllers/api/v1/trends_controller.rb
index bcea9857e..c875e9041 100644
--- a/app/controllers/api/v1/trends_controller.rb
+++ b/app/controllers/api/v1/trends_controller.rb
@@ -3,8 +3,6 @@
class Api::V1::TrendsController < Api::BaseController
before_action :set_tags
- respond_to :json
-
def index
render json: @tags, each_serializer: REST::TagSerializer
end
diff --git a/app/controllers/api/v2/search_controller.rb b/app/controllers/api/v2/search_controller.rb
index cbd9b551d..f17431dd1 100644
--- a/app/controllers/api/v2/search_controller.rb
+++ b/app/controllers/api/v2/search_controller.rb
@@ -8,8 +8,6 @@ class Api::V2::SearchController < Api::BaseController
before_action -> { doorkeeper_authorize! :read, :'read:search' }
before_action :require_user!
- respond_to :json
-
def index
@search = Search.new(search_results)
render json: @search, serializer: REST::SearchSerializer
diff --git a/app/controllers/api/web/embeds_controller.rb b/app/controllers/api/web/embeds_controller.rb
index 4aa31695c..741ba910f 100644
--- a/app/controllers/api/web/embeds_controller.rb
+++ b/app/controllers/api/web/embeds_controller.rb
@@ -1,8 +1,6 @@
# frozen_string_literal: true
class Api::Web::EmbedsController < Api::Web::BaseController
- respond_to :json
-
before_action :require_user!
def create
diff --git a/app/controllers/api/web/push_subscriptions_controller.rb b/app/controllers/api/web/push_subscriptions_controller.rb
index f388b17e5..7916b82fa 100644
--- a/app/controllers/api/web/push_subscriptions_controller.rb
+++ b/app/controllers/api/web/push_subscriptions_controller.rb
@@ -1,8 +1,6 @@
# frozen_string_literal: true
class Api::Web::PushSubscriptionsController < Api::Web::BaseController
- respond_to :json
-
before_action :require_user!
def create
diff --git a/app/controllers/api/web/settings_controller.rb b/app/controllers/api/web/settings_controller.rb
index e3178bf48..3d65e46ed 100644
--- a/app/controllers/api/web/settings_controller.rb
+++ b/app/controllers/api/web/settings_controller.rb
@@ -1,8 +1,6 @@
# frozen_string_literal: true
class Api::Web::SettingsController < Api::Web::BaseController
- respond_to :json
-
before_action :require_user!
def update
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index 0cfa2b386..973db6aca 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -29,6 +29,7 @@ class ApplicationController < ActionController::Base
rescue_from Mastodon::NotPermittedError, with: :forbidden
rescue_from HTTP::Error, OpenSSL::SSL::SSLError, with: :internal_server_error
rescue_from Mastodon::RaceConditionError, with: :service_unavailable
+ rescue_from Mastodon::RateLimitExceededError, with: :too_many_requests
before_action :store_current_location, except: :raise_not_found, unless: :devise_controller?
before_action :require_functional!, if: :user_signed_in?
@@ -111,6 +112,10 @@ class ApplicationController < ActionController::Base
respond_with_error(503)
end
+ def too_many_requests
+ respond_with_error(429)
+ end
+
def single_user_mode?
@single_user_mode ||= Rails.configuration.x.single_user_mode && Account.where('id > 0').exists?
end
diff --git a/app/controllers/authorize_interactions_controller.rb b/app/controllers/authorize_interactions_controller.rb
index e27366ea3..29c0288d0 100644
--- a/app/controllers/authorize_interactions_controller.rb
+++ b/app/controllers/authorize_interactions_controller.rb
@@ -20,7 +20,7 @@ class AuthorizeInteractionsController < ApplicationController
end
def create
- if @resource.is_a?(Account) && FollowService.new.call(current_account, @resource)
+ if @resource.is_a?(Account) && FollowService.new.call(current_account, @resource, with_rate_limit: true)
render :success
else
render :error
diff --git a/app/controllers/concerns/rate_limit_headers.rb b/app/controllers/concerns/rate_limit_headers.rb
index b79c558d8..86fe58a71 100644
--- a/app/controllers/concerns/rate_limit_headers.rb
+++ b/app/controllers/concerns/rate_limit_headers.rb
@@ -3,6 +3,20 @@
module RateLimitHeaders
extend ActiveSupport::Concern
+ class_methods do
+ def override_rate_limit_headers(method_name, options = {})
+ around_action(only: method_name, if: :current_account) do |_controller, block|
+ begin
+ block.call
+ ensure
+ rate_limiter = RateLimiter.new(current_account, options)
+ rate_limit_headers = rate_limiter.to_headers
+ response.headers.merge!(rate_limit_headers) unless response.headers['X-RateLimit-Remaining'].present? && rate_limit_headers['X-RateLimit-Remaining'].to_i > response.headers['X-RateLimit-Remaining'].to_i
+ end
+ end
+ end
+ end
+
included do
before_action :set_rate_limit_headers, if: :rate_limited_request?
end
@@ -44,7 +58,7 @@ module RateLimitHeaders
end
def api_throttle_data
- most_limited_type, = request.env['rack.attack.throttle_data'].min_by { |_, v| v[:limit] }
+ most_limited_type, = request.env['rack.attack.throttle_data'].min_by { |_, v| v[:limit] - v[:count] }
request.env['rack.attack.throttle_data'][most_limited_type]
end
diff --git a/app/helpers/admin/settings_helper.rb b/app/helpers/admin/settings_helper.rb
new file mode 100644
index 000000000..baf14ab25
--- /dev/null
+++ b/app/helpers/admin/settings_helper.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+module Admin::SettingsHelper
+ def site_upload_delete_hint(hint, var)
+ upload = SiteUpload.find_by(var: var.to_s)
+ return hint unless upload
+
+ link = link_to t('admin.site_uploads.delete'), admin_site_upload_path(upload), data: { method: :delete }
+ safe_join([hint, link], '
'.html_safe)
+ end
+end
diff --git a/app/javascript/mastodon/components/media_gallery.js b/app/javascript/mastodon/components/media_gallery.js
index cfe164a50..283d7e0a5 100644
--- a/app/javascript/mastodon/components/media_gallery.js
+++ b/app/javascript/mastodon/components/media_gallery.js
@@ -10,7 +10,7 @@ import { autoPlayGif, cropImages, displayMedia, useBlurhash } from '../initial_s
import { decode } from 'blurhash';
const messages = defineMessages({
- toggle_visible: { id: 'media_gallery.toggle_visible', defaultMessage: 'Toggle visibility' },
+ toggle_visible: { id: 'media_gallery.toggle_visible', defaultMessage: 'Hide media' },
});
class Item extends React.PureComponent {
diff --git a/app/javascript/mastodon/components/status_action_bar.js b/app/javascript/mastodon/components/status_action_bar.js
index 7f9c17293..bebbbcb5a 100644
--- a/app/javascript/mastodon/components/status_action_bar.js
+++ b/app/javascript/mastodon/components/status_action_bar.js
@@ -6,54 +6,49 @@ import IconButton from './icon_button';
import DropdownMenuContainer from '../containers/dropdown_menu_container';
import { defineMessages, injectIntl } from 'react-intl';
import ImmutablePureComponent from 'react-immutable-pure-component';
-import { isStaff, me } from '../initial_state';
+import { me, isStaff } from '../initial_state';
const messages = defineMessages({
- delete : { id: 'status.delete', defaultMessage: 'Delete' },
- redraft : { id: 'status.redraft', defaultMessage: 'Delete & re-draft' },
- direct : { id: 'status.direct', defaultMessage: 'Direct message @{name}' },
- mention : { id: 'status.mention', defaultMessage: 'Mention @{name}' },
- mute : { id: 'account.mute', defaultMessage: 'Mute @{name}' },
- block : { id: 'account.block', defaultMessage: 'Block @{name}' },
- reply : { id: 'status.reply', defaultMessage: 'Reply' },
- share : { id: 'status.share', defaultMessage: 'Share' },
- more : { id: 'status.more', defaultMessage: 'More' },
- replyAll : { id: 'status.replyAll', defaultMessage: 'Reply to thread' },
- reblog : { id: 'status.reblog', defaultMessage: 'Boost' },
- reblog_private : { id: 'status.reblog_private', defaultMessage: 'Boost to original audience' },
+ delete: { id: 'status.delete', defaultMessage: 'Delete' },
+ redraft: { id: 'status.redraft', defaultMessage: 'Delete & re-draft' },
+ direct: { id: 'status.direct', defaultMessage: 'Direct message @{name}' },
+ mention: { id: 'status.mention', defaultMessage: 'Mention @{name}' },
+ mute: { id: 'account.mute', defaultMessage: 'Mute @{name}' },
+ block: { id: 'account.block', defaultMessage: 'Block @{name}' },
+ reply: { id: 'status.reply', defaultMessage: 'Reply' },
+ share: { id: 'status.share', defaultMessage: 'Share' },
+ more: { id: 'status.more', defaultMessage: 'More' },
+ replyAll: { id: 'status.replyAll', defaultMessage: 'Reply to thread' },
+ reblog: { id: 'status.reblog', defaultMessage: 'Boost' },
+ reblog_private: { id: 'status.reblog_private', defaultMessage: 'Boost to original audience' },
cancel_reblog_private: { id: 'status.cancel_reblog_private', defaultMessage: 'Unboost' },
- cannot_reblog : { id: 'status.cannot_reblog', defaultMessage: 'This post cannot be boosted' },
- favourite : { id: 'status.favourite', defaultMessage: 'Favourite' },
- bookmark : { id: 'status.bookmark', defaultMessage: 'Bookmark' },
- removeBookmark : { id: 'status.remove_bookmark', defaultMessage: 'Remove bookmark' },
- open : { id: 'status.open', defaultMessage: 'Expand this status' },
- report : { id: 'status.report', defaultMessage: 'Report @{name}' },
- muteConversation : { id: 'status.mute_conversation', defaultMessage: 'Mute conversation' },
- unmuteConversation : { id: 'status.unmute_conversation', defaultMessage: 'Unmute conversation' },
- pin : { id: 'status.pin', defaultMessage: 'Pin on profile' },
- unpin : { id: 'status.unpin', defaultMessage: 'Unpin from profile' },
- embed : { id: 'status.embed', defaultMessage: 'Embed' },
- admin_account : { id: 'status.admin_account', defaultMessage: 'Open moderation interface for @{name}' },
- admin_status : { id: 'status.admin_status', defaultMessage: 'Open this status in the moderation interface' },
- copy : { id: 'status.copy', defaultMessage: 'Copy link to status' },
- blockDomain : { id: 'account.block_domain', defaultMessage: 'Hide everything from {domain}' },
- unblockDomain : { id: 'account.unblock_domain', defaultMessage: 'Unhide {domain}' },
- unmute : { id: 'account.unmute', defaultMessage: 'Unmute @{name}' },
- unblock : { id: 'account.unblock', defaultMessage: 'Unblock @{name}' },
+ cannot_reblog: { id: 'status.cannot_reblog', defaultMessage: 'This post cannot be boosted' },
+ favourite: { id: 'status.favourite', defaultMessage: 'Favourite' },
+ bookmark: { id: 'status.bookmark', defaultMessage: 'Bookmark' },
+ removeBookmark: { id: 'status.remove_bookmark', defaultMessage: 'Remove bookmark' },
+ open: { id: 'status.open', defaultMessage: 'Expand this status' },
+ report: { id: 'status.report', defaultMessage: 'Report @{name}' },
+ muteConversation: { id: 'status.mute_conversation', defaultMessage: 'Mute conversation' },
+ unmuteConversation: { id: 'status.unmute_conversation', defaultMessage: 'Unmute conversation' },
+ pin: { id: 'status.pin', defaultMessage: 'Pin on profile' },
+ unpin: { id: 'status.unpin', defaultMessage: 'Unpin from profile' },
+ embed: { id: 'status.embed', defaultMessage: 'Embed' },
+ admin_account: { id: 'status.admin_account', defaultMessage: 'Open moderation interface for @{name}' },
+ admin_status: { id: 'status.admin_status', defaultMessage: 'Open this status in the moderation interface' },
+ copy: { id: 'status.copy', defaultMessage: 'Copy link to status' },
+ blockDomain: { id: 'account.block_domain', defaultMessage: 'Block domain {domain}' },
+ unblockDomain: { id: 'account.unblock_domain', defaultMessage: 'Unblock domain {domain}' },
+ unmute: { id: 'account.unmute', defaultMessage: 'Unmute @{name}' },
+ unblock: { id: 'account.unblock', defaultMessage: 'Unblock @{name}' },
});
-const ObfuscateCountReplies = false;
-const obfuscatedCount = count => {
- if (ObfuscateCountReplies) {
- if (count < 0) {
- return 0;
- } else if (count <= 1) {
- return count;
- } else {
- return '1+';
- }
- } else {
+const obfuscatedCount = count => {
+ if (count < 0) {
+ return 0;
+ } else if (count <= 1) {
return count;
+ } else {
+ return '1+';
}
};
@@ -70,28 +65,27 @@ class StatusActionBar extends ImmutablePureComponent {
};
static propTypes = {
- status : ImmutablePropTypes.map.isRequired,
- relationship : ImmutablePropTypes.map,
- onReply : PropTypes.func,
- onFavourite : PropTypes.func,
- onReblog : PropTypes.func,
- onDelete : PropTypes.func,
- onDirect : PropTypes.func,
- onMention : PropTypes.func,
- onMute : PropTypes.func,
- onUnmute : PropTypes.func,
- onBlock : PropTypes.func,
- onUnblock : PropTypes.func,
- onBlockDomain : PropTypes.func,
- onUnblockDomain : PropTypes.func,
- onReport : PropTypes.func,
- onEmbed : PropTypes.func,
+ status: ImmutablePropTypes.map.isRequired,
+ relationship: ImmutablePropTypes.map,
+ onReply: PropTypes.func,
+ onFavourite: PropTypes.func,
+ onReblog: PropTypes.func,
+ onDelete: PropTypes.func,
+ onDirect: PropTypes.func,
+ onMention: PropTypes.func,
+ onMute: PropTypes.func,
+ onUnmute: PropTypes.func,
+ onBlock: PropTypes.func,
+ onUnblock: PropTypes.func,
+ onBlockDomain: PropTypes.func,
+ onUnblockDomain: PropTypes.func,
+ onReport: PropTypes.func,
+ onEmbed: PropTypes.func,
onMuteConversation: PropTypes.func,
- onPin : PropTypes.func,
- onBookmark : PropTypes.func,
- withDismiss : PropTypes.bool,
- showReplyFormUnder: PropTypes.bool,
- intl : PropTypes.object.isRequired,
+ onPin: PropTypes.func,
+ onBookmark: PropTypes.func,
+ withDismiss: PropTypes.bool,
+ intl: PropTypes.object.isRequired,
};
// Avoid checking props that are functions (and whose equality will always
@@ -100,7 +94,7 @@ class StatusActionBar extends ImmutablePureComponent {
'status',
'relationship',
'withDismiss',
- ];
+ ]
handleReplyClick = () => {
if (me) {
@@ -108,20 +102,16 @@ class StatusActionBar extends ImmutablePureComponent {
} else {
this._openInteractionDialog('reply');
}
- };
- handleReplyUnderClick = () => {
- console.info('hop show');
- this.handleReplyClick();
- };
+ }
handleShareClick = () => {
navigator.share({
text: this.props.status.get('search_index'),
- url : this.props.status.get('url'),
+ url: this.props.status.get('url'),
}).catch((e) => {
if (e.name !== 'AbortError') console.error(e);
});
- };
+ }
handleFavouriteClick = () => {
if (me) {
@@ -129,7 +119,7 @@ class StatusActionBar extends ImmutablePureComponent {
} else {
this._openInteractionDialog('favourite');
}
- };
+ }
handleReblogClick = e => {
if (me) {
@@ -137,35 +127,35 @@ class StatusActionBar extends ImmutablePureComponent {
} else {
this._openInteractionDialog('reblog');
}
- };
+ }
_openInteractionDialog = type => {
window.open(`/interact/${this.props.status.get('id')}?type=${type}`, 'mastodon-intent', 'width=445,height=600,resizable=no,menubar=no,status=no,scrollbars=yes');
- };
+ }
handleBookmarkClick = () => {
this.props.onBookmark(this.props.status);
- };
+ }
handleDeleteClick = () => {
this.props.onDelete(this.props.status, this.context.router.history);
- };
+ }
handleRedraftClick = () => {
this.props.onDelete(this.props.status, this.context.router.history, true);
- };
+ }
handlePinClick = () => {
this.props.onPin(this.props.status);
- };
+ }
handleMentionClick = () => {
this.props.onMention(this.props.status.get('account'), this.context.router.history);
- };
+ }
handleDirectClick = () => {
this.props.onDirect(this.props.status.get('account'), this.context.router.history);
- };
+ }
handleMuteClick = () => {
const { status, relationship, onMute, onUnmute } = this.props;
@@ -176,7 +166,7 @@ class StatusActionBar extends ImmutablePureComponent {
} else {
onMute(account);
}
- };
+ }
handleBlockClick = () => {
const { status, relationship, onBlock, onUnblock } = this.props;
@@ -187,43 +177,43 @@ class StatusActionBar extends ImmutablePureComponent {
} else {
onBlock(status);
}
- };
+ }
handleBlockDomain = () => {
const { status, onBlockDomain } = this.props;
const account = status.get('account');
onBlockDomain(account.get('acct').split('@')[1]);
- };
+ }
handleUnblockDomain = () => {
const { status, onUnblockDomain } = this.props;
const account = status.get('account');
onUnblockDomain(account.get('acct').split('@')[1]);
- };
+ }
handleOpen = () => {
this.context.router.history.push(`/statuses/${this.props.status.get('id')}`);
- };
+ }
handleEmbed = () => {
this.props.onEmbed(this.props.status);
- };
+ }
handleReport = () => {
this.props.onReport(this.props.status);
- };
+ }
handleConversationMuteClick = () => {
this.props.onMuteConversation(this.props.status);
- };
+ }
handleCopy = () => {
- const url = this.props.status.get('url');
+ const url = this.props.status.get('url');
const textarea = document.createElement('textarea');
- textarea.textContent = url;
+ textarea.textContent = url;
textarea.style.position = 'fixed';
document.body.appendChild(textarea);
@@ -236,16 +226,15 @@ class StatusActionBar extends ImmutablePureComponent {
} finally {
document.body.removeChild(textarea);
}
- };
+ }
- render() {
+ render () {
const { status, relationship, intl, withDismiss } = this.props;
- console.log('this.props', this.props);
const mutingConversation = status.get('muted');
- const anonymousAccess = !me;
- const publicStatus = ['public', 'unlisted'].includes(status.get('visibility'));
- const account = status.get('account');
+ const anonymousAccess = !me;
+ const publicStatus = ['public', 'unlisted'].includes(status.get('visibility'));
+ const account = status.get('account');
let menu = [];
let reblogIcon = 'retweet';
@@ -259,76 +248,43 @@ class StatusActionBar extends ImmutablePureComponent {
menu.push({ text: intl.formatMessage(messages.embed), action: this.handleEmbed });
}
- menu.push({
- text : intl.formatMessage(status.get('bookmarked') ? messages.removeBookmark : messages.bookmark),
- action: this.handleBookmarkClick,
- });
+ menu.push({ text: intl.formatMessage(status.get('bookmarked') ? messages.removeBookmark : messages.bookmark), action: this.handleBookmarkClick });
menu.push(null);
if (status.getIn(['account', 'id']) === me || withDismiss) {
- menu.push({
- text : intl.formatMessage(mutingConversation ? messages.unmuteConversation : messages.muteConversation),
- action: this.handleConversationMuteClick,
- });
+ menu.push({ text: intl.formatMessage(mutingConversation ? messages.unmuteConversation : messages.muteConversation), action: this.handleConversationMuteClick });
menu.push(null);
}
if (status.getIn(['account', 'id']) === me) {
if (publicStatus) {
- menu.push({
- text : intl.formatMessage(status.get('pinned') ? messages.unpin : messages.pin),
- action: this.handlePinClick,
- });
+ menu.push({ text: intl.formatMessage(status.get('pinned') ? messages.unpin : messages.pin), action: this.handlePinClick });
} else {
if (status.get('visibility') === 'private') {
- menu.push({
- text : intl.formatMessage(status.get('reblogged') ? messages.cancel_reblog_private : messages.reblog_private),
- action: this.handleReblogClick,
- });
+ menu.push({ text: intl.formatMessage(status.get('reblogged') ? messages.cancel_reblog_private : messages.reblog_private), action: this.handleReblogClick });
}
}
menu.push({ text: intl.formatMessage(messages.delete), action: this.handleDeleteClick });
menu.push({ text: intl.formatMessage(messages.redraft), action: this.handleRedraftClick });
} else {
- menu.push({
- text : intl.formatMessage(messages.mention, { name: account.get('username') }),
- action: this.handleMentionClick,
- });
- menu.push({
- text : intl.formatMessage(messages.direct, { name: account.get('username') }),
- action: this.handleDirectClick,
- });
+ menu.push({ text: intl.formatMessage(messages.mention, { name: account.get('username') }), action: this.handleMentionClick });
+ menu.push({ text: intl.formatMessage(messages.direct, { name: account.get('username') }), action: this.handleDirectClick });
menu.push(null);
if (relationship && relationship.get('muting')) {
- menu.push({
- text : intl.formatMessage(messages.unmute, { name: account.get('username') }),
- action: this.handleMuteClick,
- });
+ menu.push({ text: intl.formatMessage(messages.unmute, { name: account.get('username') }), action: this.handleMuteClick });
} else {
- menu.push({
- text : intl.formatMessage(messages.mute, { name: account.get('username') }),
- action: this.handleMuteClick,
- });
+ menu.push({ text: intl.formatMessage(messages.mute, { name: account.get('username') }), action: this.handleMuteClick });
}
if (relationship && relationship.get('blocking')) {
- menu.push({
- text : intl.formatMessage(messages.unblock, { name: account.get('username') }),
- action: this.handleBlockClick,
- });
+ menu.push({ text: intl.formatMessage(messages.unblock, { name: account.get('username') }), action: this.handleBlockClick });
} else {
- menu.push({
- text : intl.formatMessage(messages.block, { name: account.get('username') }),
- action: this.handleBlockClick,
- });
+ menu.push({ text: intl.formatMessage(messages.block, { name: account.get('username') }), action: this.handleBlockClick });
}
- menu.push({
- text : intl.formatMessage(messages.report, { name: account.get('username') }),
- action: this.handleReport,
- });
+ menu.push({ text: intl.formatMessage(messages.report, { name: account.get('username') }), action: this.handleReport });
if (account.get('acct') !== account.get('username')) {
const domain = account.get('acct').split('@')[1];
@@ -344,14 +300,8 @@ class StatusActionBar extends ImmutablePureComponent {
if (isStaff) {
menu.push(null);
- menu.push({
- text: intl.formatMessage(messages.admin_account, { name: account.get('username') }),
- href: `/admin/accounts/${status.getIn(['account', 'id'])}`,
- });
- menu.push({
- text: intl.formatMessage(messages.admin_status),
- href: `/admin/accounts/${status.getIn(['account', 'id'])}/statuses/${status.get('id')}`,
- });
+ menu.push({ text: intl.formatMessage(messages.admin_account, { name: account.get('username') }), href: `/admin/accounts/${status.getIn(['account', 'id'])}` });
+ menu.push({ text: intl.formatMessage(messages.admin_status), href: `/admin/accounts/${status.getIn(['account', 'id'])}/statuses/${status.get('id')}` });
}
}
@@ -369,73 +319,21 @@ class StatusActionBar extends ImmutablePureComponent {
replyTitle = intl.formatMessage(messages.replyAll);
}
- const shareButton = ('share' in navigator) && status.get('visibility') === 'public' && (
-