diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2023-10-26 06:11:53 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2023-10-26 06:11:53 +0300 |
commit | 40512a72dfb1e73836effc10c201eae9f6c10e28 (patch) | |
tree | dee9077bc44729820327bed27dee1be655439bb7 /app | |
parent | 9a02cb29182ae369f98a8b04840144c67b544a7a (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app')
-rw-r--r-- | app/services/activity_pub/accept_follow_service.rb | 55 | ||||
-rw-r--r-- | app/services/activity_pub/inbox_resolver_service.rb | 50 | ||||
-rw-r--r-- | app/services/activity_pub/third_party_error.rb | 5 | ||||
-rw-r--r-- | app/workers/activity_pub/projects/releases_subscription_worker.rb | 39 | ||||
-rw-r--r-- | app/workers/all_queues.yml | 9 |
5 files changed, 158 insertions, 0 deletions
diff --git a/app/services/activity_pub/accept_follow_service.rb b/app/services/activity_pub/accept_follow_service.rb new file mode 100644 index 00000000000..0ec440fa972 --- /dev/null +++ b/app/services/activity_pub/accept_follow_service.rb @@ -0,0 +1,55 @@ +# frozen_string_literal: true + +module ActivityPub + class AcceptFollowService + MissingInboxURLError = Class.new(StandardError) + + attr_reader :subscription, :actor + + def initialize(subscription, actor) + @subscription = subscription + @actor = actor + end + + def execute + return if subscription.accepted? + raise MissingInboxURLError unless subscription.subscriber_inbox_url.present? + + upload_accept_activity + subscription.accepted! + end + + private + + def upload_accept_activity + body = Gitlab::Json::LimitedEncoder.encode(payload, limit: 1.megabyte) + + begin + Gitlab::HTTP.post(subscription.subscriber_inbox_url, body: body, headers: headers) + rescue StandardError => e + raise ThirdPartyError, e.message + end + end + + def payload + follow = subscription.payload.dup + follow.delete('@context') + + { + '@context': 'https://www.w3.org/ns/activitystreams', + id: "#{actor}#follow/#{subscription.id}/accept", + type: 'Accept', + actor: actor, + object: follow + } + end + + def headers + { + 'User-Agent' => "GitLab/#{Gitlab::VERSION}", + 'Content-Type' => 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"', + 'Accept' => 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"' + } + end + end +end diff --git a/app/services/activity_pub/inbox_resolver_service.rb b/app/services/activity_pub/inbox_resolver_service.rb new file mode 100644 index 00000000000..c2bd2112b16 --- /dev/null +++ b/app/services/activity_pub/inbox_resolver_service.rb @@ -0,0 +1,50 @@ +# frozen_string_literal: true + +module ActivityPub + class InboxResolverService + attr_reader :subscription + + def initialize(subscription) + @subscription = subscription + end + + def execute + profile = subscriber_profile + unless profile.has_key?('inbox') && profile['inbox'].is_a?(String) + raise ThirdPartyError, 'Inbox parameter absent or invalid' + end + + subscription.subscriber_inbox_url = profile['inbox'] + subscription.shared_inbox_url = profile.dig('entrypoints', 'sharedInbox') + subscription.save! + end + + private + + def subscriber_profile + raw_data = download_subscriber_profile + + begin + profile = Gitlab::Json.parse(raw_data) + rescue JSON::ParserError => e + raise ThirdPartyError, e.message + end + + profile + end + + def download_subscriber_profile + begin + response = Gitlab::HTTP.get(subscription.subscriber_url, + headers: { + 'Accept' => 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"' + } + ) + rescue StandardError => e + raise ThirdPartyError, e.message + end + + response.body + end + end +end diff --git a/app/services/activity_pub/third_party_error.rb b/app/services/activity_pub/third_party_error.rb new file mode 100644 index 00000000000..473a67984a4 --- /dev/null +++ b/app/services/activity_pub/third_party_error.rb @@ -0,0 +1,5 @@ +# frozen_string_literal: true + +module ActivityPub + ThirdPartyError = Class.new(StandardError) +end diff --git a/app/workers/activity_pub/projects/releases_subscription_worker.rb b/app/workers/activity_pub/projects/releases_subscription_worker.rb new file mode 100644 index 00000000000..c392726a469 --- /dev/null +++ b/app/workers/activity_pub/projects/releases_subscription_worker.rb @@ -0,0 +1,39 @@ +# frozen_string_literal: true + +module ActivityPub + module Projects + class ReleasesSubscriptionWorker + include ApplicationWorker + include Gitlab::Routing.url_helpers + + idempotent! + worker_has_external_dependencies! + feature_category :release_orchestration + data_consistency :delayed + queue_namespace :activity_pub + + sidekiq_retries_exhausted do |msg, _ex| + subscription_id = msg['args'].second + subscription = ActivityPub::ReleasesSubscription.find_by_id(subscription_id) + subscription&.destroy + end + + def perform(subscription_id) + subscription = ActivityPub::ReleasesSubscription.find_by_id(subscription_id) + return if subscription.nil? + + unless subscription.project.public? + subscription.destroy + return + end + + InboxResolverService.new(subscription).execute if needs_resolving?(subscription) + AcceptFollowService.new(subscription, project_releases_url(subscription.project)).execute + end + + def needs_resolving?(subscription) + subscription.subscriber_inbox_url.blank? || subscription.shared_inbox_url.blank? + end + end + end +end diff --git a/app/workers/all_queues.yml b/app/workers/all_queues.yml index c758708c58f..96514f64c26 100644 --- a/app/workers/all_queues.yml +++ b/app/workers/all_queues.yml @@ -3,6 +3,15 @@ # # Do not edit it manually! --- +- :name: activity_pub:activity_pub_projects_releases_subscription + :worker_name: ActivityPub::Projects::ReleasesSubscriptionWorker + :feature_category: :release_orchestration + :has_external_dependencies: true + :urgency: :low + :resource_boundary: :unknown + :weight: 1 + :idempotent: true + :tags: [] - :name: authorized_project_update:authorized_project_update_project_recalculate :worker_name: AuthorizedProjectUpdate::ProjectRecalculateWorker :feature_category: :system_access |