diff options
author | Starfall <root@starfall.blue> | 2019-12-09 19:07:33 -0600 |
---|---|---|
committer | Starfall <root@starfall.blue> | 2019-12-09 19:09:31 -0600 |
commit | 6b34fcfef7566105e8d80ab5fee0a539c06cddbf (patch) | |
tree | 8fad2d47bf8be255d3c671c40cbfd04c2f55ed03 /app/controllers/activitypub | |
parent | 9fbb4af7611aa7836e65ef9f544d341423c15685 (diff) | |
parent | 246addd5b33a172600342af3fb6fb5e4c80ad95e (diff) |
Merge branch 'glitch'`
Diffstat (limited to 'app/controllers/activitypub')
-rw-r--r-- | app/controllers/activitypub/base_controller.rb | 11 | ||||
-rw-r--r-- | app/controllers/activitypub/collections_controller.rb | 25 | ||||
-rw-r--r-- | app/controllers/activitypub/inboxes_controller.rb | 36 | ||||
-rw-r--r-- | app/controllers/activitypub/outboxes_controller.rb | 12 | ||||
-rw-r--r-- | app/controllers/activitypub/replies_controller.rb | 71 |
5 files changed, 114 insertions, 41 deletions
diff --git a/app/controllers/activitypub/base_controller.rb b/app/controllers/activitypub/base_controller.rb new file mode 100644 index 000000000..0c2591e97 --- /dev/null +++ b/app/controllers/activitypub/base_controller.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +class ActivityPub::BaseController < Api::BaseController + skip_before_action :require_authenticated_user! + + private + + def set_cache_headers + response.headers['Vary'] = 'Signature' if authorized_fetch_mode? + end +end diff --git a/app/controllers/activitypub/collections_controller.rb b/app/controllers/activitypub/collections_controller.rb index 012c3c538..910fefb1c 100644 --- a/app/controllers/activitypub/collections_controller.rb +++ b/app/controllers/activitypub/collections_controller.rb @@ -1,30 +1,21 @@ # frozen_string_literal: true -class ActivityPub::CollectionsController < Api::BaseController +class ActivityPub::CollectionsController < ActivityPub::BaseController include SignatureVerification + include AccountOwnedConcern - before_action :set_account + before_action :require_signature!, if: :authorized_fetch_mode? before_action :set_size before_action :set_statuses before_action :set_cache_headers def show - render_cached_json(['activitypub', 'collection', @account, params[:id]], content_type: 'application/activity+json') do - ActiveModelSerializers::SerializableResource.new( - collection_presenter, - serializer: ActivityPub::CollectionSerializer, - adapter: ActivityPub::Adapter, - skip_activities: true - ) - end + expires_in 3.minutes, public: public_fetch_mode? + render_with_cache json: collection_presenter, content_type: 'application/activity+json', serializer: ActivityPub::CollectionSerializer, adapter: ActivityPub::Adapter, skip_activities: true end private - def set_account - @account = Account.find_local!(params[:account_username]) - end - def set_statuses @statuses = scope_for_collection @statuses = cache_collection(@statuses, Status) @@ -42,9 +33,9 @@ class ActivityPub::CollectionsController < Api::BaseController def scope_for_collection case params[:id] when 'featured' - @account.statuses.permitted_for(@account, signed_request_account).tap do |scope| - scope.merge!(@account.pinned_statuses) - end + return Status.none if @account.blocking?(signed_request_account) + + @account.pinned_statuses else raise ActiveRecord::RecordNotFound end diff --git a/app/controllers/activitypub/inboxes_controller.rb b/app/controllers/activitypub/inboxes_controller.rb index a0b7532c2..291eec19a 100644 --- a/app/controllers/activitypub/inboxes_controller.rb +++ b/app/controllers/activitypub/inboxes_controller.rb @@ -1,40 +1,45 @@ # frozen_string_literal: true -class ActivityPub::InboxesController < Api::BaseController +class ActivityPub::InboxesController < ActivityPub::BaseController include SignatureVerification include JsonLdHelper + include AccountOwnedConcern - before_action :set_account + before_action :skip_unknown_actor_delete + before_action :require_signature! + skip_before_action :authenticate_user! def create - if unknown_deleted_account? - head 202 - elsif signed_request_account - upgrade_account - process_payload - head 202 - else - render plain: signature_verification_failure_reason, status: 401 - end + upgrade_account + process_payload + head 202 end private + def skip_unknown_actor_delete + head 202 if unknown_deleted_account? + end + def unknown_deleted_account? json = Oj.load(body, mode: :strict) - json['type'] == 'Delete' && json['actor'].present? && json['actor'] == value_or_id(json['object']) && !Account.where(uri: json['actor']).exists? + json.is_a?(Hash) && json['type'] == 'Delete' && json['actor'].present? && json['actor'] == value_or_id(json['object']) && !Account.where(uri: json['actor']).exists? rescue Oj::ParseError false end - def set_account - @account = Account.find_local!(params[:account_username]) if params[:account_username] + def account_required? + params[:account_username].present? end def body return @body if defined?(@body) - @body = request.body.read.force_encoding('UTF-8') + + @body = request.body.read + @body.force_encoding('UTF-8') if @body.present? + request.body.rewind if request.body.respond_to?(:rewind) + @body end @@ -44,7 +49,6 @@ class ActivityPub::InboxesController < Api::BaseController ResolveAccountWorker.perform_async(signed_request_account.acct) end - Pubsubhubbub::UnsubscribeWorker.perform_async(signed_request_account.id) if signed_request_account.subscribed? DeliveryFailureTracker.track_inverse_success!(signed_request_account) end diff --git a/app/controllers/activitypub/outboxes_controller.rb b/app/controllers/activitypub/outboxes_controller.rb index 5147afbf7..891756b7e 100644 --- a/app/controllers/activitypub/outboxes_controller.rb +++ b/app/controllers/activitypub/outboxes_controller.rb @@ -1,26 +1,22 @@ # frozen_string_literal: true -class ActivityPub::OutboxesController < Api::BaseController +class ActivityPub::OutboxesController < ActivityPub::BaseController LIMIT = 20 include SignatureVerification + include AccountOwnedConcern - before_action :set_account + before_action :require_signature!, if: :authorized_fetch_mode? before_action :set_statuses before_action :set_cache_headers def show - expires_in 1.minute, public: true unless page_requested? - + expires_in(page_requested? ? 0 : 3.minutes, public: public_fetch_mode?) render json: outbox_presenter, serializer: ActivityPub::OutboxSerializer, adapter: ActivityPub::Adapter, content_type: 'application/activity+json' end private - def set_account - @account = Account.find_local!(params[:account_username]) - end - def outbox_presenter if page_requested? ActivityPub::CollectionPresenter.new( diff --git a/app/controllers/activitypub/replies_controller.rb b/app/controllers/activitypub/replies_controller.rb new file mode 100644 index 000000000..c62061555 --- /dev/null +++ b/app/controllers/activitypub/replies_controller.rb @@ -0,0 +1,71 @@ +# frozen_string_literal: true + +class ActivityPub::RepliesController < ActivityPub::BaseController + include SignatureAuthentication + include Authorization + include AccountOwnedConcern + + DESCENDANTS_LIMIT = 60 + + before_action :require_signature!, if: :authorized_fetch_mode? + before_action :set_status + before_action :set_cache_headers + before_action :set_replies + + def index + expires_in 0, public: public_fetch_mode? + render json: replies_collection_presenter, serializer: ActivityPub::CollectionSerializer, adapter: ActivityPub::Adapter, content_type: 'application/activity+json', skip_activities: true + end + + private + + def set_status + @status = @account.statuses.find(params[:status_id]) + authorize @status, :show? + rescue Mastodon::NotPermittedError + raise ActiveRecord::RecordNotFound + end + + def set_replies + @replies = page_params[:only_other_accounts] ? Status.where.not(account_id: @account.id) : @account.statuses + @replies = @replies.where(in_reply_to_id: @status.id, visibility: [:public, :unlisted]) + @replies = @replies.paginate_by_min_id(DESCENDANTS_LIMIT, params[:min_id]) + end + + def replies_collection_presenter + page = ActivityPub::CollectionPresenter.new( + id: account_status_replies_url(@account, @status, page_params), + type: :unordered, + part_of: account_status_replies_url(@account, @status), + next: next_page, + items: @replies.map { |status| status.local ? status : status.uri } + ) + + return page if page_requested? + + ActivityPub::CollectionPresenter.new( + id: account_status_replies_url(@account, @status), + type: :unordered, + first: page + ) + end + + def page_requested? + params[:page] == 'true' + end + + def next_page + only_other_accounts = !(@replies&.last&.account_id == @account.id && @replies.size == DESCENDANTS_LIMIT) + account_status_replies_url( + @account, + @status, + page: true, + min_id: only_other_accounts && !page_params[:only_other_accounts] ? nil : @replies&.last&.id, + only_other_accounts: only_other_accounts + ) + end + + def page_params + params_slice(:only_other_accounts, :min_id).merge(page: true) + end +end |