Commit 08086ff5 authored by GitLab Bot's avatar GitLab Bot

Add latest changes from gitlab-org/gitlab@13-12-stable-ee

parent 8f3fbbf0
......@@ -344,7 +344,7 @@ db:migrate-from-previous-major-version:
- sed -i -e "s/gem 'grpc', '~> 1.24.0'/gem 'grpc', '~> 1.30.2'/" Gemfile # Update gRPC for Ruby 2.7
- sed -i -e "s/gem 'google-protobuf', '~> 3.8.0'/gem 'google-protobuf', '~> 3.12'/" Gemfile
- sed -i -e "s/gem 'nokogiri', '~> 1.10.5'/gem 'nokogiri', '~> 1.11.0'/" Gemfile
- sed -i -e "s/gem 'mimemagic', '~> 0.3.2'/gem 'ruby-magic', '~> 0.3.2'/" Gemfile
- sed -i -e "s/gem 'mimemagic', '~> 0.3.2'/gem 'ruby-magic', '~> 0.4.0'/" Gemfile
- run_timed_command "gem install bundler:1.17.3"
- run_timed_command "bundle update google-protobuf nokogiri grpc mimemagic bootsnap"
- run_timed_command "bundle install ${BUNDLE_INSTALL_FLAGS}"
......
......@@ -20,14 +20,18 @@ module Spam
created_at: DateTime.current,
author: owner_name,
author_email: owner_email,
referer: options[:referer]
referrer: options[:referer]
}
begin
is_spam, is_blatant = akismet_client.check(options[:ip_address], options[:user_agent], params)
is_spam || is_blatant
rescue ArgumentError => e
Gitlab::ErrorTracking.track_and_raise_for_dev_exception(e)
false
rescue StandardError => e
Gitlab::AppLogger.error("Unable to connect to Akismet: #{e}, skipping check")
Gitlab::ErrorTracking.track_exception(e)
Gitlab::AppLogger.error("Error during Akismet spam check, flagging as not spam: #{e}")
false
end
end
......
......@@ -17,7 +17,7 @@
= link_to _('Forgot your password?'), new_password_path(:user)
%div
- if captcha_enabled? || captcha_on_login_required?
= recaptcha_tags
= recaptcha_tags nonce: content_security_policy_nonce
.submit-container.move-submit-down
= f.submit _('Sign in'), class: 'gl-button btn btn-confirm', data: { qa_selector: 'sign_in_button' }
......@@ -11,7 +11,7 @@
.devise-errors
= render 'devise/shared/error_messages', resource: resource
- if Gitlab::CurrentSettings.invisible_captcha_enabled
= invisible_captcha
= invisible_captcha nonce: true
.name.form-row
.col.form-group
= f.label :first_name, _('First name'), for: 'new_user_first_name', class: 'label-bold'
......@@ -34,7 +34,7 @@
%p.gl-field-hint.text-secondary= s_('SignUp|Minimum length is %{minimum_password_length} characters.') % { minimum_password_length: @minimum_password_length }
%div
- if show_recaptcha_sign_up?
= recaptcha_tags
= recaptcha_tags nonce: content_security_policy_nonce
.submit-container
= f.submit button_text, class: 'btn gl-button btn-confirm', data: { qa_selector: 'new_user_register_button' }
= render 'devise/shared/terms_of_service_notice', button_text: button_text
......
......@@ -20,7 +20,7 @@
- if captcha_required?
.row.recaptcha
.col-sm-4
= recaptcha_tags
= recaptcha_tags nonce: content_security_policy_nonce
.row
.form-actions.col-sm-12
= f.submit _('Create group'), class: "btn gl-button btn-confirm"
......
%p
= _('Hi %{username}!') % { username: sanitize_name(@user.name) }
%p
= _('Your SSH keys with the following fingerprints has expired:')
= _('Your SSH keys with the following fingerprints have expired. Expired SSH keys will not be usable in future versions of GitLab:')
%table
%tbody
- @fingerprints.each do |fingerprint|
......
<%= _('Hi %{username}!') % { username: sanitize_name(@user.name) } %>
<%= _('Your SSH keys with the following fingerprints has expired:') %>
<%= _('Your SSH keys with the following fingerprints have expired. Expired SSH keys will not be usable in future versions of GitLab:') %>
<% @fingerprints.each do |fingerprint| %>
- <%= fingerprint %>
......
<%= _('Hi %{username}!') % { username: sanitize_name(@user.name) } %>
<%= _('Your SSH keys with the following fingerprints are scheduled to expire soon:') %>
<%= _('Your SSH keys with the following fingerprints are scheduled to expire soon. Expired SSH keys will not be usable in future versions of GitLab:') %>
<% @fingerprints.each do |fingerprint| %>
- <%= fingerprint %>
......
%p
= _('Hi %{username}!') % { username: sanitize_name(@user.name) }
%p
= _('Your SSH keys with the following fingerprints are scheduled to expire soon:')
= _('Your SSH keys with the following fingerprints are scheduled to expire soon. Expired SSH keys will not be usable in future versions of GitLab:')
%table
%tbody
- @fingerprints.each do |fingerprint|
......
......@@ -10,7 +10,7 @@
= hidden_field(resource_name, field, value: value)
= hidden_field_tag(:spam_log_id, spammable.spam_log.id)
-# The reCAPTCHA response value will be returned in the 'g-recaptcha-response' field
= recaptcha_tags script: script, callback: 'recaptchaDialogCallback' unless Rails.env.test?
= recaptcha_tags script: script, callback: 'recaptchaDialogCallback', nonce: content_security_policy_nonce unless Rails.env.test?
-# Fake the 'g-recaptcha-response' field in the test environment, so that the feature spec
-# can get to the (mocked) SpamVerdictService check.
= hidden_field_tag('g-recaptcha-response', 'abc123') if Rails.env.test?
......
---
name: remove_description_html_in_release_api
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/60380
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/329188
milestone: '13.12'
type: development
group: group::release
default_enabled: true
---
name: remove_description_html_in_release_api_override
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/60380
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/329188
milestone: '13.12'
type: development
group: group::release
default_enabled: false
......@@ -10,7 +10,8 @@ info: To determine the technical writer assigned to the Stage/Group associated w
> - Using this API you can manipulate GitLab [Release](../../user/project/releases/index.md) entries.
> - For manipulating links as a release asset, see [Release Links API](links.md).
> - Release Evidences were [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/26019) in GitLab 12.5.
> - `description_html` field was [removed](https://gitlab.com/gitlab-org/gitlab/-/issues/299447) in GitLab 13.12.
> - `description_html` became an opt-in field [with GitLab 13.12 for performance reasons](https://gitlab.com/gitlab-org/gitlab/-/issues/299447).
Please pass the `include_html_description` query string parameter if you need it.
## List Releases
......@@ -25,6 +26,7 @@ GET /projects/:id/releases
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](../README.md#namespaced-path-encoding). |
| `order_by` | string | no | The field to use as order. Either `released_at` (default) or `created_at`. |
| `sort` | string | no | The direction of the order. Either `desc` (default) for descending order or `asc` for ascending order. |
| `include_html_description` | boolean | no | If `true`, a response includes HTML rendered Markdown of the release description. |
Example request:
......@@ -228,6 +230,7 @@ GET /projects/:id/releases/:tag_name
| ------------- | -------------- | -------- | ----------------------------------------------------------------------------------- |
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](../README.md#namespaced-path-encoding). |
| `tag_name` | string | yes | The Git tag the release is associated with. |
| `include_html_description` | boolean | no | If `true`, a response includes HTML rendered Markdown of the release description. |
Example request:
......
......@@ -149,7 +149,7 @@ test-jdk11:
stage: test
image: maven:3.6.3-jdk-11
script:
- 'mvn $MAVEN_CLI_OPTS clean org.jacoco:jacoco-maven-plugin:prepare-agent test jacoco:report'
- mvn $MAVEN_CLI_OPTS clean org.jacoco:jacoco-maven-plugin:prepare-agent test jacoco:report
artifacts:
paths:
- target/site/jacoco/jacoco.xml
......@@ -161,10 +161,8 @@ coverage-jdk11:
stage: visualize
image: registry.gitlab.com/haynes/jacoco2cobertura:1.0.7
script:
# convert report from jacoco to cobertura, use relative project path
- 'python /opt/cover2cover.py target/site/jacoco/jacoco.xml src/main/java > target/site/cobertura.xml'
# read the <source></source> tag and prepend the path to every filename attribute
- 'python /opt/source2filename.py target/site/cobertura.xml'
# convert report from jacoco to cobertura, using relative project path
- python /opt/cover2cover.py target/site/jacoco/jacoco.xml $CI_PROJECT_DIR/src/main/java/ > target/site/cobertura.xml
needs: ["test-jdk11"]
dependencies:
- test-jdk11
......@@ -201,10 +199,8 @@ coverage-jdk11:
stage: visualize
image: registry.gitlab.com/haynes/jacoco2cobertura:1.0.7
script:
# convert report from jacoco to cobertura, use relative project path
- 'python /opt/cover2cover.py build/jacoco/jacoco.xml src/main/java > build/cobertura.xml'
# read the <source></source> tag and prepend the path to every filename attribute
- 'python /opt/source2filename.py build/cobertura.xml'
# convert report from jacoco to cobertura, using relative project path
- python /opt/cover2cover.py build/jacoco/jacoco.xml $CI_PROJECT_DIR/src/main/java/ > build/cobertura.xml
needs: ["test-jdk11"]
dependencies:
- test-jdk11
......
......@@ -8,7 +8,7 @@ module API
expose :name
expose :tag, as: :tag_name, if: ->(_, _) { can_download_code? }
expose :description
expose :description_html, unless: ->(_, _) { remove_description_html? } do |entity|
expose :description_html, if: -> (_, options) { options[:include_html_description] } do |entity|
MarkupHelper.markdown_field(entity, :description, current_user: options[:current_user])
end
expose :created_at
......@@ -45,11 +45,6 @@ module API
def can_read_milestone?
Ability.allowed?(options[:current_user], :read_milestone, object.project)
end
def remove_description_html?
::Feature.enabled?(:remove_description_html_in_release_api, object.project, default_enabled: :yaml) &&
::Feature.disabled?(:remove_description_html_in_release_api_override, object.project)
end
end
end
end
......@@ -29,6 +29,8 @@ module API
desc: 'Return releases ordered by `released_at` or `created_at`.'
optional :sort, type: String, values: %w[asc desc], default: 'desc',
desc: 'Return releases sorted in `asc` or `desc` order.'
optional :include_html_description, type: Boolean,
desc: 'If `true`, a response includes HTML rendered markdown of the release description.'
end
get ':id/releases' do
releases = ::ReleasesFinder.new(user_project, current_user, declared_params.slice(:order_by, :sort)).execute
......@@ -43,7 +45,8 @@ module API
# context is unnecessary here.
cache_context: -> (_) { "user:{#{current_user&.id}}" },
expires_in: 5.minutes,
current_user: current_user
current_user: current_user,
include_html_description: params[:include_html_description]
end
desc 'Get a single project release' do
......@@ -53,11 +56,13 @@ module API
end
params do
requires :tag_name, type: String, desc: 'The name of the tag', as: :tag
optional :include_html_description, type: Boolean,
desc: 'If `true`, a response includes HTML rendered markdown of the release description.'
end
get ':id/releases/:tag_name', requirements: RELEASE_ENDPOINT_REQUIREMENTS do
authorize_download_code!
present release, with: Entities::Release, current_user: current_user
present release, with: Entities::Release, current_user: current_user, include_html_description: params[:include_html_description]
end
desc 'Create a new release' do
......
......@@ -9,21 +9,20 @@ module Gitlab
def self.default_settings_hash
settings_hash = {
'enabled' => true,
'enabled' => Rails.env.development? || Rails.env.test?,
'report_only' => false,
'directives' => {
'default_src' => "'self'",
'base_uri' => "'self'",
'child_src' => "'none'",
'connect_src' => "'self'",
'font_src' => "'self'",
'form_action' => "'self' https: http:",
'frame_ancestors' => "'self'",
'frame_src' => "'self' https://www.recaptcha.net/ https://content.googleapis.com https://content-compute.googleapis.com https://content-cloudbilling.googleapis.com https://content-cloudresourcemanager.googleapis.com",
'frame_src' => "'self' https://www.google.com/recaptcha/ https://www.recaptcha.net/ https://content.googleapis.com https://content-compute.googleapis.com https://content-cloudbilling.googleapis.com https://content-cloudresourcemanager.googleapis.com",
'img_src' => "'self' data: blob: http: https:",
'manifest_src' => "'self'",
'media_src' => "'self'",
'script_src' => "'strict-dynamic' 'self' 'unsafe-inline' 'unsafe-eval' https://www.recaptcha.net https://apis.google.com",
'script_src' => "'strict-dynamic' 'self' 'unsafe-inline' 'unsafe-eval' https://www.google.com/recaptcha/ https://www.recaptcha.net https://apis.google.com",
'style_src' => "'self' 'unsafe-inline'",
'worker_src' => "'self'",
'object_src' => "'none'",
......@@ -31,6 +30,11 @@ module Gitlab
}
}
# frame-src was deprecated in CSP level 2 in favor of child-src
# CSP level 3 "undeprecated" frame-src and browsers fall back on child-src if it's missing
# However Safari seems to read child-src first so we'll just keep both equal
settings_hash['directives']['child_src'] = settings_hash['directives']['frame_src']
allow_webpack_dev_server(settings_hash) if Rails.env.development?
allow_cdn(settings_hash) if ENV['GITLAB_CDN_HOST'].present?
......
......@@ -37597,10 +37597,10 @@ msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
msgid "Your SSH keys with the following fingerprints are scheduled to expire soon:"
msgid "Your SSH keys with the following fingerprints are scheduled to expire soon. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
msgid "Your SSH keys with the following fingerprints has expired:"
msgid "Your SSH keys with the following fingerprints have expired. Expired SSH keys will not be usable in future versions of GitLab:"
msgstr ""
msgid "Your To-Do List"
......
......@@ -8,7 +8,8 @@ RSpec.describe API::Entities::Release do
let(:release) { create(:release, project: project) }
let(:evidence) { release.evidences.first }
let(:user) { create(:user) }
let(:entity) { described_class.new(release, current_user: user).as_json }
let(:entity) { described_class.new(release, current_user: user, include_html_description: include_html_description).as_json }
let(:include_html_description) { false }
before do
::Releases::CreateEvidenceService.new(release).execute
......@@ -58,10 +59,8 @@ RSpec.describe API::Entities::Release do
expect(description_html).to be_nil
end
context 'when remove_description_html_in_release_api feature flag is disabled' do
before do
stub_feature_flags(remove_description_html_in_release_api: false)
end
context 'when include_html_description option is true' do
let(:include_html_description) { true }
it 'renders special references if current user has access' do
project.add_reporter(user)
......@@ -77,18 +76,5 @@ RSpec.describe API::Entities::Release do
expect(description_html).not_to include(issue_title)
end
end
context 'when remove_description_html_in_release_api_override feature flag is enabled' do
before do
stub_feature_flags(remove_description_html_in_release_api_override: project)
end
it 'renders special references if current user has access' do
project.add_reporter(user)
expect(description_html).to include(issue_path)
expect(description_html).to include(issue_title)
end
end
end
end
......@@ -20,9 +20,9 @@ RSpec.describe Gitlab::ContentSecurityPolicy::ConfigLoader do
end
describe '.default_settings_hash' do
it 'returns defaults for all keys' do
settings = described_class.default_settings_hash
let(:settings) { described_class.default_settings_hash }
it 'returns defaults for all keys' do
expect(settings['enabled']).to be_truthy
expect(settings['report_only']).to be_falsey
......@@ -35,6 +35,17 @@ RSpec.describe Gitlab::ContentSecurityPolicy::ConfigLoader do
expect(directives.has_key?('report_uri')).to be_truthy
expect(directives['report_uri']).to be_nil
expect(directives['child_src']).to eq(directives['frame_src'])
end
context 'when in production' do
before do
allow(Rails).to receive(:env).and_return(ActiveSupport::StringInquirer.new('production'))
end
it 'is disabled' do
expect(settings['enabled']).to be_falsey
end
end
context 'when GITLAB_CDN_HOST is set' do
......@@ -43,10 +54,9 @@ RSpec.describe Gitlab::ContentSecurityPolicy::ConfigLoader do
end
it 'adds GITLAB_CDN_HOST to CSP' do
settings = described_class.default_settings_hash
directives = settings['directives']
expect(directives['script_src']).to eq("'strict-dynamic' 'self' 'unsafe-inline' 'unsafe-eval' https://www.recaptcha.net https://apis.google.com https://example.com")
expect(directives['script_src']).to eq("'strict-dynamic' 'self' 'unsafe-inline' 'unsafe-eval' https://www.google.com/recaptcha/ https://www.recaptcha.net https://apis.google.com https://example.com")
expect(directives['style_src']).to eq("'self' 'unsafe-inline' https://example.com")
end
end
......
......@@ -264,7 +264,7 @@ RSpec.describe Emails::Profile do
include_examples 'valid use case'
it_behaves_like 'has the correct subject', /Your SSH key has expired/
it_behaves_like 'has the correct body text', /Your SSH keys with the following fingerprints has expired/
it_behaves_like 'has the correct body text', /Your SSH keys with the following fingerprints have expired/
end
context 'when invalid' do
......
......@@ -50,6 +50,12 @@ RSpec.describe API::Releases do
expect(json_response.second['tag_name']).to eq(release_1.tag)
end
it 'does not include description_html' do
get api("/projects/#{project.id}/releases", maintainer)
expect(json_response.map { |h| h['description_html'] }).to contain_exactly(nil, nil)
end
RSpec.shared_examples 'release sorting' do |order_by|
subject { get api(url, access_level), params: { sort: sort, order_by: order_by } }
......@@ -107,6 +113,15 @@ RSpec.describe API::Releases do
expect(json_response.second['commit_path']).to eq("/#{release_1.project.full_path}/-/commit/#{release_1.commit.id}")
expect(json_response.second['tag_path']).to eq("/#{release_1.project.full_path}/-/tags/#{release_1.tag}")
end
context 'when include_html_description option is true' do
it 'includes description_html field' do
get api("/projects/#{project.id}/releases", maintainer), params: { include_html_description: true }
expect(json_response.map { |h| h['description_html'] })
.to contain_exactly(instance_of(String), instance_of(String))
end
end
end
it 'returns an upcoming_release status for a future release' do
......@@ -328,6 +343,12 @@ RSpec.describe API::Releases do
.to match_array(release.sources.map(&:url))
end
it 'does not include description_html' do
get api("/projects/#{project.id}/releases/v0.1", maintainer)
expect(json_response['description_html']).to eq(nil)
end
context 'with evidence' do
let!(:evidence) { create(:evidence, release: release) }
......@@ -403,6 +424,14 @@ RSpec.describe API::Releases do
end
end
context 'when include_html_description option is true' do
it 'includes description_html field' do
get api("/projects/#{project.id}/releases/v0.1", maintainer), params: { include_html_description: true }
expect(json_response['description_html']).to be_instance_of(String)
end
end
context 'when user is a guest' do
it 'responds 403 Forbidden' do
get api("/projects/#{project.id}/releases/v0.1", guest)
......
......@@ -4,12 +4,15 @@ require 'spec_helper'
RSpec.describe Spam::AkismetService do
let(:fake_akismet_client) { double(:akismet_client) }
let(:ip) { '1.2.3.4' }
let(:user_agent) { 'some user_agent' }
let(:referer) { 'some referer' }
let_it_be(:text) { "Would you like to buy some tinned meat product?" }
let_it_be(:spam_owner) { create(:user) }
subject do
options = { ip_address: '1.2.3.4', user_agent: 'some user_agent', referrer: 'some referrer' }
options = { ip_address: ip, user_agent: user_agent, referer: referer }
described_class.new(spam_owner.name, spam_owner.email, text, options)
end
......@@ -56,6 +59,21 @@ RSpec.describe Spam::AkismetService do
it_behaves_like 'no activity if Akismet is not enabled', :spam?, :check
context 'if Akismet is enabled' do
it 'correctly transforms options for the akismet client' do
expected_check_params = {
type: 'comment',
text: text,
created_at: anything,
author: spam_owner.name,
author_email: spam_owner.email,
# NOTE: The akismet_client needs the option to be named `:referrer`, not `:referer`
referrer: referer
}
expect(fake_akismet_client).to receive(:check).with(ip, user_agent, expected_check_params)
subject.spam?
end
context 'the text is spam' do
before do
allow(fake_akismet_client).to receive(:check).and_return([true, false])
......@@ -86,19 +104,31 @@ RSpec.describe Spam::AkismetService do
end
end
context 'if Akismet is not available' do
describe 'error handling' do
before do
allow(fake_akismet_client).to receive(:check).and_raise(StandardError.new("oh noes!"))
allow(fake_akismet_client).to receive(:check).and_raise(error)
end
specify do
expect(subject.spam?).to be_falsey
context 'StandardError other than ArgumentError is raised' do
let(:error) { Akismet::Error.new("Lovely spam! Wonderful spam!") }
specify do
expect(subject.spam?).to be_falsey
end
it 'logs an error' do
expect(Gitlab::AppLogger).to receive(:error).with(/Error during Akismet.*flagging as not spam.*Lovely spam/)
subject.spam?
end
end
it 'logs an error' do
expect(Gitlab::AppLogger).to receive(:error).with(/skipping check/)
context 'ArgumentError is raised in dev' do
let(:error) { ArgumentError }
subject.spam?
it 'raises original error' do
expect { subject.spam? }.to raise_error(error)
end
end
end
end
......
......@@ -286,9 +286,6 @@ RSpec.configure do |config|
# As we're ready to change `master` usages to `main`, let's enable it
stub_feature_flags(main_branch_over_master: false)
# Selectively disable by actor https://docs.gitlab.com/ee/development/feature_flags/#selectively-disable-by-actor
stub_feature_flags(remove_description_html_in_release_api_override: false)
# Disable issue respositioning to avoid heavy load on database when importing big projects.
# This is only turned on when app is handling heavy project imports.
# Can be removed when we find a better way to deal with the problem.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment