diff --git a/app/assets/javascripts/vue_shared/components/project_selector/project_selector.vue b/app/assets/javascripts/vue_shared/components/project_selector/project_selector.vue index f21092af501..67ad7769c7c 100644 --- a/app/assets/javascripts/vue_shared/components/project_selector/project_selector.vue +++ b/app/assets/javascripts/vue_shared/components/project_selector/project_selector.vue @@ -130,16 +130,19 @@ export default { {{ legendText }} -
+
{{ __('Sorry, no projects matched your search') }}
{{ __('Enter at least three characters to search') }}
-
+
{{ __('Something went wrong, unable to search projects') }}
diff --git a/app/controllers/admin/groups_controller.rb b/app/controllers/admin/groups_controller.rb index 4d163824ef6..2ae0442c005 100644 --- a/app/controllers/admin/groups_controller.rb +++ b/app/controllers/admin/groups_controller.rb @@ -108,6 +108,7 @@ class Admin::GroupsController < Admin::ApplicationController :visibility_level, :require_two_factor_authentication, :two_factor_grace_period, + :enabled_git_access_protocol, :project_creation_level, :subgroup_creation_level, admin_note_attributes: [ diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb index fd3bcc67b12..327b4832f31 100644 --- a/app/controllers/groups_controller.rb +++ b/app/controllers/groups_controller.rb @@ -285,6 +285,7 @@ class GroupsController < Groups::ApplicationController :chat_team_name, :require_two_factor_authentication, :two_factor_grace_period, + :enabled_git_access_protocol, :project_creation_level, :subgroup_creation_level, :default_branch_protection, diff --git a/app/controllers/jwks_controller.rb b/app/controllers/jwks_controller.rb index 3b0e6ca2eb1..d3a8d3dafea 100644 --- a/app/controllers/jwks_controller.rb +++ b/app/controllers/jwks_controller.rb @@ -13,10 +13,6 @@ class JwksController < Doorkeeper::OpenidConnect::DiscoveryController def payload [ - # We keep openid_connect_signing_key so that we can seamlessly - # replace it with ci_jwt_signing_key and remove it on the next release. - # TODO: Remove openid_connect_signing_key in 13.7 - # https://gitlab.com/gitlab-org/gitlab/-/issues/221031 Rails.application.secrets.openid_connect_signing_key, Gitlab::CurrentSettings.ci_jwt_signing_key ].compact.map do |key_data| diff --git a/app/helpers/groups_helper.rb b/app/helpers/groups_helper.rb index 348a5af699d..9ea9509bc28 100644 --- a/app/helpers/groups_helper.rb +++ b/app/helpers/groups_helper.rb @@ -167,6 +167,17 @@ module GroupsHelper } end + def enabled_git_access_protocol_options_for_group + case ::Gitlab::CurrentSettings.enabled_git_access_protocol + when nil, "" + [[_("Both SSH and HTTP(S)"), "all"], [_("Only SSH"), "ssh"], [_("Only HTTP(S)"), "http"]] + when "ssh" + [[_("Only SSH"), "ssh"]] + when "http" + [[_("Only HTTP(S)"), "http"]] + end + end + private def group_title_link(group, hidable: false, show_avatar: false, for_dropdown: false) diff --git a/app/models/namespace.rb b/app/models/namespace.rb index e7bf1ff42a5..5bb06cdbb4a 100644 --- a/app/models/namespace.rb +++ b/app/models/namespace.rb @@ -557,6 +557,14 @@ class Namespace < ApplicationRecord cluster_enabled_granted? || certificate_based_clusters_enabled_ff? end + def enabled_git_access_protocol + # If the instance-level setting is enabled, we defer to that + return ::Gitlab::CurrentSettings.enabled_git_access_protocol unless ::Gitlab::CurrentSettings.enabled_git_access_protocol.blank? + + # Otherwise we use the stored setting on the group + namespace_settings&.enabled_git_access_protocol + end + private def cluster_enabled_granted? diff --git a/app/models/namespace_setting.rb b/app/models/namespace_setting.rb index ef917c8a22e..504daf2662e 100644 --- a/app/models/namespace_setting.rb +++ b/app/models/namespace_setting.rb @@ -9,14 +9,17 @@ class NamespaceSetting < ApplicationRecord belongs_to :namespace, inverse_of: :namespace_settings + enum jobs_to_be_done: { basics: 0, move_repository: 1, code_storage: 2, exploring: 3, ci: 4, other: 5 }, _suffix: true + enum enabled_git_access_protocol: { all: 0, ssh: 1, http: 2 }, _suffix: true + + validates :enabled_git_access_protocol, inclusion: { in: enabled_git_access_protocols.keys } + validate :default_branch_name_content validate :allow_mfa_for_group validate :allow_resource_access_token_creation_for_group before_validation :normalize_default_branch_name - enum jobs_to_be_done: { basics: 0, move_repository: 1, code_storage: 2, exploring: 3, ci: 4, other: 5 }, _suffix: true - chronic_duration_attr :runner_token_expiration_interval_human_readable, :runner_token_expiration_interval chronic_duration_attr :subgroup_runner_token_expiration_interval_human_readable, :subgroup_runner_token_expiration_interval chronic_duration_attr :project_runner_token_expiration_interval_human_readable, :project_runner_token_expiration_interval @@ -24,7 +27,7 @@ class NamespaceSetting < ApplicationRecord NAMESPACE_SETTINGS_PARAMS = [:default_branch_name, :delayed_project_removal, :lock_delayed_project_removal, :resource_access_token_creation_allowed, :prevent_sharing_groups_outside_hierarchy, :new_user_signups_cap, - :setup_for_company, :jobs_to_be_done, :runner_token_expiration_interval, + :setup_for_company, :jobs_to_be_done, :runner_token_expiration_interval, :enabled_git_access_protocol, :subgroup_runner_token_expiration_interval, :project_runner_token_expiration_interval].freeze self.primary_key = :namespace_id diff --git a/app/views/admin/application_settings/_repository_storage.html.haml b/app/views/admin/application_settings/_repository_storage.html.haml index b5fa08aed79..5dc2d322bb3 100644 --- a/app/views/admin/application_settings/_repository_storage.html.haml +++ b/app/views/admin/application_settings/_repository_storage.html.haml @@ -1,5 +1,5 @@ = gitlab_ui_form_for @application_setting, url: repository_admin_application_settings_path(anchor: 'js-repository-storage-settings'), html: { class: 'fieldset-form' } do |f| - = form_errors(@application_setting) + = form_errors(@application_setting, pajamas_alert: true) %fieldset .sub-section diff --git a/app/views/groups/settings/_git_access_protocols.html.haml b/app/views/groups/settings/_git_access_protocols.html.haml new file mode 100644 index 00000000000..df798db79ad --- /dev/null +++ b/app/views/groups/settings/_git_access_protocols.html.haml @@ -0,0 +1,7 @@ +- if group.root? && Feature.enabled?(:group_level_git_protocol_control, group) + .form-group + = f.label s_('Enabled Git access protocols'), class: 'label-bold' + = f.select :enabled_git_access_protocol, options_for_select(enabled_git_access_protocol_options_for_group, group.enabled_git_access_protocol), {}, class: 'form-control', data: { qa_selector: 'enabled_git_access_protocol_dropdown' }, disabled: !::Gitlab::CurrentSettings.enabled_git_access_protocol.blank? + - if !::Gitlab::CurrentSettings.enabled_git_access_protocol.blank? + .form-text.text-muted + = _("This setting has been configured at the instance level and cannot be overridden per group") diff --git a/app/views/groups/settings/_permissions.html.haml b/app/views/groups/settings/_permissions.html.haml index ecb31b37fd3..a30770b292d 100644 --- a/app/views/groups/settings/_permissions.html.haml +++ b/app/views/groups/settings/_permissions.html.haml @@ -37,6 +37,7 @@ - if @group.licensed_feature_available?(:group_wikis) = render_if_exists 'groups/settings/wiki', f: f, group: @group = render 'groups/settings/lfs', f: f + = render 'groups/settings/git_access_protocols', f: f, group: @group = render 'groups/settings/project_creation_level', f: f, group: @group = render 'groups/settings/subgroup_creation_level', f: f, group: @group = render_if_exists 'groups/settings/prevent_forking', f: f, group: @group diff --git a/app/views/projects/graphs/show.html.haml b/app/views/projects/graphs/show.html.haml index 1973b23a062..c7639eec75d 100644 --- a/app/views/projects/graphs/show.html.haml +++ b/app/views/projects/graphs/show.html.haml @@ -1,7 +1,7 @@ - page_title _('Contributors') -.sub-header-block.bg-gray-light.gl-p-5 - .tree-ref-holder.inline.vertical-align-middle +.sub-header-block.gl-bg-gray-10.gl-p-5 + .tree-ref-holder.gl-display-inline-block.gl-vertical-align-middle.gl-mr-3> = render 'shared/ref_switcher', destination: 'graphs' = link_to s_('Commits|History'), project_commits_path(@project, current_ref), class: 'btn gl-button btn-default' diff --git a/config/feature_flags/development/ci_jwt_signing_key.yml b/config/feature_flags/development/group_level_git_protocol_control.yml similarity index 53% rename from config/feature_flags/development/ci_jwt_signing_key.yml rename to config/feature_flags/development/group_level_git_protocol_control.yml index 7d96264e25f..ad9ba309d69 100644 --- a/config/feature_flags/development/ci_jwt_signing_key.yml +++ b/config/feature_flags/development/group_level_git_protocol_control.yml @@ -1,8 +1,8 @@ --- -name: ci_jwt_signing_key -introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/34249 -rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/258546 -milestone: '13.6' +name: group_level_git_protocol_control +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/89817 +rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/365357 +milestone: '15.1' type: development -group: group::configure -default_enabled: true +group: group::source code +default_enabled: false diff --git a/config/metrics/counts_28d/20220525231314_unique_monthly_active_users.yml b/config/metrics/counts_28d/20220525231314_unique_monthly_active_users.yml new file mode 100644 index 00000000000..658db1a27af --- /dev/null +++ b/config/metrics/counts_28d/20220525231314_unique_monthly_active_users.yml @@ -0,0 +1,23 @@ +--- +key_path: counts_monthly.unique_active_users +name: +description: Users that have a last_activity_on date within the past 28 days +product_category: +product_section: dev +product_stage: manage +product_group: group::manage +value_type: number +status: active +milestone: "15.1" +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/88631 +time_frame: 28d +data_source: database +data_category: optional +instrumentation_class: UniqueActiveUsersMetric +distribution: +- ce +- ee +tier: +- free +- premium +- ultimate diff --git a/db/migrate/20220610125248_add_enabled_git_access_protocol_to_namespace_settings.rb b/db/migrate/20220610125248_add_enabled_git_access_protocol_to_namespace_settings.rb new file mode 100644 index 00000000000..2f16467acd1 --- /dev/null +++ b/db/migrate/20220610125248_add_enabled_git_access_protocol_to_namespace_settings.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +class AddEnabledGitAccessProtocolToNamespaceSettings < Gitlab::Database::Migration[2.0] + def change + add_column :namespace_settings, :enabled_git_access_protocol, :integer, default: 0, null: false, limit: 2 + end +end diff --git a/db/schema_migrations/20220610125248 b/db/schema_migrations/20220610125248 new file mode 100644 index 00000000000..25e863f8c14 --- /dev/null +++ b/db/schema_migrations/20220610125248 @@ -0,0 +1 @@ +8ba7386e21ebb3ac082e322059b41d423cede484e60748222de6a0673c3ca41f \ No newline at end of file diff --git a/db/structure.sql b/db/structure.sql index a3f5ece22b9..cc1f70bc8a8 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -17500,6 +17500,7 @@ CREATE TABLE namespace_settings ( subgroup_runner_token_expiration_interval integer, project_runner_token_expiration_interval integer, exclude_from_free_user_cap boolean DEFAULT false NOT NULL, + enabled_git_access_protocol smallint DEFAULT 0 NOT NULL, CONSTRAINT check_0ba93c78c7 CHECK ((char_length(default_branch_name) <= 255)) ); diff --git a/doc/user/project/repository/mirror/pull.md b/doc/user/project/repository/mirror/pull.md index 73103a9af3d..3599faf4de6 100644 --- a/doc/user/project/repository/mirror/pull.md +++ b/doc/user/project/repository/mirror/pull.md @@ -96,9 +96,9 @@ assigned when you set up pull mirroring. > Moved to GitLab Premium in 13.9. Pull mirroring uses polling to detect new branches and commits added upstream, -often minutes afterwards. If you notify GitLab by -[API](../../../../api/projects.md#start-the-pull-mirroring-process-for-a-project), -updates are pulled immediately. +often minutes afterwards. You can notify GitLab using an +[API call](../../../../api/projects.md#start-the-pull-mirroring-process-for-a-project), +but the [minimum interval for pull mirroring limits](index.md#force-an-update) is still enforced. For more information, read [Start the pull mirroring process for a project](../../../../api/projects.md#start-the-pull-mirroring-process-for-a-project). diff --git a/lib/gitlab/ci/jwt.rb b/lib/gitlab/ci/jwt.rb index 97774bc5e13..19678def666 100644 --- a/lib/gitlab/ci/jwt.rb +++ b/lib/gitlab/ci/jwt.rb @@ -73,11 +73,7 @@ module Gitlab def key @key ||= begin - key_data = if Feature.enabled?(:ci_jwt_signing_key, build.project) - Gitlab::CurrentSettings.ci_jwt_signing_key - else - Rails.application.secrets.openid_connect_signing_key - end + key_data = Gitlab::CurrentSettings.ci_jwt_signing_key raise NoSigningKeyError unless key_data diff --git a/lib/gitlab/git_access.rb b/lib/gitlab/git_access.rb index c96c8afd22d..66fd7aaedea 100644 --- a/lib/gitlab/git_access.rb +++ b/lib/gitlab/git_access.rb @@ -133,7 +133,7 @@ module Gitlab end def protocol_allowed? - Gitlab::ProtocolAccess.allowed?(protocol) + Gitlab::ProtocolAccess.allowed?(protocol, project: project) end private diff --git a/lib/gitlab/protocol_access.rb b/lib/gitlab/protocol_access.rb index efeb1e07d49..5bcbf7b5cca 100644 --- a/lib/gitlab/protocol_access.rb +++ b/lib/gitlab/protocol_access.rb @@ -2,14 +2,42 @@ module Gitlab module ProtocolAccess - def self.allowed?(protocol) - if protocol == 'web' + class << self + def allowed?(protocol, project: nil) + # Web is always allowed + return true if protocol == "web" + + # System settings + return false unless instance_allowed?(protocol) + + # Group-level settings + return false unless namespace_allowed?(protocol, namespace: project&.root_namespace) + + # Default to allowing all protocols true - elsif Gitlab::CurrentSettings.enabled_git_access_protocol.blank? - true - else + end + + private + + def instance_allowed?(protocol) + # If admin hasn't configured this setting, default to true + return true if Gitlab::CurrentSettings.enabled_git_access_protocol.blank? + protocol == Gitlab::CurrentSettings.enabled_git_access_protocol end + + def namespace_allowed?(protocol, namespace: nil) + # If the namespace parameter was nil, we default to true here + return true if namespace.nil? + + # Return immediately if all protocols are allowed + return true if namespace.enabled_git_access_protocol == "all" + + # If the setting is somehow nil, such as in an unsaved state, we default to allow + return true if namespace.enabled_git_access_protocol.blank? + + protocol == namespace.enabled_git_access_protocol + end end end end diff --git a/lib/gitlab/usage/metrics/instrumentations/unique_active_users_metric.rb b/lib/gitlab/usage/metrics/instrumentations/unique_active_users_metric.rb new file mode 100644 index 00000000000..9da30db05dd --- /dev/null +++ b/lib/gitlab/usage/metrics/instrumentations/unique_active_users_metric.rb @@ -0,0 +1,29 @@ +# frozen_string_literal: true + +module Gitlab + module Usage + module Metrics + module Instrumentations + class UniqueActiveUsersMetric < DatabaseMetric + operation :count + relation { ::User.active } + + metric_options do + { + batch_size: 10_000 + } + end + + def time_constraints + case time_frame + when '28d' + monthly_time_range_db_params(column: :last_activity_on) + else + super + end + end + end + end + end + end +end diff --git a/locale/gitlab.pot b/locale/gitlab.pot index d82e155eeaa..4c5129d0b1a 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -6481,6 +6481,9 @@ msgstr "" msgid "Bold text" msgstr "" +msgid "Both SSH and HTTP(S)" +msgstr "" + msgid "Both project and dashboard_path are required" msgstr "" @@ -26700,6 +26703,9 @@ msgstr "" msgid "Only 1 appearances row can exist" msgstr "" +msgid "Only HTTP(S)" +msgstr "" + msgid "Only Issue ID or merge request ID is required" msgstr "" @@ -26709,6 +26715,9 @@ msgstr "" msgid "Only Project Members" msgstr "" +msgid "Only SSH" +msgstr "" + msgid "Only Task can be assigned as a child in hierarchy." msgstr "" @@ -39387,6 +39396,9 @@ msgstr "" msgid "This setting can be overridden in each project." msgstr "" +msgid "This setting has been configured at the instance level and cannot be overridden per group" +msgstr "" + msgid "This setting is allowed for forked projects only" msgstr "" diff --git a/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_large_project_spec.rb b/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_large_project_spec.rb index edb7838e81d..89150c73069 100644 --- a/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_large_project_spec.rb +++ b/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_large_project_spec.rb @@ -73,7 +73,7 @@ module QA let(:source_commits) { source_project.commits(auto_paginate: true).map { |c| c[:id] } } let(:source_labels) { source_project.labels(auto_paginate: true).map { |l| l.except(:id) } } let(:source_milestones) { source_project.milestones(auto_paginate: true).map { |ms| ms.except(:id, :web_url, :project_id) } } - let(:source_pipelines) { source_project.pipelines.map { |pp| pp.except(:id, :web_url, :project_id) } } + let(:source_pipelines) { source_project.pipelines(auto_paginate: true).map { |pp| pp.except(:id, :web_url, :project_id) } } let(:source_mrs) { fetch_mrs(source_project, source_api_client) } let(:source_issues) { fetch_issues(source_project, source_api_client) } @@ -259,7 +259,7 @@ module QA missing_comments = verify_comments(type, actual, expected) { - "#{type}s": (expected.keys - actual.keys).map { |it| actual[it].slice(:title, :url) }, + "#{type}s": (expected.keys - actual.keys).map { |it| actual[it]&.slice(:title, :url) }.compact, "#{type}_comments": missing_comments } end diff --git a/qa/qa/specs/features/browser_ui/1_manage/project/project_access_token_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/project/project_access_token_spec.rb index 19aa3d12568..63ae90aed9c 100644 --- a/qa/qa/specs/features/browser_ui/1_manage/project/project_access_token_spec.rb +++ b/qa/qa/specs/features/browser_ui/1_manage/project/project_access_token_spec.rb @@ -2,16 +2,9 @@ module QA RSpec.describe 'Manage' do - describe 'Project access tokens', :reliable, feature_flag: { - name: 'bootstrap_confirmation_modals', - scope: :global - } do + describe 'Project access tokens', :reliable do let(:project_access_token) { QA::Resource::ProjectAccessToken.fabricate_via_browser_ui! } - before do - Runtime::Feature.enable(:bootstrap_confirmation_modals) - end - it( 'can be created and revoked via the UI', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347688' diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/add_list_delete_branches_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/add_list_delete_branches_spec.rb index 2300e384ab5..0bd470fcb77 100644 --- a/qa/qa/specs/features/browser_ui/3_create/repository/add_list_delete_branches_spec.rb +++ b/qa/qa/specs/features/browser_ui/3_create/repository/add_list_delete_branches_spec.rb @@ -1,10 +1,7 @@ # frozen_string_literal: true module QA - RSpec.describe 'Create', feature_flag: { - name: 'bootstrap_confirmation_modals', - scope: :global - } do + RSpec.describe 'Create' do describe 'Create, list, and delete branches via web', :requires_admin do master_branch = nil second_branch = 'second-branch' @@ -19,8 +16,6 @@ module QA commit_message_of_third_branch = "Add #{file_third_branch}" before do - Runtime::Feature.enable(:bootstrap_confirmation_modals) - Flow::Login.sign_in project = Resource::Project.fabricate_via_api! do |proj| diff --git a/qa/qa/specs/features/browser_ui/3_create/snippet/add_comment_to_snippet_spec.rb b/qa/qa/specs/features/browser_ui/3_create/snippet/add_comment_to_snippet_spec.rb index 171567b7ed9..1a7c64a363f 100644 --- a/qa/qa/specs/features/browser_ui/3_create/snippet/add_comment_to_snippet_spec.rb +++ b/qa/qa/specs/features/browser_ui/3_create/snippet/add_comment_to_snippet_spec.rb @@ -1,10 +1,7 @@ # frozen_string_literal: true module QA - RSpec.describe 'Create', feature_flag: { - name: 'bootstrap_confirmation_modals', - scope: :global - } do + RSpec.describe 'Create' do describe 'Adding comments on snippets' do let(:comment_author) { Resource::User.fabricate_or_use(Runtime::Env.gitlab_qa_username_1, Runtime::Env.gitlab_qa_password_1) } let(:comment_content) { 'Comment 123' } @@ -23,7 +20,6 @@ module QA end before do - Runtime::Feature.enable(:bootstrap_confirmation_modals) Flow::Login.sign_in end diff --git a/qa/qa/specs/features/browser_ui/3_create/snippet/copy_snippet_file_contents_spec.rb b/qa/qa/specs/features/browser_ui/3_create/snippet/copy_snippet_file_contents_spec.rb index ed421ac7279..e4204776c46 100644 --- a/qa/qa/specs/features/browser_ui/3_create/snippet/copy_snippet_file_contents_spec.rb +++ b/qa/qa/specs/features/browser_ui/3_create/snippet/copy_snippet_file_contents_spec.rb @@ -1,10 +1,7 @@ # frozen_string_literal: true module QA - RSpec.describe 'Create', :reliable, feature_flag: { - name: 'bootstrap_confirmation_modals', - scope: :global - } do + RSpec.describe 'Create', :reliable do describe 'Multiple file snippet' do let(:first_file_content) { 'First file content' } let(:second_file_content) { 'Second file content' } @@ -38,23 +35,22 @@ module QA let(:files) do [ - { - number: 1, - content: first_file_content - }, - { - number: 2, - content: second_file_content - }, - { - number: 3, - content: third_file_content - } + { + number: 1, + content: first_file_content + }, + { + number: 2, + content: second_file_content + }, + { + number: 3, + content: third_file_content + } ] end before do - Runtime::Feature.enable(:bootstrap_confirmation_modals) Flow::Login.sign_in end diff --git a/qa/qa/support/api.rb b/qa/qa/support/api.rb index 0c0a1a90ff2..a1bbe9f378a 100644 --- a/qa/qa/support/api.rb +++ b/qa/qa/support/api.rb @@ -141,31 +141,18 @@ module QA get(url).tap { |resp| not_ok_error.call(resp) if resp.code != HTTP_STATUS_OK } end - page, pages = response.headers.values_at(:x_page, :x_total_pages) + page, pages, next_page = response.headers.values_at(:x_page, :x_total_pages, :x_next_page) api_endpoint = url.match(%r{v4/(\S+)\?})[1] QA::Runtime::Logger.debug("Fetching page (#{page}/#{pages}) for '#{api_endpoint}' ...") unless pages.to_i <= 1 yield parse_body(response) - next_link = pagination_links(response).find { |link| link[:rel] == 'next' } - break unless next_link + break if next_page.empty? - url = next_link[:url] + url = url.match?(/&page=\d+/) ? url.gsub(/&page=\d+/, "&page=#{next_page}") : "#{url}&page=#{next_page}" end end - - def pagination_links(response) - link = response.headers[:link] - return unless link - - link.split(',').map do |link| - match = link.match(/<(?.*)>; rel="(?\w+)"/) - break nil unless match - - { url: match[:url], rel: match[:rel] } - end.compact - end end end end diff --git a/spec/helpers/groups_helper_spec.rb b/spec/helpers/groups_helper_spec.rb index 3ea5701c134..bcbe571db5e 100644 --- a/spec/helpers/groups_helper_spec.rb +++ b/spec/helpers/groups_helper_spec.rb @@ -472,4 +472,36 @@ RSpec.describe GroupsHelper do }) end end + + describe "#enabled_git_access_protocol_options_for_group" do + subject { helper.enabled_git_access_protocol_options_for_group } + + before do + expect(::Gitlab::CurrentSettings).to receive(:enabled_git_access_protocol).and_return(instance_setting) + end + + context "instance setting is nil" do + let(:instance_setting) { nil } + + it { is_expected.to contain_exactly([_("Both SSH and HTTP(S)"), "all"], [_("Only SSH"), "ssh"], [_("Only HTTP(S)"), "http"]) } + end + + context "instance setting is blank" do + let(:instance_setting) { nil } + + it { is_expected.to contain_exactly([_("Both SSH and HTTP(S)"), "all"], [_("Only SSH"), "ssh"], [_("Only HTTP(S)"), "http"]) } + end + + context "instance setting is ssh" do + let(:instance_setting) { "ssh" } + + it { is_expected.to contain_exactly([_("Only SSH"), "ssh"]) } + end + + context "instance setting is http" do + let(:instance_setting) { "http" } + + it { is_expected.to contain_exactly([_("Only HTTP(S)"), "http"]) } + end + end end diff --git a/spec/lib/gitlab/ci/jwt_spec.rb b/spec/lib/gitlab/ci/jwt_spec.rb index b0d6f5adfb1..179e2efc0c7 100644 --- a/spec/lib/gitlab/ci/jwt_spec.rb +++ b/spec/lib/gitlab/ci/jwt_spec.rb @@ -160,20 +160,8 @@ RSpec.describe Gitlab::Ci::Jwt do subject(:jwt) { described_class.for_build(build) } - context 'when ci_jwt_signing_key feature flag is disabled' do + context 'when ci_jwt_signing_key is present' do before do - stub_feature_flags(ci_jwt_signing_key: false) - - allow(Rails.application.secrets).to receive(:openid_connect_signing_key).and_return(rsa_key_data) - end - - it_behaves_like 'generating JWT for build' - end - - context 'when ci_jwt_signing_key feature flag is enabled' do - before do - stub_feature_flags(ci_jwt_signing_key: true) - stub_application_setting(ci_jwt_signing_key: rsa_key_data) end diff --git a/spec/lib/gitlab/git_access_spec.rb b/spec/lib/gitlab/git_access_spec.rb index e628a06a542..5ee9cf05b3e 100644 --- a/spec/lib/gitlab/git_access_spec.rb +++ b/spec/lib/gitlab/git_access_spec.rb @@ -34,7 +34,7 @@ RSpec.describe Gitlab::GitAccess do describe '#check with single protocols allowed' do def disable_protocol(protocol) - allow(Gitlab::ProtocolAccess).to receive(:allowed?).with(protocol).and_return(false) + allow(Gitlab::ProtocolAccess).to receive(:allowed?).with(protocol, project: project).and_return(false) end context 'ssh disabled' do diff --git a/spec/lib/gitlab/protocol_access_spec.rb b/spec/lib/gitlab/protocol_access_spec.rb new file mode 100644 index 00000000000..4722ea99608 --- /dev/null +++ b/spec/lib/gitlab/protocol_access_spec.rb @@ -0,0 +1,50 @@ +# frozen_string_literal: true + +require "spec_helper" + +RSpec.describe Gitlab::ProtocolAccess do + using RSpec::Parameterized::TableSyntax + + let_it_be(:group) { create(:group) } + let_it_be(:p1) { create(:project, :repository, namespace: group) } + + describe ".allowed?" do + where(:protocol, :project, :admin_setting, :namespace_setting, :expected_result) do + "web" | nil | nil | nil | true + "ssh" | nil | nil | nil | true + "http" | nil | nil | nil | true + "ssh" | nil | "" | nil | true + "http" | nil | "" | nil | true + "ssh" | nil | "ssh" | nil | true + "http" | nil | "http" | nil | true + "ssh" | nil | "http" | nil | false + "http" | nil | "ssh" | nil | false + "ssh" | ref(:p1) | nil | "all" | true + "http" | ref(:p1) | nil | "all" | true + "ssh" | ref(:p1) | nil | "ssh" | true + "http" | ref(:p1) | nil | "http" | true + "ssh" | ref(:p1) | nil | "http" | false + "http" | ref(:p1) | nil | "ssh" | false + "ssh" | ref(:p1) | "" | "all" | true + "http" | ref(:p1) | "" | "all" | true + "ssh" | ref(:p1) | "ssh" | "ssh" | true + "http" | ref(:p1) | "http" | "http" | true + end + + with_them do + subject { described_class.allowed?(protocol, project: project) } + + before do + allow(Gitlab::CurrentSettings).to receive(:enabled_git_access_protocol).and_return(admin_setting) + + if project.present? + project.root_namespace.namespace_settings.update!(enabled_git_access_protocol: namespace_setting) + end + end + + it do + is_expected.to be(expected_result) + end + end + end +end diff --git a/spec/lib/gitlab/usage/metrics/instrumentations/unique_active_users_metric_spec.rb b/spec/lib/gitlab/usage/metrics/instrumentations/unique_active_users_metric_spec.rb new file mode 100644 index 00000000000..8a0ce61de74 --- /dev/null +++ b/spec/lib/gitlab/usage/metrics/instrumentations/unique_active_users_metric_spec.rb @@ -0,0 +1,31 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Gitlab::Usage::Metrics::Instrumentations::UniqueActiveUsersMetric do + let_it_be(:user1) { create(:user, last_activity_on: 1.day.ago) } + let_it_be(:user2) { create(:user, last_activity_on: 5.days.ago) } + let_it_be(:user3) { create(:user, last_activity_on: 50.days.ago) } + let_it_be(:user4) { create(:user) } + let_it_be(:user5) { create(:user, user_type: 1, last_activity_on: 5.days.ago ) } # support bot + let_it_be(:user6) { create(:user, state: 'blocked') } + + context '28d' do + let(:start) { 30.days.ago.to_date.to_s } + let(:finish) { 2.days.ago.to_date.to_s } + let(:expected_value) { 1 } + let(:expected_query) do + "SELECT COUNT(\"users\".\"id\") FROM \"users\" WHERE (\"users\".\"state\" IN ('active')) AND " \ + "(\"users\".\"user_type\" IS NULL OR \"users\".\"user_type\" IN (6, 4)) AND \"users\".\"last_activity_on\" " \ + "BETWEEN '#{start}' AND '#{finish}'" + end + + it_behaves_like 'a correct instrumented metric value and query', { time_frame: '28d' } + end + + context 'all' do + let(:expected_value) { 4 } + + it_behaves_like 'a correct instrumented metric value', { time_frame: 'all' } + end +end diff --git a/spec/models/namespace_setting_spec.rb b/spec/models/namespace_setting_spec.rb index c9f8a1bcdc2..25234db5734 100644 --- a/spec/models/namespace_setting_spec.rb +++ b/spec/models/namespace_setting_spec.rb @@ -12,6 +12,7 @@ RSpec.describe NamespaceSetting, type: :model do end it { is_expected.to define_enum_for(:jobs_to_be_done).with_values([:basics, :move_repository, :code_storage, :exploring, :ci, :other]).with_suffix } + it { is_expected.to define_enum_for(:enabled_git_access_protocol).with_values([:all, :ssh, :http]).with_suffix } describe "validations" do describe "#default_branch_name_content" do