summaryrefslogtreecommitdiff
path: root/app/controllers
diff options
context:
space:
mode:
Diffstat (limited to 'app/controllers')
-rw-r--r--app/controllers/admin/appearances_controller.rb1
-rw-r--r--app/controllers/admin/application_settings_controller.rb4
-rw-r--r--app/controllers/admin/ci/variables_controller.rb48
-rw-r--r--app/controllers/admin/dashboard_controller.rb1
-rw-r--r--app/controllers/admin/logs_controller.rb24
-rw-r--r--app/controllers/admin/sessions_controller.rb1
-rw-r--r--app/controllers/admin/users_controller.rb2
-rw-r--r--app/controllers/application_controller.rb67
-rw-r--r--app/controllers/boards/issues_controller.rb3
-rw-r--r--app/controllers/clusters/applications_controller.rb2
-rw-r--r--app/controllers/clusters/clusters_controller.rb40
-rw-r--r--app/controllers/concerns/boards_actions.rb3
-rw-r--r--app/controllers/concerns/impersonation.rb43
-rw-r--r--app/controllers/concerns/issuable_actions.rb3
-rw-r--r--app/controllers/concerns/issuable_collections_action.rb4
-rw-r--r--app/controllers/concerns/known_sign_in.rb31
-rw-r--r--app/controllers/concerns/members_presentation.rb1
-rw-r--r--app/controllers/concerns/metrics_dashboard.rb29
-rw-r--r--app/controllers/concerns/notes_actions.rb2
-rw-r--r--app/controllers/concerns/preview_markdown.rb2
-rw-r--r--app/controllers/concerns/record_user_last_activity.rb1
-rw-r--r--app/controllers/concerns/renders_ldap_servers.rb19
-rw-r--r--app/controllers/concerns/service_params.rb1
-rw-r--r--app/controllers/concerns/snippets_actions.rb15
-rw-r--r--app/controllers/concerns/spammable_actions.rb2
-rw-r--r--app/controllers/dashboard/projects_controller.rb6
-rw-r--r--app/controllers/dashboard_controller.rb1
-rw-r--r--app/controllers/google_api/authorizations_controller.rb3
-rw-r--r--app/controllers/graphql_controller.rb14
-rw-r--r--app/controllers/groups/group_links_controller.rb5
-rw-r--r--app/controllers/groups/group_members_controller.rb47
-rw-r--r--app/controllers/groups/registry/repositories_controller.rb4
-rw-r--r--app/controllers/groups/settings/repository_controller.rb2
-rw-r--r--app/controllers/groups_controller.rb6
-rw-r--r--app/controllers/help_controller.rb4
-rw-r--r--app/controllers/ide_controller.rb4
-rw-r--r--app/controllers/import/github_controller.rb2
-rw-r--r--app/controllers/import/google_code_controller.rb4
-rw-r--r--app/controllers/jwt_controller.rb11
-rw-r--r--app/controllers/ldap/omniauth_callbacks_controller.rb4
-rw-r--r--app/controllers/omniauth_callbacks_controller.rb11
-rw-r--r--app/controllers/projects/alert_management_controller.rb16
-rw-r--r--app/controllers/projects/artifacts_controller.rb15
-rw-r--r--app/controllers/projects/branches_controller.rb1
-rw-r--r--app/controllers/projects/ci/daily_build_group_report_results_controller.rb77
-rw-r--r--app/controllers/projects/design_management/designs/raw_images_controller.rb30
-rw-r--r--app/controllers/projects/design_management/designs/resized_image_controller.rb46
-rw-r--r--app/controllers/projects/design_management/designs_controller.rb21
-rw-r--r--app/controllers/projects/environments_controller.rb15
-rw-r--r--app/controllers/projects/graphs_controller.rb22
-rw-r--r--app/controllers/projects/import/jira_controller.rb2
-rw-r--r--app/controllers/projects/issues_controller.rb23
-rw-r--r--app/controllers/projects/mattermosts_controller.rb2
-rw-r--r--app/controllers/projects/merge_requests/creations_controller.rb8
-rw-r--r--app/controllers/projects/merge_requests/diffs_controller.rb2
-rw-r--r--app/controllers/projects/merge_requests_controller.rb23
-rw-r--r--app/controllers/projects/pipelines_controller.rb47
-rw-r--r--app/controllers/projects/project_members_controller.rb14
-rw-r--r--app/controllers/projects/refs_controller.rb39
-rw-r--r--app/controllers/projects/registry/repositories_controller.rb3
-rw-r--r--app/controllers/projects/settings/access_tokens_controller.rb71
-rw-r--r--app/controllers/projects/settings/repository_controller.rb2
-rw-r--r--app/controllers/projects/snippets_controller.rb11
-rw-r--r--app/controllers/projects/tree_controller.rb2
-rw-r--r--app/controllers/projects/usage_ping_controller.rb6
-rw-r--r--app/controllers/projects/wikis_controller.rb27
-rw-r--r--app/controllers/projects_controller.rb12
-rw-r--r--app/controllers/registrations_controller.rb3
-rw-r--r--app/controllers/repositories/git_http_controller.rb8
-rw-r--r--app/controllers/search_controller.rb11
-rw-r--r--app/controllers/sessions_controller.rb14
-rw-r--r--app/controllers/snippets_controller.rb25
-rw-r--r--app/controllers/user_callouts_controller.rb2
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