summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/api/api_guard.rb4
-rw-r--r--lib/api/internal/base.rb10
-rw-r--r--lib/api/settings.rb1
-rw-r--r--lib/constraints/admin_constrainer.rb2
-rw-r--r--lib/gitlab/diff/highlight.rb70
-rw-r--r--lib/gitlab/diff/highlight_cache.rb3
-rw-r--r--lib/gitlab/diff/inline_diff.rb1
-rw-r--r--lib/gitlab/diff/line.rb8
-rw-r--r--lib/gitlab/sidekiq_middleware/admin_mode/client.rb3
-rw-r--r--lib/gitlab/sidekiq_middleware/admin_mode/server.rb3
10 files changed, 77 insertions, 28 deletions
diff --git a/lib/api/api_guard.rb b/lib/api/api_guard.rb
index 8641271f2df..8822a30d4a1 100644
--- a/lib/api/api_guard.rb
+++ b/lib/api/api_guard.rb
@@ -55,7 +55,7 @@ module API
user = find_user_from_sources
return unless user
- if user.is_a?(User) && Feature.enabled?(:user_mode_in_session)
+ if user.is_a?(User) && Gitlab::CurrentSettings.admin_mode
# Sessions are enforced to be unavailable for API calls, so ignore them for admin mode
Gitlab::Auth::CurrentUserMode.bypass_session!(user.id)
end
@@ -236,7 +236,7 @@ module API
def after
# Use a Grape middleware since the Grape `after` blocks might run
# before we are finished rendering the `Grape::Entity` classes
- Gitlab::Auth::CurrentUserMode.reset_bypass_session! if Feature.enabled?(:user_mode_in_session)
+ Gitlab::Auth::CurrentUserMode.reset_bypass_session! if Gitlab::CurrentSettings.admin_mode
# Explicit nil is needed or the api call return value will be overwritten
nil
diff --git a/lib/api/internal/base.rb b/lib/api/internal/base.rb
index 3dd01b96e39..664b05ea010 100644
--- a/lib/api/internal/base.rb
+++ b/lib/api/internal/base.rb
@@ -52,7 +52,7 @@ module API
actor.update_last_used_at!
check_result = begin
- Gitlab::Auth::CurrentUserMode.bypass_session!(actor.user&.id) do
+ with_admin_mode_bypass!(actor.user&.id) do
access_check!(actor, params)
end
rescue Gitlab::GitAccess::ForbiddenError => e
@@ -120,6 +120,14 @@ module API
def two_factor_otp_check
{ success: false, message: 'Feature is not available' }
end
+
+ def with_admin_mode_bypass!(actor_id)
+ return yield unless Gitlab::CurrentSettings.admin_mode
+
+ Gitlab::Auth::CurrentUserMode.bypass_session!(actor_id) do
+ yield
+ end
+ end
end
namespace 'internal' do
diff --git a/lib/api/settings.rb b/lib/api/settings.rb
index 64a72b4cb7f..95d0c525ced 100644
--- a/lib/api/settings.rb
+++ b/lib/api/settings.rb
@@ -30,6 +30,7 @@ module API
success Entities::ApplicationSetting
end
params do
+ optional :admin_mode, type: Boolean, desc: 'Require admin users to re-authenticate for administrative (i.e. potentially dangerous) operations'
optional :admin_notification_email, type: String, desc: 'Deprecated: Use :abuse_notification_email instead. Abuse reports will be sent to this address if it is set. Abuse reports are always available in the admin area.'
optional :abuse_notification_email, type: String, desc: 'Abuse reports will be sent to this address if it is set. Abuse reports are always available in the admin area.'
optional :after_sign_up_text, type: String, desc: 'Text shown after sign up'
diff --git a/lib/constraints/admin_constrainer.rb b/lib/constraints/admin_constrainer.rb
index 59c855a1b73..2f32cc7ad91 100644
--- a/lib/constraints/admin_constrainer.rb
+++ b/lib/constraints/admin_constrainer.rb
@@ -3,7 +3,7 @@
module Constraints
class AdminConstrainer
def matches?(request)
- if Feature.enabled?(:user_mode_in_session)
+ if Gitlab::CurrentSettings.admin_mode
admin_mode_enabled?(request)
else
user_is_admin?(request)
diff --git a/lib/gitlab/diff/highlight.rb b/lib/gitlab/diff/highlight.rb
index baa46e7e306..23859e2573e 100644
--- a/lib/gitlab/diff/highlight.rb
+++ b/lib/gitlab/diff/highlight.rb
@@ -3,7 +3,7 @@
module Gitlab
module Diff
class Highlight
- attr_reader :diff_file, :diff_lines, :raw_lines, :repository, :project
+ attr_reader :diff_file, :diff_lines, :repository, :project
delegate :old_path, :new_path, :old_sha, :new_sha, to: :diff_file, prefix: :diff
@@ -22,29 +22,15 @@ module Gitlab
end
def highlight
- @diff_lines.map.with_index do |diff_line, i|
+ populate_marker_ranges if Feature.enabled?(:use_marker_ranges, project, default_enabled: :yaml)
+
+ @diff_lines.map.with_index do |diff_line, index|
diff_line = diff_line.dup
# ignore highlighting for "match" lines
next diff_line if diff_line.meta?
- rich_line = highlight_line(diff_line) || ERB::Util.html_escape(diff_line.text)
-
- if line_inline_diffs = inline_diffs[i]
- begin
- # MarkerRange objects are converted to Ranges to keep the previous behavior
- # Issue: https://gitlab.com/gitlab-org/gitlab/-/issues/324068
- if Feature.disabled?(:introduce_marker_ranges, project, default_enabled: :yaml)
- line_inline_diffs = line_inline_diffs.map { |marker_range| marker_range.to_range }
- end
-
- rich_line = InlineDiffMarker.new(diff_line.text, rich_line).mark(line_inline_diffs)
- # This should only happen when the encoding of the diff doesn't
- # match the blob, which is a bug. But we shouldn't fail to render
- # completely in that case, even though we want to report the error.
- rescue RangeError => e
- Gitlab::ErrorTracking.track_and_raise_for_dev_exception(e, issue_url: 'https://gitlab.com/gitlab-org/gitlab-foss/issues/45441')
- end
- end
+ rich_line = apply_syntax_highlight(diff_line)
+ rich_line = apply_marker_ranges_highlight(diff_line, rich_line, index)
diff_line.rich_text = rich_line
@@ -54,6 +40,49 @@ module Gitlab
private
+ def populate_marker_ranges
+ pair_selector = Gitlab::Diff::PairSelector.new(@raw_lines)
+
+ pair_selector.each do |old_index, new_index|
+ old_line = diff_lines[old_index]
+ new_line = diff_lines[new_index]
+
+ old_diffs, new_diffs = Gitlab::Diff::InlineDiff.new(old_line.text, new_line.text, offset: 1).inline_diffs
+
+ old_line.set_marker_ranges(old_diffs)
+ new_line.set_marker_ranges(new_diffs)
+ end
+ end
+
+ def apply_syntax_highlight(diff_line)
+ highlight_line(diff_line) || ERB::Util.html_escape(diff_line.text)
+ end
+
+ def apply_marker_ranges_highlight(diff_line, rich_line, index)
+ marker_ranges = if Feature.enabled?(:use_marker_ranges, project, default_enabled: :yaml)
+ diff_line.marker_ranges
+ else
+ inline_diffs[index]
+ end
+
+ return rich_line if marker_ranges.blank?
+
+ begin
+ # MarkerRange objects are converted to Ranges to keep the previous behavior
+ # Issue: https://gitlab.com/gitlab-org/gitlab/-/issues/324068
+ if Feature.disabled?(:introduce_marker_ranges, project, default_enabled: :yaml)
+ marker_ranges = marker_ranges.map { |marker_range| marker_range.to_range }
+ end
+
+ InlineDiffMarker.new(diff_line.text, rich_line).mark(marker_ranges)
+ # This should only happen when the encoding of the diff doesn't
+ # match the blob, which is a bug. But we shouldn't fail to render
+ # completely in that case, even though we want to report the error.
+ rescue RangeError => e
+ Gitlab::ErrorTracking.track_and_raise_for_dev_exception(e, issue_url: 'https://gitlab.com/gitlab-org/gitlab-foss/issues/45441')
+ end
+ end
+
def highlight_line(diff_line)
return unless diff_file && diff_file.diff_refs
@@ -72,6 +101,7 @@ module Gitlab
end
end
+ # Deprecated: https://gitlab.com/gitlab-org/gitlab/-/issues/324638
def inline_diffs
@inline_diffs ||= InlineDiff.for_lines(@raw_lines)
end
diff --git a/lib/gitlab/diff/highlight_cache.rb b/lib/gitlab/diff/highlight_cache.rb
index c5e9bfdc321..2192582348c 100644
--- a/lib/gitlab/diff/highlight_cache.rb
+++ b/lib/gitlab/diff/highlight_cache.rb
@@ -73,7 +73,8 @@ module Gitlab
'highlighted-diff-files',
diffable.cache_key, VERSION,
diff_options,
- Feature.enabled?(:introduce_marker_ranges, diffable.project, default_enabled: :yaml)
+ Feature.enabled?(:introduce_marker_ranges, diffable.project, default_enabled: :yaml),
+ Feature.enabled?(:use_marker_ranges, diffable.project, default_enabled: :yaml)
].join(":")
end
end
diff --git a/lib/gitlab/diff/inline_diff.rb b/lib/gitlab/diff/inline_diff.rb
index dd73e4d6c15..f70618195d0 100644
--- a/lib/gitlab/diff/inline_diff.rb
+++ b/lib/gitlab/diff/inline_diff.rb
@@ -18,6 +18,7 @@ module Gitlab
CharDiff.new(old_line, new_line).changed_ranges(offset: offset)
end
+ # Deprecated: https://gitlab.com/gitlab-org/gitlab/-/issues/324638
class << self
def for_lines(lines)
pair_selector = Gitlab::Diff::PairSelector.new(lines)
diff --git a/lib/gitlab/diff/line.rb b/lib/gitlab/diff/line.rb
index 98ed2400d82..444928b4310 100644
--- a/lib/gitlab/diff/line.rb
+++ b/lib/gitlab/diff/line.rb
@@ -8,7 +8,7 @@ module Gitlab
#
SERIALIZE_KEYS = %i(line_code rich_text text type index old_pos new_pos).freeze
- attr_reader :line_code
+ attr_reader :line_code, :marker_ranges
attr_writer :rich_text
attr_accessor :text, :index, :type, :old_pos, :new_pos
@@ -21,6 +21,8 @@ module Gitlab
# When line code is not provided from cache store we build it
# using the parent_file(Diff::File or Conflict::File).
@line_code = line_code || calculate_line_code
+
+ @marker_ranges = []
end
def self.init_from_hash(hash)
@@ -48,6 +50,10 @@ module Gitlab
hash
end
+ def set_marker_ranges(marker_ranges)
+ @marker_ranges = marker_ranges
+ end
+
def old_line
old_pos unless added? || meta?
end
diff --git a/lib/gitlab/sidekiq_middleware/admin_mode/client.rb b/lib/gitlab/sidekiq_middleware/admin_mode/client.rb
index 36204e1bee0..1b33743a0e9 100644
--- a/lib/gitlab/sidekiq_middleware/admin_mode/client.rb
+++ b/lib/gitlab/sidekiq_middleware/admin_mode/client.rb
@@ -8,7 +8,8 @@ module Gitlab
# If enabled then it injects a job field that persists through the job execution
class Client
def call(_worker_class, job, _queue, _redis_pool)
- return yield unless ::Feature.enabled?(:user_mode_in_session)
+ # Not calling Gitlab::CurrentSettings.admin_mode on purpose on sidekiq middleware
+ # Only when admin mode application setting is enabled might the admin_mode_user_id be non-nil here
# Admin mode enabled in the original request or in a nested sidekiq job
admin_mode_user_id = find_admin_user_id
diff --git a/lib/gitlab/sidekiq_middleware/admin_mode/server.rb b/lib/gitlab/sidekiq_middleware/admin_mode/server.rb
index 6366867a0fa..c4e64705d6e 100644
--- a/lib/gitlab/sidekiq_middleware/admin_mode/server.rb
+++ b/lib/gitlab/sidekiq_middleware/admin_mode/server.rb
@@ -5,7 +5,8 @@ module Gitlab
module AdminMode
class Server
def call(_worker, job, _queue)
- return yield unless Feature.enabled?(:user_mode_in_session)
+ # Not calling Gitlab::CurrentSettings.admin_mode on purpose on sidekiq middleware
+ # Only when admin_mode setting is enabled can it be true here
admin_mode_user_id = job['admin_mode_user_id']