diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-05-20 14:34:42 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-05-20 14:34:42 +0000 |
commit | 9f46488805e86b1bc341ea1620b866016c2ce5ed (patch) | |
tree | f9748c7e287041e37d6da49e0a29c9511dc34768 /app/controllers | |
parent | dfc92d081ea0332d69c8aca2f0e745cb48ae5e6d (diff) | |
download | gitlab-ce-9f46488805e86b1bc341ea1620b866016c2ce5ed.tar.gz |
Add latest changes from gitlab-org/gitlab@13-0-stable-ee
Diffstat (limited to 'app/controllers')
73 files changed, 771 insertions, 306 deletions
diff --git a/app/controllers/admin/appearances_controller.rb b/app/controllers/admin/appearances_controller.rb index 383ec2a7d16..8405f2a5cf8 100644 --- a/app/controllers/admin/appearances_controller.rb +++ b/app/controllers/admin/appearances_controller.rb @@ -73,6 +73,7 @@ class Admin::AppearancesController < Admin::ApplicationController favicon favicon_cache new_project_guidelines + profile_image_guidelines updated_by header_message footer_message diff --git a/app/controllers/admin/application_settings_controller.rb b/app/controllers/admin/application_settings_controller.rb index 16254c74ba4..355662bbb38 100644 --- a/app/controllers/admin/application_settings_controller.rb +++ b/app/controllers/admin/application_settings_controller.rb @@ -5,7 +5,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController # NOTE: Use @application_setting in this controller when you need to access # application_settings after it has been modified. This is because the - # ApplicationSetting model uses Gitlab::ThreadMemoryCache for caching and the + # ApplicationSetting model uses Gitlab::ProcessMemoryCache for caching and the # cache might be stale immediately after an update. # https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/30233 before_action :set_application_setting, except: :integrations @@ -43,7 +43,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController def usage_data respond_to do |format| format.html do - usage_data_json = JSON.pretty_generate(Gitlab::UsageData.data) + usage_data_json = Gitlab::Json.pretty_generate(Gitlab::UsageData.data) render html: Gitlab::Highlight.highlight('payload.json', usage_data_json, language: 'json') end diff --git a/app/controllers/admin/ci/variables_controller.rb b/app/controllers/admin/ci/variables_controller.rb new file mode 100644 index 00000000000..ca9b393550d --- /dev/null +++ b/app/controllers/admin/ci/variables_controller.rb @@ -0,0 +1,48 @@ +# frozen_string_literal: true + +class Admin::Ci::VariablesController < Admin::ApplicationController + def show + respond_to do |format| + format.json { render_instance_variables } + end + end + + def update + service = Ci::UpdateInstanceVariablesService.new(variables_params) + + if service.execute + respond_to do |format| + format.json { render_instance_variables } + end + else + respond_to do |format| + format.json { render_error(service.errors) } + end + end + end + + private + + def variables + @variables ||= Ci::InstanceVariable.all + end + + def render_instance_variables + render status: :ok, + json: { + variables: Ci::InstanceVariableSerializer.new.represent(variables) + } + end + + def render_error(errors) + render status: :bad_request, json: errors + end + + def variables_params + params.permit(variables_attributes: [*variable_params_attributes]) + end + + def variable_params_attributes + %i[id variable_type key secret_value protected masked _destroy] + end +end diff --git a/app/controllers/admin/dashboard_controller.rb b/app/controllers/admin/dashboard_controller.rb index cd95105a893..b7b535e70df 100644 --- a/app/controllers/admin/dashboard_controller.rb +++ b/app/controllers/admin/dashboard_controller.rb @@ -13,6 +13,7 @@ class Admin::DashboardController < Admin::ApplicationController @users = User.order_id_desc.limit(10) @groups = Group.order_id_desc.with_route.limit(10) @notices = Gitlab::ConfigChecker::PumaRuggedChecker.check + @notices += Gitlab::ConfigChecker::ExternalDatabaseChecker.check end # rubocop: enable CodeReuse/ActiveRecord diff --git a/app/controllers/admin/logs_controller.rb b/app/controllers/admin/logs_controller.rb deleted file mode 100644 index 3ae0aef0fa4..00000000000 --- a/app/controllers/admin/logs_controller.rb +++ /dev/null @@ -1,24 +0,0 @@ -# frozen_string_literal: true - -class Admin::LogsController < Admin::ApplicationController - before_action :loggers - - def show - end - - private - - def loggers - @loggers ||= [ - Gitlab::AppJsonLogger, - Gitlab::GitLogger, - Gitlab::EnvironmentLogger, - Gitlab::SidekiqLogger, - Gitlab::RepositoryCheckLogger, - Gitlab::ProjectServiceLogger, - Gitlab::Kubernetes::Logger - ] - end -end - -Admin::LogsController.prepend_if_ee('EE::Admin::LogsController') diff --git a/app/controllers/admin/sessions_controller.rb b/app/controllers/admin/sessions_controller.rb index 1dc1cd5fb82..0c0bbaf4d93 100644 --- a/app/controllers/admin/sessions_controller.rb +++ b/app/controllers/admin/sessions_controller.rb @@ -3,6 +3,7 @@ class Admin::SessionsController < ApplicationController include Authenticates2FAForAdminMode include InternalRedirect + include RendersLdapServers before_action :user_is_admin! diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb index 8414095d454..ee42baa8326 100644 --- a/app/controllers/admin/users_controller.rb +++ b/app/controllers/admin/users_controller.rb @@ -145,7 +145,7 @@ class Admin::UsersController < Admin::ApplicationController password_confirmation: params[:user][:password_confirmation] } - password_params[:password_expires_at] = Time.now unless changing_own_password? + password_params[:password_expires_at] = Time.current unless changing_own_password? user_params_with_pass.merge!(password_params) end diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index b5695322eb6..54e3275662b 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -18,6 +18,9 @@ class ApplicationController < ActionController::Base include Gitlab::Tracking::ControllerConcern include Gitlab::Experimentation::ControllerConcern include InitializesCurrentUserMode + include Impersonation + include Gitlab::Logging::CloudflareHelper + include Gitlab::Utils::StrongMemoize before_action :authenticate_user!, except: [:route_not_found] before_action :enforce_terms!, if: :should_enforce_terms? @@ -35,6 +38,10 @@ class ApplicationController < ActionController::Base before_action :check_impersonation_availability before_action :required_signup_info + # Make sure the `auth_user` is memoized so it can be logged, we do this after + # all other before filters that could have set the user. + before_action :auth_user + prepend_around_action :set_current_context around_action :sessionless_bypass_admin_mode!, if: :sessionless_user? @@ -141,16 +148,19 @@ class ApplicationController < ActionController::Base payload[:ua] = request.env["HTTP_USER_AGENT"] payload[:remote_ip] = request.remote_ip + payload[Labkit::Correlation::CorrelationId::LOG_KEY] = Labkit::Correlation::CorrelationId.current_id + payload[:metadata] = @current_context logged_user = auth_user - if logged_user.present? payload[:user_id] = logged_user.try(:id) payload[:username] = logged_user.try(:username) end payload[:queue_duration_s] = request.env[::Gitlab::Middleware::RailsQueueDuration::GITLAB_RAILS_QUEUE_DURATION_KEY] + + store_cloudflare_headers!(payload, request) end ## @@ -158,10 +168,12 @@ class ApplicationController < ActionController::Base # (e.g. tokens) to authenticate the user, whereas Devise sets current_user. # def auth_user - if user_signed_in? - current_user - else - try(:authenticated_user) + strong_memoize(:auth_user) do + if user_signed_in? + current_user + else + try(:authenticated_user) + end end end @@ -453,11 +465,16 @@ class ApplicationController < ActionController::Base def set_current_context(&block) Gitlab::ApplicationContext.with_context( - user: -> { auth_user }, - project: -> { @project }, - namespace: -> { @group }, - caller_id: full_action_name, - &block) + # Avoid loading the auth_user again after the request. Otherwise calling + # `auth_user` again would also trigger the Warden callbacks again + user: -> { auth_user if strong_memoized?(:auth_user) }, + project: -> { @project if @project&.persisted? }, + namespace: -> { @group if @group&.persisted? }, + caller_id: full_action_name) do + yield + ensure + @current_context = Labkit::Context.current.to_h + end end def set_locale(&block) @@ -525,36 +542,6 @@ class ApplicationController < ActionController::Base .execute end - def check_impersonation_availability - return unless session[:impersonator_id] - - unless Gitlab.config.gitlab.impersonation_enabled - stop_impersonation - access_denied! _('Impersonation has been disabled') - end - end - - def stop_impersonation - log_impersonation_event - - warden.set_user(impersonator, scope: :user) - session[:impersonator_id] = nil - - impersonated_user - end - - def impersonated_user - current_user - end - - def log_impersonation_event - Gitlab::AppLogger.info("User #{impersonator.username} has stopped impersonating #{impersonated_user.username}") - end - - def impersonator - @impersonator ||= User.find(session[:impersonator_id]) if session[:impersonator_id] - end - def sentry_context(&block) Gitlab::ErrorTracking.with_context(current_user, &block) end diff --git a/app/controllers/boards/issues_controller.rb b/app/controllers/boards/issues_controller.rb index 1bfff210ecf..a18c80b996e 100644 --- a/app/controllers/boards/issues_controller.rb +++ b/app/controllers/boards/issues_controller.rb @@ -20,9 +20,6 @@ module Boards skip_before_action :authenticate_user!, only: [:index] before_action :validate_id_list, only: [:bulk_move] before_action :can_move_issues?, only: [:bulk_move] - before_action do - push_frontend_feature_flag(:board_search_optimization, board.group, default_enabled: true) - end def index list_service = Boards::Issues::ListService.new(board_parent, current_user, filter_params) diff --git a/app/controllers/clusters/applications_controller.rb b/app/controllers/clusters/applications_controller.rb index de14bd319e0..c533fe007d7 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, :pages_domain_id, :email, :stack, :modsecurity_enabled, :modsecurity_mode, :host, :port, :protocol) + params.permit(:application, :hostname, :pages_domain_id, :email, :stack, :modsecurity_enabled, :modsecurity_mode, :host, :port, :protocol, :waf_log_enabled, :cilium_log_enabled) end def cluster_application_destroy_params diff --git a/app/controllers/clusters/clusters_controller.rb b/app/controllers/clusters/clusters_controller.rb index 2c9ee69c8c4..aa39d430b24 100644 --- a/app/controllers/clusters/clusters_controller.rb +++ b/app/controllers/clusters/clusters_controller.rb @@ -18,20 +18,19 @@ class Clusters::ClustersController < Clusters::BaseController STATUS_POLLING_INTERVAL = 10_000 def index - finder = ClusterAncestorsFinder.new(clusterable.subject, current_user) - clusters = finder.execute + @clusters = cluster_list - # Note: We are paginating through an array here but this should OK as: - # - # In CE, we can have a maximum group nesting depth of 21, so including - # project cluster, we can have max 22 clusters for a group hierarchy. - # In EE (Premium) we can have any number, as multiple clusters are - # supported, but the number of clusters are fairly low currently. - # - # See https://gitlab.com/gitlab-org/gitlab-foss/issues/55260 also. - @clusters = Kaminari.paginate_array(clusters).page(params[:page]).per(20) + respond_to do |format| + format.html + format.json do + serializer = ClusterSerializer.new(current_user: current_user) - @has_ancestor_clusters = finder.has_ancestor_clusters? + render json: { + clusters: serializer.with_pagination(request, response).represent_list(@clusters), + has_ancestor_clusters: @has_ancestor_clusters + } + end + end end def new @@ -158,6 +157,23 @@ class Clusters::ClustersController < Clusters::BaseController private + def cluster_list + finder = ClusterAncestorsFinder.new(clusterable.subject, current_user) + clusters = finder.execute + + @has_ancestor_clusters = finder.has_ancestor_clusters? + + # Note: We are paginating through an array here but this should OK as: + # + # In CE, we can have a maximum group nesting depth of 21, so including + # project cluster, we can have max 22 clusters for a group hierarchy. + # In EE (Premium) we can have any number, as multiple clusters are + # supported, but the number of clusters are fairly low currently. + # + # See https://gitlab.com/gitlab-org/gitlab-foss/issues/55260 also. + Kaminari.paginate_array(clusters).page(params[:page]).per(20) + end + def destroy_params params.permit(:cleanup) end diff --git a/app/controllers/concerns/boards_actions.rb b/app/controllers/concerns/boards_actions.rb index eb1080cb3d2..9d40b9e8c88 100644 --- a/app/controllers/concerns/boards_actions.rb +++ b/app/controllers/concerns/boards_actions.rb @@ -10,6 +10,9 @@ module BoardsActions before_action :boards, only: :index before_action :board, only: :show before_action :push_wip_limits, only: [:index, :show] + before_action do + push_frontend_feature_flag(:not_issuable_queries, parent, default_enabled: true) + end end def index diff --git a/app/controllers/concerns/impersonation.rb b/app/controllers/concerns/impersonation.rb new file mode 100644 index 00000000000..a4f2c263eb4 --- /dev/null +++ b/app/controllers/concerns/impersonation.rb @@ -0,0 +1,43 @@ +# frozen_string_literal: true + +module Impersonation + include Gitlab::Utils::StrongMemoize + + def current_user + user = super + + user.impersonator = impersonator if impersonator + + user + end + + protected + + def check_impersonation_availability + return unless session[:impersonator_id] + + unless Gitlab.config.gitlab.impersonation_enabled + stop_impersonation + access_denied! _('Impersonation has been disabled') + end + end + + def stop_impersonation + log_impersonation_event + + warden.set_user(impersonator, scope: :user) + session[:impersonator_id] = nil + + current_user + end + + def log_impersonation_event + Gitlab::AppLogger.info("User #{impersonator.username} has stopped impersonating #{current_user.username}") + end + + def impersonator + strong_memoize(:impersonator) do + User.find(session[:impersonator_id]) if session[:impersonator_id] + end + end +end diff --git a/app/controllers/concerns/issuable_actions.rb b/app/controllers/concerns/issuable_actions.rb index ca43bf42580..0b1b3f2bcba 100644 --- a/app/controllers/concerns/issuable_actions.rb +++ b/app/controllers/concerns/issuable_actions.rb @@ -11,6 +11,9 @@ module IssuableActions before_action only: :show do push_frontend_feature_flag(:scoped_labels, default_enabled: true) end + before_action do + push_frontend_feature_flag(:not_issuable_queries, @project, default_enabled: true) + end end def permitted_keys diff --git a/app/controllers/concerns/issuable_collections_action.rb b/app/controllers/concerns/issuable_collections_action.rb index 0a6f684a9fc..78b3c6771b3 100644 --- a/app/controllers/concerns/issuable_collections_action.rb +++ b/app/controllers/concerns/issuable_collections_action.rb @@ -32,6 +32,10 @@ module IssuableCollectionsAction private + def set_not_query_feature_flag(object = nil) + push_frontend_feature_flag(:not_issuable_queries, object, default_enabled: true) + end + def sorting_field case action_name when 'issues' diff --git a/app/controllers/concerns/known_sign_in.rb b/app/controllers/concerns/known_sign_in.rb new file mode 100644 index 00000000000..97883d8d08c --- /dev/null +++ b/app/controllers/concerns/known_sign_in.rb @@ -0,0 +1,31 @@ +# frozen_string_literal: true + +module KnownSignIn + include Gitlab::Utils::StrongMemoize + + private + + def verify_known_sign_in + return unless current_user + + notify_user unless known_remote_ip? + end + + def known_remote_ip? + known_ip_addresses.include?(request.remote_ip) + end + + def sessions + strong_memoize(:session) do + ActiveSession.list(current_user).reject(&:is_impersonated) + end + end + + def known_ip_addresses + [current_user.last_sign_in_ip, sessions.map(&:ip_address)].flatten + end + + def notify_user + current_user.notification_service.unknown_sign_in(current_user, request.remote_ip) + end +end diff --git a/app/controllers/concerns/members_presentation.rb b/app/controllers/concerns/members_presentation.rb index 0a9d3d86245..ceccef8113f 100644 --- a/app/controllers/concerns/members_presentation.rb +++ b/app/controllers/concerns/members_presentation.rb @@ -5,6 +5,7 @@ module MembersPresentation def present_members(members) preload_associations(members) + Gitlab::View::Presenter::Factory.new( members, current_user: current_user, diff --git a/app/controllers/concerns/metrics_dashboard.rb b/app/controllers/concerns/metrics_dashboard.rb index fa79f3bc4e6..1aea0e294a5 100644 --- a/app/controllers/concerns/metrics_dashboard.rb +++ b/app/controllers/concerns/metrics_dashboard.rb @@ -18,7 +18,7 @@ module MetricsDashboard if result result[:all_dashboards] = all_dashboards if include_all_dashboards? - result[:metrics_data] = metrics_data(project_for_dashboard, environment_for_dashboard) if project_for_dashboard && environment_for_dashboard + result[:metrics_data] = metrics_data(project_for_dashboard, environment_for_dashboard) end respond_to do |format| @@ -35,10 +35,9 @@ module MetricsDashboard private def all_dashboards - dashboards = dashboard_finder.find_all_paths(project_for_dashboard) - dashboards.map do |dashboard| - amend_dashboard(dashboard) - end + dashboard_finder + .find_all_paths(project_for_dashboard) + .map(&method(:amend_dashboard)) end def amend_dashboard(dashboard) @@ -46,10 +45,16 @@ module MetricsDashboard dashboard[:can_edit] = project_dashboard ? can_edit?(dashboard) : false dashboard[:project_blob_path] = project_dashboard ? dashboard_project_blob_path(dashboard) : nil + dashboard[:starred] = starred_dashboards.include?(dashboard[:path]) + dashboard[:user_starred_path] = project_for_dashboard ? user_starred_path(project_for_dashboard, dashboard[:path]) : nil dashboard end + def user_starred_path(project, path) + expose_path(api_v4_projects_metrics_user_starred_dashboards_path(id: project.id, params: { dashboard_path: path })) + end + def dashboard_project_blob_path(dashboard) project_blob_path(project_for_dashboard, File.join(project_for_dashboard.default_branch, dashboard.fetch(:path, ""))) end @@ -73,6 +78,20 @@ module MetricsDashboard ::Gitlab::Metrics::Dashboard::Finder end + def starred_dashboards + @starred_dashboards ||= begin + if project_for_dashboard.present? + ::Metrics::UsersStarredDashboardsFinder + .new(user: current_user, project: project_for_dashboard) + .execute + .map(&:dashboard_path) + .to_set + else + Set.new + end + end + end + # Project is not defined for group and admin level clusters. def project_for_dashboard defined?(project) ? project : nil diff --git a/app/controllers/concerns/notes_actions.rb b/app/controllers/concerns/notes_actions.rb index 7dd2f6e5706..d4b0d3b2674 100644 --- a/app/controllers/concerns/notes_actions.rb +++ b/app/controllers/concerns/notes_actions.rb @@ -13,7 +13,7 @@ module NotesActions end def index - current_fetched_at = Time.now.to_i + current_fetched_at = Time.current.to_i notes_json = { notes: [], last_fetched_at: current_fetched_at } diff --git a/app/controllers/concerns/preview_markdown.rb b/app/controllers/concerns/preview_markdown.rb index c7c9f2e9b70..ba15d611c0d 100644 --- a/app/controllers/concerns/preview_markdown.rb +++ b/app/controllers/concerns/preview_markdown.rb @@ -37,7 +37,7 @@ module PreviewMarkdown when 'groups' then { group: group } when 'projects' then projects_filter_params else {} - end.merge(requested_path: params[:path]) + end.merge(requested_path: params[:path], ref: params[:ref]) end # rubocop:enable Gitlab/ModuleWithInstanceVariables diff --git a/app/controllers/concerns/record_user_last_activity.rb b/app/controllers/concerns/record_user_last_activity.rb index 4013596ba12..29164df4516 100644 --- a/app/controllers/concerns/record_user_last_activity.rb +++ b/app/controllers/concerns/record_user_last_activity.rb @@ -17,7 +17,6 @@ module RecordUserLastActivity def set_user_last_activity return unless request.get? - return unless Feature.enabled?(:set_user_last_activity, default_enabled: true) return if Gitlab::Database.read_only? if current_user && current_user.last_activity_on != Date.today diff --git a/app/controllers/concerns/renders_ldap_servers.rb b/app/controllers/concerns/renders_ldap_servers.rb new file mode 100644 index 00000000000..cc83ff47048 --- /dev/null +++ b/app/controllers/concerns/renders_ldap_servers.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +module RendersLdapServers + extend ActiveSupport::Concern + + included do + helper_method :ldap_servers + end + + def ldap_servers + @ldap_servers ||= begin + if Gitlab::Auth::Ldap::Config.sign_in_enabled? + Gitlab::Auth::Ldap::Config.available_servers + else + [] + end + end + end +end diff --git a/app/controllers/concerns/service_params.rb b/app/controllers/concerns/service_params.rb index 3ccf227c431..e2c83f9a069 100644 --- a/app/controllers/concerns/service_params.rb +++ b/app/controllers/concerns/service_params.rb @@ -19,6 +19,7 @@ module ServiceParams :color, :colorize_messages, :comment_on_event_enabled, + :comment_detail, :confidential_issues_events, :default_irc_uri, :description, diff --git a/app/controllers/concerns/snippets_actions.rb b/app/controllers/concerns/snippets_actions.rb index 096c6efc0fc..e78723bdda2 100644 --- a/app/controllers/concerns/snippets_actions.rb +++ b/app/controllers/concerns/snippets_actions.rb @@ -53,10 +53,10 @@ module SnippetsActions def blob return unless snippet - @blob ||= if Feature.enabled?(:version_snippets, current_user) && !snippet.repository.empty? - snippet.blobs.first - else + @blob ||= if snippet.empty_repo? snippet.blob + else + snippet.blobs.first end end # rubocop:enable Gitlab/ModuleWithInstanceVariables @@ -65,11 +65,12 @@ module SnippetsActions params[:line_ending] == 'raw' ? content : content.gsub(/\r\n/, "\n") end - def check_repository_error - repository_errors = Array(snippet.errors.delete(:repository)) + def handle_repository_error(action) + errors = Array(snippet.errors.delete(:repository)) + + flash.now[:alert] = errors.first if errors.present? - flash.now[:alert] = repository_errors.first if repository_errors.present? - recaptcha_check_with_fallback(repository_errors.empty?) { render :edit } + recaptcha_check_with_fallback(errors.empty?) { render action } end def redirect_if_binary diff --git a/app/controllers/concerns/spammable_actions.rb b/app/controllers/concerns/spammable_actions.rb index 46ba270f328..50c93441dd4 100644 --- a/app/controllers/concerns/spammable_actions.rb +++ b/app/controllers/concerns/spammable_actions.rb @@ -82,6 +82,6 @@ module SpammableActions return false if spammable.errors.count > 1 # re-render "new" template in case there are other errors return false unless Gitlab::Recaptcha.enabled? - spammable.spam + spammable.needs_recaptcha? end end diff --git a/app/controllers/dashboard/projects_controller.rb b/app/controllers/dashboard/projects_controller.rb index c173d7d2310..25c48fadf49 100644 --- a/app/controllers/dashboard/projects_controller.rb +++ b/app/controllers/dashboard/projects_controller.rb @@ -83,11 +83,13 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController def use_cte_for_finder? # The starred action loads public projects, which causes the CTE to be less efficient - action_name == 'index' && Feature.enabled?(:use_cte_for_projects_finder, default_enabled: true) + action_name == 'index' end def load_events - projects = load_projects(params.merge(non_public: true)) + projects = ProjectsFinder + .new(params: params.merge(non_public: true), current_user: current_user) + .execute @events = EventCollection .new(projects, offset: params[:offset].to_i, filter: event_filter) diff --git a/app/controllers/dashboard_controller.rb b/app/controllers/dashboard_controller.rb index 1668cf004f8..dd9e6488bc5 100644 --- a/app/controllers/dashboard_controller.rb +++ b/app/controllers/dashboard_controller.rb @@ -10,6 +10,7 @@ class DashboardController < Dashboard::ApplicationController before_action :projects, only: [:issues, :merge_requests] before_action :set_show_full_reference, only: [:issues, :merge_requests] before_action :check_filters_presence!, only: [:issues, :merge_requests] + before_action :set_not_query_feature_flag respond_to :html diff --git a/app/controllers/google_api/authorizations_controller.rb b/app/controllers/google_api/authorizations_controller.rb index ed0995e7ffd..5723ccc14a7 100644 --- a/app/controllers/google_api/authorizations_controller.rb +++ b/app/controllers/google_api/authorizations_controller.rb @@ -15,6 +15,9 @@ module GoogleApi session[GoogleApi::CloudPlatform::Client.session_key_for_expires_at] = expires_at.to_s + rescue ::Faraday::TimeoutError, ::Faraday::ConnectionFailed + flash[:alert] = _('Timeout connecting to the Google API. Please try again.') + ensure redirect_to redirect_uri_from_session end diff --git a/app/controllers/graphql_controller.rb b/app/controllers/graphql_controller.rb index 522d171b5bf..a1348e4d858 100644 --- a/app/controllers/graphql_controller.rb +++ b/app/controllers/graphql_controller.rb @@ -3,7 +3,12 @@ class GraphqlController < ApplicationController # Unauthenticated users have access to the API for public data skip_before_action :authenticate_user! - skip_around_action :set_session_storage + + # If a user is using their session to access GraphQL, we need to have session + # storage, since the admin-mode check is session wide. + # We can't enable this for anonymous users because that would cause users using + # enforced SSO from using an auth token to access the API. + skip_around_action :set_session_storage, unless: :current_user # Allow missing CSRF tokens, this would mean that if a CSRF is invalid or missing, # the user won't be authenticated but can proceed as an anonymous user. @@ -14,6 +19,7 @@ class GraphqlController < ApplicationController before_action :authorize_access_api! before_action(only: [:execute]) { authenticate_sessionless_user!(:api) } + before_action :set_user_last_activity # Since we deactivate authentication from the main ApplicationController and # defer it to :authorize_access_api!, we need to override the bypass session @@ -42,6 +48,12 @@ class GraphqlController < ApplicationController private + def set_user_last_activity + return unless current_user + + Users::ActivityService.new(current_user).execute + end + def execute_multiplex GitlabSchema.multiplex(multiplex_queries, context: context) end diff --git a/app/controllers/groups/group_links_controller.rb b/app/controllers/groups/group_links_controller.rb index 23daa29ac43..52ee69edaa5 100644 --- a/app/controllers/groups/group_links_controller.rb +++ b/app/controllers/groups/group_links_controller.rb @@ -1,7 +1,6 @@ # frozen_string_literal: true class Groups::GroupLinksController < Groups::ApplicationController - before_action :check_feature_flag! before_action :authorize_admin_group! before_action :group_link, only: [:update, :destroy] @@ -51,8 +50,4 @@ class Groups::GroupLinksController < Groups::ApplicationController def group_link_params params.require(:group_link).permit(:group_access, :expires_at) end - - def check_feature_flag! - render_404 unless Feature.enabled?(:share_group_with_group, default_enabled: true) - end end diff --git a/app/controllers/groups/group_members_controller.rb b/app/controllers/groups/group_members_controller.rb index 664c58e8b7a..63311ab983b 100644 --- a/app/controllers/groups/group_members_controller.rb +++ b/app/controllers/groups/group_members_controller.rb @@ -21,19 +21,26 @@ class Groups::GroupMembersController < Groups::ApplicationController def index @sort = params[:sort].presence || sort_value_name + @project = @group.projects.find(params[:project_id]) if params[:project_id] - @members = find_members + + @members = GroupMembersFinder + .new(@group, current_user, params: filter_params) + .execute(include_relations: requested_relations) if can_manage_members @skip_groups = @group.related_group_ids - @invited_members = present_invited_members(@members) + + @invited_members = @members.invite + @invited_members = @invited_members.search_invite_email(params[:search_invited]) if params[:search_invited].present? + @invited_members = present_invited_members(@invited_members) end - @members = @members.non_invite - @members = present_group_members(@members) + @members = present_group_members(@members.non_invite) @requesters = present_members( - AccessRequestsFinder.new(@group).execute(current_user)) + AccessRequestsFinder.new(@group).execute(current_user) + ) @group_member = @group.group_members.new end @@ -43,30 +50,24 @@ class Groups::GroupMembersController < Groups::ApplicationController private - def present_invited_members(members) - invited_members = members.invite - - if params[:search_invited].present? - invited_members = invited_members.search_invite_email(params[:search_invited]) - end - - present_members(invited_members - .page(params[:invited_members_page]) - .per(MEMBER_PER_PAGE_LIMIT)) + def can_manage_members + can?(current_user, :admin_group_member, @group) end - def find_members - filter_params = params.slice(:two_factor, :search).merge(sort: @sort) - GroupMembersFinder.new(@group, current_user, params: filter_params).execute(include_relations: requested_relations) + def present_invited_members(invited_members) + present_members(invited_members + .page(params[:invited_members_page]) + .per(MEMBER_PER_PAGE_LIMIT)) end - def can_manage_members - can?(current_user, :admin_group_member, @group) + def present_group_members(members) + present_members(members + .page(params[:page]) + .per(MEMBER_PER_PAGE_LIMIT)) end - def present_group_members(original_members) - members = original_members.page(params[:page]).per(MEMBER_PER_PAGE_LIMIT) - present_members(members) + def filter_params + params.permit(:two_factor, :search).merge(sort: @sort) end end diff --git a/app/controllers/groups/registry/repositories_controller.rb b/app/controllers/groups/registry/repositories_controller.rb index 16aa6e50320..14651e0794a 100644 --- a/app/controllers/groups/registry/repositories_controller.rb +++ b/app/controllers/groups/registry/repositories_controller.rb @@ -9,7 +9,9 @@ module Groups respond_to do |format| format.html format.json do - @images = ContainerRepositoriesFinder.new(user: current_user, subject: group).execute.with_api_entity_associations + @images = ContainerRepositoriesFinder.new(user: current_user, subject: group, params: params.slice(:name)) + .execute + .with_api_entity_associations track_event(:list_repositories) diff --git a/app/controllers/groups/settings/repository_controller.rb b/app/controllers/groups/settings/repository_controller.rb index 6e8c5628d24..4af5e613296 100644 --- a/app/controllers/groups/settings/repository_controller.rb +++ b/app/controllers/groups/settings/repository_controller.rb @@ -46,7 +46,7 @@ module Groups end def deploy_token_params - params.require(:deploy_token).permit(:name, :expires_at, :read_repository, :read_registry, :write_registry, :username) + params.require(:deploy_token).permit(:name, :expires_at, :read_repository, :read_registry, :write_registry, :read_package_registry, :write_package_registry, :username) end end end diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb index 44120fda17c..d5f2239b16a 100644 --- a/app/controllers/groups_controller.rb +++ b/app/controllers/groups_controller.rb @@ -31,6 +31,10 @@ class GroupsController < Groups::ApplicationController push_frontend_feature_flag(:vue_issuables_list, @group) end + before_action do + set_not_query_feature_flag(@group) + end + before_action :export_rate_limit, only: [:export, :download_export] skip_cross_project_access_check :index, :new, :create, :edit, :update, @@ -142,7 +146,7 @@ class GroupsController < Groups::ApplicationController export_service = Groups::ImportExport::ExportService.new(group: @group, user: current_user) if export_service.async_execute - redirect_to edit_group_path(@group), notice: _('Group export started.') + redirect_to edit_group_path(@group), notice: _('Group export started. A download link will be sent by email and made available on this page.') else redirect_to edit_group_path(@group), alert: _('Group export could not be started.') end diff --git a/app/controllers/help_controller.rb b/app/controllers/help_controller.rb index 91bba1eb617..a1bbcf34f69 100644 --- a/app/controllers/help_controller.rb +++ b/app/controllers/help_controller.rb @@ -26,7 +26,7 @@ class HelpController < ApplicationController respond_to do |format| format.any(:markdown, :md, :html) do - # Note: We are purposefully NOT using `Rails.root.join` + # Note: We are purposefully NOT using `Rails.root.join` because of https://gitlab.com/gitlab-org/gitlab/-/issues/216028. path = File.join(Rails.root, 'doc', "#{@path}.md") if File.exist?(path) @@ -42,7 +42,7 @@ class HelpController < ApplicationController # 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` + # Note: We are purposefully NOT using `Rails.root.join` because of https://gitlab.com/gitlab-org/gitlab/-/issues/216028. path = File.join(Rails.root, 'doc', "#{@path}.#{params[:format]}") if File.exist?(path) diff --git a/app/controllers/ide_controller.rb b/app/controllers/ide_controller.rb index bffbdf01f8f..8a838db04f9 100644 --- a/app/controllers/ide_controller.rb +++ b/app/controllers/ide_controller.rb @@ -6,10 +6,6 @@ class IdeController < ApplicationController include ClientsidePreviewCSP include StaticObjectExternalStorageCSP - before_action do - push_frontend_feature_flag(:webide_dark_theme) - end - def index Gitlab::UsageDataCounters::WebIdeCounter.increment_views_count end diff --git a/app/controllers/import/github_controller.rb b/app/controllers/import/github_controller.rb index 34af1ecd6a5..4e8ceae75bd 100644 --- a/app/controllers/import/github_controller.rb +++ b/app/controllers/import/github_controller.rb @@ -144,7 +144,7 @@ class Import::GithubController < Import::BaseController end def provider_rate_limit(exception) - reset_time = Time.at(exception.response_headers['x-ratelimit-reset'].to_i) + reset_time = Time.zone.at(exception.response_headers['x-ratelimit-reset'].to_i) session[access_token_key] = nil redirect_to new_import_url, alert: _("GitHub API rate limit exceeded. Try again after %{reset_time}") % { reset_time: reset_time } diff --git a/app/controllers/import/google_code_controller.rb b/app/controllers/import/google_code_controller.rb index 4dddfbcd20d..03bde0345e3 100644 --- a/app/controllers/import/google_code_controller.rb +++ b/app/controllers/import/google_code_controller.rb @@ -15,7 +15,7 @@ class Import::GoogleCodeController < Import::BaseController end begin - dump = JSON.parse(dump_file.read) + dump = Gitlab::Json.parse(dump_file.read) rescue return redirect_back_or_default(options: { alert: _("The uploaded file is not a valid Google Takeout archive.") }) end @@ -42,7 +42,7 @@ class Import::GoogleCodeController < Import::BaseController user_map_json = "{}" if user_map_json.blank? begin - user_map = JSON.parse(user_map_json) + user_map = Gitlab::Json.parse(user_map_json) rescue flash.now[:alert] = _("The entered user map is not a valid JSON user map.") diff --git a/app/controllers/jwt_controller.rb b/app/controllers/jwt_controller.rb index da39d64c93d..3e7755046cd 100644 --- a/app/controllers/jwt_controller.rb +++ b/app/controllers/jwt_controller.rb @@ -4,7 +4,9 @@ class JwtController < ApplicationController skip_around_action :set_session_storage skip_before_action :authenticate_user! skip_before_action :verify_authenticity_token - before_action :authenticate_project_or_user + + # Add this before other actions, since we want to have the user or project + prepend_before_action :auth_user, :authenticate_project_or_user SERVICES = { Auth::ContainerRegistryAuthenticationService::AUDIENCE => Auth::ContainerRegistryAuthenticationService @@ -75,4 +77,11 @@ class JwtController < ApplicationController Array(Rack::Utils.parse_query(request.query_string)['scope']) end + + def auth_user + strong_memoize(:auth_user) do + actor = @authentication_result&.actor + actor.is_a?(User) ? actor : nil + end + end end diff --git a/app/controllers/ldap/omniauth_callbacks_controller.rb b/app/controllers/ldap/omniauth_callbacks_controller.rb index 8e4d8f3d21b..4b6339c21cd 100644 --- a/app/controllers/ldap/omniauth_callbacks_controller.rb +++ b/app/controllers/ldap/omniauth_callbacks_controller.rb @@ -16,6 +16,10 @@ class Ldap::OmniauthCallbacksController < OmniauthCallbacksController def ldap return unless Gitlab::Auth::Ldap::Config.sign_in_enabled? + if Feature.enabled?(:user_mode_in_session) + return admin_mode_flow(Gitlab::Auth::Ldap::User) if current_user_mode.admin_mode_requested? + end + sign_in_user_flow(Gitlab::Auth::Ldap::User) end diff --git a/app/controllers/omniauth_callbacks_controller.rb b/app/controllers/omniauth_callbacks_controller.rb index d82a46e57ea..4c595313cb6 100644 --- a/app/controllers/omniauth_callbacks_controller.rb +++ b/app/controllers/omniauth_callbacks_controller.rb @@ -6,6 +6,9 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController include Devise::Controllers::Rememberable include AuthHelper include InitializesCurrentUserMode + include KnownSignIn + + after_action :verify_known_sign_in protect_from_forgery except: [:kerberos, :saml, :cas3, :failure], with: :exception, prepend: true @@ -87,6 +90,14 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController private + def after_omniauth_failure_path_for(scope) + if Feature.enabled?(:user_mode_in_session) + return new_admin_session_path if current_user_mode.admin_mode_requested? + end + + super + end + def omniauth_flow(auth_module, identity_linker: nil) if fragment = request.env.dig('omniauth.params', 'redirect_fragment').presence store_redirect_fragment(fragment) diff --git a/app/controllers/projects/alert_management_controller.rb b/app/controllers/projects/alert_management_controller.rb new file mode 100644 index 00000000000..0c0a91e136f --- /dev/null +++ b/app/controllers/projects/alert_management_controller.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true + +class Projects::AlertManagementController < Projects::ApplicationController + before_action :authorize_read_alert_management_alert! + before_action do + push_frontend_feature_flag(:alert_list_status_filtering_enabled) + push_frontend_feature_flag(:create_issue_from_alert_enabled) + end + + def index + end + + def details + @alert_id = params[:id] + end +end diff --git a/app/controllers/projects/artifacts_controller.rb b/app/controllers/projects/artifacts_controller.rb index 50399a8cfbb..b8663bc59f2 100644 --- a/app/controllers/projects/artifacts_controller.rb +++ b/app/controllers/projects/artifacts_controller.rb @@ -10,7 +10,7 @@ class Projects::ArtifactsController < Projects::ApplicationController 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: [:index, :download, :destroy] + before_action :validate_artifacts!, except: [:index, :download, :raw, :destroy] before_action :entry, only: [:file] MAX_PER_PAGE = 20 @@ -22,7 +22,7 @@ class Projects::ArtifactsController < Projects::ApplicationController # 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) + finder = Ci::JobArtifactsFinder.new(@project, artifacts_params) all_artifacts = finder.execute @artifacts = all_artifacts.page(params[:page]).per(MAX_PER_PAGE) @@ -73,9 +73,11 @@ class Projects::ArtifactsController < Projects::ApplicationController end def raw + return render_404 unless zip_artifact? + path = Gitlab::Ci::Build::Artifacts::Path.new(params[:path]) - send_artifacts_entry(build, path) + send_artifacts_entry(artifacts_file, path) end def keep @@ -138,6 +140,13 @@ class Projects::ArtifactsController < Projects::ApplicationController @artifacts_file ||= build&.artifacts_file_for_type(params[:file_type] || :archive) end + def zip_artifact? + types = HashWithIndifferentAccess.new(Ci::JobArtifact::TYPE_AND_FORMAT_PAIRS) + file_type = params[:file_type] || :archive + + types[file_type] == :zip + end + def entry @entry = build.artifacts_metadata_entry(params[:path]) diff --git a/app/controllers/projects/branches_controller.rb b/app/controllers/projects/branches_controller.rb index 09754409104..cc595740696 100644 --- a/app/controllers/projects/branches_controller.rb +++ b/app/controllers/projects/branches_controller.rb @@ -186,7 +186,6 @@ class Projects::BranchesController < Projects::ApplicationController end def confidential_issue_project - return unless helpers.create_confidential_merge_request_enabled? return if params[:confidential_issue_project_id].blank? confidential_issue_project = Project.find(params[:confidential_issue_project_id]) diff --git a/app/controllers/projects/ci/daily_build_group_report_results_controller.rb b/app/controllers/projects/ci/daily_build_group_report_results_controller.rb new file mode 100644 index 00000000000..dfda5fca310 --- /dev/null +++ b/app/controllers/projects/ci/daily_build_group_report_results_controller.rb @@ -0,0 +1,77 @@ +# frozen_string_literal: true + +class Projects::Ci::DailyBuildGroupReportResultsController < Projects::ApplicationController + include Gitlab::Utils::StrongMemoize + + MAX_ITEMS = 1000 + REPORT_WINDOW = 90.days + + before_action :validate_feature_flag! + before_action :authorize_download_code! # Share the same authorization rules as the graphs controller + before_action :validate_param_type! + + def index + respond_to do |format| + format.csv { send_data(render_csv(results), type: 'text/csv; charset=utf-8') } + end + end + + private + + def validate_feature_flag! + render_404 unless Feature.enabled?(:ci_download_daily_code_coverage, project, default_enabled: true) + end + + def validate_param_type! + respond_422 unless allowed_param_types.include?(param_type) + end + + def render_csv(collection) + CsvBuilders::SingleBatch.new( + collection, + { + date: 'date', + group_name: 'group_name', + param_type => -> (record) { record.data[param_type] } + } + ).render + end + + def results + Ci::DailyBuildGroupReportResultsFinder.new(finder_params).execute + end + + def finder_params + { + current_user: current_user, + project: project, + ref_path: params.require(:ref_path), + start_date: start_date, + end_date: end_date, + limit: MAX_ITEMS + } + end + + def start_date + strong_memoize(:start_date) do + start_date = Date.parse(params.require(:start_date)) + + # The start_date cannot be older than `end_date - 90 days` + [start_date, end_date - REPORT_WINDOW].max + end + end + + def end_date + strong_memoize(:end_date) do + Date.parse(params.require(:end_date)) + end + end + + def allowed_param_types + Ci::DailyBuildGroupReportResult::PARAM_TYPES + end + + def param_type + params.require(:param_type) + end +end diff --git a/app/controllers/projects/design_management/designs/raw_images_controller.rb b/app/controllers/projects/design_management/designs/raw_images_controller.rb new file mode 100644 index 00000000000..beb7e9d294b --- /dev/null +++ b/app/controllers/projects/design_management/designs/raw_images_controller.rb @@ -0,0 +1,30 @@ +# frozen_string_literal: true + +# Returns full-size design images +module Projects + module DesignManagement + module Designs + class RawImagesController < Projects::DesignManagement::DesignsController + include SendsBlob + + skip_before_action :default_cache_headers, only: :show + + def show + blob = design_repository.blob_at(ref, design.full_path) + + send_blob(design_repository, blob, inline: false, allow_caching: project.public?) + end + + private + + def design_repository + @design_repository ||= project.design_repository + end + + def ref + sha || design_repository.root_ref + end + end + end + end +end diff --git a/app/controllers/projects/design_management/designs/resized_image_controller.rb b/app/controllers/projects/design_management/designs/resized_image_controller.rb new file mode 100644 index 00000000000..50a997f32db --- /dev/null +++ b/app/controllers/projects/design_management/designs/resized_image_controller.rb @@ -0,0 +1,46 @@ +# frozen_string_literal: true + +# Returns smaller sized design images +module Projects + module DesignManagement + module Designs + class ResizedImageController < Projects::DesignManagement::DesignsController + include SendFileUpload + + before_action :validate_size! + + skip_before_action :default_cache_headers, only: :show + + def show + relation = design.actions + relation = relation.up_to_version(sha) if sha + action = relation.most_recent.first + + return render_404 unless action + + # This controller returns a 404 if the the `size` param + # is not one of our specific sizes, so using `send` here is safe. + uploader = action.public_send(:"image_#{size}") # rubocop:disable GitlabSecurity/PublicSend + + return render_404 unless uploader.file # The image has not been processed + + if stale?(etag: action.cache_key) + workhorse_set_content_type! + + send_upload(uploader, attachment: design.filename) + end + end + + private + + def validate_size! + render_404 unless ::DesignManagement::DESIGN_IMAGE_SIZES.include?(size) + end + + def size + params[:id] + end + end + end + end +end diff --git a/app/controllers/projects/design_management/designs_controller.rb b/app/controllers/projects/design_management/designs_controller.rb new file mode 100644 index 00000000000..fec09fa9515 --- /dev/null +++ b/app/controllers/projects/design_management/designs_controller.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +class Projects::DesignManagement::DesignsController < Projects::ApplicationController + before_action :authorize_read_design! + + private + + def authorize_read_design! + unless can?(current_user, :read_design, design) + access_denied! + end + end + + def design + @design ||= project.designs.find(params[:design_id]) + end + + def sha + params[:sha].presence + end +end diff --git a/app/controllers/projects/environments_controller.rb b/app/controllers/projects/environments_controller.rb index 09dc4d118a1..5f4d88c57e9 100644 --- a/app/controllers/projects/environments_controller.rb +++ b/app/controllers/projects/environments_controller.rb @@ -4,6 +4,12 @@ class Projects::EnvironmentsController < Projects::ApplicationController include MetricsDashboard layout 'project' + + before_action only: [:metrics, :additional_metrics, :metrics_dashboard] do + authorize_metrics_dashboard! + + push_frontend_feature_flag(:prometheus_computed_alerts) + end before_action :authorize_read_environment! before_action :authorize_create_environment!, only: [:new, :create] before_action :authorize_stop_environment!, only: [:stop] @@ -12,10 +18,6 @@ class Projects::EnvironmentsController < Projects::ApplicationController before_action :environment, only: [:show, :edit, :update, :stop, :terminal, :terminal_websocket_authorize, :metrics, :cancel_auto_stop] before_action :verify_api_request!, only: :terminal_websocket_authorize before_action :expire_etag_cache, only: [:index], unless: -> { request.format.json? } - before_action only: [:metrics, :additional_metrics, :metrics_dashboard] do - push_frontend_feature_flag(:prometheus_computed_alerts) - push_frontend_feature_flag(:metrics_dashboard_annotations) - end after_action :expire_etag_cache, only: [:cancel_auto_stop] def index @@ -27,12 +29,13 @@ class Projects::EnvironmentsController < Projects::ApplicationController format.html format.json do Gitlab::PollingInterval.set_header(response, interval: 3_000) + environments_count_by_state = project.environments.count_by_state render json: { environments: serialize_environments(request, response, params[:nested]), review_app: serialize_review_app, - available_count: project.environments.available.count, - stopped_count: project.environments.stopped.count + available_count: environments_count_by_state[:available], + stopped_count: environments_count_by_state[:stopped] } end end diff --git a/app/controllers/projects/graphs_controller.rb b/app/controllers/projects/graphs_controller.rb index 889dcefb65a..34246f27241 100644 --- a/app/controllers/projects/graphs_controller.rb +++ b/app/controllers/projects/graphs_controller.rb @@ -28,6 +28,7 @@ class Projects::GraphsController < Projects::ApplicationController def charts get_commits get_languages + get_daily_coverage_options end def ci @@ -52,6 +53,27 @@ class Projects::GraphsController < Projects::ApplicationController end end + def get_daily_coverage_options + return unless Feature.enabled?(:ci_download_daily_code_coverage, default_enabled: true) + + date_today = Date.current + report_window = Projects::Ci::DailyBuildGroupReportResultsController::REPORT_WINDOW + + @daily_coverage_options = { + base_params: { + start_date: date_today - report_window, + end_date: date_today, + ref_path: @project.repository.expand_ref(@ref), + param_type: 'coverage' + }, + download_path: namespace_project_ci_daily_build_group_report_results_path( + namespace_id: @project.namespace, + project_id: @project, + format: :csv + ) + } + end + def fetch_graph @commits = @project.repository.commits(@ref, limit: 6000, skip_merges: true) @log = [] diff --git a/app/controllers/projects/import/jira_controller.rb b/app/controllers/projects/import/jira_controller.rb index 4a70ed45404..711e23dc3ce 100644 --- a/app/controllers/projects/import/jira_controller.rb +++ b/app/controllers/projects/import/jira_controller.rb @@ -36,7 +36,7 @@ module Projects response = ::JiraImport::StartImportService.new(current_user, @project, jira_project_key).execute flash[:notice] = response.message if response.message.present? else - flash[:alert] = 'No jira project key has been provided.' + flash[:alert] = 'No Jira project key has been provided.' end redirect_to project_import_jira_path(@project) diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb index 3aae8990f07..3e9d956f7b1 100644 --- a/app/controllers/projects/issues_controller.rb +++ b/app/controllers/projects/issues_controller.rb @@ -21,7 +21,6 @@ class Projects::IssuesController < Projects::ApplicationController prepend_before_action(only: [:index]) { authenticate_sessionless_user!(:rss) } prepend_before_action(only: [:calendar]) { authenticate_sessionless_user!(:ics) } prepend_before_action :authenticate_user!, only: [:new, :export_csv] - # designs is only applicable to EE, but defining a prepend_before_action in EE code would overwrite this prepend_before_action :store_uri, only: [:new, :show, :designs] before_action :whitelist_query_limiting, only: [:create, :create_merge_request, :move, :bulk_update] @@ -50,6 +49,10 @@ class Projects::IssuesController < Projects::ApplicationController push_frontend_feature_flag(:save_issuable_health_status, project.group, default_enabled: true) end + before_action only: :show do + push_frontend_feature_flag(:real_time_issue_sidebar, @project) + end + around_action :allow_gitaly_ref_name_caching, only: [:discussions] respond_to :html @@ -81,11 +84,13 @@ class Projects::IssuesController < Projects::ApplicationController ) build_params = issue_params.merge( merge_request_to_resolve_discussions_of: params[:merge_request_to_resolve_discussions_of], - discussion_to_resolve: params[:discussion_to_resolve] + discussion_to_resolve: params[:discussion_to_resolve], + confidential: !!Gitlab::Utils.to_boolean(params[:issue][:confidential]) ) service = Issues::BuildService.new(project, current_user, build_params) @issue = @noteable = service.execute + @merge_request_to_resolve_discussions_of = service.merge_request_to_resolve_discussions_of @discussion_to_resolve = service.discussions_to_resolve.first if params[:discussion_to_resolve] @@ -154,7 +159,10 @@ class Projects::IssuesController < Projects::ApplicationController end def related_branches - @related_branches = Issues::RelatedBranchesService.new(project, current_user).execute(issue) + @related_branches = Issues::RelatedBranchesService + .new(project, current_user) + .execute(issue) + .map { |branch| branch.merge(link: branch_link(branch)) } respond_to do |format| format.json do @@ -179,7 +187,7 @@ class Projects::IssuesController < Projects::ApplicationController def create_merge_request create_params = params.slice(:branch_name, :ref).merge(issue_iid: issue.iid) - create_params[:target_project_id] = params[:target_project_id] if helpers.create_confidential_merge_request_enabled? + create_params[:target_project_id] = params[:target_project_id] result = ::MergeRequests::CreateFromIssueService.new(project, current_user, create_params).execute if result[:status] == :success @@ -193,7 +201,8 @@ class Projects::IssuesController < Projects::ApplicationController ExportCsvWorker.perform_async(current_user.id, project.id, finder_options.to_h) # rubocop:disable CodeReuse/Worker index_path = project_issues_path(project) - redirect_to(index_path, notice: "Your CSV export has started. It will be emailed to #{current_user.notification_email} when complete.") + message = _('Your CSV export has started. It will be emailed to %{email} when complete.') % { email: current_user.notification_email } + redirect_to(index_path, notice: message) end def import_csv @@ -305,6 +314,10 @@ class Projects::IssuesController < Projects::ApplicationController private + def branch_link(branch) + project_compare_path(project, from: project.default_branch, to: branch[:name]) + end + def create_rate_limit key = :issues_create diff --git a/app/controllers/projects/mattermosts_controller.rb b/app/controllers/projects/mattermosts_controller.rb index 085b1bc1498..cfaeddf711a 100644 --- a/app/controllers/projects/mattermosts_controller.rb +++ b/app/controllers/projects/mattermosts_controller.rb @@ -30,7 +30,7 @@ class Projects::MattermostsController < Projects::ApplicationController def configure_params params.require(:mattermost).permit(:trigger, :team_id).merge( url: service_trigger_url(@service), - icon_url: asset_url('slash-command-logo.png')) + icon_url: asset_url('slash-command-logo.png', skip_pipeline: true)) end def teams diff --git a/app/controllers/projects/merge_requests/creations_controller.rb b/app/controllers/projects/merge_requests/creations_controller.rb index 23222cbd37c..28aa1b300aa 100644 --- a/app/controllers/projects/merge_requests/creations_controller.rb +++ b/app/controllers/projects/merge_requests/creations_controller.rb @@ -16,7 +16,6 @@ class Projects::MergeRequests::CreationsController < Projects::MergeRequests::Ap end def create - @target_branches ||= [] @merge_request = ::MergeRequests::CreateService.new(project, current_user, merge_request_params).execute if @merge_request.valid? @@ -97,13 +96,6 @@ class Projects::MergeRequests::CreationsController < Projects::MergeRequests::Ap def define_new_vars @noteable = @merge_request - - @target_branches = if @merge_request.target_project - @merge_request.target_project.repository.branch_names - else - [] - end - @target_project = @merge_request.target_project @source_project = @merge_request.source_project diff --git a/app/controllers/projects/merge_requests/diffs_controller.rb b/app/controllers/projects/merge_requests/diffs_controller.rb index 79598c0aaff..2331674f42c 100644 --- a/app/controllers/projects/merge_requests/diffs_controller.rb +++ b/app/controllers/projects/merge_requests/diffs_controller.rb @@ -9,6 +9,8 @@ class Projects::MergeRequests::DiffsController < Projects::MergeRequests::Applic before_action :define_diff_vars before_action :define_diff_comment_vars, except: [:diffs_batch, :diffs_metadata] + around_action :allow_gitaly_ref_name_caching + def show render_diffs end diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb index 8c37d70d4c9..5613b5b9589 100644 --- a/app/controllers/projects/merge_requests_controller.rb +++ b/app/controllers/projects/merge_requests_controller.rb @@ -14,7 +14,13 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo 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_read_actual_head_pipeline!, only: [:test_reports, :exposed_artifacts, :coverage_reports] + before_action :authorize_read_actual_head_pipeline!, only: [ + :test_reports, + :exposed_artifacts, + :coverage_reports, + :terraform_reports, + :accessibility_reports + ] 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] @@ -26,7 +32,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo push_frontend_feature_flag(:code_navigation, @project) push_frontend_feature_flag(:widget_visibility_polling, @project, default_enabled: true) push_frontend_feature_flag(:merge_ref_head_comments, @project) - push_frontend_feature_flag(:diff_compare_with_head, @project) + push_frontend_feature_flag(:mr_commit_neighbor_nav, @project, default_enabled: true) end before_action do @@ -136,6 +142,14 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo reports_response(@merge_request.compare_test_reports) end + def accessibility_reports + if @merge_request.has_accessibility_reports? + reports_response(@merge_request.compare_accessibility_reports) + else + head :no_content + end + end + def coverage_reports if @merge_request.has_coverage_reports? reports_response(@merge_request.find_coverage_reports) @@ -144,6 +158,10 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo end end + def terraform_reports + reports_response(@merge_request.find_terraform_reports) + end + def exposed_artifacts if @merge_request.has_exposed_artifacts? reports_response(@merge_request.find_exposed_artifacts) @@ -353,7 +371,6 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo def define_edit_vars @source_project = @merge_request.source_project @target_project = @merge_request.target_project - @target_branches = @merge_request.target_project.repository.branch_names @noteable = @merge_request # FIXME: We have to assign a presenter to another instance variable diff --git a/app/controllers/projects/pipelines_controller.rb b/app/controllers/projects/pipelines_controller.rb index 726ce8974c7..678d0862f48 100644 --- a/app/controllers/projects/pipelines_controller.rb +++ b/app/controllers/projects/pipelines_controller.rb @@ -11,7 +11,9 @@ class Projects::PipelinesController < Projects::ApplicationController before_action :authorize_create_pipeline!, only: [:new, :create] before_action :authorize_update_pipeline!, only: [:retry, :cancel] before_action do - push_frontend_feature_flag(:junit_pipeline_view) + push_frontend_feature_flag(:junit_pipeline_view, project) + push_frontend_feature_flag(:filter_pipelines_search, default_enabled: true) + push_frontend_feature_flag(:dag_pipeline_tab) end before_action :ensure_pipeline, only: [:show] @@ -22,9 +24,8 @@ class Projects::PipelinesController < Projects::ApplicationController POLLING_INTERVAL = 10_000 def index - @scope = params[:scope] @pipelines = Ci::PipelinesFinder - .new(project, current_user, scope: @scope) + .new(project, current_user, index_params) .execute .page(params[:page]) .per(30) @@ -69,6 +70,8 @@ class Projects::PipelinesController < Projects::ApplicationController end def show + Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab/-/issues/26657') + respond_to do |format| format.html format.json do @@ -91,6 +94,10 @@ class Projects::PipelinesController < Projects::ApplicationController render_show end + def dag + render_show + end + def failures if @pipeline.failed_builds.present? render_show @@ -169,19 +176,9 @@ class Projects::PipelinesController < Projects::ApplicationController end format.json do - if pipeline_test_report == :error - render json: { status: :error_parsing_report } - else - test_reports = if params[:scope] == "with_attachment" - pipeline_test_report.with_attachment! - else - pipeline_test_report - end - - render json: TestReportSerializer - .new(current_user: @current_user) - .represent(test_reports, project: project) - end + render json: TestReportSerializer + .new(current_user: @current_user) + .represent(pipeline_test_report, project: project) end end end @@ -189,11 +186,7 @@ class Projects::PipelinesController < Projects::ApplicationController def test_reports_count return unless Feature.enabled?(:junit_pipeline_view, project) - begin - render json: { total_count: pipeline.test_reports_count }.to_json - rescue Gitlab::Ci::Parsers::ParserError - render json: { total_count: 0 }.to_json - end + render json: { total_count: pipeline.test_reports_count }.to_json end private @@ -262,18 +255,22 @@ class Projects::PipelinesController < Projects::ApplicationController end def limited_pipelines_count(project, scope = nil) - finder = Ci::PipelinesFinder.new(project, current_user, scope: scope) + finder = Ci::PipelinesFinder.new(project, current_user, index_params.merge(scope: scope)) 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 + @pipeline.test_reports.tap do |reports| + reports.with_attachment! if params[:scope] == 'with_attachment' + end end end + + def index_params + params.permit(:scope, :username, :ref) + end end Projects::PipelinesController.prepend_if_ee('EE::Projects::PipelinesController') diff --git a/app/controllers/projects/project_members_controller.rb b/app/controllers/projects/project_members_controller.rb index 109c8b7005f..3e52248f292 100644 --- a/app/controllers/projects/project_members_controller.rb +++ b/app/controllers/projects/project_members_controller.rb @@ -17,8 +17,9 @@ class Projects::ProjectMembersController < Projects::ApplicationController @group_links = @project.project_group_links @group_links = @group_links.search(params[:search]) if params[:search].present? - @project_members = MembersFinder.new(@project, current_user) - .execute(include_relations: requested_relations, params: params.merge(sort: @sort)) + @project_members = MembersFinder + .new(@project, current_user, params: filter_params) + .execute(include_relations: requested_relations) @project_members = present_members(@project_members.page(params[:page])) @@ -43,12 +44,17 @@ class Projects::ProjectMembersController < Projects::ApplicationController return render_404 end - redirect_to(project_project_members_path(project), - notice: notice) + redirect_to(project_project_members_path(project), notice: notice) end # MembershipActions concern alias_method :membershipable, :project + + private + + def filter_params + params.permit(:search).merge(sort: @sort) + end end Projects::ProjectMembersController.prepend_if_ee('EE::Projects::ProjectMembersController') diff --git a/app/controllers/projects/refs_controller.rb b/app/controllers/projects/refs_controller.rb index 7c606bd8c45..fcbeb5c840c 100644 --- a/app/controllers/projects/refs_controller.rb +++ b/app/controllers/projects/refs_controller.rb @@ -12,7 +12,7 @@ class Projects::RefsController < Projects::ApplicationController before_action :authorize_download_code! before_action only: [:logs_tree] do - push_frontend_feature_flag(:vue_file_list_lfs_badge) + push_frontend_feature_flag(:vue_file_list_lfs_badge, default_enabled: true) end def switch @@ -44,30 +44,25 @@ class Projects::RefsController < Projects::ApplicationController end def logs_tree - summary = ::Gitlab::TreeSummary.new( - @commit, - @project, - path: @path, - offset: params[:offset], - limit: 25 - ) - - @logs, commits = summary.summarize - @more_log_url = more_url(summary.next_offset) if summary.more? + tree_summary = ::Gitlab::TreeSummary.new( + @commit, @project, current_user, + path: @path, offset: params[:offset], limit: 25) respond_to do |format| format.html { render_404 } format.json do - response.headers["More-Logs-Url"] = @more_log_url if summary.more? - response.headers["More-Logs-Offset"] = summary.next_offset if summary.more? - render json: @logs + logs, next_offset = tree_summary.fetch_logs + + response.headers["More-Logs-Offset"] = next_offset if next_offset + + render json: logs end - # The commit titles must be rendered and redacted before being shown. - # Doing it here allows us to apply performance optimizations that avoid - # N+1 problems + # Deprecated due to https://gitlab.com/gitlab-org/gitlab/-/issues/36863 + # Will be removed soon https://gitlab.com/gitlab-org/gitlab/-/merge_requests/29895 format.js do - prerender_commit_full_titles!(commits) + @logs, _ = tree_summary.summarize + @more_log_url = more_url(tree_summary.next_offset) if tree_summary.more? end end end @@ -78,14 +73,6 @@ class Projects::RefsController < Projects::ApplicationController logs_file_project_ref_path(@project, @ref, @path, offset: offset) end - def prerender_commit_full_titles!(commits) - # Preload commit authors as they are used in rendering - commits.each(&:lazy_author) - - renderer = Banzai::ObjectRenderer.new(user: current_user, default_project: @project) - renderer.render(commits, :full_title) - end - def validate_ref_id return not_found! if params[:id].present? && params[:id] !~ Gitlab::PathRegex.git_reference_regex end diff --git a/app/controllers/projects/registry/repositories_controller.rb b/app/controllers/projects/registry/repositories_controller.rb index 2418ea97409..19d0cb9acdc 100644 --- a/app/controllers/projects/registry/repositories_controller.rb +++ b/app/controllers/projects/registry/repositories_controller.rb @@ -10,7 +10,8 @@ module Projects respond_to do |format| format.html format.json do - @images = project.container_repositories + @images = ContainerRepositoriesFinder.new(user: current_user, subject: project, params: params.slice(:name)) + .execute track_event(:list_repositories) diff --git a/app/controllers/projects/settings/access_tokens_controller.rb b/app/controllers/projects/settings/access_tokens_controller.rb new file mode 100644 index 00000000000..d6b4c4dd5dc --- /dev/null +++ b/app/controllers/projects/settings/access_tokens_controller.rb @@ -0,0 +1,71 @@ +# frozen_string_literal: true + +module Projects + module Settings + class AccessTokensController < Projects::ApplicationController + include ProjectsHelper + + before_action :check_feature_availability + + def index + @project_access_token = PersonalAccessToken.new + set_index_vars + end + + def create + token_response = ResourceAccessTokens::CreateService.new(current_user, @project, create_params).execute + + if token_response.success? + @project_access_token = token_response.payload[:access_token] + PersonalAccessToken.redis_store!(key_identity, @project_access_token.token) + + redirect_to namespace_project_settings_access_tokens_path, notice: _("Your new project access token has been created.") + else + render :index + end + end + + def revoke + @project_access_token = finder.find(params[:id]) + revoked_response = ResourceAccessTokens::RevokeService.new(current_user, @project, @project_access_token).execute + + if revoked_response.success? + flash[:notice] = _("Revoked project access token %{project_access_token_name}!") % { project_access_token_name: @project_access_token.name } + else + flash[:alert] = _("Could not revoke project access token %{project_access_token_name}.") % { project_access_token_name: @project_access_token.name } + end + + redirect_to namespace_project_settings_access_tokens_path + end + + private + + def check_feature_availability + render_404 unless project_access_token_available?(@project) + end + + def create_params + params.require(:project_access_token).permit(:name, :expires_at, scopes: []) + end + + def set_index_vars + @scopes = Gitlab::Auth.resource_bot_scopes + @active_project_access_tokens = finder(state: 'active').execute + @inactive_project_access_tokens = finder(state: 'inactive', sort: 'expires_at_asc').execute + @new_project_access_token = PersonalAccessToken.redis_getdel(key_identity) + end + + def finder(options = {}) + PersonalAccessTokensFinder.new({ user: bot_users, impersonation: false }.merge(options)) + end + + def bot_users + @project.bots + end + + def key_identity + "#{current_user.id}:#{@project.id}" + end + end + end +end diff --git a/app/controllers/projects/settings/repository_controller.rb b/app/controllers/projects/settings/repository_controller.rb index 0aa55dcc5b9..35ca9336613 100644 --- a/app/controllers/projects/settings/repository_controller.rb +++ b/app/controllers/projects/settings/repository_controller.rb @@ -89,7 +89,7 @@ module Projects end def deploy_token_params - params.require(:deploy_token).permit(:name, :expires_at, :read_repository, :read_registry, :write_registry, :username) + params.require(:deploy_token).permit(:name, :expires_at, :read_repository, :read_registry, :write_registry, :read_package_registry, :write_package_registry, :username) end def access_levels_options diff --git a/app/controllers/projects/snippets_controller.rb b/app/controllers/projects/snippets_controller.rb index da0e3a44f05..9233f063f55 100644 --- a/app/controllers/projects/snippets_controller.rb +++ b/app/controllers/projects/snippets_controller.rb @@ -52,15 +52,8 @@ class Projects::SnippetsController < Projects::ApplicationController create_params = snippet_params.merge(spammable_params) service_response = Snippets::CreateService.new(project, current_user, create_params).execute @snippet = service_response.payload[:snippet] - repository_operation_error = service_response.error? && !@snippet.persisted? && @snippet.valid? - if repository_operation_error - flash.now[:alert] = service_response.message - - render :new - else - recaptcha_check_with_fallback { render :new } - end + handle_repository_error(:new) end def update @@ -69,7 +62,7 @@ class Projects::SnippetsController < Projects::ApplicationController service_response = Snippets::UpdateService.new(project, current_user, update_params).execute(@snippet) @snippet = service_response.payload[:snippet] - check_repository_error + handle_repository_error(:edit) end def show diff --git a/app/controllers/projects/tree_controller.rb b/app/controllers/projects/tree_controller.rb index b8fe2a47b30..9cb345724cc 100644 --- a/app/controllers/projects/tree_controller.rb +++ b/app/controllers/projects/tree_controller.rb @@ -16,7 +16,7 @@ class Projects::TreeController < Projects::ApplicationController before_action :authorize_edit_tree!, only: [:create_dir] before_action only: [:show] do - push_frontend_feature_flag(:vue_file_list_lfs_badge) + push_frontend_feature_flag(:vue_file_list_lfs_badge, default_enabled: true) end def show diff --git a/app/controllers/projects/usage_ping_controller.rb b/app/controllers/projects/usage_ping_controller.rb index ebdf28bd59c..0e2c8f879b1 100644 --- a/app/controllers/projects/usage_ping_controller.rb +++ b/app/controllers/projects/usage_ping_controller.rb @@ -10,4 +10,10 @@ class Projects::UsagePingController < Projects::ApplicationController head(200) end + + def web_ide_pipelines_count + Gitlab::UsageDataCounters::WebIdeCounter.increment_pipelines_count + + head(200) + end end diff --git a/app/controllers/projects/wikis_controller.rb b/app/controllers/projects/wikis_controller.rb index 90ff798077a..508b1f5bd0a 100644 --- a/app/controllers/projects/wikis_controller.rb +++ b/app/controllers/projects/wikis_controller.rb @@ -10,8 +10,9 @@ class Projects::WikisController < Projects::ApplicationController before_action :authorize_admin_wiki!, only: :destroy before_action :load_project_wiki before_action :load_page, only: [:show, :edit, :update, :history, :destroy] - before_action :valid_encoding?, - if: -> { %w[show edit update].include?(action_name) && load_page } + before_action only: [:show, :edit, :update] do + @valid_encoding = valid_encoding? + end before_action only: [:edit, :update], unless: :valid_encoding? do redirect_to(project_wiki_path(@project, @page)) end @@ -64,7 +65,7 @@ class Projects::WikisController < Projects::ApplicationController def update return render('empty') unless can?(current_user, :create_wiki, @project) - @page = WikiPages::UpdateService.new(@project, current_user, wiki_params).execute(@page) + @page = WikiPages::UpdateService.new(container: @project, current_user: current_user, params: wiki_params).execute(@page) if @page.valid? redirect_to( @@ -80,7 +81,7 @@ class Projects::WikisController < Projects::ApplicationController end def create - @page = WikiPages::CreateService.new(@project, current_user, wiki_params).execute + @page = WikiPages::CreateService.new(container: @project, current_user: current_user, params: wiki_params).execute if @page.persisted? redirect_to( @@ -111,7 +112,7 @@ class Projects::WikisController < Projects::ApplicationController end def destroy - WikiPages::DestroyService.new(@project, current_user).execute(@page) + WikiPages::DestroyService.new(container: @project, current_user: current_user).execute(@page) redirect_to project_wiki_path(@project, :home), status: :found, @@ -144,7 +145,7 @@ class Projects::WikisController < Projects::ApplicationController @sidebar_page = @project_wiki.find_sidebar(params[:version_id]) unless @sidebar_page # Fallback to default sidebar - @sidebar_wiki_entries = WikiPage.group_by_directory(@project_wiki.list_pages(limit: 15)) + @sidebar_wiki_entries, @sidebar_limited = @project_wiki.sidebar_entries end rescue ProjectWiki::CouldNotCreateWikiError flash[:notice] = _("Could not create Wiki Repository at this time. Please try again later.") @@ -167,7 +168,11 @@ class Projects::WikisController < Projects::ApplicationController end def load_page - @page ||= @project_wiki.find_page(*page_params) + @page ||= find_page + end + + def find_page + @project_wiki.find_page(*page_params) end def page_params @@ -178,9 +183,11 @@ class Projects::WikisController < Projects::ApplicationController end def valid_encoding? - strong_memoize(:valid_encoding) do - @page.content.encoding == Encoding::UTF_8 - end + page_encoding == Encoding::UTF_8 + end + + def page_encoding + strong_memoize(:page_encoding) { @page&.content&.encoding } end def set_encoding_error diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index bb20ea1de49..2f86b945b06 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -36,10 +36,6 @@ class ProjectsController < Projects::ApplicationController layout :determine_layout - before_action do - push_frontend_feature_flag(:metrics_dashboard_visibility_switching_available) - end - def index redirect_to(current_user ? root_path : explore_root_path) end @@ -62,7 +58,7 @@ class ProjectsController < Projects::ApplicationController @project = ::Projects::CreateService.new(current_user, project_params(attributes: project_params_create_attributes)).execute if @project.saved? - cookies[:issue_board_welcome_hidden] = { path: project_path(@project), value: nil, expires: Time.at(0) } + cookies[:issue_board_welcome_hidden] = { path: project_path(@project), value: nil, expires: Time.zone.at(0) } redirect_to( project_path(@project, custom_import_params), @@ -205,7 +201,7 @@ class ProjectsController < Projects::ApplicationController redirect_to( edit_project_path(@project, anchor: 'js-export-project'), - notice: _("Project export started. A download link will be sent by email.") + notice: _("Project export started. A download link will be sent by email and made available on this page.") ) end @@ -403,6 +399,10 @@ class ProjectsController < Projects::ApplicationController snippets_access_level wiki_access_level pages_access_level + metrics_dashboard_access_level + ], + project_setting_attributes: %i[ + show_default_award_emojis ] ] end diff --git a/app/controllers/registrations_controller.rb b/app/controllers/registrations_controller.rb index a6c5a6d8526..ffbccbb01f2 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 :required_signup_info, only: [:welcome, :update_registration] + skip_before_action :required_signup_info, :check_two_factor_requirement, only: [:welcome, :update_registration] prepend_before_action :check_captcha, only: :create before_action :whitelist_query_limiting, only: [:destroy] before_action :ensure_terms_accepted, @@ -137,7 +137,6 @@ class RegistrationsController < Devise::RegistrationsController def check_captcha ensure_correct_params! - return unless Feature.enabled?(:registrations_recaptcha, default_enabled: true) # reCAPTCHA on the UI will still display however return unless show_recaptcha_sign_up? return unless Gitlab::Recaptcha.load_configurations! diff --git a/app/controllers/repositories/git_http_controller.rb b/app/controllers/repositories/git_http_controller.rb index 118036de230..e3dbe6fcbdf 100644 --- a/app/controllers/repositories/git_http_controller.rb +++ b/app/controllers/repositories/git_http_controller.rb @@ -4,7 +4,6 @@ module Repositories class GitHttpController < Repositories::GitHttpClientController include WorkhorseRequest - before_action :snippet_request_allowed? before_action :access_check prepend_before_action :deny_head_requests, only: [:info_refs] @@ -121,13 +120,6 @@ module Repositories def log_user_activity Users::ActivityService.new(user).execute end - - def snippet_request_allowed? - if repo_type.snippet? && Feature.disabled?(:version_snippets, user) - Gitlab::AppLogger.info('Snippet access attempt with feature disabled') - render plain: 'Snippet git access is disabled.', status: :forbidden - end - end end end diff --git a/app/controllers/search_controller.rb b/app/controllers/search_controller.rb index d1e15a72350..04d2b3068da 100644 --- a/app/controllers/search_controller.rb +++ b/app/controllers/search_controller.rb @@ -5,7 +5,6 @@ class SearchController < ApplicationController include SearchHelper include RendersCommits - before_action :override_snippet_scope, only: :show around_action :allow_gitaly_ref_name_caching skip_before_action :authenticate_user! @@ -104,14 +103,4 @@ class SearchController < ApplicationController Gitlab::UsageDataCounters::SearchCounter.increment_navbar_searches_count end - - # Disallow web snippet_blobs search as we migrate snippet - # from database-backed storage to git repository-based, - # and searching across multiple git repositories is not feasible. - # - # TODO: after 13.0 refactor this into Search::SnippetService - # See https://gitlab.com/gitlab-org/gitlab/issues/208882 - def override_snippet_scope - params[:scope] = 'snippet_titles' if params[:snippets] == 'true' - end end diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb index 2c87c3c890f..9e8075d4bcc 100644 --- a/app/controllers/sessions_controller.rb +++ b/app/controllers/sessions_controller.rb @@ -6,6 +6,8 @@ class SessionsController < Devise::SessionsController include Devise::Controllers::Rememberable include Recaptcha::ClientHelper include Recaptcha::Verify + include RendersLdapServers + include KnownSignIn skip_before_action :check_two_factor_requirement, only: [:destroy] # replaced with :require_no_authentication_without_flash @@ -16,7 +18,6 @@ class SessionsController < Devise::SessionsController if: -> { action_name == 'create' && two_factor_enabled? } prepend_before_action :check_captcha, only: [:create] prepend_before_action :store_redirect_uri, only: [:new] - prepend_before_action :ldap_servers, only: [:new, :create] prepend_before_action :require_no_authentication_without_flash, only: [:new, :create] prepend_before_action :ensure_password_authentication_enabled!, if: -> { action_name == 'create' && password_based_login? } @@ -27,6 +28,7 @@ class SessionsController < Devise::SessionsController before_action :frontend_tracking_data, only: [:new] after_action :log_failed_login, if: :action_new_and_failed_login? + after_action :verify_known_sign_in, only: [:create] helper_method :captcha_enabled?, :captcha_on_login_required? @@ -269,16 +271,6 @@ class SessionsController < Devise::SessionsController Gitlab::Recaptcha.load_configurations! end - def ldap_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? exceeded_failed_login_attempts? || exceeded_anonymous_sessions? end diff --git a/app/controllers/snippets_controller.rb b/app/controllers/snippets_controller.rb index a07baa1a045..425e0458b41 100644 --- a/app/controllers/snippets_controller.rb +++ b/app/controllers/snippets_controller.rb @@ -49,29 +49,22 @@ class SnippetsController < ApplicationController end def create - create_params = snippet_params.merge(spammable_params) + create_params = snippet_params.merge(files: params.delete(:files)) service_response = Snippets::CreateService.new(nil, current_user, create_params).execute @snippet = service_response.payload[:snippet] - repository_operation_error = service_response.error? && !@snippet.persisted? && @snippet.valid? - if repository_operation_error - flash.now[:alert] = service_response.message - - render :new + if service_response.error? && @snippet.errors[:repository].present? + handle_repository_error(:new) else - move_temporary_files if @snippet.valid? && params[:files] - recaptcha_check_with_fallback { render :new } end end def update - update_params = snippet_params.merge(spammable_params) - - service_response = Snippets::UpdateService.new(nil, current_user, update_params).execute(@snippet) + service_response = Snippets::UpdateService.new(nil, current_user, snippet_params).execute(@snippet) @snippet = service_response.payload[:snippet] - check_repository_error + handle_repository_error(:edit) end def show @@ -153,12 +146,6 @@ class SnippetsController < ApplicationController end def snippet_params - params.require(:personal_snippet).permit(:title, :content, :file_name, :private, :visibility_level, :description) - end - - def move_temporary_files - params[:files].each do |file| - FileMover.new(file, from_model: current_user, to_model: @snippet).execute - end + params.require(:personal_snippet).permit(:title, :content, :file_name, :private, :visibility_level, :description).merge(spammable_params) end end diff --git a/app/controllers/user_callouts_controller.rb b/app/controllers/user_callouts_controller.rb index 4ee75218db1..06f422b9d90 100644 --- a/app/controllers/user_callouts_controller.rb +++ b/app/controllers/user_callouts_controller.rb @@ -5,7 +5,7 @@ class UserCalloutsController < ApplicationController callout = ensure_callout if callout.persisted? - callout.update(dismissed_at: Time.now) + callout.update(dismissed_at: Time.current) respond_to do |format| format.json { head :ok } end |