summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
Diffstat (limited to 'app')
-rw-r--r--app/assets/javascripts/create_item_dropdown.js7
-rw-r--r--app/assets/javascripts/notebook/cells/output/html.vue3
-rw-r--r--app/controllers/jira_connect/users_controller.rb10
-rw-r--r--app/finders/users_finder.rb2
-rw-r--r--app/graphql/mutations/packages/destroy.rb2
-rw-r--r--app/graphql/mutations/packages/destroy_file.rb2
-rw-r--r--app/graphql/types/project_type.rb6
-rw-r--r--app/models/application_setting.rb1
-rw-r--r--app/models/concerns/integrations/enable_ssl_verification.rb32
-rw-r--r--app/models/concerns/integrations/has_web_hook.rb6
-rw-r--r--app/models/integrations/bamboo.rb3
-rw-r--r--app/models/integrations/buildkite.rb2
-rw-r--r--app/models/integrations/drone_ci.rb26
-rw-r--r--app/models/integrations/jenkins.rb1
-rw-r--r--app/models/integrations/jira.rb10
-rw-r--r--app/models/integrations/mock_ci.rb23
-rw-r--r--app/models/integrations/teamcity.rb18
-rw-r--r--app/models/packages/package.rb8
-rw-r--r--app/models/packages/package_file.rb1
-rw-r--r--app/models/system_note_metadata.rb2
-rw-r--r--app/models/user.rb19
-rw-r--r--app/services/concerns/protected_ref_name_sanitizer.rb12
-rw-r--r--app/services/packages/mark_package_files_for_destruction_service.rb26
-rw-r--r--app/services/packages/mark_package_for_destruction_service.rb (renamed from app/services/packages/destroy_package_service.rb)9
-rw-r--r--app/services/protected_branches/base_service.rb11
-rw-r--r--app/services/protected_branches/create_service.rb2
-rw-r--r--app/services/protected_branches/update_service.rb2
-rw-r--r--app/services/protected_tags/base_service.rb16
-rw-r--r--app/services/protected_tags/create_service.rb4
-rw-r--r--app/services/protected_tags/update_service.rb4
-rw-r--r--app/views/devise/confirmations/new.html.haml2
-rw-r--r--app/views/devise/passwords/new.html.haml2
-rw-r--r--app/views/groups/_import_group_from_another_instance_panel.html.haml1
-rw-r--r--app/workers/all_queues.yml9
-rw-r--r--app/workers/concerns/packages/cleanup_artifact_worker.rb16
-rw-r--r--app/workers/irker_worker.rb18
-rw-r--r--app/workers/packages/cleanup_package_file_worker.rb8
-rw-r--r--app/workers/packages/mark_package_files_for_destruction_worker.rb25
38 files changed, 257 insertions, 94 deletions
diff --git a/app/assets/javascripts/create_item_dropdown.js b/app/assets/javascripts/create_item_dropdown.js
index 1472adf458b..b39720c6094 100644
--- a/app/assets/javascripts/create_item_dropdown.js
+++ b/app/assets/javascripts/create_item_dropdown.js
@@ -1,4 +1,3 @@
-import { escape } from 'lodash';
import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
export default class CreateItemDropdown {
@@ -37,14 +36,14 @@ export default class CreateItemDropdown {
},
selectable: true,
toggleLabel(selected) {
- return selected && 'id' in selected ? escape(selected.title) : this.defaultToggleLabel;
+ return selected && 'id' in selected ? selected.title : this.defaultToggleLabel;
},
fieldName: this.fieldName,
text(item) {
- return escape(item.text);
+ return item.text;
},
id(item) {
- return escape(item.id);
+ return item.id;
},
onFilter: this.toggleCreateNewButton.bind(this),
clicked: (options) => {
diff --git a/app/assets/javascripts/notebook/cells/output/html.vue b/app/assets/javascripts/notebook/cells/output/html.vue
index ca02ee18dd1..2d1d8845e41 100644
--- a/app/assets/javascripts/notebook/cells/output/html.vue
+++ b/app/assets/javascripts/notebook/cells/output/html.vue
@@ -30,6 +30,9 @@ export default {
},
safeHtmlConfig: {
ADD_TAGS: ['use'], // to support icon SVGs
+ FORBID_TAGS: ['style'],
+ FORBID_ATTR: ['style'],
+ ALLOW_DATA_ATTR: false,
},
};
</script>
diff --git a/app/controllers/jira_connect/users_controller.rb b/app/controllers/jira_connect/users_controller.rb
index 569dc42fed3..a37c68de299 100644
--- a/app/controllers/jira_connect/users_controller.rb
+++ b/app/controllers/jira_connect/users_controller.rb
@@ -5,7 +5,17 @@ class JiraConnect::UsersController < ApplicationController
layout 'signup_onboarding'
+ before_action :verify_return_to_url, only: [:show]
+
def show
@jira_app_link = params.delete(:return_to)
end
+
+ private
+
+ def verify_return_to_url
+ return unless params[:return_to].present?
+
+ params.delete(:return_to) unless Integrations::Jira.valid_jira_cloud_url?(params[:return_to])
+ end
end
diff --git a/app/finders/users_finder.rb b/app/finders/users_finder.rb
index 8054ecbd502..2b4ce615090 100644
--- a/app/finders/users_finder.rb
+++ b/app/finders/users_finder.rb
@@ -74,7 +74,7 @@ class UsersFinder
def by_search(users)
return users unless params[:search].present?
- users.search(params[:search])
+ users.search(params[:search], with_private_emails: current_user&.admin?)
end
def by_blocked(users)
diff --git a/app/graphql/mutations/packages/destroy.rb b/app/graphql/mutations/packages/destroy.rb
index 979a54da6bd..81fa53fc116 100644
--- a/app/graphql/mutations/packages/destroy.rb
+++ b/app/graphql/mutations/packages/destroy.rb
@@ -15,7 +15,7 @@ module Mutations
def resolve(id:)
package = authorized_find!(id: id)
- result = ::Packages::DestroyPackageService.new(container: package, current_user: current_user).execute
+ result = ::Packages::MarkPackageForDestructionService.new(container: package, current_user: current_user).execute
errors = result.error? ? Array.wrap(result[:message]) : []
diff --git a/app/graphql/mutations/packages/destroy_file.rb b/app/graphql/mutations/packages/destroy_file.rb
index 35a486666d5..4aa33b3504c 100644
--- a/app/graphql/mutations/packages/destroy_file.rb
+++ b/app/graphql/mutations/packages/destroy_file.rb
@@ -15,7 +15,7 @@ module Mutations
def resolve(id:)
package_file = authorized_find!(id: id)
- if package_file.destroy
+ if package_file.update(status: :pending_destruction)
return { errors: [] }
end
diff --git a/app/graphql/types/project_type.rb b/app/graphql/types/project_type.rb
index f4067552f55..d49244f6b65 100644
--- a/app/graphql/types/project_type.rb
+++ b/app/graphql/types/project_type.rb
@@ -438,6 +438,12 @@ module Types
::Security::CiConfiguration::SastParserService.new(object).configuration
end
+ def service_desk_address
+ return unless Ability.allowed?(current_user, :admin_issue, project)
+
+ object.service_desk_address
+ end
+
def tag_list
object.topic_list
end
diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb
index b69c0199c70..3c9f7c4dd7f 100644
--- a/app/models/application_setting.rb
+++ b/app/models/application_setting.rb
@@ -10,6 +10,7 @@ class ApplicationSetting < ApplicationRecord
ignore_columns %i[elasticsearch_shards elasticsearch_replicas], remove_with: '14.4', remove_after: '2021-09-22'
ignore_columns %i[static_objects_external_storage_auth_token], remove_with: '14.9', remove_after: '2022-03-22'
+ ignore_column %i[max_package_files_for_package_destruction], remove_with: '14.9', remove_after: '2022-03-22'
INSTANCE_REVIEW_MIN_USERS = 50
GRAFANA_URL_ERROR_MESSAGE = 'Please check your Grafana URL setting in ' \
diff --git a/app/models/concerns/integrations/enable_ssl_verification.rb b/app/models/concerns/integrations/enable_ssl_verification.rb
new file mode 100644
index 00000000000..11dc8a76a2b
--- /dev/null
+++ b/app/models/concerns/integrations/enable_ssl_verification.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+module Integrations
+ module EnableSslVerification
+ extend ActiveSupport::Concern
+
+ prepended do
+ boolean_accessor :enable_ssl_verification
+ end
+
+ def initialize_properties
+ super
+
+ self.enable_ssl_verification = true if new_record? && enable_ssl_verification.nil?
+ end
+
+ def fields
+ super.tap do |fields|
+ url_index = fields.index { |field| field[:name].ends_with?('_url') }
+ insert_index = url_index ? url_index + 1 : -1
+
+ fields.insert(insert_index, {
+ type: 'checkbox',
+ name: 'enable_ssl_verification',
+ title: s_('Integrations|SSL verification'),
+ checkbox_label: s_('Integrations|Enable SSL verification'),
+ help: s_('Integrations|Clear if using a self-signed certificate.')
+ })
+ end
+ end
+ end
+end
diff --git a/app/models/concerns/integrations/has_web_hook.rb b/app/models/concerns/integrations/has_web_hook.rb
index dabe7152b18..bc28c32695c 100644
--- a/app/models/concerns/integrations/has_web_hook.rb
+++ b/app/models/concerns/integrations/has_web_hook.rb
@@ -15,7 +15,11 @@ module Integrations
# Return whether the webhook should use SSL verification.
def hook_ssl_verification
- true
+ if respond_to?(:enable_ssl_verification)
+ enable_ssl_verification
+ else
+ true
+ end
end
# Create or update the webhook, raising an exception if it cannot be saved.
diff --git a/app/models/integrations/bamboo.rb b/app/models/integrations/bamboo.rb
index 0774b84b69f..57767c63cf4 100644
--- a/app/models/integrations/bamboo.rb
+++ b/app/models/integrations/bamboo.rb
@@ -4,6 +4,7 @@ module Integrations
class Bamboo < BaseCi
include ActionView::Helpers::UrlHelper
include ReactivelyCached
+ prepend EnableSslVerification
prop_accessor :bamboo_url, :build_key, :username, :password
@@ -162,7 +163,7 @@ module Integrations
end
def build_get_params(query_params)
- params = { verify: false, query: query_params }
+ params = { verify: enable_ssl_verification, query: query_params }
return params if username.blank? && password.blank?
query_params[:os_authType] = 'basic'
diff --git a/app/models/integrations/buildkite.rb b/app/models/integrations/buildkite.rb
index 9fad3a42647..90593d78a5d 100644
--- a/app/models/integrations/buildkite.rb
+++ b/app/models/integrations/buildkite.rb
@@ -137,7 +137,7 @@ module Integrations
end
def request_options
- { verify: false, extra_log_info: { project_id: project_id } }
+ { extra_log_info: { project_id: project_id } }
end
end
end
diff --git a/app/models/integrations/drone_ci.rb b/app/models/integrations/drone_ci.rb
index 856d14c022d..3c18e5d8732 100644
--- a/app/models/integrations/drone_ci.rb
+++ b/app/models/integrations/drone_ci.rb
@@ -5,10 +5,12 @@ module Integrations
include HasWebHook
include PushDataValidations
include ReactivelyCached
+ prepend EnableSslVerification
extend Gitlab::Utils::Override
+ DRONE_SAAS_HOSTNAME = 'cloud.drone.io'
+
prop_accessor :drone_url, :token
- boolean_accessor :enable_ssl_verification
validates :drone_url, presence: true, public_url: true, if: :activated?
validates :token, presence: true, if: :activated?
@@ -95,8 +97,7 @@ module Integrations
def fields
[
{ type: 'text', name: 'token', help: s_('ProjectService|Token for the Drone project.'), required: true },
- { type: 'text', name: 'drone_url', title: s_('ProjectService|Drone server URL'), placeholder: 'http://drone.example.com', required: true },
- { type: 'checkbox', name: 'enable_ssl_verification', title: "Enable SSL verification" }
+ { type: 'text', name: 'drone_url', title: s_('ProjectService|Drone server URL'), placeholder: 'http://drone.example.com', required: true }
]
end
@@ -105,15 +106,24 @@ module Integrations
[drone_url, "/hook", "?owner=#{project.namespace.full_path}", "&name=#{project.path}", "&access_token=#{token}"].join
end
- override :hook_ssl_verification
- def hook_ssl_verification
- !!enable_ssl_verification
- end
-
override :update_web_hook!
def update_web_hook!
# If using a service template, project may not be available
super if project
end
+
+ def enable_ssl_verification
+ original_value = Gitlab::Utils.to_boolean(properties['enable_ssl_verification'])
+ original_value.nil? ? (new_record? || url_is_saas?) : original_value
+ end
+
+ private
+
+ def url_is_saas?
+ parsed_url = Addressable::URI.parse(drone_url)
+ parsed_url&.scheme == 'https' && parsed_url.hostname == DRONE_SAAS_HOSTNAME
+ rescue Addressable::URI::InvalidURIError
+ false
+ end
end
end
diff --git a/app/models/integrations/jenkins.rb b/app/models/integrations/jenkins.rb
index e5c1d5ad0d7..5ea92170c26 100644
--- a/app/models/integrations/jenkins.rb
+++ b/app/models/integrations/jenkins.rb
@@ -4,6 +4,7 @@ module Integrations
class Jenkins < BaseCi
include HasWebHook
include ActionView::Helpers::UrlHelper
+ prepend EnableSslVerification
extend Gitlab::Utils::Override
prop_accessor :jenkins_url, :project_name, :username, :password
diff --git a/app/models/integrations/jira.rb b/app/models/integrations/jira.rb
index 816f5cbe177..966ad07afad 100644
--- a/app/models/integrations/jira.rb
+++ b/app/models/integrations/jira.rb
@@ -56,6 +56,12 @@ module Integrations
@reference_pattern ||= /(?<issue>\b#{Gitlab::Regex.jira_issue_key_regex})/
end
+ def self.valid_jira_cloud_url?(url)
+ return false unless url.present?
+
+ !!URI(url).hostname&.end_with?(JIRA_CLOUD_HOST)
+ end
+
def initialize_properties
{}
end
@@ -565,7 +571,7 @@ module Integrations
end
def jira_cloud?
- server_info['deploymentType'] == 'Cloud' || URI(client_url).hostname.end_with?(JIRA_CLOUD_HOST)
+ server_info['deploymentType'] == 'Cloud' || self.class.valid_jira_cloud_url?(client_url)
end
def set_deployment_type_from_url
@@ -578,7 +584,7 @@ module Integrations
# we can only assume it's either Cloud or Server
# based on the URL being *.atlassian.net
- if URI(client_url).hostname.end_with?(JIRA_CLOUD_HOST)
+ if self.class.valid_jira_cloud_url?(client_url)
data_fields.deployment_cloud!
else
data_fields.deployment_server!
diff --git a/app/models/integrations/mock_ci.rb b/app/models/integrations/mock_ci.rb
index 7359be83d4f..568fb609a44 100644
--- a/app/models/integrations/mock_ci.rb
+++ b/app/models/integrations/mock_ci.rb
@@ -3,6 +3,8 @@
# For an example companion mocking service, see https://gitlab.com/gitlab-org/gitlab-mock-ci-service
module Integrations
class MockCi < BaseCi
+ prepend EnableSslVerification
+
ALLOWED_STATES = %w[failed canceled running pending success success-with-warnings skipped not_found].freeze
prop_accessor :mock_service_url
@@ -55,7 +57,7 @@ module Integrations
# # => 'running'
#
def commit_status(sha, ref)
- response = Gitlab::HTTP.get(commit_status_path(sha), verify: false, use_read_total_timeout: true)
+ response = Gitlab::HTTP.get(commit_status_path(sha), verify: enable_ssl_verification, use_read_total_timeout: true)
read_commit_status(response)
rescue Errno::ECONNREFUSED
:error
@@ -68,19 +70,16 @@ module Integrations
end
def read_commit_status(response)
- return :error unless response.code == 200 || response.code == 404
-
- status = if response.code == 404
- 'pending'
- else
- response['status']
- end
+ return :pending if response.code == 404
+ return :error unless response.code == 200
- if status.present? && ALLOWED_STATES.include?(status)
- status
- else
- :error
+ begin
+ status = Gitlab::Json.parse(response.body).try(:fetch, 'status', nil)
+ return status if ALLOWED_STATES.include?(status)
+ rescue JSON::ParserError
end
+
+ :error
end
def testable?
diff --git a/app/models/integrations/teamcity.rb b/app/models/integrations/teamcity.rb
index 008b591c304..f0f83f118d7 100644
--- a/app/models/integrations/teamcity.rb
+++ b/app/models/integrations/teamcity.rb
@@ -4,6 +4,9 @@ module Integrations
class Teamcity < BaseCi
include PushDataValidations
include ReactivelyCached
+ prepend EnableSslVerification
+
+ TEAMCITY_SAAS_HOSTNAME = /\A[^\.]+\.teamcity\.com\z/i.freeze
prop_accessor :teamcity_url, :build_type, :username, :password
@@ -104,8 +107,20 @@ module Integrations
end
end
+ def enable_ssl_verification
+ original_value = Gitlab::Utils.to_boolean(properties['enable_ssl_verification'])
+ original_value.nil? ? (new_record? || url_is_saas?) : original_value
+ end
+
private
+ def url_is_saas?
+ parsed_url = Addressable::URI.parse(teamcity_url)
+ parsed_url&.scheme == 'https' && parsed_url.hostname.match?(TEAMCITY_SAAS_HOSTNAME)
+ rescue Addressable::URI::InvalidURIError
+ false
+ end
+
def execute_push(data)
branch = Gitlab::Git.ref_name(data[:ref])
post_to_build_queue(data, branch) if push_valid?(data)
@@ -155,7 +170,7 @@ module Integrations
end
def get_path(path)
- Gitlab::HTTP.try_get(build_url(path), verify: false, basic_auth: basic_auth, extra_log_info: { project_id: project_id }, use_read_total_timeout: true)
+ Gitlab::HTTP.try_get(build_url(path), verify: enable_ssl_verification, basic_auth: basic_auth, extra_log_info: { project_id: project_id }, use_read_total_timeout: true)
end
def post_to_build_queue(data, branch)
@@ -165,6 +180,7 @@ module Integrations
"<buildType id=#{build_type.encode(xml: :attr)}/>"\
'</build>',
headers: { 'Content-type' => 'application/xml' },
+ verify: enable_ssl_verification,
basic_auth: basic_auth,
use_read_total_timeout: true
)
diff --git a/app/models/packages/package.rb b/app/models/packages/package.rb
index 52dd0aba43b..1b2c3e25283 100644
--- a/app/models/packages/package.rb
+++ b/app/models/packages/package.rb
@@ -25,7 +25,7 @@ class Packages::Package < ApplicationRecord
terraform_module: 12
}
- enum status: { default: 0, hidden: 1, processing: 2, error: 3 }
+ enum status: { default: 0, hidden: 1, processing: 2, error: 3, pending_destruction: 4 }
belongs_to :project
belongs_to :creator, class_name: 'User'
@@ -304,6 +304,12 @@ class Packages::Package < ApplicationRecord
build_infos.find_or_create_by!(pipeline: build.pipeline)
end
+ def mark_package_files_for_destruction
+ return unless pending_destruction?
+
+ ::Packages::MarkPackageFilesForDestructionWorker.perform_async(id)
+ end
+
private
def composer_tag_version?
diff --git a/app/models/packages/package_file.rb b/app/models/packages/package_file.rb
index 072ff4a3a5f..190081c4e8e 100644
--- a/app/models/packages/package_file.rb
+++ b/app/models/packages/package_file.rb
@@ -1,5 +1,6 @@
# frozen_string_literal: true
class Packages::PackageFile < ApplicationRecord
+ include EachBatch
include UpdateProjectStatistics
include FileStoreMounter
include Packages::Installable
diff --git a/app/models/system_note_metadata.rb b/app/models/system_note_metadata.rb
index 7b13109dbc4..a3c9db90b5d 100644
--- a/app/models/system_note_metadata.rb
+++ b/app/models/system_note_metadata.rb
@@ -10,7 +10,7 @@ class SystemNoteMetadata < ApplicationRecord
# in the same project (i.e. with the same permissions)
TYPES_WITH_CROSS_REFERENCES = %w[
commit cross_reference
- close duplicate
+ closed duplicate
moved merge
label milestone
relate unrelate
diff --git a/app/models/user.rb b/app/models/user.rb
index a587723053f..1d452fc2e50 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -648,6 +648,7 @@ class User < ApplicationRecord
# This method uses ILIKE on PostgreSQL.
#
# query - The search query as a String
+ # with_private_emails - include private emails in search
#
# Returns an ActiveRecord::Relation.
def search(query, **options)
@@ -660,14 +661,16 @@ class User < ApplicationRecord
CASE
WHEN users.name = :query THEN 0
WHEN users.username = :query THEN 1
- WHEN users.email = :query THEN 2
+ WHEN users.public_email = :query THEN 2
ELSE 3
END
SQL
sanitized_order_sql = Arel.sql(sanitize_sql_array([order, query: query]))
- search_with_secondary_emails(query).reorder(sanitized_order_sql, :name)
+ scope = options[:with_private_emails] ? search_with_secondary_emails(query) : search_with_public_emails(query)
+
+ scope.reorder(sanitized_order_sql, :name)
end
# Limits the result set to users _not_ in the given query/list of IDs.
@@ -682,6 +685,18 @@ class User < ApplicationRecord
reorder(:name)
end
+ def search_with_public_emails(query)
+ return none if query.blank?
+
+ query = query.downcase
+
+ where(
+ fuzzy_arel_match(:name, query, use_minimum_char_limit: user_search_minimum_char_limit)
+ .or(fuzzy_arel_match(:username, query, use_minimum_char_limit: user_search_minimum_char_limit))
+ .or(arel_table[:public_email].eq(query))
+ )
+ end
+
def search_without_secondary_emails(query)
return none if query.blank?
diff --git a/app/services/concerns/protected_ref_name_sanitizer.rb b/app/services/concerns/protected_ref_name_sanitizer.rb
deleted file mode 100644
index 3966c410fec..00000000000
--- a/app/services/concerns/protected_ref_name_sanitizer.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-# frozen_string_literal: true
-
-module ProtectedRefNameSanitizer
- def sanitize_name(name)
- name = CGI.unescapeHTML(name)
- name = Sanitize.fragment(name)
-
- # Sanitize.fragment escapes HTML chars, so unescape again to allow names
- # like `feature->master`
- CGI.unescapeHTML(name)
- end
-end
diff --git a/app/services/packages/mark_package_files_for_destruction_service.rb b/app/services/packages/mark_package_files_for_destruction_service.rb
new file mode 100644
index 00000000000..3672b44b409
--- /dev/null
+++ b/app/services/packages/mark_package_files_for_destruction_service.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+module Packages
+ # WARNING: ensure that permissions are verified before using this service.
+ class MarkPackageFilesForDestructionService
+ BATCH_SIZE = 500
+
+ def initialize(package_files)
+ @package_files = package_files
+ end
+
+ def execute
+ @package_files.each_batch(of: BATCH_SIZE) do |batched_package_files|
+ batched_package_files.update_all(status: :pending_destruction)
+ end
+
+ service_response_success('Package files are now pending destruction')
+ end
+
+ private
+
+ def service_response_success(message)
+ ServiceResponse.success(message: message)
+ end
+ end
+end
diff --git a/app/services/packages/destroy_package_service.rb b/app/services/packages/mark_package_for_destruction_service.rb
index 697f1fa3ac8..3417febe79a 100644
--- a/app/services/packages/destroy_package_service.rb
+++ b/app/services/packages/mark_package_for_destruction_service.rb
@@ -1,19 +1,20 @@
# frozen_string_literal: true
module Packages
- class DestroyPackageService < BaseContainerService
+ class MarkPackageForDestructionService < BaseContainerService
alias_method :package, :container
def execute
return service_response_error("You don't have access to this package", 403) unless user_can_delete_package?
- package.destroy!
+ package.pending_destruction!
+ package.mark_package_files_for_destruction
package.sync_maven_metadata(current_user)
- service_response_success('Package was successfully deleted')
+ service_response_success('Package was successfully marked as pending destruction')
rescue StandardError
- service_response_error('Failed to remove the package', 400)
+ service_response_error('Failed to mark the package as pending destruction', 400)
end
private
diff --git a/app/services/protected_branches/base_service.rb b/app/services/protected_branches/base_service.rb
index 1ab3ccfcaae..f48e02ab4b5 100644
--- a/app/services/protected_branches/base_service.rb
+++ b/app/services/protected_branches/base_service.rb
@@ -2,8 +2,6 @@
module ProtectedBranches
class BaseService < ::BaseService
- include ProtectedRefNameSanitizer
-
# current_user - The user that performs the action
# params - A hash of parameters
def initialize(project, current_user = nil, params = {})
@@ -15,14 +13,5 @@ module ProtectedBranches
def after_execute(*)
# overridden in EE::ProtectedBranches module
end
-
- private
-
- def filtered_params
- return unless params
-
- params[:name] = sanitize_name(params[:name]) if params[:name].present?
- params
- end
end
end
diff --git a/app/services/protected_branches/create_service.rb b/app/services/protected_branches/create_service.rb
index ea494dd4426..dada449989a 100644
--- a/app/services/protected_branches/create_service.rb
+++ b/app/services/protected_branches/create_service.rb
@@ -21,7 +21,7 @@ module ProtectedBranches
end
def protected_branch
- @protected_branch ||= project.protected_branches.new(filtered_params)
+ @protected_branch ||= project.protected_branches.new(params)
end
end
end
diff --git a/app/services/protected_branches/update_service.rb b/app/services/protected_branches/update_service.rb
index 40e9a286af9..1e70f2d9793 100644
--- a/app/services/protected_branches/update_service.rb
+++ b/app/services/protected_branches/update_service.rb
@@ -8,7 +8,7 @@ module ProtectedBranches
old_merge_access_levels = protected_branch.merge_access_levels.map(&:clone)
old_push_access_levels = protected_branch.push_access_levels.map(&:clone)
- if protected_branch.update(filtered_params)
+ if protected_branch.update(params)
after_execute(protected_branch: protected_branch, old_merge_access_levels: old_merge_access_levels, old_push_access_levels: old_push_access_levels)
end
diff --git a/app/services/protected_tags/base_service.rb b/app/services/protected_tags/base_service.rb
deleted file mode 100644
index e0181815f0f..00000000000
--- a/app/services/protected_tags/base_service.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-# frozen_string_literal: true
-
-module ProtectedTags
- class BaseService < ::BaseService
- include ProtectedRefNameSanitizer
-
- private
-
- def filtered_params
- return unless params
-
- params[:name] = sanitize_name(params[:name]) if params[:name].present?
- params
- end
- end
-end
diff --git a/app/services/protected_tags/create_service.rb b/app/services/protected_tags/create_service.rb
index 7d2b583a295..65303f21a4a 100644
--- a/app/services/protected_tags/create_service.rb
+++ b/app/services/protected_tags/create_service.rb
@@ -1,13 +1,13 @@
# frozen_string_literal: true
module ProtectedTags
- class CreateService < ProtectedTags::BaseService
+ class CreateService < ::BaseService
attr_reader :protected_tag
def execute
raise Gitlab::Access::AccessDeniedError unless can?(current_user, :admin_project, project)
- project.protected_tags.create(filtered_params)
+ project.protected_tags.create(params)
end
end
end
diff --git a/app/services/protected_tags/update_service.rb b/app/services/protected_tags/update_service.rb
index e337ec39898..283aa8882c5 100644
--- a/app/services/protected_tags/update_service.rb
+++ b/app/services/protected_tags/update_service.rb
@@ -1,11 +1,11 @@
# frozen_string_literal: true
module ProtectedTags
- class UpdateService < ProtectedTags::BaseService
+ class UpdateService < ::BaseService
def execute(protected_tag)
raise Gitlab::Access::AccessDeniedError unless can?(current_user, :admin_project, project)
- protected_tag.update(filtered_params)
+ protected_tag.update(params)
protected_tag
end
end
diff --git a/app/views/devise/confirmations/new.html.haml b/app/views/devise/confirmations/new.html.haml
index eee223ff63c..2ae950f3b0d 100644
--- a/app/views/devise/confirmations/new.html.haml
+++ b/app/views/devise/confirmations/new.html.haml
@@ -6,7 +6,7 @@
= render "devise/shared/error_messages", resource: resource
.form-group
= f.label :email
- = f.email_field :email, class: "form-control gl-form-input", required: true, title: _('Please provide a valid email address.'), value: nil
+ = f.email_field :email, class: "form-control gl-form-input", required: true, autocomplete: 'off', title: _('Please provide a valid email address.'), value: nil
%div
- if recaptcha_enabled?
diff --git a/app/views/devise/passwords/new.html.haml b/app/views/devise/passwords/new.html.haml
index 7bbde4a39c7..d5372862128 100644
--- a/app/views/devise/passwords/new.html.haml
+++ b/app/views/devise/passwords/new.html.haml
@@ -5,7 +5,7 @@
= render "devise/shared/error_messages", resource: resource
.form-group
= f.label :email
- = f.email_field :email, class: "form-control gl-form-input", required: true, value: params[:user_email], autofocus: true, title: _('Please provide a valid email address.')
+ = f.email_field :email, class: "form-control gl-form-input", required: true, autocomplete: 'off', value: params[:user_email], autofocus: true, title: _('Please provide a valid email address.')
.form-text.text-muted
= _('Requires your primary GitLab email address.')
diff --git a/app/views/groups/_import_group_from_another_instance_panel.html.haml b/app/views/groups/_import_group_from_another_instance_panel.html.haml
index 06a86c2465f..3b079ea00b7 100644
--- a/app/views/groups/_import_group_from_another_instance_panel.html.haml
+++ b/app/views/groups/_import_group_from_another_instance_panel.html.haml
@@ -26,6 +26,7 @@
= s_('GroupsNew|Navigate to user settings to find your %{link_start}personal access token%{link_end}.').html_safe % { link_start: pat_link_start, link_end: '</a>'.html_safe }
= f.text_field :bulk_import_gitlab_access_token, placeholder: s_('GroupsNew|e.g. h8d3f016698e...'), class: 'gl-form-input gl-mt-3 col-xs-12 col-sm-8',
required: true,
+ autocomplete: 'off',
title: s_('GroupsNew|Please fill in your personal access token.'),
id: 'import_gitlab_token',
data: { qa_selector: 'import_gitlab_token' }
diff --git a/app/workers/all_queues.yml b/app/workers/all_queues.yml
index 14fa6599073..239b66bdeb0 100644
--- a/app/workers/all_queues.yml
+++ b/app/workers/all_queues.yml
@@ -1384,6 +1384,15 @@
:weight: 1
:idempotent: true
:tags: []
+- :name: package_cleanup:packages_mark_package_files_for_destruction
+ :worker_name: Packages::MarkPackageFilesForDestructionWorker
+ :feature_category: :package_registry
+ :has_external_dependencies:
+ :urgency: :low
+ :resource_boundary: :unknown
+ :weight: 1
+ :idempotent: true
+ :tags: []
- :name: package_repositories:packages_debian_generate_distribution
:worker_name: Packages::Debian::GenerateDistributionWorker
:feature_category: :package_registry
diff --git a/app/workers/concerns/packages/cleanup_artifact_worker.rb b/app/workers/concerns/packages/cleanup_artifact_worker.rb
index db6c7330ea3..d4ad023b4a8 100644
--- a/app/workers/concerns/packages/cleanup_artifact_worker.rb
+++ b/app/workers/concerns/packages/cleanup_artifact_worker.rb
@@ -9,11 +9,15 @@ module Packages
def perform_work
return unless artifact
- log_metadata(artifact)
+ artifact.transaction do
+ log_metadata(artifact)
- artifact.destroy!
- rescue StandardError
- artifact&.error!
+ artifact.destroy!
+ rescue StandardError
+ artifact&.error!
+ end
+
+ after_destroy
end
def remaining_work_count
@@ -34,6 +38,10 @@ module Packages
raise NotImplementedError
end
+ def after_destroy
+ # no op
+ end
+
def artifact
strong_memoize(:artifact) do
model.transaction do
diff --git a/app/workers/irker_worker.rb b/app/workers/irker_worker.rb
index 3097a9fbc03..4f51bb69b8c 100644
--- a/app/workers/irker_worker.rb
+++ b/app/workers/irker_worker.rb
@@ -2,6 +2,7 @@
require 'json'
require 'socket'
+require 'resolv'
class IrkerWorker # rubocop:disable Scalability/IdempotentWorker
include ApplicationWorker
@@ -43,9 +44,18 @@ class IrkerWorker # rubocop:disable Scalability/IdempotentWorker
private
def start_connection(irker_server, irker_port)
+ ip_address = Resolv.getaddress(irker_server)
+ # handle IP6 addresses
+ domain = Resolv::IPv6::Regex.match?(ip_address) ? "[#{ip_address}]" : ip_address
+
begin
- @socket = TCPSocket.new irker_server, irker_port
- rescue Errno::ECONNREFUSED => e
+ Gitlab::UrlBlocker.validate!(
+ "irc://#{domain}",
+ allow_localhost: allow_local_requests?,
+ allow_local_network: allow_local_requests?,
+ schemes: ['irc'])
+ @socket = TCPSocket.new ip_address, irker_port
+ rescue Errno::ECONNREFUSED, Gitlab::UrlBlocker::BlockedUrlError => e
logger.fatal "Can't connect to Irker daemon: #{e}"
return false
end
@@ -53,6 +63,10 @@ class IrkerWorker # rubocop:disable Scalability/IdempotentWorker
true
end
+ def allow_local_requests?
+ Gitlab::CurrentSettings.allow_local_requests_from_web_hooks_and_services?
+ end
+
def send_to_irker(privmsg)
to_send = { to: @channels, privmsg: privmsg }
diff --git a/app/workers/packages/cleanup_package_file_worker.rb b/app/workers/packages/cleanup_package_file_worker.rb
index cb2b2a12c5e..f188017ee7a 100644
--- a/app/workers/packages/cleanup_package_file_worker.rb
+++ b/app/workers/packages/cleanup_package_file_worker.rb
@@ -19,6 +19,14 @@ module Packages
private
+ def after_destroy
+ pkg = artifact.package
+
+ pkg.transaction do
+ pkg.destroy if model.for_package_ids(pkg.id).empty?
+ end
+ end
+
def model
Packages::PackageFile
end
diff --git a/app/workers/packages/mark_package_files_for_destruction_worker.rb b/app/workers/packages/mark_package_files_for_destruction_worker.rb
new file mode 100644
index 00000000000..d8e52202841
--- /dev/null
+++ b/app/workers/packages/mark_package_files_for_destruction_worker.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+module Packages
+ class MarkPackageFilesForDestructionWorker
+ include ApplicationWorker
+
+ data_consistency :sticky
+ queue_namespace :package_cleanup
+ feature_category :package_registry
+ urgency :low
+ deduplicate :until_executing, including_scheduled: true
+ idempotent!
+
+ sidekiq_options retry: 3
+
+ def perform(package_id)
+ package = ::Packages::Package.find_by_id(package_id)
+
+ return unless package
+
+ ::Packages::MarkPackageFilesForDestructionService.new(package.package_files)
+ .execute
+ end
+ end
+end