diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-01-04 21:10:19 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-01-04 21:10:19 +0000 |
commit | 9248363e3eb740b2f1dccb3a63f09aff4fcdf94f (patch) | |
tree | ee6b7e7122a3b6c9b21e4a163ad116e354cca483 | |
parent | db3acec198e92833482b9ce5c055f562b06a14a1 (diff) | |
download | gitlab-ce-9248363e3eb740b2f1dccb3a63f09aff4fcdf94f.tar.gz |
Add latest changes from gitlab-org/gitlab@master
33 files changed, 291 insertions, 130 deletions
@@ -145,7 +145,7 @@ gem 'aws-sdk-s3', '~> 1' gem 'faraday_middleware-aws-sigv4', '~>0.3.0' # Markdown and HTML processing -gem 'html-pipeline', '~> 2.12' +gem 'html-pipeline', '~> 2.13.2' gem 'deckar01-task_list', '2.3.1' gem 'gitlab-markup', '~> 1.7.1' gem 'github-markup', '~> 1.7.0', require: 'github/markup' diff --git a/Gemfile.lock b/Gemfile.lock index 88ae776579f..e046f9172d6 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -577,7 +577,7 @@ GEM hipchat (1.5.2) httparty mimemagic - html-pipeline (2.12.2) + html-pipeline (2.13.2) activesupport (>= 2) nokogiri (>= 1.4) html2text (0.2.0) @@ -1391,7 +1391,7 @@ DEPENDENCIES hashie-forbidden_attributes health_check (~> 3.0) hipchat (~> 1.5.0) - html-pipeline (~> 2.12) + html-pipeline (~> 2.13.2) html2text httparty (~> 0.16.4) icalendar diff --git a/app/controllers/projects/pipeline_schedules_controller.rb b/app/controllers/projects/pipeline_schedules_controller.rb index 5655d3b4c0d..4af7508b935 100644 --- a/app/controllers/projects/pipeline_schedules_controller.rb +++ b/app/controllers/projects/pipeline_schedules_controller.rb @@ -17,7 +17,6 @@ class Projects::PipelineSchedulesController < Projects::ApplicationController @scope = params[:scope] @all_schedules = Ci::PipelineSchedulesFinder.new(@project).execute @schedules = Ci::PipelineSchedulesFinder.new(@project).execute(scope: params[:scope]) - .includes(:last_pipeline) end # rubocop: enable CodeReuse/ActiveRecord diff --git a/changelogs/unreleased/254664-fix-pipeline-schedules-timeouts.yml b/changelogs/unreleased/254664-fix-pipeline-schedules-timeouts.yml new file mode 100644 index 00000000000..bc608206847 --- /dev/null +++ b/changelogs/unreleased/254664-fix-pipeline-schedules-timeouts.yml @@ -0,0 +1,5 @@ +--- +title: Index ci_pipelines on pipeline_schedule_id and id +merge_request: 50478 +author: +type: performance diff --git a/changelogs/unreleased/270392-ldap-override-throws-404-when-member-has-minimal-access.yml b/changelogs/unreleased/270392-ldap-override-throws-404-when-member-has-minimal-access.yml new file mode 100644 index 00000000000..8d902f8961c --- /dev/null +++ b/changelogs/unreleased/270392-ldap-override-throws-404-when-member-has-minimal-access.yml @@ -0,0 +1,5 @@ +--- +title: Fix LDAP override throws 404 when member has Minimal access +merge_request: 50680 +author: +type: fixed diff --git a/changelogs/unreleased/eliminate-tz-sensitivity-ci-analytics-charts.yml b/changelogs/unreleased/eliminate-tz-sensitivity-ci-analytics-charts.yml new file mode 100644 index 00000000000..23b00c80186 --- /dev/null +++ b/changelogs/unreleased/eliminate-tz-sensitivity-ci-analytics-charts.yml @@ -0,0 +1,5 @@ +--- +title: Fix empty pipeline analytics charts when time_zone is non-UTC +merge_request: 50760 +author: +type: fixed diff --git a/db/post_migrate/20201223012231_reindex_ci_pipelines_on_schedule_id_and_id.rb b/db/post_migrate/20201223012231_reindex_ci_pipelines_on_schedule_id_and_id.rb new file mode 100644 index 00000000000..9ed1aea911a --- /dev/null +++ b/db/post_migrate/20201223012231_reindex_ci_pipelines_on_schedule_id_and_id.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +class ReindexCiPipelinesOnScheduleIdAndId < ActiveRecord::Migration[6.0] + include Gitlab::Database::MigrationHelpers + + DOWNTIME = false + OLD_INDEX_NAME = 'index_ci_pipelines_on_pipeline_schedule_id' + NEW_INDEX_NAME = 'index_ci_pipelines_on_pipeline_schedule_id_and_id' + + disable_ddl_transaction! + + def up + add_concurrent_index :ci_pipelines, [:pipeline_schedule_id, :id], name: NEW_INDEX_NAME + remove_concurrent_index_by_name :ci_pipelines, OLD_INDEX_NAME + end + + def down + add_concurrent_index :ci_pipelines, :pipeline_schedule_id, name: OLD_INDEX_NAME + remove_concurrent_index_by_name :ci_pipelines, NEW_INDEX_NAME + end +end diff --git a/db/schema_migrations/20201223012231 b/db/schema_migrations/20201223012231 new file mode 100644 index 00000000000..77813ca0655 --- /dev/null +++ b/db/schema_migrations/20201223012231 @@ -0,0 +1 @@ +e845a6704ac92881926cca56bf7fb01c6252f1fe2b2d94fc9d6548144126d6a5
\ No newline at end of file diff --git a/db/structure.sql b/db/structure.sql index 800f7701061..da386570f21 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -21088,7 +21088,7 @@ CREATE INDEX index_ci_pipelines_on_external_pull_request_id ON ci_pipelines USIN CREATE INDEX index_ci_pipelines_on_merge_request_id ON ci_pipelines USING btree (merge_request_id) WHERE (merge_request_id IS NOT NULL); -CREATE INDEX index_ci_pipelines_on_pipeline_schedule_id ON ci_pipelines USING btree (pipeline_schedule_id); +CREATE INDEX index_ci_pipelines_on_pipeline_schedule_id_and_id ON ci_pipelines USING btree (pipeline_schedule_id, id); CREATE INDEX index_ci_pipelines_on_project_id_and_id_desc ON ci_pipelines USING btree (project_id, id DESC); diff --git a/lib/banzai/filter/ascii_doc_sanitization_filter.rb b/lib/banzai/filter/ascii_doc_sanitization_filter.rb index 11762c3bfb4..67f5baf4635 100644 --- a/lib/banzai/filter/ascii_doc_sanitization_filter.rb +++ b/lib/banzai/filter/ascii_doc_sanitization_filter.rb @@ -27,7 +27,7 @@ module Banzai TABLE_GRID_CLASSES = %w(grid-all grid-rows grid-cols grid-none).freeze TABLE_STRIPES_CLASSES = %w(stripes-all stripes-odd stripes-even stripes-hover stripes-none).freeze - ELEMENT_CLASSES_WHITELIST = { + ELEMENT_CLASSES_ALLOWLIST = { span: %w(big small underline overline line-through).freeze, div: ALIGNMENT_BUILTINS_CLASSES + ['admonitionblock'].freeze, td: ['icon'].freeze, @@ -38,35 +38,35 @@ module Banzai table: TABLE_FRAME_CLASSES + TABLE_GRID_CLASSES + TABLE_STRIPES_CLASSES }.freeze - def customize_whitelist(whitelist) + def customize_allowlist(allowlist) # Allow marks - whitelist[:elements].push('mark') + allowlist[:elements].push('mark') # Allow any classes in `span`, `i`, `div`, `td`, `ul`, `ol` and `a` elements # but then remove any unknown classes - whitelist[:attributes]['span'] = %w(class) - whitelist[:attributes]['div'].push('class') - whitelist[:attributes]['td'] = %w(class) - whitelist[:attributes]['i'] = %w(class) - whitelist[:attributes]['ul'] = %w(class) - whitelist[:attributes]['ol'] = %w(class) - whitelist[:attributes]['a'].push('class') - whitelist[:attributes]['table'] = %w(class) - whitelist[:transformers].push(self.class.remove_element_classes) + allowlist[:attributes]['span'] = %w(class) + allowlist[:attributes]['div'].push('class') + allowlist[:attributes]['td'] = %w(class) + allowlist[:attributes]['i'] = %w(class) + allowlist[:attributes]['ul'] = %w(class) + allowlist[:attributes]['ol'] = %w(class) + allowlist[:attributes]['a'].push('class') + allowlist[:attributes]['table'] = %w(class) + allowlist[:transformers].push(self.class.remove_element_classes) # Allow `id` in anchor and footnote elements - whitelist[:attributes]['a'].push('id') - whitelist[:attributes]['div'].push('id') + allowlist[:attributes]['a'].push('id') + allowlist[:attributes]['div'].push('id') # Allow `id` in heading elements for section anchors SECTION_HEADINGS.each do |header| - whitelist[:attributes][header] = %w(id) + allowlist[:attributes][header] = %w(id) end # Remove ids that are not explicitly allowed - whitelist[:transformers].push(self.class.remove_disallowed_ids) + allowlist[:transformers].push(self.class.remove_disallowed_ids) - whitelist + allowlist end class << self @@ -91,11 +91,11 @@ module Banzai lambda do |env| node = env[:node] - return unless (classes_whitelist = ELEMENT_CLASSES_WHITELIST[node.name.to_sym]) + return unless (classes_allowlist = ELEMENT_CLASSES_ALLOWLIST[node.name.to_sym]) return unless node.has_attribute?('class') classes = node['class'].strip.split(' ') - allowed_classes = (classes & classes_whitelist) + allowed_classes = (classes & classes_allowlist) if allowed_classes.empty? node.remove_attribute('class') else diff --git a/lib/banzai/filter/asset_proxy_filter.rb b/lib/banzai/filter/asset_proxy_filter.rb index 8acd3917d81..55dc426edaf 100644 --- a/lib/banzai/filter/asset_proxy_filter.rb +++ b/lib/banzai/filter/asset_proxy_filter.rb @@ -15,7 +15,7 @@ module Banzai needs(:asset_proxy, :asset_proxy_secret_key) if asset_proxy_enabled? end - def asset_host_whitelisted?(host) + def asset_host_allowed?(host) context[:asset_proxy_domain_regexp] ? context[:asset_proxy_domain_regexp].match?(host) : false end @@ -44,21 +44,21 @@ module Banzai Gitlab.config.asset_proxy['enabled'] = application_settings.asset_proxy_enabled Gitlab.config.asset_proxy['url'] = application_settings.asset_proxy_url Gitlab.config.asset_proxy['secret_key'] = application_settings.asset_proxy_secret_key - Gitlab.config.asset_proxy['whitelist'] = determine_whitelist(application_settings) - Gitlab.config.asset_proxy['domain_regexp'] = compile_whitelist(Gitlab.config.asset_proxy.whitelist) + Gitlab.config.asset_proxy['allowlist'] = determine_allowlist(application_settings) + Gitlab.config.asset_proxy['domain_regexp'] = compile_allowlist(Gitlab.config.asset_proxy.allowlist) else Gitlab.config.asset_proxy['enabled'] = ::ApplicationSetting.defaults[:asset_proxy_enabled] end end - def self.compile_whitelist(domain_list) + def self.compile_allowlist(domain_list) return if domain_list.empty? escaped = domain_list.map { |domain| Regexp.escape(domain).gsub('\*', '.*?') } Regexp.new("^(#{escaped.join('|')})$", Regexp::IGNORECASE) end - def self.determine_whitelist(application_settings) + def self.determine_allowlist(application_settings) application_settings.asset_proxy_whitelist.presence || [Gitlab.config.gitlab.host] end end diff --git a/lib/banzai/filter/base_sanitization_filter.rb b/lib/banzai/filter/base_sanitization_filter.rb index 4f9e8cffd11..c63453f94ca 100644 --- a/lib/banzai/filter/base_sanitization_filter.rb +++ b/lib/banzai/filter/base_sanitization_filter.rb @@ -16,42 +16,42 @@ module Banzai UNSAFE_PROTOCOLS = %w(data javascript vbscript).freeze - def whitelist - strong_memoize(:whitelist) do - whitelist = super.deep_dup + def allowlist + strong_memoize(:allowlist) do + allowlist = super.deep_dup # Allow span elements - whitelist[:elements].push('span') + allowlist[:elements].push('span') # Allow data-math-style attribute in order to support LaTeX formatting - whitelist[:attributes]['code'] = %w(data-math-style) - whitelist[:attributes]['pre'] = %w(data-math-style data-mermaid-style data-kroki-style) + allowlist[:attributes]['code'] = %w(data-math-style) + allowlist[:attributes]['pre'] = %w(data-math-style data-mermaid-style data-kroki-style) # Allow html5 details/summary elements - whitelist[:elements].push('details') - whitelist[:elements].push('summary') + allowlist[:elements].push('details') + allowlist[:elements].push('summary') # Allow abbr elements with title attribute - whitelist[:elements].push('abbr') - whitelist[:attributes]['abbr'] = %w(title) + allowlist[:elements].push('abbr') + allowlist[:attributes]['abbr'] = %w(title) # Disallow `name` attribute globally, allow on `a` - whitelist[:attributes][:all].delete('name') - whitelist[:attributes]['a'].push('name') + allowlist[:attributes][:all].delete('name') + allowlist[:attributes]['a'].push('name') # Allow any protocol in `a` elements # and then remove links with unsafe protocols - whitelist[:protocols].delete('a') - whitelist[:transformers].push(self.class.method(:remove_unsafe_links)) + allowlist[:protocols].delete('a') + allowlist[:transformers].push(self.class.method(:remove_unsafe_links)) # Remove `rel` attribute from `a` elements - whitelist[:transformers].push(self.class.remove_rel) + allowlist[:transformers].push(self.class.remove_rel) - customize_whitelist(whitelist) + customize_allowlist(allowlist) end end - def customize_whitelist(whitelist) + def customize_allowlist(allowlist) raise NotImplementedError end diff --git a/lib/banzai/filter/broadcast_message_sanitization_filter.rb b/lib/banzai/filter/broadcast_message_sanitization_filter.rb index 042293170c8..183908d02a9 100644 --- a/lib/banzai/filter/broadcast_message_sanitization_filter.rb +++ b/lib/banzai/filter/broadcast_message_sanitization_filter.rb @@ -6,14 +6,14 @@ module Banzai # # Extends Banzai::Filter::BaseSanitizationFilter with specific rules. class BroadcastMessageSanitizationFilter < Banzai::Filter::BaseSanitizationFilter - def customize_whitelist(whitelist) - whitelist[:elements].push('br') + def customize_allowlist(allowlist) + allowlist[:elements].push('br') - whitelist[:attributes]['a'].push('class', 'style') + allowlist[:attributes]['a'].push('class', 'style') - whitelist[:css] = { properties: %w(color border background padding margin text-decoration) } + allowlist[:css] = { properties: %w(color border background padding margin text-decoration) } - whitelist + allowlist end end end diff --git a/lib/banzai/filter/sanitization_filter.rb b/lib/banzai/filter/sanitization_filter.rb index f57e57890f8..f6314040f28 100644 --- a/lib/banzai/filter/sanitization_filter.rb +++ b/lib/banzai/filter/sanitization_filter.rb @@ -9,26 +9,26 @@ module Banzai # Styles used by Markdown for table alignment TABLE_ALIGNMENT_PATTERN = /text-align: (?<alignment>center|left|right)/.freeze - def customize_whitelist(whitelist) - # Allow table alignment; we whitelist specific text-align values in a + def customize_allowlist(allowlist) + # Allow table alignment; we allow specific text-align values in a # transformer below - whitelist[:attributes]['th'] = %w(style) - whitelist[:attributes]['td'] = %w(style) - whitelist[:css] = { properties: ['text-align'] } + allowlist[:attributes]['th'] = %w(style) + allowlist[:attributes]['td'] = %w(style) + allowlist[:css] = { properties: ['text-align'] } # Allow the 'data-sourcepos' from CommonMark on all elements - whitelist[:attributes][:all].push('data-sourcepos') + allowlist[:attributes][:all].push('data-sourcepos') # Remove any `style` properties not required for table alignment - whitelist[:transformers].push(self.class.remove_unsafe_table_style) + allowlist[:transformers].push(self.class.remove_unsafe_table_style) # Allow `id` in a and li elements for footnotes # and remove any `id` properties not matching for footnotes - whitelist[:attributes]['a'].push('id') - whitelist[:attributes]['li'] = %w(id) - whitelist[:transformers].push(self.class.remove_non_footnote_ids) + allowlist[:attributes]['a'].push('id') + allowlist[:attributes]['li'] = %w(id) + allowlist[:transformers].push(self.class.remove_non_footnote_ids) - whitelist + allowlist end class << self diff --git a/lib/banzai/pipeline/description_pipeline.rb b/lib/banzai/pipeline/description_pipeline.rb index d5ff9b025cc..8f8ce1cbd41 100644 --- a/lib/banzai/pipeline/description_pipeline.rb +++ b/lib/banzai/pipeline/description_pipeline.rb @@ -3,14 +3,14 @@ module Banzai module Pipeline class DescriptionPipeline < FullPipeline - WHITELIST = Banzai::Filter::SanitizationFilter::LIMITED.deep_dup.merge( + ALLOWLIST = Banzai::Filter::SanitizationFilter::LIMITED.deep_dup.merge( elements: Banzai::Filter::SanitizationFilter::LIMITED[:elements] - %w(pre code img ol ul li) ) def self.transform_context(context) super(context).merge( # SanitizationFilter - whitelist: WHITELIST + allowlist: ALLOWLIST ) end end diff --git a/lib/gitlab/auth/auth_finders.rb b/lib/gitlab/auth/auth_finders.rb index e23f4c8592d..4c6254c9e69 100644 --- a/lib/gitlab/auth/auth_finders.rb +++ b/lib/gitlab/auth/auth_finders.rb @@ -92,10 +92,10 @@ module Gitlab # We only 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. - def find_user_from_web_access_token(request_format) + def find_user_from_web_access_token(request_format, scopes: [:api]) return unless access_token && valid_web_access_format?(request_format) - validate_access_token!(scopes: [:api]) + validate_access_token!(scopes: scopes) ::PersonalAccessTokens::LastUsedService.new(access_token).execute diff --git a/lib/gitlab/auth/request_authenticator.rb b/lib/gitlab/auth/request_authenticator.rb index d28ee54cfbc..504265a83ef 100644 --- a/lib/gitlab/auth/request_authenticator.rb +++ b/lib/gitlab/auth/request_authenticator.rb @@ -30,7 +30,7 @@ module Gitlab end def find_sessionless_user(request_format) - find_user_from_web_access_token(request_format) || + find_user_from_web_access_token(request_format, scopes: [:api, :read_api]) || find_user_from_feed_token(request_format) || find_user_from_static_object_token(request_format) || find_user_from_basic_auth_job || diff --git a/lib/gitlab/ci/charts.rb b/lib/gitlab/ci/charts.rb index 25fb9c0ca97..797193a6be5 100644 --- a/lib/gitlab/ci/charts.rb +++ b/lib/gitlab/ci/charts.rb @@ -31,9 +31,10 @@ module Gitlab current = @from while current <= @to - @labels << current.strftime(@format) - @total << (totals_count[current] || 0) - @success << (success_count[current] || 0) + label = current.strftime(@format) + @labels << label + @total << (totals_count[label] || 0) + @success << (success_count[label] || 0) current += interval_step end @@ -45,6 +46,7 @@ module Gitlab query .group("date_trunc('#{interval}', #{::Ci::Pipeline.table_name}.created_at)") .count(:created_at) + .transform_keys { |date| date.strftime(@format) } end # rubocop: enable CodeReuse/ActiveRecord diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 728530184d2..b27d977225a 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -19559,12 +19559,21 @@ msgstr "" msgid "OnDemandScans|Create a new site profile" msgstr "" +msgid "OnDemandScans|Description" +msgstr "" + msgid "OnDemandScans|Edit on-demand DAST scan" msgstr "" +msgid "OnDemandScans|For example: Tests the login page for SQL injections" +msgstr "" + msgid "OnDemandScans|Manage profiles" msgstr "" +msgid "OnDemandScans|My daily scan" +msgstr "" + msgid "OnDemandScans|New on-demand DAST scan" msgstr "" @@ -19583,6 +19592,15 @@ msgstr "" msgid "OnDemandScans|Run scan" msgstr "" +msgid "OnDemandScans|Save and run scan" +msgstr "" + +msgid "OnDemandScans|Save scan" +msgstr "" + +msgid "OnDemandScans|Scan name" +msgstr "" + msgid "OnDemandScans|Scanner profile" msgstr "" diff --git a/package.json b/package.json index fb3bb5ede5f..b33944562f7 100644 --- a/package.json +++ b/package.json @@ -146,7 +146,7 @@ "visibilityjs": "^1.2.4", "vue": "^2.6.12", "vue-apollo": "^3.0.3", - "vue-loader": "^15.9.5", + "vue-loader": "^15.9.6", "vue-router": "3.4.9", "vue-template-compiler": "^2.6.12", "vue-virtual-scroll-list": "^1.4.4", diff --git a/spec/lib/banzai/filter/asset_proxy_filter_spec.rb b/spec/lib/banzai/filter/asset_proxy_filter_spec.rb index 2a4ee28130b..1f886059bf6 100644 --- a/spec/lib/banzai/filter/asset_proxy_filter_spec.rb +++ b/spec/lib/banzai/filter/asset_proxy_filter_spec.rb @@ -35,8 +35,8 @@ RSpec.describe Banzai::Filter::AssetProxyFilter do expect(Gitlab.config.asset_proxy.enabled).to be_truthy expect(Gitlab.config.asset_proxy.secret_key).to eq 'shared-secret' expect(Gitlab.config.asset_proxy.url).to eq 'https://assets.example.com' - expect(Gitlab.config.asset_proxy.whitelist).to eq %w(gitlab.com *.mydomain.com) - expect(Gitlab.config.asset_proxy.domain_regexp).to eq /^(gitlab\.com|.*?\.mydomain\.com)$/i + expect(Gitlab.config.asset_proxy.allowlist).to eq %w(gitlab.com *.mydomain.com) + expect(Gitlab.config.asset_proxy.domain_regexp).to eq(/^(gitlab\.com|.*?\.mydomain\.com)$/i) end context 'when whitelist is empty' do @@ -46,7 +46,7 @@ RSpec.describe Banzai::Filter::AssetProxyFilter do described_class.initialize_settings - expect(Gitlab.config.asset_proxy.whitelist).to eq [Gitlab.config.gitlab.host] + expect(Gitlab.config.asset_proxy.allowlist).to eq [Gitlab.config.gitlab.host] end end end @@ -56,8 +56,8 @@ RSpec.describe Banzai::Filter::AssetProxyFilter do stub_asset_proxy_setting(enabled: true) stub_asset_proxy_setting(secret_key: 'shared-secret') stub_asset_proxy_setting(url: 'https://assets.example.com') - stub_asset_proxy_setting(whitelist: %W(gitlab.com *.mydomain.com #{Gitlab.config.gitlab.host})) - stub_asset_proxy_setting(domain_regexp: described_class.compile_whitelist(Gitlab.config.asset_proxy.whitelist)) + stub_asset_proxy_setting(allowlist: %W(gitlab.com *.mydomain.com #{Gitlab.config.gitlab.host})) + stub_asset_proxy_setting(domain_regexp: described_class.compile_allowlist(Gitlab.config.asset_proxy.allowlist)) @context = described_class.transform_context({}) end diff --git a/spec/lib/banzai/filter/broadcast_message_sanitization_filter_spec.rb b/spec/lib/banzai/filter/broadcast_message_sanitization_filter_spec.rb index 1f65268bd3c..67b480f8973 100644 --- a/spec/lib/banzai/filter/broadcast_message_sanitization_filter_spec.rb +++ b/spec/lib/banzai/filter/broadcast_message_sanitization_filter_spec.rb @@ -5,9 +5,9 @@ require 'spec_helper' RSpec.describe Banzai::Filter::BroadcastMessageSanitizationFilter do include FilterSpecHelper - it_behaves_like 'default whitelist' + it_behaves_like 'default allowlist' - describe 'custom whitelist' do + describe 'custom allowlist' do it_behaves_like 'XSS prevention' it_behaves_like 'sanitize link' @@ -26,19 +26,19 @@ RSpec.describe Banzai::Filter::BroadcastMessageSanitizationFilter do end context 'when `a` elements have `style` attribute' do - let(:whitelisted_style) { 'color: red; border: blue; background: green; padding: 10px; margin: 10px; text-decoration: underline;' } + let(:allowed_style) { 'color: red; border: blue; background: green; padding: 10px; margin: 10px; text-decoration: underline;' } context 'allows specific properties' do - let(:exp) { %{<a href="#" style="#{whitelisted_style}">Stylish Link</a>} } + let(:exp) { %{<a href="#" style="#{allowed_style}">Stylish Link</a>} } it { is_expected.to eq(exp) } end it 'disallows other properties in `style` attribute on `a` elements' do - style = [whitelisted_style, 'position: fixed'].join(';') + style = [allowed_style, 'position: fixed'].join(';') doc = filter(%{<a href="#" style="#{style}">Stylish Link</a>}) - expect(doc.at_css('a')['style']).to eq(whitelisted_style) + expect(doc.at_css('a')['style']).to eq(allowed_style) end end diff --git a/spec/lib/banzai/filter/sanitization_filter_spec.rb b/spec/lib/banzai/filter/sanitization_filter_spec.rb index 09dcd5518ff..bc4b60dfe60 100644 --- a/spec/lib/banzai/filter/sanitization_filter_spec.rb +++ b/spec/lib/banzai/filter/sanitization_filter_spec.rb @@ -5,31 +5,31 @@ require 'spec_helper' RSpec.describe Banzai::Filter::SanitizationFilter do include FilterSpecHelper - it_behaves_like 'default whitelist' + it_behaves_like 'default allowlist' - describe 'custom whitelist' do + describe 'custom allowlist' do it_behaves_like 'XSS prevention' it_behaves_like 'sanitize link' - it 'customizes the whitelist only once' do + it 'customizes the allowlist only once' do instance = described_class.new('Foo') - control_count = instance.whitelist[:transformers].size + control_count = instance.allowlist[:transformers].size - 3.times { instance.whitelist } + 3.times { instance.allowlist } - expect(instance.whitelist[:transformers].size).to eq control_count + expect(instance.allowlist[:transformers].size).to eq control_count end - it 'customizes the whitelist only once for different instances' do + it 'customizes the allowlist only once for different instances' do instance1 = described_class.new('Foo1') instance2 = described_class.new('Foo2') - control_count = instance1.whitelist[:transformers].size + control_count = instance1.allowlist[:transformers].size - instance1.whitelist - instance2.whitelist + instance1.allowlist + instance2.allowlist - expect(instance1.whitelist[:transformers].size).to eq control_count - expect(instance2.whitelist[:transformers].size).to eq control_count + expect(instance1.allowlist[:transformers].size).to eq control_count + expect(instance2.allowlist[:transformers].size).to eq control_count end it 'sanitizes `class` attribute from all elements' do diff --git a/spec/lib/banzai/pipeline/description_pipeline_spec.rb b/spec/lib/banzai/pipeline/description_pipeline_spec.rb index 82d4f883e0d..be553433e9e 100644 --- a/spec/lib/banzai/pipeline/description_pipeline_spec.rb +++ b/spec/lib/banzai/pipeline/description_pipeline_spec.rb @@ -21,7 +21,7 @@ RSpec.describe Banzai::Pipeline::DescriptionPipeline do stub_commonmark_sourcepos_disabled end - it 'uses a limited whitelist' do + it 'uses a limited allowlist' do doc = parse('# Description') expect(doc.strip).to eq 'Description' diff --git a/spec/lib/banzai/pipeline/gfm_pipeline_spec.rb b/spec/lib/banzai/pipeline/gfm_pipeline_spec.rb index 247f4591632..31047b9494a 100644 --- a/spec/lib/banzai/pipeline/gfm_pipeline_spec.rb +++ b/spec/lib/banzai/pipeline/gfm_pipeline_spec.rb @@ -176,8 +176,8 @@ RSpec.describe Banzai::Pipeline::GfmPipeline do stub_asset_proxy_setting(enabled: true) stub_asset_proxy_setting(secret_key: 'shared-secret') stub_asset_proxy_setting(url: 'https://assets.example.com') - stub_asset_proxy_setting(whitelist: %W(gitlab.com *.mydomain.com #{Gitlab.config.gitlab.host})) - stub_asset_proxy_setting(domain_regexp: Banzai::Filter::AssetProxyFilter.compile_whitelist(Gitlab.config.asset_proxy.whitelist)) + stub_asset_proxy_setting(allowlist: %W(gitlab.com *.mydomain.com #{Gitlab.config.gitlab.host})) + stub_asset_proxy_setting(domain_regexp: Banzai::Filter::AssetProxyFilter.compile_allowlist(Gitlab.config.asset_proxy.allowlist)) end it 'replaces a lazy loaded img src' do diff --git a/spec/lib/gitlab/asset_proxy_spec.rb b/spec/lib/gitlab/asset_proxy_spec.rb index 73b101c0dd8..7d7952d5741 100644 --- a/spec/lib/gitlab/asset_proxy_spec.rb +++ b/spec/lib/gitlab/asset_proxy_spec.rb @@ -17,12 +17,12 @@ RSpec.describe Gitlab::AssetProxy do context 'when asset proxy is enabled' do before do - stub_asset_proxy_setting(whitelist: %w(gitlab.com *.mydomain.com)) + stub_asset_proxy_setting(allowlist: %w(gitlab.com *.mydomain.com)) stub_asset_proxy_setting( enabled: true, url: 'https://assets.example.com', secret_key: 'shared-secret', - domain_regexp: Banzai::Filter::AssetProxyFilter.compile_whitelist(Gitlab.config.asset_proxy.whitelist) + domain_regexp: Banzai::Filter::AssetProxyFilter.compile_allowlist(Gitlab.config.asset_proxy.allowlist) ) end diff --git a/spec/lib/gitlab/auth/auth_finders_spec.rb b/spec/lib/gitlab/auth/auth_finders_spec.rb index f927d5912bb..775f8f056b5 100644 --- a/spec/lib/gitlab/auth/auth_finders_spec.rb +++ b/spec/lib/gitlab/auth/auth_finders_spec.rb @@ -6,7 +6,8 @@ RSpec.describe Gitlab::Auth::AuthFinders do include described_class include HttpBasicAuthHelpers - let(:user) { create(:user) } + # Create the feed_token and static_object_token for the user + let_it_be(:user) { create(:user).tap(&:feed_token).tap(&:static_object_token) } let(:env) do { 'rack.input' => '' @@ -65,7 +66,7 @@ RSpec.describe Gitlab::Auth::AuthFinders do end describe '#find_user_from_bearer_token' do - let(:job) { create(:ci_build, user: user) } + let_it_be_with_reload(:job) { create(:ci_build, user: user) } subject { find_user_from_bearer_token } @@ -91,7 +92,7 @@ RSpec.describe Gitlab::Auth::AuthFinders do end context 'with a personal access token' do - let(:pat) { create(:personal_access_token, user: user) } + let_it_be(:pat) { create(:personal_access_token, user: user) } let(:token) { pat.token } before do @@ -148,7 +149,7 @@ RSpec.describe Gitlab::Auth::AuthFinders do end it 'returns nil if valid feed_token and disabled' do - allow(Gitlab::CurrentSettings).to receive(:disable_feed_token).and_return(true) + stub_application_setting(disable_feed_token: true) set_param(:feed_token, user.feed_token) expect(find_user_from_feed_token(:rss)).to be_nil @@ -166,7 +167,7 @@ RSpec.describe Gitlab::Auth::AuthFinders do end context 'when rss_token param is provided' do - it 'returns user if valid rssd_token' do + it 'returns user if valid rss_token' do set_param(:rss_token, user.feed_token) expect(find_user_from_feed_token(:rss)).to eq user @@ -347,7 +348,7 @@ RSpec.describe Gitlab::Auth::AuthFinders do end describe '#find_user_from_access_token' do - let(:personal_access_token) { create(:personal_access_token, user: user) } + let_it_be(:personal_access_token) { create(:personal_access_token, user: user) } before do set_header('SCRIPT_NAME', 'url.atom') @@ -386,7 +387,7 @@ RSpec.describe Gitlab::Auth::AuthFinders do end context 'when using a non-prefixed access token' do - let(:personal_access_token) { create(:personal_access_token, :no_prefix, user: user) } + let_it_be(:personal_access_token) { create(:personal_access_token, :no_prefix, user: user) } it 'returns user' do set_header('HTTP_AUTHORIZATION', "Bearer #{personal_access_token.token}") @@ -398,7 +399,7 @@ RSpec.describe Gitlab::Auth::AuthFinders do end describe '#find_user_from_web_access_token' do - let(:personal_access_token) { create(:personal_access_token, user: user) } + let_it_be_with_reload(:personal_access_token) { create(:personal_access_token, user: user) } before do set_header(described_class::PRIVATE_TOKEN_HEADER, personal_access_token.token) @@ -449,6 +450,22 @@ RSpec.describe Gitlab::Auth::AuthFinders do expect(find_user_from_web_access_token(:api)).to be_nil end + context 'when the token has read_api scope' do + before do + personal_access_token.update!(scopes: ['read_api']) + + set_header('SCRIPT_NAME', '/api/endpoint') + end + + it 'raises InsufficientScopeError by default' do + expect { find_user_from_web_access_token(:api) }.to raise_error(Gitlab::Auth::InsufficientScopeError) + end + + it 'finds the user when the read_api scope is passed' do + expect(find_user_from_web_access_token(:api, scopes: [:api, :read_api])).to eq(user) + end + end + context 'when relative_url_root is set' do before do stub_config_setting(relative_url_root: '/relative_root') @@ -464,7 +481,7 @@ RSpec.describe Gitlab::Auth::AuthFinders do end describe '#find_personal_access_token' do - let(:personal_access_token) { create(:personal_access_token, user: user) } + let_it_be(:personal_access_token) { create(:personal_access_token, user: user) } before do set_header('SCRIPT_NAME', 'url.atom') @@ -534,7 +551,7 @@ RSpec.describe Gitlab::Auth::AuthFinders do end context 'access token is valid' do - let(:personal_access_token) { create(:personal_access_token, user: user) } + let_it_be(:personal_access_token) { create(:personal_access_token, user: user) } let(:route_authentication_setting) { { basic_auth_personal_access_token: true } } it 'finds the token from basic auth' do @@ -555,7 +572,7 @@ RSpec.describe Gitlab::Auth::AuthFinders do end context 'route_setting is not set' do - let(:personal_access_token) { create(:personal_access_token, user: user) } + let_it_be(:personal_access_token) { create(:personal_access_token, user: user) } it 'returns nil' do auth_header_with(personal_access_token.token) @@ -565,7 +582,7 @@ RSpec.describe Gitlab::Auth::AuthFinders do end context 'route_setting is not correct' do - let(:personal_access_token) { create(:personal_access_token, user: user) } + let_it_be(:personal_access_token) { create(:personal_access_token, user: user) } let(:route_authentication_setting) { { basic_auth_personal_access_token: false } } it 'returns nil' do @@ -611,8 +628,9 @@ RSpec.describe Gitlab::Auth::AuthFinders do context 'with CI username' do let(:username) { ::Gitlab::Auth::CI_JOB_USER } - let(:user) { create(:user) } - let(:build) { create(:ci_build, user: user, status: :running) } + + let_it_be(:user) { create(:user) } + let_it_be(:build) { create(:ci_build, user: user, status: :running) } it 'returns nil without password' do set_basic_auth_header(username, nil) @@ -645,11 +663,11 @@ RSpec.describe Gitlab::Auth::AuthFinders do describe '#validate_access_token!' do subject { validate_access_token! } - let(:personal_access_token) { create(:personal_access_token, user: user) } + let_it_be_with_reload(:personal_access_token) { create(:personal_access_token, user: user) } context 'with a job token' do + let_it_be(:job) { create(:ci_build, user: user, status: :running) } let(:route_authentication_setting) { { job_token_allowed: true } } - let(:job) { create(:ci_build, user: user, status: :running) } before do env['HTTP_AUTHORIZATION'] = "Bearer #{job.token}" @@ -671,7 +689,7 @@ RSpec.describe Gitlab::Auth::AuthFinders do end it 'returns Gitlab::Auth::ExpiredError if token expired' do - personal_access_token.expires_at = 1.day.ago + personal_access_token.update!(expires_at: 1.day.ago) expect { validate_access_token! }.to raise_error(Gitlab::Auth::ExpiredError) end @@ -688,7 +706,7 @@ RSpec.describe Gitlab::Auth::AuthFinders do end context 'with impersonation token' do - let(:personal_access_token) { create(:personal_access_token, :impersonation, user: user) } + let_it_be(:personal_access_token) { create(:personal_access_token, :impersonation, user: user) } context 'when impersonation is disabled' do before do @@ -704,7 +722,7 @@ RSpec.describe Gitlab::Auth::AuthFinders do end describe '#find_user_from_job_token' do - let(:job) { create(:ci_build, user: user, status: :running) } + let_it_be(:job) { create(:ci_build, user: user, status: :running) } let(:route_authentication_setting) { { job_token_allowed: true } } subject { find_user_from_job_token } @@ -866,7 +884,7 @@ RSpec.describe Gitlab::Auth::AuthFinders do end describe '#find_runner_from_token' do - let(:runner) { create(:ci_runner) } + let_it_be(:runner) { create(:ci_runner) } context 'with API requests' do before do diff --git a/spec/lib/gitlab/auth/request_authenticator_spec.rb b/spec/lib/gitlab/auth/request_authenticator_spec.rb index ef6b1d72712..93e9cb06786 100644 --- a/spec/lib/gitlab/auth/request_authenticator_spec.rb +++ b/spec/lib/gitlab/auth/request_authenticator_spec.rb @@ -47,7 +47,10 @@ RSpec.describe Gitlab::Auth::RequestAuthenticator do let!(:job_token_user) { build(:user) } it 'returns access_token user first' do - allow_any_instance_of(described_class).to receive(:find_user_from_web_access_token).and_return(access_token_user) + allow_any_instance_of(described_class).to receive(:find_user_from_web_access_token) + .with(anything, scopes: [:api, :read_api]) + .and_return(access_token_user) + allow_any_instance_of(described_class).to receive(:find_user_from_feed_token).and_return(feed_token_user) expect(subject.find_sessionless_user(:api)).to eq access_token_user diff --git a/spec/lib/gitlab/ci/charts_spec.rb b/spec/lib/gitlab/ci/charts_spec.rb index cfc2019a89b..c7869383dc4 100644 --- a/spec/lib/gitlab/ci/charts_spec.rb +++ b/spec/lib/gitlab/ci/charts_spec.rb @@ -47,6 +47,10 @@ RSpec.describe Gitlab::Ci::Charts do subject { chart.to } + before do + create(:ci_empty_pipeline, project: project, duration: 120) + end + it 'includes the whole current day' do is_expected.to eq(Date.today.end_of_day) end @@ -58,6 +62,37 @@ RSpec.describe Gitlab::Ci::Charts do it 'uses %d %B as labels format' do expect(chart.labels).to include(chart.from.strftime('%d %B')) end + + it 'returns count of pipelines run each day in the current week' do + expect(chart.total).to contain_exactly(0, 0, 0, 0, 0, 0, 0, 1) + end + end + + context 'weekchart_non_utc' do + today = Date.today + end_of_today = Time.use_zone(Time.find_zone('Asia/Dubai')) { today.end_of_day } + + let(:project) { create(:project) } + let(:chart) do + allow(Date).to receive(:today).and_return(today) + allow(today).to receive(:end_of_day).and_return(end_of_today) + Gitlab::Ci::Charts::WeekChart.new(project) + end + + subject { chart.total } + + before do + create(:ci_empty_pipeline, project: project, duration: 120) + end + + it 'uses a non-utc time zone for range times' do + expect(chart.to.zone).to eq(end_of_today.zone) + expect(chart.from.zone).to eq(end_of_today.zone) + end + + it 'returns count of pipelines run each day in the current week' do + is_expected.to contain_exactly(0, 0, 0, 0, 0, 0, 0, 1) + end end context 'pipeline_times' do diff --git a/spec/requests/rack_attack_global_spec.rb b/spec/requests/rack_attack_global_spec.rb index 157fcac56fa..1d99f042c06 100644 --- a/spec/requests/rack_attack_global_spec.rb +++ b/spec/requests/rack_attack_global_spec.rb @@ -188,10 +188,10 @@ RSpec.describe 'Rack Attack global throttles' do end describe 'API requests authenticated with personal access token', :api do - let(:user) { create(:user) } - let(:token) { create(:personal_access_token, user: user) } - let(:other_user) { create(:user) } - let(:other_user_token) { create(:personal_access_token, user: other_user) } + let_it_be(:user) { create(:user) } + let_it_be(:token) { create(:personal_access_token, user: user) } + let_it_be(:other_user) { create(:user) } + let_it_be(:other_user_token) { create(:personal_access_token, user: other_user) } let(:throttle_setting_prefix) { 'throttle_authenticated_api' } let(:api_partial_url) { '/todos' } @@ -208,6 +208,41 @@ RSpec.describe 'Rack Attack global throttles' do it_behaves_like 'rate-limited token-authenticated requests' end + + context 'with the token in the OAuth headers' do + let(:request_args) { api_get_args_with_token_headers(api_partial_url, oauth_token_headers(token)) } + let(:other_user_request_args) { api_get_args_with_token_headers(api_partial_url, oauth_token_headers(other_user_token)) } + + it_behaves_like 'rate-limited token-authenticated requests' + end + + context 'with the token in basic auth' do + let(:request_args) { api_get_args_with_token_headers(api_partial_url, basic_auth_headers(user, token)) } + let(:other_user_request_args) { api_get_args_with_token_headers(api_partial_url, basic_auth_headers(other_user, other_user_token)) } + + it_behaves_like 'rate-limited token-authenticated requests' + end + + context 'with a read_api scope' do + before do + token.update!(scopes: ['read_api']) + other_user_token.update!(scopes: ['read_api']) + end + + context 'with the token in the headers' do + let(:request_args) { api_get_args_with_token_headers(api_partial_url, personal_access_token_headers(token)) } + let(:other_user_request_args) { api_get_args_with_token_headers(api_partial_url, personal_access_token_headers(other_user_token)) } + + it_behaves_like 'rate-limited token-authenticated requests' + end + + context 'with the token in the OAuth headers' do + let(:request_args) { api_get_args_with_token_headers(api_partial_url, oauth_token_headers(token)) } + let(:other_user_request_args) { api_get_args_with_token_headers(api_partial_url, oauth_token_headers(other_user_token)) } + + it_behaves_like 'rate-limited token-authenticated requests' + end + end end describe 'API requests authenticated with OAuth token', :api do @@ -235,6 +270,15 @@ RSpec.describe 'Rack Attack global throttles' do it_behaves_like 'rate-limited token-authenticated requests' end + + context 'with a read_api scope' do + let(:read_token) { Doorkeeper::AccessToken.create!(application_id: application.id, resource_owner_id: user.id, scopes: "read_api") } + let(:other_user_read_token) { Doorkeeper::AccessToken.create!(application_id: other_user_application.id, resource_owner_id: other_user.id, scopes: "read_api") } + let(:request_args) { api_get_args_with_token_headers(api_partial_url, oauth_token_headers(read_token)) } + let(:other_user_request_args) { api_get_args_with_token_headers(api_partial_url, oauth_token_headers(other_user_read_token)) } + + it_behaves_like 'rate-limited token-authenticated requests' + end end describe '"web" (non-API) requests authenticated with RSS token' do diff --git a/spec/support/helpers/rack_attack_spec_helpers.rb b/spec/support/helpers/rack_attack_spec_helpers.rb index d479420e87b..0f17b5b9137 100644 --- a/spec/support/helpers/rack_attack_spec_helpers.rb +++ b/spec/support/helpers/rack_attack_spec_helpers.rb @@ -21,6 +21,11 @@ module RackAttackSpecHelpers { 'AUTHORIZATION' => "Bearer #{oauth_access_token.token}" } end + def basic_auth_headers(user, personal_access_token) + encoded_login = ["#{user.username}:#{personal_access_token.token}"].pack('m0') + { 'AUTHORIZATION' => "Basic #{encoded_login}" } + end + def expect_rejection(&block) yield diff --git a/spec/support/shared_examples/lib/banzai/filters/sanitization_filter_shared_examples.rb b/spec/support/shared_examples/lib/banzai/filters/sanitization_filter_shared_examples.rb index 134e38833cf..b5c07f45d59 100644 --- a/spec/support/shared_examples/lib/banzai/filters/sanitization_filter_shared_examples.rb +++ b/spec/support/shared_examples/lib/banzai/filters/sanitization_filter_shared_examples.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true -RSpec.shared_examples 'default whitelist' do - it 'sanitizes tags that are not whitelisted' do +RSpec.shared_examples 'default allowlist' do + it 'sanitizes tags that are not allowed' do act = %q{<textarea>no inputs</textarea> and <blink>no blinks</blink>} exp = 'no inputs and no blinks' expect(filter(act).to_html).to eq exp diff --git a/yarn.lock b/yarn.lock index b77d5d4cb34..6eb8bc1ec73 100644 --- a/yarn.lock +++ b/yarn.lock @@ -12431,10 +12431,10 @@ vue-jest@4.0.0-rc.0: source-map "0.5.6" ts-jest "26.x" -vue-loader@^15.9.5: - version "15.9.5" - resolved "https://registry.yarnpkg.com/vue-loader/-/vue-loader-15.9.5.tgz#7a960dc420a3439deaacdda038fdcdbf7c432706" - integrity sha512-oeMOs2b5o5gRqkxfds10bCx6JeXYTwivRgbb8hzOrcThD2z1+GqEKE3EX9A2SGbsYDf4rXwRg6D5n1w0jO5SwA== +vue-loader@^15.9.6: + version "15.9.6" + resolved "https://registry.yarnpkg.com/vue-loader/-/vue-loader-15.9.6.tgz#f4bb9ae20c3a8370af3ecf09b8126d38ffdb6b8b" + integrity sha512-j0cqiLzwbeImIC6nVIby2o/ABAWhlppyL/m5oJ67R5MloP0hj/DtFgb0Zmq3J9CG7AJ+AXIvHVnJAPBvrLyuDg== dependencies: "@vue/component-compiler-utils" "^3.1.0" hash-sum "^1.0.2" |