diff options
Diffstat (limited to 'app/serializers')
17 files changed, 190 insertions, 59 deletions
diff --git a/app/serializers/README.md b/app/serializers/README.md index d83c2061e0b..6bab3c83e1b 100644 --- a/app/serializers/README.md +++ b/app/serializers/README.md @@ -22,6 +22,10 @@ Using serializers, instead of `to_json` method, has several benefits: * it makes it easier to reduce merge conflicts between CE -> EE * it makes it easier to benefit from domain driven development techniques +## Security considerations + +Consult the `Serialization` section of our [Secure Coding Guidelines](../../doc/development/secure_coding_guidelines.md#serialization) to help avoiding leaking sensitive attributes when using serializers. + ## What is a serializer? A serializer is a class that encapsulates all business rules for building a diff --git a/app/serializers/ci/job_entity.rb b/app/serializers/ci/job_entity.rb index b6b11e54a16..813938c2a18 100644 --- a/app/serializers/ci/job_entity.rb +++ b/app/serializers/ci/job_entity.rb @@ -41,6 +41,8 @@ module Ci expose :scheduled?, as: :scheduled expose :scheduled_at, if: -> (*) { scheduled? } expose :created_at + expose :queued_at + expose :queued_duration expose :updated_at expose :detailed_status, as: :status, with: DetailedStatusEntity expose :callout_message, if: -> (*) { failed? && !job.script_failure? } diff --git a/app/serializers/ci/job_serializer.rb b/app/serializers/ci/job_serializer.rb index 01f9e223943..37213ee284a 100644 --- a/app/serializers/ci/job_serializer.rb +++ b/app/serializers/ci/job_serializer.rb @@ -3,10 +3,5 @@ module Ci class JobSerializer < BaseSerializer entity Ci::JobEntity - - def represent_status(resource) - data = represent(resource, { only: [:status] }) - data.fetch(:status, {}) - end end end diff --git a/app/serializers/cluster_entity.rb b/app/serializers/cluster_entity.rb index df72a994143..8e256863bcd 100644 --- a/app/serializers/cluster_entity.rb +++ b/app/serializers/cluster_entity.rb @@ -19,21 +19,7 @@ class ClusterEntity < Grape::Entity Clusters::ClusterPresenter.new(cluster).show_path # rubocop: disable CodeReuse/Presenter end - expose :gitlab_managed_apps_logs_path, if: -> (*) { logging_enabled? } do |cluster| - Clusters::ClusterPresenter.new(cluster, current_user: request.current_user).gitlab_managed_apps_logs_path # rubocop: disable CodeReuse/Presenter - end - expose :kubernetes_errors do |cluster| Clusters::KubernetesErrorEntity.new(cluster) end - - expose :enable_advanced_logs_querying, if: -> (*) { logging_enabled? } do |cluster| - cluster.elastic_stack_available? - end - - private - - def logging_enabled? - Feature.enabled?(:monitor_logging, object.project) - end end diff --git a/app/serializers/cluster_serializer.rb b/app/serializers/cluster_serializer.rb index f71591612a6..30b8863efa2 100644 --- a/app/serializers/cluster_serializer.rb +++ b/app/serializers/cluster_serializer.rb @@ -10,8 +10,6 @@ class ClusterSerializer < BaseSerializer :cluster_type, :enabled, :environment_scope, - :gitlab_managed_apps_logs_path, - :enable_advanced_logs_querying, :id, :kubernetes_errors, :name, diff --git a/app/serializers/environment_entity.rb b/app/serializers/environment_entity.rb index ac99463bd64..3473b4aebc8 100644 --- a/app/serializers/environment_entity.rb +++ b/app/serializers/environment_entity.rb @@ -66,22 +66,6 @@ class EnvironmentEntity < Grape::Entity environment.available? && can?(current_user, :stop_environment, environment) end - expose :logs_path, if: -> (*) { can_read_pod_logs? } do |environment| - project_logs_path(environment.project, environment_name: environment.name) - end - - expose :logs_api_path, if: -> (*) { can_read_pod_logs? } do |environment| - if environment.elastic_stack_available? - elasticsearch_project_logs_path(environment.project, environment_name: environment.name, format: :json) - else - k8s_project_logs_path(environment.project, environment_name: environment.name, format: :json) - end - end - - expose :enable_advanced_logs_querying, if: -> (*) { can_read_pod_logs? } do |environment| - environment.elastic_stack_available? - end - expose :can_delete do |environment| can?(current_user, :destroy_environment, environment) end @@ -102,11 +86,6 @@ class EnvironmentEntity < Grape::Entity can?(current_user, :update_environment, environment) end - def can_read_pod_logs? - Feature.enabled?(:monitor_logging, environment.project) && - can?(current_user, :read_pod_logs, environment.project) - end - def can_read_deploy_board? can?(current_user, :read_deploy_board, environment.project) end diff --git a/app/serializers/error_tracking/error_entity.rb b/app/serializers/error_tracking/error_entity.rb index 91388e7c3ad..49644ed2fe7 100644 --- a/app/serializers/error_tracking/error_entity.rb +++ b/app/serializers/error_tracking/error_entity.rb @@ -2,7 +2,11 @@ module ErrorTracking class ErrorEntity < Grape::Entity - expose :id, :title, :type, :user_count, :count, + expose :id do |error| + error.id.to_s + end + + expose :title, :type, :user_count, :count, :first_seen, :last_seen, :message, :culprit, :external_url, :project_id, :project_name, :project_slug, :short_id, :status, :frequency diff --git a/app/serializers/integrations/event_entity.rb b/app/serializers/integrations/event_entity.rb index 170f660f334..91bd91dd941 100644 --- a/app/serializers/integrations/event_entity.rb +++ b/app/serializers/integrations/event_entity.rb @@ -18,12 +18,12 @@ module Integrations IntegrationsHelper.integration_event_description(integration, event) end - expose :field, if: ->(_, _) { event_field } do + expose :field, if: ->(_, _) { integration.try(:configurable_channels?) } do expose :name do |event| - event_field[:name] + integration.event_channel_name(event) end expose :value do |event| - integration.public_send(event_field[:name]) # rubocop:disable GitlabSecurity/PublicSend + integration.event_channel_value(event) end end @@ -35,10 +35,6 @@ module Integrations IntegrationsHelper.integration_event_field_name(event) end - def event_field - @event_field ||= integration.event_field(event) - end - def integration request.integration end diff --git a/app/serializers/integrations/harbor_serializers/artifact_entity.rb b/app/serializers/integrations/harbor_serializers/artifact_entity.rb new file mode 100644 index 00000000000..010380561eb --- /dev/null +++ b/app/serializers/integrations/harbor_serializers/artifact_entity.rb @@ -0,0 +1,29 @@ +# frozen_string_literal: true + +module Integrations + module HarborSerializers + class ArtifactEntity < Grape::Entity + include ActionView::Helpers::SanitizeHelper + + expose :harbor_id do |item| + item['id'] + end + + expose :digest do |item| + strip_tags(item['digest']) + end + + expose :size do |item| + item['size'] + end + + expose :push_time do |item| + item['push_time']&.to_datetime&.utc + end + + expose :tags do |item| + item['tags'].map { |tag| strip_tags(tag['name']) } + end + end + end +end diff --git a/app/serializers/integrations/harbor_serializers/artifact_serializer.rb b/app/serializers/integrations/harbor_serializers/artifact_serializer.rb new file mode 100644 index 00000000000..aaf78a72330 --- /dev/null +++ b/app/serializers/integrations/harbor_serializers/artifact_serializer.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +module Integrations + module HarborSerializers + class ArtifactSerializer < BaseSerializer + include WithPagination + + entity ::Integrations::HarborSerializers::ArtifactEntity + end + end +end diff --git a/app/serializers/integrations/harbor_serializers/repository_entity.rb b/app/serializers/integrations/harbor_serializers/repository_entity.rb new file mode 100644 index 00000000000..f03465fe8e2 --- /dev/null +++ b/app/serializers/integrations/harbor_serializers/repository_entity.rb @@ -0,0 +1,57 @@ +# frozen_string_literal: true + +module Integrations + module HarborSerializers + class RepositoryEntity < Grape::Entity + include ActionView::Helpers::SanitizeHelper + + expose :harbor_id do |item| + item['id'] + end + + expose :name do |item| + strip_tags(item['name']) + end + + expose :artifact_count do |item| + item['artifact_count'] + end + + expose :creation_time do |item| + item['creation_time']&.to_datetime&.utc + end + + expose :update_time do |item| + item['update_time']&.to_datetime&.utc + end + + expose :harbor_project_id do |item| + item['project_id'] + end + + expose :pull_count do |item| + item['pull_count'] + end + + expose :location do |item| + path = [ + 'harbor/projects', + item['project_id'].to_s, + 'repositories', + item['name'].remove("#{options[:project_name]}/") + ].join('/') + path = validate_path(path) + strip_tags(Gitlab::Utils.append_path(options[:url], path)) + end + + private + + def validate_path(path) + Gitlab::Utils.check_path_traversal!(path) + rescue ::Gitlab::Utils::PathTraversalAttackError + Gitlab::AppLogger.error("Path traversal attack detected #{path}") + '' + end + end + end +end diff --git a/app/serializers/integrations/harbor_serializers/repository_serializer.rb b/app/serializers/integrations/harbor_serializers/repository_serializer.rb new file mode 100644 index 00000000000..9b9e089eab8 --- /dev/null +++ b/app/serializers/integrations/harbor_serializers/repository_serializer.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +module Integrations + module HarborSerializers + class RepositorySerializer < BaseSerializer + include WithPagination + + entity ::Integrations::HarborSerializers::RepositoryEntity + end + end +end diff --git a/app/serializers/integrations/harbor_serializers/tag_entity.rb b/app/serializers/integrations/harbor_serializers/tag_entity.rb new file mode 100644 index 00000000000..8c26bc1ecbd --- /dev/null +++ b/app/serializers/integrations/harbor_serializers/tag_entity.rb @@ -0,0 +1,41 @@ +# frozen_string_literal: true + +module Integrations + module HarborSerializers + class TagEntity < Grape::Entity + include ActionView::Helpers::SanitizeHelper + + expose :harbor_repository_id do |item| + item['repository_id'] + end + + expose :harbor_artifact_id do |item| + item['artifact_id'] + end + + expose :harbor_id do |item| + item['id'] + end + + expose :name do |item| + strip_tags(item['name']) + end + + expose :pull_time do |item| + item['pull_time']&.to_datetime&.utc + end + + expose :push_time do |item| + item['push_time']&.to_datetime&.utc + end + + expose :signed do |item| + item['signed'] + end + + expose :immutable do |item| + item['immutable'] + end + end + end +end diff --git a/app/serializers/integrations/harbor_serializers/tag_serializer.rb b/app/serializers/integrations/harbor_serializers/tag_serializer.rb new file mode 100644 index 00000000000..7111e65e3e6 --- /dev/null +++ b/app/serializers/integrations/harbor_serializers/tag_serializer.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +module Integrations + module HarborSerializers + class TagSerializer < BaseSerializer + include WithPagination + + entity ::Integrations::HarborSerializers::TagEntity + end + end +end diff --git a/app/serializers/issue_entity.rb b/app/serializers/issue_entity.rb index eba2c49bc2e..ea43ed87d22 100644 --- a/app/serializers/issue_entity.rb +++ b/app/serializers/issue_entity.rb @@ -73,7 +73,7 @@ class IssueEntity < IssuableEntity end expose :archived_project_docs_path, if: -> (issue) { issue.project.archived? } do |issue| - help_page_path('user/project/settings/index.md', anchor: 'archiving-a-project') + help_page_path('user/project/settings/index.md', anchor: 'archive-a-project') end expose :issue_email_participants do |issue| diff --git a/app/serializers/merge_request_basic_entity.rb b/app/serializers/merge_request_basic_entity.rb index 7d45484fc2f..2820c88b293 100644 --- a/app/serializers/merge_request_basic_entity.rb +++ b/app/serializers/merge_request_basic_entity.rb @@ -7,6 +7,7 @@ class MergeRequestBasicEntity < Grape::Entity expose :state expose :source_branch_exists?, as: :source_branch_exists expose :rebase_in_progress?, as: :rebase_in_progress + expose :should_be_rebased?, as: :should_be_rebased expose :milestone, using: API::Entities::Milestone expose :labels, using: LabelEntity expose :assignees, using: API::Entities::UserBasic diff --git a/app/serializers/stage_entity.rb b/app/serializers/stage_entity.rb index 548ff577863..f278ccfce73 100644 --- a/app/serializers/stage_entity.rb +++ b/app/serializers/stage_entity.rb @@ -50,14 +50,6 @@ class StageEntity < Grape::Entity stage.detailed_status(request.current_user) end - def grouped_statuses - @grouped_statuses ||= stage.statuses.latest_ordered.group_by(&:status) - end - - def grouped_retried_statuses - @grouped_retried_statuses ||= stage.statuses.retried_ordered.group_by(&:status) - end - def latest_statuses Ci::HasStatus::ORDERED_STATUSES.flat_map do |ordered_status| grouped_statuses.fetch(ordered_status, []) @@ -69,4 +61,18 @@ class StageEntity < Grape::Entity grouped_retried_statuses.fetch(ordered_status, []) end end + + def grouped_statuses + @grouped_statuses ||= preload_metadata(stage.statuses.latest_ordered).group_by(&:status) + end + + def grouped_retried_statuses + @grouped_retried_statuses ||= preload_metadata(stage.statuses.retried_ordered).group_by(&:status) + end + + def preload_metadata(statuses) + Preloaders::CommitStatusPreloader.new(statuses).execute([:metadata]) + + statuses + end end |