Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2021-01-04 21:10:19 +00:00
parent db3acec198
commit 9248363e3e
33 changed files with 291 additions and 130 deletions

View file

@ -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'

View file

@ -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

View file

@ -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

View file

@ -0,0 +1,5 @@
---
title: Index ci_pipelines on pipeline_schedule_id and id
merge_request: 50478
author:
type: performance

View file

@ -0,0 +1,5 @@
---
title: Fix LDAP override throws 404 when member has Minimal access
merge_request: 50680
author:
type: fixed

View file

@ -0,0 +1,5 @@
---
title: Fix empty pipeline analytics charts when time_zone is non-UTC
merge_request: 50760
author:
type: fixed

View file

@ -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

View file

@ -0,0 +1 @@
e845a6704ac92881926cca56bf7fb01c6252f1fe2b2d94fc9d6548144126d6a5

View file

@ -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);

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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 ||

View file

@ -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

View file

@ -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 ""

View file

@ -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",

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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'

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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"