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>2019-10-22 14:31:16 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2019-10-22 14:31:16 +0300
commit905c1110b08f93a19661cf42a276c7ea90d0a0ff (patch)
tree756d138db422392c00471ab06acdff92c5a9b69c /app/controllers
parent50d93f8d1686950fc58dda4823c4835fd0d8c14b (diff)
Add latest changes from gitlab-org/gitlab@12-4-stable-ee
Diffstat (limited to 'app/controllers')
-rw-r--r--app/controllers/admin/application_settings_controller.rb11
-rw-r--r--app/controllers/admin/dashboard_controller.rb5
-rw-r--r--app/controllers/admin/sessions_controller.rb33
-rw-r--r--app/controllers/admin/users_controller.rb16
-rw-r--r--app/controllers/application_controller.rb31
-rw-r--r--app/controllers/boards/application_controller.rb2
-rw-r--r--app/controllers/boards/lists_controller.rb17
-rw-r--r--app/controllers/clusters/clusters_controller.rb1
-rw-r--r--app/controllers/concerns/cycle_analytics_params.rb25
-rw-r--r--app/controllers/concerns/enforces_admin_authentication.rb12
-rw-r--r--app/controllers/concerns/invisible_captcha.rb4
-rw-r--r--app/controllers/concerns/metrics_dashboard.rb63
-rw-r--r--app/controllers/concerns/milestone_actions.rb2
-rw-r--r--app/controllers/concerns/render_service_results.rb29
-rw-r--r--app/controllers/concerns/renders_assignees.rb7
-rw-r--r--app/controllers/concerns/sessionless_authentication.rb10
-rw-r--r--app/controllers/concerns/uploads_actions.rb28
-rw-r--r--app/controllers/dashboard/todos_controller.rb4
-rw-r--r--app/controllers/explore/snippets_controller.rb2
-rw-r--r--app/controllers/groups/boards_controller.rb3
-rw-r--r--app/controllers/groups/milestones_controller.rb2
-rw-r--r--app/controllers/groups/registry/repositories_controller.rb39
-rw-r--r--app/controllers/groups/settings/ci_cd_controller.rb23
-rw-r--r--app/controllers/groups/uploads_controller.rb2
-rw-r--r--app/controllers/groups_controller.rb23
-rw-r--r--app/controllers/health_controller.rb36
-rw-r--r--app/controllers/help_controller.rb4
-rw-r--r--app/controllers/import/bitbucket_controller.rb8
-rw-r--r--app/controllers/import/github_controller.rb21
-rw-r--r--app/controllers/notification_settings_controller.rb4
-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.rb5
-rw-r--r--app/controllers/profiles/groups_controller.rb2
-rw-r--r--app/controllers/profiles/notifications_controller.rb11
-rw-r--r--app/controllers/profiles_controller.rb1
-rw-r--r--app/controllers/projects/artifacts_controller.rb38
-rw-r--r--app/controllers/projects/boards_controller.rb3
-rw-r--r--app/controllers/projects/branches_controller.rb19
-rw-r--r--app/controllers/projects/commits_controller.rb4
-rw-r--r--app/controllers/projects/cycle_analytics/events_controller.rb10
-rw-r--r--app/controllers/projects/cycle_analytics_controller.rb8
-rw-r--r--app/controllers/projects/deploy_keys_controller.rb14
-rw-r--r--app/controllers/projects/deployments_controller.rb4
-rw-r--r--app/controllers/projects/environments/prometheus_api_controller.rb21
-rw-r--r--app/controllers/projects/environments_controller.rb52
-rw-r--r--app/controllers/projects/git_http_client_controller.rb2
-rw-r--r--app/controllers/projects/git_http_controller.rb16
-rw-r--r--app/controllers/projects/grafana_api_controller.rb25
-rw-r--r--app/controllers/projects/issues_controller.rb4
-rw-r--r--app/controllers/projects/jobs_controller.rb41
-rw-r--r--app/controllers/projects/lfs_api_controller.rb17
-rw-r--r--app/controllers/projects/merge_requests/application_controller.rb6
-rw-r--r--app/controllers/projects/merge_requests/diffs_controller.rb43
-rw-r--r--app/controllers/projects/merge_requests_controller.rb12
-rw-r--r--app/controllers/projects/pipelines_controller.rb25
-rw-r--r--app/controllers/projects/protected_branches_controller.rb12
-rw-r--r--app/controllers/projects/registry/repositories_controller.rb2
-rw-r--r--app/controllers/projects/registry/tags_controller.rb38
-rw-r--r--app/controllers/projects/releases_controller.rb3
-rw-r--r--app/controllers/projects/settings/ci_cd_controller.rb10
-rw-r--r--app/controllers/projects/settings/operations_controller.rb9
-rw-r--r--app/controllers/projects/templates_controller.rb8
-rw-r--r--app/controllers/projects/uploads_controller.rb2
-rw-r--r--app/controllers/projects_controller.rb1
-rw-r--r--app/controllers/registrations_controller.rb68
-rw-r--r--app/controllers/sessions_controller.rb10
-rw-r--r--app/controllers/uploads_controller.rb9
68 files changed, 777 insertions, 247 deletions
diff --git a/app/controllers/admin/application_settings_controller.rb b/app/controllers/admin/application_settings_controller.rb
index fbf63997b15..f7e33c09928 100644
--- a/app/controllers/admin/application_settings_controller.rb
+++ b/app/controllers/admin/application_settings_controller.rb
@@ -6,9 +6,9 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
before_action :set_application_setting
before_action :whitelist_query_limiting, only: [:usage_data]
- VALID_SETTING_PANELS = %w(general integrations repository templates
+ VALID_SETTING_PANELS = %w(general integrations repository
ci_cd reporting metrics_and_profiling
- network geo preferences).freeze
+ network preferences).freeze
VALID_SETTING_PANELS.each do |action|
define_method(action) { perform_update if submitted? }
@@ -145,10 +145,15 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
end
def render_update_error
- action = VALID_SETTING_PANELS.include?(action_name) ? action_name : :general
+ action = valid_setting_panels.include?(action_name) ? action_name : :general
render action
end
+
+ # overridden in EE
+ def valid_setting_panels
+ VALID_SETTING_PANELS
+ end
end
Admin::ApplicationSettingsController.prepend_if_ee('EE::Admin::ApplicationSettingsController')
diff --git a/app/controllers/admin/dashboard_controller.rb b/app/controllers/admin/dashboard_controller.rb
index c36bbaab23b..f24ce9b5d03 100644
--- a/app/controllers/admin/dashboard_controller.rb
+++ b/app/controllers/admin/dashboard_controller.rb
@@ -2,6 +2,7 @@
class Admin::DashboardController < Admin::ApplicationController
include CountHelper
+ helper_method :show_license_breakdown?
COUNTED_ITEMS = [Project, User, Group].freeze
@@ -13,6 +14,10 @@ class Admin::DashboardController < Admin::ApplicationController
@groups = Group.order_id_desc.with_route.limit(10)
end
# rubocop: enable CodeReuse/ActiveRecord
+
+ def show_license_breakdown?
+ false
+ end
end
Admin::DashboardController.prepend_if_ee('EE::Admin::DashboardController')
diff --git a/app/controllers/admin/sessions_controller.rb b/app/controllers/admin/sessions_controller.rb
new file mode 100644
index 00000000000..1f946e41995
--- /dev/null
+++ b/app/controllers/admin/sessions_controller.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+class Admin::SessionsController < ApplicationController
+ include InternalRedirect
+
+ before_action :user_is_admin!
+
+ def new
+ # Renders a form in which the admin can enter their password
+ end
+
+ def create
+ if current_user_mode.enable_admin_mode!(password: params[:password])
+ redirect_location = stored_location_for(:redirect) || admin_root_path
+ redirect_to safe_redirect_path(redirect_location)
+ else
+ flash.now[:alert] = _('Invalid Login or password')
+ render :new
+ end
+ end
+
+ def destroy
+ current_user_mode.disable_admin_mode!
+
+ redirect_to root_path, status: :found, notice: _('Admin mode disabled')
+ end
+
+ private
+
+ def user_is_admin!
+ render_404 unless current_user&.admin?
+ end
+end
diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb
index 61d36d1efc2..4c1ac8f206a 100644
--- a/app/controllers/admin/users_controller.rb
+++ b/app/controllers/admin/users_controller.rb
@@ -58,6 +58,22 @@ class Admin::UsersController < Admin::ApplicationController
end
end
+ def activate
+ return redirect_back_or_admin_user(notice: _("Error occurred. A blocked user must be unblocked to be activated")) if user.blocked?
+
+ user.activate
+ redirect_back_or_admin_user(notice: _("Successfully activated"))
+ end
+
+ def deactivate
+ return redirect_back_or_admin_user(notice: _("Error occurred. A blocked user cannot be deactivated")) if user.blocked?
+ return redirect_back_or_admin_user(notice: _("Successfully deactivated")) if user.deactivated?
+ return redirect_back_or_admin_user(notice: _("The user you are trying to deactivate has been active in the past %{minimum_inactive_days} days and cannot be deactivated") % { minimum_inactive_days: ::User::MINIMUM_INACTIVE_DAYS }) unless user.can_be_deactivated?
+
+ user.deactivate
+ redirect_back_or_admin_user(notice: _("Successfully deactivated"))
+ end
+
def block
if update_user { |user| user.block }
redirect_back_or_admin_user(notice: _("Successfully blocked"))
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index 9a7859fc687..1443a71f6b1 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -13,6 +13,8 @@ class ApplicationController < ActionController::Base
include WithPerformanceBar
include SessionlessAuthentication
include ConfirmEmailWarning
+ include Gitlab::Tracking::ControllerConcern
+ include Gitlab::Experimentation::ControllerConcern
before_action :authenticate_user!
before_action :enforce_terms!, if: :should_enforce_terms?
@@ -24,8 +26,10 @@ class ApplicationController < ActionController::Base
before_action :add_gon_variables, unless: [:peek_request?, :json_request?]
before_action :configure_permitted_parameters, if: :devise_controller?
before_action :require_email, unless: :devise_controller?
+ before_action :active_user_check, unless: :devise_controller?
before_action :set_usage_stats_consent_flag
before_action :check_impersonation_availability
+ before_action :require_role
around_action :set_locale
around_action :set_session_storage
@@ -36,6 +40,7 @@ class ApplicationController < ActionController::Base
protect_from_forgery with: :exception, prepend: true
helper_method :can?
+ helper_method :current_user_mode
helper_method :import_sources_enabled?, :github_import_enabled?,
:gitea_import_enabled?, :github_import_configured?,
:gitlab_import_enabled?, :gitlab_import_configured?,
@@ -286,13 +291,19 @@ class ApplicationController < ActionController::Base
def check_password_expiration
return if session[:impersonator_id] || !current_user&.allow_password_authentication?
- password_expires_at = current_user&.password_expires_at
-
- if password_expires_at && password_expires_at < Time.now
+ if current_user&.password_expired?
return redirect_to new_profile_password_path
end
end
+ def active_user_check
+ return unless current_user && current_user.deactivated?
+
+ sign_out current_user
+ flash[:alert] = _("Your account has been deactivated by your administrator. Please log back in to reactivate your account.")
+ redirect_to new_user_session_path
+ end
+
def ldap_security_check
if current_user && current_user.requires_ldap_check?
return unless current_user.try_obtain_ldap_lease
@@ -533,6 +544,20 @@ class ApplicationController < ActionController::Base
yield
end
end
+
+ def current_user_mode
+ @current_user_mode ||= Gitlab::Auth::CurrentUserMode.new(current_user)
+ end
+
+ # A user requires a role when they are part of the experimental signup flow (executed by the Growth team). Users
+ # are redirected to the welcome page when their role is required and the experiment is enabled for the current user.
+ def require_role
+ return unless current_user && current_user.role_required? && experiment_enabled?(:signup_flow)
+
+ store_location_for :user, request.fullpath
+
+ redirect_to users_sign_up_welcome_path
+ end
end
ApplicationController.prepend_if_ee('EE::ApplicationController')
diff --git a/app/controllers/boards/application_controller.rb b/app/controllers/boards/application_controller.rb
index eab908ba5ed..15ef6698472 100644
--- a/app/controllers/boards/application_controller.rb
+++ b/app/controllers/boards/application_controller.rb
@@ -13,7 +13,7 @@ module Boards
end
def board_parent
- @board_parent ||= board.parent
+ @board_parent ||= board.resource_parent
end
def record_not_found(exception)
diff --git a/app/controllers/boards/lists_controller.rb b/app/controllers/boards/lists_controller.rb
index d0f4904c34e..880f7500708 100644
--- a/app/controllers/boards/lists_controller.rb
+++ b/app/controllers/boards/lists_controller.rb
@@ -9,13 +9,15 @@ module Boards
skip_before_action :authenticate_user!, only: [:index]
def index
- lists = Boards::Lists::ListService.new(board.parent, current_user).execute(board)
+ 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
- list = Boards::Lists::CreateService.new(board.parent, current_user, create_list_params).execute(board)
+ list = Boards::Lists::CreateService.new(board.resource_parent, current_user, create_list_params).execute(board)
if list.valid?
render json: serialize_as_json(list)
@@ -51,7 +53,10 @@ module Boards
service = Boards::Lists::GenerateService.new(board_parent, current_user)
if service.execute(board)
- lists = board.lists.movable.preload_associations(current_user)
+ lists = board.lists.movable.preload_associations
+
+ List.preload_preferences_for_user(lists, current_user)
+
render json: serialize_as_json(lists)
else
head :unprocessable_entity
@@ -64,12 +69,16 @@ module Boards
%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(:collapsed, :position)
+ params.require(:list).permit(list_update_attrs)
end
def serialize_as_json(resource)
diff --git a/app/controllers/clusters/clusters_controller.rb b/app/controllers/clusters/clusters_controller.rb
index 15f1e8284ff..993aba661f3 100644
--- a/app/controllers/clusters/clusters_controller.rb
+++ b/app/controllers/clusters/clusters_controller.rb
@@ -170,6 +170,7 @@ class Clusters::ClustersController < Clusters::BaseController
:zone,
:num_nodes,
:machine_type,
+ :cloud_run,
:legacy_abac
]).merge(
provider_type: :gcp,
diff --git a/app/controllers/concerns/cycle_analytics_params.rb b/app/controllers/concerns/cycle_analytics_params.rb
index b970bdc544e..1645af695be 100644
--- a/app/controllers/concerns/cycle_analytics_params.rb
+++ b/app/controllers/concerns/cycle_analytics_params.rb
@@ -3,8 +3,20 @@
module CycleAnalyticsParams
extend ActiveSupport::Concern
+ def cycle_analytics_project_params
+ return {} unless params[:cycle_analytics].present?
+
+ params[:cycle_analytics].permit(:start_date, :created_after, :created_before, :branch_name)
+ end
+
+ def cycle_analytics_group_params
+ return {} unless params[:cycle_analytics].present?
+
+ params[:cycle_analytics].permit(:start_date, :created_after, :created_before, project_ids: [])
+ end
+
def options(params)
- @options ||= { from: start_date(params), current_user: current_user }
+ @options ||= { from: start_date(params), current_user: current_user }.merge(date_range(params))
end
def start_date(params)
@@ -17,6 +29,17 @@ module CycleAnalyticsParams
90.days.ago
end
end
+
+ def date_range(params)
+ {}.tap do |date_range_params|
+ date_range_params[:from] = to_utc_time(params[:created_after]).beginning_of_day if params[:created_after]
+ date_range_params[:to] = to_utc_time(params[:created_before]).end_of_day if params[:created_before]
+ end.compact
+ end
+
+ def to_utc_time(field)
+ Date.parse(field).to_time.utc
+ end
end
CycleAnalyticsParams.prepend_if_ee('EE::CycleAnalyticsParams')
diff --git a/app/controllers/concerns/enforces_admin_authentication.rb b/app/controllers/concerns/enforces_admin_authentication.rb
index 3ef92730df6..e731211f423 100644
--- a/app/controllers/concerns/enforces_admin_authentication.rb
+++ b/app/controllers/concerns/enforces_admin_authentication.rb
@@ -14,6 +14,16 @@ module EnforcesAdminAuthentication
end
def authenticate_admin!
- render_404 unless current_user.admin?
+ return render_404 unless current_user.admin?
+ return unless Feature.enabled?(:user_mode_in_session)
+
+ unless current_user_mode.admin_mode?
+ store_location_for(:redirect, request.fullpath) if storable_location?
+ redirect_to(new_admin_session_path, notice: _('Re-authentication required'))
+ end
+ end
+
+ def storable_location?
+ request.path != new_admin_session_path
end
end
diff --git a/app/controllers/concerns/invisible_captcha.rb b/app/controllers/concerns/invisible_captcha.rb
index 45c0a5c58ef..d56f1d7fa5f 100644
--- a/app/controllers/concerns/invisible_captcha.rb
+++ b/app/controllers/concerns/invisible_captcha.rb
@@ -8,7 +8,7 @@ module InvisibleCaptcha
end
def on_honeypot_spam_callback
- return unless Feature.enabled?(:invisible_captcha)
+ return unless Feature.enabled?(:invisible_captcha) || experiment_enabled?(:signup_flow)
invisible_captcha_honeypot_counter.increment
log_request('Invisible_Captcha_Honeypot_Request')
@@ -17,7 +17,7 @@ module InvisibleCaptcha
end
def on_timestamp_spam_callback
- return unless Feature.enabled?(:invisible_captcha)
+ return unless Feature.enabled?(:invisible_captcha) || experiment_enabled?(:signup_flow)
invisible_captcha_timestamp_counter.increment
log_request('Invisible_Captcha_Timestamp_Request')
diff --git a/app/controllers/concerns/metrics_dashboard.rb b/app/controllers/concerns/metrics_dashboard.rb
new file mode 100644
index 00000000000..62efdacb710
--- /dev/null
+++ b/app/controllers/concerns/metrics_dashboard.rb
@@ -0,0 +1,63 @@
+# frozen_string_literal: true
+
+# Provides an action which fetches a metrics dashboard according
+# to the parameters specified by the controller.
+module MetricsDashboard
+ extend ActiveSupport::Concern
+
+ def metrics_dashboard
+ result = dashboard_finder.find(
+ project_for_dashboard,
+ current_user,
+ metrics_dashboard_params
+ )
+
+ if include_all_dashboards?
+ result[:all_dashboards] = dashboard_finder.find_all_paths(project_for_dashboard)
+ end
+
+ respond_to do |format|
+ if result[:status] == :success
+ format.json { render dashboard_success_response(result) }
+ else
+ format.json { render dashboard_error_response(result) }
+ end
+ end
+ end
+
+ private
+
+ # Override in class to provide arguments to the finder.
+ def metrics_dashboard_params
+ {}
+ end
+
+ # Override in class if response requires complete list of
+ # dashboards in addition to requested dashboard body.
+ def include_all_dashboards?
+ false
+ end
+
+ def dashboard_finder
+ ::Gitlab::Metrics::Dashboard::Finder
+ end
+
+ # Project is not defined for group and admin level clusters.
+ def project_for_dashboard
+ defined?(project) ? project : nil
+ end
+
+ def dashboard_success_response(result)
+ {
+ status: :ok,
+ json: result.slice(:all_dashboards, :dashboard, :status)
+ }
+ end
+
+ def dashboard_error_response(result)
+ {
+ status: result[:http_status],
+ json: result.slice(:all_dashboards, :message, :status)
+ }
+ end
+end
diff --git a/app/controllers/concerns/milestone_actions.rb b/app/controllers/concerns/milestone_actions.rb
index 1ead631663e..672d31ec779 100644
--- a/app/controllers/concerns/milestone_actions.rb
+++ b/app/controllers/concerns/milestone_actions.rb
@@ -35,7 +35,7 @@ module MilestoneActions
render json: tabs_json("shared/milestones/_labels_tab", {
labels: milestone_labels.map do |label|
- label.present(issuable_subject: @milestone.parent)
+ label.present(issuable_subject: @milestone.resource_parent)
end
})
end
diff --git a/app/controllers/concerns/render_service_results.rb b/app/controllers/concerns/render_service_results.rb
new file mode 100644
index 00000000000..0149a71d9f5
--- /dev/null
+++ b/app/controllers/concerns/render_service_results.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+module RenderServiceResults
+ extend ActiveSupport::Concern
+
+ def success_response(result)
+ render({
+ status: result[:http_status],
+ json: result[:body]
+ })
+ end
+
+ def continue_polling_response
+ render({
+ status: :no_content,
+ json: {
+ status: _('processing'),
+ message: _('Not ready yet. Try again later.')
+ }
+ })
+ end
+
+ def error_response(result)
+ render({
+ status: result[:http_status] || :bad_request,
+ json: { status: result[:status], message: result[:message] }
+ })
+ end
+end
diff --git a/app/controllers/concerns/renders_assignees.rb b/app/controllers/concerns/renders_assignees.rb
new file mode 100644
index 00000000000..e9583a7a530
--- /dev/null
+++ b/app/controllers/concerns/renders_assignees.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+module RendersAssignees
+ def preload_assignees_for_render(merge_request)
+ merge_request.project.team.max_member_access_for_user_ids(merge_request.assignees.map(&:id))
+ end
+end
diff --git a/app/controllers/concerns/sessionless_authentication.rb b/app/controllers/concerns/sessionless_authentication.rb
index ba06384a37a..f644923443b 100644
--- a/app/controllers/concerns/sessionless_authentication.rb
+++ b/app/controllers/concerns/sessionless_authentication.rb
@@ -5,6 +5,12 @@
# Controller concern to handle PAT, RSS, and static objects token authentication methods
#
module SessionlessAuthentication
+ extend ActiveSupport::Concern
+
+ included do
+ before_action :enable_admin_mode!, if: :sessionless_user?
+ end
+
# This filter handles personal access tokens, atom requests with rss tokens, and static object tokens
def authenticate_sessionless_user!(request_format)
user = Gitlab::Auth::RequestAuthenticator.new(request).find_sessionless_user(request_format)
@@ -25,4 +31,8 @@ module SessionlessAuthentication
sign_in(user, store: false, message: :sessionless_sign_in)
end
end
+
+ def enable_admin_mode!
+ current_user_mode.enable_admin_mode!(skip_password_validation: true) if Feature.enabled?(:user_mode_in_session)
+ end
end
diff --git a/app/controllers/concerns/uploads_actions.rb b/app/controllers/concerns/uploads_actions.rb
index 60a68cec3c3..6d9ee39f841 100644
--- a/app/controllers/concerns/uploads_actions.rb
+++ b/app/controllers/concerns/uploads_actions.rb
@@ -29,15 +29,17 @@ module UploadsActions
def show
return render_404 unless uploader&.exists?
- if cache_publicly?
- # We need to reset caching from the applications controller to get rid of the no-store value
- headers['Cache-Control'] = ''
- expires_in 5.minutes, public: true, must_revalidate: false
- else
- expires_in 0.seconds, must_revalidate: true, private: true
- end
+ # We need to reset caching from the applications controller to get rid of the no-store value
+ headers['Cache-Control'] = ''
+ headers['Pragma'] = ''
+
+ ttl, directives = *cache_settings
+ ttl ||= 6.months
+ directives ||= { private: true, must_revalidate: true }
+
+ expires_in ttl, directives
- disposition = uploader.image_or_video? ? 'inline' : 'attachment'
+ disposition = uploader.embeddable? ? 'inline' : 'attachment'
uploaders = [uploader, *uploader.versions.values]
uploader = uploaders.find { |version| version.filename == params[:filename] }
@@ -91,7 +93,7 @@ module UploadsActions
upload_paths = uploader.upload_paths(params[:filename])
upload = Upload.find_by(model: model, uploader: uploader_class.to_s, path: upload_paths)
- upload&.build_uploader
+ upload&.retrieve_uploader
end
# rubocop: enable CodeReuse/ActiveRecord
@@ -112,16 +114,16 @@ module UploadsActions
uploader
end
- def image_or_video?
- uploader && uploader.exists? && uploader.image_or_video?
+ def embeddable?
+ uploader && uploader.exists? && uploader.embeddable?
end
def find_model
nil
end
- def cache_publicly?
- false
+ def cache_settings
+ []
end
def model
diff --git a/app/controllers/dashboard/todos_controller.rb b/app/controllers/dashboard/todos_controller.rb
index 7012bfcefe3..80c0a0d88a8 100644
--- a/app/controllers/dashboard/todos_controller.rb
+++ b/app/controllers/dashboard/todos_controller.rb
@@ -78,8 +78,8 @@ class Dashboard::TodosController < Dashboard::ApplicationController
def todos_counts
{
- count: number_with_delimiter(current_user.todos_pending_count),
- done_count: number_with_delimiter(current_user.todos_done_count)
+ count: current_user.todos_pending_count,
+ done_count: current_user.todos_done_count
}
end
diff --git a/app/controllers/explore/snippets_controller.rb b/app/controllers/explore/snippets_controller.rb
index d4c6aae2ca8..61068df77d1 100644
--- a/app/controllers/explore/snippets_controller.rb
+++ b/app/controllers/explore/snippets_controller.rb
@@ -5,7 +5,7 @@ class Explore::SnippetsController < Explore::ApplicationController
include Gitlab::NoteableMetadata
def index
- @snippets = SnippetsFinder.new(current_user)
+ @snippets = SnippetsFinder.new(current_user, explore: true)
.execute
.page(params[:page])
.inc_author
diff --git a/app/controllers/groups/boards_controller.rb b/app/controllers/groups/boards_controller.rb
index 40b8d5ed72c..3c86f3108ab 100644
--- a/app/controllers/groups/boards_controller.rb
+++ b/app/controllers/groups/boards_controller.rb
@@ -5,6 +5,9 @@ class Groups::BoardsController < Groups::ApplicationController
include RecordUserLastActivity
before_action :assign_endpoint_vars
+ before_action do
+ push_frontend_feature_flag(:multi_select_board)
+ end
private
diff --git a/app/controllers/groups/milestones_controller.rb b/app/controllers/groups/milestones_controller.rb
index 1eacae06457..1e9d51cf970 100644
--- a/app/controllers/groups/milestones_controller.rb
+++ b/app/controllers/groups/milestones_controller.rb
@@ -44,7 +44,7 @@ class Groups::MilestonesController < Groups::ApplicationController
# all projects milestones states at once.
milestones, update_params = get_milestones_for_update
milestones.each do |milestone|
- Milestones::UpdateService.new(milestone.parent, current_user, update_params).execute(milestone)
+ Milestones::UpdateService.new(milestone.resource_parent, current_user, update_params).execute(milestone)
end
redirect_to milestone_path
diff --git a/app/controllers/groups/registry/repositories_controller.rb b/app/controllers/groups/registry/repositories_controller.rb
new file mode 100644
index 00000000000..e09a9e6eb21
--- /dev/null
+++ b/app/controllers/groups/registry/repositories_controller.rb
@@ -0,0 +1,39 @@
+# frozen_string_literal: true
+module Groups
+ module Registry
+ class RepositoriesController < Groups::ApplicationController
+ before_action :verify_container_registry_enabled!
+ before_action :authorize_read_container_image!
+ before_action :feature_flag_group_container_registry_browser!
+
+ def index
+ track_event(:list_repositories)
+
+ respond_to do |format|
+ format.html
+ format.json do
+ @images = group.container_repositories.with_api_entity_associations
+
+ render json: ContainerRepositoriesSerializer
+ .new(current_user: current_user)
+ .represent(@images)
+ end
+ end
+ end
+
+ private
+
+ def feature_flag_group_container_registry_browser!
+ render_404 unless Feature.enabled?(:group_container_registry_browser, group)
+ end
+
+ def verify_container_registry_enabled!
+ render_404 unless Gitlab.config.registry.enabled
+ end
+
+ def authorize_read_container_image!
+ return render_404 unless can?(current_user, :read_container_image, group)
+ end
+ end
+ end
+end
diff --git a/app/controllers/groups/settings/ci_cd_controller.rb b/app/controllers/groups/settings/ci_cd_controller.rb
index c465e622de0..0e83d057484 100644
--- a/app/controllers/groups/settings/ci_cd_controller.rb
+++ b/app/controllers/groups/settings/ci_cd_controller.rb
@@ -5,11 +5,22 @@ module Groups
class CiCdController < Groups::ApplicationController
skip_cross_project_access_check :show
before_action :authorize_admin_group!
+ before_action :authorize_update_max_artifacts_size!, only: [:update]
def show
define_ci_variables
end
+ def update
+ if update_group_service.execute
+ flash[:notice] = s_('GroupSettings|Pipeline settings was updated for the group')
+ else
+ flash[:alert] = s_("GroupSettings|There was a problem updating the pipeline settings: %{error_messages}." % { error_messages: group.errors.full_messages })
+ end
+
+ redirect_to group_settings_ci_cd_path
+ end
+
def reset_registration_token
@group.reset_runners_token!
@@ -40,6 +51,10 @@ module Groups
return render_404 unless can?(current_user, :admin_group, group)
end
+ def authorize_update_max_artifacts_size!
+ return render_404 unless can?(current_user, :update_max_artifacts_size, group)
+ end
+
def auto_devops_params
params.require(:group).permit(:auto_devops_enabled)
end
@@ -47,6 +62,14 @@ module Groups
def auto_devops_service
Groups::AutoDevopsService.new(group, current_user, auto_devops_params)
end
+
+ def update_group_service
+ Groups::UpdateService.new(group, current_user, update_group_params)
+ end
+
+ def update_group_params
+ params.require(:group).permit(:max_artifacts_size)
+ end
end
end
end
diff --git a/app/controllers/groups/uploads_controller.rb b/app/controllers/groups/uploads_controller.rb
index 7e5cdae0ce3..3ae7e36c740 100644
--- a/app/controllers/groups/uploads_controller.rb
+++ b/app/controllers/groups/uploads_controller.rb
@@ -4,7 +4,7 @@ class Groups::UploadsController < Groups::ApplicationController
include UploadsActions
include WorkhorseRequest
- skip_before_action :group, if: -> { action_name == 'show' && image_or_video? }
+ skip_before_action :group, if: -> { action_name == 'show' && embeddable? }
before_action :authorize_upload_file!, only: [:create, :authorize]
before_action :verify_workhorse_api!, only: [:authorize]
diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb
index 95a7876a055..35e364abba3 100644
--- a/app/controllers/groups_controller.rb
+++ b/app/controllers/groups_controller.rb
@@ -104,7 +104,6 @@ class GroupsController < Groups::ApplicationController
redirect_to edit_group_path(@group, anchor: params[:update_section]), notice: "Group '#{@group.name}' was successfully updated."
else
@group.path = @group.path_before_last_save || @group.path_was
-
render action: "edit"
end
end
@@ -124,7 +123,7 @@ class GroupsController < Groups::ApplicationController
flash[:notice] = "Group '#{@group.name}' was successfully transferred."
redirect_to group_path(@group)
else
- flash[:alert] = service.error
+ flash[:alert] = service.error.html_safe
redirect_to edit_group_path(@group)
end
end
@@ -198,15 +197,13 @@ class GroupsController < Groups::ApplicationController
def load_events
params[:sort] ||= 'latest_activity_desc'
- options = {}
- options[:include_subgroups] = true
-
- @projects = GroupProjectsFinder.new(params: params, group: group, options: options, current_user: current_user)
- .execute
- .includes(:namespace)
+ options = { include_subgroups: true }
+ projects = GroupProjectsFinder.new(params: params, group: group, options: options, current_user: current_user)
+ .execute
+ .includes(:namespace)
@events = EventCollection
- .new(@projects, offset: params[:offset].to_i, filter: event_filter)
+ .new(projects, offset: params[:offset].to_i, filter: event_filter, groups: groups)
.to_a
Events::RenderService
@@ -228,6 +225,14 @@ class GroupsController < Groups::ApplicationController
url_for(safe_params)
end
+
+ private
+
+ def groups
+ if @group.supports_events?
+ @group.self_and_descendants.public_or_visible_to_user(current_user)
+ end
+ end
end
GroupsController.prepend_if_ee('EE::GroupsController')
diff --git a/app/controllers/health_controller.rb b/app/controllers/health_controller.rb
index dc9a52f8da5..efd5f0fc607 100644
--- a/app/controllers/health_controller.rb
+++ b/app/controllers/health_controller.rb
@@ -14,35 +14,25 @@ class HealthController < ActionController::Base
].freeze
def readiness
- results = CHECKS.map { |check| [check.name, check.readiness] }
-
- render_check_results(results)
+ # readiness check is a collection with all above application-level checks
+ render_checks(*CHECKS)
end
def liveness
- results = CHECKS.map { |check| [check.name, check.liveness] }
-
- render_check_results(results)
+ # liveness check is a collection without additional checks
+ render_checks
end
private
- def render_check_results(results)
- flattened = results.flat_map do |name, result|
- if result.is_a?(Gitlab::HealthChecks::Result)
- [[name, result]]
- else
- result.map { |r| [name, r] }
- end
- end
- success = flattened.all? { |name, r| r.success }
-
- response = flattened.map do |name, r|
- info = { status: r.success ? 'ok' : 'failed' }
- info['message'] = r.message if r.message
- info[:labels] = r.labels if r.labels
- [name, info]
- end
- render json: response.to_h, status: success ? :ok : :service_unavailable
+ def render_checks(*checks)
+ result = Gitlab::HealthChecks::Probes::Collection
+ .new(*checks)
+ .execute
+
+ # disable static error pages at the gitlab-workhorse level, we want to see this error response even in production
+ headers["X-GitLab-Custom-Error"] = 1 unless result.success?
+
+ render json: result.json, status: result.http_status
end
end
diff --git a/app/controllers/help_controller.rb b/app/controllers/help_controller.rb
index 837c26c630a..a58235790ad 100644
--- a/app/controllers/help_controller.rb
+++ b/app/controllers/help_controller.rb
@@ -40,8 +40,8 @@ class HelpController < ApplicationController
end
end
- # Allow access to images in the doc folder
- format.any(:png, :gif, :jpeg, :mp4) do
+ # Allow access to specific media files in the doc folder
+ format.any(:png, :gif, :jpeg, :mp4, :mp3) do
# Note: We are purposefully NOT using `Rails.root.join`
path = File.join(Rails.root, 'doc', "#{@path}.#{params[:format]}")
diff --git a/app/controllers/import/bitbucket_controller.rb b/app/controllers/import/bitbucket_controller.rb
index 293d76ea765..c37e799de62 100644
--- a/app/controllers/import/bitbucket_controller.rb
+++ b/app/controllers/import/bitbucket_controller.rb
@@ -1,6 +1,8 @@
# frozen_string_literal: true
class Import::BitbucketController < Import::BaseController
+ include ActionView::Helpers::SanitizeHelper
+
before_action :verify_bitbucket_import_enabled
before_action :bitbucket_auth, except: :callback
@@ -21,7 +23,7 @@ class Import::BitbucketController < Import::BaseController
# rubocop: disable CodeReuse/ActiveRecord
def status
bitbucket_client = Bitbucket::Client.new(credentials)
- repos = bitbucket_client.repos
+ repos = bitbucket_client.repos(filter: sanitized_filter_param)
@repos, @incompatible_repos = repos.partition { |repo| repo.valid? }
@@ -104,4 +106,8 @@ class Import::BitbucketController < Import::BaseController
refresh_token: session[:bitbucket_refresh_token]
}
end
+
+ def sanitized_filter_param
+ @filter ||= sanitize(params[:filter])
+ end
end
diff --git a/app/controllers/import/github_controller.rb b/app/controllers/import/github_controller.rb
index 72f830fc9a1..c418b11ab13 100644
--- a/app/controllers/import/github_controller.rb
+++ b/app/controllers/import/github_controller.rb
@@ -2,6 +2,7 @@
class Import::GithubController < Import::BaseController
include ImportHelper
+ include ActionView::Helpers::SanitizeHelper
before_action :verify_import_enabled
before_action :provider_auth, only: [:status, :realtime_changes, :create]
@@ -55,7 +56,7 @@ class Import::GithubController < Import::BaseController
def realtime_changes
Gitlab::PollingInterval.set_header(response, interval: 3_000)
- render json: find_jobs(provider)
+ render json: already_added_projects.to_json(only: [:id], methods: [:import_status])
end
private
@@ -82,7 +83,7 @@ class Import::GithubController < Import::BaseController
end
def already_added_projects
- @already_added_projects ||= find_already_added_projects(provider)
+ @already_added_projects ||= filtered(find_already_added_projects(provider))
end
def already_added_project_names
@@ -104,7 +105,7 @@ class Import::GithubController < Import::BaseController
end
def client_repos
- @client_repos ||= client.repos
+ @client_repos ||= filtered(client.repos)
end
def verify_import_enabled
@@ -185,6 +186,20 @@ class Import::GithubController < Import::BaseController
def extra_import_params
{}
end
+
+ def sanitized_filter_param
+ @filter ||= sanitize(params[:filter])
+ end
+
+ def filter_attribute
+ :name
+ end
+
+ def filtered(collection)
+ return collection unless sanitized_filter_param
+
+ collection.select { |item| item[filter_attribute].include?(sanitized_filter_param) }
+ end
end
Import::GithubController.prepend_if_ee('EE::Import::GithubController')
diff --git a/app/controllers/notification_settings_controller.rb b/app/controllers/notification_settings_controller.rb
index 43c4f4d220e..c97fec0a6ee 100644
--- a/app/controllers/notification_settings_controller.rb
+++ b/app/controllers/notification_settings_controller.rb
@@ -50,8 +50,6 @@ class NotificationSettingsController < ApplicationController
end
def notification_setting_params_for(source)
- allowed_fields = NotificationSetting.email_events(source).dup
- allowed_fields << :level
- params.require(:notification_setting).permit(allowed_fields)
+ params.require(:notification_setting).permit(NotificationSetting.allowed_fields(source))
end
end
diff --git a/app/controllers/oauth/applications_controller.rb b/app/controllers/oauth/applications_controller.rb
index ab4ca56bb49..12dc2d1af1c 100644
--- a/app/controllers/oauth/applications_controller.rb
+++ b/app/controllers/oauth/applications_controller.rb
@@ -5,6 +5,7 @@ class Oauth::ApplicationsController < Doorkeeper::ApplicationsController
include Gitlab::Allowable
include PageLayoutHelper
include OauthApplications
+ include Gitlab::Experimentation::ControllerConcern
before_action :verify_user_oauth_applications_enabled, except: :index
before_action :authenticate_user!
diff --git a/app/controllers/oauth/authorizations_controller.rb b/app/controllers/oauth/authorizations_controller.rb
index 705389749d8..e65726dffbf 100644
--- a/app/controllers/oauth/authorizations_controller.rb
+++ b/app/controllers/oauth/authorizations_controller.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
class Oauth::AuthorizationsController < Doorkeeper::AuthorizationsController
+ include Gitlab::Experimentation::ControllerConcern
layout 'profile'
# Overridden from Doorkeeper::AuthorizationsController to
diff --git a/app/controllers/omniauth_callbacks_controller.rb b/app/controllers/omniauth_callbacks_controller.rb
index 755ce3463c4..b992972dfb8 100644
--- a/app/controllers/omniauth_callbacks_controller.rb
+++ b/app/controllers/omniauth_callbacks_controller.rb
@@ -148,6 +148,11 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
if user.two_factor_enabled? && !auth_user.bypass_two_factor?
prompt_for_two_factor(user)
else
+ if user.deactivated?
+ user.activate
+ flash[:notice] = _('Welcome back! Your account had been deactivated due to inactivity but is now reactivated.')
+ end
+
sign_in_and_redirect(user, event: :authentication)
end
else
diff --git a/app/controllers/profiles/groups_controller.rb b/app/controllers/profiles/groups_controller.rb
index c755bcb718a..04b5ee270dc 100644
--- a/app/controllers/profiles/groups_controller.rb
+++ b/app/controllers/profiles/groups_controller.rb
@@ -5,7 +5,7 @@ class Profiles::GroupsController < Profiles::ApplicationController
def update
group = find_routable!(Group, params[:id])
- notification_setting = current_user.notification_settings.find_by(source: group) # rubocop: disable CodeReuse/ActiveRecord
+ notification_setting = current_user.notification_settings_for(group)
if notification_setting.update(update_params)
flash[:notice] = "Notification settings for #{group.name} saved"
diff --git a/app/controllers/profiles/notifications_controller.rb b/app/controllers/profiles/notifications_controller.rb
index 617e5bb7cb3..5f44e55f3ef 100644
--- a/app/controllers/profiles/notifications_controller.rb
+++ b/app/controllers/profiles/notifications_controller.rb
@@ -3,9 +3,14 @@
class Profiles::NotificationsController < Profiles::ApplicationController
# rubocop: disable CodeReuse/ActiveRecord
def show
- @user = current_user
- @group_notifications = current_user.notification_settings.for_groups.order(:id)
- @project_notifications = current_user.notification_settings.for_projects.order(:id)
+ @user = current_user
+ @group_notifications = current_user.notification_settings.for_groups.order(:id)
+ @group_notifications += GroupsFinder.new(
+ current_user,
+ all_available: false,
+ exclude_group_ids: @group_notifications.select(:source_id)
+ ).execute.map { |group| current_user.notification_settings_for(group, inherit: true) }
+ @project_notifications = current_user.notification_settings.for_projects.order(:id)
@global_notification_setting = current_user.global_notification_setting
end
# rubocop: enable CodeReuse/ActiveRecord
diff --git a/app/controllers/profiles_controller.rb b/app/controllers/profiles_controller.rb
index 958a24b6c0e..2b7571e42b7 100644
--- a/app/controllers/profiles_controller.rb
+++ b/app/controllers/profiles_controller.rb
@@ -100,6 +100,7 @@ class ProfilesController < Profiles::ApplicationController
:avatar,
:bio,
:email,
+ :role,
:hide_no_password,
:hide_no_ssh_key,
:hide_project_limit,
diff --git a/app/controllers/projects/artifacts_controller.rb b/app/controllers/projects/artifacts_controller.rb
index da8a371acaa..50399a8cfbb 100644
--- a/app/controllers/projects/artifacts_controller.rb
+++ b/app/controllers/projects/artifacts_controller.rb
@@ -8,10 +8,37 @@ class Projects::ArtifactsController < Projects::ApplicationController
layout 'project'
before_action :authorize_read_build!
before_action :authorize_update_build!, only: [:keep]
+ before_action :authorize_destroy_artifacts!, only: [:destroy]
before_action :extract_ref_name_and_path
- before_action :validate_artifacts!, except: [:download]
+ before_action :validate_artifacts!, except: [:index, :download, :destroy]
before_action :entry, only: [:file]
+ MAX_PER_PAGE = 20
+
+ def index
+ # Loading artifacts is very expensive in projects with a lot of artifacts.
+ # This feature flag prevents a DOS attack vector.
+ # It should be removed only after resolving the underlying performance
+ # issues: https://gitlab.com/gitlab-org/gitlab/issues/32281
+ return head :no_content unless Feature.enabled?(:artifacts_management_page, @project)
+
+ finder = ArtifactsFinder.new(@project, artifacts_params)
+ all_artifacts = finder.execute
+
+ @artifacts = all_artifacts.page(params[:page]).per(MAX_PER_PAGE)
+ @total_size = all_artifacts.total_size
+ end
+
+ def destroy
+ notice = if artifact.destroy
+ _('Artifact was successfully deleted.')
+ else
+ _('Artifact could not be deleted.')
+ end
+
+ redirect_to project_artifacts_path(@project), status: :see_other, notice: notice
+ end
+
def download
return render_404 unless artifacts_file
@@ -74,6 +101,10 @@ class Projects::ArtifactsController < Projects::ApplicationController
@ref_name, @path = extract_ref(params[:ref_name_and_path])
end
+ def artifacts_params
+ params.permit(:sort)
+ end
+
def validate_artifacts!
render_404 unless build&.artifacts?
end
@@ -85,6 +116,11 @@ class Projects::ArtifactsController < Projects::ApplicationController
end
end
+ def artifact
+ @artifact ||=
+ project.job_artifacts.find(params[:id])
+ end
+
def build_from_id
project.builds.find_by_id(params[:job_id]) if params[:job_id]
end
diff --git a/app/controllers/projects/boards_controller.rb b/app/controllers/projects/boards_controller.rb
index 14b02993e6e..3b335fa4af4 100644
--- a/app/controllers/projects/boards_controller.rb
+++ b/app/controllers/projects/boards_controller.rb
@@ -7,6 +7,9 @@ class Projects::BoardsController < Projects::ApplicationController
before_action :check_issues_available!
before_action :authorize_read_board!, only: [:index, :show]
before_action :assign_endpoint_vars
+ before_action do
+ push_frontend_feature_flag(:multi_select_board)
+ end
private
diff --git a/app/controllers/projects/branches_controller.rb b/app/controllers/projects/branches_controller.rb
index c125ed3605a..578a3d451a7 100644
--- a/app/controllers/projects/branches_controller.rb
+++ b/app/controllers/projects/branches_controller.rb
@@ -11,6 +11,7 @@ class Projects::BranchesController < Projects::ApplicationController
# Support legacy URLs
before_action :redirect_for_legacy_index_sort_or_search, only: [:index]
+ before_action :limit_diverging_commit_counts!, only: [:diverging_commit_counts]
def index
respond_to do |format|
@@ -125,6 +126,24 @@ class Projects::BranchesController < Projects::ApplicationController
private
+ # It can be expensive to calculate the diverging counts for each
+ # branch. Normally the frontend should be specifying a set of branch
+ # names, but prior to
+ # https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/32496, the
+ # frontend could omit this set. To prevent excessive I/O, we require
+ # that a list of names be specified.
+ def limit_diverging_commit_counts!
+ return unless Feature.enabled?(:limit_diverging_commit_counts, default_enabled: true)
+
+ limit = Kaminari.config.default_per_page
+
+ # If we don't have many branches in the repository, then go ahead.
+ return if project.repository.branch_count <= limit
+ return if params[:names].present? && Array(params[:names]).length <= limit
+
+ render json: { error: "Specify at least one and at most #{limit} branch names" }, status: :unprocessable_entity
+ end
+
def ref
if params[:ref]
ref_escaped = strip_tags(sanitize(params[:ref]))
diff --git a/app/controllers/projects/commits_controller.rb b/app/controllers/projects/commits_controller.rb
index 76705b4410c..15bb35dd0be 100644
--- a/app/controllers/projects/commits_controller.rb
+++ b/app/controllers/projects/commits_controller.rb
@@ -72,7 +72,9 @@ class Projects::CommitsController < Projects::ApplicationController
@repository.commits(@ref, path: @path, limit: @limit, offset: @offset)
end
- @commits = @commits.with_pipeline_status
+ @commits.each(&:lazy_author) # preload authors
+
+ @commits = @commits.with_latest_pipeline(@ref)
@commits = set_commits_for_rendering(@commits)
end
diff --git a/app/controllers/projects/cycle_analytics/events_controller.rb b/app/controllers/projects/cycle_analytics/events_controller.rb
index 926592b9681..673f53c221b 100644
--- a/app/controllers/projects/cycle_analytics/events_controller.rb
+++ b/app/controllers/projects/cycle_analytics/events_controller.rb
@@ -23,7 +23,7 @@ module Projects
end
def test
- options(cycle_analytics_params)[:branch] = cycle_analytics_params[:branch_name]
+ options(cycle_analytics_project_params)[:branch] = cycle_analytics_project_params[:branch_name]
render_events(cycle_analytics[:test].events)
end
@@ -50,13 +50,7 @@ module Projects
end
def cycle_analytics
- @cycle_analytics ||= ::CycleAnalytics::ProjectLevel.new(project, options: options(cycle_analytics_params))
- end
-
- def cycle_analytics_params
- return {} unless params[:cycle_analytics].present?
-
- params[:cycle_analytics].permit(:start_date, :branch_name)
+ @cycle_analytics ||= ::CycleAnalytics::ProjectLevel.new(project, options: options(cycle_analytics_project_params))
end
end
end
diff --git a/app/controllers/projects/cycle_analytics_controller.rb b/app/controllers/projects/cycle_analytics_controller.rb
index b9d7dbd37be..f13c75ac4cc 100644
--- a/app/controllers/projects/cycle_analytics_controller.rb
+++ b/app/controllers/projects/cycle_analytics_controller.rb
@@ -9,7 +9,7 @@ class Projects::CycleAnalyticsController < Projects::ApplicationController
before_action :authorize_read_cycle_analytics!
def show
- @cycle_analytics = ::CycleAnalytics::ProjectLevel.new(@project, options: options(cycle_analytics_params))
+ @cycle_analytics = ::CycleAnalytics::ProjectLevel.new(@project, options: options(cycle_analytics_project_params))
@cycle_analytics_no_data = @cycle_analytics.no_stats?
@@ -27,12 +27,6 @@ class Projects::CycleAnalyticsController < Projects::ApplicationController
private
- def cycle_analytics_params
- return {} unless params[:cycle_analytics].present?
-
- params[:cycle_analytics].permit(:start_date)
- end
-
def cycle_analytics_json
{
summary: @cycle_analytics.summary,
diff --git a/app/controllers/projects/deploy_keys_controller.rb b/app/controllers/projects/deploy_keys_controller.rb
index 514b03e23b5..f13fb4d0b3d 100644
--- a/app/controllers/projects/deploy_keys_controller.rb
+++ b/app/controllers/projects/deploy_keys_controller.rb
@@ -73,6 +73,10 @@ class Projects::DeployKeysController < Projects::ApplicationController
@deploy_key ||= DeployKey.find(params[:id])
end
+ def deploy_keys_project
+ @deploy_keys_project ||= deploy_key.deploy_keys_project_for(@project)
+ end
+
def create_params
create_params = params.require(:deploy_key)
.permit(:key, :title, deploy_keys_projects_attributes: [:can_push])
@@ -81,10 +85,16 @@ class Projects::DeployKeysController < Projects::ApplicationController
end
def update_params
- params.require(:deploy_key).permit(:title, deploy_keys_projects_attributes: [:id, :can_push])
+ permitted_params = [deploy_keys_projects_attributes: [:id, :can_push]]
+ permitted_params << :title if can?(current_user, :update_deploy_key, deploy_key)
+
+ params.require(:deploy_key).permit(*permitted_params)
end
def authorize_update_deploy_key!
- access_denied! unless can?(current_user, :update_deploy_key, deploy_key)
+ if !can?(current_user, :update_deploy_key, deploy_key) &&
+ !can?(current_user, :update_deploy_keys_project, deploy_keys_project)
+ access_denied!
+ end
end
end
diff --git a/app/controllers/projects/deployments_controller.rb b/app/controllers/projects/deployments_controller.rb
index 32111b07a0b..766e2f86ea2 100644
--- a/app/controllers/projects/deployments_controller.rb
+++ b/app/controllers/projects/deployments_controller.rb
@@ -47,11 +47,9 @@ class Projects::DeploymentsController < Projects::ApplicationController
@deployment_metrics ||= DeploymentMetrics.new(deployment.project, deployment)
end
- # rubocop: disable CodeReuse/ActiveRecord
def deployment
- @deployment ||= environment.deployments.find_by(iid: params[:id])
+ @deployment ||= environment.deployments.find_successful_deployment!(params[:id])
end
- # rubocop: enable CodeReuse/ActiveRecord
def environment
@environment ||= project.environments.find(params[:environment_id])
diff --git a/app/controllers/projects/environments/prometheus_api_controller.rb b/app/controllers/projects/environments/prometheus_api_controller.rb
index 9c6c6513a78..e902d218c75 100644
--- a/app/controllers/projects/environments/prometheus_api_controller.rb
+++ b/app/controllers/projects/environments/prometheus_api_controller.rb
@@ -1,6 +1,8 @@
# frozen_string_literal: true
class Projects::Environments::PrometheusApiController < Projects::ApplicationController
+ include RenderServiceResults
+
before_action :authorize_read_prometheus!
before_action :environment
@@ -12,21 +14,10 @@ class Projects::Environments::PrometheusApiController < Projects::ApplicationCon
proxy_params
).execute
- if result.nil?
- return render status: :no_content, json: {
- status: _('processing'),
- message: _('Not ready yet. Try again later.')
- }
- end
-
- if result[:status] == :success
- render status: result[:http_status], json: result[:body]
- else
- render(
- status: result[:http_status] || :bad_request,
- json: { status: result[:status], message: result[:message] }
- )
- end
+ return continue_polling_response if result.nil?
+ return error_response(result) if result[:status] == :error
+
+ success_response(result)
end
private
diff --git a/app/controllers/projects/environments_controller.rb b/app/controllers/projects/environments_controller.rb
index 64de0e665d3..c053ca19a94 100644
--- a/app/controllers/projects/environments_controller.rb
+++ b/app/controllers/projects/environments_controller.rb
@@ -1,6 +1,8 @@
# frozen_string_literal: true
class Projects::EnvironmentsController < Projects::ApplicationController
+ include MetricsDashboard
+
layout 'project'
before_action :authorize_read_environment!
before_action :authorize_create_environment!, only: [:new, :create]
@@ -12,7 +14,6 @@ class Projects::EnvironmentsController < Projects::ApplicationController
before_action :expire_etag_cache, only: [:index]
before_action only: [:metrics, :additional_metrics, :metrics_dashboard] do
push_frontend_feature_flag(:environment_metrics_use_prometheus_endpoint, default_enabled: true)
- push_frontend_feature_flag(:environment_metrics_show_multiple_dashboards)
push_frontend_feature_flag(:environment_metrics_additional_panel_types)
push_frontend_feature_flag(:prometheus_computed_alerts)
end
@@ -159,44 +160,6 @@ class Projects::EnvironmentsController < Projects::ApplicationController
end
end
- def metrics_dashboard
- if params[:embedded]
- result = dashboard_finder.find(
- project,
- current_user,
- environment: environment,
- dashboard_path: params[:dashboard],
- **dashboard_params.to_h.symbolize_keys
- )
- elsif Feature.enabled?(:environment_metrics_show_multiple_dashboards, project)
- result = dashboard_finder.find(
- project,
- current_user,
- environment: environment,
- dashboard_path: params[:dashboard]
- )
-
- result[:all_dashboards] = dashboard_finder.find_all_paths(project)
- else
- result = dashboard_finder.find(project, current_user, environment: environment)
- end
-
- respond_to do |format|
- if result[:status] == :success
- format.json do
- render status: :ok, json: result.slice(:all_dashboards, :dashboard, :status)
- end
- else
- format.json do
- render(
- status: result[:http_status],
- json: result.slice(:all_dashboards, :message, :status)
- )
- end
- end
- end
- end
-
def search
respond_to do |format|
format.json do
@@ -234,12 +197,15 @@ class Projects::EnvironmentsController < Projects::ApplicationController
params.require([:start, :end])
end
- def dashboard_params
- params.permit(:embedded, :group, :title, :y_label)
+ def metrics_dashboard_params
+ params
+ .permit(:embedded, :group, :title, :y_label)
+ .to_h.symbolize_keys
+ .merge(dashboard_path: params[:dashboard], environment: environment)
end
- def dashboard_finder
- Gitlab::Metrics::Dashboard::Finder
+ def include_all_dashboards?
+ !params[:embedded]
end
def search_environment_names
diff --git a/app/controllers/projects/git_http_client_controller.rb b/app/controllers/projects/git_http_client_controller.rb
index a597cc9af32..ccfc38d97b2 100644
--- a/app/controllers/projects/git_http_client_controller.rb
+++ b/app/controllers/projects/git_http_client_controller.rb
@@ -1,7 +1,5 @@
# frozen_string_literal: true
-# This file should be identical in GitLab Community Edition and Enterprise Edition
-
class Projects::GitHttpClientController < Projects::ApplicationController
include ActionController::HttpAuthentication::Basic
include KerberosSpnegoHelper
diff --git a/app/controllers/projects/git_http_controller.rb b/app/controllers/projects/git_http_controller.rb
index 0c8c03cb16a..93f7ce73a51 100644
--- a/app/controllers/projects/git_http_controller.rb
+++ b/app/controllers/projects/git_http_controller.rb
@@ -6,10 +6,10 @@ class Projects::GitHttpController < Projects::GitHttpClientController
before_action :access_check
prepend_before_action :deny_head_requests, only: [:info_refs]
- rescue_from Gitlab::GitAccess::UnauthorizedError, with: :render_403
- rescue_from Gitlab::GitAccess::NotFoundError, with: :render_404
- rescue_from Gitlab::GitAccess::ProjectCreationError, with: :render_422
- rescue_from Gitlab::GitAccess::TimeoutError, with: :render_503
+ rescue_from Gitlab::GitAccess::UnauthorizedError, with: :render_403_with_exception
+ rescue_from Gitlab::GitAccess::NotFoundError, with: :render_404_with_exception
+ rescue_from Gitlab::GitAccess::ProjectCreationError, with: :render_422_with_exception
+ rescue_from Gitlab::GitAccess::TimeoutError, with: :render_503_with_exception
# GET /foo/bar.git/info/refs?service=git-upload-pack (git pull)
# GET /foo/bar.git/info/refs?service=git-receive-pack (git push)
@@ -58,19 +58,19 @@ class Projects::GitHttpController < Projects::GitHttpClientController
render json: Gitlab::Workhorse.git_http_ok(repository, repo_type, user, action_name)
end
- def render_403(exception)
+ def render_403_with_exception(exception)
render plain: exception.message, status: :forbidden
end
- def render_404(exception)
+ def render_404_with_exception(exception)
render plain: exception.message, status: :not_found
end
- def render_422(exception)
+ def render_422_with_exception(exception)
render plain: exception.message, status: :unprocessable_entity
end
- def render_503(exception)
+ def render_503_with_exception(exception)
render plain: exception.message, status: :service_unavailable
end
diff --git a/app/controllers/projects/grafana_api_controller.rb b/app/controllers/projects/grafana_api_controller.rb
new file mode 100644
index 00000000000..4bdf4c12cac
--- /dev/null
+++ b/app/controllers/projects/grafana_api_controller.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+class Projects::GrafanaApiController < Projects::ApplicationController
+ include RenderServiceResults
+
+ def proxy
+ result = ::Grafana::ProxyService.new(
+ project,
+ params[:datasource_id],
+ params[:proxy_path],
+ query_params.to_h
+ ).execute
+
+ return continue_polling_response if result.nil?
+ return error_response(result) if result[:status] == :error
+
+ success_response(result)
+ end
+
+ private
+
+ def query_params
+ params.permit(:query, :start, :end, :step)
+ end
+end
diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb
index 7a192a9ec2d..96cb400950b 100644
--- a/app/controllers/projects/issues_controller.rb
+++ b/app/controllers/projects/issues_controller.rb
@@ -42,6 +42,10 @@ class Projects::IssuesController < Projects::ApplicationController
before_action :authorize_import_issues!, only: [:import_csv]
before_action :authorize_download_code!, only: [:related_branches]
+ before_action do
+ push_frontend_feature_flag(:vue_issuable_sidebar, project.group)
+ end
+
respond_to :html
alias_method :designs, :show
diff --git a/app/controllers/projects/jobs_controller.rb b/app/controllers/projects/jobs_controller.rb
index 0fdd4d4f33d..1d914ab6011 100644
--- a/app/controllers/projects/jobs_controller.rb
+++ b/app/controllers/projects/jobs_controller.rb
@@ -11,8 +11,8 @@ class Projects::JobsController < Projects::ApplicationController
before_action :authorize_erase_build!, only: [:erase]
before_action :authorize_use_build_terminal!, only: [:terminal, :terminal_websocket_authorize]
before_action :verify_api_request!, only: :terminal_websocket_authorize
- before_action only: [:trace] do
- push_frontend_feature_flag(:job_log_json)
+ before_action only: [:show] do
+ push_frontend_feature_flag(:job_log_json, project)
end
layout 'project'
@@ -67,38 +67,27 @@ class Projects::JobsController < Projects::ApplicationController
# rubocop: enable CodeReuse/ActiveRecord
def trace
- if Feature.enabled?(:job_log_json, @project)
- json_trace
- else
- html_trace
- end
- end
-
- def html_trace
build.trace.read do |stream|
respond_to do |format|
format.json do
- result = {
- id: @build.id, status: @build.status, complete: @build.complete?
- }
-
- if stream.valid?
- stream.limit
- state = params[:state].presence
- trace = stream.html_with_state(state)
- result.merge!(trace.to_h)
- end
-
- render json: result
+ # TODO: when the feature flag is removed we should not pass
+ # content_format to serialize method.
+ content_format = Feature.enabled?(:job_log_json, @project) ? :json : :html
+
+ build_trace = Ci::BuildTrace.new(
+ build: @build,
+ stream: stream,
+ state: params[:state],
+ content_format: content_format)
+
+ render json: BuildTraceSerializer
+ .new(project: @project, current_user: @current_user)
+ .represent(build_trace)
end
end
end
end
- def json_trace
- # will be implemented with https://gitlab.com/gitlab-org/gitlab-foss/issues/66454
- end
-
def retry
return respond_422 unless @build.retryable?
diff --git a/app/controllers/projects/lfs_api_controller.rb b/app/controllers/projects/lfs_api_controller.rb
index 739f7a2437e..a1983bc5462 100644
--- a/app/controllers/projects/lfs_api_controller.rb
+++ b/app/controllers/projects/lfs_api_controller.rb
@@ -2,6 +2,7 @@
class Projects::LfsApiController < Projects::GitHttpClientController
include LfsRequest
+ include Gitlab::Utils::StrongMemoize
LFS_TRANSFER_CONTENT_TYPE = 'application/octet-stream'
@@ -81,7 +82,7 @@ class Projects::LfsApiController < Projects::GitHttpClientController
download: {
href: "#{project.http_url_to_repo}/gitlab-lfs/objects/#{object[:oid]}",
header: {
- Authorization: request.headers['Authorization']
+ Authorization: authorization_header
}.compact
}
}
@@ -92,7 +93,7 @@ class Projects::LfsApiController < Projects::GitHttpClientController
upload: {
href: "#{project.http_url_to_repo}/gitlab-lfs/objects/#{object[:oid]}/#{object[:size]}",
header: {
- Authorization: request.headers['Authorization'],
+ Authorization: authorization_header,
# git-lfs v2.5.0 sets the Content-Type based on the uploaded file. This
# ensures that Workhorse can intercept the request.
'Content-Type': LFS_TRANSFER_CONTENT_TYPE
@@ -122,6 +123,18 @@ class Projects::LfsApiController < Projects::GitHttpClientController
def lfs_read_only_message
_('You cannot write to this read-only GitLab instance.')
end
+
+ def authorization_header
+ strong_memoize(:authorization_header) do
+ lfs_auth_header || request.headers['Authorization']
+ end
+ end
+
+ def lfs_auth_header
+ return unless user.is_a?(User)
+
+ Gitlab::LfsToken.new(user).basic_encoding
+ end
end
Projects::LfsApiController.prepend_if_ee('EE::Projects::LfsApiController')
diff --git a/app/controllers/projects/merge_requests/application_controller.rb b/app/controllers/projects/merge_requests/application_controller.rb
index edffeb32203..b7e99cb7ed0 100644
--- a/app/controllers/projects/merge_requests/application_controller.rb
+++ b/app/controllers/projects/merge_requests/application_controller.rb
@@ -14,7 +14,11 @@ class Projects::MergeRequests::ApplicationController < Projects::ApplicationCont
end
def merge_request_includes(association)
- association.includes(:metrics, :assignees, author: :status) # rubocop:disable CodeReuse/ActiveRecord
+ association.includes(preloadable_mr_relations) # rubocop:disable CodeReuse/ActiveRecord
+ end
+
+ def preloadable_mr_relations
+ [:metrics, :assignees, { author: :status }]
end
def merge_request_params
diff --git a/app/controllers/projects/merge_requests/diffs_controller.rb b/app/controllers/projects/merge_requests/diffs_controller.rb
index 9c5caf7719e..4a37dfe5c19 100644
--- a/app/controllers/projects/merge_requests/diffs_controller.rb
+++ b/app/controllers/projects/merge_requests/diffs_controller.rb
@@ -5,9 +5,9 @@ class Projects::MergeRequests::DiffsController < Projects::MergeRequests::Applic
include RendersNotes
before_action :apply_diff_view_cookie!
- before_action :commit
- before_action :define_diff_vars
- before_action :define_diff_comment_vars
+ before_action :commit, except: :diffs_batch
+ before_action :define_diff_vars, except: :diffs_batch
+ before_action :define_diff_comment_vars, except: [:diffs_batch, :diffs_metadata]
def show
render_diffs
@@ -17,14 +17,41 @@ class Projects::MergeRequests::DiffsController < Projects::MergeRequests::Applic
render_diffs
end
+ def diffs_batch
+ return render_404 unless Feature.enabled?(:diffs_batch_load, @merge_request.project)
+
+ diffable = @merge_request.merge_request_diff
+
+ return render_404 unless diffable
+
+ diffs = diffable.diffs_in_batch(params[:page], params[:per_page], diff_options: diff_options)
+ positions = @merge_request.note_positions_for_paths(diffs.diff_file_paths, current_user)
+
+ diffs.unfold_diff_files(positions.unfoldable)
+
+ options = {
+ merge_request: @merge_request,
+ pagination_data: diffs.pagination_data
+ }
+
+ render json: PaginatedDiffSerializer.new(current_user: current_user).represent(diffs, options)
+ end
+
+ def diffs_metadata
+ render json: DiffsMetadataSerializer.new(project: @merge_request.project)
+ .represent(@diffs, additional_attributes)
+ end
+
private
+ def preloadable_mr_relations
+ [{ source_project: :namespace }, { target_project: :namespace }]
+ end
+
def render_diffs
@environment = @merge_request.environments_for(current_user).last
- note_positions = renderable_notes.map(&:position).compact
- @diffs.unfold_diff_files(note_positions)
-
+ @diffs.unfold_diff_files(note_positions.unfoldable)
@diffs.write_cache
request = {
@@ -111,6 +138,10 @@ class Projects::MergeRequests::DiffsController < Projects::MergeRequests::Applic
@notes = prepare_notes_for_rendering(@grouped_diff_discussions.values.flatten.flat_map(&:notes), @merge_request)
end
+ def note_positions
+ @note_positions ||= Gitlab::Diff::PositionCollection.new(renderable_notes.map(&:position))
+ end
+
def renderable_notes
define_diff_comment_vars unless @notes
diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb
index e51ce752233..ff199e05e99 100644
--- a/app/controllers/projects/merge_requests_controller.rb
+++ b/app/controllers/projects/merge_requests_controller.rb
@@ -5,6 +5,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
include IssuableActions
include RendersNotes
include RendersCommits
+ include RendersAssignees
include ToggleAwardEmoji
include IssuableCollections
include RecordUserLastActivity
@@ -16,6 +17,13 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
before_action :set_issuables_index, only: [:index]
before_action :authenticate_user!, only: [:assign_related_issues]
before_action :check_user_can_push_to_source_branch!, only: [:rebase]
+ before_action only: [:show] do
+ push_frontend_feature_flag(:diffs_batch_load, @project)
+ end
+
+ before_action do
+ push_frontend_feature_flag(:vue_issuable_sidebar, @project.group)
+ end
around_action :allow_gitaly_ref_name_caching, only: [:index, :show, :discussions]
@@ -41,6 +49,8 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
# use next to appease Rubocop
next render('invalid') if target_branch_missing?
+ preload_assignees_for_render(@merge_request)
+
# Build a note object for comment form
@note = @project.notes.new(noteable: @merge_request)
@@ -79,7 +89,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
# Get commits from repository
# or from cache if already merged
@commits =
- set_commits_for_rendering(@merge_request.commits.with_pipeline_status)
+ set_commits_for_rendering(@merge_request.commits.with_latest_pipeline)
render json: { html: view_to_html_string('projects/merge_requests/_commits') }
end
diff --git a/app/controllers/projects/pipelines_controller.rb b/app/controllers/projects/pipelines_controller.rb
index cfa46705483..106ef1b72c1 100644
--- a/app/controllers/projects/pipelines_controller.rb
+++ b/app/controllers/projects/pipelines_controller.rb
@@ -1,6 +1,8 @@
# frozen_string_literal: true
class Projects::PipelinesController < Projects::ApplicationController
+ include ::Gitlab::Utils::StrongMemoize
+
before_action :whitelist_query_limiting, only: [:create, :retry]
before_action :pipeline, except: [:index, :new, :create, :charts]
before_action :set_pipeline_path, only: [:show]
@@ -151,6 +153,19 @@ class Projects::PipelinesController < Projects::ApplicationController
@counts[:failed] = @project.all_pipelines.failed.count(:all)
end
+ def test_report
+ return unless Feature.enabled?(:junit_pipeline_view, project)
+
+ if pipeline_test_report == :error
+ render json: { status: :error_parsing_report }
+ return
+ end
+
+ render json: TestReportSerializer
+ .new(current_user: @current_user)
+ .represent(pipeline_test_report)
+ end
+
private
def serialize_pipelines
@@ -169,7 +184,7 @@ class Projects::PipelinesController < Projects::ApplicationController
end
def show_represent_params
- { grouped: true }
+ { grouped: true, expanded: params[:expanded].to_a.map(&:to_i) }
end
def create_params
@@ -217,6 +232,14 @@ class Projects::PipelinesController < Projects::ApplicationController
view_context.limited_counter_with_delimiter(finder.execute)
end
+
+ def pipeline_test_report
+ strong_memoize(:pipeline_test_report) do
+ @pipeline.test_reports
+ rescue Gitlab::Ci::Parsers::ParserError
+ :error
+ end
+ end
end
Projects::PipelinesController.prepend_if_ee('EE::Projects::PipelinesController')
diff --git a/app/controllers/projects/protected_branches_controller.rb b/app/controllers/projects/protected_branches_controller.rb
index c5454883060..d4f7d0bc521 100644
--- a/app/controllers/projects/protected_branches_controller.rb
+++ b/app/controllers/projects/protected_branches_controller.rb
@@ -19,9 +19,13 @@ class Projects::ProtectedBranchesController < Projects::ProtectedRefsController
[:merge_access_levels, :push_access_levels]
end
- def protected_ref_params
- params.require(:protected_branch).permit(:name,
- merge_access_levels_attributes: access_level_attributes,
- push_access_levels_attributes: access_level_attributes)
+ def protected_ref_params(*attrs)
+ attrs = ([:name,
+ merge_access_levels_attributes: access_level_attributes,
+ push_access_levels_attributes: access_level_attributes] + attrs).uniq
+
+ params.require(:protected_branch).permit(attrs)
end
end
+
+Projects::ProtectedBranchesController.prepend_if_ee('EE::Projects::ProtectedBranchesController')
diff --git a/app/controllers/projects/registry/repositories_controller.rb b/app/controllers/projects/registry/repositories_controller.rb
index e205e2fd4f8..9405fd526ae 100644
--- a/app/controllers/projects/registry/repositories_controller.rb
+++ b/app/controllers/projects/registry/repositories_controller.rb
@@ -8,6 +8,7 @@ module Projects
def index
@images = project.container_repositories
+ track_event(:list_repositories)
respond_to do |format|
format.html
@@ -21,6 +22,7 @@ module Projects
def destroy
DeleteContainerRepositoryWorker.perform_async(current_user.id, image.id)
+ track_event(:delete_repository)
respond_to do |format|
format.json { head :no_content }
diff --git a/app/controllers/projects/registry/tags_controller.rb b/app/controllers/projects/registry/tags_controller.rb
index 54e2faa2dd7..e572c56adf5 100644
--- a/app/controllers/projects/registry/tags_controller.rb
+++ b/app/controllers/projects/registry/tags_controller.rb
@@ -8,6 +8,7 @@ module Projects
LIMIT = 15
def index
+ track_event(:list_tags)
respond_to do |format|
format.json do
render json: ContainerTagsSerializer
@@ -19,14 +20,13 @@ module Projects
end
def destroy
- if tag.delete
- respond_to do |format|
- format.json { head :no_content }
- end
- else
- respond_to do |format|
- format.json { head :bad_request }
- end
+ result = Projects::ContainerRepository::DeleteTagsService
+ .new(image.project, current_user, tags: [params[:id]])
+ .execute(image)
+ track_event(:delete_tag)
+
+ respond_to do |format|
+ format.json { head(result[:status] == :success ? :ok : bad_request) }
end
end
@@ -42,21 +42,13 @@ module Projects
return
end
- @tags = tag_names.map { |tag_name| image.tag(tag_name) }
- unless @tags.all? { |tag| tag.valid_name? }
- head :bad_request
- return
- end
-
- success_count = 0
- @tags.each do |tag|
- if tag.delete
- success_count += 1
- end
- end
+ result = Projects::ContainerRepository::DeleteTagsService
+ .new(image.project, current_user, tags: tag_names)
+ .execute(image)
+ track_event(:delete_tag_bulk)
respond_to do |format|
- format.json { head(success_count == @tags.size ? :no_content : :bad_request) }
+ format.json { head(result[:status] == :success ? :no_content : :bad_request) }
end
end
@@ -70,10 +62,6 @@ module Projects
@image ||= project.container_repositories
.find(params[:repository_id])
end
-
- def tag
- @tag ||= image.tag(params[:id])
- end
end
end
end
diff --git a/app/controllers/projects/releases_controller.rb b/app/controllers/projects/releases_controller.rb
index 4c39ee4045f..717df9f09e0 100644
--- a/app/controllers/projects/releases_controller.rb
+++ b/app/controllers/projects/releases_controller.rb
@@ -4,6 +4,9 @@ class Projects::ReleasesController < Projects::ApplicationController
# Authorize
before_action :require_non_empty_project
before_action :authorize_read_release!
+ before_action do
+ push_frontend_feature_flag(:release_edit_page, project)
+ end
def index
end
diff --git a/app/controllers/projects/settings/ci_cd_controller.rb b/app/controllers/projects/settings/ci_cd_controller.rb
index 0d61c3cc031..cfed8727450 100644
--- a/app/controllers/projects/settings/ci_cd_controller.rb
+++ b/app/controllers/projects/settings/ci_cd_controller.rb
@@ -46,13 +46,19 @@ module Projects
private
def update_params
- params.require(:project).permit(
+ params.require(:project).permit(*permitted_project_params)
+ end
+
+ def permitted_project_params
+ [
:runners_token, :builds_enabled, :build_allow_git_fetch,
:build_timeout_human_readable, :build_coverage_regex, :public_builds,
:auto_cancel_pending_pipelines, :ci_config_path,
auto_devops_attributes: [:id, :domain, :enabled, :deploy_strategy],
ci_cd_settings_attributes: [:default_git_depth]
- )
+ ].tap do |list|
+ list << :max_artifacts_size if can?(current_user, :update_max_artifacts_size, project)
+ end
end
def run_autodevops_pipeline(service)
diff --git a/app/controllers/projects/settings/operations_controller.rb b/app/controllers/projects/settings/operations_controller.rb
index 7c71486a765..5bf3618b389 100644
--- a/app/controllers/projects/settings/operations_controller.rb
+++ b/app/controllers/projects/settings/operations_controller.rb
@@ -13,9 +13,14 @@ module Projects
def update
result = ::Projects::Operations::UpdateService.new(project, current_user, update_params).execute
+ track_events(result)
render_update_response(result)
end
+ # overridden in EE
+ def track_events(result)
+ end
+
private
# overridden in EE
@@ -63,7 +68,9 @@ module Projects
:api_host,
:token,
project: [:slug, :name, :organization_slug, :organization_name]
- ]
+ ],
+
+ grafana_integration_attributes: [:token, :grafana_url]
}
end
end
diff --git a/app/controllers/projects/templates_controller.rb b/app/controllers/projects/templates_controller.rb
index f987033a26c..95739f96d39 100644
--- a/app/controllers/projects/templates_controller.rb
+++ b/app/controllers/projects/templates_controller.rb
@@ -13,6 +13,14 @@ class Projects::TemplatesController < Projects::ApplicationController
end
end
+ def names
+ templates = @template_type.dropdown_names(project)
+
+ respond_to do |format|
+ format.json { render json: templates }
+ end
+ end
+
private
# User must have:
diff --git a/app/controllers/projects/uploads_controller.rb b/app/controllers/projects/uploads_controller.rb
index 4ffcc2ac805..3e5a1cfc74d 100644
--- a/app/controllers/projects/uploads_controller.rb
+++ b/app/controllers/projects/uploads_controller.rb
@@ -6,7 +6,7 @@ class Projects::UploadsController < Projects::ApplicationController
# These will kick you out if you don't have access.
skip_before_action :project, :repository,
- if: -> { action_name == 'show' && image_or_video? }
+ if: -> { action_name == 'show' && embeddable? }
before_action :authorize_upload_file!, only: [:create, :authorize]
before_action :verify_workhorse_api!, only: [:authorize]
diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb
index b8beecf823c..abd19df9a3d 100644
--- a/app/controllers/projects_controller.rb
+++ b/app/controllers/projects_controller.rb
@@ -376,6 +376,7 @@ class ProjectsController < Projects::ApplicationController
:tag_list,
:visibility_level,
:template_name,
+ :template_project_id,
:merge_method,
:initialize_with_readme,
diff --git a/app/controllers/registrations_controller.rb b/app/controllers/registrations_controller.rb
index 2e4c6a801b0..4a746fc915d 100644
--- a/app/controllers/registrations_controller.rb
+++ b/app/controllers/registrations_controller.rb
@@ -6,13 +6,20 @@ class RegistrationsController < Devise::RegistrationsController
include RecaptchaExperimentHelper
include InvisibleCaptcha
+ layout :choose_layout
+
+ skip_before_action :require_role, only: [:welcome, :update_role]
prepend_before_action :check_captcha, only: :create
before_action :whitelist_query_limiting, only: [:destroy]
before_action :ensure_terms_accepted,
if: -> { action_name == 'create' && Gitlab::CurrentSettings.current_application_settings.enforce_terms? }
def new
- redirect_to(new_user_session_path)
+ if experiment_enabled?(:signup_flow)
+ @resource = build_resource
+ else
+ redirect_to new_user_session_path(anchor: 'register-pane')
+ end
end
def create
@@ -20,8 +27,13 @@ class RegistrationsController < Devise::RegistrationsController
super do |new_user|
persist_accepted_terms_if_required(new_user)
+ set_role_required(new_user)
yield new_user if block_given?
end
+
+ # Do not show the signed_up notice message when the signup_flow experiment is enabled.
+ # Instead, show it after succesfully updating the role.
+ flash[:notice] = nil if experiment_enabled?(:signup_flow)
rescue Gitlab::Access::AccessDeniedError
redirect_to(new_user_session_path)
end
@@ -36,6 +48,26 @@ class RegistrationsController < Devise::RegistrationsController
end
end
+ def welcome
+ return redirect_to new_user_registration_path unless current_user
+ return redirect_to stored_location_or_dashboard_or_almost_there_path(current_user) if current_user.role.present?
+
+ current_user.name = nil
+ render layout: 'devise_experimental_separate_sign_up_flow'
+ end
+
+ def update_role
+ user_params = params.require(:user).permit(:name, :role)
+ result = ::Users::UpdateService.new(current_user, user_params.merge(user: current_user)).execute
+
+ if result[:status] == :success
+ set_flash_message! :notice, :signed_up
+ redirect_to stored_location_or_dashboard_or_almost_there_path(current_user)
+ else
+ redirect_to users_sign_up_welcome_path, alert: result[:message]
+ end
+ end
+
protected
def persist_accepted_terms_if_required(new_user)
@@ -48,6 +80,10 @@ class RegistrationsController < Devise::RegistrationsController
end
end
+ def set_role_required(new_user)
+ new_user.set_role_required! if new_user.persisted? && experiment_enabled?(:signup_flow)
+ end
+
def destroy_confirmation_valid?
if current_user.confirm_deletion_with_password?
current_user.valid_password?(params[:password])
@@ -70,7 +106,10 @@ class RegistrationsController < Devise::RegistrationsController
def after_sign_up_path_for(user)
Gitlab::AppLogger.info(user_created_message(confirmed: user.confirmed?))
- confirmed_or_unconfirmed_access_allowed(user) ? stored_location_or_dashboard(user) : users_almost_there_path
+
+ return users_sign_up_welcome_path if experiment_enabled?(:signup_flow)
+
+ stored_location_or_dashboard_or_almost_there_path(user)
end
def after_inactive_sign_up_path_for(resource)
@@ -97,6 +136,7 @@ class RegistrationsController < Devise::RegistrationsController
ensure_correct_params!
return unless Feature.enabled?(:registrations_recaptcha, default_enabled: true) # reCAPTCHA on the UI will still display however
+ return if experiment_enabled?(:signup_flow) # when the experimental signup flow is enabled for the current user, disable the reCAPTCHA check
return unless show_recaptcha_sign_up?
return unless Gitlab::Recaptcha.load_configurations!
@@ -108,7 +148,13 @@ class RegistrationsController < Devise::RegistrationsController
end
def sign_up_params
- params.require(:user).permit(:username, :email, :email_confirmation, :name, :password)
+ clean_params = params.require(:user).permit(:username, :email, :email_confirmation, :name, :password)
+
+ if experiment_enabled?(:signup_flow)
+ clean_params[:name] = clean_params[:username]
+ end
+
+ clean_params
end
def resource_name
@@ -138,12 +184,26 @@ class RegistrationsController < Devise::RegistrationsController
end
def confirmed_or_unconfirmed_access_allowed(user)
- user.confirmed? || Feature.enabled?(:soft_email_confirmation)
+ user.confirmed? || Feature.enabled?(:soft_email_confirmation) || experiment_enabled?(:signup_flow)
end
def stored_location_or_dashboard(user)
stored_location_for(user) || dashboard_projects_path
end
+
+ def stored_location_or_dashboard_or_almost_there_path(user)
+ confirmed_or_unconfirmed_access_allowed(user) ? stored_location_or_dashboard(user) : users_almost_there_path
+ end
+
+ # Part of an experiment to build a new sign up flow. Will be resolved
+ # with https://gitlab.com/gitlab-org/growth/engineering/issues/64
+ def choose_layout
+ if experiment_enabled?(:signup_flow)
+ 'devise_experimental_separate_sign_up_flow'
+ else
+ 'devise'
+ end
+ end
end
RegistrationsController.prepend_if_ee('EE::RegistrationsController')
diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb
index f8da152e3d2..1c506065b56 100644
--- a/app/controllers/sessions_controller.rb
+++ b/app/controllers/sessions_controller.rb
@@ -57,8 +57,14 @@ class SessionsController < Devise::SessionsController
reset_password_sent_at: nil)
end
- # hide the signed-in notification
- flash[:notice] = nil
+ if resource.deactivated?
+ resource.activate
+ flash[:notice] = _('Welcome back! Your account had been deactivated due to inactivity but is now reactivated.')
+ else
+ # hide the default signed-in notification
+ flash[:notice] = nil
+ end
+
log_audit_event(current_user, resource, with: authentication_method)
log_user_activity(current_user)
end
diff --git a/app/controllers/uploads_controller.rb b/app/controllers/uploads_controller.rb
index 2adfeab182e..635db386792 100644
--- a/app/controllers/uploads_controller.rb
+++ b/app/controllers/uploads_controller.rb
@@ -81,8 +81,13 @@ class UploadsController < ApplicationController
end
end
- def cache_publicly?
- User === model || Appearance === model
+ def cache_settings
+ case model
+ when User, Appearance
+ [5.minutes, { public: true, must_revalidate: false }]
+ when Project, Group
+ [5.minutes, { private: true, must_revalidate: true }]
+ end
end
def secret?