diff --git a/app/controllers/api/base_controller.rb b/app/controllers/api/base_controller.rb
index 98fa1897e..bf7deac5c 100644
--- a/app/controllers/api/base_controller.rb
+++ b/app/controllers/api/base_controller.rb
@@ -8,6 +8,7 @@ class Api::BaseController < ApplicationController
include Api::AccessTokenTrackingConcern
include Api::CachingConcern
include Api::ContentSecurityPolicy
+ include Api::ErrorHandling
skip_before_action :require_functional!, unless: :limited_federation_mode?
@@ -18,51 +19,6 @@ class Api::BaseController < ApplicationController
protect_from_forgery with: :null_session
- rescue_from ActiveRecord::RecordInvalid, Mastodon::ValidationError do |e|
- render json: { error: e.to_s }, status: 422
- end
-
- rescue_from ActiveRecord::RecordNotUnique do
- render json: { error: 'Duplicate record' }, status: 422
- end
-
- rescue_from Date::Error do
- render json: { error: 'Invalid date supplied' }, status: 422
- end
-
- rescue_from ActiveRecord::RecordNotFound do
- render json: { error: 'Record not found' }, status: 404
- end
-
- rescue_from HTTP::Error, Mastodon::UnexpectedResponseError do
- render json: { error: 'Remote data could not be fetched' }, status: 503
- end
-
- rescue_from OpenSSL::SSL::SSLError do
- render json: { error: 'Remote SSL certificate could not be verified' }, status: 503
- end
-
- rescue_from Mastodon::NotPermittedError do
- render json: { error: 'This action is not allowed' }, status: 403
- end
-
- rescue_from Seahorse::Client::NetworkingError do |e|
- Rails.logger.warn "Storage server error: #{e}"
- render json: { error: 'There was a temporary problem serving your request, please try again' }, status: 503
- end
-
- rescue_from Mastodon::RaceConditionError, Stoplight::Error::RedLight do
- 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, Mastodon::InvalidParameterError do |e|
- render json: { error: e.to_s }, status: 400
- end
-
def doorkeeper_unauthorized_render_options(error: nil)
{ json: { error: error.try(:description) || 'Not authorized' } }
end
@@ -73,6 +29,14 @@ class Api::BaseController < ApplicationController
protected
+ def pagination_max_id
+ pagination_collection.last.id
+ end
+
+ def pagination_since_id
+ pagination_collection.first.id
+ end
+
def set_pagination_headers(next_path = nil, prev_path = nil)
links = []
links << [next_path, [%w(rel next)]] if next_path
diff --git a/app/controllers/api/v1/accounts/statuses_controller.rb b/app/controllers/api/v1/accounts/statuses_controller.rb
index 6a994ff54..56d4e6909 100644
--- a/app/controllers/api/v1/accounts/statuses_controller.rb
+++ b/app/controllers/api/v1/accounts/statuses_controller.rb
@@ -51,11 +51,7 @@ class Api::V1::Accounts::StatusesController < Api::BaseController
@statuses.size == limit_param(DEFAULT_STATUSES_LIMIT)
end
- def pagination_max_id
- @statuses.last.id
- end
-
- def pagination_since_id
- @statuses.first.id
+ def pagination_collection
+ @statuses
end
end
diff --git a/app/controllers/api/v1/admin/accounts_controller.rb b/app/controllers/api/v1/admin/accounts_controller.rb
index ff9cae639..06cebffcb 100644
--- a/app/controllers/api/v1/admin/accounts_controller.rb
+++ b/app/controllers/api/v1/admin/accounts_controller.rb
@@ -137,12 +137,8 @@ class Api::V1::Admin::AccountsController < Api::BaseController
api_v1_admin_accounts_url(pagination_params(min_id: pagination_since_id)) unless @accounts.empty?
end
- def pagination_max_id
- @accounts.last.id
- end
-
- def pagination_since_id
- @accounts.first.id
+ def pagination_collection
+ @accounts
end
def records_continue?
diff --git a/app/controllers/api/v1/admin/canonical_email_blocks_controller.rb b/app/controllers/api/v1/admin/canonical_email_blocks_controller.rb
index 7b192b979..f81e480bd 100644
--- a/app/controllers/api/v1/admin/canonical_email_blocks_controller.rb
+++ b/app/controllers/api/v1/admin/canonical_email_blocks_controller.rb
@@ -77,12 +77,8 @@ class Api::V1::Admin::CanonicalEmailBlocksController < Api::BaseController
api_v1_admin_canonical_email_blocks_url(pagination_params(min_id: pagination_since_id)) unless @canonical_email_blocks.empty?
end
- def pagination_max_id
- @canonical_email_blocks.last.id
- end
-
- def pagination_since_id
- @canonical_email_blocks.first.id
+ def pagination_collection
+ @canonical_email_blocks
end
def records_continue?
diff --git a/app/controllers/api/v1/admin/domain_allows_controller.rb b/app/controllers/api/v1/admin/domain_allows_controller.rb
index dd54d6710..184129284 100644
--- a/app/controllers/api/v1/admin/domain_allows_controller.rb
+++ b/app/controllers/api/v1/admin/domain_allows_controller.rb
@@ -73,12 +73,8 @@ class Api::V1::Admin::DomainAllowsController < Api::BaseController
api_v1_admin_domain_allows_url(pagination_params(min_id: pagination_since_id)) unless @domain_allows.empty?
end
- def pagination_max_id
- @domain_allows.last.id
- end
-
- def pagination_since_id
- @domain_allows.first.id
+ def pagination_collection
+ @domain_allows
end
def records_continue?
diff --git a/app/controllers/api/v1/admin/domain_blocks_controller.rb b/app/controllers/api/v1/admin/domain_blocks_controller.rb
index 2538c7c7c..8cd90b7c5 100644
--- a/app/controllers/api/v1/admin/domain_blocks_controller.rb
+++ b/app/controllers/api/v1/admin/domain_blocks_controller.rb
@@ -84,12 +84,8 @@ class Api::V1::Admin::DomainBlocksController < Api::BaseController
api_v1_admin_domain_blocks_url(pagination_params(min_id: pagination_since_id)) unless @domain_blocks.empty?
end
- def pagination_max_id
- @domain_blocks.last.id
- end
-
- def pagination_since_id
- @domain_blocks.first.id
+ def pagination_collection
+ @domain_blocks
end
def records_continue?
diff --git a/app/controllers/api/v1/admin/email_domain_blocks_controller.rb b/app/controllers/api/v1/admin/email_domain_blocks_controller.rb
index df54b9f0a..34489e19b 100644
--- a/app/controllers/api/v1/admin/email_domain_blocks_controller.rb
+++ b/app/controllers/api/v1/admin/email_domain_blocks_controller.rb
@@ -70,12 +70,8 @@ class Api::V1::Admin::EmailDomainBlocksController < Api::BaseController
api_v1_admin_email_domain_blocks_url(pagination_params(min_id: pagination_since_id)) unless @email_domain_blocks.empty?
end
- def pagination_max_id
- @email_domain_blocks.last.id
- end
-
- def pagination_since_id
- @email_domain_blocks.first.id
+ def pagination_collection
+ @email_domain_blocks
end
def records_continue?
diff --git a/app/controllers/api/v1/admin/ip_blocks_controller.rb b/app/controllers/api/v1/admin/ip_blocks_controller.rb
index 61c191234..0f666476c 100644
--- a/app/controllers/api/v1/admin/ip_blocks_controller.rb
+++ b/app/controllers/api/v1/admin/ip_blocks_controller.rb
@@ -75,12 +75,8 @@ class Api::V1::Admin::IpBlocksController < Api::BaseController
api_v1_admin_ip_blocks_url(pagination_params(min_id: pagination_since_id)) unless @ip_blocks.empty?
end
- def pagination_max_id
- @ip_blocks.last.id
- end
-
- def pagination_since_id
- @ip_blocks.first.id
+ def pagination_collection
+ @ip_blocks
end
def records_continue?
diff --git a/app/controllers/api/v1/admin/reports_controller.rb b/app/controllers/api/v1/admin/reports_controller.rb
index 7129a5f6c..f0598aa81 100644
--- a/app/controllers/api/v1/admin/reports_controller.rb
+++ b/app/controllers/api/v1/admin/reports_controller.rb
@@ -101,12 +101,8 @@ class Api::V1::Admin::ReportsController < Api::BaseController
api_v1_admin_reports_url(pagination_params(min_id: pagination_since_id)) unless @reports.empty?
end
- def pagination_max_id
- @reports.last.id
- end
-
- def pagination_since_id
- @reports.first.id
+ def pagination_collection
+ @reports
end
def records_continue?
diff --git a/app/controllers/api/v1/admin/tags_controller.rb b/app/controllers/api/v1/admin/tags_controller.rb
index 6a7c9f5bf..989e7e610 100644
--- a/app/controllers/api/v1/admin/tags_controller.rb
+++ b/app/controllers/api/v1/admin/tags_controller.rb
@@ -56,12 +56,8 @@ class Api::V1::Admin::TagsController < Api::BaseController
api_v1_admin_tags_url(pagination_params(min_id: pagination_since_id)) unless @tags.empty?
end
- def pagination_max_id
- @tags.last.id
- end
-
- def pagination_since_id
- @tags.first.id
+ def pagination_collection
+ @tags
end
def records_continue?
diff --git a/app/controllers/api/v1/admin/trends/links/preview_card_providers_controller.rb b/app/controllers/api/v1/admin/trends/links/preview_card_providers_controller.rb
index 5d9fcc82c..7ab7e6bd0 100644
--- a/app/controllers/api/v1/admin/trends/links/preview_card_providers_controller.rb
+++ b/app/controllers/api/v1/admin/trends/links/preview_card_providers_controller.rb
@@ -54,12 +54,8 @@ class Api::V1::Admin::Trends::Links::PreviewCardProvidersController < Api::BaseC
api_v1_admin_trends_links_preview_card_providers_url(pagination_params(min_id: pagination_since_id)) unless @providers.empty?
end
- def pagination_max_id
- @providers.last.id
- end
-
- def pagination_since_id
- @providers.first.id
+ def pagination_collection
+ @providers
end
def records_continue?
diff --git a/app/controllers/api/v1/blocks_controller.rb b/app/controllers/api/v1/blocks_controller.rb
index 0934622f8..7826a3c68 100644
--- a/app/controllers/api/v1/blocks_controller.rb
+++ b/app/controllers/api/v1/blocks_controller.rb
@@ -40,12 +40,8 @@ class Api::V1::BlocksController < Api::BaseController
api_v1_blocks_url pagination_params(since_id: pagination_since_id) unless paginated_blocks.empty?
end
- def pagination_max_id
- paginated_blocks.last.id
- end
-
- def pagination_since_id
- paginated_blocks.first.id
+ def pagination_collection
+ paginated_blocks
end
def records_continue?
diff --git a/app/controllers/api/v1/bookmarks_controller.rb b/app/controllers/api/v1/bookmarks_controller.rb
index 498eb16f4..08d3cf834 100644
--- a/app/controllers/api/v1/bookmarks_controller.rb
+++ b/app/controllers/api/v1/bookmarks_controller.rb
@@ -43,12 +43,8 @@ class Api::V1::BookmarksController < Api::BaseController
api_v1_bookmarks_url pagination_params(min_id: pagination_since_id) unless results.empty?
end
- def pagination_max_id
- results.last.id
- end
-
- def pagination_since_id
- results.first.id
+ def pagination_collection
+ results
end
def records_continue?
diff --git a/app/controllers/api/v1/crypto/encrypted_messages_controller.rb b/app/controllers/api/v1/crypto/encrypted_messages_controller.rb
index 68cf4384f..c70ae46d1 100644
--- a/app/controllers/api/v1/crypto/encrypted_messages_controller.rb
+++ b/app/controllers/api/v1/crypto/encrypted_messages_controller.rb
@@ -41,12 +41,8 @@ class Api::V1::Crypto::EncryptedMessagesController < Api::BaseController
api_v1_crypto_encrypted_messages_url pagination_params(min_id: pagination_since_id) unless @encrypted_messages.empty?
end
- def pagination_max_id
- @encrypted_messages.last.id
- end
-
- def pagination_since_id
- @encrypted_messages.first.id
+ def pagination_collection
+ @encrypted_messages
end
def records_continue?
diff --git a/app/controllers/api/v1/domain_blocks_controller.rb b/app/controllers/api/v1/domain_blocks_controller.rb
index 34def3c44..5774c4d1c 100644
--- a/app/controllers/api/v1/domain_blocks_controller.rb
+++ b/app/controllers/api/v1/domain_blocks_controller.rb
@@ -50,12 +50,8 @@ class Api::V1::DomainBlocksController < Api::BaseController
api_v1_domain_blocks_url pagination_params(since_id: pagination_since_id) unless @blocks.empty?
end
- def pagination_max_id
- @blocks.last.id
- end
-
- def pagination_since_id
- @blocks.first.id
+ def pagination_collection
+ @blocks
end
def records_continue?
diff --git a/app/controllers/api/v1/endorsements_controller.rb b/app/controllers/api/v1/endorsements_controller.rb
index 2216a9860..449a9ac24 100644
--- a/app/controllers/api/v1/endorsements_controller.rb
+++ b/app/controllers/api/v1/endorsements_controller.rb
@@ -44,12 +44,8 @@ class Api::V1::EndorsementsController < Api::BaseController
api_v1_endorsements_url pagination_params(since_id: pagination_since_id) unless @accounts.empty?
end
- def pagination_max_id
- @accounts.last.id
- end
-
- def pagination_since_id
- @accounts.first.id
+ def pagination_collection
+ @accounts
end
def records_continue?
diff --git a/app/controllers/api/v1/favourites_controller.rb b/app/controllers/api/v1/favourites_controller.rb
index faf1bda96..85e46b116 100644
--- a/app/controllers/api/v1/favourites_controller.rb
+++ b/app/controllers/api/v1/favourites_controller.rb
@@ -43,12 +43,8 @@ class Api::V1::FavouritesController < Api::BaseController
api_v1_favourites_url pagination_params(min_id: pagination_since_id) unless results.empty?
end
- def pagination_max_id
- results.last.id
- end
-
- def pagination_since_id
- results.first.id
+ def pagination_collection
+ results
end
def records_continue?
diff --git a/app/controllers/api/v1/followed_tags_controller.rb b/app/controllers/api/v1/followed_tags_controller.rb
index eae2bdc01..0ea4a95ef 100644
--- a/app/controllers/api/v1/followed_tags_controller.rb
+++ b/app/controllers/api/v1/followed_tags_controller.rb
@@ -34,12 +34,8 @@ class Api::V1::FollowedTagsController < Api::BaseController
api_v1_followed_tags_url pagination_params(since_id: pagination_since_id) unless @results.empty?
end
- def pagination_max_id
- @results.last.id
- end
-
- def pagination_since_id
- @results.first.id
+ def pagination_collection
+ @results
end
def records_continue?
diff --git a/app/controllers/api/v1/lists/accounts_controller.rb b/app/controllers/api/v1/lists/accounts_controller.rb
index 0604ad60f..5ae74bf04 100644
--- a/app/controllers/api/v1/lists/accounts_controller.rb
+++ b/app/controllers/api/v1/lists/accounts_controller.rb
@@ -71,12 +71,8 @@ class Api::V1::Lists::AccountsController < Api::BaseController
api_v1_list_accounts_url pagination_params(since_id: pagination_since_id) unless @accounts.empty?
end
- def pagination_max_id
- @accounts.last.id
- end
-
- def pagination_since_id
- @accounts.first.id
+ def pagination_collection
+ @accounts
end
def records_continue?
diff --git a/app/controllers/api/v1/mutes_controller.rb b/app/controllers/api/v1/mutes_controller.rb
index 2fb685ac3..9542d9611 100644
--- a/app/controllers/api/v1/mutes_controller.rb
+++ b/app/controllers/api/v1/mutes_controller.rb
@@ -40,12 +40,8 @@ class Api::V1::MutesController < Api::BaseController
api_v1_mutes_url pagination_params(since_id: pagination_since_id) unless paginated_mutes.empty?
end
- def pagination_max_id
- paginated_mutes.last.id
- end
-
- def pagination_since_id
- paginated_mutes.first.id
+ def pagination_collection
+ paginated_mutes
end
def records_continue?
diff --git a/app/controllers/api/v1/notifications_controller.rb b/app/controllers/api/v1/notifications_controller.rb
index 52280ef60..777740751 100644
--- a/app/controllers/api/v1/notifications_controller.rb
+++ b/app/controllers/api/v1/notifications_controller.rb
@@ -70,12 +70,8 @@ class Api::V1::NotificationsController < Api::BaseController
api_v1_notifications_url pagination_params(min_id: pagination_since_id) unless @notifications.empty?
end
- def pagination_max_id
- @notifications.last.id
- end
-
- def pagination_since_id
- @notifications.first.id
+ def pagination_collection
+ @notifications
end
def browserable_params
diff --git a/app/controllers/api/v1/scheduled_statuses_controller.rb b/app/controllers/api/v1/scheduled_statuses_controller.rb
index 2220b6d22..f6c070383 100644
--- a/app/controllers/api/v1/scheduled_statuses_controller.rb
+++ b/app/controllers/api/v1/scheduled_statuses_controller.rb
@@ -63,11 +63,7 @@ class Api::V1::ScheduledStatusesController < Api::BaseController
@statuses.size == limit_param(DEFAULT_STATUSES_LIMIT)
end
- def pagination_max_id
- @statuses.last.id
- end
-
- def pagination_since_id
- @statuses.first.id
+ def pagination_collection
+ @statuses
end
end
diff --git a/app/controllers/api/v1/timelines/base_controller.rb b/app/controllers/api/v1/timelines/base_controller.rb
index 173e173cc..7735cf1dc 100644
--- a/app/controllers/api/v1/timelines/base_controller.rb
+++ b/app/controllers/api/v1/timelines/base_controller.rb
@@ -9,12 +9,8 @@ class Api::V1::Timelines::BaseController < Api::BaseController
set_pagination_headers(next_path, prev_path)
end
- def pagination_max_id
- @statuses.last.id
- end
-
- def pagination_since_id
- @statuses.first.id
+ def pagination_collection
+ @statuses
end
def next_path_params
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index a046ea19c..8ba10d64c 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -129,7 +129,7 @@ class ApplicationController < ActionController::Base
end
def single_user_mode?
- @single_user_mode ||= Rails.configuration.x.single_user_mode && Account.where('id > 0').exists?
+ @single_user_mode ||= Rails.configuration.x.single_user_mode && Account.without_internal.exists?
end
def use_seamless_external_login?
diff --git a/app/controllers/concerns/api/error_handling.rb b/app/controllers/concerns/api/error_handling.rb
new file mode 100644
index 000000000..ad559fe2d
--- /dev/null
+++ b/app/controllers/concerns/api/error_handling.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+
+module Api::ErrorHandling
+ extend ActiveSupport::Concern
+
+ included do
+ rescue_from ActiveRecord::RecordInvalid, Mastodon::ValidationError do |e|
+ render json: { error: e.to_s }, status: 422
+ end
+
+ rescue_from ActiveRecord::RecordNotUnique do
+ render json: { error: 'Duplicate record' }, status: 422
+ end
+
+ rescue_from Date::Error do
+ render json: { error: 'Invalid date supplied' }, status: 422
+ end
+
+ rescue_from ActiveRecord::RecordNotFound do
+ render json: { error: 'Record not found' }, status: 404
+ end
+
+ rescue_from HTTP::Error, Mastodon::UnexpectedResponseError do
+ render json: { error: 'Remote data could not be fetched' }, status: 503
+ end
+
+ rescue_from OpenSSL::SSL::SSLError do
+ render json: { error: 'Remote SSL certificate could not be verified' }, status: 503
+ end
+
+ rescue_from Mastodon::NotPermittedError do
+ render json: { error: 'This action is not allowed' }, status: 403
+ end
+
+ rescue_from Seahorse::Client::NetworkingError do |e|
+ Rails.logger.warn "Storage server error: #{e}"
+ render json: { error: 'There was a temporary problem serving your request, please try again' }, status: 503
+ end
+
+ rescue_from Mastodon::RaceConditionError, Stoplight::Error::RedLight do
+ 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, Mastodon::InvalidParameterError do |e|
+ render json: { error: e.to_s }, status: 400
+ end
+ end
+end
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index 4f7f66985..a4f92743c 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -213,7 +213,7 @@ module ApplicationHelper
state_params[:moved_to_account] = current_account.moved_to_account
end
- state_params[:owner] = Account.local.without_suspended.where('id > 0').first if single_user_mode?
+ state_params[:owner] = Account.local.without_suspended.without_internal.first if single_user_mode?
json = ActiveModelSerializers::SerializableResource.new(InitialStatePresenter.new(state_params), serializer: InitialStateSerializer).to_json
# rubocop:disable Rails/OutputSafety
diff --git a/app/javascript/mastodon/actions/notifications.js b/app/javascript/mastodon/actions/notifications.js
index 30b7601d5..b54cbe27b 100644
--- a/app/javascript/mastodon/actions/notifications.js
+++ b/app/javascript/mastodon/actions/notifications.js
@@ -552,7 +552,10 @@ export const fetchNotificationsForRequest = accountId => (dispatch, getState) =>
api(getState).get('/api/v1/notifications', { params }).then(response => {
const next = getLinks(response).refs.find(link => link.rel === 'next');
+ dispatch(importFetchedAccounts(response.data.map(item => item.account)));
dispatch(importFetchedStatuses(response.data.map(item => item.status).filter(status => !!status)));
+ dispatch(importFetchedAccounts(response.data.filter(item => item.report).map(item => item.report.target_account)));
+
dispatch(fetchNotificationsForRequestSuccess(response.data, next?.uri));
}).catch(err => {
dispatch(fetchNotificationsForRequestFail(err));
@@ -585,7 +588,10 @@ export const expandNotificationsForRequest = () => (dispatch, getState) => {
api(getState).get(url).then(response => {
const next = getLinks(response).refs.find(link => link.rel === 'next');
+ dispatch(importFetchedAccounts(response.data.map(item => item.account)));
dispatch(importFetchedStatuses(response.data.map(item => item.status).filter(status => !!status)));
+ dispatch(importFetchedAccounts(response.data.filter(item => item.report).map(item => item.report.target_account)));
+
dispatch(expandNotificationsForRequestSuccess(response.data, next?.uri));
}).catch(err => {
dispatch(expandNotificationsForRequestFail(err));
diff --git a/app/javascript/mastodon/components/column_header.jsx b/app/javascript/mastodon/components/column_header.jsx
index 8b7dcebc6..7fd646690 100644
--- a/app/javascript/mastodon/components/column_header.jsx
+++ b/app/javascript/mastodon/components/column_header.jsx
@@ -199,7 +199,7 @@ class ColumnHeader extends PureComponent {
{hasTitle && (
<>
- {backButton}
+ {showBackButton && backButton}