Skip to content

Commit

Permalink
Merge pull request #73 from atsu1125/develop
Browse files Browse the repository at this point in the history
Merge Develop
  • Loading branch information
atsu1125 authored Feb 3, 2024
2 parents e518b97 + 6ce7e97 commit cbbb38f
Show file tree
Hide file tree
Showing 24 changed files with 172 additions and 87 deletions.
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ RUN apt-get update && \

ENV PATH="${PATH}:/opt/ruby/bin:/opt/node/bin"

RUN npm install -g npm@latest && \
RUN npm install -g npm@9 && \
npm install -g yarn && \
gem install bundler && \
apt-get update && \
Expand Down
2 changes: 1 addition & 1 deletion app/controllers/admin/domain_blocks_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ def create
@domain_block.errors.delete(:domain)
render :new
else
if existing_domain_block.present?
if existing_domain_block.present? && existing_domain_block.domain == TagManager.instance.normalize_domain(@domain_block.domain.strip)
@domain_block = existing_domain_block
@domain_block.update(resource_params)
end
Expand Down
5 changes: 5 additions & 0 deletions app/controllers/api/v1/timelines/tag_controller.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# frozen_string_literal: true

class Api::V1::Timelines::TagController < Api::BaseController
before_action -> { doorkeeper_authorize! :read, :'read:statuses' }, only: :show, if: :require_auth?
before_action :load_tag
after_action :insert_pagination_headers, unless: -> { @statuses.empty? }

Expand All @@ -11,6 +12,10 @@ def show

private

def require_auth?
!Setting.timeline_preview
end

def load_tag
@tag = Tag.find_normalized(params[:id])
end
Expand Down
2 changes: 1 addition & 1 deletion app/controllers/concerns/signature_verification.rb
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ def account_from_key_id(key_id)
stoplight_wrap_request { ResolveAccountService.new.call(key_id.gsub(/\Aacct:/, '')) }
elsif !ActivityPub::TagManager.instance.local_uri?(key_id)
account = ActivityPub::TagManager.instance.uri_to_resource(key_id, Account)
account ||= stoplight_wrap_request { ActivityPub::FetchRemoteKeyService.new.call(key_id, id: false) }
account ||= stoplight_wrap_request { ActivityPub::FetchRemoteKeyService.new.call(key_id) }
account
end
rescue Mastodon::HostValidationError
Expand Down
4 changes: 2 additions & 2 deletions app/helpers/jsonld_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -149,8 +149,8 @@ def safe_for_forwarding?(original, compacted)
end
end

def fetch_resource(uri, id, on_behalf_of = nil)
unless id
def fetch_resource(uri, id_is_known, on_behalf_of = nil)
unless id_is_known
json = fetch_resource_without_id_validation(uri, on_behalf_of)

return if !json.is_a?(Hash) || unsupported_uri_scheme?(json['id'])
Expand Down
2 changes: 1 addition & 1 deletion app/lib/activitypub/activity.rb
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ def follow_from_object
def fetch_remote_original_status
if object_uri.start_with?('http')
return if ActivityPub::TagManager.instance.local_uri?(object_uri)
ActivityPub::FetchRemoteStatusService.new.call(object_uri, id: true, on_behalf_of: @account.followers.local.first)
ActivityPub::FetchRemoteStatusService.new.call(object_uri, on_behalf_of: @account.followers.local.first)
elsif @object['url'].present?
::FetchRemoteStatusService.new.call(@object['url'])
end
Expand Down
2 changes: 1 addition & 1 deletion app/lib/activitypub/linked_data_signature.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ def verify_account!
return unless type == 'RsaSignature2017'

creator = ActivityPub::TagManager.instance.uri_to_resource(creator_uri, Account)
creator ||= ActivityPub::FetchRemoteKeyService.new.call(creator_uri, id: false)
creator ||= ActivityPub::FetchRemoteKeyService.new.call(creator_uri)

return if creator.nil?

Expand Down
34 changes: 17 additions & 17 deletions app/lib/status_reach_finder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,28 +16,28 @@ def inboxes
private

def reached_account_inboxes
Account.where(id: reached_account_ids).inboxes
end

def reached_account_ids
# When the status is a reblog, there are no interactions with it
# directly, we assume all interactions are with the original one

if @status.reblog?
[]
[reblog_of_account_id]
else
Account.where(id: reached_account_ids).inboxes
end
end

def reached_account_ids
[
replied_to_account_id,
reblog_of_account_id,
mentioned_account_ids,
reblogs_account_ids,
favourites_account_ids,
replies_account_ids,
].tap do |arr|
arr.flatten!
arr.compact!
arr.uniq!
[
replied_to_account_id,
reblog_of_account_id,
mentioned_account_ids,
reblogs_account_ids,
favourites_account_ids,
replies_account_ids,
].tap do |arr|
arr.flatten!
arr.compact!
arr.uniq!
end
end
end

