diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-11-24 15:10:21 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-11-24 15:10:21 +0300 |
commit | 77b8390171a55d4593e3730551751d8348992f80 (patch) | |
tree | 61adcb066a34458a98dfbf90f0a8ce3420533a1a /lib | |
parent | 49cea0b04a1138a00cc7068c4c1a997867aeae88 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'lib')
-rw-r--r-- | lib/banzai/filter/issuable_reference_expansion_filter.rb | 92 | ||||
-rw-r--r-- | lib/banzai/filter/issuable_state_filter.rb | 66 | ||||
-rw-r--r-- | lib/banzai/filter/references/abstract_reference_filter.rb | 2 | ||||
-rw-r--r-- | lib/banzai/pipeline/post_process_pipeline.rb | 2 | ||||
-rw-r--r-- | lib/gitlab/content_security_policy/config_loader.rb | 6 | ||||
-rw-r--r-- | lib/gitlab/database.rb | 9 | ||||
-rw-r--r-- | lib/gitlab/database/gitlab_loose_foreign_keys.yml | 8 | ||||
-rw-r--r-- | lib/gitlab/database/loose_foreign_keys.rb | 38 | ||||
-rw-r--r-- | lib/gitlab/regex.rb | 2 | ||||
-rw-r--r-- | lib/gitlab/tracking.rb | 8 | ||||
-rw-r--r-- | lib/gitlab/tracking/destinations/snowplow_micro.rb | 4 |
11 files changed, 163 insertions, 74 deletions
diff --git a/lib/banzai/filter/issuable_reference_expansion_filter.rb b/lib/banzai/filter/issuable_reference_expansion_filter.rb new file mode 100644 index 00000000000..6822e36c9be --- /dev/null +++ b/lib/banzai/filter/issuable_reference_expansion_filter.rb @@ -0,0 +1,92 @@ +# frozen_string_literal: true + +module Banzai + module Filter + # HTML filter that appends extra information to issuable links. + # Runs as a post-process filter as issuable might change while + # Markdown is in the cache. + # + # This filter supports cross-project references. + class IssuableReferenceExpansionFilter < HTML::Pipeline::Filter + include Gitlab::Utils::StrongMemoize + + VISIBLE_STATES = %w(closed merged).freeze + + def call + return doc unless context[:issuable_reference_expansion_enabled] + + context = RenderContext.new(project, current_user) + extractor = Banzai::IssuableExtractor.new(context) + issuables = extractor.extract([doc]) + + issuables.each do |node, issuable| + next if !can_read_cross_project? && cross_referenced?(issuable) + next unless should_expand?(node, issuable) + + case node.attr('data-reference-format') + when '+' + expand_reference_with_title_and_state(node, issuable) + else + expand_reference_with_state(node, issuable) + end + end + + doc + end + + private + + # Example: Issue Title (#123 - closed) + def expand_reference_with_title_and_state(node, issuable) + node.content = "#{issuable.title.truncate(50)} (#{node.content}" + node.content += " - #{issuable_state_text(issuable)}" if VISIBLE_STATES.include?(issuable.state) + node.content += ')' + end + + # Example: #123 (closed) + def expand_reference_with_state(node, issuable) + node.content += " (#{issuable_state_text(issuable)})" + end + + def issuable_state_text(issuable) + moved_issue?(issuable) ? s_("IssuableStatus|moved") : issuable.state + end + + def moved_issue?(issuable) + issuable.instance_of?(Issue) && issuable.moved? + end + + def should_expand?(node, issuable) + # We add this extra check to avoid unescaping HTML and generating reference link text for every reference + return unless node.attr('data-reference-format').present? || VISIBLE_STATES.include?(issuable.state) + + CGI.unescapeHTML(node.inner_html) == issuable.reference_link_text(project || group) + end + + def cross_referenced?(issuable) + return true if issuable.project != project + return true if issuable.respond_to?(:group) && issuable.group != group + + false + end + + def can_read_cross_project? + strong_memoize(:can_read_cross_project) do + Ability.allowed?(current_user, :read_cross_project) + end + end + + def current_user + context[:current_user] + end + + def project + context[:project] + end + + def group + context[:group] + end + end + end +end diff --git a/lib/banzai/filter/issuable_state_filter.rb b/lib/banzai/filter/issuable_state_filter.rb deleted file mode 100644 index a88629ac105..00000000000 --- a/lib/banzai/filter/issuable_state_filter.rb +++ /dev/null @@ -1,66 +0,0 @@ -# frozen_string_literal: true - -module Banzai - module Filter - # HTML filter that appends state information to issuable links. - # Runs as a post-process filter as issuable state might change while - # Markdown is in the cache. - # - # This filter supports cross-project references. - class IssuableStateFilter < HTML::Pipeline::Filter - VISIBLE_STATES = %w(closed merged).freeze - - def call - return doc unless context[:issuable_state_filter_enabled] - - context = RenderContext.new(project, current_user) - extractor = Banzai::IssuableExtractor.new(context) - issuables = extractor.extract([doc]) - - issuables.each do |node, issuable| - next if !can_read_cross_project? && cross_referenced?(issuable) - - if VISIBLE_STATES.include?(issuable.state) && issuable_reference?(node.inner_html, issuable) - state = moved_issue?(issuable) ? s_("IssuableStatus|moved") : issuable.state - node.content += " (#{state})" - end - end - - doc - end - - private - - def moved_issue?(issuable) - issuable.instance_of?(Issue) && issuable.moved? - end - - def issuable_reference?(text, issuable) - CGI.unescapeHTML(text) == issuable.reference_link_text(project || group) - end - - def cross_referenced?(issuable) - return true if issuable.project != project - return true if issuable.respond_to?(:group) && issuable.group != group - - false - end - - def can_read_cross_project? - Ability.allowed?(current_user, :read_cross_project) - end - - def current_user - context[:current_user] - end - - def project - context[:project] - end - - def group - context[:group] - end - end - end -end diff --git a/lib/banzai/filter/references/abstract_reference_filter.rb b/lib/banzai/filter/references/abstract_reference_filter.rb index cae0a8b424a..7a23326bafa 100644 --- a/lib/banzai/filter/references/abstract_reference_filter.rb +++ b/lib/banzai/filter/references/abstract_reference_filter.rb @@ -205,6 +205,8 @@ module Banzai data_attributes = data_attributes_for(link_content || match, parent, object, link_content: !!link_content, link_reference: link_reference) + data_attributes[:reference_format] = matches[:format] if matches.names.include?("format") + data = data_attribute(data_attributes) url = diff --git a/lib/banzai/pipeline/post_process_pipeline.rb b/lib/banzai/pipeline/post_process_pipeline.rb index 889574cf6bf..da2262cdf83 100644 --- a/lib/banzai/pipeline/post_process_pipeline.rb +++ b/lib/banzai/pipeline/post_process_pipeline.rb @@ -19,7 +19,7 @@ module Banzai # prevent unnecessary Gitaly calls from being made. Filter::UploadLinkFilter, Filter::RepositoryLinkFilter, - Filter::IssuableStateFilter, + Filter::IssuableReferenceExpansionFilter, Filter::SuggestionFilter ] end diff --git a/lib/gitlab/content_security_policy/config_loader.rb b/lib/gitlab/content_security_policy/config_loader.rb index bdae59e7e3c..50490d1b5a3 100644 --- a/lib/gitlab/content_security_policy/config_loader.rb +++ b/lib/gitlab/content_security_policy/config_loader.rb @@ -36,6 +36,7 @@ module Gitlab if Rails.env.development? allow_webpack_dev_server(directives) allow_letter_opener(directives) + allow_snowplow_micro(directives) if Gitlab::Tracking.snowplow_micro_enabled? allow_customersdot(directives) if ENV['CUSTOMER_PORTAL_URL'].present? end @@ -138,6 +139,11 @@ module Gitlab append_to_directive(directives, 'frame_src', Gitlab::Utils.append_path(Gitlab.config.gitlab.url, '/rails/letter_opener/')) end + def self.allow_snowplow_micro(directives) + url = URI.join(Gitlab::Tracking::Destinations::SnowplowMicro.new.uri, '/').to_s + append_to_directive(directives, 'connect_src', url) + end + # Using 'self' in the CSP introduces several CSP bypass opportunities # for this reason we list the URLs where GitLab frames itself instead def self.allow_framed_gitlab_paths(directives) diff --git a/lib/gitlab/database.rb b/lib/gitlab/database.rb index 9c74e5d2ca8..1a464555278 100644 --- a/lib/gitlab/database.rb +++ b/lib/gitlab/database.rb @@ -63,6 +63,15 @@ module Gitlab }.compact.with_indifferent_access.freeze end + # This returns a list of base models with connection associated for a given gitlab_schema + def self.schemas_to_base_models + @schemas_to_base_models ||= { + gitlab_main: [self.database_base_models.fetch(:main)], + gitlab_ci: [self.database_base_models[:ci] || self.database_base_models.fetch(:main)], # use CI or fallback to main + gitlab_shared: self.database_base_models.values # all models + }.with_indifferent_access.freeze + end + # We configure the database connection pool size automatically based on the # configured concurrency. We also add some headroom, to make sure we don't # run out of connections when more threads besides the 'user-facing' ones diff --git a/lib/gitlab/database/gitlab_loose_foreign_keys.yml b/lib/gitlab/database/gitlab_loose_foreign_keys.yml new file mode 100644 index 00000000000..27b8f3bbe0f --- /dev/null +++ b/lib/gitlab/database/gitlab_loose_foreign_keys.yml @@ -0,0 +1,8 @@ +chat_names: + - to_table: ci_pipeline_chat_data + column: chat_name_id + on_delete: async_delete +ci_runners: + - to_table: clusters_applications_runners + column: runner_id + on_delete: async_nullify diff --git a/lib/gitlab/database/loose_foreign_keys.rb b/lib/gitlab/database/loose_foreign_keys.rb new file mode 100644 index 00000000000..1d885b3fbc8 --- /dev/null +++ b/lib/gitlab/database/loose_foreign_keys.rb @@ -0,0 +1,38 @@ +# frozen_string_literal: true + +module Gitlab + module Database + module LooseForeignKeys + def self.definitions_by_table + @definitions_by_table ||= definitions.group_by(&:from_table).with_indifferent_access.freeze + end + + def self.definitions + @definitions ||= loose_foreign_keys_yaml.flat_map do |parent_table_name, configs| + configs.map { |config| build_definition(parent_table_name, config) } + end.freeze + end + + def self.build_definition(parent_table_name, config) + to_table = config.fetch('to_table') + + ActiveRecord::ConnectionAdapters::ForeignKeyDefinition.new( + parent_table_name, + to_table, + { + column: config.fetch('column'), + on_delete: config.fetch('on_delete').to_sym, + gitlab_schema: GitlabSchema.table_schema(to_table) + } + ) + end + + def self.loose_foreign_keys_yaml + @loose_foreign_keys_yaml ||= YAML.load_file(Rails.root.join('lib/gitlab/database/gitlab_loose_foreign_keys.yml')) + end + + private_class_method :build_definition + private_class_method :loose_foreign_keys_yaml + end + end +end diff --git a/lib/gitlab/regex.rb b/lib/gitlab/regex.rb index 8b2f786a91a..e247515bdde 100644 --- a/lib/gitlab/regex.rb +++ b/lib/gitlab/regex.rb @@ -413,7 +413,7 @@ module Gitlab end def issue - @issue ||= /(?<issue>\d+\b)/ + @issue ||= /(?<issue>\d+)(?<format>\+)?(?=\W|\z)/ end def base64_regex diff --git a/lib/gitlab/tracking.rb b/lib/gitlab/tracking.rb index ec032cf2d3c..216b1d04bf6 100644 --- a/lib/gitlab/tracking.rb +++ b/lib/gitlab/tracking.rb @@ -25,6 +25,10 @@ module Gitlab snowplow.hostname end + def snowplow_micro_enabled? + Rails.env.development? && Gitlab::Utils.to_boolean(ENV['SNOWPLOW_MICRO_ENABLE']) + end + private def snowplow @@ -34,10 +38,6 @@ module Gitlab Gitlab::Tracking::Destinations::Snowplow.new end end - - def snowplow_micro_enabled? - Rails.env.development? && Gitlab::Utils.to_boolean(ENV['SNOWPLOW_MICRO_ENABLE']) - end end end end diff --git a/lib/gitlab/tracking/destinations/snowplow_micro.rb b/lib/gitlab/tracking/destinations/snowplow_micro.rb index cbdc7430e78..8beab910818 100644 --- a/lib/gitlab/tracking/destinations/snowplow_micro.rb +++ b/lib/gitlab/tracking/destinations/snowplow_micro.rb @@ -23,8 +23,6 @@ module Gitlab "#{uri.host}:#{uri.port}" end - private - def uri strong_memoize(:snowplow_uri) do uri = URI(ENV['SNOWPLOW_MICRO_URI'] || DEFAULT_URI) @@ -33,6 +31,8 @@ module Gitlab end end + private + override :cookie_domain def cookie_domain '.gitlab.com' |