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:
authorGitLab Bot <gitlab-bot@gitlab.com>2023-07-31 15:07:02 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2023-07-31 15:07:02 +0300
commit74ecf758e30be848144df1672b5080a29fafbc0a (patch)
tree0bc719293526a2384b9db6638d42d49f1f5c9c9c /app
parent26d2324ac136c7a28235789ff9a0b2974b5f7c7b (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app')
-rw-r--r--app/controllers/projects/blob_controller.rb26
-rw-r--r--app/controllers/projects/performance_monitoring/dashboards_controller.rb114
-rw-r--r--app/controllers/search_controller.rb2
-rw-r--r--app/helpers/environments_helper.rb1
-rw-r--r--app/models/concerns/issuable_link.rb2
-rw-r--r--app/models/concerns/linkable_item.rb40
-rw-r--r--app/models/issue.rb24
-rw-r--r--app/models/issue_link.rb9
-rw-r--r--app/models/work_items/parent_link.rb11
-rw-r--r--app/models/work_items/related_work_item_link.rb21
-rw-r--r--app/services/issues/move_service.rb4
-rw-r--r--app/services/metrics/dashboard/clone_dashboard_service.rb170
-rw-r--r--app/services/metrics/dashboard/dynamic_embed_service.rb78
-rw-r--r--app/services/projects/prometheus/alerts/notify_service.rb41
-rw-r--r--app/services/search_service.rb4
15 files changed, 94 insertions, 453 deletions
diff --git a/app/controllers/projects/blob_controller.rb b/app/controllers/projects/blob_controller.rb
index 388135726a0..56e4b22ded2 100644
--- a/app/controllers/projects/blob_controller.rb
+++ b/app/controllers/projects/blob_controller.rb
@@ -274,8 +274,6 @@ class Projects::BlobController < Projects::ApplicationController
@last_commit = @repository.last_commit_for_path(@commit.id, @blob.path, literal_pathspec: true)
@code_navigation_path = Gitlab::CodeNavigationPath.new(@project, @blob.commit_id).full_json_path_for(@blob.path)
- allow_lfs_direct_download
-
render 'show'
end
@@ -320,30 +318,6 @@ class Projects::BlobController < Projects::ApplicationController
current_user&.id
end
- def allow_lfs_direct_download
- return unless directly_downloading_lfs_object? && content_security_policy_enabled?
- return unless (lfs_object = @project.lfs_objects.find_by_oid(@blob.lfs_oid))
-
- request.content_security_policy.directives['connect-src'] ||= []
- request.content_security_policy.directives['connect-src'] << lfs_src(lfs_object)
- end
-
- def directly_downloading_lfs_object?
- Gitlab.config.lfs.enabled &&
- !Gitlab.config.lfs.object_store.proxy_download &&
- @blob&.stored_externally?
- end
-
- def content_security_policy_enabled?
- Gitlab.config.gitlab.content_security_policy.enabled
- end
-
- def lfs_src(lfs_object)
- file = lfs_object.file
- file = file.cdn_enabled_url(request.remote_ip) if file.respond_to?(:cdn_enabled_url)
- file.url
- end
-
alias_method :tracking_project_source, :project
def tracking_namespace_source
diff --git a/app/controllers/projects/performance_monitoring/dashboards_controller.rb b/app/controllers/projects/performance_monitoring/dashboards_controller.rb
deleted file mode 100644
index 1255ec1dde2..00000000000
--- a/app/controllers/projects/performance_monitoring/dashboards_controller.rb
+++ /dev/null
@@ -1,114 +0,0 @@
-# frozen_string_literal: true
-
-module Projects
- module PerformanceMonitoring
- class DashboardsController < ::Projects::ApplicationController
- include BlobHelper
-
- before_action :check_repository_available!
- before_action :validate_required_params!
-
- rescue_from ActionController::ParameterMissing do |exception|
- respond_error(http_status: :bad_request, message: _('Request parameter %{param} is missing.') % { param: exception.param })
- end
-
- feature_category :metrics
- urgency :low
-
- def create
- return not_found if Feature.enabled?(:remove_monitor_metrics)
-
- result = ::Metrics::Dashboard::CloneDashboardService.new(project, current_user, dashboard_params).execute
-
- if result[:status] == :success
- respond_success(result)
- else
- respond_error(result)
- end
- end
-
- def update
- return not_found if Feature.enabled?(:remove_monitor_metrics)
-
- result = ::Metrics::Dashboard::UpdateDashboardService.new(project, current_user, dashboard_params.merge(file_content_params)).execute
-
- if result[:status] == :success
- respond_update_success(result)
- else
- respond_error(result)
- end
- end
-
- private
-
- def respond_success(result)
- set_web_ide_link_notice(result.dig(:dashboard, :path))
- respond_to do |format|
- format.json { render status: result.delete(:http_status), json: result }
- end
- end
-
- def respond_error(result)
- respond_to do |format|
- format.json { render json: { error: result[:message] }, status: result[:http_status] }
- end
- end
-
- def set_web_ide_link_notice(new_dashboard_path)
- web_ide_link_start = "<a href=\"#{ide_edit_path(project, redirect_safe_branch_name, new_dashboard_path)}\">"
- message = _("Your dashboard has been copied. You can %{web_ide_link_start}edit it here%{web_ide_link_end}.") % { web_ide_link_start: web_ide_link_start, web_ide_link_end: "</a>" }
- flash[:notice] = message.html_safe
- end
-
- def respond_update_success(result)
- set_web_ide_link_update_notice(result.dig(:dashboard, :path))
- respond_to do |format|
- format.json { render status: result.delete(:http_status), json: result }
- end
- end
-
- def set_web_ide_link_update_notice(new_dashboard_path)
- web_ide_link_start = "<a href=\"#{ide_edit_path(project, redirect_safe_branch_name, new_dashboard_path)}\">"
- message = _("Your dashboard has been updated. You can %{web_ide_link_start}edit it here%{web_ide_link_end}.") % { web_ide_link_start: web_ide_link_start, web_ide_link_end: "</a>" }
- flash[:notice] = message.html_safe
- end
-
- def validate_required_params!
- params.require(%i[branch file_name dashboard commit_message])
- end
-
- def redirect_safe_branch_name
- repository.find_branch(params[:branch]).name
- end
-
- def dashboard_params
- params.permit(%i[branch file_name dashboard commit_message]).to_h
- end
-
- def file_content_params
- params.permit(
- file_content: [
- :dashboard,
- panel_groups: [
- :group,
- :priority,
- panels: [
- :type,
- :title,
- :y_label,
- :weight,
- metrics: [
- :id,
- :unit,
- :label,
- :query,
- :query_range
- ]
- ]
- ]
- ]
- )
- end
- end
- end
-end
diff --git a/app/controllers/search_controller.rb b/app/controllers/search_controller.rb
index 2d6b51a49fc..af62ff8313d 100644
--- a/app/controllers/search_controller.rb
+++ b/app/controllers/search_controller.rb
@@ -252,7 +252,7 @@ class SearchController < ApplicationController
end
def search_type
- 'basic'
+ search_service.search_type
end
end
diff --git a/app/helpers/environments_helper.rb b/app/helpers/environments_helper.rb
index 219dcf29563..cd768ba8a7b 100644
--- a/app/helpers/environments_helper.rb
+++ b/app/helpers/environments_helper.rb
@@ -54,7 +54,6 @@ module EnvironmentsHelper
{
'settings_path' => edit_project_settings_integration_path(project, 'prometheus'),
'clusters_path' => project_clusters_path(project),
- 'dashboards_endpoint' => project_performance_monitoring_dashboards_path(project, format: :json),
'default_branch' => project.default_branch,
'project_path' => project_path(project),
'tags_path' => project_tags_path(project),
diff --git a/app/models/concerns/issuable_link.rb b/app/models/concerns/issuable_link.rb
index 7f29083d6c6..5cb5f410a77 100644
--- a/app/models/concerns/issuable_link.rb
+++ b/app/models/concerns/issuable_link.rb
@@ -53,7 +53,7 @@ module IssuableLink
return unless source && target
if self.class.base_class.find_by(source: target, target: source)
- errors.add(:source, "is already related to this #{self.class.issuable_type}")
+ errors.add(:source, "is already related to this #{self.class.issuable_type.to_s.humanize(capitalize: false)}")
end
end
end
diff --git a/app/models/concerns/linkable_item.rb b/app/models/concerns/linkable_item.rb
new file mode 100644
index 00000000000..ce45549aca0
--- /dev/null
+++ b/app/models/concerns/linkable_item.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+# == LinkableItem concern
+#
+# Contains common functionality shared between related issue links and related work item links
+#
+# Used by IssueLink, WorkItems::RelatedWorkItemLink
+#
+module LinkableItem
+ extend ActiveSupport::Concern
+ include FromUnion
+ include IssuableLink
+
+ included do
+ validate :check_existing_parent_link
+
+ scope :for_source, ->(item) { where(source_id: item.id) }
+ scope :for_target, ->(item) { where(target_id: item.id) }
+ scope :for_items, ->(source, target) do
+ where(source: source, target: target).or(where(source: target, target: source))
+ end
+
+ private
+
+ def check_existing_parent_link
+ return unless source && target
+
+ existing_relation = WorkItems::ParentLink.for_parents([source, target]).for_children([source, target])
+ return if existing_relation.none?
+
+ errors.add(
+ :source,
+ format(
+ _('is a parent or child of this %{item}'),
+ item: self.class.issuable_type.to_s.humanize(capitalize: false)
+ )
+ )
+ end
+ end
+end
diff --git a/app/models/issue.rb b/app/models/issue.rb
index 6e48dcab9ed..2b280f62ee6 100644
--- a/app/models/issue.rb
+++ b/app/models/issue.rb
@@ -542,18 +542,18 @@ class Issue < ApplicationRecord
end
def related_issues(current_user, preload: nil)
- related_issues = ::Issue
- .select(['issues.*', 'issue_links.id AS issue_link_id',
- 'issue_links.link_type as issue_link_type_value',
- 'issue_links.target_id as issue_link_source_id',
- 'issue_links.created_at as issue_link_created_at',
- 'issue_links.updated_at as issue_link_updated_at'])
- .joins("INNER JOIN issue_links ON
- (issue_links.source_id = issues.id AND issue_links.target_id = #{id})
- OR
- (issue_links.target_id = issues.id AND issue_links.source_id = #{id})")
- .preload(preload)
- .reorder('issue_link_id')
+ related_issues = self.class
+ .select(['issues.*', 'issue_links.id AS issue_link_id',
+ 'issue_links.link_type as issue_link_type_value',
+ 'issue_links.target_id as issue_link_source_id',
+ 'issue_links.created_at as issue_link_created_at',
+ 'issue_links.updated_at as issue_link_updated_at'])
+ .joins("INNER JOIN issue_links ON
+ (issue_links.source_id = issues.id AND issue_links.target_id = #{id})
+ OR
+ (issue_links.target_id = issues.id AND issue_links.source_id = #{id})")
+ .preload(preload)
+ .reorder('issue_link_id')
related_issues = yield related_issues if block_given?
diff --git a/app/models/issue_link.rb b/app/models/issue_link.rb
index af55a5dec91..1c596ad0341 100644
--- a/app/models/issue_link.rb
+++ b/app/models/issue_link.rb
@@ -1,18 +1,11 @@
# frozen_string_literal: true
class IssueLink < ApplicationRecord
- include FromUnion
- include IssuableLink
+ include LinkableItem
belongs_to :source, class_name: 'Issue'
belongs_to :target, class_name: 'Issue'
- scope :for_source_issue, ->(issue) { where(source_id: issue.id) }
- scope :for_target_issue, ->(issue) { where(target_id: issue.id) }
- scope :for_issues, ->(source, target) do
- where(source: source, target: target).or(where(source: target, target: source))
- end
-
class << self
def issuable_type
:issue
diff --git a/app/models/work_items/parent_link.rb b/app/models/work_items/parent_link.rb
index 5dff9e8e8d5..d9e3690b6fc 100644
--- a/app/models/work_items/parent_link.rb
+++ b/app/models/work_items/parent_link.rb
@@ -19,8 +19,10 @@ module WorkItems
validate :validate_same_project
validate :validate_max_children
validate :validate_confidentiality
+ validate :check_existing_related_link
scope :for_parents, ->(parent_ids) { where(work_item_parent_id: parent_ids) }
+ scope :for_children, ->(children_ids) { where(work_item: children_ids) }
class << self
def has_public_children?(parent_id)
@@ -109,5 +111,14 @@ module WorkItems
errors.add :work_item, _('is already present in ancestors')
end
end
+
+ def check_existing_related_link
+ return unless work_item && work_item_parent
+
+ existing_link = WorkItems::RelatedWorkItemLink.for_items(work_item, work_item_parent)
+ return if existing_link.none?
+
+ errors.add(:work_item, _('cannot assign a linked work item as a parent'))
+ end
end
end
diff --git a/app/models/work_items/related_work_item_link.rb b/app/models/work_items/related_work_item_link.rb
new file mode 100644
index 00000000000..1da776fa3bd
--- /dev/null
+++ b/app/models/work_items/related_work_item_link.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+module WorkItems
+ class RelatedWorkItemLink < ApplicationRecord
+ include LinkableItem
+
+ self.table_name = 'issue_links'
+
+ belongs_to :source, class_name: 'WorkItem'
+ belongs_to :target, class_name: 'WorkItem'
+
+ class << self
+ extend ::Gitlab::Utils::Override
+
+ override :issuable_type
+ def issuable_type
+ :work_item
+ end
+ end
+ end
+end
diff --git a/app/services/issues/move_service.rb b/app/services/issues/move_service.rb
index c1599ceef6e..e26e3d0835b 100644
--- a/app/services/issues/move_service.rb
+++ b/app/services/issues/move_service.rb
@@ -123,10 +123,10 @@ module Issues
end
def rewrite_related_issues
- source_issue_links = IssueLink.for_source_issue(original_entity)
+ source_issue_links = IssueLink.for_source(original_entity)
source_issue_links.update_all(source_id: new_entity.id)
- target_issue_links = IssueLink.for_target_issue(original_entity)
+ target_issue_links = IssueLink.for_target(original_entity)
target_issue_links.update_all(target_id: new_entity.id)
end
diff --git a/app/services/metrics/dashboard/clone_dashboard_service.rb b/app/services/metrics/dashboard/clone_dashboard_service.rb
deleted file mode 100644
index b5b46b1280b..00000000000
--- a/app/services/metrics/dashboard/clone_dashboard_service.rb
+++ /dev/null
@@ -1,170 +0,0 @@
-# frozen_string_literal: true
-
-# Copies system dashboard definition in .yml file into designated
-# .yml file inside `.gitlab/dashboards`
-module Metrics
- module Dashboard
- class CloneDashboardService < ::BaseService
- include Stepable
- include Gitlab::Utils::StrongMemoize
-
- ALLOWED_FILE_TYPE = '.yml'
- USER_DASHBOARDS_DIR = ::Gitlab::Metrics::Dashboard::RepoDashboardFinder::DASHBOARD_ROOT
- SEQUENCES = {
- ::Metrics::Dashboard::SystemDashboardService::DASHBOARD_PATH => [
- ::Gitlab::Metrics::Dashboard::Stages::CommonMetricsInserter,
- ::Gitlab::Metrics::Dashboard::Stages::CustomMetricsInserter
- ].freeze
- }.freeze
-
- steps :check_push_authorized,
- :check_branch_name,
- :check_file_type,
- :check_dashboard_template,
- :create_file,
- :refresh_repository_method_caches
-
- def execute
- execute_steps
- end
-
- private
-
- def check_push_authorized(result)
- return error(_('You are not allowed to push into this branch. Create another branch or open a merge request.'), :forbidden) unless push_authorized?
-
- success(result)
- end
-
- def check_branch_name(result)
- return error(_('There was an error creating the dashboard, branch name is invalid.'), :bad_request) unless valid_branch_name?
- return error(_('There was an error creating the dashboard, branch named: %{branch} already exists.') % { branch: params[:branch] }, :bad_request) unless new_or_default_branch?
-
- success(result)
- end
-
- def check_file_type(result)
- return error(_('The file name should have a .yml extension'), :bad_request) unless target_file_type_valid?
-
- success(result)
- end
-
- # Only allow out of the box metrics dashboards to be cloned. This can be
- # changed to allow cloning of any metrics dashboard, if desired.
- # However, only metrics dashboards should be allowed. If any file is
- # allowed to be cloned, this will become a security risk.
- def check_dashboard_template(result)
- return error(_('Not found.'), :not_found) unless dashboard_service&.out_of_the_box_dashboard?
-
- success(result)
- end
-
- def create_file(result)
- create_file_response = ::Files::CreateService.new(project, current_user, dashboard_attrs).execute
-
- if create_file_response[:status] == :success
- success(result.merge(create_file_response))
- else
- wrap_error(create_file_response)
- end
- end
-
- def refresh_repository_method_caches(result)
- repository.refresh_method_caches([:metrics_dashboard])
-
- success(result.merge(http_status: :created, dashboard: dashboard_details))
- end
-
- def dashboard_service
- strong_memoize(:dashboard_service) do
- Gitlab::Metrics::Dashboard::ServiceSelector.call(dashboard_service_options)
- end
- end
-
- def dashboard_attrs
- {
- commit_message: params[:commit_message],
- file_path: new_dashboard_path,
- file_content: new_dashboard_content,
- encoding: 'text',
- branch_name: branch,
- start_branch: repository.branch_exists?(branch) ? branch : project.default_branch
- }
- end
-
- def dashboard_details
- {
- path: new_dashboard_path,
- display_name: ::Metrics::Dashboard::CustomDashboardService.name_for_path(new_dashboard_path),
- default: false,
- system_dashboard: false
- }
- end
-
- def push_authorized?
- Gitlab::UserAccess.new(current_user, container: project).can_push_to_branch?(branch)
- end
-
- def dashboard_template
- @dashboard_template ||= params[:dashboard]
- end
-
- def branch
- @branch ||= params[:branch]
- end
-
- def new_or_default_branch?
- !repository.branch_exists?(params[:branch]) || project.default_branch == params[:branch]
- end
-
- def valid_branch_name?
- Gitlab::GitRefValidator.validate(params[:branch])
- end
-
- def new_dashboard_path
- @new_dashboard_path ||= File.join(USER_DASHBOARDS_DIR, file_name)
- end
-
- def file_name
- @file_name ||= File.basename(params[:file_name])
- end
-
- def target_file_type_valid?
- File.extname(params[:file_name]) == ALLOWED_FILE_TYPE
- end
-
- def wrap_error(result)
- if result[:message] == 'A file with this name already exists'
- error(_("A file with '%{file_name}' already exists in %{branch} branch") % { file_name: file_name, branch: branch }, :bad_request)
- else
- result
- end
- end
-
- def new_dashboard_content
- ::Gitlab::Metrics::Dashboard::Processor
- .new(project, raw_dashboard, sequence, {})
- .process.deep_stringify_keys.to_yaml
- end
-
- def repository
- @repository ||= project.repository
- end
-
- def raw_dashboard
- dashboard_service.new(project, current_user, dashboard_service_options).raw_dashboard
- end
-
- def dashboard_service_options
- {
- embedded: false,
- dashboard_path: dashboard_template
- }
- end
-
- def sequence
- SEQUENCES[dashboard_template] || []
- end
- end
- end
-end
diff --git a/app/services/metrics/dashboard/dynamic_embed_service.rb b/app/services/metrics/dashboard/dynamic_embed_service.rb
deleted file mode 100644
index a94538668c1..00000000000
--- a/app/services/metrics/dashboard/dynamic_embed_service.rb
+++ /dev/null
@@ -1,78 +0,0 @@
-# frozen_string_literal: true
-
-# Responsible for returning a filtered project dashboard
-# containing only the request-provided metrics. The result
-# is then cached for future requests. Metrics are identified
-# based on a combination of identifiers for now, but the ideal
-# would be similar to the approach in DefaultEmbedService, but
-# a single unique identifier is not currently available across
-# all metric types (custom, project-defined, cluster, or system).
-#
-# Use Gitlab::Metrics::Dashboard::Finder to retrive dashboards.
-module Metrics
- module Dashboard
- class DynamicEmbedService < ::Metrics::Dashboard::BaseEmbedService
- include Gitlab::Utils::StrongMemoize
-
- class << self
- # Determines whether the provided params are sufficient
- # to uniquely identify a panel from a yml-defined dashboard.
- #
- # See https://docs.gitlab.com/ee/operations/metrics/dashboards/index.html
- # for additional info on defining custom dashboards.
- def valid_params?(params)
- [
- embedded?(params[:embedded]),
- params[:group].present?,
- params[:title].present?,
- params[:y_label]
- ].all?
- end
- end
-
- # Returns a new dashboard with only the matching
- # metrics from the system dashboard, stripped of groups.
- # @return [Hash]
- def get_raw_dashboard
- not_found! if panels.empty?
-
- { 'panel_groups' => [{ 'panels' => panels }] }
- end
-
- private
-
- def panels
- strong_memoize(:panels) do
- not_found! unless base_dashboard
- not_found! unless groups = base_dashboard['panel_groups']
- not_found! unless matching_group = find_group(groups)
- not_found! unless all_panels = matching_group['panels']
-
- find_panels(all_panels)
- end
- end
-
- def base_dashboard
- strong_memoize(:base_dashboard) do
- Gitlab::Metrics::Dashboard::Finder.find_raw(project, dashboard_path: dashboard_path)
- end
- end
-
- def find_group(groups)
- groups.find do |candidate_group|
- candidate_group['group'] == group
- end
- end
-
- def find_panels(all_panels)
- all_panels.select do |panel|
- panel['title'] == title && panel['y_label'] == y_label
- end
- end
-
- def not_found!
- panels_not_found!(identifiers)
- end
- end
- end
-end
diff --git a/app/services/projects/prometheus/alerts/notify_service.rb b/app/services/projects/prometheus/alerts/notify_service.rb
index 22a882c4648..8f1f78beb5b 100644
--- a/app/services/projects/prometheus/alerts/notify_service.rb
+++ b/app/services/projects/prometheus/alerts/notify_service.rb
@@ -80,8 +80,7 @@ module Projects
def valid_alert_manager_token?(token, integration)
valid_for_alerts_endpoint?(token, integration) ||
- valid_for_manual?(token) ||
- valid_for_cluster?(token)
+ valid_for_manual?(token)
end
def valid_for_manual?(token)
@@ -109,44 +108,6 @@ module Projects
compare_token(token, integration.token)
end
- def valid_for_cluster?(token)
- cluster_integration = find_cluster_integration(project)
- return false unless cluster_integration
-
- cluster_integration_token = cluster_integration.alert_manager_token
-
- if token
- compare_token(token, cluster_integration_token)
- else
- cluster_integration_token.nil?
- end
- end
-
- def find_cluster_integration(project)
- alert_id = gitlab_alert_id
- return unless alert_id
-
- alert = find_alert(project, alert_id)
- return unless alert
-
- cluster = alert.environment.deployment_platform&.cluster
- return unless cluster&.enabled?
- return unless cluster.integration_prometheus_available?
-
- cluster.integration_prometheus
- end
-
- def find_alert(project, metric)
- Projects::Prometheus::AlertsFinder
- .new(project: project, metric: metric)
- .execute
- .first
- end
-
- def gitlab_alert_id
- alerts&.first&.dig('labels', 'gitlab_alert_id')
- end
-
def compare_token(expected, actual)
return unless expected && actual
diff --git a/app/services/search_service.rb b/app/services/search_service.rb
index 433e9b0da6d..3d413ed9f7b 100644
--- a/app/services/search_service.rb
+++ b/app/services/search_service.rb
@@ -44,6 +44,10 @@ class SearchService
project.blank? && group.blank?
end
+ def search_type
+ 'basic'
+ end
+
def show_snippets?
strong_memoize(:show_snippets) do
params[:snippets] == 'true'