Merge branch 'master' into glitch-soc/merge-upstream
Conflicts:
- `.github/dependabot.yml`:
Updated upstream, we deleted it to not be flooded by Depandabot.
Kept deleted.
- `Gemfile.lock`:
Puma updated on both sides, went for the most recent version.
- `app/controllers/api/v1/mutes_controller.rb`:
Upstream updated the serializer to support timed mutes, while
glitch-soc added a custom API ages ago to get information that
is already available elsewhere.
Dropped the glitch-soc-specific API, went with upstream changes.
- `app/javascript/core/admin.js`:
Conflict due to changing how assets are loaded. Went with upstream.
- `app/javascript/packs/public.js`:
Conflict due to changing how assets are loaded. Went with upstream.
- `app/models/mute.rb`:
🤷
- `app/models/user.rb`:
New user setting added upstream while we have glitch-soc-specific
user settings. Added upstream's user setting.
- `config/settings.yml`:
Upstream added a new user setting close to a user setting we had
changed the defaults for. Added the new upstream setting.
- `package.json`:
Upstream dependency updated “too close” to a glitch-soc-specific
dependency. No real conflict. Updated the dependency.
This commit is contained in:
@@ -39,17 +39,16 @@ class ActivityPub::FetchRemoteAccountService < BaseService
|
||||
webfinger = webfinger!("acct:#{@username}@#{@domain}")
|
||||
confirmed_username, confirmed_domain = split_acct(webfinger.subject)
|
||||
|
||||
return webfinger.link('self')&.href == @uri if @username.casecmp(confirmed_username).zero? && @domain.casecmp(confirmed_domain).zero?
|
||||
return webfinger.link('self', 'href') == @uri if @username.casecmp(confirmed_username).zero? && @domain.casecmp(confirmed_domain).zero?
|
||||
|
||||
webfinger = webfinger!("acct:#{confirmed_username}@#{confirmed_domain}")
|
||||
@username, @domain = split_acct(webfinger.subject)
|
||||
self_reference = webfinger.link('self')
|
||||
|
||||
return false unless @username.casecmp(confirmed_username).zero? && @domain.casecmp(confirmed_domain).zero?
|
||||
return false if self_reference&.href != @uri
|
||||
return false if webfinger.link('self', 'href') != @uri
|
||||
|
||||
true
|
||||
rescue Goldfinger::Error
|
||||
rescue Webfinger::Error
|
||||
false
|
||||
end
|
||||
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class ActivityPub::PrepareFollowersSynchronizationService < BaseService
|
||||
include JsonLdHelper
|
||||
|
||||
def call(account, params)
|
||||
@account = account
|
||||
|
||||
return if params['collectionId'] != @account.followers_url || invalid_origin?(params['url']) || @account.local_followers_hash == params['digest']
|
||||
|
||||
ActivityPub::FollowersSynchronizationWorker.perform_async(@account.id, params['url'])
|
||||
end
|
||||
end
|
||||
74
app/services/activitypub/synchronize_followers_service.rb
Normal file
74
app/services/activitypub/synchronize_followers_service.rb
Normal file
@@ -0,0 +1,74 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class ActivityPub::SynchronizeFollowersService < BaseService
|
||||
include JsonLdHelper
|
||||
include Payloadable
|
||||
|
||||
def call(account, partial_collection_url)
|
||||
@account = account
|
||||
|
||||
items = collection_items(partial_collection_url)
|
||||
return if items.nil?
|
||||
|
||||
# There could be unresolved accounts (hence the call to .compact) but this
|
||||
# should never happen in practice, since in almost all cases we keep an
|
||||
# Account record, and should we not do that, we should have sent a Delete.
|
||||
# In any case there is not much we can do if that occurs.
|
||||
@expected_followers = items.map { |uri| ActivityPub::TagManager.instance.uri_to_resource(uri, Account) }.compact
|
||||
|
||||
remove_unexpected_local_followers!
|
||||
handle_unexpected_outgoing_follows!
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def remove_unexpected_local_followers!
|
||||
@account.followers.local.where.not(id: @expected_followers.map(&:id)).each do |unexpected_follower|
|
||||
UnfollowService.new.call(unexpected_follower, @account)
|
||||
end
|
||||
end
|
||||
|
||||
def handle_unexpected_outgoing_follows!
|
||||
@expected_followers.each do |expected_follower|
|
||||
next if expected_follower.following?(@account)
|
||||
|
||||
if expected_follower.requested?(@account)
|
||||
# For some reason the follow request went through but we missed it
|
||||
expected_follower.follow_requests.find_by(target_account: @account)&.authorize!
|
||||
else
|
||||
# Since we were not aware of the follow from our side, we do not have an
|
||||
# ID for it that we can include in the Undo activity. For this reason,
|
||||
# the Undo may not work with software that relies exclusively on
|
||||
# matching activity IDs and not the actor and target
|
||||
follow = Follow.new(account: expected_follower, target_account: @account)
|
||||
ActivityPub::DeliveryWorker.perform_async(build_undo_follow_json(follow), follow.account_id, follow.target_account.inbox_url)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def build_undo_follow_json(follow)
|
||||
Oj.dump(serialize_payload(follow, ActivityPub::UndoFollowSerializer))
|
||||
end
|
||||
|
||||
def collection_items(collection_or_uri)
|
||||
collection = fetch_collection(collection_or_uri)
|
||||
return unless collection.is_a?(Hash)
|
||||
|
||||
collection = fetch_collection(collection['first']) if collection['first'].present?
|
||||
return unless collection.is_a?(Hash)
|
||||
|
||||
case collection['type']
|
||||
when 'Collection', 'CollectionPage'
|
||||
collection['items']
|
||||
when 'OrderedCollection', 'OrderedCollectionPage'
|
||||
collection['orderedItems']
|
||||
end
|
||||
end
|
||||
|
||||
def fetch_collection(collection_or_uri)
|
||||
return collection_or_uri if collection_or_uri.is_a?(Hash)
|
||||
return if invalid_origin?(collection_or_uri)
|
||||
|
||||
fetch_resource_without_id_validation(collection_or_uri, nil, true)
|
||||
end
|
||||
end
|
||||
@@ -1,13 +1,13 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class AppSignUpService < BaseService
|
||||
def call(app, params)
|
||||
def call(app, remote_ip, params)
|
||||
return unless allowed_registrations?
|
||||
|
||||
user_params = params.slice(:email, :password, :agreement, :locale)
|
||||
account_params = params.slice(:username)
|
||||
invite_request_params = { text: params[:reason] }
|
||||
user = User.create!(user_params.merge(created_by_application: app, password_confirmation: user_params[:password], account_attributes: account_params, invite_request_attributes: invite_request_params))
|
||||
user = User.create!(user_params.merge(created_by_application: app, sign_up_ip: remote_ip, password_confirmation: user_params[:password], account_attributes: account_params, invite_request_attributes: invite_request_params))
|
||||
|
||||
Doorkeeper::AccessToken.create!(application: app,
|
||||
resource_owner_id: user.id,
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class MuteService < BaseService
|
||||
def call(account, target_account, notifications: nil)
|
||||
def call(account, target_account, notifications: nil, duration: 0)
|
||||
return if account.id == target_account.id
|
||||
|
||||
mute = account.mute!(target_account, notifications: notifications)
|
||||
mute = account.mute!(target_account, notifications: notifications, duration: duration)
|
||||
|
||||
if mute.hide_notifications?
|
||||
BlockWorker.perform_async(account.id, target_account.id)
|
||||
@@ -12,6 +12,8 @@ class MuteService < BaseService
|
||||
MuteWorker.perform_async(account.id, target_account.id)
|
||||
end
|
||||
|
||||
DeleteMuteWorker.perform_at(duration.seconds, mute.id) if duration != 0
|
||||
|
||||
mute
|
||||
end
|
||||
end
|
||||
|
||||
@@ -29,7 +29,7 @@ class ProcessMentionsService < BaseService
|
||||
if mention_undeliverable?(mentioned_account)
|
||||
begin
|
||||
mentioned_account = resolve_account_service.call(Regexp.last_match(1))
|
||||
rescue Goldfinger::Error, HTTP::Error, OpenSSL::SSL::SSLError, Mastodon::UnexpectedResponseError
|
||||
rescue Webfinger::Error, HTTP::Error, OpenSSL::SSL::SSLError, Mastodon::UnexpectedResponseError
|
||||
mentioned_account = nil
|
||||
end
|
||||
end
|
||||
|
||||
@@ -26,11 +26,10 @@ class ResolveAccountService < BaseService
|
||||
|
||||
@account ||= Account.find_remote(@username, @domain)
|
||||
|
||||
return @account if @account&.local? || !webfinger_update_due?
|
||||
return @account if @account&.local? || @domain.nil? || !webfinger_update_due?
|
||||
|
||||
# At this point we are in need of a Webfinger query, which may
|
||||
# yield us a different username/domain through a redirect
|
||||
|
||||
process_webfinger!(@uri)
|
||||
|
||||
# Because the username/domain pair may be different than what
|
||||
@@ -47,7 +46,7 @@ class ResolveAccountService < BaseService
|
||||
# either needs to be created, or updated from fresh data
|
||||
|
||||
process_account!
|
||||
rescue Goldfinger::Error, WebfingerRedirectError, Oj::ParseError => e
|
||||
rescue Webfinger::Error, WebfingerRedirectError, Oj::ParseError => e
|
||||
Rails.logger.debug "Webfinger query for #{@uri} failed: #{e}"
|
||||
nil
|
||||
end
|
||||
@@ -118,11 +117,11 @@ class ResolveAccountService < BaseService
|
||||
end
|
||||
|
||||
def activitypub_ready?
|
||||
!@webfinger.link('self').nil? && ['application/activity+json', 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"'].include?(@webfinger.link('self').type)
|
||||
['application/activity+json', 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"'].include?(@webfinger.link('self', 'type'))
|
||||
end
|
||||
|
||||
def actor_url
|
||||
@actor_url ||= @webfinger.link('self').href
|
||||
@actor_url ||= @webfinger.link('self', 'href')
|
||||
end
|
||||
|
||||
def actor_json
|
||||
|
||||
Reference in New Issue
Block a user