diff --git a/ee/app/controllers/projects/analytics/dashboards_controller.rb b/ee/app/controllers/projects/analytics/dashboards_controller.rb index ac0f7eb870c9dd369bb4dc3e59fca87ce66a853e..df332427845668196afc7cfb87ad2cfedfef4af9 100644 --- a/ee/app/controllers/projects/analytics/dashboards_controller.rb +++ b/ee/app/controllers/projects/analytics/dashboards_controller.rb @@ -23,7 +23,8 @@ def index; end def dashboards_enabled! render_404 unless ::Feature.enabled?(:combined_analytics_dashboards, project) && - project.licensed_feature_available?(:combined_project_analytics_dashboards) + project.licensed_feature_available?(:combined_project_analytics_dashboards) && + !project.personal? end def viewing_single_dashboard? diff --git a/ee/app/controllers/projects/settings/analytics_controller.rb b/ee/app/controllers/projects/settings/analytics_controller.rb index e8b8540c71d72021616291c3447071de1a8daec4..ea71b305e715b2d7bbf591868b24eb45d2486853 100644 --- a/ee/app/controllers/projects/settings/analytics_controller.rb +++ b/ee/app/controllers/projects/settings/analytics_controller.rb @@ -48,7 +48,7 @@ def permitted_project_params end def authorize_analytics_settings! - access_denied! unless Feature.enabled?(:combined_analytics_dashboards, project) + access_denied! unless Feature.enabled?(:combined_analytics_dashboards, project) && !project.personal? end end end diff --git a/ee/app/services/product_analytics/cube_data_query_service.rb b/ee/app/services/product_analytics/cube_data_query_service.rb index d10f4d53f0294878263abc0091ccd495265ad03f..376521b85b5cbc8924e261db9facd8d38e62a1cf 100644 --- a/ee/app/services/product_analytics/cube_data_query_service.rb +++ b/ee/app/services/product_analytics/cube_data_query_service.rb @@ -70,7 +70,8 @@ def product_analytics_enabled? Gitlab::CurrentSettings.product_analytics_enabled? && product_analytics_settings.cube_api_base_url.present? && product_analytics_settings.cube_api_key.present? && - project.product_analytics_enabled? + project.product_analytics_enabled? && + !project.personal? end def has_access? diff --git a/ee/lib/ee/sidebars/projects/menus/analytics_menu.rb b/ee/lib/ee/sidebars/projects/menus/analytics_menu.rb index b900f9a87e719280dc38a714a871912fa1d9d271..92be41db80d3d53476f3b326b9971f7651008e40 100644 --- a/ee/lib/ee/sidebars/projects/menus/analytics_menu.rb +++ b/ee/lib/ee/sidebars/projects/menus/analytics_menu.rb @@ -93,7 +93,7 @@ def dashboards_analytics_menu_item unless ::Feature.enabled?(:combined_analytics_dashboards, context.project) && context.project.licensed_feature_available?(:combined_project_analytics_dashboards) && can?(context.current_user, :read_combined_project_analytics_dashboards, context.project) && - can?(context.current_user, :read_product_analytics, context.project) + can?(context.current_user, :read_product_analytics, context.project) && !context.project.personal? return ::Sidebars::NilMenuItem.new(item_id: :dashboards_analytics) end diff --git a/ee/lib/ee/sidebars/projects/menus/settings_menu.rb b/ee/lib/ee/sidebars/projects/menus/settings_menu.rb index 1e274561219dd1d01e09af56eeab376f4aca86b9..429f0221d5ee79f69982d69f37119a6eedee6181 100644 --- a/ee/lib/ee/sidebars/projects/menus/settings_menu.rb +++ b/ee/lib/ee/sidebars/projects/menus/settings_menu.rb @@ -17,7 +17,7 @@ def configure_menu_items end def analytics_menu_item - unless ::Feature.enabled?(:combined_analytics_dashboards, context.project) + unless ::Feature.enabled?(:combined_analytics_dashboards, context.project) && !context.project.personal? return ::Sidebars::NilMenuItem.new(item_id: :analytics) end diff --git a/ee/spec/features/projects/navbar_spec.rb b/ee/spec/features/projects/navbar_spec.rb index 7bfcab7e7f3ea6ef27fb4e2aa8e4117551457ebf..98454cddad07d72309509ac0f63a8afcf279f639 100644 --- a/ee/spec/features/projects/navbar_spec.rb +++ b/ee/spec/features/projects/navbar_spec.rb @@ -19,6 +19,7 @@ stub_feature_flags(ml_experiment_tracking: false) stub_feature_flags(model_registry: false) stub_feature_flags(remove_monitor_metrics: false) + stub_feature_flags(combined_analytics_dashboards: false) insert_package_nav insert_infrastructure_registry_nav(s_('Terraform|Terraform states')) insert_infrastructure_google_cloud_nav @@ -212,18 +213,40 @@ context 'when analytics dashboards is available' do before do stub_feature_flags(combined_analytics_dashboards: true) - stub_licensed_features(combined_project_analytics_dashboards: true) - - insert_before_sub_nav_item( - _('Value stream analytics'), - within: _('Analyze'), - new_sub_nav_item_name: _('Analytics dashboards') - ) - + stub_licensed_features({ combined_project_analytics_dashboards: true, iterations: false }) visit project_path(project) end - it_behaves_like 'verified navigation bar' + context 'when project is namespaced to a user' do + it_behaves_like 'verified navigation bar' + end + + context 'when project is namespaced to a group' do + let_it_be_with_reload(:group) { create(:group) } + let_it_be_with_reload(:project) { create(:project, :repository, group: group) } + + before_all do + project.add_maintainer(user) + end + + before do + insert_before_sub_nav_item( + _('Value stream analytics'), + within: _('Analyze'), + new_sub_nav_item_name: _('Analytics dashboards') + ) + + insert_after_sub_nav_item( + _('Monitor'), + within: _('Settings'), + new_sub_nav_item_name: _('Analytics') + ) + + visit project_path(project) + end + + it_behaves_like 'verified navigation bar' + end end context 'when model experiments is available' do diff --git a/ee/spec/lib/ee/sidebars/projects/menus/analytics_menu_spec.rb b/ee/spec/lib/ee/sidebars/projects/menus/analytics_menu_spec.rb index 8f1c612fdcaf7c0d556bbcba2e5179f8e4dfe08d..e4937699bfc89cf0030d543c5e811d5747870c02 100644 --- a/ee/spec/lib/ee/sidebars/projects/menus/analytics_menu_spec.rb +++ b/ee/spec/lib/ee/sidebars/projects/menus/analytics_menu_spec.rb @@ -111,47 +111,63 @@ stub_licensed_features(combined_project_analytics_dashboards: true) end - specify { is_expected.not_to be_nil } + describe 'for personal namespace projects' do + it 'is nil for personal namespace projects' do + is_expected.to be_nil + end + end - context 'with different user access levels' do - where(:access_level, :has_menu_item) do - nil | false - :reporter | false - :developer | true - :maintainer | true + describe 'for group namespace projects' do + let_it_be(:user) { create(:user) } + let_it_be(:group) { create(:group) } + let_it_be_with_reload(:project) { create(:project, group: group) } + + before_all do + project.add_maintainer(user) end - with_them do - let(:user) { create(:user) } + specify { is_expected.not_to be_nil } - before do - project.add_member(user, access_level) + context 'with different user access levels' do + where(:access_level, :has_menu_item) do + nil | false + :reporter | false + :developer | true + :maintainer | true end - describe "when the user is not allowed to view the menu item", if: !params[:has_menu_item] do - specify { is_expected.to be_nil } - end + with_them do + let(:user) { create(:user) } + + before do + project.add_member(user, access_level) + end + + context "when the user is not allowed to view the menu item", if: !params[:has_menu_item] do + specify { is_expected.to be_nil } + end - describe "when the user is allowed to view the menu item", if: params[:has_menu_item] do - specify { is_expected.not_to be_nil } + context "when the user is allowed to view the menu item", if: params[:has_menu_item] do + specify { is_expected.not_to be_nil } + end end end - end - describe 'when the license does not support the feature' do - before do - stub_licensed_features(combined_project_analytics_dashboards: false) + describe 'when the license does not support the feature' do + before do + stub_licensed_features(combined_project_analytics_dashboards: false) + end + + specify { is_expected.to be_nil } end - specify { is_expected.to be_nil } - end + describe 'when the dashboards analytics feature is disabled' do + before do + stub_feature_flags(combined_analytics_dashboards: false) + end - describe 'when the dashboards analytics feature is disabled' do - before do - stub_feature_flags(combined_analytics_dashboards: false) + specify { is_expected.to be_nil } end - - specify { is_expected.to be_nil } end end end diff --git a/ee/spec/lib/ee/sidebars/projects/menus/settings_menu_spec.rb b/ee/spec/lib/ee/sidebars/projects/menus/settings_menu_spec.rb index 6c88d80391d20ba21aec5b0fabfdbe56019b2cea..65ce668661ff8742c1ea1d85bd6135ca439b0809 100644 --- a/ee/spec/lib/ee/sidebars/projects/menus/settings_menu_spec.rb +++ b/ee/spec/lib/ee/sidebars/projects/menus/settings_menu_spec.rb @@ -6,6 +6,7 @@ let_it_be(:project) { create(:project) } let(:user) { project.first_owner } + let(:show_promotions) { true } let(:show_discover_project_security) { true } let(:context) do @@ -29,12 +30,27 @@ describe 'Analytics' do let(:item_id) { :analytics } - it_behaves_like 'access rights checks' + context 'for group projects' do + let_it_be(:user) { create(:user) } + let_it_be(:group) { create(:group) } + let_it_be_with_reload(:project) { create(:project, group: group) } + + before_all do + project.add_maintainer(user) + end + + it_behaves_like 'access rights checks' - it 'is nil when combined_analytics_dashboards feature flag is disabled' do - stub_feature_flags(combined_analytics_dashboards: false) + it 'is nil when combined_analytics_dashboards feature flag is disabled' do + stub_feature_flags(combined_analytics_dashboards: false) + expect(subject).to be_nil + end + end - expect(subject).to be_nil + context 'for personal projects' do + it 'is nil for personal namespace projects' do + is_expected.to be_nil + end end end diff --git a/ee/spec/requests/projects/analytics/dashboards_controller_spec.rb b/ee/spec/requests/projects/analytics/dashboards_controller_spec.rb index c08071daee834d1cb054fe32a701ef66d9c3c706..b2e59616a6cd16f4bba21096d398307f30296a6e 100644 --- a/ee/spec/requests/projects/analytics/dashboards_controller_spec.rb +++ b/ee/spec/requests/projects/analytics/dashboards_controller_spec.rb @@ -41,50 +41,59 @@ end end - context 'with the feature flag disabled' do - before do - stub_feature_flags(combined_analytics_dashboards: false) - end - + describe 'for personal namespace projects' do it_behaves_like 'returns not found' end - context 'with the feature flag enabled' do - before do - stub_feature_flags(combined_analytics_dashboards: true) - end + describe 'for group namespace projects' do + let_it_be(:group) { create(:group) } + let_it_be_with_reload(:project) { create(:project, :repository, group: group) } - context 'without the licensed feature' do + context 'with the feature flag disabled' do before do - stub_licensed_features(combined_project_analytics_dashboards: false) + stub_feature_flags(combined_analytics_dashboards: false) end it_behaves_like 'returns not found' end - context 'with the licensed feature' do - where(:access_level, :example_to_run) do - nil | 'returns not found' - :reporter | 'returns not found' - :developer | 'returns success' - :maintainer | 'returns success' + context 'with the feature flag enabled' do + before do + stub_feature_flags(combined_analytics_dashboards: true) end - with_them do - let(:user) { create(:user) } - + context 'without the licensed feature' do before do - stub_licensed_features(combined_project_analytics_dashboards: true) - project.add_member(user, access_level) + stub_licensed_features(combined_project_analytics_dashboards: false) end - it_behaves_like params[:example_to_run] + it_behaves_like 'returns not found' end - it 'does not count views for the dashboard listing' do - expect(Gitlab::UsageDataCounters::ProductAnalyticsCounter).not_to receive(:count) + context 'with the licensed feature' do + where(:access_level, :example_to_run) do + nil | 'returns not found' + :reporter | 'returns not found' + :developer | 'returns success' + :maintainer | 'returns success' + end + + with_them do + let(:user) { create(:user) } + + before do + stub_licensed_features(combined_project_analytics_dashboards: true) + project.add_member(user, access_level) + end + + it_behaves_like params[:example_to_run] + end + + it 'does not count views for the dashboard listing' do + expect(Gitlab::UsageDataCounters::ProductAnalyticsCounter).not_to receive(:count) - get project_analytics_dashboards_path(project) + get project_analytics_dashboards_path(project) + end end end end diff --git a/ee/spec/requests/projects/settings/analytics_controller_spec.rb b/ee/spec/requests/projects/settings/analytics_controller_spec.rb index fcd58a08241e53919f8ed830e50d405586d00b18..0652329fa091158cb15a34b56d87196155281557 100644 --- a/ee/spec/requests/projects/settings/analytics_controller_spec.rb +++ b/ee/spec/requests/projects/settings/analytics_controller_spec.rb @@ -191,4 +191,27 @@ end end end + + describe 'for personal namespace projects' do + let_it_be_with_reload(:project) { create(:project) } + let_it_be(:user) { project.first_owner } + + before_all do + project.add_maintainer(user) + end + + before do + sign_in(user) + end + + subject do + get project_settings_analytics_path(project) + end + + it 'returns a 404 on rendering analytics settings' do + subject + + expect(response).to have_gitlab_http_status(:not_found) + end + end end diff --git a/spec/support/shared_contexts/navbar_structure_context.rb b/spec/support/shared_contexts/navbar_structure_context.rb index 2adb9e410a76eb33874753bbeb1e0d7784a3f0b3..9188fa0833536480000410c7a4f4c8a24461678a 100644 --- a/spec/support/shared_contexts/navbar_structure_context.rb +++ b/spec/support/shared_contexts/navbar_structure_context.rb @@ -97,7 +97,6 @@ _('CI/CD'), _('Packages and registries'), _('Monitor'), - (_('Analytics') if Gitlab.ee?), s_('UsageQuota|Usage Quotas') ] }