summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFilipa Lacerda <filipa@gitlab.com>2018-08-01 15:17:47 +0000
committerFilipa Lacerda <filipa@gitlab.com>2018-08-01 15:17:47 +0000
commitea6fc714bb0306ac8ca56b5dafe4b6777aafe5fc (patch)
tree5d9673f0e526acbdb3285147024064f89d45dc23
parent47244ad5ea4e887ecb6dffa9f7b96846adbf4b6f (diff)
parent29dd1c14db6899c3858ca906e076c7b7fbbaa0e2 (diff)
downloadgitlab-ce-ea6fc714bb0306ac8ca56b5dafe4b6777aafe5fc.tar.gz
Merge branch '41416-making-instance-wide-data-tools-more-accessible' into 'master'
Resolve "Making instance-wide data tools more accessible" Closes #41416 and #48507 See merge request gitlab-org/gitlab-ce!20874
-rw-r--r--app/controllers/admin/conversational_development_index_controller.rb5
-rw-r--r--app/controllers/instance_statistics/application_controller.rb10
-rw-r--r--app/controllers/instance_statistics/cohorts_controller.rb (renamed from app/controllers/admin/cohorts_controller.rb)4
-rw-r--r--app/controllers/instance_statistics/conversational_development_index_controller.rb7
-rw-r--r--app/helpers/application_settings_helper.rb1
-rw-r--r--app/models/application_setting.rb1
-rw-r--r--app/policies/global_policy.rb5
-rw-r--r--app/views/admin/application_settings/_usage.html.haml5
-rw-r--r--app/views/instance_statistics/cohorts/_cohorts_table.html.haml (renamed from app/views/admin/cohorts/_cohorts_table.html.haml)0
-rw-r--r--app/views/instance_statistics/cohorts/_usage_ping.html.haml (renamed from app/views/admin/cohorts/_usage_ping.html.haml)0
-rw-r--r--app/views/instance_statistics/cohorts/index.html.haml (renamed from app/views/admin/cohorts/index.html.haml)0
-rw-r--r--app/views/instance_statistics/conversational_development_index/_callout.html.haml (renamed from app/views/admin/conversational_development_index/_callout.html.haml)0
-rw-r--r--app/views/instance_statistics/conversational_development_index/_card.html.haml (renamed from app/views/admin/conversational_development_index/_card.html.haml)0
-rw-r--r--app/views/instance_statistics/conversational_development_index/_disabled.html.haml (renamed from app/views/admin/conversational_development_index/_disabled.html.haml)0
-rw-r--r--app/views/instance_statistics/conversational_development_index/_no_data.html.haml (renamed from app/views/admin/conversational_development_index/_no_data.html.haml)0
-rw-r--r--app/views/instance_statistics/conversational_development_index/index.html.haml (renamed from app/views/admin/conversational_development_index/show.html.haml)0
-rw-r--r--app/views/layouts/instance_statistics.html.haml6
-rw-r--r--app/views/layouts/nav/_dashboard.html.haml8
-rw-r--r--app/views/layouts/nav/sidebar/_admin.html.haml12
-rw-r--r--app/views/layouts/nav/sidebar/_instance_statistics.html.haml33
-rw-r--r--changelogs/unreleased/41416-making-instance-wide-data-tools-more-accessible.yml5
-rw-r--r--config/routes.rb2
-rw-r--r--config/routes/admin.rb4
-rw-r--r--config/routes/instance_statistics.rb8
-rw-r--r--db/migrate/20180718005113_add_instance_statistics_visibility_to_application_setting.rb20
-rw-r--r--db/schema.rb1
-rw-r--r--doc/api/settings.md7
-rw-r--r--lib/api/settings.rb4
-rw-r--r--locale/gitlab.pot12
-rw-r--r--spec/controllers/instance_statistics/cohorts_controller_spec.rb7
-rw-r--r--spec/controllers/instance_statistics/conversational_development_index_controller_spec.rb7
-rw-r--r--spec/features/dashboard/active_tab_spec.rb28
-rw-r--r--spec/features/dashboard/instance_statistics_spec.rb60
-rw-r--r--spec/features/instance_statistics/cohorts_spec.rb (renamed from spec/features/admin/admin_cohorts_spec.rb)4
-rw-r--r--spec/features/instance_statistics/conversational_development_index_spec.rb (renamed from spec/features/admin/admin_conversational_development_index_spec.rb)8
-rw-r--r--spec/policies/global_policy_spec.rb34
-rw-r--r--spec/requests/api/settings_spec.rb5
-rw-r--r--spec/routing/instance_statistics_routing_spec.rb11
-rw-r--r--spec/support/shared_examples/instance_statistics_controllers_shared_examples.rb37
39 files changed, 315 insertions, 46 deletions
diff --git a/app/controllers/admin/conversational_development_index_controller.rb b/app/controllers/admin/conversational_development_index_controller.rb
deleted file mode 100644
index 921169d3e2b..00000000000
--- a/app/controllers/admin/conversational_development_index_controller.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-class Admin::ConversationalDevelopmentIndexController < Admin::ApplicationController
- def show
- @metric = ConversationalDevelopmentIndex::Metric.order(:created_at).last&.present
- end
-end
diff --git a/app/controllers/instance_statistics/application_controller.rb b/app/controllers/instance_statistics/application_controller.rb
new file mode 100644
index 00000000000..a273dde105c
--- /dev/null
+++ b/app/controllers/instance_statistics/application_controller.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+class InstanceStatistics::ApplicationController < ApplicationController
+ before_action :authorize_read_instance_statistics!
+ layout 'instance_statistics'
+
+ def authorize_read_instance_statistics!
+ render_404 unless can?(current_user, :read_instance_statistics)
+ end
+end
diff --git a/app/controllers/admin/cohorts_controller.rb b/app/controllers/instance_statistics/cohorts_controller.rb
index 10d9d1b5345..7eba0a5ecdd 100644
--- a/app/controllers/admin/cohorts_controller.rb
+++ b/app/controllers/instance_statistics/cohorts_controller.rb
@@ -1,4 +1,6 @@
-class Admin::CohortsController < Admin::ApplicationController
+# frozen_string_literal: true
+
+class InstanceStatistics::CohortsController < InstanceStatistics::ApplicationController
def index
if Gitlab::CurrentSettings.usage_ping_enabled
cohorts_results = Rails.cache.fetch('cohorts', expires_in: 1.day) do
diff --git a/app/controllers/instance_statistics/conversational_development_index_controller.rb b/app/controllers/instance_statistics/conversational_development_index_controller.rb
new file mode 100644
index 00000000000..d6d2191849f
--- /dev/null
+++ b/app/controllers/instance_statistics/conversational_development_index_controller.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+class InstanceStatistics::ConversationalDevelopmentIndexController < InstanceStatistics::ApplicationController
+ def index
+ @metric = ConversationalDevelopmentIndex::Metric.order(:created_at).last&.present
+ end
+end
diff --git a/app/helpers/application_settings_helper.rb b/app/helpers/application_settings_helper.rb
index da54988ccfe..a9499140f8a 100644
--- a/app/helpers/application_settings_helper.rb
+++ b/app/helpers/application_settings_helper.rb
@@ -252,6 +252,7 @@ module ApplicationSettingsHelper
:unique_ips_limit_per_user,
:unique_ips_limit_time_window,
:usage_ping_enabled,
+ :instance_statistics_visibility_private,
:user_default_external,
:user_oauth_applications,
:version_check_enabled
diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb
index a5b3116a48a..17297769e7e 100644
--- a/app/models/application_setting.rb
+++ b/app/models/application_setting.rb
@@ -295,6 +295,7 @@ class ApplicationSetting < ActiveRecord::Base
unique_ips_limit_per_user: 10,
unique_ips_limit_time_window: 3600,
usage_ping_enabled: Settings.gitlab['usage_ping_enabled'],
+ instance_statistics_visibility_private: false,
user_default_external: false
}
end
diff --git a/app/policies/global_policy.rb b/app/policies/global_policy.rb
index 6e3827736b2..16c58730878 100644
--- a/app/policies/global_policy.rb
+++ b/app/policies/global_policy.rb
@@ -19,6 +19,11 @@ class GlobalPolicy < BasePolicy
@user&.required_terms_not_accepted?
end
+ condition(:private_instance_statistics, score: 0) { Gitlab::CurrentSettings.instance_statistics_visibility_private? }
+
+ rule { admin | (~private_instance_statistics & ~anonymous) }
+ .enable :read_instance_statistics
+
rule { anonymous }.policy do
prevent :log_in
prevent :receive_notifications
diff --git a/app/views/admin/application_settings/_usage.html.haml b/app/views/admin/application_settings/_usage.html.haml
index 49a3ee33a85..60ee9ebe6aa 100644
--- a/app/views/admin/application_settings/_usage.html.haml
+++ b/app/views/admin/application_settings/_usage.html.haml
@@ -23,13 +23,16 @@
periodically collect usage information.
= link_to 'Learn more', help_page_path("user/admin_area/settings/usage_statistics", anchor: "usage-ping")
about what information is shared with GitLab Inc. Visit
- = link_to 'Cohorts', admin_cohorts_path(anchor: 'usage-ping')
+ = link_to _('Cohorts'), instance_statistics_cohorts_path(anchor: 'usage-ping')
to see the JSON payload sent.
- else
The usage ping is disabled, and cannot be configured through this
form. For more information, see the documentation on
= succeed '.' do
= link_to 'deactivating the usage ping', help_page_path('user/admin_area/settings/usage_statistics', anchor: 'deactivate-the-usage-ping')
+ .form-group
+ = f.label :instance_statistics_visibility_private, _('Instance Statistics visibility')
+ = f.select :instance_statistics_visibility_private, options_for_select({_('All users') => false, _('Only admins') => true}, Gitlab::CurrentSettings.instance_statistics_visibility_private?), {}, class: 'form-control'
= f.submit 'Save changes', class: "btn btn-success"
diff --git a/app/views/admin/cohorts/_cohorts_table.html.haml b/app/views/instance_statistics/cohorts/_cohorts_table.html.haml
index 701a4e62b39..701a4e62b39 100644
--- a/app/views/admin/cohorts/_cohorts_table.html.haml
+++ b/app/views/instance_statistics/cohorts/_cohorts_table.html.haml
diff --git a/app/views/admin/cohorts/_usage_ping.html.haml b/app/views/instance_statistics/cohorts/_usage_ping.html.haml
index 3dda386fcf7..3dda386fcf7 100644
--- a/app/views/admin/cohorts/_usage_ping.html.haml
+++ b/app/views/instance_statistics/cohorts/_usage_ping.html.haml
diff --git a/app/views/admin/cohorts/index.html.haml b/app/views/instance_statistics/cohorts/index.html.haml
index 5e9a8c083af..5e9a8c083af 100644
--- a/app/views/admin/cohorts/index.html.haml
+++ b/app/views/instance_statistics/cohorts/index.html.haml
diff --git a/app/views/admin/conversational_development_index/_callout.html.haml b/app/views/instance_statistics/conversational_development_index/_callout.html.haml
index 33a4dab1e00..33a4dab1e00 100644
--- a/app/views/admin/conversational_development_index/_callout.html.haml
+++ b/app/views/instance_statistics/conversational_development_index/_callout.html.haml
diff --git a/app/views/admin/conversational_development_index/_card.html.haml b/app/views/instance_statistics/conversational_development_index/_card.html.haml
index 57eda06630b..57eda06630b 100644
--- a/app/views/admin/conversational_development_index/_card.html.haml
+++ b/app/views/instance_statistics/conversational_development_index/_card.html.haml
diff --git a/app/views/admin/conversational_development_index/_disabled.html.haml b/app/views/instance_statistics/conversational_development_index/_disabled.html.haml
index 0a741b50960..0a741b50960 100644
--- a/app/views/admin/conversational_development_index/_disabled.html.haml
+++ b/app/views/instance_statistics/conversational_development_index/_disabled.html.haml
diff --git a/app/views/admin/conversational_development_index/_no_data.html.haml b/app/views/instance_statistics/conversational_development_index/_no_data.html.haml
index d69c46194b4..d69c46194b4 100644
--- a/app/views/admin/conversational_development_index/_no_data.html.haml
+++ b/app/views/instance_statistics/conversational_development_index/_no_data.html.haml
diff --git a/app/views/admin/conversational_development_index/show.html.haml b/app/views/instance_statistics/conversational_development_index/index.html.haml
index e3d1aa31dc2..e3d1aa31dc2 100644
--- a/app/views/admin/conversational_development_index/show.html.haml
+++ b/app/views/instance_statistics/conversational_development_index/index.html.haml
diff --git a/app/views/layouts/instance_statistics.html.haml b/app/views/layouts/instance_statistics.html.haml
new file mode 100644
index 00000000000..bebd9c4536f
--- /dev/null
+++ b/app/views/layouts/instance_statistics.html.haml
@@ -0,0 +1,6 @@
+- page_title _('Instance Statistics')
+- header_title _('Instance Statistics'), instance_statistics_root_path
+- nav 'instance_statistics'
+- @left_sidebar = true
+
+= render template: 'layouts/application'
diff --git a/app/views/layouts/nav/_dashboard.html.haml b/app/views/layouts/nav/_dashboard.html.haml
index a71a4b13a7e..5e467c862ab 100644
--- a/app/views/layouts/nav/_dashboard.html.haml
+++ b/app/views/layouts/nav/_dashboard.html.haml
@@ -64,11 +64,15 @@
= link_to '#', class: 'dashboard-shortcuts-web-ide', title: _('Web IDE') do
= _('Web IDE')
- - if current_user.admin? || Gitlab::Sherlock.enabled?
+ - if Gitlab::Sherlock.enabled? || can?(current_user, :read_instance_statistics)
%li.line-separator.d-none.d-sm-block
+ - if can?(current_user, :read_instance_statistics)
+ = nav_link(controller: [:conversational_development_index, :cohorts]) do
+ = link_to instance_statistics_root_path, title: _('Instance Statistics'), aria: { label: _('Instance Statistics') }, data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do
+ = sprite_icon('chart', size: 18)
- if current_user.admin?
= nav_link(controller: 'admin/dashboard') do
- = link_to admin_root_path, class: 'admin-icon qa-admin-area-link', title: _('Admin area'), aria: { label: _("Admin area") }, data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do
+ = link_to admin_root_path, class: 'admin-icon qa-admin-area-link', title: _('Admin area'), aria: { label: _('Admin area') }, data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do
= sprite_icon('admin', size: 18)
- if Gitlab::Sherlock.enabled?
%li
diff --git a/app/views/layouts/nav/sidebar/_admin.html.haml b/app/views/layouts/nav/sidebar/_admin.html.haml
index 0047efa363d..ff25b040913 100644
--- a/app/views/layouts/nav/sidebar/_admin.html.haml
+++ b/app/views/layouts/nav/sidebar/_admin.html.haml
@@ -7,14 +7,14 @@
.sidebar-context-title
= _('Admin Area')
%ul.sidebar-top-level-items
- = nav_link(controller: %w(dashboard admin projects users groups jobs runners gitaly_servers cohorts conversational_development_index), html_options: {class: 'home'}) do
+ = nav_link(controller: %w(dashboard admin projects users groups jobs runners gitaly_servers), html_options: {class: 'home'}) do
= link_to admin_root_path, class: 'shortcuts-tree' do
.nav-icon-container
= sprite_icon('overview')
%span.nav-item-name
= _('Overview')
%ul.sidebar-sub-level-items
- = nav_link(controller: %w(dashboard admin projects users groups jobs runners gitaly_servers cohorts conversational_development_index), html_options: { class: "fly-out-top-item" } ) do
+ = nav_link(controller: %w(dashboard admin projects users groups jobs runners gitaly_servers), html_options: { class: "fly-out-top-item" } ) do
= link_to admin_root_path do
%strong.fly-out-top-item-name
= _('Overview')
@@ -47,14 +47,6 @@
= link_to admin_gitaly_servers_path, title: 'Gitaly Servers' do
%span
= _('Gitaly Servers')
- = nav_link path: 'cohorts#index' do
- = link_to admin_cohorts_path, title: _('Cohorts') do
- %span
- = _('Cohorts')
- = nav_link(controller: :conversational_development_index) do
- = link_to admin_conversational_development_index_path, title: _('ConvDev Index') do
- %span
- = _('ConvDev Index')
= nav_link(controller: %w(system_info background_jobs logs health_check requests_profiles)) do
= link_to admin_system_info_path do
diff --git a/app/views/layouts/nav/sidebar/_instance_statistics.html.haml b/app/views/layouts/nav/sidebar/_instance_statistics.html.haml
new file mode 100644
index 00000000000..b8ff448f261
--- /dev/null
+++ b/app/views/layouts/nav/sidebar/_instance_statistics.html.haml
@@ -0,0 +1,33 @@
+.nav-sidebar{ class: ("sidebar-collapsed-desktop" if collapsed_sidebar?) }
+ .nav-sidebar-inner-scroll
+ .context-header
+ = link_to instance_statistics_root_path, title: _('Instance Statistics') do
+ .avatar-container.s40.settings-avatar
+ = sprite_icon('chart', size: 24)
+ .sidebar-context-title= _('Instance Statistics')
+ %ul.sidebar-top-level-items
+ = nav_link(controller: :conversational_development_index) do
+ = link_to instance_statistics_conversational_development_index_index_path do
+ .nav-icon-container
+ = sprite_icon('comment')
+ %span.nav-item-name
+ = _('ConvDev Index')
+ %ul.sidebar-sub-level-items.is-fly-out-only
+ = nav_link(controller: :conversational_development_index, html_options: { class: "fly-out-top-item" } ) do
+ = link_to instance_statistics_conversational_development_index_index_path do
+ %strong.fly-out-top-item-name
+ = _('ConvDev Index')
+
+ = nav_link(controller: :cohorts) do
+ = link_to instance_statistics_cohorts_path do
+ .nav-icon-container
+ = sprite_icon('users')
+ %span.nav-item-name
+ = _('Cohorts')
+ %ul.sidebar-sub-level-items.is-fly-out-only
+ = nav_link(controller: :cohorts, html_options: { class: "fly-out-top-item" } ) do
+ = link_to instance_statistics_cohorts_path do
+ %strong.fly-out-top-item-name
+ = _('Cohorts')
+
+ = render 'shared/sidebar_toggle_button'
diff --git a/changelogs/unreleased/41416-making-instance-wide-data-tools-more-accessible.yml b/changelogs/unreleased/41416-making-instance-wide-data-tools-more-accessible.yml
new file mode 100644
index 00000000000..b980b719d68
--- /dev/null
+++ b/changelogs/unreleased/41416-making-instance-wide-data-tools-more-accessible.yml
@@ -0,0 +1,5 @@
+---
+title: Allow non-admins to view instance statistics (if permitted by the instance admins)
+merge_request: 20874
+author:
+type: changed
diff --git a/config/routes.rb b/config/routes.rb
index aac3a77c4f1..d16a587c5ee 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -71,6 +71,8 @@ Rails.application.routes.draw do
get 'ide' => 'ide#index'
get 'ide/*vueroute' => 'ide#index', format: false
+
+ draw :instance_statistics
end
# Koding route
diff --git a/config/routes/admin.rb b/config/routes/admin.rb
index 109f00631fb..7ee960970f8 100644
--- a/config/routes/admin.rb
+++ b/config/routes/admin.rb
@@ -76,8 +76,6 @@ namespace :admin do
resource :system_info, controller: 'system_info', only: [:show]
resources :requests_profiles, only: [:index, :show], param: :name, constraints: { name: /.+\.html/ }
- get 'conversational_development_index' => 'conversational_development_index#show'
-
resources :projects, only: [:index]
scope(path: 'projects/*namespace_id',
@@ -123,8 +121,6 @@ namespace :admin do
end
end
- resources :cohorts, only: :index
-
resources :jobs, only: :index do
collection do
post :cancel_all
diff --git a/config/routes/instance_statistics.rb b/config/routes/instance_statistics.rb
new file mode 100644
index 00000000000..824ef47cda3
--- /dev/null
+++ b/config/routes/instance_statistics.rb
@@ -0,0 +1,8 @@
+# frozen_string_literal: true
+
+namespace :instance_statistics do
+ root to: redirect('/-/instance_statistics/conversational_development_index')
+
+ resources :cohorts, only: :index
+ resources :conversational_development_index, only: :index
+end
diff --git a/db/migrate/20180718005113_add_instance_statistics_visibility_to_application_setting.rb b/db/migrate/20180718005113_add_instance_statistics_visibility_to_application_setting.rb
new file mode 100644
index 00000000000..4b6c1f74346
--- /dev/null
+++ b/db/migrate/20180718005113_add_instance_statistics_visibility_to_application_setting.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+class AddInstanceStatisticsVisibilityToApplicationSetting < ActiveRecord::Migration
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ add_column_with_default(:application_settings, :instance_statistics_visibility_private,
+ :boolean,
+ default: false,
+ allow_null: false)
+ end
+
+ def down
+ remove_column(:application_settings, :instance_statistics_visibility_private)
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 97e7e28df09..905786172a2 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -168,6 +168,7 @@ ActiveRecord::Schema.define(version: 20180726172057) do
t.boolean "enforce_terms", default: false
t.boolean "mirror_available", default: true, null: false
t.boolean "hide_third_party_offers", default: false, null: false
+ t.boolean "instance_statistics_visibility_private", default: false, null: false
end
create_table "audit_events", force: :cascade do |t|
diff --git a/doc/api/settings.md b/doc/api/settings.md
index b6f2101fc7b..68fc56b1fa3 100644
--- a/doc/api/settings.md
+++ b/doc/api/settings.md
@@ -55,7 +55,8 @@ Example response:
"ed25519_key_restriction": 0,
"enforce_terms": true,
"terms": "Hello world!",
- "performance_bar_allowed_group_id": 42
+ "performance_bar_allowed_group_id": 42,
+ "instance_statistics_visibility_private": false
}
```
@@ -159,6 +160,7 @@ PUT /application/settings
| `version_check_enabled` | boolean | no | Let GitLab inform you when an update is available. |
| `enforce_terms` | boolean | no | Enforce application ToS to all users |
| `terms` | text | yes (if `enforce_terms` is true) | Markdown content for the ToS |
+| `instance_statistics_visibility_private` | boolean | no | When set to `true` Instance statistics will only be available to admins |
```bash
curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/application/settings?signup_enabled=false&default_project_visibility=internal
@@ -203,6 +205,7 @@ Example response:
"ed25519_key_restriction": 0,
"enforce_terms": true,
"terms": "Hello world!",
- "performance_bar_allowed_group_id": 42
+ "performance_bar_allowed_group_id": 42,
+ "instance_statistics_visibility_private": false
}
```
diff --git a/lib/api/settings.rb b/lib/api/settings.rb
index 6601c268d79..897010217dc 100644
--- a/lib/api/settings.rb
+++ b/lib/api/settings.rb
@@ -127,9 +127,7 @@ module API
optional :signup_enabled, type: Boolean, desc: 'Flag indicating if sign up is enabled'
optional :terminal_max_session_time, type: Integer, desc: 'Maximum time for web terminal websocket connection (in seconds). Set to 0 for unlimited time.'
optional :usage_ping_enabled, type: Boolean, desc: 'Every week GitLab will report license usage back to GitLab, Inc.'
- optional :user_default_external, type: Boolean, desc: 'Newly registered users will by default be external'
- optional :user_oauth_applications, type: Boolean, desc: 'Allow users to register any application to use GitLab as an OAuth provider'
- optional :version_check_enabled, type: Boolean, desc: 'Let GitLab inform you when an update is available.'
+ optional :instance_statistics_visibility_private, type: Boolean, desc: 'When set to `true` Instance statistics will only be available to admins'
ApplicationSetting::SUPPORTED_KEY_TYPES.each do |type|
optional :"#{type}_key_restriction",
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 7189d1fedaf..a767c179dea 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -396,6 +396,9 @@ msgstr ""
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
+msgid "All users"
+msgstr ""
+
msgid "Allow commits from members who can merge to the target branch."
msgstr ""
@@ -2991,6 +2994,12 @@ msgstr ""
msgid "Install Runner on Kubernetes"
msgstr ""
+msgid "Instance Statistics"
+msgstr ""
+
+msgid "Instance Statistics visibility"
+msgstr ""
+
msgid "Instance does not support multiple Kubernetes clusters"
msgstr ""
@@ -3712,6 +3721,9 @@ msgstr ""
msgid "Online IDE integration settings."
msgstr ""
+msgid "Only admins"
+msgstr ""
+
msgid "Only comments from the following commit are shown below"
msgstr ""
diff --git a/spec/controllers/instance_statistics/cohorts_controller_spec.rb b/spec/controllers/instance_statistics/cohorts_controller_spec.rb
new file mode 100644
index 00000000000..e4eedede93a
--- /dev/null
+++ b/spec/controllers/instance_statistics/cohorts_controller_spec.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe InstanceStatistics::CohortsController do
+ it_behaves_like 'instance statistics availability'
+end
diff --git a/spec/controllers/instance_statistics/conversational_development_index_controller_spec.rb b/spec/controllers/instance_statistics/conversational_development_index_controller_spec.rb
new file mode 100644
index 00000000000..4935cb265bf
--- /dev/null
+++ b/spec/controllers/instance_statistics/conversational_development_index_controller_spec.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe InstanceStatistics::ConversationalDevelopmentIndexController do
+ it_behaves_like 'instance statistics availability'
+end
diff --git a/spec/features/dashboard/active_tab_spec.rb b/spec/features/dashboard/active_tab_spec.rb
index 8bab501134b..f4d0f82d248 100644
--- a/spec/features/dashboard/active_tab_spec.rb
+++ b/spec/features/dashboard/active_tab_spec.rb
@@ -7,32 +7,38 @@ RSpec.describe 'Dashboard Active Tab', :js do
shared_examples 'page has active tab' do |title|
it "#{title} tab" do
+ subject
+
expect(page).to have_selector('.navbar-sub-nav li.active', count: 1)
expect(find('.navbar-sub-nav li.active')).to have_content(title)
end
end
context 'on dashboard projects' do
- before do
- visit dashboard_projects_path
+ it_behaves_like 'page has active tab', 'Projects' do
+ subject { visit dashboard_projects_path }
end
-
- it_behaves_like 'page has active tab', 'Projects'
end
context 'on dashboard groups' do
- before do
- visit dashboard_groups_path
+ it_behaves_like 'page has active tab', 'Groups' do
+ subject { visit dashboard_groups_path }
end
-
- it_behaves_like 'page has active tab', 'Groups'
end
context 'on activity projects' do
- before do
- visit activity_dashboard_path
+ it_behaves_like 'page has active tab', 'Activity' do
+ subject { visit activity_dashboard_path }
end
+ end
- it_behaves_like 'page has active tab', 'Activity'
+ context 'on instance statistics' do
+ subject { visit instance_statistics_root_path }
+
+ it 'shows Instance Statistics` as active' do
+ subject
+
+ expect(find('.navbar-sub-nav li.active')).to have_link('Instance Statistics')
+ end
end
end
diff --git a/spec/features/dashboard/instance_statistics_spec.rb b/spec/features/dashboard/instance_statistics_spec.rb
new file mode 100644
index 00000000000..21ee2796bd8
--- /dev/null
+++ b/spec/features/dashboard/instance_statistics_spec.rb
@@ -0,0 +1,60 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe 'Showing instance statistics' do
+ before do
+ sign_in user if user
+ end
+
+ # Using a path that is publicly accessible
+ subject { visit explore_projects_path }
+
+ context 'for unauthenticated users' do
+ let(:user) { nil }
+
+ it 'does not show the instance statistics link' do
+ subject
+
+ expect(page).not_to have_link('Instance Statistics')
+ end
+ end
+
+ context 'for regular users' do
+ let(:user) { create(:user) }
+
+ context 'when instance statistics are publicly available' do
+ before do
+ stub_application_setting(instance_statistics_visibility_private: false)
+ end
+
+ it 'shows the instance statistics link' do
+ subject
+
+ expect(page).to have_link('Instance Statistics')
+ end
+ end
+
+ context 'when instance statistics are not publicly available' do
+ before do
+ stub_application_setting(instance_statistics_visibility_private: true)
+ end
+
+ it 'shows the instance statistics link' do
+ subject
+
+ expect(page).not_to have_link('Instance Statistics')
+ end
+ end
+ end
+
+ context 'for admins' do
+ let(:user) { create(:admin) }
+
+ it 'shows the instance statistics link' do
+ subject
+
+ expect(page).to have_link('Instance Statistics')
+ end
+ end
+end
diff --git a/spec/features/admin/admin_cohorts_spec.rb b/spec/features/instance_statistics/cohorts_spec.rb
index 9dce9494b97..81fc5eff980 100644
--- a/spec/features/admin/admin_cohorts_spec.rb
+++ b/spec/features/instance_statistics/cohorts_spec.rb
@@ -1,6 +1,6 @@
require 'rails_helper'
-describe 'Admin cohorts page' do
+describe 'Cohorts page' do
before do
sign_in(create(:admin))
end
@@ -8,7 +8,7 @@ describe 'Admin cohorts page' do
it 'See users count per month' do
2.times { create(:user) }
- visit admin_cohorts_path
+ visit instance_statistics_cohorts_path
expect(page).to have_content("#{Time.now.strftime('%b %Y')} 3 0")
end
diff --git a/spec/features/admin/admin_conversational_development_index_spec.rb b/spec/features/instance_statistics/conversational_development_index_spec.rb
index 2d2c7df5364..d441a7a5af9 100644
--- a/spec/features/admin/admin_conversational_development_index_spec.rb
+++ b/spec/features/instance_statistics/conversational_development_index_spec.rb
@@ -1,6 +1,6 @@
require 'spec_helper'
-describe 'Admin Conversational Development Index' do
+describe 'Conversational Development Index' do
before do
sign_in(create(:admin))
end
@@ -9,7 +9,7 @@ describe 'Admin Conversational Development Index' do
it 'shows empty state' do
stub_application_setting(usage_ping_enabled: false)
- visit admin_conversational_development_index_path
+ visit instance_statistics_conversational_development_index_index_path
expect(page).to have_content('Usage ping is not enabled')
end
@@ -19,7 +19,7 @@ describe 'Admin Conversational Development Index' do
it 'shows empty state' do
stub_application_setting(usage_ping_enabled: true)
- visit admin_conversational_development_index_path
+ visit instance_statistics_conversational_development_index_index_path
expect(page).to have_content('Data is still calculating')
end
@@ -30,7 +30,7 @@ describe 'Admin Conversational Development Index' do
stub_application_setting(usage_ping_enabled: true)
create(:conversational_development_index_metric)
- visit admin_conversational_development_index_path
+ visit instance_statistics_conversational_development_index_index_path
expect(page).to have_content(
'Issues created per active user 1.2 You 9.3 Lead 13.3%'
diff --git a/spec/policies/global_policy_spec.rb b/spec/policies/global_policy_spec.rb
index a2047b54deb..30d68e7dc9d 100644
--- a/spec/policies/global_policy_spec.rb
+++ b/spec/policies/global_policy_spec.rb
@@ -180,4 +180,38 @@ describe GlobalPolicy do
end
end
end
+
+ describe 'read instance statistics' do
+ context 'regular user' do
+ it { is_expected.to be_allowed(:read_instance_statistics) }
+
+ context 'when instance statistics are set to private' do
+ before do
+ stub_application_setting(instance_statistics_visibility_private: true)
+ end
+
+ it { is_expected.not_to be_allowed(:read_instance_statistics) }
+ end
+ end
+
+ context 'admin' do
+ let(:current_user) { create(:admin) }
+
+ it { is_expected.to be_allowed(:read_instance_statistics) }
+
+ context 'when instance statistics are set to private' do
+ before do
+ stub_application_setting(instance_statistics_visibility_private: true)
+ end
+
+ it { is_expected.to be_allowed(:read_instance_statistics) }
+ end
+ end
+
+ context 'anonymous' do
+ let(:current_user) { nil }
+
+ it { is_expected.not_to be_allowed(:read_instance_statistics) }
+ end
+ end
end
diff --git a/spec/requests/api/settings_spec.rb b/spec/requests/api/settings_spec.rb
index 57adc3ca7a6..3e0f47b84a1 100644
--- a/spec/requests/api/settings_spec.rb
+++ b/spec/requests/api/settings_spec.rb
@@ -25,6 +25,7 @@ describe API::Settings, 'Settings' do
expect(json_response['ed25519_key_restriction']).to eq(0)
expect(json_response['circuitbreaker_failure_count_threshold']).not_to be_nil
expect(json_response['performance_bar_allowed_group_id']).to be_nil
+ expect(json_response['instance_statistics_visibility_private']).to be(false)
expect(json_response).not_to have_key('performance_bar_allowed_group_path')
expect(json_response).not_to have_key('performance_bar_enabled')
end
@@ -64,7 +65,8 @@ describe API::Settings, 'Settings' do
circuitbreaker_check_interval: 2,
enforce_terms: true,
terms: 'Hello world!',
- performance_bar_allowed_group_path: group.full_path
+ performance_bar_allowed_group_path: group.full_path,
+ instance_statistics_visibility_private: true
expect(response).to have_gitlab_http_status(200)
expect(json_response['default_projects_limit']).to eq(3)
@@ -89,6 +91,7 @@ describe API::Settings, 'Settings' do
expect(json_response['enforce_terms']).to be(true)
expect(json_response['terms']).to eq('Hello world!')
expect(json_response['performance_bar_allowed_group_id']).to eq(group.id)
+ expect(json_response['instance_statistics_visibility_private']).to be(true)
end
end
diff --git a/spec/routing/instance_statistics_routing_spec.rb b/spec/routing/instance_statistics_routing_spec.rb
new file mode 100644
index 00000000000..b94faabfa1d
--- /dev/null
+++ b/spec/routing/instance_statistics_routing_spec.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe 'Instance Statistics', 'routing' do
+ include RSpec::Rails::RequestExampleGroup
+
+ it "routes '/-/instance_statistics' to conversational development index" do
+ expect(get('/-/instance_statistics')).to redirect_to('/-/instance_statistics/conversational_development_index')
+ end
+end
diff --git a/spec/support/shared_examples/instance_statistics_controllers_shared_examples.rb b/spec/support/shared_examples/instance_statistics_controllers_shared_examples.rb
new file mode 100644
index 00000000000..5334af841e1
--- /dev/null
+++ b/spec/support/shared_examples/instance_statistics_controllers_shared_examples.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+shared_examples 'instance statistics availability' do
+ let(:user) { create(:user) }
+
+ before do
+ sign_in(user)
+ end
+
+ describe 'GET #index' do
+ it 'is available when the feature is available publicly' do
+ get :index
+
+ expect(response).to have_gitlab_http_status(:success)
+ end
+
+ it 'renders a 404 when the feature is not available publicly' do
+ stub_application_setting(instance_statistics_visibility_private: true)
+
+ get :index
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+
+ context 'for admins' do
+ let(:user) { create(:admin) }
+
+ it 'allows access when the feature is not available publicly' do
+ stub_application_setting(instance_statistics_visibility_private: true)
+
+ get :index
+
+ expect(response).to have_gitlab_http_status(:success)
+ end
+ end
+ end
+end