diff options
Diffstat (limited to 'app/controllers')
78 files changed, 483 insertions, 387 deletions
diff --git a/app/controllers/admin/application_settings_controller.rb b/app/controllers/admin/application_settings_controller.rb index b75a7c4a2dd..ec9441c2b9b 100644 --- a/app/controllers/admin/application_settings_controller.rb +++ b/app/controllers/admin/application_settings_controller.rb @@ -13,10 +13,6 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController before_action :disable_query_limiting, only: [:usage_data] - before_action do - push_frontend_feature_flag(:ci_variable_settings_graphql) - end - feature_category :not_owned, [ # rubocop:todo Gitlab/AvoidFeatureCategoryNotOwned :general, :reporting, :metrics_and_profiling, :network, :preferences, :update, :reset_health_check_token @@ -84,7 +80,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController format.json do Gitlab::UsageDataCounters::ServiceUsageDataCounter.count(:download_payload_click) - render json: service_ping_data.to_json + render json: Gitlab::Json.dump(service_ping_data) end end end diff --git a/app/controllers/admin/broadcast_messages_controller.rb b/app/controllers/admin/broadcast_messages_controller.rb index edd85414696..bdf0c6aedb9 100644 --- a/app/controllers/admin/broadcast_messages_controller.rb +++ b/app/controllers/admin/broadcast_messages_controller.rb @@ -3,39 +3,60 @@ class Admin::BroadcastMessagesController < Admin::ApplicationController include BroadcastMessagesHelper - before_action :finder, only: [:edit, :update, :destroy] + before_action :find_broadcast_message, only: [:edit, :update, :destroy] + before_action :find_broadcast_messages, only: [:index, :create] + before_action :push_features, only: [:index, :edit] feature_category :onboarding urgency :low - # rubocop: disable CodeReuse/ActiveRecord def index - push_frontend_feature_flag(:vue_broadcast_messages, current_user) - push_frontend_feature_flag(:role_targeted_broadcast_messages, current_user) - - @broadcast_messages = BroadcastMessage.order(ends_at: :desc).page(params[:page]) - @broadcast_message = BroadcastMessage.new + @broadcast_message = BroadcastMessage.new end - # rubocop: enable CodeReuse/ActiveRecord def edit end def create @broadcast_message = BroadcastMessage.new(broadcast_message_params) + success = @broadcast_message.save - if @broadcast_message.save - redirect_to admin_broadcast_messages_path, notice: _('Broadcast Message was successfully created.') - else - render :index + respond_to do |format| + format.json do + if success + render json: @broadcast_message, status: :ok + else + render json: { errors: @broadcast_message.errors.full_messages }, status: :bad_request + end + end + format.html do + if success + redirect_to admin_broadcast_messages_path, notice: _('Broadcast Message was successfully created.') + else + render :index + end + end end end def update - if @broadcast_message.update(broadcast_message_params) - redirect_to admin_broadcast_messages_path, notice: _('Broadcast Message was successfully updated.') - else - render :edit + success = @broadcast_message.update(broadcast_message_params) + + respond_to do |format| + format.json do + if success + render json: @broadcast_message, status: :ok + else + render json: { errors: @broadcast_message.errors.full_messages }, status: :bad_request + end + end + format.html do + if success + redirect_to admin_broadcast_messages_path, notice: _('Broadcast Message was successfully updated.') + else + render :edit + end + end end end @@ -55,10 +76,14 @@ class Admin::BroadcastMessagesController < Admin::ApplicationController protected - def finder + def find_broadcast_message @broadcast_message = BroadcastMessage.find(params[:id]) end + def find_broadcast_messages + @broadcast_messages = BroadcastMessage.order(ends_at: :desc).page(params[:page]) # rubocop: disable CodeReuse/ActiveRecord + end + def broadcast_message_params params.require(:broadcast_message) .permit(%i( @@ -71,4 +96,9 @@ class Admin::BroadcastMessagesController < Admin::ApplicationController dismissable ), target_access_levels: []).reverse_merge!(target_access_levels: []) end + + def push_features + push_frontend_feature_flag(:vue_broadcast_messages, current_user) + push_frontend_feature_flag(:role_targeted_broadcast_messages, current_user) + end end diff --git a/app/controllers/admin/groups_controller.rb b/app/controllers/admin/groups_controller.rb index f3c4244269d..1395d4bb3b7 100644 --- a/app/controllers/admin/groups_controller.rb +++ b/app/controllers/admin/groups_controller.rb @@ -38,12 +38,9 @@ class Admin::GroupsController < Admin::ApplicationController end def create - @group = Group.new(group_params) - @group.name = @group.path.dup unless @group.name + @group = ::Groups::CreateService.new(current_user, group_params).execute - if @group.save - @group.add_owner(current_user) - @group.create_namespace_settings + if @group.persisted? redirect_to [:admin, @group], notice: _('Group %{group_name} was successfully created.') % { group_name: @group.name } else render "new" diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb index 1a57d271271..2c8b4888d5d 100644 --- a/app/controllers/admin/users_controller.rb +++ b/app/controllers/admin/users_controller.rb @@ -26,6 +26,8 @@ class Admin::UsersController < Admin::ApplicationController end def show + @can_impersonate = can_impersonate_user + @impersonation_error_text = @can_impersonate ? nil : impersonation_error_text end # rubocop: disable CodeReuse/ActiveRecord @@ -47,7 +49,7 @@ class Admin::UsersController < Admin::ApplicationController end def impersonate - if can?(user, :log_in) && !impersonation_in_progress? + if can_impersonate_user session[:impersonator_id] = current_user.id warden.set_user(user, scope: :user) @@ -59,16 +61,7 @@ class Admin::UsersController < Admin::ApplicationController redirect_to root_path else - flash[:alert] = - if impersonation_in_progress? - _("You are already impersonating another user") - elsif user.blocked? - _("You cannot impersonate a blocked user") - elsif user.internal? - _("You cannot impersonate an internal user") - else - _("You cannot impersonate a user who cannot log in") - end + flash[:alert] = impersonation_error_text redirect_to admin_user_path(user) end @@ -378,6 +371,24 @@ class Admin::UsersController < Admin::ApplicationController def log_impersonation_event Gitlab::AppLogger.info(_("User %{current_user_username} has started impersonating %{username}") % { current_user_username: current_user.username, username: user.username }) end + + def can_impersonate_user + can?(user, :log_in) && !user.password_expired? && !impersonation_in_progress? + end + + def impersonation_error_text + if impersonation_in_progress? + _("You are already impersonating another user") + elsif user.blocked? + _("You cannot impersonate a blocked user") + elsif user.password_expired? + _("You cannot impersonate a user with an expired password") + elsif user.internal? + _("You cannot impersonate an internal user") + else + _("You cannot impersonate a user who cannot log in") + end + end end Admin::UsersController.prepend_mod_with('Admin::UsersController') diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 84efb8b0da8..4de6b5de42a 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -13,6 +13,7 @@ class ApplicationController < ActionController::Base include EnforcesTwoFactorAuthentication include WithPerformanceBar include Gitlab::SearchContext::ControllerConcern + include PreferredLanguageSwitcher include SessionlessAuthentication include SessionsHelper include ConfirmEmailWarning @@ -512,7 +513,13 @@ class ApplicationController < ActionController::Base end def set_locale(&block) - Gitlab::I18n.with_user_locale(current_user, &block) + return Gitlab::I18n.with_user_locale(current_user, &block) unless Feature.enabled?(:preferred_language_switcher) + + if current_user + Gitlab::I18n.with_user_locale(current_user, &block) + else + Gitlab::I18n.with_locale(preferred_language, &block) + end end def set_session_storage(&block) diff --git a/app/controllers/concerns/access_tokens_actions.rb b/app/controllers/concerns/access_tokens_actions.rb index 6e43be5594d..fdb08c6572f 100644 --- a/app/controllers/concerns/access_tokens_actions.rb +++ b/app/controllers/concerns/access_tokens_actions.rb @@ -13,6 +13,13 @@ module AccessTokensActions def index @resource_access_token = PersonalAccessToken.new set_index_vars + + respond_to do |format| + format.html + format.json do + render json: @active_access_tokens + end + end end # rubocop:enable Gitlab/ModuleWithInstanceVariables @@ -23,7 +30,7 @@ module AccessTokensActions if token_response.success? @resource_access_token = token_response.payload[:access_token] render json: { new_token: @resource_access_token.token, - active_access_tokens: active_resource_access_tokens }, status: :ok + active_access_tokens: active_access_tokens }, status: :ok else render json: { errors: token_response.errors }, status: :unprocessable_entity end @@ -62,15 +69,10 @@ module AccessTokensActions resource.members.load @scopes = Gitlab::Auth.resource_bot_scopes - @active_resource_access_tokens = active_resource_access_tokens + @active_access_tokens = active_access_tokens end # rubocop:enable Gitlab/ModuleWithInstanceVariables - def active_resource_access_tokens - tokens = finder(state: 'active', sort: 'expires_at_asc_id_desc').execute.preload_users - represent(tokens) - end - def finder(options = {}) PersonalAccessTokensFinder.new({ user: bot_users, impersonation: false }.merge(options)) end diff --git a/app/controllers/concerns/authenticates_with_two_factor.rb b/app/controllers/concerns/authenticates_with_two_factor.rb index fbaa754124c..817f82085e6 100644 --- a/app/controllers/concerns/authenticates_with_two_factor.rb +++ b/app/controllers/concerns/authenticates_with_two_factor.rb @@ -137,7 +137,7 @@ module AuthenticatesWithTwoFactor session[:credentialRequestOptions] = get_options session[:challenge] = get_options.challenge - gon.push(webauthn: { options: get_options.to_json }) + gon.push(webauthn: { options: Gitlab::Json.dump(get_options) }) end end # rubocop: enable CodeReuse/ActiveRecord diff --git a/app/controllers/concerns/integrations/params.rb b/app/controllers/concerns/integrations/params.rb index c3ad9d3dff3..30de4a86bec 100644 --- a/app/controllers/concerns/integrations/params.rb +++ b/app/controllers/concerns/integrations/params.rb @@ -88,6 +88,10 @@ module Integrations param_values = return_value[:integration] if param_values.is_a?(ActionController::Parameters) + if action_name == 'update' && integration.chat? && param_values['webhook'] == BaseChatNotification::SECRET_MASK + param_values.delete('webhook') + end + integration.secret_fields.each do |param| param_values.delete(param) if param_values[param].blank? end diff --git a/app/controllers/concerns/issuable_actions.rb b/app/controllers/concerns/issuable_actions.rb index 7c3401a7e90..bea184e44b9 100644 --- a/app/controllers/concerns/issuable_actions.rb +++ b/app/controllers/concerns/issuable_actions.rb @@ -142,43 +142,21 @@ module IssuableActions end end - # rubocop:disable CodeReuse/ActiveRecord def discussions - notes = NotesFinder.new(current_user, finder_params_for_issuable).execute - .inc_relations_for_view - .includes(:noteable) - .fresh + finder = Issuable::DiscussionsListService.new(current_user, issuable, finder_params_for_issuable) + discussion_notes = finder.execute - if paginated_discussions - paginated_discussions_by_type = paginated_discussions.records.group_by(&:table_name) + response.headers['X-Next-Page-Cursor'] = finder.paginator.cursor_for_next_page if finder.paginator.present? && finder.paginator.has_next_page? - notes = if paginated_discussions_by_type['notes'].present? - notes.with_discussion_ids(paginated_discussions_by_type['notes'].map(&:discussion_id)) - else - notes.none - end - - response.headers['X-Next-Page-Cursor'] = paginated_discussions.cursor_for_next_page if paginated_discussions.has_next_page? - end - - if notes_filter != UserPreference::NOTES_FILTERS[:only_comments] - notes = ResourceEvents::MergeIntoNotesService.new(issuable, current_user, paginated_notes: paginated_discussions_by_type).execute(notes) - end - - notes = prepare_notes_for_rendering(notes) - notes = notes.select { |n| n.readable_by?(current_user) } - - discussions = Discussion.build_collection(notes, issuable) - - if issuable.is_a?(MergeRequest) - render_mr_discussions(discussions, discussion_serializer, discussion_cache_context) - elsif issuable.is_a?(Issue) - render json: discussion_serializer.represent(discussions, context: self) if stale?(etag: [discussion_cache_context, discussions]) + case issuable + when MergeRequest + render_mr_discussions(discussion_notes, discussion_serializer, discussion_cache_context) + when Issue + render json: discussion_serializer.represent(discussion_notes, context: self) if stale?(etag: [discussion_cache_context, discussion_notes]) else - render json: discussion_serializer.represent(discussions, context: self) + render json: discussion_serializer.represent(discussion_notes, context: self) end end - # rubocop:enable CodeReuse/ActiveRecord private @@ -199,17 +177,6 @@ module IssuableActions context: self) end - def paginated_discussions - return if params[:per_page].blank? - return if issuable.instance_of?(MergeRequest) && Feature.disabled?(:paginated_mr_discussions, project) - - strong_memoize(:paginated_discussions) do - issuable - .discussion_root_note_ids(notes_filter: notes_filter) - .keyset_paginate(cursor: params[:cursor], per_page: params[:per_page].to_i) - end - end - def notes_filter strong_memoize(:notes_filter) do notes_filter_param = params[:notes_filter]&.to_i @@ -325,9 +292,10 @@ module IssuableActions # rubocop:disable Gitlab/ModuleWithInstanceVariables def finder_params_for_issuable { - target: @issuable, - notes_filter: notes_filter - }.tap { |new_params| new_params[:project] = project if respond_to?(:project, true) } + notes_filter: notes_filter, + cursor: params[:cursor], + per_page: params[:per_page] + } end # rubocop:enable Gitlab/ModuleWithInstanceVariables end diff --git a/app/controllers/concerns/issuable_collections_action.rb b/app/controllers/concerns/issuable_collections_action.rb index e03d1de7bf9..7beb86b51fd 100644 --- a/app/controllers/concerns/issuable_collections_action.rb +++ b/app/controllers/concerns/issuable_collections_action.rb @@ -60,7 +60,6 @@ module IssuableCollectionsAction def finder_options issue_types = Issue::TYPES_FOR_LIST - issue_types = issue_types.excluding('task') unless Feature.enabled?(:work_items) super.merge( non_archived: true, diff --git a/app/controllers/concerns/preferred_language_switcher.rb b/app/controllers/concerns/preferred_language_switcher.rb new file mode 100644 index 00000000000..9711e57cf7a --- /dev/null +++ b/app/controllers/concerns/preferred_language_switcher.rb @@ -0,0 +1,18 @@ +# frozen_string_literal: true + +module PreferredLanguageSwitcher + extend ActiveSupport::Concern + + private + + def init_preferred_language + return unless Feature.enabled?(:preferred_language_switcher) + + cookies[:preferred_language] = preferred_language + end + + def preferred_language + cookies[:preferred_language].presence_in(Gitlab::I18n.available_locales) || + Gitlab::CurrentSettings.default_preferred_language + end +end diff --git a/app/controllers/concerns/preview_markdown.rb b/app/controllers/concerns/preview_markdown.rb index 79b3fa28660..7af114313a1 100644 --- a/app/controllers/concerns/preview_markdown.rb +++ b/app/controllers/concerns/preview_markdown.rb @@ -41,7 +41,7 @@ module PreviewMarkdown case controller_name when 'wikis' then { pipeline: :wiki, wiki: wiki, page_slug: params[:id] } when 'snippets' then { skip_project_check: true } - when 'groups' then { group: group } + when 'groups' then { group: group, issuable_reference_expansion_enabled: true } when 'projects' then projects_filter_params when 'timeline_events' then timeline_events_filter_params else {} diff --git a/app/controllers/concerns/product_analytics_tracking.rb b/app/controllers/concerns/product_analytics_tracking.rb index 4f96cc5c895..dfa159ccfd7 100644 --- a/app/controllers/concerns/product_analytics_tracking.rb +++ b/app/controllers/concerns/product_analytics_tracking.rb @@ -6,6 +6,8 @@ module ProductAnalyticsTracking extend ActiveSupport::Concern class_methods do + # TODO: Remove once all the events are migrated to #track_custom_event + # during https://gitlab.com/groups/gitlab-org/-/epics/8641 def track_event(*controller_actions, name:, conditions: nil, destinations: [:redis_hll], &block) custom_conditions = [:trackable_html_request?, *conditions] diff --git a/app/controllers/concerns/render_access_tokens.rb b/app/controllers/concerns/render_access_tokens.rb new file mode 100644 index 00000000000..b0bbad7e37f --- /dev/null +++ b/app/controllers/concerns/render_access_tokens.rb @@ -0,0 +1,31 @@ +# frozen_string_literal: true +module RenderAccessTokens + extend ActiveSupport::Concern + + def active_access_tokens + tokens = finder(state: 'active', sort: 'expires_at_asc_id_desc').execute.preload_users + + if Feature.enabled?('access_token_pagination') + tokens = tokens.page(page) + add_pagination_headers(tokens) + end + + represent(tokens) + end + + def add_pagination_headers(relation) + Gitlab::Pagination::OffsetHeaderBuilder.new( + request_context: self, + per_page: relation.limit_value, + page: relation.current_page, + next_page: relation.next_page, + prev_page: relation.prev_page, + total: relation.total_count, + params: params.permit(:page, :per_page) + ).execute + end + + def page + (params[:page] || 1).to_i + end +end diff --git a/app/controllers/concerns/send_file_upload.rb b/app/controllers/concerns/send_file_upload.rb index c8369c465b8..c91edb74d6b 100644 --- a/app/controllers/concerns/send_file_upload.rb +++ b/app/controllers/concerns/send_file_upload.rb @@ -30,7 +30,17 @@ module SendFileUpload headers.store(*Gitlab::Workhorse.send_url(file_upload.url(**redirect_params))) head :ok else - redirect_to file_upload.url(**redirect_params) + redirect_to cdn_fronted_url(file_upload, redirect_params) + end + end + + def cdn_fronted_url(file, redirect_params) + if file.respond_to?(:cdn_enabled_url) + result = file.cdn_enabled_url(request.remote_ip, redirect_params[:query]) + Gitlab::ApplicationContext.push(artifact_used_cdn: result.used_cdn) + result.url + else + file.url(**redirect_params) end end diff --git a/app/controllers/concerns/verifies_with_email.rb b/app/controllers/concerns/verifies_with_email.rb index 782cae53c3f..ac1475597ff 100644 --- a/app/controllers/concerns/verifies_with_email.rb +++ b/app/controllers/concerns/verifies_with_email.rb @@ -8,7 +8,7 @@ module VerifiesWithEmail include ActionView::Helpers::DateHelper included do - prepend_before_action :verify_with_email, only: :create, unless: -> { two_factor_enabled? } + prepend_before_action :verify_with_email, only: :create, unless: -> { skip_verify_with_email? } skip_before_action :required_signup_info, only: :successful_verification end @@ -55,6 +55,10 @@ module VerifiesWithEmail private + def skip_verify_with_email? + two_factor_enabled? || Gitlab::Qa.request?(request.user_agent) + end + def find_verification_user return unless session[:verification_user_id] @@ -84,10 +88,7 @@ module VerifiesWithEmail def send_verification_instructions_email(user, token) return unless user.can?(:receive_notifications) - Notify.verification_instructions_email( - user.id, - token: token, - expires_in: Users::EmailVerification::ValidateTokenService::TOKEN_VALID_FOR_MINUTES).deliver_later + Notify.verification_instructions_email(user.email, token: token).deliver_later log_verification(user, :instructions_sent) end diff --git a/app/controllers/concerns/web_hooks/hook_actions.rb b/app/controllers/concerns/web_hooks/hook_actions.rb index ea11f13c7ef..75065ef9d24 100644 --- a/app/controllers/concerns/web_hooks/hook_actions.rb +++ b/app/controllers/concerns/web_hooks/hook_actions.rb @@ -20,7 +20,7 @@ module WebHooks unless hook.valid? self.hooks = relation.select(&:persisted?) - flash[:alert] = hook.errors.full_messages.join.html_safe + flash[:alert] = hook.errors.full_messages.to_sentence.html_safe end redirect_to action: :index @@ -53,6 +53,8 @@ module WebHooks ps = params.require(:hook).permit(*permitted).to_h + ps.delete(:token) if action_name == 'update' && ps[:token] == WebHook::SECRET_MASK + ps[:url_variables] = ps[:url_variables].to_h { [_1[:key], _1[:value].presence] } if ps.key?(:url_variables) if action_name == 'update' && ps.key?(:url_variables) @@ -64,7 +66,9 @@ module WebHooks end def hook_param_names - %i[enable_ssl_verification token url push_events_branch_filter] + param_names = %i[enable_ssl_verification token url push_events_branch_filter] + param_names.push(:branch_filter_strategy) if Feature.enabled?(:enhanced_webhook_support_regex) + param_names end def destroy_hook(hook) diff --git a/app/controllers/concerns/web_hooks/hook_execution_notice.rb b/app/controllers/concerns/web_hooks/hook_execution_notice.rb index d651313b30d..69b140723e3 100644 --- a/app/controllers/concerns/web_hooks/hook_execution_notice.rb +++ b/app/controllers/concerns/web_hooks/hook_execution_notice.rb @@ -5,7 +5,7 @@ module WebHooks private def set_hook_execution_notice(result) - http_status = result[:http_status] + http_status = result.payload[:http_status] message = result[:message] if http_status && http_status >= 200 && http_status < 400 diff --git a/app/controllers/confirmations_controller.rb b/app/controllers/confirmations_controller.rb index 713231cbc6f..6dd4d72bbc7 100644 --- a/app/controllers/confirmations_controller.rb +++ b/app/controllers/confirmations_controller.rb @@ -6,6 +6,7 @@ class ConfirmationsController < Devise::ConfirmationsController include OneTrustCSP include GoogleAnalyticsCSP + skip_before_action :required_signup_info prepend_before_action :check_recaptcha, only: :create before_action :load_recaptcha, only: :new diff --git a/app/controllers/dashboard/projects_controller.rb b/app/controllers/dashboard/projects_controller.rb index 0e4592259d8..89d362c88a4 100644 --- a/app/controllers/dashboard/projects_controller.rb +++ b/app/controllers/dashboard/projects_controller.rb @@ -66,11 +66,10 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController end def load_projects(finder_params) - @total_user_projects_count = ProjectsFinder.new(params: { non_public: true, without_deleted: true, not_aimed_for_deletion: true }, current_user: current_user).execute - @total_starred_projects_count = ProjectsFinder.new(params: { starred: true, without_deleted: true, not_aimed_for_deletion: true }, current_user: current_user).execute + @total_user_projects_count = ProjectsFinder.new(params: { non_public: true, not_aimed_for_deletion: true }, current_user: current_user).execute + @total_starred_projects_count = ProjectsFinder.new(params: { starred: true, not_aimed_for_deletion: true }, current_user: current_user).execute finder_params[:use_cte] = true if use_cte_for_finder? - finder_params[:without_deleted] = true projects = ProjectsFinder.new(params: finder_params, current_user: current_user).execute @@ -93,7 +92,7 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController def load_events projects = ProjectsFinder - .new(params: params.merge(non_public: true, without_deleted: true), current_user: current_user) + .new(params: params.merge(non_public: true, not_aimed_for_deletion: true), current_user: current_user) .execute @events = EventCollection diff --git a/app/controllers/explore/groups_controller.rb b/app/controllers/explore/groups_controller.rb index 97791b43d41..ac355b861b3 100644 --- a/app/controllers/explore/groups_controller.rb +++ b/app/controllers/explore/groups_controller.rb @@ -7,6 +7,8 @@ class Explore::GroupsController < Explore::ApplicationController urgency :low def index - render_group_tree GroupsFinder.new(current_user).execute + user = Feature.enabled?(:generic_explore_groups, current_user, type: :experiment) ? nil : current_user + + render_group_tree GroupsFinder.new(user).execute end end diff --git a/app/controllers/graphql_controller.rb b/app/controllers/graphql_controller.rb index 67eeb43d5a2..5ffd525c170 100644 --- a/app/controllers/graphql_controller.rb +++ b/app/controllers/graphql_controller.rb @@ -190,7 +190,8 @@ class GraphqlController < ApplicationController current_user: current_user, is_sessionless_user: api_user, request: request, - scope_validator: ::Gitlab::Auth::ScopeValidator.new(api_user, request_authenticator) + scope_validator: ::Gitlab::Auth::ScopeValidator.new(api_user, request_authenticator), + remove_deprecated: Gitlab::Utils.to_boolean(params[:remove_deprecated], default: false) } end diff --git a/app/controllers/groups/boards_controller.rb b/app/controllers/groups/boards_controller.rb index 14b70df0feb..e1ba86220c7 100644 --- a/app/controllers/groups/boards_controller.rb +++ b/app/controllers/groups/boards_controller.rb @@ -7,7 +7,7 @@ class Groups::BoardsController < Groups::ApplicationController before_action do push_frontend_feature_flag(:board_multi_select, group) - push_frontend_feature_flag(:realtime_labels, group) + push_frontend_feature_flag(:apollo_boards, group) experiment(:prominent_create_board_btn, subject: current_user) do |e| e.control {} e.candidate {} diff --git a/app/controllers/groups/dependency_proxy/application_controller.rb b/app/controllers/groups/dependency_proxy/application_controller.rb index f7337a3cdb1..300a82eed78 100644 --- a/app/controllers/groups/dependency_proxy/application_controller.rb +++ b/app/controllers/groups/dependency_proxy/application_controller.rb @@ -21,10 +21,11 @@ module Groups user_or_deploy_token = ::DependencyProxy::AuthTokenService.user_or_deploy_token_from_jwt(token) - if user_or_deploy_token.is_a?(User) + case user_or_deploy_token + when User @authentication_result = Gitlab::Auth::Result.new(user_or_deploy_token, nil, :user, []) sign_in(user_or_deploy_token) - elsif user_or_deploy_token.is_a?(DeployToken) + when DeployToken @authentication_result = Gitlab::Auth::Result.new(user_or_deploy_token, nil, :deploy_token, []) end end diff --git a/app/controllers/groups/observability_controller.rb b/app/controllers/groups/observability_controller.rb index 5b6503494c4..4b1f2b582ce 100644 --- a/app/controllers/groups/observability_controller.rb +++ b/app/controllers/groups/observability_controller.rb @@ -9,35 +9,41 @@ module Groups default_frame_src = p.directives['frame-src'] || p.directives['default-src'] # When ObservabilityUI is not authenticated, it needs to be able to redirect to the GL sign-in page, hence 'self' - frame_src_values = Array.wrap(default_frame_src) | [ObservabilityController.observability_url, "'self'"] + frame_src_values = Array.wrap(default_frame_src) | [observability_url, "'self'"] p.frame_src(*frame_src_values) end - before_action :check_observability_allowed, only: :index + before_action :check_observability_allowed - def index - # Format: https://observe.gitlab.com/-/GROUP_ID - @observability_iframe_src = "#{ObservabilityController.observability_url}/-/#{@group.id}" + def dashboards + render_observability + end - # Uncomment below for testing with local GDK - # @observability_iframe_src = "#{ObservabilityController.observability_url}/9970?groupId=14485840" + def manage + render_observability + end - render layout: 'group', locals: { base_layout: 'layouts/fullscreen' } + def explore + render_observability end private + def render_observability + render 'observability', layout: 'group', locals: { base_layout: 'layouts/fullscreen' } + end + def self.observability_url - return ENV['OVERRIDE_OBSERVABILITY_URL'] if ENV['OVERRIDE_OBSERVABILITY_URL'] - # TODO Make observability URL configurable https://gitlab.com/gitlab-org/opstrace/opstrace-ui/-/issues/80 - return "https://staging.observe.gitlab.com" if Gitlab.staging? + Gitlab::Observability.observability_url + end - "https://observe.gitlab.com" + def observability_url + self.class.observability_url end def check_observability_allowed - return render_404 unless self.class.observability_url.present? + return render_404 unless observability_url.present? render_404 unless can?(current_user, :read_observability, @group) end diff --git a/app/controllers/groups/registry/repositories_controller.rb b/app/controllers/groups/registry/repositories_controller.rb index bb2d08e487a..cb7bf001918 100644 --- a/app/controllers/groups/registry/repositories_controller.rb +++ b/app/controllers/groups/registry/repositories_controller.rb @@ -8,10 +8,6 @@ module Groups before_action :verify_container_registry_enabled! before_action :authorize_read_container_image! - before_action do - push_frontend_feature_flag(:container_registry_show_shortened_path, group) - end - feature_category :container_registry urgency :low diff --git a/app/controllers/groups/settings/access_tokens_controller.rb b/app/controllers/groups/settings/access_tokens_controller.rb index f01b2b779e3..d86ddcfe2d0 100644 --- a/app/controllers/groups/settings/access_tokens_controller.rb +++ b/app/controllers/groups/settings/access_tokens_controller.rb @@ -3,6 +3,7 @@ module Groups module Settings class AccessTokensController < Groups::ApplicationController + include RenderAccessTokens include AccessTokensActions layout 'group_settings' diff --git a/app/controllers/groups/settings/ci_cd_controller.rb b/app/controllers/groups/settings/ci_cd_controller.rb index e164a834519..b1afac1f1c7 100644 --- a/app/controllers/groups/settings/ci_cd_controller.rb +++ b/app/controllers/groups/settings/ci_cd_controller.rb @@ -10,9 +10,6 @@ module Groups before_action :define_variables, only: [:show] before_action :push_licensed_features, only: [:show] before_action :assign_variables_to_gon, only: [:show] - before_action do - push_frontend_feature_flag(:ci_variable_settings_graphql, @group) - end feature_category :continuous_integration urgency :low diff --git a/app/controllers/groups/settings/packages_and_registries_controller.rb b/app/controllers/groups/settings/packages_and_registries_controller.rb index 411b8577c3f..ec4a0b312ee 100644 --- a/app/controllers/groups/settings/packages_and_registries_controller.rb +++ b/app/controllers/groups/settings/packages_and_registries_controller.rb @@ -7,6 +7,10 @@ module Groups before_action :authorize_admin_group! before_action :verify_packages_enabled! + before_action do + push_frontend_feature_flag(:maven_central_request_forwarding, group) + end + feature_category :package_registry urgency :low diff --git a/app/controllers/groups/settings/repository_controller.rb b/app/controllers/groups/settings/repository_controller.rb index cb62ea2a543..ecd5d814fb6 100644 --- a/app/controllers/groups/settings/repository_controller.rb +++ b/app/controllers/groups/settings/repository_controller.rb @@ -8,9 +8,6 @@ module Groups before_action :authorize_create_deploy_token!, only: :create_deploy_token before_action :authorize_access!, only: :show before_action :define_deploy_token_variables, if: -> { can?(current_user, :create_deploy_token, @group) } - before_action do - push_frontend_feature_flag(:ajax_new_deploy_token, @group) - end feature_category :continuous_delivery urgency :low diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb index 269342a6c22..3f516c24a69 100644 --- a/app/controllers/groups_controller.rb +++ b/app/controllers/groups_controller.rb @@ -35,6 +35,7 @@ class GroupsController < Groups::ApplicationController before_action :track_experiment_event, only: [:new] before_action only: :issues do + push_frontend_feature_flag(:or_issuable_queries, group) push_force_frontend_feature_flag(:work_items, group.work_items_feature_flag_enabled?) end @@ -111,7 +112,7 @@ class GroupsController < Groups::ApplicationController def details respond_to do |format| format.html do - render_details_html + redirect_to group_path(group) end format.atom do @@ -235,10 +236,6 @@ class GroupsController < Groups::ApplicationController render 'groups/show', locals: { trial: params[:trial] } end - def render_details_html - render 'groups/show' - end - def render_details_view_atom load_events render layout: 'xml', template: 'groups/show' diff --git a/app/controllers/jira_connect/application_controller.rb b/app/controllers/jira_connect/application_controller.rb index e26d69314cd..b9f0ea795e1 100644 --- a/app/controllers/jira_connect/application_controller.rb +++ b/app/controllers/jira_connect/application_controller.rb @@ -3,6 +3,11 @@ class JiraConnect::ApplicationController < ApplicationController include Gitlab::Utils::StrongMemoize + CORS_ALLOWED_METHODS = { + '/-/jira_connect/oauth_application_id' => %i[GET OPTIONS], + '/-/jira_connect/subscriptions/*' => %i[DELETE OPTIONS] + }.freeze + skip_before_action :authenticate_user! skip_before_action :verify_authenticity_token before_action :verify_atlassian_jwt! @@ -60,4 +65,25 @@ class JiraConnect::ApplicationController < ApplicationController def auth_token params[:jwt] || request.headers['Authorization']&.split(' ', 2)&.last end + + def cors_allowed_methods + CORS_ALLOWED_METHODS[resource] + end + + def resource + request.path.gsub(%r{/\d+$}, '/*') + end + + def set_cors_headers + return unless allow_cors_request? + + response.set_header('Access-Control-Allow-Origin', Gitlab::CurrentSettings.jira_connect_proxy_url) + response.set_header('Access-Control-Allow-Methods', cors_allowed_methods.join(', ')) + end + + def allow_cors_request? + return false if cors_allowed_methods.nil? + + !Gitlab.com? && Gitlab::CurrentSettings.jira_connect_proxy_url.present? + end end diff --git a/app/controllers/jira_connect/cors_preflight_checks_controller.rb b/app/controllers/jira_connect/cors_preflight_checks_controller.rb new file mode 100644 index 00000000000..3f30c1e04df --- /dev/null +++ b/app/controllers/jira_connect/cors_preflight_checks_controller.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true + +module JiraConnect + class CorsPreflightChecksController < ApplicationController + feature_category :integrations + + skip_before_action :verify_atlassian_jwt! + before_action :set_cors_headers + + def index + return render_404 unless allow_cors_request? + + render plain: '', content_type: 'text/plain' + end + end +end diff --git a/app/controllers/jira_connect/oauth_application_ids_controller.rb b/app/controllers/jira_connect/oauth_application_ids_controller.rb index a84b47f4c8b..3e788e2282e 100644 --- a/app/controllers/jira_connect/oauth_application_ids_controller.rb +++ b/app/controllers/jira_connect/oauth_application_ids_controller.rb @@ -1,11 +1,11 @@ # frozen_string_literal: true module JiraConnect - class OauthApplicationIdsController < ::ApplicationController + class OauthApplicationIdsController < ApplicationController feature_category :integrations - skip_before_action :authenticate_user! - skip_before_action :verify_authenticity_token + skip_before_action :verify_atlassian_jwt! + before_action :set_cors_headers def show if show_application_id? diff --git a/app/controllers/jira_connect/subscriptions_controller.rb b/app/controllers/jira_connect/subscriptions_controller.rb index 9305f46c39e..9a732cadd94 100644 --- a/app/controllers/jira_connect/subscriptions_controller.rb +++ b/app/controllers/jira_connect/subscriptions_controller.rb @@ -27,6 +27,7 @@ class JiraConnect::SubscriptionsController < JiraConnect::ApplicationController before_action :verify_qsh_claim!, only: :index before_action :allow_self_managed_content_security_policy, only: :index before_action :authenticate_user!, only: :create + before_action :set_cors_headers def index @subscriptions = current_jira_installation.subscriptions.preload_namespace_route @@ -64,7 +65,7 @@ class JiraConnect::SubscriptionsController < JiraConnect::ApplicationController private def allow_self_managed_content_security_policy - return unless Feature.enabled?(:jira_connect_oauth_self_managed) + return unless Feature.enabled?(:jira_connect_oauth_self_managed_setting) return unless current_jira_installation.instance_url? @@ -83,7 +84,8 @@ class JiraConnect::SubscriptionsController < JiraConnect::ApplicationController def allowed_instance_connect_src [ Gitlab::Utils.append_path(current_jira_installation.instance_url, '/-/jira_connect/'), - Gitlab::Utils.append_path(current_jira_installation.instance_url, '/api/') + Gitlab::Utils.append_path(current_jira_installation.instance_url, '/api/'), + Gitlab::Utils.append_path(current_jira_installation.instance_url, '/oauth/token') ] end end diff --git a/app/controllers/oauth/authorizations_controller.rb b/app/controllers/oauth/authorizations_controller.rb index bf8b61db2e5..43bf895ea76 100644 --- a/app/controllers/oauth/authorizations_controller.rb +++ b/app/controllers/oauth/authorizations_controller.rb @@ -4,7 +4,7 @@ class Oauth::AuthorizationsController < Doorkeeper::AuthorizationsController include InitializesCurrentUserMode include Gitlab::Utils::StrongMemoize - before_action :verify_confirmed_email! + before_action :verify_confirmed_email!, :verify_admin_allowed! layout 'profile' @@ -97,4 +97,19 @@ class Oauth::AuthorizationsController < Doorkeeper::AuthorizationsController pre_auth.error = :unconfirmed_email render "doorkeeper/authorizations/error" end + + def verify_admin_allowed! + render "doorkeeper/authorizations/forbidden" if disallow_connect? + end + + def disallow_connect? + # we're disabling Cop/UserAdmin as OAuth tokens don't seem to respect admin mode + current_user&.admin? && Gitlab::CurrentSettings.disable_admin_oauth_scopes && dangerous_scopes? # rubocop:disable Cop/UserAdmin + end + + def dangerous_scopes? + doorkeeper_application&.includes_scope?(*::Gitlab::Auth::API_SCOPE, *::Gitlab::Auth::READ_API_SCOPE, + *::Gitlab::Auth::ADMIN_SCOPES, *::Gitlab::Auth::REPOSITORY_SCOPES, + *::Gitlab::Auth::REGISTRY_SCOPES) && !doorkeeper_application&.trusted? + end end diff --git a/app/controllers/passwords_controller.rb b/app/controllers/passwords_controller.rb index ead5d7c9026..1216353be36 100644 --- a/app/controllers/passwords_controller.rb +++ b/app/controllers/passwords_controller.rb @@ -2,6 +2,7 @@ class PasswordsController < Devise::PasswordsController include GitlabRecaptcha + include Gitlab::Tracking::Helpers::WeakPasswordErrorEvent skip_before_action :require_no_authentication, only: [:edit, :update] @@ -41,6 +42,8 @@ class PasswordsController < Devise::PasswordsController resource.password_automatically_set = false resource.password_expires_at = nil resource.save(validate: false) if resource.changed? + else + track_weak_password_error(@user, self.class.name, 'create') end end end diff --git a/app/controllers/profiles/passwords_controller.rb b/app/controllers/profiles/passwords_controller.rb index 5eb0f80ddc9..738c41207d5 100644 --- a/app/controllers/profiles/passwords_controller.rb +++ b/app/controllers/profiles/passwords_controller.rb @@ -1,6 +1,8 @@ # frozen_string_literal: true class Profiles::PasswordsController < Profiles::ApplicationController + include Gitlab::Tracking::Helpers::WeakPasswordErrorEvent + skip_before_action :check_password_expiration, only: [:new, :create] skip_before_action :check_two_factor_requirement, only: [:new, :create] @@ -27,6 +29,7 @@ class Profiles::PasswordsController < Profiles::ApplicationController redirect_to root_path, notice: _('Password successfully changed') else + track_weak_password_error(@user, self.class.name, 'create') render :new end end @@ -48,6 +51,7 @@ class Profiles::PasswordsController < Profiles::ApplicationController flash[:notice] = _('Password was successfully updated. Please sign in again.') redirect_to new_user_session_path else + track_weak_password_error(@user, self.class.name, 'update') @user.reset render 'edit' end @@ -94,3 +98,5 @@ class Profiles::PasswordsController < Profiles::ApplicationController } end end + +Profiles::PasswordsController.prepend_mod diff --git a/app/controllers/profiles/personal_access_tokens_controller.rb b/app/controllers/profiles/personal_access_tokens_controller.rb index 4cf26d3e1e2..1663aa61f62 100644 --- a/app/controllers/profiles/personal_access_tokens_controller.rb +++ b/app/controllers/profiles/personal_access_tokens_controller.rb @@ -1,6 +1,8 @@ # frozen_string_literal: true class Profiles::PersonalAccessTokensController < Profiles::ApplicationController + include RenderAccessTokens + feature_category :authentication_and_authorization before_action :check_personal_access_tokens_enabled @@ -16,7 +18,7 @@ class Profiles::PersonalAccessTokensController < Profiles::ApplicationController respond_to do |format| format.html format.json do - render json: @active_personal_access_tokens + render json: @active_access_tokens end end end @@ -30,7 +32,7 @@ class Profiles::PersonalAccessTokensController < Profiles::ApplicationController if result.success? render json: { new_token: @personal_access_token.token, - active_access_tokens: active_personal_access_tokens }, status: :ok + active_access_tokens: active_access_tokens }, status: :ok else render json: { errors: result.errors }, status: :unprocessable_entity end @@ -56,36 +58,13 @@ class Profiles::PersonalAccessTokensController < Profiles::ApplicationController def set_index_vars @scopes = Gitlab::Auth.available_scopes_for(current_user) - @active_personal_access_tokens = active_personal_access_tokens + @active_access_tokens = active_access_tokens end - def active_personal_access_tokens - tokens = finder(state: 'active', sort: 'expires_at_asc_id_desc').execute - - if Feature.enabled?('access_token_pagination') - tokens = tokens.page(page) - add_pagination_headers(tokens) - end - + def represent(tokens) ::PersonalAccessTokenSerializer.new.represent(tokens) end - def add_pagination_headers(relation) - Gitlab::Pagination::OffsetHeaderBuilder.new( - request_context: self, - per_page: relation.limit_value, - page: relation.current_page, - next_page: relation.next_page, - prev_page: relation.prev_page, - total: relation.total_count, - params: params.permit(:page) - ).execute - end - - def page - (params[:page] || 1).to_i - end - def check_personal_access_tokens_enabled render_404 if Gitlab::CurrentSettings.personal_access_tokens_disabled? end diff --git a/app/controllers/projects/alerting/notifications_controller.rb b/app/controllers/projects/alerting/notifications_controller.rb index f3283c88740..89e8a261288 100644 --- a/app/controllers/projects/alerting/notifications_controller.rb +++ b/app/controllers/projects/alerting/notifications_controller.rb @@ -18,8 +18,9 @@ module Projects def create token = extract_alert_manager_token(request) result = notify_service.execute(token, integration) + has_something_to_return = result.success? && result.http_status != :created - if result.success? + if has_something_to_return render json: AlertManagement::AlertSerializer.new.represent(result.payload[:alerts]), code: result.http_status else head result.http_status diff --git a/app/controllers/projects/application_controller.rb b/app/controllers/projects/application_controller.rb index 2256471047d..25b83aed78a 100644 --- a/app/controllers/projects/application_controller.rb +++ b/app/controllers/projects/application_controller.rb @@ -38,9 +38,9 @@ class Projects::ApplicationController < ApplicationController if build.debug_mode? access_denied!( _('You must have developer or higher permissions in the associated project to view job logs when debug trace ' \ - "is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline " \ - 'configuration or CI/CD settings. If you need to view this job log, a project maintainer or owner must add ' \ - 'you to the project with developer permissions or higher.') + "is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' and 'CI_DEBUG_SERVICES' variables to 'false' " \ + 'in your pipeline configuration or CI/CD settings. If you must view this job log, a project maintainer ' \ + 'or owner must add you to the project with developer permissions or higher.') ) else access_denied!(_('The current user is not authorized to access the job log.')) diff --git a/app/controllers/projects/artifacts_controller.rb b/app/controllers/projects/artifacts_controller.rb index 40e89a06b46..c3dcde38d09 100644 --- a/app/controllers/projects/artifacts_controller.rb +++ b/app/controllers/projects/artifacts_controller.rb @@ -4,6 +4,7 @@ class Projects::ArtifactsController < Projects::ApplicationController include ExtractsPath include RendersBlob include SendFileUpload + include Gitlab::Ci::Artifacts::Logger urgency :low, [:browse, :file, :latest_succeeded] @@ -26,12 +27,6 @@ class Projects::ArtifactsController < Projects::ApplicationController # It should be removed only after resolving the underlying performance # issues: https://gitlab.com/gitlab-org/gitlab/issues/32281 return head :no_content unless Feature.enabled?(:artifacts_management_page, @project) - - finder = Ci::JobArtifactsFinder.new(@project, artifacts_params) - all_artifacts = finder.execute - - @artifacts = all_artifacts.page(params[:page]).per(MAX_PER_PAGE) - @total_size = all_artifacts.total_size end def destroy @@ -47,6 +42,7 @@ class Projects::ArtifactsController < Projects::ApplicationController def download return render_404 unless artifacts_file + log_artifacts_filesize(artifacts_file.model) send_upload(artifacts_file, attachment: artifacts_file.filename, proxy: params[:proxy]) end diff --git a/app/controllers/projects/boards_controller.rb b/app/controllers/projects/boards_controller.rb index 6a6701ead15..84872d1e978 100644 --- a/app/controllers/projects/boards_controller.rb +++ b/app/controllers/projects/boards_controller.rb @@ -7,7 +7,7 @@ class Projects::BoardsController < Projects::ApplicationController before_action :check_issues_available! before_action do push_frontend_feature_flag(:board_multi_select, project) - push_frontend_feature_flag(:realtime_labels, project&.group) + push_frontend_feature_flag(:apollo_boards, project) experiment(:prominent_create_board_btn, subject: current_user) do |e| e.control {} e.candidate {} diff --git a/app/controllers/projects/commit_controller.rb b/app/controllers/projects/commit_controller.rb index 2b2764d2e34..870320a79d9 100644 --- a/app/controllers/projects/commit_controller.rb +++ b/app/controllers/projects/commit_controller.rb @@ -86,7 +86,7 @@ class Projects::CommitController < Projects::ApplicationController respond_to do |format| format.json do - render json: @merge_requests.to_json + render json: Gitlab::Json.dump(@merge_requests) end end end diff --git a/app/controllers/projects/environments_controller.rb b/app/controllers/projects/environments_controller.rb index 4f037cc843e..67f2f85ce65 100644 --- a/app/controllers/projects/environments_controller.rb +++ b/app/controllers/projects/environments_controller.rb @@ -183,7 +183,7 @@ class Projects::EnvironmentsController < Projects::ApplicationController def metrics respond_to do |format| format.html do - redirect_to project_metrics_dashboard_path(project, environment: environment ) + redirect_to project_metrics_dashboard_path(project, environment: environment) end format.json do # Currently, this acts as a hint to load the metrics details into the cache diff --git a/app/controllers/projects/google_cloud/configuration_controller.rb b/app/controllers/projects/google_cloud/configuration_controller.rb index 06a6674d578..e109ab95d39 100644 --- a/app/controllers/projects/google_cloud/configuration_controller.rb +++ b/app/controllers/projects/google_cloud/configuration_controller.rb @@ -15,7 +15,7 @@ module Projects gcpRegions: gcp_regions, revokeOauthUrl: revoke_oauth_url } - @js_data = js_data.to_json + @js_data = Gitlab::Json.dump(js_data) track_event(:render_page) end diff --git a/app/controllers/projects/google_cloud/databases_controller.rb b/app/controllers/projects/google_cloud/databases_controller.rb index 77ee830fd24..b511a85b0b8 100644 --- a/app/controllers/projects/google_cloud/databases_controller.rb +++ b/app/controllers/projects/google_cloud/databases_controller.rb @@ -17,7 +17,8 @@ module Projects cloudsqlInstances: ::GoogleCloud::GetCloudsqlInstancesService.new(project).execute, emptyIllustrationUrl: ActionController::Base.helpers.image_path('illustrations/pipelines_empty.svg') } - @js_data = js_data.to_json + + @js_data = Gitlab::Json.dump(js_data) track_event(:render_page) end @@ -27,7 +28,7 @@ module Projects @title = title(product) - @js_data = { + js_data = { gcpProjects: gcp_projects, refs: refs, cancelPath: project_google_cloud_databases_path(project), @@ -35,7 +36,9 @@ module Projects formDescription: description(product), databaseVersions: Projects::GoogleCloud::CloudsqlHelper::VERSIONS[product], tiers: Projects::GoogleCloud::CloudsqlHelper::TIERS - }.to_json + } + + @js_data = Gitlab::Json.dump(js_data) track_event(:render_form) render template: 'projects/google_cloud/databases/cloudsql_form', formats: :html diff --git a/app/controllers/projects/google_cloud/deployments_controller.rb b/app/controllers/projects/google_cloud/deployments_controller.rb index f6cc8d5eafb..041486eb2fb 100644 --- a/app/controllers/projects/google_cloud/deployments_controller.rb +++ b/app/controllers/projects/google_cloud/deployments_controller.rb @@ -11,7 +11,7 @@ class Projects::GoogleCloud::DeploymentsController < Projects::GoogleCloud::Base enableCloudRunUrl: project_google_cloud_deployments_cloud_run_path(project), enableCloudStorageUrl: project_google_cloud_deployments_cloud_storage_path(project) } - @js_data = js_data.to_json + @js_data = Gitlab::Json.dump(js_data) track_event(:render_page) end diff --git a/app/controllers/projects/google_cloud/gcp_regions_controller.rb b/app/controllers/projects/google_cloud/gcp_regions_controller.rb index 2f0bc05030f..c51261721b2 100644 --- a/app/controllers/projects/google_cloud/gcp_regions_controller.rb +++ b/app/controllers/projects/google_cloud/gcp_regions_controller.rb @@ -14,7 +14,7 @@ class Projects::GoogleCloud::GcpRegionsController < Projects::GoogleCloud::BaseC refs: refs, cancelPath: project_google_cloud_configuration_path(project) } - @js_data = js_data.to_json + @js_data = Gitlab::Json.dump(js_data) track_event(:render_form) end diff --git a/app/controllers/projects/google_cloud/service_accounts_controller.rb b/app/controllers/projects/google_cloud/service_accounts_controller.rb index 89d624764df..7b029e25ea2 100644 --- a/app/controllers/projects/google_cloud/service_accounts_controller.rb +++ b/app/controllers/projects/google_cloud/service_accounts_controller.rb @@ -14,7 +14,7 @@ class Projects::GoogleCloud::ServiceAccountsController < Projects::GoogleCloud:: refs: refs, cancelPath: project_google_cloud_configuration_path(project) } - @js_data = js_data.to_json + @js_data = Gitlab::Json.dump(js_data) track_event(:render_form) end diff --git a/app/controllers/projects/graphs_controller.rb b/app/controllers/projects/graphs_controller.rb index 47557133ac8..6da70b5e157 100644 --- a/app/controllers/projects/graphs_controller.rb +++ b/app/controllers/projects/graphs_controller.rb @@ -104,7 +104,7 @@ class Projects::GraphsController < Projects::ApplicationController } end - render json: @log.to_json + render json: Gitlab::Json.dump(@log) end def tracking_namespace_source diff --git a/app/controllers/projects/incidents_controller.rb b/app/controllers/projects/incidents_controller.rb index 089ee860ea6..599505dcb6d 100644 --- a/app/controllers/projects/incidents_controller.rb +++ b/app/controllers/projects/incidents_controller.rb @@ -9,7 +9,6 @@ class Projects::IncidentsController < Projects::ApplicationController before_action do push_force_frontend_feature_flag(:work_items, @project&.work_items_feature_flag_enabled?) push_force_frontend_feature_flag(:work_items_mvc_2, @project&.work_items_mvc_2_feature_flag_enabled?) - push_frontend_feature_flag(:work_items_hierarchy, @project) end feature_category :incident_management diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb index 5b1117c0224..ee845cd001e 100644 --- a/app/controllers/projects/issues_controller.rb +++ b/app/controllers/projects/issues_controller.rb @@ -1,7 +1,6 @@ # frozen_string_literal: true class Projects::IssuesController < Projects::ApplicationController - include RendersNotes include ToggleSubscriptionAction include IssuableActions include ToggleAwardEmoji @@ -49,11 +48,14 @@ class Projects::IssuesController < Projects::ApplicationController push_force_frontend_feature_flag(:work_items, project&.work_items_feature_flag_enabled?) end + before_action only: :index do + push_frontend_feature_flag(:or_issuable_queries, project) + end + before_action only: :show do push_frontend_feature_flag(:issue_assignees_widget, project) - push_frontend_feature_flag(:realtime_labels, project) + push_frontend_feature_flag(:work_items_mvc, project&.group) push_force_frontend_feature_flag(:work_items_mvc_2, project&.work_items_mvc_2_feature_flag_enabled?) - push_frontend_feature_flag(:work_items_hierarchy, project) push_frontend_feature_flag(:epic_widget_edit_confirmation, project) push_force_frontend_feature_flag(:work_items_create_from_markdown, project&.work_items_create_from_markdown_feature_flag_enabled?) end @@ -405,7 +407,6 @@ class Projects::IssuesController < Projects::ApplicationController options = super options[:issue_types] = Issue::TYPES_FOR_LIST - options[:issue_types] = options[:issue_types].excluding('task') unless project.work_items_feature_flag_enabled? if service_desk? options.reject! { |key| key == 'author_username' || key == 'author_id' } @@ -432,10 +433,13 @@ class Projects::IssuesController < Projects::ApplicationController def create_vulnerability_issue_feedback(issue); end def redirect_if_task - return render_404 if issue.task? && !project.work_items_feature_flag_enabled? return unless issue.task? - redirect_to project_work_items_path(project, issue.id, params: request.query_parameters) + if Feature.enabled?(:use_iid_in_work_items_path, project.group) + redirect_to project_work_items_path(project, issue.iid, params: request.query_parameters.merge(iid_path: true)) + else + redirect_to project_work_items_path(project, issue.id, params: request.query_parameters) + end end end diff --git a/app/controllers/projects/labels_controller.rb b/app/controllers/projects/labels_controller.rb index 8ec2cbb41e9..14f2e372bc5 100644 --- a/app/controllers/projects/labels_controller.rb +++ b/app/controllers/projects/labels_controller.rb @@ -68,9 +68,10 @@ class Projects::LabelsController < Projects::ApplicationController def generate Gitlab::IssuesLabels.generate(@project) - if params[:redirect] == 'issues' + case params[:redirect] + when 'issues' redirect_to project_issues_path(@project) - elsif params[:redirect] == 'merge_requests' + when 'merge_requests' redirect_to project_merge_requests_path(@project) else redirect_to project_labels_path(@project) diff --git a/app/controllers/projects/learn_gitlab_controller.rb b/app/controllers/projects/learn_gitlab_controller.rb index 61e4a1812ba..6fe009c8a28 100644 --- a/app/controllers/projects/learn_gitlab_controller.rb +++ b/app/controllers/projects/learn_gitlab_controller.rb @@ -23,7 +23,6 @@ class Projects::LearnGitlabController < Projects::ApplicationController experiment(:invite_for_help_continuous_onboarding, namespace: project.namespace) do |e| e.candidate {} - e.publish_to_database end end diff --git a/app/controllers/projects/merge_requests/diffs_controller.rb b/app/controllers/projects/merge_requests/diffs_controller.rb index 418e7233e21..c88dbc70ed5 100644 --- a/app/controllers/projects/merge_requests/diffs_controller.rb +++ b/app/controllers/projects/merge_requests/diffs_controller.rb @@ -38,16 +38,13 @@ class Projects::MergeRequests::DiffsController < Projects::MergeRequests::Applic diffs = @compare.diffs_in_batch(params[:page], params[:per_page], diff_options: diff_options_hash) unfoldable_positions = @merge_request.note_positions_for_paths(diffs.diff_file_paths, current_user).unfoldable - diffs.unfold_diff_files(unfoldable_positions) - diffs.write_cache - options = { merge_request: @merge_request, commit: commit, diff_view: diff_view, merge_ref_head_diff: render_merge_ref_head_diff?, pagination_data: diffs.pagination_data, - allow_tree_conflicts: display_merge_conflicts_in_diff? + merge_conflicts_in_diff: display_merge_conflicts_in_diff? } # NOTE: Any variables that would affect the resulting json needs to be added to the cache_context to avoid stale cache issues. @@ -60,10 +57,19 @@ class Projects::MergeRequests::DiffsController < Projects::MergeRequests::Applic params[:page], params[:per_page], options[:merge_ref_head_diff], - options[:allow_tree_conflicts] + options[:merge_conflicts_in_diff] ] - return unless stale?(etag: [cache_context + diff_options_hash.fetch(:paths, []), diffs]) + if Feature.enabled?(:check_etags_diffs_batch_before_write_cache, merge_request.project) && !stale?(etag: [cache_context + diff_options_hash.fetch(:paths, []), diffs]) + return + end + + diffs.unfold_diff_files(unfoldable_positions) + diffs.write_cache + + if Feature.disabled?(:check_etags_diffs_batch_before_write_cache, merge_request.project) && !stale?(etag: [cache_context + diff_options_hash.fetch(:paths, []), diffs]) + return + end render json: PaginatedDiffSerializer.new(current_user: current_user).represent(diffs, options) end @@ -75,7 +81,7 @@ class Projects::MergeRequests::DiffsController < Projects::MergeRequests::Applic options = additional_attributes.merge( only_context_commits: show_only_context_commits?, merge_ref_head_diff: render_merge_ref_head_diff?, - allow_tree_conflicts: display_merge_conflicts_in_diff? + merge_conflicts_in_diff: display_merge_conflicts_in_diff? ) render json: DiffsMetadataSerializer.new(project: @merge_request.project, current_user: current_user) @@ -104,7 +110,7 @@ class Projects::MergeRequests::DiffsController < Projects::MergeRequests::Applic options = additional_attributes.merge( diff_view: "inline", merge_ref_head_diff: render_merge_ref_head_diff?, - allow_tree_conflicts: display_merge_conflicts_in_diff? + merge_conflicts_in_diff: display_merge_conflicts_in_diff? ) options[:context_commits] = @merge_request.recent_context_commits diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb index 9c139733248..4ba79d43f27 100644 --- a/app/controllers/projects/merge_requests_controller.rb +++ b/app/controllers/projects/merge_requests_controller.rb @@ -3,7 +3,6 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationController include ToggleSubscriptionAction include IssuableActions - include RendersNotes include RendersCommits include RendersAssignees include ToggleAwardEmoji @@ -32,18 +31,15 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo before_action :check_user_can_push_to_source_branch!, only: [:rebase] before_action only: [:show] do - push_frontend_feature_flag(:merge_request_widget_graphql, project) push_frontend_feature_flag(:core_security_mr_widget_counts, project) - push_frontend_feature_flag(:refactor_code_quality_extension, project) - push_frontend_feature_flag(:refactor_mr_widget_test_summary, project) push_frontend_feature_flag(:issue_assignees_widget, @project) - push_frontend_feature_flag(:realtime_labels, project) push_frontend_feature_flag(:refactor_security_extension, @project) push_frontend_feature_flag(:refactor_code_quality_inline_findings, project) push_frontend_feature_flag(:moved_mr_sidebar, project) push_frontend_feature_flag(:paginated_mr_discussions, project) push_frontend_feature_flag(:mr_review_submit_comment, project) push_frontend_feature_flag(:mr_experience_survey, project) + push_frontend_feature_flag(:realtime_reviewers, project) end before_action do @@ -123,12 +119,13 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo @commits_count = @merge_request.commits_count + @merge_request.context_commits_count @diffs_count = get_diffs_count @issuable_sidebar = serializer.represent(@merge_request, serializer: 'sidebar') - @current_user_data = UserSerializer.new(project: @project).represent(current_user, {}, MergeRequestCurrentUserEntity).to_json + @current_user_data = Gitlab::Json.dump(UserSerializer.new(project: @project).represent(current_user, {}, MergeRequestCurrentUserEntity)) @show_whitespace_default = current_user.nil? || current_user.show_whitespace_in_diffs @file_by_file_default = current_user&.view_diffs_file_by_file @coverage_path = coverage_reports_project_merge_request_path(@project, @merge_request, format: :json) if @merge_request.has_coverage_reports? @update_current_user_path = expose_path(api_v4_user_preferences_path) @endpoint_metadata_url = endpoint_metadata_url(@project, @merge_request) + @endpoint_diff_batch_url = endpoint_diff_batch_url(@project, @merge_request) set_pipeline_variables @@ -179,15 +176,15 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo @merge_request.recent_context_commits ) - # Get commits from repository - # or from cache if already merged - @commits = - set_commits_for_rendering( - @merge_request.recent_commits(load_from_gitaly: true).with_latest_pipeline(@merge_request.source_branch).with_markdown_cache, - commits_count: @merge_request.commits_count - ) + per_page = [(params[:per_page] || MergeRequestDiff::COMMITS_SAFE_SIZE).to_i, MergeRequestDiff::COMMITS_SAFE_SIZE].min + recent_commits = @merge_request.recent_commits(load_from_gitaly: true, limit: per_page, page: params[:page]).with_latest_pipeline(@merge_request.source_branch).with_markdown_cache + @next_page = recent_commits.next_page + @commits = set_commits_for_rendering( + recent_commits, + commits_count: @merge_request.commits_count + ) - render json: { html: view_to_html_string('projects/merge_requests/_commits') } + render json: { html: view_to_html_string('projects/merge_requests/_commits'), next_page: @next_page } end def pipelines @@ -535,7 +532,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo render json: '', status: :no_content when :parsed - render json: report_comparison[:data].to_json, status: :ok + render json: Gitlab::Json.dump(report_comparison[:data]), status: :ok when :error render json: { status_reason: report_comparison[:status_reason] }, status: :bad_request else @@ -553,12 +550,23 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo return render_404 unless can?(current_user, :read_build, merge_request.actual_head_pipeline) end + def show_whitespace + current_user&.show_whitespace_in_diffs ? '0' : '1' + end + def endpoint_metadata_url(project, merge_request) - params = request.query_parameters.merge(view: 'inline', diff_head: true, w: current_user&.show_whitespace_in_diffs ? '0' : '1') + params = request.query_parameters.merge(view: 'inline', diff_head: true, w: show_whitespace) diffs_metadata_project_json_merge_request_path(project, merge_request, 'json', params) end + def endpoint_diff_batch_url(project, merge_request) + per_page = current_user&.view_diffs_file_by_file ? '1' : '5' + params = request.query_parameters.merge(view: 'inline', diff_head: true, w: show_whitespace, page: '0', per_page: per_page) + + diffs_batch_project_json_merge_request_path(project, merge_request, 'json', params) + end + def convert_date_to_epoch(date) Date.strptime(date, "%Y-%m-%d")&.to_time&.to_i if date rescue Date::Error, TypeError diff --git a/app/controllers/projects/ml/experiments_controller.rb b/app/controllers/projects/ml/experiments_controller.rb new file mode 100644 index 00000000000..749586791ac --- /dev/null +++ b/app/controllers/projects/ml/experiments_controller.rb @@ -0,0 +1,32 @@ +# frozen_string_literal: true + +module Projects + module Ml + class ExperimentsController < ::Projects::ApplicationController + include Projects::Ml::ExperimentsHelper + before_action :check_feature_flag + + feature_category :mlops + + MAX_PER_PAGE = 20 + + def index + @experiments = ::Ml::Experiment.by_project_id(@project.id).page(params[:page]).per(MAX_PER_PAGE) + end + + def show + @experiment = ::Ml::Experiment.by_project_id_and_iid(@project.id, params[:id]) + + return redirect_to project_ml_experiments_path(@project) unless @experiment.present? + + @candidates = @experiment.candidates&.including_metrics_and_params + end + + private + + def check_feature_flag + render_404 unless Feature.enabled?(:ml_experiment_tracking, @project) + end + end + end +end diff --git a/app/controllers/projects/notes_controller.rb b/app/controllers/projects/notes_controller.rb index d24b232293b..9d3506d49b0 100644 --- a/app/controllers/projects/notes_controller.rb +++ b/app/controllers/projects/notes_controller.rb @@ -58,7 +58,7 @@ class Projects::NotesController < Projects::ApplicationController def outdated_line_change diff_lines = Rails.cache.fetch(['note', note.id, 'oudated_line_change'], expires_in: 7.days) do - ::MergeRequests::OutdatedDiscussionDiffLinesService.new(project: note.noteable.source_project, note: note).execute.to_json + Gitlab::Json.dump(::MergeRequests::OutdatedDiscussionDiffLinesService.new(project: note.noteable.source_project, note: note).execute) end render json: diff_lines diff --git a/app/controllers/projects/packages/infrastructure_registry_controller.rb b/app/controllers/projects/packages/infrastructure_registry_controller.rb index f1410bf6043..733df9fdb45 100644 --- a/app/controllers/projects/packages/infrastructure_registry_controller.rb +++ b/app/controllers/projects/packages/infrastructure_registry_controller.rb @@ -5,7 +5,7 @@ module Projects class InfrastructureRegistryController < Projects::ApplicationController include PackagesAccess - feature_category :infrastructure_as_code + feature_category :package_registry urgency :low def show diff --git a/app/controllers/projects/pipeline_schedules_controller.rb b/app/controllers/projects/pipeline_schedules_controller.rb index ca787785901..31030d958df 100644 --- a/app/controllers/projects/pipeline_schedules_controller.rb +++ b/app/controllers/projects/pipeline_schedules_controller.rb @@ -98,7 +98,7 @@ class Projects::PipelineSchedulesController < Projects::ApplicationController def schedule_params params.require(:schedule) .permit(:description, :cron, :cron_timezone, :ref, :active, - variables_attributes: [:id, :variable_type, :key, :secret_value, :_destroy] ) + variables_attributes: [:id, :variable_type, :key, :secret_value, :_destroy]) end def authorize_play_pipeline_schedule! diff --git a/app/controllers/projects/pipelines_controller.rb b/app/controllers/projects/pipelines_controller.rb index 01f7bb9e2cf..7d1a75ae449 100644 --- a/app/controllers/projects/pipelines_controller.rb +++ b/app/controllers/projects/pipelines_controller.rb @@ -140,21 +140,13 @@ class Projects::PipelinesController < Projects::ApplicationController end def builds - if Feature.enabled?(:pipeline_tabs_vue, project) - redirect_to pipeline_path(@pipeline, tab: 'builds') - else - render_show - end + render_show end def dag respond_to do |format| format.html do - if Feature.enabled?(:pipeline_tabs_vue, project) - redirect_to pipeline_path(@pipeline, tab: 'dag') - else - render_show - end + render_show end format.json do render json: Ci::DagPipelineSerializer @@ -165,9 +157,7 @@ class Projects::PipelinesController < Projects::ApplicationController end def failures - if Feature.enabled?(:pipeline_tabs_vue, project) - redirect_to pipeline_path(@pipeline, tab: 'failures') - elsif @pipeline.failed_builds.present? + if @pipeline.failed_builds.present? render_show else redirect_to pipeline_path(@pipeline) @@ -222,11 +212,7 @@ class Projects::PipelinesController < Projects::ApplicationController def test_report respond_to do |format| format.html do - if Feature.enabled?(:pipeline_tabs_vue, project) - redirect_to pipeline_path(@pipeline, tab: 'test_report') - else - render_show - end + render_show end format.json do render json: TestReportSerializer @@ -352,7 +338,6 @@ class Projects::PipelinesController < Projects::ApplicationController experiment(:runners_availability_section, namespace: project.root_ancestor) do |e| e.candidate {} - e.publish_to_database end end diff --git a/app/controllers/projects/product_analytics_controller.rb b/app/controllers/projects/product_analytics_controller.rb deleted file mode 100644 index 8085b0a6334..00000000000 --- a/app/controllers/projects/product_analytics_controller.rb +++ /dev/null @@ -1,61 +0,0 @@ -# frozen_string_literal: true - -class Projects::ProductAnalyticsController < Projects::ApplicationController - before_action :feature_enabled!, only: [:index, :setup, :test, :graphs] - before_action :authorize_read_product_analytics! - before_action :tracker_variables, only: [:setup, :test] - - feature_category :product_analytics - - def index - @events = product_analytics_events.order_by_time.page(params[:page]) - end - - def setup - end - - def test - @event = product_analytics_events.try(:first) - end - - def graphs - @graphs = [] - @timerange = 30 - - requested_graphs = %w(platform os_timezone br_lang doc_charset) - - requested_graphs.each do |graph| - @graphs << ProductAnalytics::BuildGraphService - .new(project, { graph: graph, timerange: @timerange }) - .execute - end - - @activity_graph = ProductAnalytics::BuildActivityGraphService - .new(project, { timerange: @timerange }) - .execute - end - - private - - def product_analytics_events - @project.product_analytics_events - end - - def tracker_variables - # We use project id as Snowplow appId - @project_id = @project.id.to_s - - # Snowplow remembers values like appId and platform between reloads. - # That is why we have to rename the tracker with a random integer. - @random = rand(999999) - - # Generate random platform every time a tracker is rendered. - @platform = %w(web mob app)[(@random % 3)] - end - - def feature_enabled! - render_404 unless Feature.enabled?(:product_analytics, @project) - end -end - -Projects::ProductAnalyticsController.prepend_mod_with('Projects::ProductAnalyticsController') diff --git a/app/controllers/projects/prometheus/alerts_controller.rb b/app/controllers/projects/prometheus/alerts_controller.rb index c3dc17694d9..27ac64e5758 100644 --- a/app/controllers/projects/prometheus/alerts_controller.rb +++ b/app/controllers/projects/prometheus/alerts_controller.rb @@ -23,11 +23,7 @@ module Projects token = extract_alert_manager_token(request) result = notify_service.execute(token) - if result.success? - render json: AlertManagement::AlertSerializer.new.represent(result.payload[:alerts]), code: result.http_status - else - head result.http_status - end + head result.http_status end private @@ -37,19 +33,6 @@ module Projects .new(project, params.permit!) end - def serialize_as_json(alert_obj) - serializer.represent(alert_obj) - end - - def serializer - PrometheusAlertSerializer - .new(project: project, current_user: current_user) - end - - def alerts - alerts_finder.execute - end - def alert @alert ||= alerts_finder(metric: params[:id]).execute.first || render_404 end diff --git a/app/controllers/projects/registry/repositories_controller.rb b/app/controllers/projects/registry/repositories_controller.rb index 87cb8e4781f..ffe95bf4fee 100644 --- a/app/controllers/projects/registry/repositories_controller.rb +++ b/app/controllers/projects/registry/repositories_controller.rb @@ -8,10 +8,6 @@ module Projects before_action :authorize_update_container_image!, only: [:destroy] - before_action do - push_frontend_feature_flag(:container_registry_show_shortened_path, project) - end - def index respond_to do |format| format.html { ensure_root_container_repository! } @@ -26,7 +22,11 @@ module Projects def destroy image.delete_scheduled! - DeleteContainerRepositoryWorker.perform_async(current_user.id, image.id) # rubocop:disable CodeReuse/Worker + + unless Feature.enabled?(:container_registry_delete_repository_with_cron_worker) + DeleteContainerRepositoryWorker.perform_async(current_user.id, image.id) # rubocop:disable CodeReuse/Worker + end + track_package_event(:delete_repository, :container) respond_to do |format| diff --git a/app/controllers/projects/settings/access_tokens_controller.rb b/app/controllers/projects/settings/access_tokens_controller.rb index bac35583a97..0884816ef62 100644 --- a/app/controllers/projects/settings/access_tokens_controller.rb +++ b/app/controllers/projects/settings/access_tokens_controller.rb @@ -3,6 +3,7 @@ module Projects module Settings class AccessTokensController < Projects::ApplicationController + include RenderAccessTokens include AccessTokensActions layout 'project_settings' diff --git a/app/controllers/projects/settings/ci_cd_controller.rb b/app/controllers/projects/settings/ci_cd_controller.rb index cda6c8abea7..8aef1c3d24d 100644 --- a/app/controllers/projects/settings/ci_cd_controller.rb +++ b/app/controllers/projects/settings/ci_cd_controller.rb @@ -11,10 +11,6 @@ module Projects before_action :authorize_admin_pipeline! before_action :check_builds_available! before_action :define_variables - before_action do - push_frontend_feature_flag(:ajax_new_deploy_token, @project) - push_frontend_feature_flag(:ci_variable_settings_graphql, @project) - end helper_method :highlight_badge @@ -23,9 +19,11 @@ module Projects def show if Feature.enabled?(:ci_pipeline_triggers_settings_vue_ui, @project) - @triggers_json = ::Ci::TriggerSerializer.new.represent( + triggers = ::Ci::TriggerSerializer.new.represent( @project.triggers, current_user: current_user, project: @project - ).to_json + ) + + @triggers_json = Gitlab::Json.dump(triggers) end render diff --git a/app/controllers/projects/settings/repository_controller.rb b/app/controllers/projects/settings/repository_controller.rb index 43c6451577a..90988645d3a 100644 --- a/app/controllers/projects/settings/repository_controller.rb +++ b/app/controllers/projects/settings/repository_controller.rb @@ -6,11 +6,8 @@ module Projects layout 'project_settings' before_action :authorize_admin_project! before_action :define_variables, only: [:create_deploy_token] - before_action do - push_frontend_feature_flag(:ajax_new_deploy_token, @project) - end - feature_category :source_code_management, [:show, :cleanup] + feature_category :source_code_management, [:show, :cleanup, :update] feature_category :continuous_delivery, [:create_deploy_token] urgency :low, [:show, :create_deploy_token] @@ -60,6 +57,19 @@ module Projects end end + def update + result = ::Projects::UpdateService.new(@project, current_user, project_params).execute + + if result[:status] == :success + flash[:notice] = _("Project settings were successfully updated.") + else + flash[:alert] = result[:message] + @project.reset + end + + redirect_to project_settings_repository_path(project) + end + private def render_show @@ -97,6 +107,18 @@ module Projects params.require(:deploy_token).permit(:name, :expires_at, :read_repository, :read_registry, :write_registry, :read_package_registry, :write_package_registry, :username) end + def project_params + params.require(:project).permit(project_params_attributes) + end + + def project_params_attributes + [ + :issue_branch_template, + :default_branch, + :autoclose_referenced_issues + ] + end + def access_levels_options { create_access_levels: levels_for_dropdown, diff --git a/app/controllers/projects/starrers_controller.rb b/app/controllers/projects/starrers_controller.rb index bc857648a06..06996e8e5fc 100644 --- a/app/controllers/projects/starrers_controller.rb +++ b/app/controllers/projects/starrers_controller.rb @@ -11,14 +11,8 @@ class Projects::StarrersController < Projects::ApplicationController @starrers = UsersStarProjectsFinder.new(@project, params, current_user: @current_user).execute @sort = params[:sort].presence || sort_value_name @starrers = @starrers.preload_users.sort_by_attribute(@sort).page(params[:page]) - @public_count = @project.starrers.with_public_profile.size - @total_count = @project.starrers.size + @public_count = @project.starrers.active.with_public_profile.size + @total_count = @project.starrers.active.size @private_count = @total_count - @public_count end - - private - - def has_starred_project?(starrers) - starrers.first { |starrer| starrer.user_id == current_user.id } - end end diff --git a/app/controllers/projects/templates_controller.rb b/app/controllers/projects/templates_controller.rb index 6d06b05c1e9..ed5fb838670 100644 --- a/app/controllers/projects/templates_controller.rb +++ b/app/controllers/projects/templates_controller.rb @@ -12,7 +12,7 @@ class Projects::TemplatesController < Projects::ApplicationController templates = @template_type.template_subsets(project) respond_to do |format| - format.json { render json: templates.to_json } + format.json { render json: Gitlab::Json.dump(templates) } end end @@ -20,7 +20,7 @@ class Projects::TemplatesController < Projects::ApplicationController template = @template_type.find(params[:key], project) respond_to do |format| - format.json { render json: template.to_json } + format.json { render json: Gitlab::Json.dump(template) } end end diff --git a/app/controllers/projects/usage_quotas_controller.rb b/app/controllers/projects/usage_quotas_controller.rb index 07a3c010f4f..d3757eaf481 100644 --- a/app/controllers/projects/usage_quotas_controller.rb +++ b/app/controllers/projects/usage_quotas_controller.rb @@ -5,7 +5,7 @@ class Projects::UsageQuotasController < Projects::ApplicationController layout "project_settings" - feature_category :utilization + feature_category :subscription_cost_management urgency :low def index diff --git a/app/controllers/projects/work_items_controller.rb b/app/controllers/projects/work_items_controller.rb index b794785f285..a7e59a28fb7 100644 --- a/app/controllers/projects/work_items_controller.rb +++ b/app/controllers/projects/work_items_controller.rb @@ -4,13 +4,9 @@ class Projects::WorkItemsController < Projects::ApplicationController before_action do push_force_frontend_feature_flag(:work_items, project&.work_items_feature_flag_enabled?) push_force_frontend_feature_flag(:work_items_mvc_2, project&.work_items_mvc_2_feature_flag_enabled?) - push_frontend_feature_flag(:work_items_hierarchy, project) + push_frontend_feature_flag(:use_iid_in_work_items_path, project) end feature_category :team_planning urgency :low - - def index - render_404 unless project&.work_items_feature_flag_enabled? - end end diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index b7b6e6534fb..a5dacbf7f2f 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -46,7 +46,6 @@ class ProjectsController < Projects::ApplicationController push_force_frontend_feature_flag(:work_items, @project&.work_items_feature_flag_enabled?) push_force_frontend_feature_flag(:work_items_mvc_2, @project&.work_items_mvc_2_feature_flag_enabled?) push_frontend_feature_flag(:package_registry_access_level) - push_frontend_feature_flag(:work_items_hierarchy, @project) end before_action only: :edit do @@ -343,7 +342,7 @@ class ProjectsController < Projects::ApplicationController options['Commits'] = [ref] end - render json: options.to_json + render json: Gitlab::Json.dump(options) rescue Gitlab::Git::CommandError render json: { error: _('Unable to load refs') }, status: :service_unavailable end @@ -440,7 +439,7 @@ class ProjectsController < Projects::ApplicationController def operations_feature_attributes if Feature.enabled?(:split_operations_visibility_permissions, project) %i[ - environments_access_level feature_flags_access_level monitor_access_level + environments_access_level feature_flags_access_level monitor_access_level infrastructure_access_level ] else %i[operations_access_level] @@ -465,7 +464,6 @@ class ProjectsController < Projects::ApplicationController :build_timeout_human_readable, :resolve_outdated_diff_discussions, :container_registry_enabled, - :default_branch, :description, :emails_disabled, :external_authorization_classification_label, @@ -491,7 +489,6 @@ class ProjectsController < Projects::ApplicationController :merge_method, :initialize_with_sast, :initialize_with_readme, - :autoclose_referenced_issues, :ci_separated_caches, :suggestion_commit_message, :packages_enabled, diff --git a/app/controllers/registrations_controller.rb b/app/controllers/registrations_controller.rb index 31fe30f3f06..995303a631a 100644 --- a/app/controllers/registrations_controller.rb +++ b/app/controllers/registrations_controller.rb @@ -8,12 +8,15 @@ class RegistrationsController < Devise::RegistrationsController include OneTrustCSP include BizibleCSP include GoogleAnalyticsCSP + include PreferredLanguageSwitcher include RegistrationsTracking + include Gitlab::Tracking::Helpers::WeakPasswordErrorEvent layout 'devise' prepend_before_action :check_captcha, only: :create before_action :ensure_destroy_prerequisites_met, only: [:destroy] + before_action :init_preferred_language, only: :new before_action :load_recaptcha, only: :new before_action :set_invite_params, only: :new before_action only: [:create] do @@ -33,15 +36,15 @@ class RegistrationsController < Devise::RegistrationsController def create set_user_state - token = set_custom_confirmation_token + set_custom_confirmation_token super do |new_user| accept_pending_invitations if new_user.persisted? persist_accepted_terms_if_required(new_user) set_role_required(new_user) - track_experiment_event(new_user) - send_custom_confirmation_instructions(new_user, token) + send_custom_confirmation_instructions + track_weak_password_error(new_user, self.class.name, 'create') if pending_approval? NotificationService.new.new_instance_access_request(new_user) @@ -127,7 +130,7 @@ class RegistrationsController < Devise::RegistrationsController # after user confirms and comes back, he will be redirected store_location_for(:redirect, users_sign_up_welcome_path(glm_tracking_params)) - return identity_verification_redirect_path if custom_confirmation_enabled?(resource) + return identity_verification_redirect_path if custom_confirmation_enabled? users_almost_there_path(email: resource.email) end @@ -189,7 +192,8 @@ class RegistrationsController < Devise::RegistrationsController def resource @resource ||= Users::RegistrationsBuildService - .new(current_user, sign_up_params.merge({ skip_confirmation: registered_with_invite_email? })) + .new(current_user, sign_up_params.merge({ skip_confirmation: registered_with_invite_email?, + preferred_language: preferred_language })) .execute end @@ -239,19 +243,11 @@ class RegistrationsController < Devise::RegistrationsController current_user end - def track_experiment_event(new_user) - # Track signed up event to relate it with click "Sign up" button events from - # the experimental logged out header with marketing links. This allows us to - # have a funnel of visitors clicking on the header and those visitors - # signing up and becoming users - experiment(:logged_out_marketing_header, actor: new_user).track(:signed_up) if new_user.persisted? - end - def identity_verification_redirect_path # overridden by EE module end - def custom_confirmation_enabled?(resource) + def custom_confirmation_enabled? # overridden by EE module end @@ -259,7 +255,7 @@ class RegistrationsController < Devise::RegistrationsController # overridden by EE module end - def send_custom_confirmation_instructions(user, token) + def send_custom_confirmation_instructions # overridden by EE module end end diff --git a/app/controllers/search_controller.rb b/app/controllers/search_controller.rb index 7d4dd04c6d4..5351e3e9e77 100644 --- a/app/controllers/search_controller.rb +++ b/app/controllers/search_controller.rb @@ -9,7 +9,11 @@ class SearchController < ApplicationController RESCUE_FROM_TIMEOUT_ACTIONS = [:count, :show, :autocomplete, :aggregations].freeze - track_event :show, name: 'i_search_total', destinations: [:redis_hll, :snowplow] + track_custom_event :show, + name: 'i_search_total', + label: 'redis_hll_counters.search.search_total_unique_counts_monthly', + action: 'executed', + destinations: [:redis_hll, :snowplow] def self.search_rate_limited_endpoints %i[show count autocomplete] @@ -108,7 +112,7 @@ class SearchController < ApplicationController @ref = params[:project_ref] if params[:project_ref].present? @filter = params[:filter] - render json: search_autocomplete_opts(term, filter: @filter).to_json + render json: Gitlab::Json.dump(search_autocomplete_opts(term, filter: @filter)) end def opensearch @@ -140,8 +144,7 @@ class SearchController < ApplicationController def check_single_commit_result? return false if params[:force_search_results] return false unless @project.present? - # download_code project policy grants user the read_commit ability - return false unless Ability.allowed?(current_user, :download_code, @project) + return false unless Ability.allowed?(current_user, :read_code, @project) query = params[:search].strip.downcase return false unless Commit.valid_hash?(query) @@ -243,6 +246,10 @@ class SearchController < ApplicationController search_service.project&.namespace || search_service.group end + def tracking_project_source + search_service.project + end + def search_type 'basic' end diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb index 5c969c437f4..c20a9aa4485 100644 --- a/app/controllers/sessions_controller.rb +++ b/app/controllers/sessions_controller.rb @@ -13,6 +13,7 @@ class SessionsController < Devise::SessionsController include BizibleCSP include VerifiesWithEmail include GoogleAnalyticsCSP + include PreferredLanguageSwitcher skip_before_action :check_two_factor_requirement, only: [:destroy] skip_before_action :check_password_expiration, only: [:destroy] @@ -30,6 +31,7 @@ class SessionsController < Devise::SessionsController prepend_before_action :ensure_password_authentication_enabled!, if: -> { action_name == 'create' && password_based_login? } before_action :auto_sign_in_with_provider, only: [:new] + before_action :init_preferred_language, only: :new before_action :store_unauthenticated_sessions, only: [:new] before_action :save_failed_login, if: :action_new_and_failed_login? before_action :load_recaptcha diff --git a/app/controllers/terraform/services_controller.rb b/app/controllers/terraform/services_controller.rb index e7b9a94fd8e..7ebe1d9ba98 100644 --- a/app/controllers/terraform/services_controller.rb +++ b/app/controllers/terraform/services_controller.rb @@ -3,7 +3,7 @@ class Terraform::ServicesController < ApplicationController skip_before_action :authenticate_user! - feature_category :infrastructure_as_code + feature_category :package_registry def index render json: { 'modules.v1' => "/api/#{::API::API.version}/packages/terraform/modules/v1/" } diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index c35aa8e4346..0f03333d793 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -274,8 +274,6 @@ class UsersController < ApplicationController def finder_params { - # don't display projects pending deletion - without_deleted: true, # don't display projects marked for deletion not_aimed_for_deletion: true } |