diff options
19 files changed, 501 insertions, 14 deletions
diff --git a/app/assets/stylesheets/application_dark.scss b/app/assets/stylesheets/application_dark.scss index 30db4e2296d..7d6ccc40278 100644 --- a/app/assets/stylesheets/application_dark.scss +++ b/app/assets/stylesheets/application_dark.scss @@ -58,7 +58,7 @@ body.gl-dark { } } - .md code { + .md :not(pre.code) > code { background-color: $gray-200; } } diff --git a/app/models/application_setting/term.rb b/app/models/application_setting/term.rb index acdd7e4155c..8910f22c502 100644 --- a/app/models/application_setting/term.rb +++ b/app/models/application_setting/term.rb @@ -3,13 +3,12 @@ class ApplicationSetting class Term < ApplicationRecord include CacheMarkdownField - include NullifyIfBlank has_many :term_agreements cache_markdown_field :terms - nullify_if_blank :terms + validates :terms, presence: true def self.latest order(:id).last diff --git a/app/services/application_settings/update_service.rb b/app/services/application_settings/update_service.rb index 0f2099793ea..7728982779e 100644 --- a/app/services/application_settings/update_service.rb +++ b/app/services/application_settings/update_service.rb @@ -67,8 +67,10 @@ module ApplicationSettings end def update_terms(terms) + return unless terms.present? + # Avoid creating a new terms record if the text is exactly the same. - terms = terms&.strip + terms = terms.strip return if terms == @application_setting.terms ApplicationSetting::Term.create(terms: terms) diff --git a/config.ru b/config.ru index ed76239ef2e..ebe719d4b0f 100644 --- a/config.ru +++ b/config.ru @@ -9,6 +9,12 @@ def master_process? end warmup do |app| + # The following is necessary to ensure stale Prometheus metrics don't accumulate over time. + # It needs to be done as early as here to ensure metrics files aren't deleted. + # After we hit our app in `warmup`, first metrics and corresponding files already being created, + # for example in `lib/gitlab/metrics/requests_rack_middleware.rb`. + Prometheus::CleanupMultiprocDirService.new.execute if master_process? + client = Rack::MockRequest.new(app) client.get('/') end diff --git a/config/initializers/7_prometheus_metrics.rb b/config/initializers/7_prometheus_metrics.rb index fc69ae7b077..d2d546a5438 100644 --- a/config/initializers/7_prometheus_metrics.rb +++ b/config/initializers/7_prometheus_metrics.rb @@ -40,9 +40,6 @@ if !Rails.env.test? && Gitlab::Metrics.prometheus_metrics_enabled? # When running Puma in a Single mode, `on_master_start` and `on_worker_start` are the same. # Thus, we order these events to run `reinitialize_on_pid_change` with `force: true` first. Gitlab::Cluster::LifecycleEvents.on_master_start do - # Ensure that stale Prometheus metrics don't accumulate over time - ::Prometheus::CleanupMultiprocDirService.new.execute - ::Prometheus::Client.reinitialize_on_pid_change(force: true) if Gitlab::Runtime.puma? diff --git a/data/whats_new/202107220001_14_1.yml b/data/whats_new/202107220001_14_1.yml new file mode 100644 index 00000000000..5ab4651a43c --- /dev/null +++ b/data/whats_new/202107220001_14_1.yml @@ -0,0 +1,139 @@ +- title: Track progress on overall DevOps adoption + body: | + See the total number of key DevOps features adopted across your organization using the new progress bars in DevOps Adoption. Progress bars help you understand the value that teams are getting from GitLab and evaluate the state of your DevOps transformation. + stage: Manage + self-managed: true + gitlab-com: true + packages: [Ultimate] + url: https://docs.gitlab.com/ee/user/group/devops_adoption/ + image_url: https://about.gitlab.com/images/14_1/progressbar.png + published_at: 2021-07-22 + release: 14.1 +- title: Track use of security scanning across multiple teams + body: | + Track which groups across your organization have enabled SAST and DAST scanning. This is helpful for verifying compliance with organizational requirements, responding to audit requests, and tracking progress on company initiatives to make applications more secure. To track adoption, go to the **Sec** tab in DevOps Adoption either at the group level or instance level. + To see groups that have enabled fuzz testing and dependency scanning, use [the DevOps API](https://docs.gitlab.com/ee/api/graphql/reference/index.html#devopsadoptionsnapshot). Fuzz testing and dependency scanning will be added to the DevOps Adoption UI in an upcoming release. + stage: Manage + self-managed: true + gitlab-com: true + packages: [Ultimate] + url: https://docs.gitlab.com/ee/user/group/devops_adoption + image_url: https://about.gitlab.com/images/14_1/scanadoption.png + published_at: 2021-07-22 + release: 14.1 +- title: Create and apply patches in VS Code + body: | + When reviewing a merge request (MR) it can be helpful to make suggestions to many of the changed files. This is often done by creating a patch file with the suggestions and sharing it with others. The problem is that this requires several manual steps like running Git commands and uploading the patch file somewhere others can download it. + + With [GitLab Workflow](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow) [v3.26.0](https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/blob/main/CHANGELOG.md#3260-2021-07-13) for VS Code you can now create and apply patches directly in your editor. The new `GitLab: Create snippet patch` command creates a patch with the changes in your editor and uploads that patch as a [GitLab snippet](https://docs.gitlab.com/ee/user/snippets.html). + + Anyone can search for patches in the project's snippets and apply them directly in VS Code with the `GitLab: Apply snippet patch` command. The applied changes can then be committed to the MR. + + Sharing and collaborating around patches is a great way to propose more complex suggestions and provide clear improvements. Patches created in VS Code can also be linked to others through snippets and downloaded and applied outside of VS Code for users with different editing tools. + stage: Create + self-managed: true + gitlab-com: true + packages: [Free, Premium, Ultimate] + url: 'https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/blob/main/README.md#create-and-apply-snippet-patch' + image_url: https://img.youtube.com/vi/QQxpLoKJULQ/hqdefault.jpg + published_at: 2021-07-22 + release: 14.1 +- title: Code coverage merge request approval rule + body: | + To keep code test coverage high, you need to ensure that merge requests to your codebase never decrease test coverage. Previously, the only way to enforce this was to [require approvals](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/#required-approvals) from users who would check for test coverage decreases as part of their reviews. + + Now you can enforce this organizational policy with the new Coverage check approval rule. This is a simple way to ensure merge requests that would decrease test coverage cannot be merged. + stage: Verify + self-managed: true + gitlab-com: true + packages: [Premium, Ultimate] + url: 'https://docs.gitlab.com/ee/ci/pipelines/settings.html#coverage-check-approval-rule' + image_url: https://about.gitlab.com/images/14_1/coverage-mr-approval-rule.png + published_at: 2021-07-22 + release: 14.1 +- title: Registration Features + body: | + [Registration Features](https://docs.gitlab.com/ee/development/service_ping/index.html#registration-features-program) introduces the ability for free, self-managed users running GitLab EE to access paid features by registering with GitLab and sharing activity data via [Service Ping](https://docs.gitlab.com/ee/development/service_ping/index.html#what-is-service-ping). The first feature introduced is [email from GitLab](https://docs.gitlab.com/ee/tools/email.html), enabling instance administrators to email users within their instance. + stage: Growth + self-managed: true + gitlab-com: false + packages: [Free] + url: 'https://docs.gitlab.com/ee/development/service_ping/index.html#registration-features-program' + image_url: https://about.gitlab.com/images/14_1/registration-features.png + published_at: 2021-07-22 + release: 14.1 +- title: Build, publish, and share Helm charts + body: | + Helm defines a [chart](https://helm.sh/docs/intro/using_helm/#three-big-concepts) as a Helm package that contains all of the resource definitions necessary to run an application, tool, or service inside of a Kubernetes cluster. For organizations that create and manage their own Helm charts, it's important to have a central repository to collect and share them. + + GitLab already supports a variety of other [package manager formats](https://docs.gitlab.com/ee/user/packages/). Why not also support Helm? That's what community member and [MVP from the 14.0 milestone](https://about.gitlab.com/releases/2021/06/22/gitlab-14-0-released/#mvp) [Mathieu Parent](https://gitlab.com/sathieu) asked several months ago before breaking ground on the new GitLab Helm chart registry. The collaboration between the community and GitLab is part of our [dual flywheel strategy](https://about.gitlab.com/company/strategy/#dual-flywheels) and one of the reasons we love working at GitLab. Chapeau Mathieu! + + Now you can use your GitLab project to publish and share packaged Helm charts. Simply add your project as a remote, authenticating with a personal access, deploy, or CI/CD job token. Once that's done you can use the Helm client or GitLab CI/CD to manage your Helm charts. You can also download the charts using the [API](https://docs.gitlab.com/ee/api/packages.html#get-a-project-package) or the [user interface](https://docs.gitlab.com/ee/user/packages/package_registry/#download-a-package). + stage: Package + self-managed: true + gitlab-com: true + packages: [Free, Premium, Ultimate] + url: https://docs.gitlab.com/ee/user/packages/helm_repository/ + image_url: https://img.youtube.com/vi/B6K373-pAgw/hqdefault.jpg + published_at: 2021-07-22 + release: 14.1 +- title: Escalation Policies + body: | + Being on-call is a stressful, 24/7 job. It's possible to miss a notification despite your best efforts and intentions. Teams that maintain critical systems can't afford to miss alerts for outages or service disruptions. Escalation policies are a safety net for these situations. Escalation policies contain time-boxed steps that automatically page a responder in the next escalation step if the responder in the step before didn't respond. To protect your company from missed critical alerts, create an escalation policy in the GitLab project where you manage on-call schedules. + + In GitLab 14.1, users can create, view, or delete escalation policies. + stage: Monitor + self-managed: true + gitlab-com: true + packages: [Premium, Ultimate] + url: https://docs.gitlab.com/ee/operations/incident_management/escalation_policies.html + image_url: https://img.youtube.com/vi/-1MuKzWJXKQ/hqdefault.jpg + published_at: 2021-07-22 + release: 14.1 +- title: CI/CD Tunnel for Kubernetes clusters + body: | + Until now, connecting Kubernetes clusters to GitLab CI/CD required users to open up their clusters towards GitLab. Some organizations do not encourage opening up their firewall externally due to security concerns. + + GitLab now ships with a CI/CD Tunnel that connects GitLab Runners with your Kubernetes cluster using the [GitLab Kubernetes Agent](https://docs.gitlab.com/ee/user/clusters/agent/). This enables versatile GitOps workflows where the deployment logic can be coded in the pipeline. + + You and your team can safely use your preferred tool to run the deployment itself using `kubectl`, `helm`, `kpt`, `tanka`, or anything else without security concerns. + + To use the tunnel, define the `kubecontext` in your CI/CD pipeline to connect with your agent. To simplify this process, we plan to [automatically inject the `kubecontext`](https://gitlab.com/gitlab-org/gitlab/-/issues/324275) into the CI/CD environment in a future iteration. + + The CI/CD tunnel is currently supported only from the project where the agent was configured but we are working on [adding group-level support](https://gitlab.com/groups/gitlab-org/-/epics/5784). You can safely start using the tunnel on GitLab SaaS and self-managed instances. + stage: Configure + self-managed: true + gitlab-com: true + packages: [Premium, Ultimate] + url: https://docs.gitlab.com/ee/user/clusters/agent/ci_cd_tunnel.html + image_url: https://img.youtube.com/vi/eXxM4ScqiJs/hqdefault.jpg + published_at: 2021-07-22 + release: 14.1 +- title: External status checks for merge requests + body: | + You can now contact an external API to perform a status check in a merge request. This is a great way to integrate GitLab with third-party systems that: + - Run in an external system and do not have specific pipeline jobs. + - Require manual approval in another system. + + In the project, APIs for the status checks can be configured (using either the GitLab UI or the GitLab API) and then when a change is made to a merge request, that API is called with various details about the merge request. The external API can then respond with a return code to indicate if the check has passed. This result is then shown in the merge request. + + This allows teams to easily stay in sync and makes it easy to see that merge requests have met external requirements before being merged, adding an extra method to ensure compliance requirements are met. + stage: Manage + self-managed: true + gitlab-com: true + packages: [Ultimate] + url: https://docs.gitlab.com/ee/user/project/merge_requests/status_checks.html + image_url: https://about.gitlab.com/images/14_1/status-checks-pending.png + published_at: 2021-07-22 + release: 14.1 +- title: Pronouns viewable in user profile snapshot + body: | + You can now see pronouns on the snapshot view of a user profile when you hover over someone's name on an issue or merge request. This helps users better respond to comments using the correct pronouns without needing to navigate to the user's profile. + stage: Manage + self-managed: true + gitlab-com: true + packages: [Free, Premium, Ultimate] + url: 'https://docs.gitlab.com/ee/user/profile/#add-your-gender-pronouns' + image_url: https://about.gitlab.com/images/14_1/pronouns.png + published_at: 2021-07-22 + release: 14.1 diff --git a/db/migrate/20210720083432_change_application_setting_terms_not_null.rb b/db/migrate/20210720083432_change_application_setting_terms_not_null.rb new file mode 100644 index 00000000000..76dbbe68967 --- /dev/null +++ b/db/migrate/20210720083432_change_application_setting_terms_not_null.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +class ChangeApplicationSettingTermsNotNull < ActiveRecord::Migration[6.1] + def up + execute("UPDATE application_setting_terms SET terms = '' WHERE terms IS NULL") + change_column_null :application_setting_terms, :terms, false + end + + def down + change_column_null :application_setting_terms, :terms, true + end +end diff --git a/db/post_migrate/20210430121542_backfill_ci_build_trace_sections_for_bigint_conversion.rb b/db/post_migrate/20210430121542_backfill_ci_build_trace_sections_for_bigint_conversion.rb index f832b06d439..979ce5edfeb 100644 --- a/db/post_migrate/20210430121542_backfill_ci_build_trace_sections_for_bigint_conversion.rb +++ b/db/post_migrate/20210430121542_backfill_ci_build_trace_sections_for_bigint_conversion.rb @@ -7,7 +7,8 @@ class BackfillCiBuildTraceSectionsForBigintConversion < ActiveRecord::Migration[ COLUMN = :build_id def up - backfill_conversion_of_integer_to_bigint TABLE, COLUMN, batch_size: 15000, sub_batch_size: 100, primary_key: COLUMN + # No-op to disable the migration: + # backfill_conversion_of_integer_to_bigint TABLE, COLUMN, batch_size: 15000, sub_batch_size: 100, primary_key: COLUMN end def down diff --git a/db/post_migrate/20210722110515_revert_backfill_ci_build_trace_sections_for_bigint_conversion.rb b/db/post_migrate/20210722110515_revert_backfill_ci_build_trace_sections_for_bigint_conversion.rb new file mode 100644 index 00000000000..840540bb0d4 --- /dev/null +++ b/db/post_migrate/20210722110515_revert_backfill_ci_build_trace_sections_for_bigint_conversion.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true + +class RevertBackfillCiBuildTraceSectionsForBigintConversion < ActiveRecord::Migration[6.1] + include Gitlab::Database::MigrationHelpers + + TABLE = :ci_build_trace_sections + COLUMN = :build_id + + def up + revert_backfill_conversion_of_integer_to_bigint TABLE, COLUMN, primary_key: COLUMN + end + + def down + # no-op + end +end diff --git a/db/schema_migrations/20210720083432 b/db/schema_migrations/20210720083432 new file mode 100644 index 00000000000..44c8b4ae689 --- /dev/null +++ b/db/schema_migrations/20210720083432 @@ -0,0 +1 @@ +6096780be4fae007485f150a019fc4555153e4b22b893d5fe29be36834d970a9
\ No newline at end of file diff --git a/db/schema_migrations/20210722110515 b/db/schema_migrations/20210722110515 new file mode 100644 index 00000000000..1e4791fc2f9 --- /dev/null +++ b/db/schema_migrations/20210722110515 @@ -0,0 +1 @@ +c9057cb28d2576551eafe78998023742018fa8351f2e550b7e35832a5509d21c
\ No newline at end of file diff --git a/db/structure.sql b/db/structure.sql index da2d4c50068..3a11a1fc7ab 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -9216,7 +9216,7 @@ ALTER SEQUENCE appearances_id_seq OWNED BY appearances.id; CREATE TABLE application_setting_terms ( id integer NOT NULL, cached_markdown_version integer, - terms text, + terms text NOT NULL, terms_html text ); diff --git a/lib/gitlab/auth/auth_finders.rb b/lib/gitlab/auth/auth_finders.rb index 0796f23fbfe..f54fa7504a3 100644 --- a/lib/gitlab/auth/auth_finders.rb +++ b/lib/gitlab/auth/auth_finders.rb @@ -89,6 +89,32 @@ module Gitlab job.user end + def find_user_from_basic_auth_password + return unless has_basic_credentials?(current_request) + + login, password = user_name_and_password(current_request) + return if ::Gitlab::Auth::CI_JOB_USER == login + + Gitlab::Auth.find_with_user_password(login, password) + end + + def find_user_from_lfs_token + return unless has_basic_credentials?(current_request) + + login, token = user_name_and_password(current_request) + user = User.by_login(login) + + user if user && Gitlab::LfsToken.new(user).token_valid?(token) + end + + def find_user_from_personal_access_token + return unless access_token + + validate_access_token! + + access_token&.user || raise(UnauthorizedError) + end + # We allow Private Access Tokens with `api` scope to be used by web # requests on RSS feeds or ICS files for backwards compatibility. # It is also used by GraphQL/API requests. @@ -308,6 +334,10 @@ module Gitlab current_request.path.starts_with?(Gitlab::Utils.append_path(Gitlab.config.gitlab.relative_url_root, '/api/')) end + def git_request? + Gitlab::PathRegex.repository_git_route_regex.match?(current_request.path) + end + def archive_request? current_request.path.include?('/-/archive/') end diff --git a/lib/gitlab/auth/request_authenticator.rb b/lib/gitlab/auth/request_authenticator.rb index 504265a83ef..dfc682e8a5c 100644 --- a/lib/gitlab/auth/request_authenticator.rb +++ b/lib/gitlab/auth/request_authenticator.rb @@ -34,7 +34,10 @@ module Gitlab find_user_from_feed_token(request_format) || find_user_from_static_object_token(request_format) || find_user_from_basic_auth_job || - find_user_from_job_token + find_user_from_job_token || + find_user_from_lfs_token || + find_user_from_personal_access_token || + find_user_from_basic_auth_password rescue Gitlab::Auth::AuthenticationError nil end @@ -58,7 +61,7 @@ module Gitlab def route_authentication_setting @route_authentication_setting ||= { job_token_allowed: api_request?, - basic_auth_personal_access_token: api_request? + basic_auth_personal_access_token: api_request? || git_request? } end end diff --git a/spec/lib/gitlab/auth/auth_finders_spec.rb b/spec/lib/gitlab/auth/auth_finders_spec.rb index 14200733c19..2d4239eb761 100644 --- a/spec/lib/gitlab/auth/auth_finders_spec.rb +++ b/spec/lib/gitlab/auth/auth_finders_spec.rb @@ -708,6 +708,122 @@ RSpec.describe Gitlab::Auth::AuthFinders do end end + describe '#find_user_from_basic_auth_password' do + subject { find_user_from_basic_auth_password } + + context 'when the request does not have AUTHORIZATION header' do + it { is_expected.to be_nil } + end + + it 'returns nil without user and password' do + set_basic_auth_header(nil, nil) + + is_expected.to be_nil + end + + it 'returns nil without password' do + set_basic_auth_header('some-user', nil) + + is_expected.to be_nil + end + + it 'returns nil without user' do + set_basic_auth_header(nil, 'password') + + is_expected.to be_nil + end + + it 'returns nil with CI username' do + set_basic_auth_header(::Gitlab::Auth::CI_JOB_USER, 'password') + + is_expected.to be_nil + end + + it 'returns nil with wrong password' do + set_basic_auth_header(user.username, 'wrong-password') + + is_expected.to be_nil + end + + it 'returns user with correct credentials' do + set_basic_auth_header(user.username, user.password) + + is_expected.to eq(user) + end + end + + describe '#find_user_from_lfs_token' do + subject { find_user_from_lfs_token } + + context 'when the request does not have AUTHORIZATION header' do + it { is_expected.to be_nil } + end + + it 'returns nil without user and token' do + set_basic_auth_header(nil, nil) + + is_expected.to be_nil + end + + it 'returns nil without token' do + set_basic_auth_header('some-user', nil) + + is_expected.to be_nil + end + + it 'returns nil without user' do + set_basic_auth_header(nil, 'token') + + is_expected.to be_nil + end + + it 'returns nil with wrong token' do + set_basic_auth_header(user.username, 'wrong-token') + + is_expected.to be_nil + end + + it 'returns user with correct user and correct token' do + lfs_token = Gitlab::LfsToken.new(user).token + set_basic_auth_header(user.username, lfs_token) + + is_expected.to eq(user) + end + + it 'returns nil with wrong user and correct token' do + lfs_token = Gitlab::LfsToken.new(user).token + other_user = create(:user) + set_basic_auth_header(other_user.username, lfs_token) + + is_expected.to be_nil + end + end + + describe '#find_user_from_personal_access_token' do + subject { find_user_from_personal_access_token } + + it 'returns nil without access token' do + allow_any_instance_of(described_class).to receive(:access_token).and_return(nil) + + is_expected.to be_nil + end + + it 'returns user with correct access token' do + personal_access_token = create(:personal_access_token, user: user) + allow_any_instance_of(described_class).to receive(:access_token).and_return(personal_access_token) + + is_expected.to eq(user) + end + + it 'returns exception if access token has no user' do + personal_access_token = create(:personal_access_token, user: user) + allow_any_instance_of(described_class).to receive(:access_token).and_return(personal_access_token) + allow_any_instance_of(PersonalAccessToken).to receive(:user).and_return(nil) + + expect { subject }.to raise_error(Gitlab::Auth::UnauthorizedError) + end + end + describe '#validate_access_token!' do subject { validate_access_token! } diff --git a/spec/lib/gitlab/auth/request_authenticator_spec.rb b/spec/lib/gitlab/auth/request_authenticator_spec.rb index 93e9cb06786..28e93a8da52 100644 --- a/spec/lib/gitlab/auth/request_authenticator_spec.rb +++ b/spec/lib/gitlab/auth/request_authenticator_spec.rb @@ -45,6 +45,9 @@ RSpec.describe Gitlab::Auth::RequestAuthenticator do let!(:feed_token_user) { build(:user) } let!(:static_object_token_user) { build(:user) } let!(:job_token_user) { build(:user) } + let!(:lfs_token_user) { build(:user) } + let!(:basic_auth_access_token_user) { build(:user) } + let!(:basic_auth_password_user) { build(:user) } it 'returns access_token user first' do allow_any_instance_of(described_class).to receive(:find_user_from_web_access_token) @@ -78,6 +81,30 @@ RSpec.describe Gitlab::Auth::RequestAuthenticator do expect(subject.find_sessionless_user(:api)).to eq job_token_user end + it 'returns lfs_token user if no job_token user found' do + allow_any_instance_of(described_class) + .to receive(:find_user_from_lfs_token) + .and_return(lfs_token_user) + + expect(subject.find_sessionless_user(:api)).to eq lfs_token_user + end + + it 'returns basic_auth_access_token user if no lfs_token user found' do + allow_any_instance_of(described_class) + .to receive(:find_user_from_personal_access_token) + .and_return(basic_auth_access_token_user) + + expect(subject.find_sessionless_user(:api)).to eq basic_auth_access_token_user + end + + it 'returns basic_auth_access_password user if no basic_auth_access_token user found' do + allow_any_instance_of(described_class) + .to receive(:find_user_from_basic_auth_password) + .and_return(basic_auth_password_user) + + expect(subject.find_sessionless_user(:api)).to eq basic_auth_password_user + end + it 'returns nil if no user found' do expect(subject.find_sessionless_user(:api)).to be_blank end @@ -194,4 +221,27 @@ RSpec.describe Gitlab::Auth::RequestAuthenticator do expect(subject.runner).to be_blank end end + + describe '#route_authentication_setting' do + using RSpec::Parameterized::TableSyntax + + where(:script_name, :expected_job_token_allowed, :expected_basic_auth_personal_access_token) do + '/api/endpoint' | true | true + '/namespace/project.git' | false | true + '/web/endpoint' | false | false + end + + with_them do + before do + env['SCRIPT_NAME'] = script_name + end + + it 'returns correct settings' do + expect(subject.send(:route_authentication_setting)).to eql({ + job_token_allowed: expected_job_token_allowed, + basic_auth_personal_access_token: expected_basic_auth_personal_access_token + }) + end + end + end end diff --git a/spec/models/application_setting/term_spec.rb b/spec/models/application_setting/term_spec.rb index d9efa597352..6c7f29cbd71 100644 --- a/spec/models/application_setting/term_spec.rb +++ b/spec/models/application_setting/term_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' RSpec.describe ApplicationSetting::Term do - it { is_expected.to nullify_if_blank(:terms) } + it { is_expected.to validate_presence_of(:terms) } describe '.latest' do it 'finds the latest terms' do diff --git a/spec/requests/rack_attack_global_spec.rb b/spec/requests/rack_attack_global_spec.rb index f7b1b4726f6..a0f9d4c11ed 100644 --- a/spec/requests/rack_attack_global_spec.rb +++ b/spec/requests/rack_attack_global_spec.rb @@ -677,4 +677,118 @@ RSpec.describe 'Rack Attack global throttles', :use_clean_rails_memory_store_cac it_behaves_like 'reject requests over the rate limit' end end + + describe 'Gitlab::RackAttack::Request#unauthenticated?' do + let_it_be(:url) { "/api/v4/projects" } + let_it_be(:user) { create(:user) } + + def expect_unauthenticated_request + expect_next_instance_of(Rack::Attack::Request) do |instance| + expect(instance.unauthenticated?).to be true + end + end + + def expect_authenticated_request + expect_next_instance_of(Rack::Attack::Request) do |instance| + expect(instance.unauthenticated?).to be false + end + end + + before do + settings_to_set[:throttle_unauthenticated_enabled] = true + stub_application_setting(settings_to_set) + end + + context 'without authentication' do + it 'request is unauthenticated' do + expect_unauthenticated_request + + get url + end + end + + context 'authenticated by a runner token' do + let_it_be(:runner) { create(:ci_runner) } + + it 'request is authenticated' do + expect_authenticated_request + + get url, params: { token: runner.token } + end + end + + context 'authenticated with personal access token' do + let_it_be(:personal_access_token) { create(:personal_access_token, user: user) } + + it 'request is authenticated by token in query string' do + expect_authenticated_request + + get url, params: { private_token: personal_access_token.token } + end + + it 'request is authenticated by token in the headers' do + expect_authenticated_request + + get url, headers: personal_access_token_headers(personal_access_token) + end + + it 'request is authenticated by token in the OAuth headers' do + expect_authenticated_request + + get url, headers: oauth_token_headers(personal_access_token) + end + + it 'request is authenticated by token in basic auth' do + expect_authenticated_request + + get url, headers: basic_auth_headers(user, personal_access_token) + end + end + + context 'authenticated with OAuth token' do + let(:application) { Doorkeeper::Application.create!(name: "MyApp", redirect_uri: "https://app.com", owner: user) } + let(:oauth_token) { Doorkeeper::AccessToken.create!(application_id: application.id, resource_owner_id: user.id, scopes: "api") } + + it 'request is authenticated by token in query string' do + expect_authenticated_request + + get url, params: { access_token: oauth_token.token } + end + + it 'request is authenticated by token in the headers' do + expect_authenticated_request + + get url, headers: oauth_token_headers(oauth_token) + end + end + + context 'authenticated with lfs token' do + it 'request is authenticated by token in basic auth' do + lfs_token = Gitlab::LfsToken.new(user) + encoded_login = ["#{user.username}:#{lfs_token.token}"].pack('m0') + + expect_authenticated_request + + get url, headers: { 'AUTHORIZATION' => "Basic #{encoded_login}" } + end + end + + context 'authenticated with regular login' do + it 'request is authenticated after login' do + login_as(user) + + expect_authenticated_request + + get url + end + + it 'request is authenticated by credentials in basic auth' do + encoded_login = ["#{user.username}:#{user.password}"].pack('m0') + + expect_authenticated_request + + get url, headers: { 'AUTHORIZATION' => "Basic #{encoded_login}" } + end + end + end end diff --git a/spec/services/application_settings/update_service_spec.rb b/spec/services/application_settings/update_service_spec.rb index 5f0c02cd521..56c1284927d 100644 --- a/spec/services/application_settings/update_service_spec.rb +++ b/spec/services/application_settings/update_service_spec.rb @@ -23,8 +23,8 @@ RSpec.describe ApplicationSettings::UpdateService do context 'when the passed terms are blank' do let(:params) { { terms: '' } } - it 'does create terms' do - expect { subject.execute }.to change { ApplicationSetting::Term.count }.by(1) + it 'does not create terms' do + expect { subject.execute }.not_to change { ApplicationSetting::Term.count } end end |