Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'app/serializers/activity_pub/activity_streams_serializer.rb')
-rw-r--r--app/serializers/activity_pub/activity_streams_serializer.rb90
1 files changed, 90 insertions, 0 deletions
diff --git a/app/serializers/activity_pub/activity_streams_serializer.rb b/app/serializers/activity_pub/activity_streams_serializer.rb
new file mode 100644
index 00000000000..39caa4a6d10
--- /dev/null
+++ b/app/serializers/activity_pub/activity_streams_serializer.rb
@@ -0,0 +1,90 @@
+# frozen_string_literal: true
+
+module ActivityPub
+ class ActivityStreamsSerializer < ::BaseSerializer
+ MissingIdentifierError = Class.new(StandardError)
+ MissingTypeError = Class.new(StandardError)
+ MissingOutboxError = Class.new(StandardError)
+
+ alias_method :base_represent, :represent
+
+ def represent(resource, opts = {}, entity_class = nil)
+ response = if respond_to?(:paginated?) && paginated?
+ represent_paginated(resource, opts, entity_class)
+ else
+ represent_whole(resource, opts, entity_class)
+ end
+
+ validate_response(HashWithIndifferentAccess.new(response))
+ end
+
+ private
+
+ def validate_response(response)
+ unless response[:id].present?
+ raise MissingIdentifierError, "The serializer does not provide the mandatory 'id' field."
+ end
+
+ unless response[:type].present?
+ raise MissingTypeError, "The serializer does not provide the mandatory 'type' field."
+ end
+
+ response
+ end
+
+ def represent_whole(resource, opts, entity_class)
+ raise MissingOutboxError, 'Please provide an :outbox option for this actor' unless opts[:outbox].present?
+
+ serialized = base_represent(resource, opts, entity_class)
+
+ {
+ :@context => "https://www.w3.org/ns/activitystreams",
+ inbox: opts[:inbox],
+ outbox: opts[:outbox]
+ }.merge(serialized)
+ end
+
+ def represent_paginated(resources, opts, entity_class)
+ if paginator.params['page'].present?
+ represent_page(resources, resources.current_page, opts, entity_class)
+ else
+ represent_pagination_index(resources)
+ end
+ end
+
+ def represent_page(resources, page, opts, entity_class)
+ opts[:page] = page
+ serialized = base_represent(resources, opts, entity_class)
+
+ {
+ :@context => 'https://www.w3.org/ns/activitystreams',
+ type: 'OrderedCollectionPage',
+ id: collection_url(page),
+ prev: page > 1 ? collection_url(page - 1) : nil,
+ next: page < resources.total_pages ? collection_url(page + 1) : nil,
+ partOf: collection_url,
+ orderedItems: serialized
+ }
+ end
+
+ def represent_pagination_index(resources)
+ {
+ :@context => 'https://www.w3.org/ns/activitystreams',
+ type: 'OrderedCollection',
+ id: collection_url,
+ totalItems: resources.total_count,
+ first: collection_url(1),
+ last: collection_url(resources.total_pages)
+ }
+ end
+
+ def collection_url(page = nil)
+ uri = URI.parse(paginator.request.url)
+ uri.query ||= ""
+ parts = uri.query.split('&').reject { |part| part =~ /^page=/ }
+ parts << "page=#{page}" if page
+ uri.query = parts.join('&')
+ uri.to_s.sub(/\?$/, '')
+ end
+ end
+end