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
path: root/app
diff options
context:
space:
mode:
Diffstat (limited to 'app')
-rw-r--r--app/serializers/activity_pub/activity_serializer.rb40
-rw-r--r--app/serializers/activity_pub/activity_streams_serializer.rb90
-rw-r--r--app/serializers/activity_pub/actor_serializer.rb39
-rw-r--r--app/serializers/activity_pub/collection_serializer.rb68
-rw-r--r--app/serializers/activity_pub/object_serializer.rb35
-rw-r--r--app/serializers/activity_pub/publish_release_activity_serializer.rb7
-rw-r--r--app/serializers/activity_pub/releases_actor_serializer.rb2
-rw-r--r--app/serializers/activity_pub/releases_outbox_serializer.rb4
-rw-r--r--app/services/merge_requests/request_review_service.rb5
-rw-r--r--app/services/packages/npm/create_package_service.rb25
-rw-r--r--app/services/system_note_service.rb4
-rw-r--r--app/services/system_notes/issuables_service.rb6
12 files changed, 224 insertions, 101 deletions
diff --git a/app/serializers/activity_pub/activity_serializer.rb b/app/serializers/activity_pub/activity_serializer.rb
new file mode 100644
index 00000000000..71a1bfece6b
--- /dev/null
+++ b/app/serializers/activity_pub/activity_serializer.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+module ActivityPub
+ # Serializer for the `Activity` ActivityStreams model.
+ # Reference: https://www.w3.org/TR/activitystreams-core/#activities
+ class ActivitySerializer < ObjectSerializer
+ MissingActorError = Class.new(StandardError)
+ MissingObjectError = Class.new(StandardError)
+ IntransitiveWithObjectError = Class.new(StandardError)
+
+ private
+
+ def validate_response(serialized, opts)
+ response = super(serialized, opts)
+
+ unless response[:actor].present?
+ raise MissingActorError, "The serializer does not provide the mandatory 'actor' field."
+ end
+
+ if opts[:intransitive] && response[:object].present?
+ raise IntransitiveWithObjectError, <<~ERROR
+ The serializer does provide both the 'object' field and the :intransitive option.
+ Intransitive activities are meant precisely for when no object is available.
+ Please remove either of those.
+ See https://www.w3.org/TR/activitystreams-vocabulary/#activity-types
+ ERROR
+ end
+
+ unless opts[:intransitive] || response[:object].present?
+ raise MissingObjectError, <<~ERROR
+ The serializer does not provide the mandatory 'object' field.
+ Pass the :intransitive option to #represent if this is an intransitive activity.
+ See https://www.w3.org/TR/activitystreams-vocabulary/#activity-types
+ ERROR
+ end
+
+ response
+ end
+ end
+end
diff --git a/app/serializers/activity_pub/activity_streams_serializer.rb b/app/serializers/activity_pub/activity_streams_serializer.rb
deleted file mode 100644
index 39caa4a6d10..00000000000
--- a/app/serializers/activity_pub/activity_streams_serializer.rb
+++ /dev/null
@@ -1,90 +0,0 @@
-# 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
diff --git a/app/serializers/activity_pub/actor_serializer.rb b/app/serializers/activity_pub/actor_serializer.rb
new file mode 100644
index 00000000000..14ab43666ec
--- /dev/null
+++ b/app/serializers/activity_pub/actor_serializer.rb
@@ -0,0 +1,39 @@
+# frozen_string_literal: true
+
+module ActivityPub
+ # Serializer for the `Actor` ActivityStreams model.
+ # Reference: https://www.w3.org/TR/activitystreams-core/#actors
+ class ActorSerializer < ObjectSerializer
+ MissingOutboxError = Class.new(StandardError)
+
+ def represent(resource, opts = {}, entity_class = nil)
+ raise MissingInboxError, 'Please provide an :inbox option for this actor' unless opts[:inbox].present?
+ raise MissingOutboxError, 'Please provide an :outbox option for this actor' unless opts[:outbox].present?
+
+ super
+ end
+
+ private
+
+ def validate_response(response, _opts)
+ 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 wrap(serialized, opts)
+ parent_value = super(serialized, opts)
+
+ {
+ inbox: opts[:inbox],
+ outbox: opts[:outbox]
+ }.merge(parent_value)
+ end
+ end
+end
diff --git a/app/serializers/activity_pub/collection_serializer.rb b/app/serializers/activity_pub/collection_serializer.rb
new file mode 100644
index 00000000000..16c78eb1b7d
--- /dev/null
+++ b/app/serializers/activity_pub/collection_serializer.rb
@@ -0,0 +1,68 @@
+# frozen_string_literal: true
+
+module ActivityPub
+ # Serializer for the `Collection` ActivityStreams model.
+ # Reference: https://www.w3.org/TR/activitystreams-core/#collections
+ class CollectionSerializer < ::BaseSerializer
+ include WithPagination
+
+ NotPaginatedError = Class.new(StandardError)
+
+ alias_method :base_represent, :represent
+
+ def represent(resources, opts = {})
+ unless respond_to?(:paginated?) && paginated?
+ raise NotPaginatedError, 'Pass #with_pagination to the serializer or use ActivityPub::ObjectSerializer instead'
+ end
+
+ response = if paginator.params['page'].present?
+ represent_page(resources, paginator.params['page'].to_i, opts)
+ else
+ represent_pagination_index(resources)
+ end
+
+ HashWithIndifferentAccess.new(response)
+ end
+
+ private
+
+ def represent_page(resources, page, opts)
+ resources = paginator.paginate(resources)
+ opts[:page] = page
+ serialized = base_represent(resources, opts)
+
+ {
+ :@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)
+ paginator.params['page'] = 1
+ resources = paginator.paginate(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
diff --git a/app/serializers/activity_pub/object_serializer.rb b/app/serializers/activity_pub/object_serializer.rb
new file mode 100644
index 00000000000..cdcef59cc41
--- /dev/null
+++ b/app/serializers/activity_pub/object_serializer.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+module ActivityPub
+ # Serializer for the `Object` ActivityStreams model.
+ # Reference: https://www.w3.org/TR/activitystreams-core/#object
+ class ObjectSerializer < ::BaseSerializer
+ MissingIdentifierError = Class.new(StandardError)
+ MissingTypeError = Class.new(StandardError)
+
+ def represent(resource, opts = {}, entity_class = nil)
+ serialized = super(resource, opts, entity_class)
+ response = wrap(serialized, opts)
+
+ validate_response(HashWithIndifferentAccess.new(response), opts)
+ end
+
+ private
+
+ def wrap(serialized, _opts)
+ { :@context => "https://www.w3.org/ns/activitystreams" }.merge(serialized)
+ end
+
+ def validate_response(response, _opts)
+ 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
+ end
+end
diff --git a/app/serializers/activity_pub/publish_release_activity_serializer.rb b/app/serializers/activity_pub/publish_release_activity_serializer.rb
new file mode 100644
index 00000000000..b70ff470af5
--- /dev/null
+++ b/app/serializers/activity_pub/publish_release_activity_serializer.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+module ActivityPub
+ class PublishReleaseActivitySerializer < ActivitySerializer
+ entity ReleaseEntity
+ end
+end
diff --git a/app/serializers/activity_pub/releases_actor_serializer.rb b/app/serializers/activity_pub/releases_actor_serializer.rb
index 5bae83f2dc7..f4b33e25393 100644
--- a/app/serializers/activity_pub/releases_actor_serializer.rb
+++ b/app/serializers/activity_pub/releases_actor_serializer.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module ActivityPub
- class ReleasesActorSerializer < ActivityStreamsSerializer
+ class ReleasesActorSerializer < ActorSerializer
entity ReleasesActorEntity
end
end
diff --git a/app/serializers/activity_pub/releases_outbox_serializer.rb b/app/serializers/activity_pub/releases_outbox_serializer.rb
index b6d4e633fb0..6087e713e64 100644
--- a/app/serializers/activity_pub/releases_outbox_serializer.rb
+++ b/app/serializers/activity_pub/releases_outbox_serializer.rb
@@ -1,9 +1,7 @@
# frozen_string_literal: true
module ActivityPub
- class ReleasesOutboxSerializer < ActivityStreamsSerializer
- include WithPagination
-
+ class ReleasesOutboxSerializer < CollectionSerializer
entity ReleaseEntity
end
end
diff --git a/app/services/merge_requests/request_review_service.rb b/app/services/merge_requests/request_review_service.rb
index ebbae98352b..87b00aa088c 100644
--- a/app/services/merge_requests/request_review_service.rb
+++ b/app/services/merge_requests/request_review_service.rb
@@ -12,6 +12,7 @@ module MergeRequests
notify_reviewer(merge_request, user)
trigger_merge_request_reviewers_updated(merge_request)
+ create_system_note(merge_request, user)
success
else
@@ -25,5 +26,9 @@ module MergeRequests
notification_service.async.review_requested_of_merge_request(merge_request, current_user, reviewer)
todo_service.create_request_review_todo(merge_request, current_user, reviewer)
end
+
+ def create_system_note(merge_request, user)
+ ::SystemNoteService.request_review(merge_request, merge_request.project, current_user, user)
+ end
end
end
diff --git a/app/services/packages/npm/create_package_service.rb b/app/services/packages/npm/create_package_service.rb
index 0f0dc297e9a..a27f059036c 100644
--- a/app/services/packages/npm/create_package_service.rb
+++ b/app/services/packages/npm/create_package_service.rb
@@ -8,24 +8,35 @@ module Packages
PACKAGE_JSON_NOT_ALLOWED_FIELDS = %w[readme readmeFilename licenseText contributors exports].freeze
DEFAULT_LEASE_TIMEOUT = 1.hour.to_i
+ ERROR_REASON_INVALID_PARAMETER = :invalid_parameter
+ ERROR_REASON_PACKAGE_EXISTS = :package_already_exists
+ ERROR_REASON_PACKAGE_LEASE_TAKEN = :package_lease_taken
+ ERROR_REASON_PACKAGE_PROTECTED = :package_attachment_data_empty
+
def execute
- return error('Version is empty.', 400) if version.blank?
- return error('Attachment data is empty.', 400) if attachment['data'].blank?
- return error('Package already exists.', 403) if current_package_exists?
- return error('Package protected.', 403) if current_package_protected?
- return error('File is too large.', 400) if file_size_exceeded?
+ return error('Version is empty.', ERROR_REASON_INVALID_PARAMETER) if version.blank?
+ return error('Attachment data is empty.', ERROR_REASON_INVALID_PARAMETER) if attachment['data'].blank?
+ return error('Package already exists.', ERROR_REASON_PACKAGE_EXISTS) if current_package_exists?
+ return error('Package protected.', ERROR_REASON_PACKAGE_PROTECTED) if current_package_protected?
+ return error('File is too large.', ERROR_REASON_INVALID_PARAMETER) if file_size_exceeded?
package = try_obtain_lease do
ApplicationRecord.transaction { create_npm_package! }
end
- return error('Could not obtain package lease. Please try again.', 400) unless package
+ unless package
+ return error('Could not obtain package lease. Please try again.', ERROR_REASON_PACKAGE_LEASE_TAKEN)
+ end
- package
+ ServiceResponse.success(payload: { package: package })
end
private
+ def error(message, reason)
+ ServiceResponse.error(message: message, reason: reason)
+ end
+
def create_npm_package!
package = create_package!(:npm, name: name, version: version)
diff --git a/app/services/system_note_service.rb b/app/services/system_note_service.rb
index 9175d91119e..fc27303792b 100644
--- a/app/services/system_note_service.rb
+++ b/app/services/system_note_service.rb
@@ -45,6 +45,10 @@ module SystemNoteService
::SystemNotes::IssuablesService.new(noteable: issuable, project: project, author: author).change_issuable_reviewers(old_reviewers)
end
+ def request_review(issuable, project, author, user)
+ ::SystemNotes::IssuablesService.new(noteable: issuable, project: project, author: author).request_review(user)
+ end
+
def change_issuable_contacts(issuable, project, author, added_count, removed_count)
::SystemNotes::IssuablesService.new(noteable: issuable, project: project, author: author).change_issuable_contacts(added_count, removed_count)
end
diff --git a/app/services/system_notes/issuables_service.rb b/app/services/system_notes/issuables_service.rb
index 7857bf20c8f..3f96ca9cefb 100644
--- a/app/services/system_notes/issuables_service.rb
+++ b/app/services/system_notes/issuables_service.rb
@@ -133,6 +133,12 @@ module SystemNotes
create_note(NoteSummary.new(noteable, project, author, body, action: 'reviewer'))
end
+ def request_review(user)
+ body = "#{self.class.issuable_events[:review_requested]} #{user.to_reference}"
+
+ create_note(NoteSummary.new(noteable, project, author, body, action: 'reviewer'))
+ end
+
# Called when the contacts of an issuable are changed or removed
# We intend to reference the contacts but for security we are just
# going to state how many were added/removed for now. See discussion: