diff options
Diffstat (limited to 'app/controllers/concerns')
-rw-r--r-- | app/controllers/concerns/authenticates_with_two_factor.rb | 4 | ||||
-rw-r--r-- | app/controllers/concerns/confirm_email_warning.rb | 25 | ||||
-rw-r--r-- | app/controllers/concerns/group_tree.rb | 20 | ||||
-rw-r--r-- | app/controllers/concerns/invisible_captcha.rb | 51 | ||||
-rw-r--r-- | app/controllers/concerns/issuable_actions.rb | 25 | ||||
-rw-r--r-- | app/controllers/concerns/issuable_collections.rb | 61 | ||||
-rw-r--r-- | app/controllers/concerns/issuable_collections_action.rb | 2 | ||||
-rw-r--r-- | app/controllers/concerns/notes_actions.rb | 7 | ||||
-rw-r--r-- | app/controllers/concerns/requires_whitelisted_monitoring_client.rb | 2 | ||||
-rw-r--r-- | app/controllers/concerns/sessionless_authentication.rb | 2 | ||||
-rw-r--r-- | app/controllers/concerns/sorting_preference.rb | 85 | ||||
-rw-r--r-- | app/controllers/concerns/toggle_award_emoji.rb | 19 | ||||
-rw-r--r-- | app/controllers/concerns/uploads_actions.rb | 2 | ||||
-rw-r--r-- | app/controllers/concerns/with_performance_bar.rb | 4 |
14 files changed, 205 insertions, 104 deletions
diff --git a/app/controllers/concerns/authenticates_with_two_factor.rb b/app/controllers/concerns/authenticates_with_two_factor.rb index 4926062f9ca..8c8f0b3a22e 100644 --- a/app/controllers/concerns/authenticates_with_two_factor.rb +++ b/app/controllers/concerns/authenticates_with_two_factor.rb @@ -55,7 +55,7 @@ module AuthenticatesWithTwoFactor remember_me(user) if user_params[:remember_me] == '1' user.save! - sign_in(user, message: :two_factor_authenticated) + sign_in(user, message: :two_factor_authenticated, event: :authentication) else user.increment_failed_attempts! Gitlab::AppLogger.info("Failed Login: user=#{user.username} ip=#{request.remote_ip} method=OTP") @@ -72,7 +72,7 @@ module AuthenticatesWithTwoFactor session.delete(:challenge) remember_me(user) if user_params[:remember_me] == '1' - sign_in(user, message: :two_factor_authenticated) + sign_in(user, message: :two_factor_authenticated, event: :authentication) else user.increment_failed_attempts! Gitlab::AppLogger.info("Failed Login: user=#{user.username} ip=#{request.remote_ip} method=U2F") diff --git a/app/controllers/concerns/confirm_email_warning.rb b/app/controllers/concerns/confirm_email_warning.rb new file mode 100644 index 00000000000..5a4b5897a4f --- /dev/null +++ b/app/controllers/concerns/confirm_email_warning.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +module ConfirmEmailWarning + extend ActiveSupport::Concern + + included do + before_action :set_confirm_warning, if: -> { Feature.enabled?(:soft_email_confirmation) } + end + + protected + + def set_confirm_warning + return unless current_user + return if current_user.confirmed? + return if peek_request? || json_request? || !request.get? + + email = current_user.unconfirmed_email || current_user.email + + flash.now[:warning] = _("Please check your email (%{email}) to verify that you own this address. Didn't receive it? %{resend_link}. Wrong email address? %{update_link}.").html_safe % { + email: email, + resend_link: view_context.link_to(_('Resend it'), user_confirmation_path(user: { email: email }), method: :post), + update_link: view_context.link_to(_('Update it'), profile_path) + } + end +end diff --git a/app/controllers/concerns/group_tree.rb b/app/controllers/concerns/group_tree.rb index e9a7d6a3152..d076c62c707 100644 --- a/app/controllers/concerns/group_tree.rb +++ b/app/controllers/concerns/group_tree.rb @@ -32,18 +32,14 @@ module GroupTree def filtered_groups_with_ancestors(groups) filtered_groups = groups.search(params[:filter]).page(params[:page]) - if Group.supports_nested_objects? - # We find the ancestors by ID of the search results here. - # Otherwise the ancestors would also have filters applied, - # which would cause them not to be preloaded. - # - # Pagination needs to be applied before loading the ancestors to - # make sure ancestors are not cut off by pagination. - Gitlab::ObjectHierarchy.new(Group.where(id: filtered_groups.select(:id))) - .base_and_ancestors - else - filtered_groups - end + # We find the ancestors by ID of the search results here. + # Otherwise the ancestors would also have filters applied, + # which would cause them not to be preloaded. + # + # Pagination needs to be applied before loading the ancestors to + # make sure ancestors are not cut off by pagination. + Gitlab::ObjectHierarchy.new(Group.where(id: filtered_groups.select(:id))) + .base_and_ancestors end # rubocop: enable CodeReuse/ActiveRecord end diff --git a/app/controllers/concerns/invisible_captcha.rb b/app/controllers/concerns/invisible_captcha.rb new file mode 100644 index 00000000000..45c0a5c58ef --- /dev/null +++ b/app/controllers/concerns/invisible_captcha.rb @@ -0,0 +1,51 @@ +# frozen_string_literal: true + +module InvisibleCaptcha + extend ActiveSupport::Concern + + included do + invisible_captcha only: :create, on_spam: :on_honeypot_spam_callback, on_timestamp_spam: :on_timestamp_spam_callback + end + + def on_honeypot_spam_callback + return unless Feature.enabled?(:invisible_captcha) + + invisible_captcha_honeypot_counter.increment + log_request('Invisible_Captcha_Honeypot_Request') + + head(200) + end + + def on_timestamp_spam_callback + return unless Feature.enabled?(:invisible_captcha) + + invisible_captcha_timestamp_counter.increment + log_request('Invisible_Captcha_Timestamp_Request') + + redirect_to new_user_session_path, alert: InvisibleCaptcha.timestamp_error_message + end + + def invisible_captcha_honeypot_counter + @invisible_captcha_honeypot_counter ||= + Gitlab::Metrics.counter(:bot_blocked_by_invisible_captcha_honeypot, + 'Counter of blocked sign up attempts with filled honeypot') + end + + def invisible_captcha_timestamp_counter + @invisible_captcha_timestamp_counter ||= + Gitlab::Metrics.counter(:bot_blocked_by_invisible_captcha_timestamp, + 'Counter of blocked sign up attempts with invalid timestamp') + end + + def log_request(message) + request_information = { + message: message, + env: :invisible_captcha_signup_bot_detected, + remote_ip: request.ip, + request_method: request.request_method, + path: request.fullpath + } + + Gitlab::AuthLogger.error(request_information) + end +end diff --git a/app/controllers/concerns/issuable_actions.rb b/app/controllers/concerns/issuable_actions.rb index 6fa2f75be33..b86e4451a7e 100644 --- a/app/controllers/concerns/issuable_actions.rb +++ b/app/controllers/concerns/issuable_actions.rb @@ -98,13 +98,12 @@ module IssuableActions render json: { notice: "#{quantity} #{resource_name.pluralize(quantity)} updated" } end - # rubocop: disable CodeReuse/ActiveRecord + # rubocop:disable CodeReuse/ActiveRecord def discussions - notes = issuable.discussion_notes - .inc_relations_for_view - .with_notes_filter(notes_filter) - .includes(:noteable) - .fresh + notes = NotesFinder.new(current_user, finder_params_for_issuable).execute + .inc_relations_for_view + .includes(:noteable) + .fresh if notes_filter != UserPreference::NOTES_FILTERS[:only_comments] notes = ResourceEvents::MergeIntoNotesService.new(issuable, current_user).execute(notes) @@ -117,7 +116,7 @@ module IssuableActions render json: discussion_serializer.represent(discussions, context: self) end - # rubocop: enable CodeReuse/ActiveRecord + # rubocop:enable CodeReuse/ActiveRecord private @@ -128,7 +127,8 @@ module IssuableActions # GitLab Geo does not expect database UPDATE or INSERT statements to happen # on GET requests. # This is just a fail-safe in case notes_filter is sent via GET request in GitLab Geo. - if Gitlab::Database.read_only? + # In some cases, we also force the filter to not be persisted with the `persist_filter` param + if Gitlab::Database.read_only? || params[:persist_filter] == 'false' notes_filter_param || current_user&.notes_filter_for(issuable) else notes_filter = current_user&.set_notes_filter(notes_filter_param, issuable) || notes_filter_param @@ -222,4 +222,13 @@ module IssuableActions def parent @project || @group # rubocop:disable Gitlab/ModuleWithInstanceVariables end + + # 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) } + end + # rubocop:enable Gitlab/ModuleWithInstanceVariables end diff --git a/app/controllers/concerns/issuable_collections.rb b/app/controllers/concerns/issuable_collections.rb index 21b3949e361..8ea77b994de 100644 --- a/app/controllers/concerns/issuable_collections.rb +++ b/app/controllers/concerns/issuable_collections.rb @@ -2,8 +2,8 @@ module IssuableCollections extend ActiveSupport::Concern - include CookiesHelper include SortingHelper + include SortingPreference include Gitlab::IssuableMetadata include Gitlab::Utils::StrongMemoize @@ -127,47 +127,8 @@ module IssuableCollections 'opened' end - def set_sort_order - set_sort_order_from_user_preference || set_sort_order_from_cookie || default_sort_order - end - - def set_sort_order_from_user_preference - return unless current_user - return unless issuable_sorting_field - - user_preference = current_user.user_preference - - sort_param = params[:sort] - sort_param ||= user_preference[issuable_sorting_field] - - return sort_param if Gitlab::Database.read_only? - - if user_preference[issuable_sorting_field] != sort_param - user_preference.update(issuable_sorting_field => sort_param) - end - - sort_param - end - - # Implement issuable_sorting_field method on controllers - # to choose which column to store the sorting parameter. - def issuable_sorting_field - nil - end - - def set_sort_order_from_cookie - sort_param = params[:sort] if params[:sort].present? - # fallback to legacy cookie value for backward compatibility - sort_param ||= cookies['issuable_sort'] - sort_param ||= cookies[remember_sorting_key] - - sort_value = update_cookie_value(sort_param) - set_secure_cookie(remember_sorting_key, sort_value) - sort_value - end - - def remember_sorting_key - @remember_sorting_key ||= "#{collection_type.downcase}_sort" + def legacy_sort_cookie_name + 'issuable_sort' end def default_sort_order @@ -178,26 +139,14 @@ module IssuableCollections end end - # Update old values to the actual ones. - def update_cookie_value(value) - case value - when 'id_asc' then sort_value_oldest_created - when 'id_desc' then sort_value_recently_created - when 'downvotes_asc' then sort_value_popularity - when 'downvotes_desc' then sort_value_popularity - else value - end - end - def finder @finder ||= issuable_finder_for(finder_type) end def collection_type - @collection_type ||= case finder_type.name - when 'IssuesFinder' + @collection_type ||= if finder_type <= IssuesFinder 'Issue' - when 'MergeRequestsFinder' + elsif finder_type <= MergeRequestsFinder 'MergeRequest' end end diff --git a/app/controllers/concerns/issuable_collections_action.rb b/app/controllers/concerns/issuable_collections_action.rb index 4ad287c4a13..0a6f684a9fc 100644 --- a/app/controllers/concerns/issuable_collections_action.rb +++ b/app/controllers/concerns/issuable_collections_action.rb @@ -32,7 +32,7 @@ module IssuableCollectionsAction private - def issuable_sorting_field + def sorting_field case action_name when 'issues' Issue::SORTING_PREFERENCE_FIELD diff --git a/app/controllers/concerns/notes_actions.rb b/app/controllers/concerns/notes_actions.rb index 0098c4cdf4c..4b7899d469b 100644 --- a/app/controllers/concerns/notes_actions.rb +++ b/app/controllers/concerns/notes_actions.rb @@ -73,6 +73,11 @@ module NotesActions # rubocop:disable Gitlab/ModuleWithInstanceVariables def update @note = Notes::UpdateService.new(project, current_user, update_note_params).execute(note) + unless @note + head :gone + return + end + prepare_notes_for_rendering([@note]) respond_to do |format| @@ -243,7 +248,7 @@ module NotesActions end def notes_finder - @notes_finder ||= NotesFinder.new(project, current_user, finder_params) + @notes_finder ||= NotesFinder.new(current_user, finder_params) end def note_serializer diff --git a/app/controllers/concerns/requires_whitelisted_monitoring_client.rb b/app/controllers/concerns/requires_whitelisted_monitoring_client.rb index f47ead2f0da..2e9905997db 100644 --- a/app/controllers/concerns/requires_whitelisted_monitoring_client.rb +++ b/app/controllers/concerns/requires_whitelisted_monitoring_client.rb @@ -28,7 +28,7 @@ module RequiresWhitelistedMonitoringClient def valid_token? token = params[:token].presence || request.headers['TOKEN'] token.present? && - ActiveSupport::SecurityUtils.variable_size_secure_compare( + ActiveSupport::SecurityUtils.secure_compare( token, Gitlab::CurrentSettings.health_check_access_token ) diff --git a/app/controllers/concerns/sessionless_authentication.rb b/app/controllers/concerns/sessionless_authentication.rb index 590eefc6dab..4304b8565ce 100644 --- a/app/controllers/concerns/sessionless_authentication.rb +++ b/app/controllers/concerns/sessionless_authentication.rb @@ -13,7 +13,7 @@ module SessionlessAuthentication end def sessionless_user? - current_user && !session.keys.include?('warden.user.user.key') + current_user && !session.key?('warden.user.user.key') end def sessionless_sign_in(user) diff --git a/app/controllers/concerns/sorting_preference.rb b/app/controllers/concerns/sorting_preference.rb new file mode 100644 index 00000000000..a51b68147d5 --- /dev/null +++ b/app/controllers/concerns/sorting_preference.rb @@ -0,0 +1,85 @@ +# frozen_string_literal: true + +module SortingPreference + include SortingHelper + include CookiesHelper + + def set_sort_order + set_sort_order_from_user_preference || set_sort_order_from_cookie || params[:sort] || default_sort_order + end + + # Implement sorting_field method on controllers + # to choose which column to store the sorting parameter. + def sorting_field + nil + end + + # Implement default_sort_order method on controllers + # to choose which default sort should be applied if + # sort param is not provided. + def default_sort_order + nil + end + + # Implement legacy_sort_cookie_name method on controllers + # to set sort from cookie for backwards compatibility. + def legacy_sort_cookie_name + nil + end + + private + + def set_sort_order_from_user_preference + return unless current_user + return unless sorting_field + + user_preference = current_user.user_preference + + sort_param = params[:sort] + sort_param ||= user_preference[sorting_field] + + return sort_param if Gitlab::Database.read_only? + + if user_preference[sorting_field] != sort_param + user_preference.update(sorting_field => sort_param) + end + + sort_param + end + + def set_sort_order_from_cookie + return unless legacy_sort_cookie_name + + sort_param = params[:sort] if params[:sort].present? + # fallback to legacy cookie value for backward compatibility + sort_param ||= cookies[legacy_sort_cookie_name] + sort_param ||= cookies[remember_sorting_key] + + sort_value = update_cookie_value(sort_param) + set_secure_cookie(remember_sorting_key, sort_value) + sort_value + end + + # Convert sorting_field to legacy cookie name for backwards compatibility + # :merge_requests_sort => 'mergerequest_sort' + # :issues_sort => 'issue_sort' + def remember_sorting_key + @remember_sorting_key ||= sorting_field + .to_s + .split('_')[0..-2] + .map(&:singularize) + .join('') + .concat('_sort') + end + + # Update old values to the actual ones. + def update_cookie_value(value) + case value + when 'id_asc' then sort_value_oldest_created + when 'id_desc' then sort_value_recently_created + when 'downvotes_asc' then sort_value_popularity + when 'downvotes_desc' then sort_value_popularity + else value + end + end +end diff --git a/app/controllers/concerns/toggle_award_emoji.rb b/app/controllers/concerns/toggle_award_emoji.rb index 97b343f8b1a..24d178781d6 100644 --- a/app/controllers/concerns/toggle_award_emoji.rb +++ b/app/controllers/concerns/toggle_award_emoji.rb @@ -7,12 +7,9 @@ module ToggleAwardEmoji authenticate_user! name = params.require(:name) - if awardable.user_can_award?(current_user) - awardable.toggle_award_emoji(name, current_user) - - todoable = to_todoable(awardable) - TodoService.new.new_award_emoji(todoable, current_user) if todoable + service = AwardEmojis::ToggleService.new(awardable, name, current_user).execute + if service[:status] == :success render json: { ok: true } else render json: { ok: false } @@ -21,18 +18,6 @@ module ToggleAwardEmoji private - def to_todoable(awardable) - case awardable - when Note - # we don't create todos for personal snippet comments for now - awardable.for_personal_snippet? ? nil : awardable.noteable - when MergeRequest, Issue - awardable - when Snippet - nil - end - end - def awardable raise NotImplementedError end diff --git a/app/controllers/concerns/uploads_actions.rb b/app/controllers/concerns/uploads_actions.rb index 59f6d3452a3..f5d35379e10 100644 --- a/app/controllers/concerns/uploads_actions.rb +++ b/app/controllers/concerns/uploads_actions.rb @@ -90,7 +90,7 @@ module UploadsActions return unless uploader = build_uploader upload_paths = uploader.upload_paths(params[:filename]) - upload = Upload.find_by(uploader: uploader_class.to_s, path: upload_paths) + upload = Upload.find_by(model: model, uploader: uploader_class.to_s, path: upload_paths) upload&.build_uploader end # rubocop: enable CodeReuse/ActiveRecord diff --git a/app/controllers/concerns/with_performance_bar.rb b/app/controllers/concerns/with_performance_bar.rb index 77c3d476ac6..4e0ae3c59eb 100644 --- a/app/controllers/concerns/with_performance_bar.rb +++ b/app/controllers/concerns/with_performance_bar.rb @@ -3,10 +3,6 @@ module WithPerformanceBar extend ActiveSupport::Concern - included do - include Peek::Rblineprof::CustomControllerHelpers - end - def peek_enabled? return false unless Gitlab::PerformanceBar.enabled?(current_user) |