Expand Down
6 changes: 3 additions & 3 deletions app/lib/tag_manager.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,18 @@ class TagManager
include RoutingHelper

def web_domain?(domain)
domain.nil? || domain.gsub(/[\/]/, '').casecmp(Rails.configuration.x.web_domain).zero?
domain.nil? || domain.delete_suffix('/').casecmp(Rails.configuration.x.web_domain).zero?
end

def local_domain?(domain)
domain.nil? || domain.gsub(/[\/]/, '').casecmp(Rails.configuration.x.local_domain).zero?
domain.nil? || domain.delete_suffix('/').casecmp(Rails.configuration.x.local_domain).zero?
end

def normalize_domain(domain)
return if domain.nil?

uri = Addressable::URI.new
uri.host = domain.gsub(/[\/]/, '')
uri.host = domain.delete_suffix('/')
uri.normalized_host
end

Expand Down
12 changes: 12 additions & 0 deletions app/models/status.rb
Original file line number Diff line number Diff line change
Expand Up @@ -379,13 +379,25 @@ def reload_stale_associations!(cached_items)

account_ids.uniq!

status_ids = cached_items.map { |item| item.reblog? ? item.reblog_of_id : item.id }.uniq

return if account_ids.empty?

accounts = Account.where(id: account_ids).includes(:account_stat, :user).index_by(&:id)

status_stats = StatusStat.where(status_id: status_ids).index_by(&:status_id)

cached_items.each do |item|
item.account = accounts[item.account_id]
item.reblog.account = accounts[item.reblog.account_id] if item.reblog?

if item.reblog?
status_stat = status_stats[item.reblog.id]
item.reblog.status_stat = status_stat if status_stat.present?
else
status_stat = status_stats[item.id]
item.status_stat = status_stat if status_stat.present?
end
end
end

Expand Down
6 changes: 3 additions & 3 deletions app/services/activitypub/fetch_remote_account_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@ class ActivityPub::FetchRemoteAccountService < BaseService
SUPPORTED_TYPES = %w(Application Group Organization Person Service).freeze

# Does a WebFinger roundtrip on each call, unless `only_key` is true
def call(uri, id: true, prefetched_body: nil, break_on_redirect: false, only_key: false)
def call(uri, prefetched_body: nil, break_on_redirect: false, only_key: false)
return if domain_not_allowed?(uri)
return ActivityPub::TagManager.instance.uri_to_resource(uri, Account) if ActivityPub::TagManager.instance.local_uri?(uri)

@json = begin
if prefetched_body.nil?
fetch_resource(uri, id)
fetch_resource(uri, true)
else
body_to_json(prefetched_body, compare_id: id ? uri : nil)
body_to_json(prefetched_body, compare_id: uri)
end
end

Expand Down
17 changes: 2 additions & 15 deletions app/services/activitypub/fetch_remote_key_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,10 @@ class ActivityPub::FetchRemoteKeyService < BaseService
include JsonLdHelper

# Returns account that owns the key
def call(uri, id: true, prefetched_body: nil)
def call(uri)
return if uri.blank?

if prefetched_body.nil?
if id
@json = fetch_resource_without_id_validation(uri)
if person?
@json = fetch_resource(@json['id'], true)
elsif uri != @json['id']
return
end
else
@json = fetch_resource(uri, id)
end
else
@json = body_to_json(prefetched_body, compare_id: id ? uri : nil)
end
@json = fetch_resource(uri, false)

return unless supported_context?(@json) && expected_type?
return find_account(@json['id'], @json) if person?
Expand Down
8 changes: 4 additions & 4 deletions app/services/activitypub/fetch_remote_status_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ class ActivityPub::FetchRemoteStatusService < BaseService
include JsonLdHelper

# Should be called when uri has already been checked for locality
def call(uri, id: true, prefetched_body: nil, on_behalf_of: nil)
def call(uri, prefetched_body: nil, on_behalf_of: nil)
@json = begin
if prefetched_body.nil?
fetch_resource(uri, id, on_behalf_of)
fetch_resource(uri, true, on_behalf_of)
else
body_to_json(prefetched_body, compare_id: id ? uri : nil)
body_to_json(prefetched_body, compare_id: uri)
end
end

Expand All @@ -29,7 +29,7 @@ def call(uri, id: true, prefetched_body: nil, on_behalf_of: nil)
return if activity_json.nil? || !trustworthy_attribution?(@json['id'], actor_id)

actor = ActivityPub::TagManager.instance.uri_to_resource(actor_id, Account)
actor = ActivityPub::FetchRemoteAccountService.new.call(actor_id, id: true) if actor.nil? || needs_update?(actor)
actor = ActivityPub::FetchRemoteAccountService.new.call(actor_id) if actor.nil? || needs_update?(actor)

