summaryrefslogtreecommitdiff
path: root/app/controllers/projects/services_controller.rb
blob: 105f8efde7b45c5a6fa6dc01bccf55649fbb70b7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
# frozen_string_literal: true

class Projects::ServicesController < Projects::ApplicationController
  include Integrations::Params
  include InternalRedirect

  # Authorize
  before_action :authorize_admin_project!
  before_action :ensure_service_enabled
  before_action :integration
  before_action :default_integration, only: [:edit, :update]
  before_action :web_hook_logs, only: [:edit, :update]
  before_action :set_deprecation_notice_for_prometheus_integration, only: [:edit, :update]
  before_action :redirect_deprecated_prometheus_integration, only: [:update]

  before_action do
    push_frontend_feature_flag(:integration_form_sections, project, default_enabled: :yaml)
  end

  respond_to :html

  layout "project_settings"

  feature_category :integrations
  urgency :low, [:test]

  def edit
  end

  def update
    attributes = integration_params[:integration]

    if use_inherited_settings?(attributes)
      integration.inherit_from_id = default_integration.id

      if saved = integration.save(context: :manual_change)
        BulkUpdateIntegrationService.new(default_integration, [integration]).execute
      end
    else
      attributes[:inherit_from_id] = nil
      integration.attributes = attributes
      saved = integration.save(context: :manual_change)
    end

    respond_to do |format|
      format.html do
        if saved
          redirect_to redirect_path, notice: success_message
        else
          render 'edit'
        end
      end

      format.json do
        status = saved ? :ok : :unprocessable_entity

        render json: serialize_as_json, status: status
      end
    end
  end

  def test
    if integration.testable?
      render json: service_test_response, status: :ok
    else
      render json: {}, status: :not_found
    end
  end

  private

  def redirect_path
    safe_redirect_path(params[:redirect_to]).presence || edit_project_integration_path(project, integration)
  end

  def service_test_response
    unless integration.update(integration_params[:integration])
      return { error: true, message: _('Validations failed.'), service_response: integration.errors.full_messages.join(','), test_failed: false }
    end

    result = ::Integrations::Test::ProjectService.new(integration, current_user, params[:event]).execute

    unless result[:success]
      return { error: true, message: s_('Integrations|Connection failed. Please check your settings.'), service_response: result[:message].to_s, test_failed: true }
    end

    result[:data].presence || {}
  rescue *Gitlab::HTTP::HTTP_ERRORS => e
    { error: true, message: s_('Integrations|Connection failed. Please check your settings.'), service_response: e.message, test_failed: true }
  end

  def success_message
    if integration.active?
      s_('Integrations|%{integration} settings saved and active.') % { integration: integration.title }
    else
      s_('Integrations|%{integration} settings saved, but not active.') % { integration: integration.title }
    end
  end

  def integration
    @integration ||= project.find_or_initialize_integration(params[:id])
  end
  alias_method :service, :integration

  def default_integration
    @default_integration ||= Integration.default_integration(integration.type, project)
  end

  def web_hook_logs
    return unless integration.service_hook.present?

    @web_hook_logs ||= integration.service_hook.web_hook_logs.recent.page(params[:page])
  end

  def ensure_service_enabled
    render_404 unless service
  end

  def serialize_as_json
    integration
      .as_json(only: integration.json_fields)
      .merge(errors: integration.errors.as_json)
  end

  def redirect_deprecated_prometheus_integration
    redirect_to edit_project_integration_path(project, integration) if integration.is_a?(::Integrations::Prometheus) && Feature.enabled?(:settings_operations_prometheus_service, project)
  end

  def set_deprecation_notice_for_prometheus_integration
    return if !integration.is_a?(::Integrations::Prometheus) || !Feature.enabled?(:settings_operations_prometheus_service, project)

    operations_link_start = "<a href=\"#{project_settings_operations_path(project)}\">"
    message = s_('PrometheusService|You can now manage your Prometheus settings on the %{operations_link_start}Operations%{operations_link_end} page. Fields on this page have been deprecated.') % { operations_link_start: operations_link_start, operations_link_end: "</a>" }
    flash.now[:alert] = message.html_safe
  end

  def use_inherited_settings?(attributes)
    default_integration && attributes[:inherit_from_id] == default_integration.id.to_s
  end
end