diff --git a/app/controllers/instance_statistics/application_controller.rb b/app/controllers/instance_statistics/application_controller.rb index 85b28a6080d..a273dde105c 100644 --- a/app/controllers/instance_statistics/application_controller.rb +++ b/app/controllers/instance_statistics/application_controller.rb @@ -1,10 +1,10 @@ # frozen_string_literal: true class InstanceStatistics::ApplicationController < ApplicationController - before_action :authenticate_user! + before_action :authorize_read_instance_statistics! layout 'instance_statistics' - def authenticate_user! + def authorize_read_instance_statistics! render_404 unless can?(current_user, :read_instance_statistics) end end diff --git a/app/controllers/instance_statistics/cohorts_controller.rb b/app/controllers/instance_statistics/cohorts_controller.rb index 77d09c198c8..7eba0a5ecdd 100644 --- a/app/controllers/instance_statistics/cohorts_controller.rb +++ b/app/controllers/instance_statistics/cohorts_controller.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class InstanceStatistics::CohortsController < InstanceStatistics::ApplicationController def index if Gitlab::CurrentSettings.usage_ping_enabled diff --git a/app/policies/global_policy.rb b/app/policies/global_policy.rb index bf146dc375b..16c58730878 100644 --- a/app/policies/global_policy.rb +++ b/app/policies/global_policy.rb @@ -20,7 +20,9 @@ class GlobalPolicy < BasePolicy end condition(:private_instance_statistics, score: 0) { Gitlab::CurrentSettings.instance_statistics_visibility_private? } - rule { admin | ~private_instance_statistics }.enable :read_instance_statistics + + rule { admin | (~private_instance_statistics & ~anonymous) } + .enable :read_instance_statistics rule { anonymous }.policy do prevent :log_in diff --git a/config/routes/instance_statistics.rb b/config/routes/instance_statistics.rb index 1102ef6b017..824ef47cda3 100644 --- a/config/routes/instance_statistics.rb +++ b/config/routes/instance_statistics.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true namespace :instance_statistics do - root to: redirect('-/instance_statistics/conversational_development_index') + root to: redirect('/-/instance_statistics/conversational_development_index') resources :cohorts, only: :index resources :conversational_development_index, only: :index 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/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/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