diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2019-11-19 22:11:55 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2019-11-19 22:11:55 +0000 |
commit | 5a8431feceba47fd8e1804d9aa1b1730606b71d5 (patch) | |
tree | e5df8e0ceee60f4af8093f5c4c2f934b8abced05 /app/controllers | |
parent | 4d477238500c347c6553d335d920bedfc5a46869 (diff) | |
download | gitlab-ce-5a8431feceba47fd8e1804d9aa1b1730606b71d5.tar.gz |
Add latest changes from gitlab-org/gitlab@12-5-stable-ee
Diffstat (limited to 'app/controllers')
64 files changed, 554 insertions, 171 deletions
diff --git a/app/controllers/admin/abuse_reports_controller.rb b/app/controllers/admin/abuse_reports_controller.rb index d5537023b26..31d825c235b 100644 --- a/app/controllers/admin/abuse_reports_controller.rb +++ b/app/controllers/admin/abuse_reports_controller.rb @@ -1,12 +1,9 @@ # frozen_string_literal: true class Admin::AbuseReportsController < Admin::ApplicationController - # rubocop: disable CodeReuse/ActiveRecord def index - @abuse_reports = AbuseReport.order(id: :desc).page(params[:page]) - @abuse_reports.includes(:reporter, :user) + @abuse_reports = AbuseReportsFinder.new(params).execute end - # rubocop: enable CodeReuse/ActiveRecord def destroy abuse_report = AbuseReport.find(params[:id]) diff --git a/app/controllers/admin/applications_controller.rb b/app/controllers/admin/applications_controller.rb index 22e629ccf59..907b295870d 100644 --- a/app/controllers/admin/applications_controller.rb +++ b/app/controllers/admin/applications_controller.rb @@ -44,7 +44,7 @@ class Admin::ApplicationsController < Admin::ApplicationController def destroy @application.destroy - redirect_to admin_applications_url, status: 302, notice: _('Application was successfully destroyed.') + redirect_to admin_applications_url, status: :found, notice: _('Application was successfully destroyed.') end private diff --git a/app/controllers/admin/groups_controller.rb b/app/controllers/admin/groups_controller.rb index 85a37fcd43e..5455cefdc8e 100644 --- a/app/controllers/admin/groups_controller.rb +++ b/app/controllers/admin/groups_controller.rb @@ -69,7 +69,7 @@ class Admin::GroupsController < Admin::ApplicationController Groups::DestroyService.new(@group, current_user).async_execute redirect_to admin_groups_path, - status: 302, + status: :found, alert: _('Group %{group_name} was scheduled for deletion.') % { group_name: @group.name } end diff --git a/app/controllers/admin/identities_controller.rb b/app/controllers/admin/identities_controller.rb index f518f7a657f..8f2e34a6294 100644 --- a/app/controllers/admin/identities_controller.rb +++ b/app/controllers/admin/identities_controller.rb @@ -38,9 +38,9 @@ class Admin::IdentitiesController < Admin::ApplicationController def destroy if @identity.destroy RepairLdapBlockedUserService.new(@user).execute - redirect_to admin_user_identities_path(@user), status: 302, notice: _('User identity was successfully removed.') + redirect_to admin_user_identities_path(@user), status: :found, notice: _('User identity was successfully removed.') else - redirect_to admin_user_identities_path(@user), status: 302, alert: _('Failed to remove user identity.') + redirect_to admin_user_identities_path(@user), status: :found, alert: _('Failed to remove user identity.') end end diff --git a/app/controllers/admin/keys_controller.rb b/app/controllers/admin/keys_controller.rb index 340eecd7632..58ea19d1210 100644 --- a/app/controllers/admin/keys_controller.rb +++ b/app/controllers/admin/keys_controller.rb @@ -17,9 +17,9 @@ class Admin::KeysController < Admin::ApplicationController respond_to do |format| if key.destroy - format.html { redirect_to keys_admin_user_path(user), status: 302, notice: _('User key was successfully removed.') } + format.html { redirect_to keys_admin_user_path(user), status: :found, notice: _('User key was successfully removed.') } else - format.html { redirect_to keys_admin_user_path(user), status: 302, alert: _('Failed to remove user key.') } + format.html { redirect_to keys_admin_user_path(user), status: :found, alert: _('Failed to remove user key.') } end end end diff --git a/app/controllers/admin/labels_controller.rb b/app/controllers/admin/labels_controller.rb index 90c1694fd2e..6cb206c1686 100644 --- a/app/controllers/admin/labels_controller.rb +++ b/app/controllers/admin/labels_controller.rb @@ -43,7 +43,7 @@ class Admin::LabelsController < Admin::ApplicationController respond_to do |format| format.html do - redirect_to admin_labels_path, status: 302, notice: _('Label was removed') + redirect_to admin_labels_path, status: :found, notice: _('Label was removed') end format.js end diff --git a/app/controllers/admin/projects_controller.rb b/app/controllers/admin/projects_controller.rb index 0e8c69eb7d6..cdedc34e634 100644 --- a/app/controllers/admin/projects_controller.rb +++ b/app/controllers/admin/projects_controller.rb @@ -41,7 +41,7 @@ class Admin::ProjectsController < Admin::ApplicationController redirect_to admin_projects_path, status: :found rescue Projects::DestroyService::DestroyError => ex - redirect_to admin_projects_path, status: 302, alert: ex.message + redirect_to admin_projects_path, status: :found, alert: ex.message end # rubocop: disable CodeReuse/ActiveRecord diff --git a/app/controllers/admin/spam_logs_controller.rb b/app/controllers/admin/spam_logs_controller.rb index 45cf0d3207e..a41d8a22650 100644 --- a/app/controllers/admin/spam_logs_controller.rb +++ b/app/controllers/admin/spam_logs_controller.rb @@ -13,7 +13,7 @@ class Admin::SpamLogsController < Admin::ApplicationController if params[:remove_user] spam_log.remove_user(deleted_by: current_user) redirect_to admin_spam_logs_path, - status: 302, + status: :found, notice: _('User %{username} was successfully removed.') % { username: spam_log.user.username } else spam_log.destroy diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb index 4c1ac8f206a..9fbfc59f630 100644 --- a/app/controllers/admin/users_controller.rb +++ b/app/controllers/admin/users_controller.rb @@ -169,7 +169,7 @@ class Admin::UsersController < Admin::ApplicationController user.delete_async(deleted_by: current_user, params: params.permit(:hard_delete)) respond_to do |format| - format.html { redirect_to admin_users_path, status: 302, notice: _("The user is being deleted.") } + format.html { redirect_to admin_users_path, status: :found, notice: _("The user is being deleted.") } format.json { head :ok } end end diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 27e88ae569e..25c1d80b117 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -12,6 +12,7 @@ class ApplicationController < ActionController::Base include EnforcesTwoFactorAuthentication include WithPerformanceBar include SessionlessAuthentication + include SessionsHelper include ConfirmEmailWarning include Gitlab::Tracking::ControllerConcern include Gitlab::Experimentation::ControllerConcern @@ -29,13 +30,13 @@ class ApplicationController < ActionController::Base before_action :active_user_check, unless: :devise_controller? before_action :set_usage_stats_consent_flag before_action :check_impersonation_availability - before_action :require_role + before_action :required_signup_info around_action :set_locale around_action :set_session_storage after_action :set_page_title_header, if: :json_request? - after_action :limit_unauthenticated_session_times + after_action :limit_session_time, if: -> { !current_user } protect_from_forgery with: :exception, prepend: true @@ -57,7 +58,7 @@ class ApplicationController < ActionController::Base rescue_from Encoding::CompatibilityError do |exception| log_exception(exception) - render "errors/encoding", layout: "errors", status: 500 + render "errors/encoding", layout: "errors", status: :internal_server_error end rescue_from ActiveRecord::RecordNotFound do |exception| @@ -103,24 +104,6 @@ class ApplicationController < ActionController::Base end end - # By default, all sessions are given the same expiration time configured in - # the session store (e.g. 1 week). However, unauthenticated users can - # generate a lot of sessions, primarily for CSRF verification. It makes - # sense to reduce the TTL for unauthenticated to something much lower than - # the default (e.g. 1 hour) to limit Redis memory. In addition, Rails - # creates a new session after login, so the short TTL doesn't even need to - # be extended. - def limit_unauthenticated_session_times - return if current_user - - # Rack sets this header, but not all tests may have it: https://github.com/rack/rack/blob/fdcd03a3c5a1c51d1f96fc97f9dfa1a9deac0c77/lib/rack/session/abstract/id.rb#L251-L259 - return unless request.env['rack.session.options'] - - # This works because Rack uses these options every time a request is handled: - # https://github.com/rack/rack/blob/fdcd03a3c5a1c51d1f96fc97f9dfa1a9deac0c77/lib/rack/session/abstract/id.rb#L342 - request.env['rack.session.options'][:expire_after] = Settings.gitlab['unauthenticated_session_expire_delay'] - end - def render(*args) super.tap do # Set a header for custom error pages to prevent them from being intercepted by gitlab-workhorse @@ -214,25 +197,29 @@ class ApplicationController < ActionController::Base end def git_not_found! - render "errors/git_not_found.html", layout: "errors", status: 404 + render "errors/git_not_found.html", layout: "errors", status: :not_found end def render_403 respond_to do |format| format.any { head :forbidden } - format.html { render "errors/access_denied", layout: "errors", status: 403 } + format.html { render "errors/access_denied", layout: "errors", status: :forbidden } end end def render_404 respond_to do |format| - format.html { render "errors/not_found", layout: "errors", status: 404 } + format.html { render "errors/not_found", layout: "errors", status: :not_found } # Prevent the Rails CSRF protector from thinking a missing .js file is a JavaScript file format.js { render json: '', status: :not_found, content_type: 'application/json' } format.any { head :not_found } end end + def respond_201 + head :created + end + def respond_422 head :unprocessable_entity end @@ -551,10 +538,13 @@ class ApplicationController < ActionController::Base @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) + # A user requires a role and have the setup_for_company attribute set 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 required_signup_info + return unless current_user + return unless current_user.role_required? + return unless experiment_enabled?(:signup_flow) store_location_for :user, request.fullpath diff --git a/app/controllers/boards/issues_controller.rb b/app/controllers/boards/issues_controller.rb index 9894dd7d180..1298b33471b 100644 --- a/app/controllers/boards/issues_controller.rb +++ b/app/controllers/boards/issues_controller.rb @@ -13,7 +13,7 @@ module Boards requires_cross_project_access if: -> { board&.group_board? } - before_action :whitelist_query_limiting, only: [:index, :update, :bulk_move] + before_action :whitelist_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] @@ -130,8 +130,7 @@ module Boards end def whitelist_query_limiting - # Also see https://gitlab.com/gitlab-org/gitlab-foss/issues/42439 - Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab-foss/issues/42428') + Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab/issues/35174') end def validate_id_list diff --git a/app/controllers/clusters/applications_controller.rb b/app/controllers/clusters/applications_controller.rb index 16c2365f85d..be68d0d0a1d 100644 --- a/app/controllers/clusters/applications_controller.rb +++ b/app/controllers/clusters/applications_controller.rb @@ -47,7 +47,7 @@ class Clusters::ApplicationsController < Clusters::BaseController end def cluster_application_params - params.permit(:application, :hostname, :email) + params.permit(:application, :hostname, :kibana_hostname, :email, :stack) end def cluster_application_destroy_params diff --git a/app/controllers/clusters/clusters_controller.rb b/app/controllers/clusters/clusters_controller.rb index 993aba661f3..9a539cf7c24 100644 --- a/app/controllers/clusters/clusters_controller.rb +++ b/app/controllers/clusters/clusters_controller.rb @@ -3,18 +3,22 @@ class Clusters::ClustersController < Clusters::BaseController include RoutableActions - before_action :cluster, except: [:index, :new, :create_gcp, :create_user] + before_action :cluster, only: [:cluster_status, :show, :update, :destroy] before_action :generate_gcp_authorize_url, only: [:new] before_action :validate_gcp_token, only: [:new] before_action :gcp_cluster, only: [:new] before_action :user_cluster, only: [:new] - before_action :authorize_create_cluster!, only: [:new] + before_action :authorize_create_cluster!, only: [:new, :authorize_aws_role, :revoke_aws_role, :aws_proxy] before_action :authorize_update_cluster!, only: [:update] before_action :authorize_admin_cluster!, only: [:destroy] before_action :update_applications_status, only: [:cluster_status] before_action only: [:new, :create_gcp] do push_frontend_feature_flag(:create_eks_clusters) end + before_action only: [:show] do + push_frontend_feature_flag(:enable_cluster_application_elastic_stack) + push_frontend_feature_flag(:enable_cluster_application_crossplane) + end helper_method :token_in_session @@ -40,10 +44,13 @@ class Clusters::ClustersController < Clusters::BaseController def new return unless Feature.enabled?(:create_eks_clusters) - @gke_selected = params[:provider] == 'gke' - @eks_selected = params[:provider] == 'eks' + if params[:provider] == 'aws' + @aws_role = current_user.aws_role || Aws::Role.new + @aws_role.ensure_role_external_id! - return redirect_to @authorize_url if @gke_selected && @authorize_url && !@valid_gcp_token + elsif params[:provider] == 'gcp' + redirect_to @authorize_url if @authorize_url && !@valid_gcp_token + end end # Overridding ActionController::Metal#status is NOT a good idea @@ -86,13 +93,12 @@ class Clusters::ClustersController < Clusters::BaseController end def destroy - if cluster.destroy - flash[:notice] = _('Kubernetes cluster integration was successfully removed.') - redirect_to clusterable.index_path, status: :found - else - flash[:notice] = _('Kubernetes cluster integration was not removed.') - render :show - end + response = Clusters::DestroyService + .new(current_user, destroy_params) + .execute(cluster) + + flash[:notice] = response[:message] + redirect_to clusterable.index_path, status: :found end def create_gcp @@ -112,6 +118,19 @@ class Clusters::ClustersController < Clusters::BaseController end end + def create_aws + @aws_cluster = ::Clusters::CreateService + .new(current_user, create_aws_cluster_params) + .execute + .present(current_user: current_user) + + if @aws_cluster.persisted? + head :created, location: @aws_cluster.show_path + else + render status: :unprocessable_entity, json: @aws_cluster.errors + end + end + def create_user @user_cluster = ::Clusters::CreateService .new(current_user, create_user_cluster_params) @@ -129,8 +148,37 @@ class Clusters::ClustersController < Clusters::BaseController end end + def authorize_aws_role + role = current_user.build_aws_role(create_role_params) + + role.save ? respond_201 : respond_422 + end + + def revoke_aws_role + current_user.aws_role&.destroy + + head :no_content + end + + def aws_proxy + response = Clusters::Aws::ProxyService.new( + current_user.aws_role, + params: params + ).execute + + render json: response.body, status: response.status + end + private + def destroy_params + # To be uncomented on https://gitlab.com/gitlab-org/gitlab/merge_requests/16954 + # This MR got split into other since it was too big. + # + # params.permit(:cleanup) + {} + end + def update_params if cluster.provided_by_user? params.require(:cluster).permit( @@ -139,6 +187,7 @@ class Clusters::ClustersController < Clusters::BaseController :environment_scope, :managed, :base_domain, + :management_project_id, platform_kubernetes_attributes: [ :api_url, :token, @@ -152,6 +201,7 @@ class Clusters::ClustersController < Clusters::BaseController :environment_scope, :managed, :base_domain, + :management_project_id, platform_kubernetes_attributes: [ :namespace ] @@ -179,6 +229,28 @@ class Clusters::ClustersController < Clusters::BaseController ) end + def create_aws_cluster_params + params.require(:cluster).permit( + :enabled, + :name, + :environment_scope, + :managed, + provider_aws_attributes: [ + :key_name, + :role_arn, + :region, + :vpc_id, + :instance_type, + :num_nodes, + :security_group_id, + subnet_ids: [] + ]).merge( + provider_type: :aws, + platform_type: :kubernetes, + clusterable: clusterable.subject + ) + end + def create_user_cluster_params params.require(:cluster).permit( :enabled, @@ -198,6 +270,10 @@ class Clusters::ClustersController < Clusters::BaseController ) end + def create_role_params + params.require(:cluster).permit(:role_arn, :role_external_id) + end + def generate_gcp_authorize_url params = Feature.enabled?(:create_eks_clusters) ? { provider: :gke } : {} state = generate_session_key_redirect(clusterable.new_path(params).to_s) diff --git a/app/controllers/concerns/confirm_email_warning.rb b/app/controllers/concerns/confirm_email_warning.rb index 5a4b5897a4f..86df0010665 100644 --- a/app/controllers/concerns/confirm_email_warning.rb +++ b/app/controllers/concerns/confirm_email_warning.rb @@ -16,7 +16,7 @@ module ConfirmEmailWarning email = current_user.unconfirmed_email || current_user.email - flash.now[:warning] = _("Please check your email (%{email}) to verify that you own this address. Didn't receive it? %{resend_link}. Wrong email address? %{update_link}.").html_safe % { + flash.now[:warning] = _("Please check your email (%{email}) to verify that you own this address and unlock the power of CI/CD. Didn't receive it? %{resend_link}. Wrong email address? %{update_link}.").html_safe % { email: email, resend_link: view_context.link_to(_('Resend it'), user_confirmation_path(user: { email: email }), method: :post), update_link: view_context.link_to(_('Update it'), profile_path) diff --git a/app/controllers/concerns/issuable_collections.rb b/app/controllers/concerns/issuable_collections.rb index c9a8de0b290..5aa00af8910 100644 --- a/app/controllers/concerns/issuable_collections.rb +++ b/app/controllers/concerns/issuable_collections.rb @@ -148,7 +148,7 @@ module IssuableCollections when 'Issue' common_attributes + [:project, project: :namespace] when 'MergeRequest' - common_attributes + [:target_project, source_project: :route, head_pipeline: :project, target_project: :namespace, latest_merge_request_diff: :merge_request_diff_commits] + common_attributes + [:target_project, :latest_merge_request_diff, source_project: :route, head_pipeline: :project, target_project: :namespace] end end # rubocop:enable Gitlab/ModuleWithInstanceVariables diff --git a/app/controllers/concerns/lfs_request.rb b/app/controllers/concerns/lfs_request.rb index 417bb169f39..61072eec535 100644 --- a/app/controllers/concerns/lfs_request.rb +++ b/app/controllers/concerns/lfs_request.rb @@ -56,7 +56,7 @@ module LfsRequest documentation_url: help_url }, content_type: CONTENT_TYPE, - status: 403 + status: :forbidden ) end @@ -67,7 +67,7 @@ module LfsRequest documentation_url: help_url }, content_type: CONTENT_TYPE, - status: 404 + status: :not_found ) end diff --git a/app/controllers/concerns/metrics_dashboard.rb b/app/controllers/concerns/metrics_dashboard.rb index 62efdacb710..dc392147cb8 100644 --- a/app/controllers/concerns/metrics_dashboard.rb +++ b/app/controllers/concerns/metrics_dashboard.rb @@ -3,21 +3,26 @@ # Provides an action which fetches a metrics dashboard according # to the parameters specified by the controller. module MetricsDashboard + include RenderServiceResults + include ChecksCollaboration + extend ActiveSupport::Concern def metrics_dashboard result = dashboard_finder.find( project_for_dashboard, current_user, - metrics_dashboard_params + metrics_dashboard_params.to_h.symbolize_keys ) - if include_all_dashboards? - result[:all_dashboards] = dashboard_finder.find_all_paths(project_for_dashboard) + if include_all_dashboards? && result + result[:all_dashboards] = all_dashboards end respond_to do |format| - if result[:status] == :success + if result.nil? + format.json { continue_polling_response } + elsif result[:status] == :success format.json { render dashboard_success_response(result) } else format.json { render dashboard_error_response(result) } @@ -27,6 +32,30 @@ module MetricsDashboard private + def all_dashboards + dashboards = dashboard_finder.find_all_paths(project_for_dashboard) + dashboards.map do |dashboard| + amend_dashboard(dashboard) + end + end + + def amend_dashboard(dashboard) + project_dashboard = project_for_dashboard && !dashboard[:system_dashboard] + + dashboard[:can_edit] = project_dashboard ? can_edit?(dashboard) : false + dashboard[:project_blob_path] = project_dashboard ? dashboard_project_blob_path(dashboard) : nil + + dashboard + end + + def dashboard_project_blob_path(dashboard) + project_blob_path(project_for_dashboard, File.join(project_for_dashboard.default_branch, dashboard.fetch(:path, ""))) + end + + def can_edit?(dashboard) + can_collaborate_with_project?(project_for_dashboard, ref: project_for_dashboard.default_branch) + end + # Override in class to provide arguments to the finder. def metrics_dashboard_params {} @@ -56,7 +85,7 @@ module MetricsDashboard def dashboard_error_response(result) { - status: result[:http_status], + status: result[:http_status] || :bad_request, json: result.slice(:all_dashboards, :message, :status) } end diff --git a/app/controllers/concerns/milestone_actions.rb b/app/controllers/concerns/milestone_actions.rb index 672d31ec779..dbc575a1487 100644 --- a/app/controllers/concerns/milestone_actions.rb +++ b/app/controllers/concerns/milestone_actions.rb @@ -53,12 +53,10 @@ module MilestoneActions # rubocop:disable Gitlab/ModuleWithInstanceVariables def milestone_redirect_path - if @project - project_milestone_path(@project, @milestone) - elsif @group - group_milestone_path(@group, @milestone.safe_title, title: @milestone.title) + if @milestone.global_milestone? + url_for(action: :show, title: @milestone.title) else - dashboard_milestone_path(@milestone.safe_title, title: @milestone.title) + url_for(action: :show) end end # rubocop:enable Gitlab/ModuleWithInstanceVariables diff --git a/app/controllers/concerns/preview_markdown.rb b/app/controllers/concerns/preview_markdown.rb index 2a9729b6ffd..c7c9f2e9b70 100644 --- a/app/controllers/concerns/preview_markdown.rb +++ b/app/controllers/concerns/preview_markdown.rb @@ -5,19 +5,10 @@ module PreviewMarkdown # rubocop:disable Gitlab/ModuleWithInstanceVariables def preview_markdown - result = PreviewMarkdownService.new(@project, current_user, params).execute - - markdown_params = - case controller_name - when 'wikis' then { pipeline: :wiki, project_wiki: @project_wiki, page_slug: params[:id] } - when 'snippets' then { skip_project_check: true } - when 'groups' then { group: group } - when 'projects' then projects_filter_params - else {} - end + result = PreviewMarkdownService.new(@project, current_user, markdown_service_params).execute render json: { - body: view_context.markdown(result[:text], markdown_params), + body: view_context.markdown(result[:text], markdown_context_params), references: { users: result[:users], suggestions: SuggestionSerializer.new.represent_diff(result[:suggestions]), @@ -26,11 +17,28 @@ module PreviewMarkdown } end + private + def projects_filter_params { issuable_state_filter_enabled: true, suggestions_filter_enabled: params[:preview_suggestions].present? } end + + def markdown_service_params + params + end + + def markdown_context_params + case controller_name + when 'wikis' then { pipeline: :wiki, project_wiki: @project_wiki, page_slug: params[:id] } + when 'snippets' then { skip_project_check: true } + when 'groups' then { group: group } + when 'projects' then projects_filter_params + else {} + end.merge(requested_path: params[:path]) + end + # rubocop:enable Gitlab/ModuleWithInstanceVariables end diff --git a/app/controllers/concerns/redirects_for_missing_path_on_tree.rb b/app/controllers/concerns/redirects_for_missing_path_on_tree.rb new file mode 100644 index 00000000000..085afbf3975 --- /dev/null +++ b/app/controllers/concerns/redirects_for_missing_path_on_tree.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +module RedirectsForMissingPathOnTree + def redirect_to_tree_root_for_missing_path(project, ref, path) + redirect_to project_tree_path(project, ref), notice: missing_path_on_ref(path, ref) + end + + private + + def missing_path_on_ref(path, ref) + _('"%{path}" did not exist on "%{ref}"') % { path: truncate_path(path), ref: ref } + end + + def truncate_path(path) + path.reverse.truncate(60, separator: "/").reverse + end +end diff --git a/app/controllers/concerns/renders_commits.rb b/app/controllers/concerns/renders_commits.rb index ed9b898a2a3..826fae834fa 100644 --- a/app/controllers/concerns/renders_commits.rb +++ b/app/controllers/concerns/renders_commits.rb @@ -1,11 +1,11 @@ # frozen_string_literal: true module RendersCommits - def limited_commits(commits) - if commits.size > MergeRequestDiff::COMMITS_SAFE_SIZE + def limited_commits(commits, commits_count) + if commits_count > MergeRequestDiff::COMMITS_SAFE_SIZE [ commits.first(MergeRequestDiff::COMMITS_SAFE_SIZE), - commits.size - MergeRequestDiff::COMMITS_SAFE_SIZE + commits_count - MergeRequestDiff::COMMITS_SAFE_SIZE ] else [commits, 0] @@ -14,9 +14,10 @@ module RendersCommits # This is used as a helper method in a controller. # rubocop: disable Gitlab/ModuleWithInstanceVariables - def set_commits_for_rendering(commits) - @total_commit_count = commits.size - limited, @hidden_commit_count = limited_commits(commits) + def set_commits_for_rendering(commits, commits_count: nil) + @total_commit_count = commits_count || commits.size + limited, @hidden_commit_count = limited_commits(commits, @total_commit_count) + commits.each(&:lazy_author) # preload authors prepare_commits_for_rendering(limited) end # rubocop: enable Gitlab/ModuleWithInstanceVariables diff --git a/app/controllers/concerns/routable_actions.rb b/app/controllers/concerns/routable_actions.rb index 45f9888a040..1b2e6461dee 100644 --- a/app/controllers/concerns/routable_actions.rb +++ b/app/controllers/concerns/routable_actions.rb @@ -47,7 +47,7 @@ module RoutableActions canonical_path = routable.full_path if canonical_path != requested_full_path - if canonical_path.casecmp(requested_full_path) != 0 + if !request.xhr? && request.format.html? && canonical_path.casecmp(requested_full_path) != 0 flash[:notice] = "#{routable.class.to_s.titleize} '#{requested_full_path}' was moved to '#{canonical_path}'. Please update any links and bookmarks that may still have the old path." end diff --git a/app/controllers/concerns/sourcegraph_gon.rb b/app/controllers/concerns/sourcegraph_gon.rb new file mode 100644 index 00000000000..ab4abd734fb --- /dev/null +++ b/app/controllers/concerns/sourcegraph_gon.rb @@ -0,0 +1,30 @@ +# frozen_string_literal: true + +module SourcegraphGon + extend ActiveSupport::Concern + + included do + before_action :push_sourcegraph_gon, unless: :json_request? + end + + private + + def push_sourcegraph_gon + return unless sourcegraph_enabled? + + gon.push({ + sourcegraph: { url: Gitlab::CurrentSettings.sourcegraph_url } + }) + end + + def sourcegraph_enabled? + Gitlab::CurrentSettings.sourcegraph_enabled && sourcegraph_enabled_for_project? && current_user&.sourcegraph_enabled + end + + def sourcegraph_enabled_for_project? + return false unless project && Gitlab::Sourcegraph.feature_enabled?(project) + return project.public? if Gitlab::CurrentSettings.sourcegraph_public_only + + true + end +end diff --git a/app/controllers/dashboard/todos_controller.rb b/app/controllers/dashboard/todos_controller.rb index 80c0a0d88a8..ebee8e9094e 100644 --- a/app/controllers/dashboard/todos_controller.rb +++ b/app/controllers/dashboard/todos_controller.rb @@ -22,7 +22,7 @@ class Dashboard::TodosController < Dashboard::ApplicationController respond_to do |format| format.html do redirect_to dashboard_todos_path, - status: 302, + status: :found, notice: _('To-do item successfully marked as done.') end format.js { head :ok } @@ -34,7 +34,7 @@ class Dashboard::TodosController < Dashboard::ApplicationController updated_ids = TodoService.new.mark_todos_as_done(@todos, current_user) respond_to do |format| - format.html { redirect_to dashboard_todos_path, status: 302, notice: _('Everything on your to-do list is marked as done.') } + format.html { redirect_to dashboard_todos_path, status: :found, notice: _('Everything on your to-do list is marked as done.') } format.js { head :ok } format.json { render json: todos_counts.merge(updated_ids: updated_ids) } end diff --git a/app/controllers/groups/boards_controller.rb b/app/controllers/groups/boards_controller.rb index 3c86f3108ab..8c9bf17f017 100644 --- a/app/controllers/groups/boards_controller.rb +++ b/app/controllers/groups/boards_controller.rb @@ -6,7 +6,7 @@ class Groups::BoardsController < Groups::ApplicationController before_action :assign_endpoint_vars before_action do - push_frontend_feature_flag(:multi_select_board) + push_frontend_feature_flag(:multi_select_board, default_enabled: true) end private diff --git a/app/controllers/groups/group_links_controller.rb b/app/controllers/groups/group_links_controller.rb new file mode 100644 index 00000000000..7965311c5f1 --- /dev/null +++ b/app/controllers/groups/group_links_controller.rb @@ -0,0 +1,34 @@ +# frozen_string_literal: true + +class Groups::GroupLinksController < Groups::ApplicationController + before_action :check_feature_flag! + before_action :authorize_admin_group! + + def create + shared_with_group = Group.find(params[:shared_with_group_id]) if params[:shared_with_group_id].present? + + if shared_with_group + result = Groups::GroupLinks::CreateService + .new(shared_with_group, current_user, group_link_create_params) + .execute(group) + + return render_404 if result[:http_status] == 404 + + flash[:alert] = result[:message] if result[:status] == :error + else + flash[:alert] = _('Please select a group.') + end + + redirect_to group_group_members_path(group) + end + + private + + def group_link_create_params + params.permit(:shared_group_access, :expires_at) + end + + def check_feature_flag! + render_404 unless Feature.enabled?(:share_group_with_group) + end +end diff --git a/app/controllers/groups/labels_controller.rb b/app/controllers/groups/labels_controller.rb index 26768c628ca..1034ca6cd7b 100644 --- a/app/controllers/groups/labels_controller.rb +++ b/app/controllers/groups/labels_controller.rb @@ -63,7 +63,7 @@ class Groups::LabelsController < Groups::ApplicationController respond_to do |format| format.html do - redirect_to group_labels_path(@group), status: 302, notice: "#{@label.name} deleted permanently" + redirect_to group_labels_path(@group), status: :found, notice: "#{@label.name} deleted permanently" end format.js end diff --git a/app/controllers/groups/registry/repositories_controller.rb b/app/controllers/groups/registry/repositories_controller.rb index e09a9e6eb21..cfddd8a3ba9 100644 --- a/app/controllers/groups/registry/repositories_controller.rb +++ b/app/controllers/groups/registry/repositories_controller.rb @@ -16,7 +16,7 @@ module Groups render json: ContainerRepositoriesSerializer .new(current_user: current_user) - .represent(@images) + .represent_read_only(@images) end end end diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb index 35e364abba3..755d97b091c 100644 --- a/app/controllers/groups_controller.rb +++ b/app/controllers/groups_controller.rb @@ -6,6 +6,7 @@ class GroupsController < Groups::ApplicationController include ParamsBackwardCompatibility include PreviewMarkdown include RecordUserLastActivity + extend ::Gitlab::Utils::Override respond_to :html @@ -24,6 +25,10 @@ class GroupsController < Groups::ApplicationController before_action :user_actions, only: [:show] + before_action do + push_frontend_feature_flag(:vue_issuables_list, @group) + end + skip_cross_project_access_check :index, :new, :create, :edit, :update, :destroy, :projects # When loading show as an atom feed, we render events that could leak cross @@ -111,7 +116,7 @@ class GroupsController < Groups::ApplicationController def destroy Groups::DestroyService.new(@group, current_user).async_execute - redirect_to root_path, status: 302, alert: "Group '#{@group.name}' was scheduled for deletion." + redirect_to root_path, status: :found, alert: "Group '#{@group.name}' was scheduled for deletion." end # rubocop: disable CodeReuse/ActiveRecord @@ -233,6 +238,11 @@ class GroupsController < Groups::ApplicationController @group.self_and_descendants.public_or_visible_to_user(current_user) end end + + override :markdown_service_params + def markdown_service_params + params.merge(group: group) + end end GroupsController.prepend_if_ee('EE::GroupsController') diff --git a/app/controllers/health_controller.rb b/app/controllers/health_controller.rb index efd5f0fc607..c6a02250896 100644 --- a/app/controllers/health_controller.rb +++ b/app/controllers/health_controller.rb @@ -5,6 +5,11 @@ class HealthController < ActionController::Base include RequiresWhitelistedMonitoringClient CHECKS = [ + Gitlab::HealthChecks::MasterCheck + ].freeze + + ALL_CHECKS = [ + *CHECKS, Gitlab::HealthChecks::DbCheck, Gitlab::HealthChecks::Redis::RedisCheck, Gitlab::HealthChecks::Redis::CacheCheck, @@ -14,8 +19,9 @@ class HealthController < ActionController::Base ].freeze def readiness - # readiness check is a collection with all above application-level checks - render_checks(*CHECKS) + # readiness check is a collection of application-level checks + # and optionally all service checks + render_checks(params[:all] ? ALL_CHECKS : CHECKS) end def liveness @@ -25,7 +31,7 @@ class HealthController < ActionController::Base private - def render_checks(*checks) + def render_checks(checks = []) result = Gitlab::HealthChecks::Probes::Collection .new(*checks) .execute diff --git a/app/controllers/help_controller.rb b/app/controllers/help_controller.rb index a58235790ad..97895d6461c 100644 --- a/app/controllers/help_controller.rb +++ b/app/controllers/help_controller.rb @@ -36,7 +36,7 @@ class HelpController < ApplicationController render 'show.html.haml' else # Force template to Haml - render 'errors/not_found.html.haml', layout: 'errors', status: 404 + render 'errors/not_found.html.haml', layout: 'errors', status: :not_found end end diff --git a/app/controllers/ldap/omniauth_callbacks_controller.rb b/app/controllers/ldap/omniauth_callbacks_controller.rb index 4d8875937eb..71a88bf3395 100644 --- a/app/controllers/ldap/omniauth_callbacks_controller.rb +++ b/app/controllers/ldap/omniauth_callbacks_controller.rb @@ -4,7 +4,7 @@ class Ldap::OmniauthCallbacksController < OmniauthCallbacksController extend ::Gitlab::Utils::Override def self.define_providers! - return unless Gitlab::Auth::LDAP::Config.enabled? + return unless Gitlab::Auth::LDAP::Config.sign_in_enabled? Gitlab::Auth::LDAP::Config.available_servers.each do |server| alias_method server['provider_name'], :ldap @@ -14,6 +14,8 @@ class Ldap::OmniauthCallbacksController < OmniauthCallbacksController # We only find ourselves here # if the authentication to LDAP was successful. def ldap + return unless Gitlab::Auth::LDAP::Config.sign_in_enabled? + sign_in_user_flow(Gitlab::Auth::LDAP::User) end diff --git a/app/controllers/notification_settings_controller.rb b/app/controllers/notification_settings_controller.rb index c97fec0a6ee..e5d4a4bb073 100644 --- a/app/controllers/notification_settings_controller.rb +++ b/app/controllers/notification_settings_controller.rb @@ -16,12 +16,7 @@ class NotificationSettingsController < ApplicationController @notification_setting = current_user.notification_settings.find(params[:id]) @saved = @notification_setting.update(notification_setting_params_for(@notification_setting.source)) - if params[:hide_label].present? - btn_class = params[:project_id].present? ? 'btn-xs' : '' - render_response("shared/notifications/_new_button", btn_class) - else - render_response - end + render_response end private @@ -42,7 +37,16 @@ class NotificationSettingsController < ApplicationController can?(current_user, ability_name, resource) end - def render_response(response_template = "shared/notifications/_button", btn_class = nil) + def render_response + btn_class = nil + + if params[:hide_label].present? + btn_class = 'btn-xs' if params[:project_id].present? + response_template = 'shared/notifications/_new_button' + else + response_template = 'shared/notifications/_button' + end + render json: { html: view_to_html_string(response_template, notification_setting: @notification_setting, btn_class: btn_class), saved: @saved diff --git a/app/controllers/oauth/applications_controller.rb b/app/controllers/oauth/applications_controller.rb index 12dc2d1af1c..8dd51ce1d64 100644 --- a/app/controllers/oauth/applications_controller.rb +++ b/app/controllers/oauth/applications_controller.rb @@ -57,7 +57,7 @@ class Oauth::ApplicationsController < Doorkeeper::ApplicationsController end rescue_from ActiveRecord::RecordNotFound do |exception| - render "errors/not_found", layout: "errors", status: 404 + render "errors/not_found", layout: "errors", status: :not_found end def create_application_params diff --git a/app/controllers/oauth/authorized_applications_controller.rb b/app/controllers/oauth/authorized_applications_controller.rb index a59ade559b3..9cfa57c53a5 100644 --- a/app/controllers/oauth/authorized_applications_controller.rb +++ b/app/controllers/oauth/authorized_applications_controller.rb @@ -13,7 +13,7 @@ class Oauth::AuthorizedApplicationsController < Doorkeeper::AuthorizedApplicatio end redirect_to applications_profile_url, - status: 302, + status: :found, notice: I18n.t(:notice, scope: [:doorkeeper, :flash, :authorized_applications, :destroy]) end end diff --git a/app/controllers/omniauth_callbacks_controller.rb b/app/controllers/omniauth_callbacks_controller.rb index b992972dfb8..eca58748cc5 100644 --- a/app/controllers/omniauth_callbacks_controller.rb +++ b/app/controllers/omniauth_callbacks_controller.rb @@ -47,7 +47,7 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController def omniauth_error @provider = params[:provider] @error = params[:error] - render 'errors/omniauth_error', layout: "oauth_error", status: 422 + render 'errors/omniauth_error', layout: "oauth_error", status: :unprocessable_entity end def cas3 diff --git a/app/controllers/profiles/preferences_controller.rb b/app/controllers/profiles/preferences_controller.rb index 42d4d785174..214640a5295 100644 --- a/app/controllers/profiles/preferences_controller.rb +++ b/app/controllers/profiles/preferences_controller.rb @@ -47,7 +47,8 @@ class Profiles::PreferencesController < Profiles::ApplicationController :preferred_language, :time_display_relative, :time_format_in_24h, - :show_whitespace_in_diffs + :show_whitespace_in_diffs, + :sourcegraph_enabled ] end end diff --git a/app/controllers/profiles/u2f_registrations_controller.rb b/app/controllers/profiles/u2f_registrations_controller.rb index 866c4dee6e2..84ce4a56e64 100644 --- a/app/controllers/profiles/u2f_registrations_controller.rb +++ b/app/controllers/profiles/u2f_registrations_controller.rb @@ -4,6 +4,6 @@ class Profiles::U2fRegistrationsController < Profiles::ApplicationController def destroy u2f_registration = current_user.u2f_registrations.find(params[:id]) u2f_registration.destroy - redirect_to profile_two_factor_auth_path, status: 302, notice: _("Successfully deleted U2F device.") + redirect_to profile_two_factor_auth_path, status: :found, notice: _("Successfully deleted U2F device.") end end diff --git a/app/controllers/projects/blame_controller.rb b/app/controllers/projects/blame_controller.rb index 9076bdb9f04..92655d593dd 100644 --- a/app/controllers/projects/blame_controller.rb +++ b/app/controllers/projects/blame_controller.rb @@ -3,6 +3,7 @@ # Controller for viewing a file's blame class Projects::BlameController < Projects::ApplicationController include ExtractsPath + include RedirectsForMissingPathOnTree before_action :require_non_empty_project before_action :assign_ref_vars @@ -11,7 +12,9 @@ class Projects::BlameController < Projects::ApplicationController def show @blob = @repository.blob_at(@commit.id, @path) - return render_404 unless @blob + unless @blob + return redirect_to_tree_root_for_missing_path(@project, @ref, @path) + end environment_params = @repository.branch_exists?(@ref) ? { ref: @ref } : { commit: @commit } @environment = EnvironmentsFinder.new(@project, current_user, environment_params).execute.last diff --git a/app/controllers/projects/blob_controller.rb b/app/controllers/projects/blob_controller.rb index 7c3d43fb49a..7c97f771a70 100644 --- a/app/controllers/projects/blob_controller.rb +++ b/app/controllers/projects/blob_controller.rb @@ -7,6 +7,9 @@ class Projects::BlobController < Projects::ApplicationController include RendersBlob include NotesHelper include ActionView::Helpers::SanitizeHelper + include RedirectsForMissingPathOnTree + include SourcegraphGon + prepend_before_action :authenticate_user!, only: [:edit] around_action :allow_gitaly_ref_name_caching, only: [:show] @@ -119,7 +122,7 @@ class Projects::BlobController < Projects::ApplicationController end end - return render_404 + return redirect_to_tree_root_for_missing_path(@project, @ref, @path) end end diff --git a/app/controllers/projects/boards_controller.rb b/app/controllers/projects/boards_controller.rb index 3b335fa4af4..db05da0bb7f 100644 --- a/app/controllers/projects/boards_controller.rb +++ b/app/controllers/projects/boards_controller.rb @@ -8,7 +8,7 @@ class Projects::BoardsController < Projects::ApplicationController before_action :authorize_read_board!, only: [:index, :show] before_action :assign_endpoint_vars before_action do - push_frontend_feature_flag(:multi_select_board) + push_frontend_feature_flag(:multi_select_board, default_enabled: true) end private diff --git a/app/controllers/projects/commit_controller.rb b/app/controllers/projects/commit_controller.rb index 939a09d4fd2..afb670b687b 100644 --- a/app/controllers/projects/commit_controller.rb +++ b/app/controllers/projects/commit_controller.rb @@ -8,6 +8,7 @@ class Projects::CommitController < Projects::ApplicationController include CreatesCommit include DiffForPath include DiffHelper + include SourcegraphGon # Authorize before_action :require_non_empty_project diff --git a/app/controllers/projects/environments_controller.rb b/app/controllers/projects/environments_controller.rb index c053ca19a94..4562296cea0 100644 --- a/app/controllers/projects/environments_controller.rb +++ b/app/controllers/projects/environments_controller.rb @@ -13,8 +13,6 @@ class Projects::EnvironmentsController < Projects::ApplicationController before_action :verify_api_request!, only: :terminal_websocket_authorize 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_additional_panel_types) push_frontend_feature_flag(:prometheus_computed_alerts) end @@ -133,7 +131,7 @@ class Projects::EnvironmentsController < Projects::ApplicationController if environment redirect_to environment_metrics_path(environment) else - render :empty + render :empty_metrics end end @@ -199,8 +197,7 @@ class Projects::EnvironmentsController < Projects::ApplicationController def metrics_dashboard_params params - .permit(:embedded, :group, :title, :y_label) - .to_h.symbolize_keys + .permit(:embedded, :group, :title, :y_label, :dashboard_path, :environment) .merge(dashboard_path: params[:dashboard], environment: environment) end diff --git a/app/controllers/projects/error_tracking_controller.rb b/app/controllers/projects/error_tracking_controller.rb index 88d0755f41f..9dea6b663ea 100644 --- a/app/controllers/projects/error_tracking_controller.rb +++ b/app/controllers/projects/error_tracking_controller.rb @@ -15,6 +15,23 @@ class Projects::ErrorTrackingController < Projects::ApplicationController end end + def details + respond_to do |format| + format.html + format.json do + render_issue_detail_json + end + end + end + + def stack_trace + respond_to do |format| + format.json do + render_issue_stack_trace_json + end + end + end + def list_projects respond_to do |format| format.json do @@ -29,10 +46,7 @@ class Projects::ErrorTrackingController < Projects::ApplicationController service = ErrorTracking::ListIssuesService.new(project, current_user) result = service.execute - unless result[:status] == :success - return render json: { message: result[:message] }, - status: result[:http_status] || :bad_request - end + return if handle_errors(result) render json: { errors: serialize_errors(result[:issues]), @@ -40,6 +54,28 @@ class Projects::ErrorTrackingController < Projects::ApplicationController } end + def render_issue_detail_json + service = ErrorTracking::IssueDetailsService.new(project, current_user, issue_details_params) + result = service.execute + + return if handle_errors(result) + + render json: { + error: serialize_detailed_error(result[:issue]) + } + end + + def render_issue_stack_trace_json + service = ErrorTracking::IssueLatestEventService.new(project, current_user, issue_details_params) + result = service.execute + + return if handle_errors(result) + + render json: { + error: serialize_error_event(result[:latest_event]) + } + end + def render_project_list_json service = ErrorTracking::ListProjectsService.new( project, @@ -62,10 +98,21 @@ class Projects::ErrorTrackingController < Projects::ApplicationController end end + def handle_errors(result) + unless result[:status] == :success + render json: { message: result[:message] }, + status: result[:http_status] || :bad_request + end + end + def list_projects_params params.require(:error_tracking_setting).permit([:api_host, :token]) end + def issue_details_params + params.permit(:issue_id) + end + def set_polling_interval Gitlab::PollingInterval.set_header(response, interval: POLLING_INTERVAL) end @@ -76,6 +123,18 @@ class Projects::ErrorTrackingController < Projects::ApplicationController .represent(errors) end + def serialize_detailed_error(error) + ErrorTracking::DetailedErrorSerializer + .new(project: project, user: current_user) + .represent(error) + end + + def serialize_error_event(event) + ErrorTracking::ErrorEventSerializer + .new(project: project, user: current_user) + .represent(event) + end + def serialize_projects(projects) ErrorTracking::ProjectSerializer .new(project: project, user: current_user) diff --git a/app/controllers/projects/grafana_api_controller.rb b/app/controllers/projects/grafana_api_controller.rb index 4bdf4c12cac..380a18818ab 100644 --- a/app/controllers/projects/grafana_api_controller.rb +++ b/app/controllers/projects/grafana_api_controller.rb @@ -2,6 +2,7 @@ class Projects::GrafanaApiController < Projects::ApplicationController include RenderServiceResults + include MetricsDashboard def proxy result = ::Grafana::ProxyService.new( @@ -19,6 +20,10 @@ class Projects::GrafanaApiController < Projects::ApplicationController private + def metrics_dashboard_params + params.permit(:embedded, :grafana_url) + end + def query_params params.permit(:query, :start, :end, :step) end diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb index 96cb400950b..009765702ab 100644 --- a/app/controllers/projects/issues_controller.rb +++ b/app/controllers/projects/issues_controller.rb @@ -44,6 +44,7 @@ class Projects::IssuesController < Projects::ApplicationController before_action do push_frontend_feature_flag(:vue_issuable_sidebar, project.group) + push_frontend_feature_flag(:release_search_filter, project) end respond_to :html diff --git a/app/controllers/projects/labels_controller.rb b/app/controllers/projects/labels_controller.rb index 386a1f00bd2..b7aeab8f5ff 100644 --- a/app/controllers/projects/labels_controller.rb +++ b/app/controllers/projects/labels_controller.rb @@ -76,7 +76,7 @@ class Projects::LabelsController < Projects::ApplicationController @labels = find_labels redirect_to project_labels_path(@project), - status: 302, + status: :found, notice: 'Label was removed' end diff --git a/app/controllers/projects/lfs_api_controller.rb b/app/controllers/projects/lfs_api_controller.rb index a1983bc5462..1273c55b83a 100644 --- a/app/controllers/projects/lfs_api_controller.rb +++ b/app/controllers/projects/lfs_api_controller.rb @@ -109,7 +109,7 @@ class Projects::LfsApiController < Projects::GitHttpClientController message: lfs_read_only_message }, content_type: LfsRequest::CONTENT_TYPE, - status: 403 + status: :forbidden ) end end diff --git a/app/controllers/projects/merge_requests/creations_controller.rb b/app/controllers/projects/merge_requests/creations_controller.rb index 808265634da..78dc196b08e 100644 --- a/app/controllers/projects/merge_requests/creations_controller.rb +++ b/app/controllers/projects/merge_requests/creations_controller.rb @@ -109,7 +109,13 @@ class Projects::MergeRequests::CreationsController < Projects::MergeRequests::Ap @target_project = @merge_request.target_project @source_project = @merge_request.source_project - @commits = set_commits_for_rendering(@merge_request.commits) + + @commits = + set_commits_for_rendering( + @merge_request.recent_commits.with_latest_pipeline(@merge_request.source_branch), + commits_count: @merge_request.commits_count + ) + @commit = @merge_request.diff_head_commit # FIXME: We have to assign a presenter to another instance variable diff --git a/app/controllers/projects/merge_requests/diffs_controller.rb b/app/controllers/projects/merge_requests/diffs_controller.rb index 4a37dfe5c19..42f9c0522a3 100644 --- a/app/controllers/projects/merge_requests/diffs_controller.rb +++ b/app/controllers/projects/merge_requests/diffs_controller.rb @@ -31,6 +31,7 @@ class Projects::MergeRequests::DiffsController < Projects::MergeRequests::Applic options = { merge_request: @merge_request, + diff_view: diff_view, pagination_data: diffs.pagination_data } @@ -60,7 +61,9 @@ class Projects::MergeRequests::DiffsController < Projects::MergeRequests::Applic render: ->(partial, locals) { view_to_html_string(partial, locals) } } - render json: DiffsSerializer.new(request).represent(@diffs, additional_attributes) + options = additional_attributes.merge(diff_view: diff_view) + + render json: DiffsSerializer.new(request).represent(@diffs, options) end def define_diff_vars diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb index ff199e05e99..766ec1e33f3 100644 --- a/app/controllers/projects/merge_requests_controller.rb +++ b/app/controllers/projects/merge_requests_controller.rb @@ -9,11 +9,12 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo include ToggleAwardEmoji include IssuableCollections include RecordUserLastActivity + include SourcegraphGon skip_before_action :merge_request, only: [:index, :bulk_update] before_action :whitelist_query_limiting, only: [:assign_related_issues, :update] before_action :authorize_update_issuable!, only: [:close, :edit, :update, :remove_wip, :sort] - before_action :authorize_test_reports!, only: [:test_reports] + before_action :authorize_read_actual_head_pipeline!, only: [:test_reports, :exposed_artifacts] 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] @@ -23,6 +24,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo before_action do push_frontend_feature_flag(:vue_issuable_sidebar, @project.group) + push_frontend_feature_flag(:release_search_filter, @project) end around_action :allow_gitaly_ref_name_caching, only: [:index, :show, :discussions] @@ -89,7 +91,10 @@ 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_latest_pipeline) + set_commits_for_rendering( + @merge_request.recent_commits.with_latest_pipeline(@merge_request.source_branch), + commits_count: @merge_request.commits_count + ) render json: { html: view_to_html_string('projects/merge_requests/_commits') } end @@ -115,6 +120,14 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo reports_response(@merge_request.compare_test_reports) end + def exposed_artifacts + if @merge_request.has_exposed_artifacts? + reports_response(@merge_request.find_exposed_artifacts) + else + head :no_content + end + end + def edit define_edit_vars end @@ -218,6 +231,8 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo @merge_request.rebase_async(current_user.id) head :ok + rescue MergeRequest::RebaseLockTimeout => e + render json: { merge_error: e.message }, status: :conflict end def discussions @@ -241,7 +256,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo end def merge_params_attributes - [:should_remove_source_branch, :commit_message, :squash_commit_message, :squash, :auto_merge_strategy] + MergeRequest::KNOWN_MERGE_PARAMS end def auto_merge_requested? @@ -281,7 +296,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo return :sha_mismatch if params[:sha] != @merge_request.diff_head_sha - @merge_request.update(merge_error: nil, squash: merge_params.fetch(:squash, false)) + @merge_request.update(merge_error: nil, squash: params.fetch(:squash, false)) if auto_merge_requested? if merge_request.auto_merge_enabled? @@ -353,12 +368,11 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo when :error render json: { status_reason: report_comparison[:status_reason] }, status: :bad_request else - render json: { status_reason: 'Unknown error' }, status: :internal_server_error + raise "Failed to build comparison response as comparison yielded unknown status '#{report_comparison[:status]}'" end end - def authorize_test_reports! - # MergeRequest#actual_head_pipeline is the pipeline accessed in MergeRequest#compare_reports. + def authorize_read_actual_head_pipeline! return render_404 unless can?(current_user, :read_build, merge_request.actual_head_pipeline) end end diff --git a/app/controllers/projects/pages_controller.rb b/app/controllers/projects/pages_controller.rb index 73e629ab7c3..722fc30b3ff 100644 --- a/app/controllers/projects/pages_controller.rb +++ b/app/controllers/projects/pages_controller.rb @@ -21,7 +21,7 @@ class Projects::PagesController < Projects::ApplicationController respond_to do |format| format.html do redirect_to project_pages_path(@project), - status: 302, + status: :found, notice: 'Pages were removed' end end diff --git a/app/controllers/projects/pages_domains_controller.rb b/app/controllers/projects/pages_domains_controller.rb index c287e440db0..b693642981e 100644 --- a/app/controllers/projects/pages_domains_controller.rb +++ b/app/controllers/projects/pages_domains_controller.rb @@ -8,6 +8,7 @@ class Projects::PagesDomainsController < Projects::ApplicationController before_action :domain, except: [:new, :create] def show + redirect_to edit_project_pages_domain_path(@project, @domain) end def new @@ -23,7 +24,7 @@ class Projects::PagesDomainsController < Projects::ApplicationController flash[:alert] = 'Failed to verify domain ownership' end - redirect_to project_pages_domain_path(@project, @domain) + redirect_to edit_project_pages_domain_path(@project, @domain) end def edit @@ -33,7 +34,7 @@ class Projects::PagesDomainsController < Projects::ApplicationController @domain = @project.pages_domains.create(create_params) if @domain.valid? - redirect_to project_pages_domain_path(@project, @domain) + redirect_to edit_project_pages_domain_path(@project, @domain) else render 'new' end @@ -42,7 +43,7 @@ class Projects::PagesDomainsController < Projects::ApplicationController def update if @domain.update(update_params) redirect_to project_pages_path(@project), - status: 302, + status: :found, notice: 'Domain was updated' else render 'edit' @@ -55,13 +56,21 @@ class Projects::PagesDomainsController < Projects::ApplicationController respond_to do |format| format.html do redirect_to project_pages_path(@project), - status: 302, + status: :found, notice: 'Domain was removed' end format.js end end + def clean_certificate + unless @domain.update(user_provided_certificate: nil, user_provided_key: nil) + flash[:alert] = @domain.errors.full_messages.join(', ') + end + + redirect_to edit_project_pages_domain_path(@project, @domain) + end + private def create_params @@ -69,7 +78,7 @@ class Projects::PagesDomainsController < Projects::ApplicationController end def update_params - params.require(:pages_domain).permit(:user_provided_key, :user_provided_certificate, :auto_ssl_enabled) + params.fetch(:pages_domain, {}).permit(:user_provided_key, :user_provided_certificate, :auto_ssl_enabled) end def domain diff --git a/app/controllers/projects/pipelines_controller.rb b/app/controllers/projects/pipelines_controller.rb index 106ef1b72c1..4d35353d5f5 100644 --- a/app/controllers/projects/pipelines_controller.rb +++ b/app/controllers/projects/pipelines_controller.rb @@ -12,6 +12,7 @@ class Projects::PipelinesController < Projects::ApplicationController before_action :authorize_update_pipeline!, only: [:retry, :cancel] before_action do push_frontend_feature_flag(:hide_dismissed_vulnerabilities) + push_frontend_feature_flag(:junit_pipeline_view) end around_action :allow_gitaly_ref_name_caching, only: [:index, :show] @@ -156,14 +157,21 @@ class Projects::PipelinesController < Projects::ApplicationController def test_report return unless Feature.enabled?(:junit_pipeline_view, project) - if pipeline_test_report == :error - render json: { status: :error_parsing_report } - return - end + respond_to do |format| + format.html do + render 'show' + end - render json: TestReportSerializer - .new(current_user: @current_user) - .represent(pipeline_test_report) + format.json do + if pipeline_test_report == :error + render json: { status: :error_parsing_report } + else + render json: TestReportSerializer + .new(current_user: @current_user) + .represent(pipeline_test_report) + end + end + end end private diff --git a/app/controllers/projects/releases_controller.rb b/app/controllers/projects/releases_controller.rb index 717df9f09e0..72c82aec31d 100644 --- a/app/controllers/projects/releases_controller.rb +++ b/app/controllers/projects/releases_controller.rb @@ -2,12 +2,48 @@ class Projects::ReleasesController < Projects::ApplicationController # Authorize - before_action :require_non_empty_project + before_action :require_non_empty_project, except: [:index] + before_action :release, only: %i[edit update] before_action :authorize_read_release! before_action do - push_frontend_feature_flag(:release_edit_page, project) + push_frontend_feature_flag(:release_edit_page, project, default_enabled: true) + push_frontend_feature_flag(:release_issue_summary, project) end + before_action :authorize_update_release!, only: %i[edit update] def index + respond_to do |format| + format.html do + require_non_empty_project + end + format.json { render json: releases } + end + end + + protected + + def releases + ReleasesFinder.new(@project, current_user).execute + end + + def edit + respond_to do |format| + format.html { render 'edit' } + end + end + + private + + def authorize_update_release! + access_denied! unless Feature.enabled?(:release_edit_page, project, default_enabled: true) + access_denied! unless can?(current_user, :update_release, release) + end + + def release + @release ||= project.releases.find_by_tag!(sanitized_tag_name) + end + + def sanitized_tag_name + CGI.unescape(params[:tag]) end end diff --git a/app/controllers/projects/settings/operations_controller.rb b/app/controllers/projects/settings/operations_controller.rb index 5bf3618b389..1571cb8cd34 100644 --- a/app/controllers/projects/settings/operations_controller.rb +++ b/app/controllers/projects/settings/operations_controller.rb @@ -70,7 +70,7 @@ module Projects project: [:slug, :name, :organization_slug, :organization_name] ], - grafana_integration_attributes: [:token, :grafana_url] + grafana_integration_attributes: [:token, :grafana_url, :enabled] } end end diff --git a/app/controllers/projects/tags_controller.rb b/app/controllers/projects/tags_controller.rb index 7d9387b1d94..c89bfd110c4 100644 --- a/app/controllers/projects/tags_controller.rb +++ b/app/controllers/projects/tags_controller.rb @@ -84,7 +84,7 @@ class Projects::TagsController < Projects::ApplicationController format.html do redirect_to project_tags_path(@project), - alert: @error, status: 303 + alert: @error, status: :see_other end format.js do diff --git a/app/controllers/projects/tree_controller.rb b/app/controllers/projects/tree_controller.rb index 7509cc29a76..eec89afe354 100644 --- a/app/controllers/projects/tree_controller.rb +++ b/app/controllers/projects/tree_controller.rb @@ -5,6 +5,7 @@ class Projects::TreeController < Projects::ApplicationController include ExtractsPath include CreatesCommit include ActionView::Helpers::SanitizeHelper + include RedirectsForMissingPathOnTree around_action :allow_gitaly_ref_name_caching, only: [:show] @@ -19,12 +20,9 @@ class Projects::TreeController < Projects::ApplicationController if tree.entries.empty? if @repository.blob_at(@commit.id, @path) - return redirect_to( - project_blob_path(@project, - File.join(@ref, @path)) - ) + return redirect_to project_blob_path(@project, File.join(@ref, @path)) elsif @path.present? - return render_404 + return redirect_to_tree_root_for_missing_path(@project, @ref, @path) end end diff --git a/app/controllers/projects/usage_ping_controller.rb b/app/controllers/projects/usage_ping_controller.rb new file mode 100644 index 00000000000..ebdf28bd59c --- /dev/null +++ b/app/controllers/projects/usage_ping_controller.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +class Projects::UsagePingController < Projects::ApplicationController + before_action :authenticate_user! + + def web_ide_clientside_preview + return render_404 unless Gitlab::CurrentSettings.web_ide_clientside_preview_enabled? + + Gitlab::UsageDataCounters::WebIdeCounter.increment_previews_count + + head(200) + end +end diff --git a/app/controllers/projects/wikis_controller.rb b/app/controllers/projects/wikis_controller.rb index b187fdb2723..fb06299676c 100644 --- a/app/controllers/projects/wikis_controller.rb +++ b/app/controllers/projects/wikis_controller.rb @@ -110,7 +110,7 @@ class Projects::WikisController < Projects::ApplicationController WikiPages::DestroyService.new(@project, current_user).execute(@page) redirect_to project_wiki_path(@project, :home), - status: 302, + status: :found, notice: _("Page was successfully deleted") rescue Gitlab::Git::Wiki::OperationError => e @error = e diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index abd19df9a3d..e5dea031bb5 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -154,7 +154,7 @@ class ProjectsController < Projects::ApplicationController redirect_to dashboard_projects_path, status: :found rescue Projects::DestroyService::DestroyError => ex - redirect_to edit_project_path(@project), status: 302, alert: ex.message + redirect_to edit_project_path(@project), status: :found, alert: ex.message end def new_issuable_address @@ -371,6 +371,7 @@ class ProjectsController < Projects::ApplicationController :path, :printing_merge_request_link_enabled, :public_builds, + :remove_source_branch_after_merge, :request_access_enabled, :runners_token, :tag_list, diff --git a/app/controllers/registrations_controller.rb b/app/controllers/registrations_controller.rb index 4a746fc915d..5fc7f5c84f0 100644 --- a/app/controllers/registrations_controller.rb +++ b/app/controllers/registrations_controller.rb @@ -8,7 +8,7 @@ class RegistrationsController < Devise::RegistrationsController layout :choose_layout - skip_before_action :require_role, only: [:welcome, :update_role] + skip_before_action :required_signup_info, only: [:welcome, :update_registration] prepend_before_action :check_captcha, only: :create before_action :whitelist_query_limiting, only: [:destroy] before_action :ensure_terms_accepted, @@ -16,6 +16,7 @@ class RegistrationsController < Devise::RegistrationsController def new if experiment_enabled?(:signup_flow) + track_experiment_event(:signup_flow, 'start') # We want this event to be tracked when the user is _in_ the experimental group @resource = build_resource else redirect_to new_user_session_path(anchor: 'register-pane') @@ -23,6 +24,8 @@ class RegistrationsController < Devise::RegistrationsController end def create + track_experiment_event(:signup_flow, 'end') unless experiment_enabled?(:signup_flow) # We want this event to be tracked when the user is _in_ the control group + accept_pending_invitations super do |new_user| @@ -42,29 +45,30 @@ class RegistrationsController < Devise::RegistrationsController if destroy_confirmation_valid? current_user.delete_async(deleted_by: current_user) session.try(:destroy) - redirect_to new_user_session_path, status: 303, notice: s_('Profiles|Account scheduled for removal.') + redirect_to new_user_session_path, status: :see_other, notice: s_('Profiles|Account scheduled for removal.') else - redirect_to profile_account_path, status: 303, alert: destroy_confirmation_failure_message + redirect_to profile_account_path, status: :see_other, alert: destroy_confirmation_failure_message 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? + return redirect_to stored_location_or_dashboard_or_almost_there_path(current_user) if current_user.role.present? && !current_user.setup_for_company.nil? - current_user.name = nil + current_user.name = nil if current_user.name == current_user.username 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 + def update_registration + user_params = params.require(:user).permit(:name, :role, :setup_for_company) + result = ::Users::SignupService.new(current_user, user_params).execute if result[:status] == :success + track_experiment_event(:signup_flow, 'end') # We want this event to be tracked when the user is _in_ the experimental group 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] + render :welcome, layout: 'devise_experimental_separate_sign_up_flow' end end diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb index 1c506065b56..0007d5826ba 100644 --- a/app/controllers/sessions_controller.rb +++ b/app/controllers/sessions_controller.rb @@ -24,6 +24,7 @@ class SessionsController < Devise::SessionsController before_action :store_unauthenticated_sessions, only: [:new] before_action :save_failed_login, if: :action_new_and_failed_login? before_action :load_recaptcha + before_action :frontend_tracking_data, only: [:new] after_action :log_failed_login, if: :action_new_and_failed_login? @@ -269,7 +270,13 @@ class SessionsController < Devise::SessionsController end def ldap_servers - @ldap_servers ||= Gitlab::Auth::LDAP::Config.available_servers + @ldap_servers ||= begin + if Gitlab::Auth::LDAP::Config.sign_in_enabled? + Gitlab::Auth::LDAP::Config.available_servers + else + [] + end + end end def unverified_anonymous_user? @@ -293,6 +300,11 @@ class SessionsController < Devise::SessionsController "standard" end end + + def frontend_tracking_data + # We want tracking data pushed to the frontend when the user is _in_ the control group + frontend_experimentation_tracking_data(:signup_flow, 'start') unless experiment_enabled?(:signup_flow) + end end SessionsController.prepend_if_ee('EE::SessionsController') diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index c3c227b08c5..06374736dcf 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -16,7 +16,7 @@ class UsersController < ApplicationController skip_before_action :authenticate_user! prepend_before_action(only: [:show]) { authenticate_sessionless_user!(:rss) } - before_action :user, except: [:exists] + before_action :user, except: [:exists, :suggests] before_action :authorize_read_user_profile!, only: [:calendar, :calendar_activities, :groups, :projects, :contributed_projects, :starred_projects, :snippets] @@ -114,6 +114,14 @@ class UsersController < ApplicationController render json: { exists: !!Namespace.find_by_path_or_name(params[:username]) } end + def suggests + namespace_path = params[:username] + exists = !!Namespace.find_by_path_or_name(namespace_path) + suggestions = exists ? [Namespace.clean_path(namespace_path)] : [] + + render json: { exists: exists, suggests: suggestions } + end + private def user |