Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2023-12-13 21:16:51 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2023-12-13 21:16:51 +0300
commit46e1fdb8bbdaf149371334f1a1757ba4d68fe020 (patch)
treec2a0bd6da129d9d41cef38e7a6c0efd2c79de893 /app/services
parent57ed4c594d37326f1d27752df575b581c522ab05 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/services')
-rw-r--r--app/services/auth/dependency_proxy_authentication_service.rb30
-rw-r--r--app/services/ci/pipeline_schedules/variables_base_save_service.rb52
-rw-r--r--app/services/ci/pipeline_schedules/variables_create_service.rb24
-rw-r--r--app/services/ci/pipeline_schedules/variables_update_service.rb24
-rw-r--r--app/services/personal_access_tokens/rotate_service.rb44
-rw-r--r--app/services/project_access_tokens/rotate_service.rb58
-rw-r--r--app/services/work_items/delete_task_service.rb45
-rw-r--r--app/services/work_items/task_list_reference_removal_service.rb56
8 files changed, 205 insertions, 128 deletions
diff --git a/app/services/auth/dependency_proxy_authentication_service.rb b/app/services/auth/dependency_proxy_authentication_service.rb
index 164594d6f6c..29f5a50d809 100644
--- a/app/services/auth/dependency_proxy_authentication_service.rb
+++ b/app/services/auth/dependency_proxy_authentication_service.rb
@@ -5,10 +5,11 @@ module Auth
AUDIENCE = 'dependency_proxy'
HMAC_KEY = 'gitlab-dependency-proxy'
DEFAULT_EXPIRE_TIME = 1.minute
+ REQUIRED_ABILITIES = %i[read_container_image create_container_image].freeze
def execute(authentication_abilities:)
return error('dependency proxy not enabled', 404) unless ::Gitlab.config.dependency_proxy.enabled
- return error('access forbidden', 403) unless valid_user_actor?
+ return error('access forbidden', 403) unless valid_user_actor?(authentication_abilities)
{ token: authorized_token.encoded }
end
@@ -33,8 +34,27 @@ module Auth
private
- def valid_user_actor?
- current_user || valid_deploy_token?
+ def valid_user_actor?(authentication_abilities)
+ feature_user = deploy_token&.user || current_user
+ if Feature.enabled?(:packages_dependency_proxy_containers_scope_check, feature_user)
+ if deploy_token
+ deploy_token.valid_for_dependency_proxy?
+ elsif current_user&.project_bot?
+ group_access_token&.active? && has_required_abilities?(authentication_abilities)
+ else
+ current_user
+ end
+ else
+ current_user || valid_deploy_token?
+ end
+ end
+
+ def has_required_abilities?(authentication_abilities)
+ (REQUIRED_ABILITIES & authentication_abilities).size == REQUIRED_ABILITIES.size
+ end
+
+ def group_access_token
+ PersonalAccessTokensFinder.new(state: 'active').find_by_token(raw_token)
end
def valid_deploy_token?
@@ -52,5 +72,9 @@ module Auth
def deploy_token
params[:deploy_token]
end
+
+ def raw_token
+ params[:raw_token]
+ end
end
end
diff --git a/app/services/ci/pipeline_schedules/variables_base_save_service.rb b/app/services/ci/pipeline_schedules/variables_base_save_service.rb
new file mode 100644
index 00000000000..fb3ba52b36e
--- /dev/null
+++ b/app/services/ci/pipeline_schedules/variables_base_save_service.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+
+module Ci
+ module PipelineSchedules
+ class VariablesBaseSaveService
+ include Gitlab::Utils::StrongMemoize
+
+ def execute
+ variable.assign_attributes(params)
+
+ return forbidden_to_update_pipeline_schedule unless allowed_to_update_pipeline_schedule?
+ return forbidden_to_save_variables unless allowed_to_save_variables?
+
+ if variable.save
+ ServiceResponse.success(payload: variable)
+ else
+ ServiceResponse.error(payload: variable, message: variable.errors.full_messages)
+ end
+ end
+
+ private
+
+ attr_reader :project, :user, :params, :variable, :pipeline_schedule
+
+ def allowed_to_update_pipeline_schedule?
+ user.can?(:update_pipeline_schedule, pipeline_schedule)
+ end
+
+ def forbidden_to_update_pipeline_schedule
+ # We add the error to the base object too
+ # because model errors are used in the API responses and the `form_errors` helper.
+ pipeline_schedule.errors.add(:base, authorize_message)
+
+ ServiceResponse.error(payload: pipeline_schedule, message: [authorize_message], reason: :forbidden)
+ end
+
+ def allowed_to_save_variables?
+ user.can?(:set_pipeline_variables, project)
+ end
+
+ def forbidden_to_save_variables
+ message = _('The current user is not authorized to set pipeline schedule variables')
+
+ # We add the error to the base object too
+ # because model errors are used in the API responses and the `form_errors` helper.
+ pipeline_schedule.errors.add(:base, message)
+
+ ServiceResponse.error(payload: pipeline_schedule, message: [message], reason: :forbidden)
+ end
+ end
+ end
+end
diff --git a/app/services/ci/pipeline_schedules/variables_create_service.rb b/app/services/ci/pipeline_schedules/variables_create_service.rb
new file mode 100644
index 00000000000..7d81b0771dc
--- /dev/null
+++ b/app/services/ci/pipeline_schedules/variables_create_service.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+module Ci
+ module PipelineSchedules
+ class VariablesCreateService < VariablesBaseSaveService
+ AUTHORIZE = :update_pipeline_schedule
+
+ def initialize(pipeline_schedule, user, params)
+ @variable = pipeline_schedule.variables.new
+ @user = user
+ @pipeline_schedule = pipeline_schedule
+ @project = pipeline_schedule.project
+ @params = params
+ end
+
+ private
+
+ def authorize_message
+ _('The current user is not authorized to create the pipeline schedule variables')
+ end
+ strong_memoize_attr :authorize_message
+ end
+ end
+end
diff --git a/app/services/ci/pipeline_schedules/variables_update_service.rb b/app/services/ci/pipeline_schedules/variables_update_service.rb
new file mode 100644
index 00000000000..f0e3a03c37a
--- /dev/null
+++ b/app/services/ci/pipeline_schedules/variables_update_service.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+module Ci
+ module PipelineSchedules
+ class VariablesUpdateService < VariablesBaseSaveService
+ AUTHORIZE = :update_pipeline_schedule
+
+ def initialize(pipeline_schedule_variable, user, params)
+ @variable = pipeline_schedule_variable
+ @user = user
+ @pipeline_schedule = pipeline_schedule_variable.pipeline_schedule
+ @project = pipeline_schedule.project
+ @params = params
+ end
+
+ private
+
+ def authorize_message
+ _('The current user is not authorized to update the pipeline schedule variables')
+ end
+ strong_memoize_attr :authorize_message
+ end
+ end
+end
diff --git a/app/services/personal_access_tokens/rotate_service.rb b/app/services/personal_access_tokens/rotate_service.rb
index 55eff1e69aa..e381d86fbed 100644
--- a/app/services/personal_access_tokens/rotate_service.rb
+++ b/app/services/personal_access_tokens/rotate_service.rb
@@ -10,27 +10,19 @@ module PersonalAccessTokens
end
def execute(params = {})
- return error_response(message: _('token already revoked')) if token.revoked?
+ return error_response(_('token already revoked')) if token.revoked?
response = ServiceResponse.success
PersonalAccessToken.transaction do
unless token.revoke!
- response = error_response
+ response = error_response(_('failed to revoke token'))
raise ActiveRecord::Rollback
end
- target_user = token.user
- new_token = target_user.personal_access_tokens.create(create_token_params(token, params))
+ response = create_access_token(params)
- if new_token.persisted?
- response = error_response unless update_bot_membership(target_user, new_token.expires_at)
- response = success_response(new_token)
- else
- response = error_response(message: new_token.errors.full_messages.to_sentence)
-
- raise ActiveRecord::Rollback
- end
+ raise ActiveRecord::Rollback unless response.success?
end
response
@@ -40,6 +32,16 @@ module PersonalAccessTokens
attr_reader :current_user, :token
+ def create_access_token(params)
+ target_user = token.user
+
+ new_token = target_user.personal_access_tokens.create(create_token_params(token, params))
+
+ return success_response(new_token) if new_token.persisted?
+
+ error_response(new_token.errors.full_messages.to_sentence)
+ end
+
def expires_at(params)
return params[:expires_at] if params[:expires_at]
@@ -50,22 +52,16 @@ module PersonalAccessTokens
ServiceResponse.success(payload: { personal_access_token: new_token })
end
- def error_response(message: _('failed to revoke token'))
+ def error_response(message)
ServiceResponse.error(message: message)
end
def create_token_params(token, params)
- { name: token.name,
- previous_personal_access_token_id: token.id,
- impersonation: token.impersonation,
- scopes: token.scopes,
- expires_at: expires_at(params) }
- end
-
- def update_bot_membership(target_user, expires_at)
- return unless target_user.project_bot?
-
- target_user.members.first.update(expires_at: expires_at)
+ { name: token.name,
+ previous_personal_access_token_id: token.id,
+ impersonation: token.impersonation,
+ scopes: token.scopes,
+ expires_at: expires_at(params) }
end
end
end
diff --git a/app/services/project_access_tokens/rotate_service.rb b/app/services/project_access_tokens/rotate_service.rb
new file mode 100644
index 00000000000..63d8d2a82cc
--- /dev/null
+++ b/app/services/project_access_tokens/rotate_service.rb
@@ -0,0 +1,58 @@
+# frozen_string_literal: true
+
+module ProjectAccessTokens
+ class RotateService < ::PersonalAccessTokens::RotateService
+ extend ::Gitlab::Utils::Override
+
+ def initialize(current_user, token, resource = nil)
+ @current_user = current_user
+ @token = token
+ @project = resource
+ end
+
+ def execute(params = {})
+ super
+ end
+
+ attr_reader :project
+
+ private
+
+ override :create_access_token
+ def create_access_token(params)
+ target_user = token.user
+
+ unless valid_access_level?
+ return error_response(
+ _("Not eligible to rotate token with access level higher than the user")
+ )
+ end
+
+ new_token = target_user.personal_access_tokens.create(create_token_params(token, params))
+
+ if new_token.persisted?
+ update_bot_membership(target_user, new_token.expires_at)
+
+ return success_response(new_token)
+ end
+
+ error_response(new_token.errors.full_messages.to_sentence)
+ end
+
+ def update_bot_membership(target_user, expires_at)
+ target_user.members.update(expires_at: expires_at)
+ end
+
+ def valid_access_level?
+ return true if current_user.can_admin_all_resources?
+ return false unless current_user.can?(:manage_resource_access_tokens, project)
+
+ token_access_level = project.team.max_member_access(token.user.id).to_i
+ current_user_access_level = project.team.max_member_access(current_user.id).to_i
+
+ return true if token_access_level.to_i <= current_user_access_level
+
+ false
+ end
+ end
+end
diff --git a/app/services/work_items/delete_task_service.rb b/app/services/work_items/delete_task_service.rb
deleted file mode 100644
index 4c0ee2f827d..00000000000
--- a/app/services/work_items/delete_task_service.rb
+++ /dev/null
@@ -1,45 +0,0 @@
-# frozen_string_literal: true
-
-module WorkItems
- class DeleteTaskService
- def initialize(work_item:, lock_version:, current_user: nil, task_params: {})
- @work_item = work_item
- @current_user = current_user
- @task_params = task_params
- @lock_version = lock_version
- @task = task_params[:task]
- @errors = []
- end
-
- def execute
- transaction_result = ::WorkItem.transaction do
- replacement_result = TaskListReferenceRemovalService.new(
- work_item: @work_item,
- task: @task,
- line_number_start: @task_params[:line_number_start],
- line_number_end: @task_params[:line_number_end],
- lock_version: @lock_version,
- current_user: @current_user
- ).execute
-
- next ::ServiceResponse.error(message: replacement_result.errors, http_status: 422) if replacement_result.error?
-
- delete_result = ::WorkItems::DeleteService.new(
- container: @task.project,
- current_user: @current_user
- ).execute(@task)
-
- if delete_result.error?
- @errors += delete_result.errors
- raise ActiveRecord::Rollback
- end
-
- delete_result
- end
-
- return transaction_result if transaction_result
-
- ::ServiceResponse.error(message: @errors, http_status: 422)
- end
- end
-end
diff --git a/app/services/work_items/task_list_reference_removal_service.rb b/app/services/work_items/task_list_reference_removal_service.rb
deleted file mode 100644
index 843b03906ac..00000000000
--- a/app/services/work_items/task_list_reference_removal_service.rb
+++ /dev/null
@@ -1,56 +0,0 @@
-# frozen_string_literal: true
-
-module WorkItems
- class TaskListReferenceRemovalService
- STALE_OBJECT_MESSAGE = 'Stale work item. Check lock version'
-
- def initialize(work_item:, task:, line_number_start:, line_number_end:, lock_version:, current_user:)
- @work_item = work_item
- @task = task
- @line_number_start = line_number_start
- @line_number_end = line_number_end
- @lock_version = lock_version
- @current_user = current_user
- @task_reference = /#{Regexp.escape(@task.to_reference)}(?!\d)\+/
- end
-
- def execute
- return ::ServiceResponse.error(message: 'line_number_start must be greater than 0') if @line_number_start < 1
- return ::ServiceResponse.error(message: "Work item description can't be blank") if @work_item.description.blank?
-
- if @line_number_end < @line_number_start
- return ::ServiceResponse.error(message: 'line_number_end must be greater or equal to line_number_start')
- end
-
- source_lines = @work_item.description.split("\n")
-
- line_matches_reference = (@line_number_start..@line_number_end).any? do |line_number|
- markdown_line = source_lines[line_number - 1]
-
- if @task_reference.match?(markdown_line)
- markdown_line.sub!(@task_reference, @task.title)
- end
- end
-
- unless line_matches_reference
- return ::ServiceResponse.error(
- message: "Unable to detect a task on lines #{@line_number_start}-#{@line_number_end}"
- )
- end
-
- ::WorkItems::UpdateService.new(
- container: @work_item.project,
- current_user: @current_user,
- params: { description: source_lines.join("\n"), lock_version: @lock_version }
- ).execute(@work_item)
-
- if @work_item.valid?
- ::ServiceResponse.success
- else
- ::ServiceResponse.error(message: @work_item.errors.full_messages)
- end
- rescue ActiveRecord::StaleObjectError
- ::ServiceResponse.error(message: STALE_OBJECT_MESSAGE)
- end
- end
-end