diff --git a/app/controllers/api/base_controller.rb b/app/controllers/api/base_controller.rb index 0980e0ebbc..b10c2f5737 100644 --- a/app/controllers/api/base_controller.rb +++ b/app/controllers/api/base_controller.rb @@ -72,6 +72,13 @@ class Api::BaseController < ApplicationController end end + # Redefine `require_functional!` to properly output JSON instead of HTML redirects + def require_functional! + return if current_user.functional? + + require_user! + end + def render_empty render json: {}, status: 200 end diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 9ec5092667..ee799168d6 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -74,7 +74,23 @@ class ApplicationController < ActionController::Base end def require_functional! - redirect_to edit_user_registration_path unless current_user.functional? + return if current_user.functional? + + respond_to do |format| + format.any do + redirect_to edit_user_registration_path + end + + format.json do + if !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 + end + end + end end def skip_csrf_meta_tags? diff --git a/app/helpers/context_helper.rb b/app/helpers/context_helper.rb index b36e25c092..14f018d118 100644 --- a/app/helpers/context_helper.rb +++ b/app/helpers/context_helper.rb @@ -26,6 +26,13 @@ module ContextHelper voters_count: { 'toot' => 'http://joinmastodon.org/ns#', 'votersCount' => 'toot:votersCount' }, suspended: { 'toot' => 'http://joinmastodon.org/ns#', 'suspended' => 'toot:suspended' }, attribution_domains: { 'toot' => 'http://joinmastodon.org/ns#', 'attributionDomains' => { '@id' => 'toot:attributionDomains', '@type' => '@id' } }, + interaction_policies: { + 'gts' => 'https://gotosocial.org/ns#', + 'interactionPolicy' => { '@id' => 'gts:interactionPolicy', '@type' => '@id' }, + 'canQuote' => { '@id' => 'gts:canQuote', '@type' => '@id' }, + 'automaticApproval' => { '@id' => 'gts:automaticApproval', '@type' => '@id' }, + 'manualApproval' => { '@id' => 'gts:manualApproval', '@type' => '@id' }, + }, }.freeze def full_context diff --git a/app/javascript/entrypoints/sign_up.ts b/app/javascript/entrypoints/sign_up.ts index 880738fcb7..87100be56d 100644 --- a/app/javascript/entrypoints/sign_up.ts +++ b/app/javascript/entrypoints/sign_up.ts @@ -4,9 +4,12 @@ import axios from 'axios'; import ready from '../mastodon/ready'; async function checkConfirmation() { - const response = await axios.get('/api/v1/emails/check_confirmation'); + const response = await axios.get('/api/v1/emails/check_confirmation', { + headers: { Accept: 'application/json' }, + withCredentials: true, + }); - if (response.data) { + if (response.status === 200 && response.data === true) { window.location.href = '/start'; } } diff --git a/app/javascript/flavours/glitch/entrypoints/sign_up.ts b/app/javascript/flavours/glitch/entrypoints/sign_up.ts index 18e2931546..72f3b638c3 100644 --- a/app/javascript/flavours/glitch/entrypoints/sign_up.ts +++ b/app/javascript/flavours/glitch/entrypoints/sign_up.ts @@ -4,9 +4,12 @@ import axios from 'axios'; import ready from 'flavours/glitch/ready'; async function checkConfirmation() { - const response = await axios.get('/api/v1/emails/check_confirmation'); + const response = await axios.get('/api/v1/emails/check_confirmation', { + headers: { Accept: 'application/json' }, + withCredentials: true, + }); - if (response.data) { + if (response.status === 200 && response.data === true) { window.location.href = '/start'; } } diff --git a/app/lib/http_signature_draft.rb b/app/lib/http_signature_draft.rb index fc0d498b29..cb794b223a 100644 --- a/app/lib/http_signature_draft.rb +++ b/app/lib/http_signature_draft.rb @@ -6,14 +6,13 @@ class HttpSignatureDraft REQUEST_TARGET = '(request-target)' - def initialize(keypair, key_id, full_path: true) + def initialize(keypair, key_id) @keypair = keypair @key_id = key_id - @full_path = full_path end def request_target(verb, url) - if url.query.nil? || !@full_path + if url.query.nil? "#{verb} #{url.path}" else "#{verb} #{url.path}?#{url.query}" diff --git a/app/lib/request.rb b/app/lib/request.rb index 03c27c7cea..10a3680484 100644 --- a/app/lib/request.rb +++ b/app/lib/request.rb @@ -75,7 +75,6 @@ class Request @url = Addressable::URI.parse(url).normalize @http_client = options.delete(:http_client) @allow_local = options.delete(:allow_local) - @full_path = !options.delete(:omit_query_string) @options = { follow: { max_hops: 3, @@ -102,7 +101,7 @@ class Request key_id = ActivityPub::TagManager.instance.key_uri_for(actor) keypair = sign_with.present? ? OpenSSL::PKey::RSA.new(sign_with) : actor.keypair - @signing = HttpSignatureDraft.new(keypair, key_id, full_path: @full_path) + @signing = HttpSignatureDraft.new(keypair, key_id) self end diff --git a/app/services/activitypub/fetch_replies_service.rb b/app/services/activitypub/fetch_replies_service.rb index 46cab6caf9..0e0ba673be 100644 --- a/app/services/activitypub/fetch_replies_service.rb +++ b/app/services/activitypub/fetch_replies_service.rb @@ -37,20 +37,7 @@ class ActivityPub::FetchRepliesService < BaseService return unless @allow_synchronous_requests return if non_matching_uri_hosts?(@account.uri, collection_or_uri) - # NOTE: For backward compatibility reasons, Mastodon signs outgoing - # queries incorrectly by default. - # - # While this is relevant for all URLs with query strings, this is - # the only code path where this happens in practice. - # - # Therefore, retry with correct signatures if this fails. - begin - fetch_resource_without_id_validation(collection_or_uri, nil, true) - rescue Mastodon::UnexpectedResponseError => e - raise unless e.response && e.response.code == 401 && Addressable::URI.parse(collection_or_uri).query.present? - - fetch_resource_without_id_validation(collection_or_uri, nil, true, request_options: { omit_query_string: false }) - end + fetch_resource_without_id_validation(collection_or_uri, nil, true) end def filtered_replies diff --git a/app/workers/activitypub/delivery_worker.rb b/app/workers/activitypub/delivery_worker.rb index 0c6ca026bb..7a1440ed15 100644 --- a/app/workers/activitypub/delivery_worker.rb +++ b/app/workers/activitypub/delivery_worker.rb @@ -62,7 +62,7 @@ class ActivityPub::DeliveryWorker stoplight_wrapper.run do request_pool.with(@host) do |http_client| build_request(http_client).perform do |response| - raise Mastodon::UnexpectedResponseError, response unless response_successful?(response) || response_error_unsalvageable?(response) + raise Mastodon::UnexpectedResponseError, response unless response_successful?(response) || response_error_unsalvageable?(response) || unsalvageable_authorization_failure?(response) @performed = true end @@ -70,6 +70,10 @@ class ActivityPub::DeliveryWorker end end + def unsalvageable_authorization_failure?(response) + @source_account.permanently_unavailable? && response.code == 401 + end + def stoplight_wrapper Stoplight(@inbox_url) .with_threshold(STOPLIGHT_FAILURE_THRESHOLD) diff --git a/config/initializers/deprecations.rb b/config/initializers/deprecations.rb new file mode 100644 index 0000000000..e0ad54d8c3 --- /dev/null +++ b/config/initializers/deprecations.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true + +if ENV['REDIS_NAMESPACE'] + es_configured = ENV['ES_ENABLED'] == 'true' || ENV.fetch('ES_HOST', 'localhost') != 'localhost' || ENV.fetch('ES_PORT', '9200') != '9200' || ENV.fetch('ES_PASS', 'password') != 'password' + + warn <<~MESSAGE + WARNING: the REDIS_NAMESPACE environment variable is deprecated and will be removed in Mastodon 4.4.0. + + Please see documentation at https://github.com/mastodon/redis_namespace_migration + MESSAGE + + warn <<~MESSAGE if es_configured && !ENV['ES_PREFIX'] + + In addition, as REDIS_NAMESPACE is being used as a prefix for Elasticsearch, please do not forget to set ES_PREFIX to "#{ENV.fetch('REDIS_NAMESPACE')}". + MESSAGE +end