summaryrefslogtreecommitdiff
path: root/app/controllers
diff options
context:
space:
mode:
Diffstat (limited to 'app/controllers')
-rw-r--r--app/controllers/admin/broadcast_messages_controller.rb3
-rw-r--r--app/controllers/admin/groups_controller.rb11
-rw-r--r--app/controllers/admin/impersonation_tokens_controller.rb19
-rw-r--r--app/controllers/admin/runners_controller.rb7
-rw-r--r--app/controllers/application_controller.rb1
-rw-r--r--app/controllers/autocomplete_controller.rb20
-rw-r--r--app/controllers/boards/application_controller.rb23
-rw-r--r--app/controllers/boards/issues_controller.rb162
-rw-r--r--app/controllers/boards/lists_controller.rb103
-rw-r--r--app/controllers/concerns/access_tokens_actions.rb16
-rw-r--r--app/controllers/concerns/authenticates_with_two_factor.rb5
-rw-r--r--app/controllers/concerns/boards_actions.rb59
-rw-r--r--app/controllers/concerns/boards_responses.rb94
-rw-r--r--app/controllers/concerns/import/github_oauth.rb100
-rw-r--r--app/controllers/concerns/issuable_collections_action.rb5
-rw-r--r--app/controllers/concerns/multiple_boards_actions.rb93
-rw-r--r--app/controllers/concerns/preview_markdown.rb16
-rw-r--r--app/controllers/concerns/product_analytics_tracking.rb9
-rw-r--r--app/controllers/concerns/registrations_tracking.rb15
-rw-r--r--app/controllers/concerns/sends_blob.rb22
-rw-r--r--app/controllers/concerns/wiki_actions.rb6
-rw-r--r--app/controllers/groups/application_controller.rb4
-rw-r--r--app/controllers/groups/boards_controller.rb15
-rw-r--r--app/controllers/groups/runners_controller.rb16
-rw-r--r--app/controllers/groups/settings/access_tokens_controller.rb6
-rw-r--r--app/controllers/groups_controller.rb6
-rw-r--r--app/controllers/ide_controller.rb5
-rw-r--r--app/controllers/import/bulk_imports_controller.rb8
-rw-r--r--app/controllers/import/github_controller.rb89
-rw-r--r--app/controllers/import/github_groups_controller.rb57
-rw-r--r--app/controllers/jira_connect/public_keys_controller.rb24
-rw-r--r--app/controllers/oauth/applications_controller.rb1
-rw-r--r--app/controllers/oauth/authorizations_controller.rb1
-rw-r--r--app/controllers/omniauth_callbacks_controller.rb11
-rw-r--r--app/controllers/profiles/personal_access_tokens_controller.rb6
-rw-r--r--app/controllers/profiles/preferences_controller.rb4
-rw-r--r--app/controllers/profiles/two_factor_auths_controller.rb60
-rw-r--r--app/controllers/projects/application_controller.rb4
-rw-r--r--app/controllers/projects/autocomplete_sources_controller.rb7
-rw-r--r--app/controllers/projects/blame_controller.rb3
-rw-r--r--app/controllers/projects/boards_controller.rb18
-rw-r--r--app/controllers/projects/compare_controller.rb11
-rw-r--r--app/controllers/projects/deploy_keys_controller.rb6
-rw-r--r--app/controllers/projects/google_cloud/databases_controller.rb25
-rw-r--r--app/controllers/projects/incident_management/timeline_events_controller.rb16
-rw-r--r--app/controllers/projects/incidents_controller.rb2
-rw-r--r--app/controllers/projects/issues_controller.rb47
-rw-r--r--app/controllers/projects/merge_requests/diffs_controller.rb1
-rw-r--r--app/controllers/projects/merge_requests_controller.rb9
-rw-r--r--app/controllers/projects/milestones_controller.rb14
-rw-r--r--app/controllers/projects/pages_domains_controller.rb19
-rw-r--r--app/controllers/projects/pipeline_schedules_controller.rb5
-rw-r--r--app/controllers/projects/product_analytics_controller.rb4
-rw-r--r--app/controllers/projects/protected_refs_controller.rb1
-rw-r--r--app/controllers/projects/settings/access_tokens_controller.rb6
-rw-r--r--app/controllers/projects/snippets_controller.rb2
-rw-r--r--app/controllers/projects/web_ide_terminals_controller.rb2
-rw-r--r--app/controllers/projects_controller.rb10
-rw-r--r--app/controllers/registrations/welcome_controller.rb7
-rw-r--r--app/controllers/registrations_controller.rb12
-rw-r--r--app/controllers/search_controller.rb4
-rw-r--r--app/controllers/sessions_controller.rb4
-rw-r--r--app/controllers/users/namespace_callouts_controller.rb17
-rw-r--r--app/controllers/users_controller.rb5
64 files changed, 577 insertions, 786 deletions
diff --git a/app/controllers/admin/broadcast_messages_controller.rb b/app/controllers/admin/broadcast_messages_controller.rb
index 251ba9e29f2..edd85414696 100644
--- a/app/controllers/admin/broadcast_messages_controller.rb
+++ b/app/controllers/admin/broadcast_messages_controller.rb
@@ -10,6 +10,9 @@ class Admin::BroadcastMessagesController < Admin::ApplicationController
# rubocop: disable CodeReuse/ActiveRecord
def index
+ push_frontend_feature_flag(:vue_broadcast_messages, current_user)
+ push_frontend_feature_flag(:role_targeted_broadcast_messages, current_user)
+
@broadcast_messages = BroadcastMessage.order(ends_at: :desc).page(params[:page])
@broadcast_message = BroadcastMessage.new
end
diff --git a/app/controllers/admin/groups_controller.rb b/app/controllers/admin/groups_controller.rb
index 2ae0442c005..f3c4244269d 100644
--- a/app/controllers/admin/groups_controller.rb
+++ b/app/controllers/admin/groups_controller.rb
@@ -60,17 +60,6 @@ class Admin::GroupsController < Admin::ApplicationController
end
end
- def members_update
- member_params = params.permit(:user_id, :access_level, :expires_at)
- result = Members::CreateService.new(current_user, member_params.merge(limit: -1, source: @group, invite_source: 'admin-group-page')).execute
-
- if result[:status] == :success
- redirect_to [:admin, @group], notice: _('Users were successfully added.')
- else
- redirect_to [:admin, @group], alert: result[:message]
- end
- end
-
def destroy
Groups::DestroyService.new(@group, current_user).async_execute
diff --git a/app/controllers/admin/impersonation_tokens_controller.rb b/app/controllers/admin/impersonation_tokens_controller.rb
index eb279298baf..9d884478e98 100644
--- a/app/controllers/admin/impersonation_tokens_controller.rb
+++ b/app/controllers/admin/impersonation_tokens_controller.rb
@@ -14,11 +14,10 @@ class Admin::ImpersonationTokensController < Admin::ApplicationController
@impersonation_token = finder.build(impersonation_token_params)
if @impersonation_token.save
- PersonalAccessToken.redis_store!(current_user.id, @impersonation_token.token)
- redirect_to admin_user_impersonation_tokens_path, notice: _("A new impersonation token has been created.")
+ render json: { new_token: @impersonation_token.token,
+ active_access_tokens: active_impersonation_tokens }, status: :ok
else
- set_index_vars
- render :index
+ render json: { errors: @impersonation_token.errors.full_messages }, status: :unprocessable_entity
end
end
@@ -50,19 +49,19 @@ class Admin::ImpersonationTokensController < Admin::ApplicationController
PersonalAccessTokensFinder.new({ user: user, impersonation: true }.merge(options))
end
+ def active_impersonation_tokens
+ tokens = finder(state: 'active', sort: 'expires_at_asc_id_desc').execute
+ ::ImpersonationAccessTokenSerializer.new.represent(tokens)
+ end
+
def impersonation_token_params
params.require(:personal_access_token).permit(:name, :expires_at, :impersonation, scopes: [])
end
- # rubocop: disable CodeReuse/ActiveRecord
def set_index_vars
@scopes = Gitlab::Auth.available_scopes_for(current_user)
@impersonation_token ||= finder.build
- @inactive_impersonation_tokens = finder(state: 'inactive').execute
- @active_impersonation_tokens = finder(state: 'active').execute.order(:expires_at)
-
- @new_impersonation_token = PersonalAccessToken.redis_getdel(current_user.id)
+ @active_impersonation_tokens = active_impersonation_tokens
end
- # rubocop: enable CodeReuse/ActiveRecord
end
diff --git a/app/controllers/admin/runners_controller.rb b/app/controllers/admin/runners_controller.rb
index a0f72f5e58c..96fe0c9331d 100644
--- a/app/controllers/admin/runners_controller.rb
+++ b/app/controllers/admin/runners_controller.rb
@@ -4,13 +4,6 @@ class Admin::RunnersController < Admin::ApplicationController
include RunnerSetupScripts
before_action :runner, except: [:index, :tag_list, :runner_setup_scripts]
- before_action only: [:index] do
- push_frontend_feature_flag(:admin_runners_bulk_delete)
- end
-
- before_action only: [:show] do
- push_frontend_feature_flag(:enforce_runner_token_expires_at)
- end
feature_category :runner
urgency :low
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index 71d9910b4b8..84efb8b0da8 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -16,7 +16,6 @@ class ApplicationController < ActionController::Base
include SessionlessAuthentication
include SessionsHelper
include ConfirmEmailWarning
- include Gitlab::Experimentation::ControllerConcern
include InitializesCurrentUserMode
include Impersonation
include Gitlab::Logging::CloudflareHelper
diff --git a/app/controllers/autocomplete_controller.rb b/app/controllers/autocomplete_controller.rb
index 88592efcec7..45585ab84b4 100644
--- a/app/controllers/autocomplete_controller.rb
+++ b/app/controllers/autocomplete_controller.rb
@@ -25,7 +25,20 @@ class AutocompleteController < ApplicationController
.new(params: params, current_user: current_user, project: project, group: group)
.execute
- render json: UserSerializer.new(params.merge({ current_user: current_user })).represent(users, project: project)
+ presented_users = UserSerializer
+ .new(params.merge({ current_user: current_user }))
+ .represent(users, project: project)
+
+ extra_users = presented_suggested_users
+
+ if extra_users.present?
+ presented_users.reject! do |user|
+ extra_users.any? { |suggested_user| suggested_user[:id] == user[:id] }
+ end
+ presented_users += extra_users
+ end
+
+ render json: presented_users
end
def user
@@ -80,6 +93,11 @@ class AutocompleteController < ApplicationController
def target_branch_params
params.permit(:group_id, :project_id).select { |_, v| v.present? }
end
+
+ # overridden in EE
+ def presented_suggested_users
+ []
+ end
end
AutocompleteController.prepend_mod_with('AutocompleteController')
diff --git a/app/controllers/boards/application_controller.rb b/app/controllers/boards/application_controller.rb
deleted file mode 100644
index 15ef6698472..00000000000
--- a/app/controllers/boards/application_controller.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-# frozen_string_literal: true
-
-module Boards
- class ApplicationController < ::ApplicationController
- respond_to :json
-
- rescue_from ActiveRecord::RecordNotFound, with: :record_not_found
-
- private
-
- def board
- @board ||= Board.find(params[:board_id])
- end
-
- def board_parent
- @board_parent ||= board.resource_parent
- end
-
- def record_not_found(exception)
- render json: { error: exception.message }, status: :not_found
- end
- end
-end
diff --git a/app/controllers/boards/issues_controller.rb b/app/controllers/boards/issues_controller.rb
deleted file mode 100644
index 5028544795c..00000000000
--- a/app/controllers/boards/issues_controller.rb
+++ /dev/null
@@ -1,162 +0,0 @@
-# frozen_string_literal: true
-
-module Boards
- class IssuesController < Boards::ApplicationController
- # This is the maximum amount of issues which can be moved by one request to
- # bulk_move for now. This is temporary and might be removed in future by
- # introducing an alternative (async?) approach.
- # (related: https://gitlab.com/groups/gitlab-org/-/epics/382)
- MAX_MOVE_ISSUES_COUNT = 50
-
- include BoardsResponses
- include ControllerWithCrossProjectAccessCheck
-
- requires_cross_project_access if: -> { board&.group_board? }
-
- before_action :disable_query_limiting, only: [:bulk_move]
- before_action :authorize_read_issue, only: [:index]
- before_action :authorize_create_issue, only: [:create]
- before_action :authorize_update_issue, only: [:update]
- skip_before_action :authenticate_user!, only: [:index]
- before_action :validate_id_list, only: [:bulk_move]
- before_action :can_move_issues?, only: [:bulk_move]
-
- feature_category :team_planning
- urgency :low
-
- def index
- list_service = Boards::Issues::ListService.new(board_parent, current_user, filter_params)
- issues = issues_from(list_service)
-
- ::Boards::Issues::ListService.initialize_relative_positions(board, current_user, issues)
-
- render_issues(issues, list_service.metadata)
- end
-
- def create
- service = Boards::Issues::CreateService.new(board_parent, project, current_user, issue_params)
- issue = service.execute
-
- if issue.valid?
- render json: serialize_as_json(issue)
- else
- render json: issue.errors, status: :unprocessable_entity
- end
- end
-
- def bulk_move
- service = Boards::Issues::MoveService.new(board_parent, current_user, move_params(true))
-
- issues = Issue.find(params[:ids])
-
- render json: service.execute_multiple(issues)
- end
-
- def update
- service = Boards::Issues::MoveService.new(board_parent, current_user, move_params)
-
- if service.execute(issue)
- head :ok
- else
- head :unprocessable_entity
- end
- end
-
- private
-
- def issues_from(list_service)
- issues = list_service.execute
- issues.page(params[:page]).per(params[:per] || 20)
- .without_count
- .preload(associations_to_preload) # rubocop: disable CodeReuse/ActiveRecord
- .load
- end
-
- def associations_to_preload
- [
- :milestone,
- :assignees,
- project: [
- :route,
- {
- namespace: [:route]
- }
- ],
- labels: [:priorities],
- notes: [:award_emoji, :author]
- ]
- end
-
- def can_move_issues?
- head(:forbidden) unless can?(current_user, :admin_issue, board)
- end
-
- def serializer_options(issues)
- {}
- end
-
- def render_issues(issues, metadata)
- data = { issues: serialize_as_json(issues, opts: serializer_options(issues)) }
- data.merge!(metadata)
-
- render json: data
- end
-
- def issue
- @issue ||= issues_finder.find(params[:id])
- end
-
- def filter_params
- params.permit(*Boards::Issues::ListService.valid_params).merge(board_id: params[:board_id], id: params[:list_id])
- .reject { |_, value| value.nil? }
- end
-
- def issues_finder
- if board.group_board?
- IssuesFinder.new(current_user, group_id: board_parent.id)
- else
- IssuesFinder.new(current_user, project_id: board_parent.id)
- end
- end
-
- def project
- @project ||= if board.group_board?
- Project.find(issue_params[:project_id])
- else
- board_parent
- end
- end
-
- def move_params(multiple = false)
- id_param = multiple ? :ids : :id
- params.permit(id_param, :board_id, :from_list_id, :to_list_id, :move_before_id, :move_after_id)
- end
-
- def issue_params
- params.require(:issue)
- .permit(:title, :milestone_id, :project_id)
- .merge(board_id: params[:board_id], list_id: params[:list_id])
- end
-
- def serializer
- IssueSerializer.new(current_user: current_user)
- end
-
- def serialize_as_json(resource, opts: {})
- opts.merge!(include_full_project_path: board.group_board?, serializer: 'board')
-
- serializer.represent(resource, opts)
- end
-
- def disable_query_limiting
- Gitlab::QueryLimiting.disable!('https://gitlab.com/gitlab-org/gitlab/issues/35174')
- end
-
- def validate_id_list
- head(:bad_request) unless params[:ids].is_a?(Array)
- head(:unprocessable_entity) if params[:ids].size > MAX_MOVE_ISSUES_COUNT
- end
- end
-end
-
-Boards::IssuesController.prepend_mod_with('Boards::IssuesController')
diff --git a/app/controllers/boards/lists_controller.rb b/app/controllers/boards/lists_controller.rb
deleted file mode 100644
index c3b5a887920..00000000000
--- a/app/controllers/boards/lists_controller.rb
+++ /dev/null
@@ -1,103 +0,0 @@
-# frozen_string_literal: true
-
-module Boards
- class ListsController < Boards::ApplicationController
- include BoardsResponses
-
- before_action :authorize_admin_list, only: [:create, :destroy, :generate]
- before_action :authorize_read_list, only: [:index]
- skip_before_action :authenticate_user!, only: [:index]
-
- feature_category :team_planning
- urgency :low
-
- def index
- lists = Boards::Lists::ListService.new(board.resource_parent, current_user).execute(board)
-
- List.preload_preferences_for_user(lists, current_user)
-
- render json: serialize_as_json(lists)
- end
-
- def create
- response = Boards::Lists::CreateService.new(board.resource_parent, current_user, create_list_params).execute(board)
-
- if response.success?
- render json: serialize_as_json(response.payload[:list])
- else
- render json: { errors: response.errors }, status: :unprocessable_entity
- end
- end
-
- def update
- list = board.lists.find(params[:id])
- service = Boards::Lists::UpdateService.new(board_parent, current_user, update_list_params)
- result = service.execute(list)
-
- if result.success?
- head :ok
- else
- head result.http_status
- end
- end
-
- def destroy
- list = board.lists.destroyable.find(params[:id])
- service = Boards::Lists::DestroyService.new(board_parent, current_user)
-
- if service.execute(list).success?
- head :ok
- else
- head :unprocessable_entity
- end
- end
-
- def generate
- service = Boards::Lists::GenerateService.new(board_parent, current_user)
-
- if service.execute(board)
- lists = board.lists.movable.preload_associated_models
-
- List.preload_preferences_for_user(lists, current_user)
-
- render json: serialize_as_json(lists)
- else
- head :unprocessable_entity
- end
- end
-
- private
-
- def list_creation_attrs
- %i[label_id]
- end
-
- def list_update_attrs
- %i[collapsed position]
- end
-
- def create_list_params
- params.require(:list).permit(list_creation_attrs)
- end
-
- def update_list_params
- params.require(:list).permit(list_update_attrs)
- end
-
- def serialize_as_json(resource)
- resource.as_json(serialization_attrs)
- end
-
- def serialization_attrs
- {
- only: [:id, :list_type, :position],
- methods: [:title],
- label: true,
- collapsed: true,
- current_user: current_user
- }
- end
- end
-end
-
-Boards::ListsController.prepend_mod_with('Boards::ListsController')
diff --git a/app/controllers/concerns/access_tokens_actions.rb b/app/controllers/concerns/access_tokens_actions.rb
index 451841c43bb..6e43be5594d 100644
--- a/app/controllers/concerns/access_tokens_actions.rb
+++ b/app/controllers/concerns/access_tokens_actions.rb
@@ -22,11 +22,10 @@ module AccessTokensActions
if token_response.success?
@resource_access_token = token_response.payload[:access_token]
- PersonalAccessToken.redis_store!(key_identity, @resource_access_token.token)
-
- redirect_to resource_access_tokens_path, notice: _("Your new access token has been created.")
+ render json: { new_token: @resource_access_token.token,
+ active_access_tokens: active_resource_access_tokens }, status: :ok
else
- redirect_to resource_access_tokens_path, alert: _("Failed to create new access token: %{token_response_message}") % { token_response_message: token_response.message }
+ render json: { errors: token_response.errors }, status: :unprocessable_entity
end
end
# rubocop:enable Gitlab/ModuleWithInstanceVariables
@@ -63,12 +62,15 @@ module AccessTokensActions
resource.members.load
@scopes = Gitlab::Auth.resource_bot_scopes
- @active_resource_access_tokens = finder(state: 'active').execute.preload_users
- @inactive_resource_access_tokens = finder(state: 'inactive', sort: 'expires_at_asc').execute.preload_users
- @new_resource_access_token = PersonalAccessToken.redis_getdel(key_identity)
+ @active_resource_access_tokens = active_resource_access_tokens
end
# rubocop:enable Gitlab/ModuleWithInstanceVariables
+ def active_resource_access_tokens
+ tokens = finder(state: 'active', sort: 'expires_at_asc_id_desc').execute.preload_users
+ represent(tokens)
+ end
+
def finder(options = {})
PersonalAccessTokensFinder.new({ user: bot_users, impersonation: false }.merge(options))
end
diff --git a/app/controllers/concerns/authenticates_with_two_factor.rb b/app/controllers/concerns/authenticates_with_two_factor.rb
index 4228a93d310..fbaa754124c 100644
--- a/app/controllers/concerns/authenticates_with_two_factor.rb
+++ b/app/controllers/concerns/authenticates_with_two_factor.rb
@@ -89,6 +89,7 @@ module AuthenticatesWithTwoFactor
user.save!
sign_in(user, message: :two_factor_authenticated, event: :authentication)
else
+ send_two_factor_otp_attempt_failed_email(user)
handle_two_factor_failure(user, 'OTP', _('Invalid two-factor code.'))
end
end
@@ -158,6 +159,10 @@ module AuthenticatesWithTwoFactor
prompt_for_two_factor(user)
end
+ def send_two_factor_otp_attempt_failed_email(user)
+ user.notification_service.two_factor_otp_attempt_failed(user, request.remote_ip)
+ end
+
def log_failed_two_factor(user, method)
# overridden in EE
end
diff --git a/app/controllers/concerns/boards_actions.rb b/app/controllers/concerns/boards_actions.rb
index 2f9edfad12d..42bf6c68aa7 100644
--- a/app/controllers/concerns/boards_actions.rb
+++ b/app/controllers/concerns/boards_actions.rb
@@ -5,41 +5,38 @@ module BoardsActions
extend ActiveSupport::Concern
included do
- include BoardsResponses
-
before_action :authorize_read_board!, only: [:index, :show]
- before_action :boards, only: :index
- before_action :board, only: :show
+ before_action :redirect_to_recent_board, only: [:index]
+ before_action :board, only: [:index, :show]
before_action :push_licensed_features, only: [:index, :show]
end
def index
- respond_with_boards
+ # if no board exists, create one
+ @board = board_create_service.execute.payload unless board # rubocop:disable Gitlab/ModuleWithInstanceVariables
end
def show
- # Add / update the board in the recent visits table
- board_visit_service.new(parent, current_user).execute(board) if request.format.html?
+ return render_404 unless board
- respond_with_board
+ # Add / update the board in the recent visits table
+ board_visit_service.new(parent, current_user).execute(board)
end
private
- # Noop on FOSS
- def push_licensed_features
+ def redirect_to_recent_board
+ return if !parent.multiple_issue_boards_available? || !latest_visited_board
+
+ redirect_to board_path(latest_visited_board.board)
end
- def boards
- strong_memoize(:boards) do
- existing_boards = boards_finder.execute
- if existing_boards.any?
- existing_boards
- else
- # if no board exists, create one
- [board_create_service.execute.payload]
- end
- end
+ def latest_visited_board
+ @latest_visited_board ||= Boards::VisitsFinder.new(parent, current_user).latest
+ end
+
+ # Noop on FOSS
+ def push_licensed_features
end
def board
@@ -48,20 +45,26 @@ module BoardsActions
end
end
- def board_type
- board_klass.to_type
- end
-
def board_visit_service
Boards::Visits::CreateService
end
- def serializer
- BoardSerializer.new(current_user: current_user)
+ def parent
+ strong_memoize(:parent) do
+ group? ? group : project
+ end
+ end
+
+ def board_path(board)
+ if group?
+ group_board_path(parent, board)
+ else
+ project_board_path(parent, board)
+ end
end
- def serialize_as_json(resource)
- serializer.represent(resource, serializer: 'board', include_full_project_path: board.group_board?)
+ def group?
+ instance_variable_defined?(:@group)
end
end
diff --git a/app/controllers/concerns/boards_responses.rb b/app/controllers/concerns/boards_responses.rb
deleted file mode 100644
index eb7392648a1..00000000000
--- a/app/controllers/concerns/boards_responses.rb
+++ /dev/null
@@ -1,94 +0,0 @@
-# frozen_string_literal: true
-
-module BoardsResponses
- include Gitlab::Utils::StrongMemoize
-
- # Overridden on EE module
- def board_params
- params.require(:board).permit(:name)
- end
-
- def parent
- strong_memoize(:parent) do
- group? ? group : project
- end
- end
-
- def boards_path
- if group?
- group_boards_path(parent)
- else
- project_boards_path(parent)
- end
- end
-
- def board_path(board)
- if group?
- group_board_path(parent, board)
- else
- project_board_path(parent, board)
- end
- end
-
- def group?
- instance_variable_defined?(:@group)
- end
-
- def authorize_read_list
- authorize_action_for!(board, :read_issue_board_list)
- end
-
- def authorize_read_issue
- authorize_action_for!(board, :read_issue)
- end
-
- def authorize_update_issue
- authorize_action_for!(issue, :admin_issue)
- end
-
- def authorize_create_issue
- list = List.find(issue_params[:list_id])
- action = list.backlog? ? :create_issue : :admin_issue
-
- authorize_action_for!(project, action)
- end
-
- def authorize_admin_list
- authorize_action_for!(board, :admin_issue_board_list)
- end
-
- def authorize_action_for!(resource, ability)
- return render_403 unless can?(current_user, ability, resource)
- end
-
- def respond_with_boards
- respond_with(@boards) # rubocop:disable Gitlab/ModuleWithInstanceVariables
- end
-
- def respond_with_board
- # rubocop:disable Gitlab/ModuleWithInstanceVariables
- return render_404 unless @board
-
- respond_with(@board)
- # rubocop:enable Gitlab/ModuleWithInstanceVariables
- end
-
- def serialize_as_json(resource)
- serializer.represent(resource).as_json
- end
-
- def respond_with(resource)
- respond_to do |format|
- format.html
- format.json do
- render json: serialize_as_json(resource)
- end
- end
- end
-
- def serializer
- BoardSerializer.new
- end
-end
-
-BoardsResponses.prepend_mod_with('BoardsResponses')
diff --git a/app/controllers/concerns/import/github_oauth.rb b/app/controllers/concerns/import/github_oauth.rb
new file mode 100644
index 00000000000..d53022aabf2
--- /dev/null
+++ b/app/controllers/concerns/import/github_oauth.rb
@@ -0,0 +1,100 @@
+# frozen_string_literal: true
+
+module Import
+ module GithubOauth
+ extend ActiveSupport::Concern
+
+ OAuthConfigMissingError = Class.new(StandardError)
+
+ included do
+ rescue_from OAuthConfigMissingError, with: :missing_oauth_config
+ end
+
+ private
+
+ def provider_auth
+ return if session[access_token_key].present?
+
+ go_to_provider_for_permissions unless ci_cd_only?
+ end
+
+ def ci_cd_only?
+ %w[1 true].include?(params[:ci_cd_only])
+ end
+
+ def go_to_provider_for_permissions
+ redirect_to authorize_url
+ end
+
+ def oauth_client
+ raise OAuthConfigMissingError unless oauth_config
+
+ oauth_client_from_config
+ end
+
+ def oauth_client_from_config
+ @oauth_client_from_config ||= ::OAuth2::Client.new(
+ oauth_config.app_id,
+ oauth_config.app_secret,
+ oauth_options.merge(ssl: { verify: oauth_config['verify_ssl'] })
+ )
+ end
+
+ def oauth_config
+ @oauth_config ||= Gitlab::Auth::OAuth::Provider.config_for('github')
+ end
+
+ def oauth_options
+ return unless oauth_config
+
+ oauth_config.dig('args', 'client_options').deep_symbolize_keys
+ end
+
+ def authorize_url
+ state = SecureRandom.base64(64)
+ session[auth_state_key] = state
+ if Feature.enabled?(:remove_legacy_github_client)
+ oauth_client.auth_code.authorize_url(
+ redirect_uri: callback_import_url,
+ scope: 'repo, user, user:email',
+ state: state
+ )
+ else
+ client.authorize_url(callback_import_url, state)
+ end
+ end
+
+ def get_token(code)
+ if Feature.enabled?(:remove_legacy_github_client)
+ oauth_client.auth_code.get_token(code).token
+ else
+ client.get_token(code)
+ end
+ end
+
+ def missing_oauth_config
+ session[access_token_key] = nil
+
+ message = _('Missing OAuth configuration for GitHub.')
+
+ respond_to do |format|
+ format.json do
+ render json: { errors: message }, status: :unauthorized
+ end
+
+ format.any do
+ redirect_to new_import_url,
+ alert: message
+ end
+ end
+ end
+
+ def callback_import_url
+ public_send("users_import_#{provider_name}_callback_url", extra_import_params.merge({ namespace_id: params[:namespace_id] })) # rubocop:disable GitlabSecurity/PublicSend
+ end
+
+ def extra_import_params
+ {}
+ end
+ end
+end
diff --git a/app/controllers/concerns/issuable_collections_action.rb b/app/controllers/concerns/issuable_collections_action.rb
index 96cf6021ea9..e03d1de7bf9 100644
--- a/app/controllers/concerns/issuable_collections_action.rb
+++ b/app/controllers/concerns/issuable_collections_action.rb
@@ -59,9 +59,12 @@ module IssuableCollectionsAction
end
def finder_options
+ issue_types = Issue::TYPES_FOR_LIST
+ issue_types = issue_types.excluding('task') unless Feature.enabled?(:work_items)
+
super.merge(
non_archived: true,
- issue_types: Issue::TYPES_FOR_LIST
+ issue_types: issue_types
)
end
end
diff --git a/app/controllers/concerns/multiple_boards_actions.rb b/app/controllers/concerns/multiple_boards_actions.rb
deleted file mode 100644
index 685c93fc2a2..00000000000
--- a/app/controllers/concerns/multiple_boards_actions.rb
+++ /dev/null
@@ -1,93 +0,0 @@
-# frozen_string_literal: true
-
-module MultipleBoardsActions
- include Gitlab::Utils::StrongMemoize
- extend ActiveSupport::Concern
-
- included do
- include BoardsActions
-
- before_action :redirect_to_recent_board, only: [:index]
- before_action :authenticate_user!, only: [:recent]
- before_action :authorize_create_board!, only: [:create]
- before_action :authorize_admin_board!, only: [:create, :update, :destroy]
- end
-
- def recent
- recent_visits = ::Boards::VisitsFinder.new(parent, current_user).latest(Board::RECENT_BOARDS_SIZE)
- recent_boards = recent_visits.map(&:board)
-
- render json: serialize_as_json(recent_boards)
- end
-
- def create
- response = Boards::CreateService.new(parent, current_user, board_params).execute
-
- respond_to do |format|
- format.json do
- board = response.payload
-
- if response.success?
- extra_json = { board_path: board_path(board) }
- render json: serialize_as_json(board).merge(extra_json)
- else
- render json: board.errors, status: :unprocessable_entity
- end
- end
- end
- end
-
- def update
- service = Boards::UpdateService.new(parent, current_user, board_params)
-
- respond_to do |format|
- format.json do
- if service.execute(board)
- extra_json = { board_path: board_path(board) }
- render json: serialize_as_json(board).merge(extra_json)
- else
- render json: board.errors, status: :unprocessable_entity
- end
- end
- end
- end
-
- def destroy
- service = Boards::DestroyService.new(parent, current_user)
- service.execute(board)
-
- respond_to do |format|
- format.json { head :ok }
- format.html { redirect_to boards_path, status: :found }
- end
- end
-
- private
-
- def redirect_to_recent_board
- return unless board_type == Board.to_type
- return if request.format.json? || !parent.multiple_issue_boards_available? || !latest_visited_board
-
- redirect_to board_path(latest_visited_board.board)
- end
-
- def latest_visited_board
- @latest_visited_board ||= Boards::VisitsFinder.new(parent, current_user).latest
- end
-
- def authorize_create_board!
- check_multiple_group_issue_boards_available! if group?
- end
-
- def authorize_admin_board!
- return render_404 unless can?(current_user, :admin_issue_board, parent)
- end
-
- def serializer
- BoardSerializer.new(current_user: current_user)
- end
-
- def serialize_as_json(resource)
- serializer.represent(resource, serializer: 'board', include_full_project_path: board.group_board?)
- end
-end
diff --git a/app/controllers/concerns/preview_markdown.rb b/app/controllers/concerns/preview_markdown.rb
index 1d2f9e31c46..79b3fa28660 100644
--- a/app/controllers/concerns/preview_markdown.rb
+++ b/app/controllers/concerns/preview_markdown.rb
@@ -26,16 +26,24 @@ module PreviewMarkdown
}
end
+ def timeline_events_filter_params
+ {
+ issuable_reference_expansion_enabled: true,
+ pipeline: :'incident_management/timeline_event'
+ }
+ end
+
def markdown_service_params
params
end
def markdown_context_params
case controller_name
- when 'wikis' then { pipeline: :wiki, wiki: wiki, page_slug: params[:id] }
- when 'snippets' then { skip_project_check: true }
- when 'groups' then { group: group }
- when 'projects' then projects_filter_params
+ when 'wikis' then { pipeline: :wiki, wiki: wiki, page_slug: params[:id] }
+ when 'snippets' then { skip_project_check: true }
+ when 'groups' then { group: group }
+ when 'projects' then projects_filter_params
+ when 'timeline_events' then timeline_events_filter_params
else {}
end.merge(requested_path: params[:path], ref: params[:ref])
end
diff --git a/app/controllers/concerns/product_analytics_tracking.rb b/app/controllers/concerns/product_analytics_tracking.rb
index 8e936782e5a..4f96cc5c895 100644
--- a/app/controllers/concerns/product_analytics_tracking.rb
+++ b/app/controllers/concerns/product_analytics_tracking.rb
@@ -29,7 +29,13 @@ module ProductAnalyticsTracking
track_unique_redis_hll_event(name, &block) if destinations.include?(:redis_hll)
if destinations.include?(:snowplow) && event_enabled?(name)
- Gitlab::Tracking.event(self.class.to_s, name, namespace: tracking_namespace_source, user: current_user)
+ Gitlab::Tracking.event(
+ self.class.to_s,
+ name,
+ namespace: tracking_namespace_source,
+ user: current_user,
+ context: [Gitlab::Tracking::ServicePingContext.new(data_source: :redis_hll, event: name).to_context]
+ )
end
end
@@ -49,6 +55,7 @@ module ProductAnalyticsTracking
user: current_user,
property: name,
label: label,
+ context: [Gitlab::Tracking::ServicePingContext.new(data_source: :redis_hll, event: name).to_context],
**optional_arguments
)
end
diff --git a/app/controllers/concerns/registrations_tracking.rb b/app/controllers/concerns/registrations_tracking.rb
new file mode 100644
index 00000000000..14743349c1a
--- /dev/null
+++ b/app/controllers/concerns/registrations_tracking.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module RegistrationsTracking
+ extend ActiveSupport::Concern
+
+ included do
+ helper_method :glm_tracking_params
+ end
+
+ private
+
+ def glm_tracking_params
+ params.permit(:glm_source, :glm_content)
+ end
+end
diff --git a/app/controllers/concerns/sends_blob.rb b/app/controllers/concerns/sends_blob.rb
index 381f2eba352..3cf260c9f1b 100644
--- a/app/controllers/concerns/sends_blob.rb
+++ b/app/controllers/concerns/sends_blob.rb
@@ -27,12 +27,14 @@ module SendsBlob
private
def cached_blob?(blob, allow_caching: false)
- stale = stale?(etag: blob.id) # The #stale? method sets cache headers.
-
- # Because we are opinionated we set the cache headers ourselves.
- response.cache_control[:public] = allow_caching
+ stale =
+ if Feature.enabled?(:improve_blobs_cache_headers)
+ stale?(strong_etag: blob.id)
+ else
+ stale?(etag: blob.id)
+ end
- response.cache_control[:max_age] =
+ max_age =
if @ref && @commit && @ref == @commit.id # rubocop:disable Gitlab/ModuleWithInstanceVariables
# This is a link to a commit by its commit SHA. That means that the blob
# is immutable. The only reason to invalidate the cache is if the commit
@@ -44,6 +46,16 @@ module SendsBlob
Blob::CACHE_TIME
end
+ # Because we are opinionated we set the cache headers ourselves.
+ if Feature.enabled?(:improve_blobs_cache_headers)
+ expires_in(max_age,
+ public: allow_caching, must_revalidate: true, stale_if_error: 5.minutes,
+ stale_while_revalidate: 1.minute, 's-maxage': 1.minute)
+ else
+ response.cache_control[:public] = allow_caching
+ response.cache_control[:max_age] = max_age
+ end
+
!stale
end
diff --git a/app/controllers/concerns/wiki_actions.rb b/app/controllers/concerns/wiki_actions.rb
index 83447744013..2b781c528ad 100644
--- a/app/controllers/concerns/wiki_actions.rb
+++ b/app/controllers/concerns/wiki_actions.rb
@@ -209,9 +209,7 @@ module WikiActions
def wiki
strong_memoize(:wiki) do
wiki = Wiki.for_container(container, current_user)
-
- # Call #wiki to make sure the Wiki Repo is initialized
- wiki.wiki
+ wiki.create_wiki_repository
wiki
end
@@ -242,7 +240,7 @@ module WikiActions
def wiki_pages
strong_memoize(:wiki_pages) do
Kaminari.paginate_array(
- wiki.list_pages(sort: params[:sort], direction: params[:direction])
+ wiki.list_pages(direction: params[:direction])
).page(params[:page])
end
end
diff --git a/app/controllers/groups/application_controller.rb b/app/controllers/groups/application_controller.rb
index aec3247f4b2..f8cfa996447 100644
--- a/app/controllers/groups/application_controller.rb
+++ b/app/controllers/groups/application_controller.rb
@@ -67,6 +67,10 @@ class Groups::ApplicationController < ApplicationController
end
end
+ def authorize_billings_page!
+ render_404 unless can?(current_user, :read_billing, group)
+ end
+
def authorize_read_group_member!
unless can?(current_user, :read_group_member, group)
render_403
diff --git a/app/controllers/groups/boards_controller.rb b/app/controllers/groups/boards_controller.rb
index e64d838b7d1..14b70df0feb 100644
--- a/app/controllers/groups/boards_controller.rb
+++ b/app/controllers/groups/boards_controller.rb
@@ -5,7 +5,6 @@ class Groups::BoardsController < Groups::ApplicationController
include RecordUserLastActivity
include Gitlab::Utils::StrongMemoize
- before_action :assign_endpoint_vars
before_action do
push_frontend_feature_flag(:board_multi_select, group)
push_frontend_feature_flag(:realtime_labels, group)
@@ -20,16 +19,6 @@ class Groups::BoardsController < Groups::ApplicationController
private
- def board_klass
- Board
- end
-
- def boards_finder
- strong_memoize :boards_finder do
- Boards::BoardsFinder.new(parent, current_user)
- end
- end
-
def board_finder
strong_memoize :board_finder do
Boards::BoardsFinder.new(parent, current_user, board_id: params[:id])
@@ -42,10 +31,6 @@ class Groups::BoardsController < Groups::ApplicationController
end
end
- def assign_endpoint_vars
- @boards_endpoint = group_boards_path(group)
- end
-
def authorize_read_board!
access_denied! unless can?(current_user, :read_issue_board, group)
end
diff --git a/app/controllers/groups/runners_controller.rb b/app/controllers/groups/runners_controller.rb
index 652f12e34ba..18b055b3f05 100644
--- a/app/controllers/groups/runners_controller.rb
+++ b/app/controllers/groups/runners_controller.rb
@@ -2,13 +2,9 @@
class Groups::RunnersController < Groups::ApplicationController
before_action :authorize_read_group_runners!, only: [:index, :show]
- before_action :authorize_admin_group_runners!, only: [:edit, :update, :destroy, :pause, :resume]
+ before_action :authorize_update_runner!, only: [:edit, :update, :destroy, :pause, :resume]
before_action :runner, only: [:edit, :update, :destroy, :pause, :resume, :show]
- before_action only: [:show] do
- push_frontend_feature_flag(:enforce_runner_token_expires_at)
- end
-
feature_category :runner
urgency :low
@@ -37,7 +33,9 @@ class Groups::RunnersController < Groups::ApplicationController
private
def runner
- @runner ||= Ci::RunnersFinder.new(current_user: current_user, params: { group: @group }).execute
+ group_params = { group: @group, membership: :all_available }
+
+ @runner ||= Ci::RunnersFinder.new(current_user: current_user, params: group_params).execute
.except(:limit, :offset)
.find(params[:id])
end
@@ -45,6 +43,12 @@ class Groups::RunnersController < Groups::ApplicationController
def runner_params
params.require(:runner).permit(Ci::Runner::FORM_EDITABLE)
end
+
+ def authorize_update_runner!
+ return if can?(current_user, :admin_group_runners, group) && can?(current_user, :update_runner, runner)
+
+ render_404
+ end
end
Groups::RunnersController.prepend_mod
diff --git a/app/controllers/groups/settings/access_tokens_controller.rb b/app/controllers/groups/settings/access_tokens_controller.rb
index b9ab2e008cc..f01b2b779e3 100644
--- a/app/controllers/groups/settings/access_tokens_controller.rb
+++ b/app/controllers/groups/settings/access_tokens_controller.rb
@@ -13,6 +13,12 @@ module Groups
def resource_access_tokens_path
group_settings_access_tokens_path
end
+
+ private
+
+ def represent(tokens)
+ ::GroupAccessTokenSerializer.new.represent(tokens, group: resource)
+ end
end
end
end
diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb
index 9316204d89c..269342a6c22 100644
--- a/app/controllers/groups_controller.rb
+++ b/app/controllers/groups_controller.rb
@@ -81,9 +81,9 @@ class GroupsController < Groups::ApplicationController
successful_creation_hooks
notice = if @group.chat_team.present?
- "Group '#{@group.name}' and its Mattermost team were successfully created."
+ format(_("Group %{group_name} and its Mattermost team were successfully created."), group_name: @group.name)
else
- "Group '#{@group.name}' was successfully created."
+ format(_("Group %{group_name} was successfully created."), group_name: @group.name)
end
redirect_to @group, notice: notice
@@ -393,7 +393,7 @@ class GroupsController < Groups::ApplicationController
end
def captcha_enabled?
- Gitlab::Recaptcha.enabled? && Feature.enabled?(:recaptcha_on_top_level_group_creation, type: :ops)
+ helpers.recaptcha_enabled? && Feature.enabled?(:recaptcha_on_top_level_group_creation, type: :ops)
end
def captcha_required?
diff --git a/app/controllers/ide_controller.rb b/app/controllers/ide_controller.rb
index 58a985cbc46..fcf6871d137 100644
--- a/app/controllers/ide_controller.rb
+++ b/app/controllers/ide_controller.rb
@@ -1,8 +1,6 @@
# frozen_string_literal: true
class IdeController < ApplicationController
- layout 'fullscreen'
-
include ClientsidePreviewCSP
include StaticObjectExternalStorageCSP
include Gitlab::Utils::StrongMemoize
@@ -13,7 +11,6 @@ class IdeController < ApplicationController
push_frontend_feature_flag(:build_service_proxy)
push_frontend_feature_flag(:schema_linting)
push_frontend_feature_flag(:reject_unsigned_commits_by_gitlab)
- push_frontend_feature_flag(:vscode_web_ide, current_user)
define_index_vars
end
@@ -28,6 +25,8 @@ class IdeController < ApplicationController
Gitlab::Tracking.event(self.class.to_s, 'web_ide_views',
namespace: project&.namespace, user: current_user)
end
+
+ render layout: 'fullscreen', locals: { minimal: helpers.use_new_web_ide? }
end
private
diff --git a/app/controllers/import/bulk_imports_controller.rb b/app/controllers/import/bulk_imports_controller.rb
index 893c0b6ac54..655fc7854fe 100644
--- a/app/controllers/import/bulk_imports_controller.rb
+++ b/app/controllers/import/bulk_imports_controller.rb
@@ -47,6 +47,8 @@ class Import::BulkImportsController < ApplicationController
end
def create
+ return render json: { success: false }, status: :unprocessable_entity unless valid_create_params?
+
responses = create_params.map do |entry|
if entry[:destination_name]
entry[:destination_slug] ||= entry[:destination_name]
@@ -102,6 +104,10 @@ class Import::BulkImportsController < ApplicationController
params.permit(bulk_import: bulk_import_params)[:bulk_import]
end
+ def valid_create_params?
+ create_params.all? { _1[:source_type] == 'group_entity' }
+ end
+
def bulk_import_params
%i[
source_type
@@ -113,7 +119,7 @@ class Import::BulkImportsController < ApplicationController
end
def ensure_group_import_enabled
- render_404 unless Feature.enabled?(:bulk_import)
+ render_404 unless ::BulkImports::Features.enabled?
end
def access_token_key
diff --git a/app/controllers/import/github_controller.rb b/app/controllers/import/github_controller.rb
index 8a3e6809736..92763e09ba3 100644
--- a/app/controllers/import/github_controller.rb
+++ b/app/controllers/import/github_controller.rb
@@ -5,14 +5,12 @@ class Import::GithubController < Import::BaseController
include ImportHelper
include ActionView::Helpers::SanitizeHelper
+ include Import::GithubOauth
before_action :verify_import_enabled
before_action :provider_auth, only: [:status, :realtime_changes, :create]
before_action :expire_etag_cache, only: [:status, :create]
- OAuthConfigMissingError = Class.new(StandardError)
-
- rescue_from OAuthConfigMissingError, with: :missing_oauth_config
rescue_from Octokit::Unauthorized, with: :provider_unauthorized
rescue_from Octokit::TooManyRequests, with: :provider_rate_limit
rescue_from Gitlab::GithubImport::RateLimitError, with: :rate_limit_threshold_exceeded
@@ -73,6 +71,17 @@ class Import::GithubController < Import::BaseController
}
end
+ def cancel
+ project = Project.imported_from(provider_name).find(params[:project_id])
+ result = Import::Github::CancelProjectImportService.new(project, current_user).execute
+
+ if result[:status] == :success
+ render json: serialized_imported_projects(result[:project])
+ else
+ render json: { errors: result[:message] }, status: result[:http_status]
+ end
+ end
+
protected
override :importable_repos
@@ -104,7 +113,7 @@ class Import::GithubController < Import::BaseController
end
def permitted_import_params
- [:repo_id, :new_name, :target_namespace]
+ [:repo_id, :new_name, :target_namespace, { optional_stages: {} }]
end
def serialized_imported_projects(projects = already_added_projects)
@@ -143,58 +152,10 @@ class Import::GithubController < Import::BaseController
@filter = @filter&.tr(' ', '')&.tr(':', '')
end
- def oauth_client
- raise OAuthConfigMissingError unless oauth_config
-
- @oauth_client ||= ::OAuth2::Client.new(
- oauth_config.app_id,
- oauth_config.app_secret,
- oauth_options.merge(ssl: { verify: oauth_config['verify_ssl'] })
- )
- end
-
- def oauth_config
- @oauth_config ||= Gitlab::Auth::OAuth::Provider.config_for('github')
- end
-
- def oauth_options
- if oauth_config
- oauth_config.dig('args', 'client_options').deep_symbolize_keys
- else
- OmniAuth::Strategies::GitHub.default_options[:client_options].symbolize_keys
- end
- end
-
- def authorize_url
- state = SecureRandom.base64(64)
- session[auth_state_key] = state
- if Feature.enabled?(:remove_legacy_github_client)
- oauth_client.auth_code.authorize_url(
- redirect_uri: callback_import_url,
- scope: 'repo, user, user:email',
- state: state
- )
- else
- client.authorize_url(callback_import_url, state)
- end
- end
-
- def get_token(code)
- if Feature.enabled?(:remove_legacy_github_client)
- oauth_client.auth_code.get_token(code).token
- else
- client.get_token(code)
- end
- end
-
def verify_import_enabled
render_404 unless import_enabled?
end
- def go_to_provider_for_permissions
- redirect_to authorize_url
- end
-
def import_enabled?
__send__("#{provider_name}_import_enabled?") # rubocop:disable GitlabSecurity/PublicSend
end
@@ -211,10 +172,6 @@ class Import::GithubController < Import::BaseController
public_send("status_import_#{provider_name}_url", extra_import_params.merge({ namespace_id: params[:namespace_id].presence })) # rubocop:disable GitlabSecurity/PublicSend
end
- def callback_import_url
- public_send("users_import_#{provider_name}_callback_url", extra_import_params.merge({ namespace_id: params[:namespace_id] })) # rubocop:disable GitlabSecurity/PublicSend
- end
-
def provider_unauthorized
session[access_token_key] = nil
redirect_to new_import_url,
@@ -228,12 +185,6 @@ class Import::GithubController < Import::BaseController
alert: _("GitHub API rate limit exceeded. Try again after %{reset_time}") % { reset_time: reset_time }
end
- def missing_oauth_config
- session[access_token_key] = nil
- redirect_to new_import_url,
- alert: _('Missing OAuth configuration for GitHub.')
- end
-
def auth_state_key
:"#{provider_name}_auth_state_key"
end
@@ -252,24 +203,10 @@ class Import::GithubController < Import::BaseController
end
# rubocop: enable CodeReuse/ActiveRecord
- def provider_auth
- if !ci_cd_only? && session[access_token_key].blank?
- go_to_provider_for_permissions
- end
- end
-
- def ci_cd_only?
- %w[1 true].include?(params[:ci_cd_only])
- end
-
def client_options
{ wait_for_rate_limit_reset: false }
end
- def extra_import_params
- {}
- end
-
def rate_limit_threshold_exceeded
head :too_many_requests
end
diff --git a/app/controllers/import/github_groups_controller.rb b/app/controllers/import/github_groups_controller.rb
new file mode 100644
index 00000000000..6c0773bcfb3
--- /dev/null
+++ b/app/controllers/import/github_groups_controller.rb
@@ -0,0 +1,57 @@
+# frozen_string_literal: true
+
+module Import
+ class GithubGroupsController < ApplicationController
+ include Import::GithubOauth
+
+ before_action :provider_auth, only: [:status]
+ feature_category :importers
+
+ PAGE_LENGTH = 25
+
+ def status
+ respond_to do |format|
+ format.json do
+ render json: { provider_groups: serialized_provider_groups }
+ end
+ end
+ end
+
+ private
+
+ def serialized_provider_groups
+ Import::GithubOrgSerializer.new.represent(importable_orgs)
+ end
+
+ def importable_orgs
+ client_orgs.to_a
+ end
+
+ def client_orgs
+ @client_orgs ||= client.octokit.organizations(nil, pagination_options)
+ end
+
+ def client
+ @client ||= Gitlab::GithubImport::Client.new(session[access_token_key])
+ end
+
+ def pagination_options
+ {
+ page: [1, params[:page].to_i].max,
+ per_page: PAGE_LENGTH
+ }
+ end
+
+ def auth_state_key
+ :"#{provider_name}_auth_state_key"
+ end
+
+ def access_token_key
+ :"#{provider_name}_access_token"
+ end
+
+ def provider_name
+ :github
+ end
+ end
+end
diff --git a/app/controllers/jira_connect/public_keys_controller.rb b/app/controllers/jira_connect/public_keys_controller.rb
new file mode 100644
index 00000000000..b3144993edb
--- /dev/null
+++ b/app/controllers/jira_connect/public_keys_controller.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+module JiraConnect
+ class PublicKeysController < ::ApplicationController
+ # This is not inheriting from JiraConnect::Application controller because
+ # it doesn't need to handle JWT authentication.
+
+ feature_category :integrations
+
+ skip_before_action :authenticate_user!
+
+ def show
+ return render_404 if Feature.disabled?(:jira_connect_oauth_self_managed) || !Gitlab.com?
+
+ render plain: public_key.key
+ end
+
+ private
+
+ def public_key
+ JiraConnect::PublicKey.find(params[:id])
+ end
+ end
+end
diff --git a/app/controllers/oauth/applications_controller.rb b/app/controllers/oauth/applications_controller.rb
index ff466fd5fbb..3b78b997da1 100644
--- a/app/controllers/oauth/applications_controller.rb
+++ b/app/controllers/oauth/applications_controller.rb
@@ -4,7 +4,6 @@ class Oauth::ApplicationsController < Doorkeeper::ApplicationsController
include Gitlab::GonHelper
include PageLayoutHelper
include OauthApplications
- include Gitlab::Experimentation::ControllerConcern
include InitializesCurrentUserMode
# Defined by the `Doorkeeper::ApplicationsController` and is redundant as we call `authenticate_user!` below. Not
diff --git a/app/controllers/oauth/authorizations_controller.rb b/app/controllers/oauth/authorizations_controller.rb
index 2e9fbb1d0d9..bf8b61db2e5 100644
--- a/app/controllers/oauth/authorizations_controller.rb
+++ b/app/controllers/oauth/authorizations_controller.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
class Oauth::AuthorizationsController < Doorkeeper::AuthorizationsController
- include Gitlab::Experimentation::ControllerConcern
include InitializesCurrentUserMode
include Gitlab::Utils::StrongMemoize
diff --git a/app/controllers/omniauth_callbacks_controller.rb b/app/controllers/omniauth_callbacks_controller.rb
index 817f272d458..f3f0ddd968a 100644
--- a/app/controllers/omniauth_callbacks_controller.rb
+++ b/app/controllers/omniauth_callbacks_controller.rb
@@ -181,6 +181,8 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
end
accept_pending_invitations(user: user) if new_user
+ persist_accepted_terms_if_required(user) if new_user
+
store_after_sign_up_path_for_user if intent_to_register?
sign_in_and_redirect(user, event: :authentication)
end
@@ -301,6 +303,15 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
redirect_to new_admin_session_path, alert: _('Invalid login or password')
end
+ def persist_accepted_terms_if_required(user)
+ return unless Feature.enabled?(:update_oauth_registration_flow)
+ return unless user.persisted?
+ return unless Gitlab::CurrentSettings.current_application_settings.enforce_terms?
+
+ terms = ApplicationSetting::Term.latest
+ Users::RespondToTermsService.new(user, terms).execute(accepted: true)
+ end
+
def store_after_sign_up_path_for_user
store_location_for(:user, users_sign_up_welcome_path)
end
diff --git a/app/controllers/profiles/personal_access_tokens_controller.rb b/app/controllers/profiles/personal_access_tokens_controller.rb
index 8ed67c26f19..4cf26d3e1e2 100644
--- a/app/controllers/profiles/personal_access_tokens_controller.rb
+++ b/app/controllers/profiles/personal_access_tokens_controller.rb
@@ -3,6 +3,8 @@
class Profiles::PersonalAccessTokensController < Profiles::ApplicationController
feature_category :authentication_and_authorization
+ before_action :check_personal_access_tokens_enabled
+
def index
set_index_vars
scopes = params[:scopes].split(',').map(&:squish).select(&:present?).map(&:to_sym) unless params[:scopes].nil?
@@ -83,4 +85,8 @@ class Profiles::PersonalAccessTokensController < Profiles::ApplicationController
def page
(params[:page] || 1).to_i
end
+
+ def check_personal_access_tokens_enabled
+ render_404 if Gitlab::CurrentSettings.personal_access_tokens_disabled?
+ end
end
diff --git a/app/controllers/profiles/preferences_controller.rb b/app/controllers/profiles/preferences_controller.rb
index 7aca76c2fb1..a57c87bf691 100644
--- a/app/controllers/profiles/preferences_controller.rb
+++ b/app/controllers/profiles/preferences_controller.rb
@@ -55,7 +55,9 @@ class Profiles::PreferencesController < Profiles::ApplicationController
:sourcegraph_enabled,
:gitpod_enabled,
:render_whitespace_in_code,
- :markdown_surround_selection
+ :markdown_surround_selection,
+ :markdown_automatic_lists,
+ :use_legacy_web_ide
]
end
end
diff --git a/app/controllers/profiles/two_factor_auths_controller.rb b/app/controllers/profiles/two_factor_auths_controller.rb
index 0b7d4626c6d..0933f2bb7ea 100644
--- a/app/controllers/profiles/two_factor_auths_controller.rb
+++ b/app/controllers/profiles/two_factor_auths_controller.rb
@@ -15,31 +15,7 @@ class Profiles::TwoFactorAuthsController < Profiles::ApplicationController
feature_category :authentication_and_authorization
def show
- if two_factor_authentication_required? && !current_user.two_factor_enabled?
- two_factor_authentication_reason(
- global: lambda do
- flash.now[:alert] =
- _('The global settings require you to enable Two-Factor Authentication for your account.')
- end,
- group: lambda do |groups|
- flash.now[:alert] = groups_notification(groups)
- end
- )
-
- unless two_factor_grace_period_expired?
- grace_period_deadline = current_user.otp_grace_period_started_at + two_factor_grace_period.hours
- flash.now[:alert] = flash.now[:alert] + _(" You need to do this before %{grace_period_deadline}.") % { grace_period_deadline: l(grace_period_deadline) }
- end
- end
-
- @qr_code = build_qr_code
- @account_string = account_string
-
- if Feature.enabled?(:webauthn)
- setup_webauthn_registration
- else
- setup_u2f_registration
- end
+ setup_show_page
end
def create
@@ -147,7 +123,11 @@ class Profiles::TwoFactorAuthsController < Profiles::ApplicationController
current_user.increment_failed_attempts!
- redirect_to profile_two_factor_auth_path, alert: _('You must provide a valid current password')
+ @error = { message: _('You must provide a valid current password') }
+
+ setup_show_page
+
+ render 'show'
end
def current_password_required?
@@ -245,4 +225,32 @@ class Profiles::TwoFactorAuthsController < Profiles::ApplicationController
redirect_to profile_emails_path, notice: s_('You need to verify your primary email first before enabling Two-Factor Authentication.')
end
end
+
+ def setup_show_page
+ if two_factor_authentication_required? && !current_user.two_factor_enabled?
+ two_factor_authentication_reason(
+ global: lambda do
+ flash.now[:alert] =
+ _('The global settings require you to enable Two-Factor Authentication for your account.')
+ end,
+ group: lambda do |groups|
+ flash.now[:alert] = groups_notification(groups)
+ end
+ )
+
+ unless two_factor_grace_period_expired?
+ grace_period_deadline = current_user.otp_grace_period_started_at + two_factor_grace_period.hours
+ flash.now[:alert] = flash.now[:alert] + _(" You need to do this before %{grace_period_deadline}.") % { grace_period_deadline: l(grace_period_deadline) }
+ end
+ end
+
+ @qr_code = build_qr_code
+ @account_string = account_string
+
+ if Feature.enabled?(:webauthn)
+ setup_webauthn_registration
+ else
+ setup_u2f_registration
+ end
+ end
end
diff --git a/app/controllers/projects/application_controller.rb b/app/controllers/projects/application_controller.rb
index 028b7af02c9..2256471047d 100644
--- a/app/controllers/projects/application_controller.rb
+++ b/app/controllers/projects/application_controller.rb
@@ -39,8 +39,8 @@ class Projects::ApplicationController < ApplicationController
access_denied!(
_('You must have developer or higher permissions in the associated project to view job logs when debug trace ' \
"is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline " \
- 'configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to ' \
- 'the project with developer permissions or higher.')
+ 'configuration or CI/CD settings. If you need to view this job log, a project maintainer or owner must add ' \
+ 'you to the project with developer permissions or higher.')
)
else
access_denied!(_('The current user is not authorized to access the job log.'))
diff --git a/app/controllers/projects/autocomplete_sources_controller.rb b/app/controllers/projects/autocomplete_sources_controller.rb
index 9dbf989ca3f..7755effe1da 100644
--- a/app/controllers/projects/autocomplete_sources_controller.rb
+++ b/app/controllers/projects/autocomplete_sources_controller.rb
@@ -41,7 +41,7 @@ class Projects::AutocompleteSourcesController < Projects::ApplicationController
end
def contacts
- render json: autocomplete_service.contacts
+ render json: autocomplete_service.contacts(target)
end
private
@@ -51,9 +51,12 @@ class Projects::AutocompleteSourcesController < Projects::ApplicationController
end
def target
+ # type_id is not required in general
+ target_type = params.require(:type)
+
QuickActions::TargetService
.new(project, current_user)
- .execute(params[:type], params[:type_id])
+ .execute(target_type, params[:type_id])
end
def authorize_read_crm_contact!
diff --git a/app/controllers/projects/blame_controller.rb b/app/controllers/projects/blame_controller.rb
index 2a20c67a23d..01ed5473b41 100644
--- a/app/controllers/projects/blame_controller.rb
+++ b/app/controllers/projects/blame_controller.rb
@@ -26,7 +26,10 @@ class Projects::BlameController < Projects::ApplicationController
blame_service = Projects::BlameService.new(@blob, @commit, params.permit(:page, :no_pagination))
@blame = Gitlab::View::Presenter::Factory.new(blame_service.blame, project: @project, path: @path, page: blame_service.page).fabricate!
+
@blame_pagination = blame_service.pagination
+
+ @blame_per_page = blame_service.per_page
end
end
diff --git a/app/controllers/projects/boards_controller.rb b/app/controllers/projects/boards_controller.rb
index 82b35a22669..6a6701ead15 100644
--- a/app/controllers/projects/boards_controller.rb
+++ b/app/controllers/projects/boards_controller.rb
@@ -1,11 +1,10 @@
# frozen_string_literal: true
class Projects::BoardsController < Projects::ApplicationController
- include MultipleBoardsActions
+ include BoardsActions
include IssuableCollections
before_action :check_issues_available!
- before_action :assign_endpoint_vars
before_action do
push_frontend_feature_flag(:board_multi_select, project)
push_frontend_feature_flag(:realtime_labels, project&.group)
@@ -20,16 +19,6 @@ class Projects::BoardsController < Projects::ApplicationController
private
- def board_klass
- Board
- end
-
- def boards_finder
- strong_memoize :boards_finder do
- Boards::BoardsFinder.new(parent, current_user)
- end
- end
-
def board_finder
strong_memoize :board_finder do
Boards::BoardsFinder.new(parent, current_user, board_id: params[:id])
@@ -42,11 +31,6 @@ class Projects::BoardsController < Projects::ApplicationController
end
end
- def assign_endpoint_vars
- @boards_endpoint = project_boards_path(project)
- @bulk_issues_path = bulk_update_project_issues_path(project)
- end
-
def authorize_read_board!
access_denied! unless can?(current_user, :read_issue_board, project)
end
diff --git a/app/controllers/projects/compare_controller.rb b/app/controllers/projects/compare_controller.rb
index d7fd65f02a8..61308f24412 100644
--- a/app/controllers/projects/compare_controller.rb
+++ b/app/controllers/projects/compare_controller.rb
@@ -47,7 +47,8 @@ class Projects::CompareController < Projects::ApplicationController
from_to_vars = {
from: compare_params[:from].presence,
to: compare_params[:to].presence,
- from_project_id: compare_params[:from_project_id].presence
+ from_project_id: compare_params[:from_project_id].presence,
+ straight: compare_params[:straight].presence
}
if from_to_vars[:from].blank? || from_to_vars[:to].blank?
@@ -112,7 +113,11 @@ class Projects::CompareController < Projects::ApplicationController
def compare
return @compare if defined?(@compare)
- @compare = CompareService.new(source_project, head_ref).execute(target_project, start_ref)
+ @compare = CompareService.new(source_project, head_ref).execute(target_project, start_ref, straight: straight)
+ end
+
+ def straight
+ compare_params[:straight] == "true"
end
def start_ref
@@ -160,6 +165,6 @@ class Projects::CompareController < Projects::ApplicationController
# rubocop: enable CodeReuse/ActiveRecord
def compare_params
- @compare_params ||= params.permit(:from, :to, :from_project_id)
+ @compare_params ||= params.permit(:from, :to, :from_project_id, :straight)
end
end
diff --git a/app/controllers/projects/deploy_keys_controller.rb b/app/controllers/projects/deploy_keys_controller.rb
index 96afe9dbb9f..22a42d22914 100644
--- a/app/controllers/projects/deploy_keys_controller.rb
+++ b/app/controllers/projects/deploy_keys_controller.rb
@@ -27,11 +27,9 @@ class Projects::DeployKeysController < Projects::ApplicationController
end
def create
- @key = DeployKeys::CreateService.new(current_user, create_params).execute(project: @project)
+ @key = DeployKeys::CreateService.new(current_user, create_params).execute(project: @project).present
- unless @key.valid?
- flash[:alert] = @key.errors.full_messages.join(', ').html_safe
- end
+ flash[:alert] = @key.humanized_error_message unless @key.valid?
redirect_to_repository
end
diff --git a/app/controllers/projects/google_cloud/databases_controller.rb b/app/controllers/projects/google_cloud/databases_controller.rb
index 8f7554f248b..77ee830fd24 100644
--- a/app/controllers/projects/google_cloud/databases_controller.rb
+++ b/app/controllers/projects/google_cloud/databases_controller.rb
@@ -50,16 +50,15 @@ module Projects
track_event(:error_enable_cloudsql_services)
flash[:error] = error_message(enable_response[:message])
else
- permitted_params = params.permit(:gcp_project, :ref, :database_version, :tier)
create_response = ::GoogleCloud::CreateCloudsqlInstanceService
- .new(project, current_user, create_service_params(permitted_params))
+ .new(project, current_user, create_service_params)
.execute
if create_response[:status] == :error
track_event(:error_create_cloudsql_instance)
flash[:warning] = error_message(create_response[:message])
else
- track_event(:create_cloudsql_instance, permitted_params.to_s)
+ track_event(:create_cloudsql_instance, permitted_params_create.to_s)
flash[:notice] = success_message
end
end
@@ -69,17 +68,25 @@ module Projects
private
+ def permitted_params_create
+ params.permit(:gcp_project, :ref, :database_version, :tier)
+ end
+
def enable_service_params
- { google_oauth2_token: token_in_session }
+ {
+ google_oauth2_token: token_in_session,
+ gcp_project_id: permitted_params_create[:gcp_project],
+ environment_name: permitted_params_create[:ref]
+ }
end
- def create_service_params(permitted_params)
+ def create_service_params
{
google_oauth2_token: token_in_session,
- gcp_project_id: permitted_params[:gcp_project],
- environment_name: permitted_params[:ref],
- database_version: permitted_params[:database_version],
- tier: permitted_params[:tier]
+ gcp_project_id: permitted_params_create[:gcp_project],
+ environment_name: permitted_params_create[:ref],
+ database_version: permitted_params_create[:database_version],
+ tier: permitted_params_create[:tier]
}
end
diff --git a/app/controllers/projects/incident_management/timeline_events_controller.rb b/app/controllers/projects/incident_management/timeline_events_controller.rb
new file mode 100644
index 00000000000..7e7a4758e48
--- /dev/null
+++ b/app/controllers/projects/incident_management/timeline_events_controller.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+module Projects
+ module IncidentManagement
+ class TimelineEventsController < Projects::ApplicationController
+ include PreviewMarkdown
+
+ before_action :authenticate_user!
+
+ respond_to :json
+
+ feature_category :incident_management
+ urgency :low
+ end
+ end
+end
diff --git a/app/controllers/projects/incidents_controller.rb b/app/controllers/projects/incidents_controller.rb
index cbf0c756e1e..089ee860ea6 100644
--- a/app/controllers/projects/incidents_controller.rb
+++ b/app/controllers/projects/incidents_controller.rb
@@ -7,11 +7,9 @@ class Projects::IncidentsController < Projects::ApplicationController
before_action :authorize_read_issue!
before_action :load_incident, only: [:show]
before_action do
- push_frontend_feature_flag(:incident_timeline, @project)
push_force_frontend_feature_flag(:work_items, @project&.work_items_feature_flag_enabled?)
push_force_frontend_feature_flag(:work_items_mvc_2, @project&.work_items_mvc_2_feature_flag_enabled?)
push_frontend_feature_flag(:work_items_hierarchy, @project)
- push_frontend_feature_flag(:remove_user_attributes_projects, @project)
end
feature_category :incident_management
diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb
index 800a7df2566..5b1117c0224 100644
--- a/app/controllers/projects/issues_controller.rb
+++ b/app/controllers/projects/issues_controller.rb
@@ -41,8 +41,8 @@ class Projects::IssuesController < Projects::ApplicationController
before_action :authorize_download_code!, only: [:related_branches]
before_action do
- push_frontend_feature_flag(:incident_timeline, project)
- push_frontend_feature_flag(:remove_user_attributes_projects, project)
+ push_frontend_feature_flag(:preserve_unchanged_markdown, project)
+ push_frontend_feature_flag(:content_editor_on_issues, project)
end
before_action only: [:index, :show] do
@@ -147,19 +147,26 @@ class Projects::IssuesController < Projects::ApplicationController
spam_params = ::Spam::SpamParams.new_from_request(request: request)
service = ::Issues::CreateService.new(project: project, current_user: current_user, params: create_params, spam_params: spam_params)
- @issue = service.execute
+ result = service.execute
- create_vulnerability_issue_feedback(issue)
-
- if service.discussions_to_resolve.count(&:resolved?) > 0
- flash[:notice] = if service.discussion_to_resolve_id
- _("Resolved 1 discussion.")
- else
- _("Resolved all discussions.")
- end
+ # Only irrecoverable errors such as unauthorized user won't contain an issue in the response
+ if result.error? && result[:issue].blank?
+ render_by_create_result_error(result) && return
end
- if @issue.valid?
+ @issue = result[:issue]
+
+ if result.success?
+ create_vulnerability_issue_feedback(@issue)
+
+ if service.discussions_to_resolve.count(&:resolved?) > 0
+ flash[:notice] = if service.discussion_to_resolve_id
+ _("Resolved 1 discussion.")
+ else
+ _("Resolved all discussions.")
+ end
+ end
+
redirect_to project_issue_path(@project, @issue)
else
# NOTE: this CAPTCHA support method is indirectly included via IssuableActions
@@ -372,6 +379,21 @@ class Projects::IssuesController < Projects::ApplicationController
private
+ def render_by_create_result_error(result)
+ Gitlab::AppLogger.warn(
+ message: 'Cannot create issue',
+ errors: result.errors,
+ http_status: result.http_status
+ )
+ error_method_name = "render_#{result.http_status}".to_sym
+
+ if respond_to?(error_method_name, true)
+ send(error_method_name) # rubocop:disable GitlabSecurity/PublicSend
+ else
+ render_404
+ end
+ end
+
def clean_params(all_params)
issue_type = all_params[:issue_type].to_s
all_params.delete(:issue_type) unless WorkItems::Type.allowed_types_for_issues.include?(issue_type)
@@ -383,6 +405,7 @@ class Projects::IssuesController < Projects::ApplicationController
options = super
options[:issue_types] = Issue::TYPES_FOR_LIST
+ options[:issue_types] = options[:issue_types].excluding('task') unless project.work_items_feature_flag_enabled?
if service_desk?
options.reject! { |key| key == 'author_username' || key == 'author_id' }
diff --git a/app/controllers/projects/merge_requests/diffs_controller.rb b/app/controllers/projects/merge_requests/diffs_controller.rb
index a68c2ffa06d..418e7233e21 100644
--- a/app/controllers/projects/merge_requests/diffs_controller.rb
+++ b/app/controllers/projects/merge_requests/diffs_controller.rb
@@ -4,6 +4,7 @@ class Projects::MergeRequests::DiffsController < Projects::MergeRequests::Applic
include DiffHelper
include RendersNotes
include Gitlab::Cache::Helpers
+ include Gitlab::Tracking::Helpers
before_action :commit
before_action :define_diff_vars
diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb
index 5a212e9a152..9c139733248 100644
--- a/app/controllers/projects/merge_requests_controller.rb
+++ b/app/controllers/projects/merge_requests_controller.rb
@@ -34,7 +34,6 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
before_action only: [:show] do
push_frontend_feature_flag(:merge_request_widget_graphql, project)
push_frontend_feature_flag(:core_security_mr_widget_counts, project)
- push_frontend_feature_flag(:refactor_mr_widgets_extensions, project)
push_frontend_feature_flag(:refactor_code_quality_extension, project)
push_frontend_feature_flag(:refactor_mr_widget_test_summary, project)
push_frontend_feature_flag(:issue_assignees_widget, @project)
@@ -45,7 +44,6 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
push_frontend_feature_flag(:paginated_mr_discussions, project)
push_frontend_feature_flag(:mr_review_submit_comment, project)
push_frontend_feature_flag(:mr_experience_survey, project)
- push_frontend_feature_flag(:remove_user_attributes_projects, @project)
end
before_action do
@@ -451,15 +449,16 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
return :failed
end
+ squashing = params.fetch(:squash, false)
merge_service = ::MergeRequests::MergeService.new(project: @project, current_user: current_user, params: merge_params)
- unless merge_service.hooks_validation_pass?(@merge_request)
+ unless merge_service.hooks_validation_pass?(@merge_request, validate_squash_message: squashing)
return :hook_validation_error
end
return :sha_mismatch if params[:sha] != @merge_request.diff_head_sha
- @merge_request.update(merge_error: nil, squash: params.fetch(:squash, false))
+ @merge_request.update(merge_error: nil, squash: squashing)
if auto_merge_requested?
if merge_request.auto_merge_enabled?
@@ -555,7 +554,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
end
def endpoint_metadata_url(project, merge_request)
- params = request.query_parameters.merge(view: 'inline', diff_head: true)
+ params = request.query_parameters.merge(view: 'inline', diff_head: true, w: current_user&.show_whitespace_in_diffs ? '0' : '1')
diffs_metadata_project_json_merge_request_path(project, merge_request, 'json', params)
end
diff --git a/app/controllers/projects/milestones_controller.rb b/app/controllers/projects/milestones_controller.rb
index cfb67b7b4ff..78108cf3478 100644
--- a/app/controllers/projects/milestones_controller.rb
+++ b/app/controllers/projects/milestones_controller.rb
@@ -4,8 +4,11 @@ class Projects::MilestonesController < Projects::ApplicationController
include Gitlab::Utils::StrongMemoize
include MilestoneActions
+ REDIRECT_TARGETS = [:new_release].freeze
+
before_action :check_issuables_available!
before_action :milestone, only: [:edit, :update, :destroy, :show, :issues, :merge_requests, :participants, :labels, :promote]
+ before_action :redirect_path, only: [:new, :create]
# Allow read any milestone
before_action :authorize_read_milestone!
@@ -59,7 +62,11 @@ class Projects::MilestonesController < Projects::ApplicationController
@milestone = Milestones::CreateService.new(project, current_user, milestone_params).execute
if @milestone.valid?
- redirect_to project_milestone_path(@project, @milestone)
+ if @redirect_path == :new_release
+ redirect_to new_project_release_path(@project)
+ else
+ redirect_to project_milestone_path(@project, @milestone)
+ end
else
render "new"
end
@@ -113,6 +120,11 @@ class Projects::MilestonesController < Projects::ApplicationController
protected
+ def redirect_path
+ path = params[:redirect_path]&.to_sym
+ @redirect_path = path if REDIRECT_TARGETS.include?(path)
+ end
+
def project_group
strong_memoize(:project_group) do
project.group
diff --git a/app/controllers/projects/pages_domains_controller.rb b/app/controllers/projects/pages_domains_controller.rb
index a6b22a28b17..43952a2efe4 100644
--- a/app/controllers/projects/pages_domains_controller.rb
+++ b/app/controllers/projects/pages_domains_controller.rb
@@ -41,9 +41,9 @@ class Projects::PagesDomainsController < Projects::ApplicationController
end
def create
- @domain = @project.pages_domains.create(create_params)
+ @domain = PagesDomains::CreateService.new(@project, current_user, create_params).execute
- if @domain.valid?
+ if @domain&.persisted?
redirect_to project_pages_domain_path(@project, @domain)
else
render 'new'
@@ -51,7 +51,9 @@ class Projects::PagesDomainsController < Projects::ApplicationController
end
def update
- if @domain.update(update_params)
+ service = ::PagesDomains::UpdateService.new(@project, current_user, update_params)
+
+ if service.execute(@domain)
redirect_to project_pages_path(@project),
status: :found,
notice: 'Domain was updated'
@@ -61,7 +63,9 @@ class Projects::PagesDomainsController < Projects::ApplicationController
end
def destroy
- @domain.destroy
+ PagesDomains::DeleteService
+ .new(@project, current_user)
+ .execute(@domain)
respond_to do |format|
format.html do
@@ -74,9 +78,10 @@ class Projects::PagesDomainsController < Projects::ApplicationController
end
def clean_certificate
- unless @domain.update(user_provided_certificate: nil, user_provided_key: nil)
- flash[:alert] = @domain.errors.full_messages.join(', ')
- end
+ update_params = { user_provided_certificate: nil, user_provided_key: nil }
+ service = ::PagesDomains::UpdateService.new(@project, current_user, update_params)
+
+ flash[:alert] = @domain.errors.full_messages.join(', ') unless service.execute(@domain)
redirect_to project_pages_domain_path(@project, @domain)
end
diff --git a/app/controllers/projects/pipeline_schedules_controller.rb b/app/controllers/projects/pipeline_schedules_controller.rb
index a23d7fb3e6b..ca787785901 100644
--- a/app/controllers/projects/pipeline_schedules_controller.rb
+++ b/app/controllers/projects/pipeline_schedules_controller.rb
@@ -10,6 +10,7 @@ class Projects::PipelineSchedulesController < Projects::ApplicationController
before_action :authorize_update_pipeline_schedule!, only: [:edit, :update]
before_action :authorize_take_ownership_pipeline_schedule!, only: [:take_ownership]
before_action :authorize_admin_pipeline_schedule!, only: [:destroy]
+ before_action :push_schedule_feature_flag, only: [:index, :new, :edit]
feature_category :continuous_integration
urgency :low
@@ -115,4 +116,8 @@ class Projects::PipelineSchedulesController < Projects::ApplicationController
def authorize_admin_pipeline_schedule!
return access_denied! unless can?(current_user, :admin_pipeline_schedule, schedule)
end
+
+ def push_schedule_feature_flag
+ push_frontend_feature_flag(:pipeline_schedules_vue, @project)
+ end
end
diff --git a/app/controllers/projects/product_analytics_controller.rb b/app/controllers/projects/product_analytics_controller.rb
index c89cd52530a..8085b0a6334 100644
--- a/app/controllers/projects/product_analytics_controller.rb
+++ b/app/controllers/projects/product_analytics_controller.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
class Projects::ProductAnalyticsController < Projects::ApplicationController
- before_action :feature_enabled!
+ before_action :feature_enabled!, only: [:index, :setup, :test, :graphs]
before_action :authorize_read_product_analytics!
before_action :tracker_variables, only: [:setup, :test]
@@ -57,3 +57,5 @@ class Projects::ProductAnalyticsController < Projects::ApplicationController
render_404 unless Feature.enabled?(:product_analytics, @project)
end
end
+
+Projects::ProductAnalyticsController.prepend_mod_with('Projects::ProductAnalyticsController')
diff --git a/app/controllers/projects/protected_refs_controller.rb b/app/controllers/projects/protected_refs_controller.rb
index abbfe9ce22a..69a540158c6 100644
--- a/app/controllers/projects/protected_refs_controller.rb
+++ b/app/controllers/projects/protected_refs_controller.rb
@@ -4,7 +4,6 @@ class Projects::ProtectedRefsController < Projects::ApplicationController
include RepositorySettingsRedirect
# Authorize
- before_action :require_non_empty_project
before_action :authorize_admin_project!
before_action :load_protected_ref, only: [:show, :update, :destroy]
diff --git a/app/controllers/projects/settings/access_tokens_controller.rb b/app/controllers/projects/settings/access_tokens_controller.rb
index 32916831ecd..bac35583a97 100644
--- a/app/controllers/projects/settings/access_tokens_controller.rb
+++ b/app/controllers/projects/settings/access_tokens_controller.rb
@@ -13,6 +13,12 @@ module Projects
def resource_access_tokens_path
namespace_project_settings_access_tokens_path
end
+
+ private
+
+ def represent(tokens)
+ ::ProjectAccessTokenSerializer.new.represent(tokens, project: resource)
+ end
end
end
end
diff --git a/app/controllers/projects/snippets_controller.rb b/app/controllers/projects/snippets_controller.rb
index c861b24d9ec..76e2da6eb57 100644
--- a/app/controllers/projects/snippets_controller.rb
+++ b/app/controllers/projects/snippets_controller.rb
@@ -14,7 +14,7 @@ class Projects::SnippetsController < Projects::Snippets::ApplicationController
before_action :authorize_read_snippet!, except: [:new, :index]
before_action :authorize_update_snippet!, only: :edit
- urgency :low, [:index]
+ urgency :low, [:index, :show]
def index
@snippet_counts = ::Snippets::CountService
diff --git a/app/controllers/projects/web_ide_terminals_controller.rb b/app/controllers/projects/web_ide_terminals_controller.rb
index 350b091edfa..cfccc949244 100644
--- a/app/controllers/projects/web_ide_terminals_controller.rb
+++ b/app/controllers/projects/web_ide_terminals_controller.rb
@@ -10,6 +10,8 @@ class Projects::WebIdeTerminalsController < Projects::ApplicationController
feature_category :web_ide
+ urgency :low, [:check_config]
+
def check_config
return respond_422 unless branch_sha
diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb
index 5ceedbc1e01..b7b6e6534fb 100644
--- a/app/controllers/projects_controller.rb
+++ b/app/controllers/projects_controller.rb
@@ -311,8 +311,6 @@ class ProjectsController < Projects::ApplicationController
find_tags = true
find_commits = true
- use_gitaly_pagination = Feature.enabled?(:use_gitaly_pagination_for_refs, @project)
-
unless find_refs.nil?
find_branches = find_refs.include?('branches')
find_tags = find_refs.include?('tags')
@@ -323,7 +321,7 @@ class ProjectsController < Projects::ApplicationController
if find_branches
branches = BranchesFinder.new(@repository, refs_params.merge(per_page: REFS_LIMIT))
- .execute(gitaly_pagination: use_gitaly_pagination)
+ .execute(gitaly_pagination: true)
.take(REFS_LIMIT)
.map(&:name)
@@ -332,7 +330,7 @@ class ProjectsController < Projects::ApplicationController
if find_tags && @repository.tag_count.nonzero?
tags = TagsFinder.new(@repository, refs_params.merge(per_page: REFS_LIMIT))
- .execute(gitaly_pagination: use_gitaly_pagination)
+ .execute(gitaly_pagination: true)
.take(REFS_LIMIT)
.map(&:name)
@@ -435,14 +433,14 @@ class ProjectsController < Projects::ApplicationController
analytics_access_level
security_and_compliance_access_level
container_registry_access_level
+ releases_access_level
] + operations_feature_attributes
end
def operations_feature_attributes
if Feature.enabled?(:split_operations_visibility_permissions, project)
%i[
- environments_access_level feature_flags_access_level releases_access_level
- monitor_access_level
+ environments_access_level feature_flags_access_level monitor_access_level
]
else
%i[operations_access_level]
diff --git a/app/controllers/registrations/welcome_controller.rb b/app/controllers/registrations/welcome_controller.rb
index 4e18e6a3b20..a49b82319da 100644
--- a/app/controllers/registrations/welcome_controller.rb
+++ b/app/controllers/registrations/welcome_controller.rb
@@ -4,6 +4,7 @@ module Registrations
class WelcomeController < ApplicationController
include OneTrustCSP
include GoogleAnalyticsCSP
+ include RegistrationsTracking
layout 'minimal'
skip_before_action :authenticate_user!, :required_signup_info, :check_two_factor_requirement, only: [:show, :update]
@@ -25,7 +26,7 @@ module Registrations
members = current_user.members
- if members.count == 1 && members.last.source.present?
+ if registering_from_invite?(members)
redirect_to members_activity_path(members), notice: helpers.invite_accepted_notice(members.last)
else
redirect_to path_for_signed_in_user(current_user)
@@ -37,6 +38,10 @@ module Registrations
private
+ def registering_from_invite?(members)
+ members.count == 1 && members.last.source.present?
+ end
+
def require_current_user
return redirect_to new_user_registration_path unless current_user
end
diff --git a/app/controllers/registrations_controller.rb b/app/controllers/registrations_controller.rb
index 0bd266bb490..31fe30f3f06 100644
--- a/app/controllers/registrations_controller.rb
+++ b/app/controllers/registrations_controller.rb
@@ -8,6 +8,7 @@ class RegistrationsController < Devise::RegistrationsController
include OneTrustCSP
include BizibleCSP
include GoogleAnalyticsCSP
+ include RegistrationsTracking
layout 'devise'
@@ -114,13 +115,18 @@ class RegistrationsController < Devise::RegistrationsController
def after_sign_up_path_for(user)
Gitlab::AppLogger.info(user_created_message(confirmed: user.confirmed?))
- users_sign_up_welcome_path
+ users_sign_up_welcome_path(glm_tracking_params)
end
def after_inactive_sign_up_path_for(resource)
Gitlab::AppLogger.info(user_created_message)
return new_user_session_path(anchor: 'login-pane') if resource.blocked_pending_approval?
return dashboard_projects_path if Feature.enabled?(:soft_email_confirmation)
+
+ # when email confirmation is enabled, path to redirect is saved
+ # after user confirms and comes back, he will be redirected
+ store_location_for(:redirect, users_sign_up_welcome_path(glm_tracking_params))
+
return identity_verification_redirect_path if custom_confirmation_enabled?(resource)
users_almost_there_path(email: resource.email)
@@ -183,7 +189,7 @@ class RegistrationsController < Devise::RegistrationsController
def resource
@resource ||= Users::RegistrationsBuildService
- .new(current_user, sign_up_params.merge({ skip_confirmation: skip_email_confirmation? }))
+ .new(current_user, sign_up_params.merge({ skip_confirmation: registered_with_invite_email? }))
.execute
end
@@ -191,7 +197,7 @@ class RegistrationsController < Devise::RegistrationsController
@devise_mapping ||= Devise.mappings[:user]
end
- def skip_email_confirmation?
+ def registered_with_invite_email?
invite_email = session.delete(:invite_email)
sign_up_params[:email] == invite_email
diff --git a/app/controllers/search_controller.rb b/app/controllers/search_controller.rb
index 9f87ad6aaf6..7d4dd04c6d4 100644
--- a/app/controllers/search_controller.rb
+++ b/app/controllers/search_controller.rb
@@ -25,6 +25,10 @@ class SearchController < ApplicationController
end
before_action :check_search_rate_limit!, only: search_rate_limited_endpoints
+ before_action only: :show do
+ push_frontend_feature_flag(:search_page_vertical_nav, current_user)
+ end
+
rescue_from ActiveRecord::QueryCanceled, with: :render_timeout
layout 'search'
diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb
index fe3b8d9b8b4..5c969c437f4 100644
--- a/app/controllers/sessions_controller.rb
+++ b/app/controllers/sessions_controller.rb
@@ -107,11 +107,11 @@ class SessionsController < Devise::SessionsController
end
def captcha_enabled?
- request.headers[CAPTCHA_HEADER] && Gitlab::Recaptcha.enabled?
+ request.headers[CAPTCHA_HEADER] && helpers.recaptcha_enabled?
end
def captcha_on_login_required?
- Gitlab::Recaptcha.enabled_on_login? && unverified_anonymous_user?
+ helpers.recaptcha_enabled_on_login? && unverified_anonymous_user?
end
# From https://github.com/plataformatec/devise/wiki/How-To:-Use-Recaptcha-with-Devise#devisepasswordscontroller
diff --git a/app/controllers/users/namespace_callouts_controller.rb b/app/controllers/users/namespace_callouts_controller.rb
deleted file mode 100644
index d4876382dfe..00000000000
--- a/app/controllers/users/namespace_callouts_controller.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-module Users
- class NamespaceCalloutsController < Users::CalloutsController
- private
-
- def callout
- Users::DismissNamespaceCalloutService.new(
- container: nil, current_user: current_user, params: callout_params
- ).execute
- end
-
- def callout_params
- params.permit(:namespace_id).merge(feature_name: feature_name)
- end
- end
-end
diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb
index 3c1a3534912..c35aa8e4346 100644
--- a/app/controllers/users_controller.rb
+++ b/app/controllers/users_controller.rb
@@ -35,7 +35,7 @@ class UsersController < ApplicationController
feature_category :source_code_management, [:gpg_keys]
# TODO: Set higher urgency after resolving https://gitlab.com/gitlab-org/gitlab/-/issues/357914
- urgency :low, [:show, :calendar_activities, :contributed, :activity, :projects, :groups, :calendar]
+ urgency :low, [:show, :calendar_activities, :contributed, :activity, :projects, :groups, :calendar, :snippets]
urgency :default, [:followers, :following, :starred]
urgency :high, [:exists]
@@ -174,8 +174,9 @@ class UsersController < ApplicationController
end
def follow
- current_user.follow(user)
+ followee = current_user.follow(user)
+ flash[:alert] = followee.errors.full_messages.join(', ') if followee&.errors&.any?
redirect_path = referer_path(request) || @user
redirect_to redirect_path