summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app/controllers/projects/settings/operations_controller.rb2
-rw-r--r--app/models/project.rb2
-rw-r--r--app/models/project_metrics_setting.rb9
-rw-r--r--app/services/projects/operations/update_service.rb11
-rw-r--r--changelogs/unreleased/57171-add-dashboard-settings.yml5
-rw-r--r--config/locales/en.yml2
-rw-r--r--db/migrate/20190422082247_create_project_metrics_settings.rb14
-rw-r--r--db/schema.rb7
-rw-r--r--lib/gitlab/import_export/import_export.yml1
-rw-r--r--lib/gitlab/import_export/relation_factory.rb3
-rw-r--r--spec/controllers/projects/settings/operations_controller_spec.rb14
-rw-r--r--spec/factories/project_metrics_settings.rb8
-rw-r--r--spec/lib/gitlab/import_export/all_models.yml3
-rw-r--r--spec/lib/gitlab/import_export/safe_model_attributes.yml6
-rw-r--r--spec/models/project_metrics_setting_spec.rb55
-rw-r--r--spec/services/projects/operations/update_service_spec.rb50
16 files changed, 188 insertions, 4 deletions
diff --git a/app/controllers/projects/settings/operations_controller.rb b/app/controllers/projects/settings/operations_controller.rb
index 1fafc33e917..5cfb0ac307d 100644
--- a/app/controllers/projects/settings/operations_controller.rb
+++ b/app/controllers/projects/settings/operations_controller.rb
@@ -56,6 +56,8 @@ module Projects
# overridden in EE
def permitted_project_params
{
+ metrics_setting_attributes: [:external_dashboard_url],
+
error_tracking_setting_attributes: [
:enabled,
:api_host,
diff --git a/app/models/project.rb b/app/models/project.rb
index 626ff9e1389..a29100405f9 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -188,6 +188,7 @@ class Project < ApplicationRecord
has_one :import_export_upload, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
has_one :project_repository, inverse_of: :project
has_one :error_tracking_setting, inverse_of: :project, class_name: 'ErrorTracking::ProjectErrorTrackingSetting'
+ has_one :metrics_setting, inverse_of: :project, class_name: 'ProjectMetricsSetting'
# Merge Requests for target project should be removed with it
has_many :merge_requests, foreign_key: 'target_project_id', inverse_of: :target_project
@@ -297,6 +298,7 @@ class Project < ApplicationRecord
reject_if: ->(attrs) { attrs[:id].blank? && attrs[:url].blank? }
accepts_nested_attributes_for :error_tracking_setting, update_only: true
+ accepts_nested_attributes_for :metrics_setting, update_only: true, allow_destroy: true
delegate :name, to: :owner, allow_nil: true, prefix: true
delegate :members, to: :team, prefix: true
diff --git a/app/models/project_metrics_setting.rb b/app/models/project_metrics_setting.rb
new file mode 100644
index 00000000000..a2a7dc571a4
--- /dev/null
+++ b/app/models/project_metrics_setting.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class ProjectMetricsSetting < ApplicationRecord
+ belongs_to :project
+
+ validates :external_dashboard_url,
+ length: { maximum: 255 },
+ addressable_url: { enforce_sanitization: true, ascii_only: true }
+end
diff --git a/app/services/projects/operations/update_service.rb b/app/services/projects/operations/update_service.rb
index aedf79c86d7..48eddb0e8d0 100644
--- a/app/services/projects/operations/update_service.rb
+++ b/app/services/projects/operations/update_service.rb
@@ -12,7 +12,16 @@ module Projects
private
def project_update_params
- error_tracking_params
+ error_tracking_params.merge(metrics_setting_params)
+ end
+
+ def metrics_setting_params
+ attribs = params[:metrics_setting_attributes]
+ return {} unless attribs
+
+ destroy = attribs[:external_dashboard_url].blank?
+
+ { metrics_setting_attributes: attribs.merge(_destroy: destroy) }
end
def error_tracking_params
diff --git a/changelogs/unreleased/57171-add-dashboard-settings.yml b/changelogs/unreleased/57171-add-dashboard-settings.yml
new file mode 100644
index 00000000000..f235872b35c
--- /dev/null
+++ b/changelogs/unreleased/57171-add-dashboard-settings.yml
@@ -0,0 +1,5 @@
+---
+title: Add backend support for a External Dashboard URL setting
+merge_request: 27550
+author:
+type: added
diff --git a/config/locales/en.yml b/config/locales/en.yml
index eb3b7771968..a3dceb2fb62 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -14,6 +14,8 @@ en:
token: "Auth Token"
project: "Project"
api_url: "Sentry API URL"
+ project/metrics_setting:
+ external_dashboard_url: "External dashboard URL"
errors:
messages:
label_already_exists_at_group_level: "already exists at group level for %{group}. Please choose another one."
diff --git a/db/migrate/20190422082247_create_project_metrics_settings.rb b/db/migrate/20190422082247_create_project_metrics_settings.rb
new file mode 100644
index 00000000000..3e21dd0a934
--- /dev/null
+++ b/db/migrate/20190422082247_create_project_metrics_settings.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+class CreateProjectMetricsSettings < ActiveRecord::Migration[5.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def change
+ create_table :project_metrics_settings, id: :int, primary_key: :project_id, default: nil do |t|
+ t.string :external_dashboard_url, null: false
+ t.foreign_key :projects, column: :project_id, on_delete: :cascade
+ end
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 3a5d567ac57..23566a31a9d 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema.define(version: 20190408163745) do
+ActiveRecord::Schema.define(version: 20190422082247) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@@ -1681,6 +1681,10 @@ ActiveRecord::Schema.define(version: 20190408163745) do
t.index ["project_id"], name: "index_project_import_data_on_project_id", using: :btree
end
+ create_table "project_metrics_settings", primary_key: "project_id", id: :integer, default: nil, force: :cascade do |t|
+ t.string "external_dashboard_url", null: false
+ end
+
create_table "project_mirror_data", id: :serial, force: :cascade do |t|
t.integer "project_id", null: false
t.string "status"
@@ -2529,6 +2533,7 @@ ActiveRecord::Schema.define(version: 20190408163745) do
add_foreign_key "project_features", "projects", name: "fk_18513d9b92", on_delete: :cascade
add_foreign_key "project_group_links", "projects", name: "fk_daa8cee94c", on_delete: :cascade
add_foreign_key "project_import_data", "projects", name: "fk_ffb9ee3a10", on_delete: :cascade
+ add_foreign_key "project_metrics_settings", "projects", on_delete: :cascade
add_foreign_key "project_mirror_data", "projects", on_delete: :cascade
add_foreign_key "project_repositories", "projects", on_delete: :cascade
add_foreign_key "project_repositories", "shards", on_delete: :restrict
diff --git a/lib/gitlab/import_export/import_export.yml b/lib/gitlab/import_export/import_export.yml
index ce268793128..c6d4fda4af5 100644
--- a/lib/gitlab/import_export/import_export.yml
+++ b/lib/gitlab/import_export/import_export.yml
@@ -75,6 +75,7 @@ project_tree:
- :project_badges
- :ci_cd_settings
- :error_tracking_setting
+ - :metrics_setting
# Only include the following attributes for the models specified.
included_attributes:
diff --git a/lib/gitlab/import_export/relation_factory.rb b/lib/gitlab/import_export/relation_factory.rb
index 61a1aa6da5a..e1e70a008d9 100644
--- a/lib/gitlab/import_export/relation_factory.rb
+++ b/lib/gitlab/import_export/relation_factory.rb
@@ -25,7 +25,8 @@ module Gitlab
metrics: 'MergeRequest::Metrics',
ci_cd_settings: 'ProjectCiCdSetting',
error_tracking_setting: 'ErrorTracking::ProjectErrorTrackingSetting',
- links: 'Releases::Link' }.freeze
+ links: 'Releases::Link',
+ metrics_setting: 'ProjectMetricsSetting' }.freeze
USER_REFERENCES = %w[author_id assignee_id updated_by_id merged_by_id latest_closed_by_id user_id created_by_id last_edited_by_id merge_user_id resolved_by_id closed_by_id].freeze
diff --git a/spec/controllers/projects/settings/operations_controller_spec.rb b/spec/controllers/projects/settings/operations_controller_spec.rb
index 0dd73972098..aa9cd41ed19 100644
--- a/spec/controllers/projects/settings/operations_controller_spec.rb
+++ b/spec/controllers/projects/settings/operations_controller_spec.rb
@@ -166,6 +166,20 @@ describe Projects::Settings::OperationsController do
end
end
+ context 'metrics dashboard setting' do
+ describe 'PATCH #update' do
+ let(:params) do
+ {
+ metrics_setting_attributes: {
+ external_dashboard_url: 'https://gitlab.com'
+ }
+ }
+ end
+
+ it_behaves_like 'PATCHable'
+ end
+ end
+
private
def project_params(project, params = {})
diff --git a/spec/factories/project_metrics_settings.rb b/spec/factories/project_metrics_settings.rb
new file mode 100644
index 00000000000..234753f9b87
--- /dev/null
+++ b/spec/factories/project_metrics_settings.rb
@@ -0,0 +1,8 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :project_metrics_setting, class: ProjectMetricsSetting do
+ project
+ external_dashboard_url 'https://grafana.com'
+ end
+end
diff --git a/spec/lib/gitlab/import_export/all_models.yml b/spec/lib/gitlab/import_export/all_models.yml
index 54369ff75f4..482e9c05da8 100644
--- a/spec/lib/gitlab/import_export/all_models.yml
+++ b/spec/lib/gitlab/import_export/all_models.yml
@@ -322,6 +322,7 @@ project:
- pool_repository
- kubernetes_namespaces
- error_tracking_setting
+- metrics_setting
award_emoji:
- awardable
- user
@@ -360,3 +361,5 @@ error_tracking_setting:
- project
suggestions:
- note
+metrics_setting:
+- project
diff --git a/spec/lib/gitlab/import_export/safe_model_attributes.yml b/spec/lib/gitlab/import_export/safe_model_attributes.yml
index ebb62124cb1..591a3d296c2 100644
--- a/spec/lib/gitlab/import_export/safe_model_attributes.yml
+++ b/spec/lib/gitlab/import_export/safe_model_attributes.yml
@@ -606,7 +606,6 @@ ResourceLabelEvent:
- user_id
- created_at
ErrorTracking::ProjectErrorTrackingSetting:
-- id
- api_url
- project_id
- project_name
@@ -626,3 +625,8 @@ MergeRequestAssignee:
- id
- user_id
- merge_request_id
+ProjectMetricsSetting:
+- project_id
+- external_dashboard_url
+- created_at
+- updated_at
diff --git a/spec/models/project_metrics_setting_spec.rb b/spec/models/project_metrics_setting_spec.rb
new file mode 100644
index 00000000000..7df01625ba1
--- /dev/null
+++ b/spec/models/project_metrics_setting_spec.rb
@@ -0,0 +1,55 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe ProjectMetricsSetting do
+ describe 'Associations' do
+ it { is_expected.to belong_to(:project) }
+ end
+
+ describe 'Validations' do
+ context 'when external_dashboard_url is over 255 chars' do
+ before do
+ subject.external_dashboard_url = 'https://' + 'a' * 250
+ end
+
+ it 'fails validation' do
+ expect(subject).not_to be_valid
+ expect(subject.errors.messages[:external_dashboard_url])
+ .to include('is too long (maximum is 255 characters)')
+ end
+ end
+
+ context 'with unsafe url' do
+ before do
+ subject.external_dashboard_url = %{https://replaceme.com/'><script>alert(document.cookie)</script>}
+ end
+
+ it { is_expected.to be_invalid }
+ end
+
+ context 'non ascii chars in external_dashboard_url' do
+ before do
+ subject.external_dashboard_url = 'http://gitlab.com/api/0/projects/project1/something€'
+ end
+
+ it { is_expected.to be_invalid }
+ end
+
+ context 'internal url in external_dashboard_url' do
+ before do
+ subject.external_dashboard_url = 'http://192.168.1.1'
+ end
+
+ it { is_expected.to be_valid }
+ end
+
+ context 'external_dashboard_url is blank' do
+ before do
+ subject.external_dashboard_url = ''
+ end
+
+ it { is_expected.to be_invalid }
+ end
+ end
+end
diff --git a/spec/services/projects/operations/update_service_spec.rb b/spec/services/projects/operations/update_service_spec.rb
index 86b1ec83f50..7e765659b9d 100644
--- a/spec/services/projects/operations/update_service_spec.rb
+++ b/spec/services/projects/operations/update_service_spec.rb
@@ -11,6 +11,56 @@ describe Projects::Operations::UpdateService do
subject { described_class.new(project, user, params) }
describe '#execute' do
+ context 'metrics dashboard setting' do
+ let(:params) do
+ {
+ metrics_setting_attributes: {
+ external_dashboard_url: 'http://gitlab.com'
+ }
+ }
+ end
+
+ context 'without existing metrics dashboard setting' do
+ it 'creates a setting' do
+ expect(result[:status]).to eq(:success)
+
+ expect(project.reload.metrics_setting.external_dashboard_url).to eq(
+ 'http://gitlab.com'
+ )
+ end
+ end
+
+ context 'with existing metrics dashboard setting' do
+ before do
+ create(:project_metrics_setting, project: project)
+ end
+
+ it 'updates the settings' do
+ expect(result[:status]).to eq(:success)
+
+ expect(project.reload.metrics_setting.external_dashboard_url).to eq(
+ 'http://gitlab.com'
+ )
+ end
+
+ context 'with blank external_dashboard_url in params' do
+ let(:params) do
+ {
+ metrics_setting_attributes: {
+ external_dashboard_url: ''
+ }
+ }
+ end
+
+ it 'destroys the metrics_setting entry in DB' do
+ expect(result[:status]).to eq(:success)
+
+ expect(project.reload.metrics_setting).to be_nil
+ end
+ end
+ end
+ end
+
context 'error tracking' do
context 'with existing error tracking setting' do
let(:params) do