From 88a0824944720b6edaaef56376713541b9a02118 Mon Sep 17 00:00:00 2001 From: GitLab Bot Date: Tue, 4 Feb 2020 12:09:00 +0000 Subject: Add latest changes from gitlab-org/gitlab@master --- lib/gitlab/auth/current_user_mode.rb | 61 +++++++++++++++++++--- .../backfill_project_fullpath_in_repo_config.rb | 4 +- .../backfill_project_repositories.rb | 4 +- lib/gitlab/sidekiq_middleware.rb | 2 + lib/gitlab/sidekiq_middleware/admin_mode/client.rb | 34 ++++++++++++ lib/gitlab/sidekiq_middleware/admin_mode/server.rb | 24 +++++++++ lib/microsoft_teams/notifier.rb | 5 +- 7 files changed, 120 insertions(+), 14 deletions(-) create mode 100644 lib/gitlab/sidekiq_middleware/admin_mode/client.rb create mode 100644 lib/gitlab/sidekiq_middleware/admin_mode/server.rb (limited to 'lib') diff --git a/lib/gitlab/auth/current_user_mode.rb b/lib/gitlab/auth/current_user_mode.rb index cb39baaa6cc..1ef95c03cfc 100644 --- a/lib/gitlab/auth/current_user_mode.rb +++ b/lib/gitlab/auth/current_user_mode.rb @@ -10,12 +10,54 @@ module Gitlab class CurrentUserMode NotRequestedError = Class.new(StandardError) + # RequestStore entries + CURRENT_REQUEST_BYPASS_SESSION_ADMIN_ID_RS_KEY = { res: :current_user_mode, data: :bypass_session_admin_id }.freeze + CURRENT_REQUEST_ADMIN_MODE_USER_RS_KEY = { res: :current_user_mode, data: :current_admin }.freeze + + # SessionStore entries SESSION_STORE_KEY = :current_user_mode - ADMIN_MODE_START_TIME_KEY = 'admin_mode' - ADMIN_MODE_REQUESTED_TIME_KEY = 'admin_mode_requested' + ADMIN_MODE_START_TIME_KEY = :admin_mode + ADMIN_MODE_REQUESTED_TIME_KEY = :admin_mode_requested MAX_ADMIN_MODE_TIME = 6.hours ADMIN_MODE_REQUESTED_GRACE_PERIOD = 5.minutes + class << self + # Admin mode activation requires storing a flag in the user session. Using this + # method when scheduling jobs in Sidekiq will bypass the session check for a + # user that was already in admin mode + def bypass_session!(admin_id) + Gitlab::SafeRequestStore[CURRENT_REQUEST_BYPASS_SESSION_ADMIN_ID_RS_KEY] = admin_id + + Gitlab::AppLogger.debug("Bypassing session in admin mode for: #{admin_id}") + + yield + ensure + Gitlab::SafeRequestStore.delete(CURRENT_REQUEST_BYPASS_SESSION_ADMIN_ID_RS_KEY) + end + + def bypass_session_admin_id + Gitlab::SafeRequestStore[CURRENT_REQUEST_BYPASS_SESSION_ADMIN_ID_RS_KEY] + end + + # Store in the current request the provided user model (only if in admin mode) + # and yield + def with_current_admin(admin) + return yield unless self.new(admin).admin_mode? + + Gitlab::SafeRequestStore[CURRENT_REQUEST_ADMIN_MODE_USER_RS_KEY] = admin + + Gitlab::AppLogger.debug("Admin mode active for: #{admin.username}") + + yield + ensure + Gitlab::SafeRequestStore.delete(CURRENT_REQUEST_ADMIN_MODE_USER_RS_KEY) + end + + def current_admin + Gitlab::SafeRequestStore[CURRENT_REQUEST_ADMIN_MODE_USER_RS_KEY] + end + end + def initialize(user) @user = user end @@ -42,7 +84,7 @@ module Gitlab raise NotRequestedError unless admin_mode_requested? - reset_request_store + reset_request_store_cache_entries current_session_data[ADMIN_MODE_REQUESTED_TIME_KEY] = nil current_session_data[ADMIN_MODE_START_TIME_KEY] = Time.now @@ -55,7 +97,7 @@ module Gitlab def disable_admin_mode! return unless user&.admin? - reset_request_store + reset_request_store_cache_entries current_session_data[ADMIN_MODE_REQUESTED_TIME_KEY] = nil current_session_data[ADMIN_MODE_START_TIME_KEY] = nil @@ -64,7 +106,7 @@ module Gitlab def request_admin_mode! return unless user&.admin? - reset_request_store + reset_request_store_cache_entries current_session_data[ADMIN_MODE_REQUESTED_TIME_KEY] = Time.now end @@ -73,10 +115,12 @@ module Gitlab attr_reader :user + # RequestStore entry to cache #admin_mode? result def admin_mode_rs_key @admin_mode_rs_key ||= { res: :current_user_mode, user: user.id, method: :admin_mode? } end + # RequestStore entry to cache #admin_mode_requested? result def admin_mode_requested_rs_key @admin_mode_requested_rs_key ||= { res: :current_user_mode, user: user.id, method: :admin_mode_requested? } end @@ -86,6 +130,7 @@ module Gitlab end def any_session_with_admin_mode? + return true if bypass_session? return true if current_session_data.initiated? && current_session_data[ADMIN_MODE_START_TIME_KEY].to_i > MAX_ADMIN_MODE_TIME.ago.to_i all_sessions.any? do |session| @@ -103,7 +148,11 @@ module Gitlab current_session_data[ADMIN_MODE_REQUESTED_TIME_KEY].to_i > ADMIN_MODE_REQUESTED_GRACE_PERIOD.ago.to_i end - def reset_request_store + def bypass_session? + user&.id && user.id == self.class.bypass_session_admin_id + end + + def reset_request_store_cache_entries Gitlab::SafeRequestStore.delete(admin_mode_rs_key) Gitlab::SafeRequestStore.delete(admin_mode_requested_rs_key) end diff --git a/lib/gitlab/background_migration/backfill_project_fullpath_in_repo_config.rb b/lib/gitlab/background_migration/backfill_project_fullpath_in_repo_config.rb index 3c142327e94..2a079060380 100644 --- a/lib/gitlab/background_migration/backfill_project_fullpath_in_repo_config.rb +++ b/lib/gitlab/background_migration/backfill_project_fullpath_in_repo_config.rb @@ -11,7 +11,7 @@ module Gitlab module Storage # Class that returns the disk path for a project using hashed storage - class HashedProject + class Hashed attr_accessor :project ROOT_PATH_PREFIX = '@hashed' @@ -121,7 +121,7 @@ module Gitlab def storage @storage ||= if hashed_storage? - Storage::HashedProject.new(self) + Storage::Hashed.new(self) else Storage::LegacyProject.new(self) end diff --git a/lib/gitlab/background_migration/backfill_project_repositories.rb b/lib/gitlab/background_migration/backfill_project_repositories.rb index 1d9aa050041..263546bd132 100644 --- a/lib/gitlab/background_migration/backfill_project_repositories.rb +++ b/lib/gitlab/background_migration/backfill_project_repositories.rb @@ -46,7 +46,7 @@ module Gitlab module Storage # Class that returns the disk path for a project using hashed storage - class HashedProject + class Hashed attr_accessor :project ROOT_PATH_PREFIX = '@hashed' @@ -176,7 +176,7 @@ module Gitlab def storage @storage ||= if hashed_storage? - Storage::HashedProject.new(self) + Storage::Hashed.new(self) else Storage::LegacyProject.new(self) end diff --git a/lib/gitlab/sidekiq_middleware.rb b/lib/gitlab/sidekiq_middleware.rb index 439d45b7a14..6c27213df49 100644 --- a/lib/gitlab/sidekiq_middleware.rb +++ b/lib/gitlab/sidekiq_middleware.rb @@ -17,6 +17,7 @@ module Gitlab chain.add Gitlab::SidekiqMiddleware::BatchLoader chain.add Labkit::Middleware::Sidekiq::Server chain.add Gitlab::SidekiqMiddleware::InstrumentationLogger + chain.add Gitlab::SidekiqMiddleware::AdminMode::Server chain.add Gitlab::SidekiqStatus::ServerMiddleware chain.add Gitlab::SidekiqMiddleware::WorkerContext::Server end @@ -31,6 +32,7 @@ module Gitlab chain.add Gitlab::SidekiqMiddleware::ClientMetrics chain.add Gitlab::SidekiqMiddleware::WorkerContext::Client # needs to be before the Labkit middleware chain.add Labkit::Middleware::Sidekiq::Client + chain.add Gitlab::SidekiqMiddleware::AdminMode::Client end end end diff --git a/lib/gitlab/sidekiq_middleware/admin_mode/client.rb b/lib/gitlab/sidekiq_middleware/admin_mode/client.rb new file mode 100644 index 00000000000..e227ee654ee --- /dev/null +++ b/lib/gitlab/sidekiq_middleware/admin_mode/client.rb @@ -0,0 +1,34 @@ +# frozen_string_literal: true + +module Gitlab + module SidekiqMiddleware + module AdminMode + # Checks if admin mode is enabled for the request creating the sidekiq job + # by examining if admin mode has been enabled for the user + # 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) + + # Admin mode enabled in the original request or in a nested sidekiq job + admin_mode_user_id = find_admin_user_id + + if admin_mode_user_id + job['admin_mode_user_id'] ||= admin_mode_user_id + + Gitlab::AppLogger.debug("AdminMode::Client injected admin mode for job: #{job.inspect}") + end + + yield + end + + private + + def find_admin_user_id + Gitlab::Auth::CurrentUserMode.current_admin&.id || + Gitlab::Auth::CurrentUserMode.bypass_session_admin_id + end + end + end + end +end diff --git a/lib/gitlab/sidekiq_middleware/admin_mode/server.rb b/lib/gitlab/sidekiq_middleware/admin_mode/server.rb new file mode 100644 index 00000000000..6366867a0fa --- /dev/null +++ b/lib/gitlab/sidekiq_middleware/admin_mode/server.rb @@ -0,0 +1,24 @@ +# frozen_string_literal: true + +module Gitlab + module SidekiqMiddleware + module AdminMode + class Server + def call(_worker, job, _queue) + return yield unless Feature.enabled?(:user_mode_in_session) + + admin_mode_user_id = job['admin_mode_user_id'] + + # Do not bypass session if this job was not enabled with admin mode on + return yield unless admin_mode_user_id + + Gitlab::Auth::CurrentUserMode.bypass_session!(admin_mode_user_id) do + Gitlab::AppLogger.debug("AdminMode::Server bypasses session for admin mode in job: #{job.inspect}") + + yield + end + end + end + end + end +end diff --git a/lib/microsoft_teams/notifier.rb b/lib/microsoft_teams/notifier.rb index 340bf709f5e..096e1e2ee96 100644 --- a/lib/microsoft_teams/notifier.rb +++ b/lib/microsoft_teams/notifier.rb @@ -36,10 +36,7 @@ module MicrosoftTeams attachments = options[:attachments] unless attachments.blank? - result['sections'] << { - 'title' => 'Details', - 'facts' => [{ 'name' => 'Attachments', 'value' => attachments }] - } + result['sections'] << { text: attachments } end result.to_json -- cgit v1.2.1