return if actor.nil? || actor.suspended?

Expand Down
2 changes: 1 addition & 1 deletion app/services/activitypub/process_account_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,7 @@ def collection_info(type)

def moved_account
account = ActivityPub::TagManager.instance.uri_to_resource(@json['movedTo'], Account)
account ||= ActivityPub::FetchRemoteAccountService.new.call(@json['movedTo'], id: true, break_on_redirect: true)
account ||= ActivityPub::FetchRemoteAccountService.new.call(@json['movedTo'], break_on_redirect: true)
account
end

Expand Down
2 changes: 1 addition & 1 deletion app/services/fetch_oembed_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ def parse_for_format(body)
end

def validate(oembed)
oembed if oembed[:version] == '1.0' && oembed[:type].present?
oembed if oembed.present? && oembed[:version].to_s == '1.0' && oembed[:type].present?
end

def html
Expand Down
10 changes: 9 additions & 1 deletion app/services/fetch_resource_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,15 @@ def process_response(response, terminal = false)
body = response.body_with_limit
json = body_to_json(body)

[json['id'], { prefetched_body: body, id: true }] if supported_context?(json) && (equals_or_includes_any?(json['type'], ActivityPub::FetchRemoteAccountService::SUPPORTED_TYPES) || expected_type?(json))
return unless supported_context?(json) && (equals_or_includes_any?(json['type'], ActivityPub::FetchRemoteAccountService::SUPPORTED_TYPES) || expected_type?(json))

if json['id'] != @url
return if terminal

return process(json['id'], terminal: true)
end

[@url, { prefetched_body: body }]
elsif !terminal
link_header = response['Link'] && parse_link_header(response)

Expand Down
6 changes: 1 addition & 5 deletions app/services/reblog_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,7 @@ def call(account, reblogged_status, options = {})
def create_notification(reblog)
reblogged_status = reblog.reblog

if reblogged_status.account.local?
LocalNotificationWorker.perform_async(reblogged_status.account_id, reblog.id, reblog.class.name, 'reblog')
elsif reblogged_status.account.activitypub? && !reblogged_status.account.following?(reblog.account)
ActivityPub::DeliveryWorker.perform_async(build_json(reblog), reblog.account_id, reblogged_status.account.inbox_url)
end
LocalNotificationWorker.perform_async(reblogged_status.account_id, reblog.id, reblog.class.name, 'reblog') if reblogged_status.account.local?
end

def bump_potential_friendship(account, reblog)
Expand Down
71 changes: 53 additions & 18 deletions spec/controllers/api/v1/timelines/tag_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,36 +5,71 @@
describe Api::V1::Timelines::TagController do
render_views

let(:user) { Fabricate(:user) }
let(:user) { Fabricate(:user) }
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'read:statuses') }

before do
allow(controller).to receive(:doorkeeper_token) { token }
end

context 'with a user context' do
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id) }
describe 'GET #show' do
subject do
get :show, params: { id: 'test' }
end

before do
PostStatusService.new.call(user.account, text: 'It is a #test')
end

context 'when the instance allows public preview' do
context 'when the user is not authenticated' do
let(:token) { nil }

describe 'GET #show' do
before do
PostStatusService.new.call(user.account, text: 'It is a #test')
it 'returns http success', :aggregate_failures do
subject

expect(response).to have_http_status(200)
expect(response.headers['Link'].links.size).to eq(2)
end
end

it 'returns http success' do
get :show, params: { id: 'test' }
expect(response).to have_http_status(200)
expect(response.headers['Link'].links.size).to eq(2)
context 'when the user is authenticated' do
it 'returns http success', :aggregate_failures do
subject

expect(response).to have_http_status(200)
expect(response.headers['Link'].links.size).to eq(2)
end
end
end
end

context 'without a user context' do
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: nil) }
context 'when the instance does not allow public preview' do
around do |example|
timeline_preview = Setting.timeline_preview
Setting.timeline_preview = false

example.run

Setting.timeline_preview = timeline_preview
end

context 'when the user is not authenticated' do
let(:token) { nil }

it 'returns http unauthorized' do
subject

expect(response).to have_http_status(401)
end
end

context 'when the user is authenticated' do
it 'returns http success', :aggregate_failures do
subject

describe 'GET #show' do
it 'returns http success' do
get :show, params: { id: 'test' }
expect(response).to have_http_status(200)
expect(response.headers['Link']).to be_nil
expect(response).to have_http_status(200)
expect(response.headers['Link'].links.size).to eq(2)
end
end
end
end
Expand Down
Loading

0 comments on commit cbbb38f

Please sign in to comment.