2018-08-03 13:22:24 -04:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2016-07-21 19:11:53 -04:00
|
|
|
module Spammable
|
|
|
|
extend ActiveSupport::Concern
|
2016-07-28 20:02:56 -04:00
|
|
|
|
2018-08-27 08:35:31 -04:00
|
|
|
class_methods do
|
2016-08-05 18:10:08 -04:00
|
|
|
def attr_spammable(attr, options = {})
|
|
|
|
spammable_attrs << [attr.to_s, options]
|
2016-07-28 20:02:56 -04:00
|
|
|
end
|
|
|
|
end
|
2016-07-21 19:11:53 -04:00
|
|
|
|
|
|
|
included do
|
2017-06-08 11:16:27 -04:00
|
|
|
has_one :user_agent_detail, as: :subject, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
|
2016-08-09 13:43:47 -04:00
|
|
|
|
2022-02-20 19:18:15 -05:00
|
|
|
attr_writer :spam
|
2020-04-21 11:21:10 -04:00
|
|
|
attr_accessor :needs_recaptcha
|
2017-01-27 11:25:39 -05:00
|
|
|
attr_accessor :spam_log
|
2020-04-21 11:21:10 -04:00
|
|
|
|
2017-11-21 10:15:24 -05:00
|
|
|
alias_method :spam?, :spam
|
2020-04-21 11:21:10 -04:00
|
|
|
alias_method :needs_recaptcha?, :needs_recaptcha
|
2016-08-09 13:43:47 -04:00
|
|
|
|
2020-04-21 11:21:10 -04:00
|
|
|
# if spam errors are added before validation, they will be wiped
|
2020-02-26 04:08:47 -05:00
|
|
|
after_validation :invalidate_if_spam, on: [:create, :update]
|
2016-07-28 20:02:56 -04:00
|
|
|
|
|
|
|
cattr_accessor :spammable_attrs, instance_accessor: false do
|
|
|
|
[]
|
|
|
|
end
|
2016-08-09 13:43:47 -04:00
|
|
|
|
|
|
|
delegate :ip_address, :user_agent, to: :user_agent_detail, allow_nil: true
|
2016-07-28 20:02:56 -04:00
|
|
|
end
|
|
|
|
|
2022-02-20 19:18:15 -05:00
|
|
|
def spam
|
|
|
|
!!@spam # rubocop:disable Gitlab/ModuleWithInstanceVariables
|
|
|
|
end
|
|
|
|
|
2017-02-10 05:41:22 -05:00
|
|
|
def submittable_as_spam_by?(current_user)
|
|
|
|
current_user && current_user.admin? && submittable_as_spam?
|
|
|
|
end
|
|
|
|
|
2016-08-09 13:43:47 -04:00
|
|
|
def submittable_as_spam?
|
2016-07-28 20:02:56 -04:00
|
|
|
if user_agent_detail
|
2017-08-31 05:47:03 -04:00
|
|
|
user_agent_detail.submittable? && Gitlab::CurrentSettings.current_application_settings.akismet_enabled
|
2016-07-28 20:02:56 -04:00
|
|
|
else
|
|
|
|
false
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2020-04-07 05:09:13 -04:00
|
|
|
def needs_recaptcha!
|
2020-04-21 11:21:10 -04:00
|
|
|
self.needs_recaptcha = true
|
2020-04-07 05:09:13 -04:00
|
|
|
end
|
|
|
|
|
2021-01-28 19:09:17 -05:00
|
|
|
##
|
|
|
|
# Indicates if a recaptcha should be rendered before allowing this model to be saved.
|
|
|
|
#
|
|
|
|
def render_recaptcha?
|
|
|
|
return false unless Gitlab::Recaptcha.enabled?
|
|
|
|
|
|
|
|
return false if self.errors.count > 1 # captcha should not be rendered if are still other errors
|
|
|
|
|
|
|
|
self.needs_recaptcha?
|
|
|
|
end
|
|
|
|
|
2020-04-21 11:21:10 -04:00
|
|
|
def spam!
|
|
|
|
self.spam = true
|
2020-04-07 05:09:13 -04:00
|
|
|
end
|
|
|
|
|
2020-04-21 11:21:10 -04:00
|
|
|
def clear_spam_flags!
|
|
|
|
self.spam = false
|
|
|
|
self.needs_recaptcha = false
|
|
|
|
end
|
2020-04-07 05:09:13 -04:00
|
|
|
|
2020-04-21 11:21:10 -04:00
|
|
|
def invalidate_if_spam
|
|
|
|
if needs_recaptcha? && Gitlab::Recaptcha.enabled?
|
|
|
|
recaptcha_error!
|
|
|
|
elsif needs_recaptcha? || spam?
|
2020-04-07 05:09:13 -04:00
|
|
|
unrecoverable_spam_error!
|
|
|
|
end
|
2017-02-01 13:15:59 -05:00
|
|
|
end
|
|
|
|
|
2020-04-21 11:21:10 -04:00
|
|
|
def recaptcha_error!
|
2022-03-03 07:14:02 -05:00
|
|
|
self.errors.add(:base, _("Your %{spammable_entity_type} has been recognized as spam. "\
|
|
|
|
"Please, change the content or solve the reCAPTCHA to proceed.") \
|
|
|
|
% { spammable_entity_type: spammable_entity_type })
|
2020-04-21 11:21:10 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
def unrecoverable_spam_error!
|
2022-04-15 11:10:38 -04:00
|
|
|
self.errors.add(:base, _("Your %{spammable_entity_type} has been recognized as spam and has been discarded.") \
|
|
|
|
% { spammable_entity_type: spammable_entity_type })
|
2020-04-21 11:21:10 -04:00
|
|
|
end
|
|
|
|
|
2017-02-01 13:15:59 -05:00
|
|
|
def spammable_entity_type
|
|
|
|
self.class.name.underscore
|
2016-07-30 00:18:32 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
def spam_title
|
2016-08-09 13:43:47 -04:00
|
|
|
attr = self.class.spammable_attrs.find do |_, options|
|
2016-08-05 18:10:08 -04:00
|
|
|
options.fetch(:spam_title, false)
|
|
|
|
end
|
|
|
|
|
2017-08-03 22:20:34 -04:00
|
|
|
public_send(attr.first) if attr && respond_to?(attr.first.to_sym) # rubocop:disable GitlabSecurity/PublicSend
|
2016-07-30 00:18:32 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
def spam_description
|
2016-08-09 13:43:47 -04:00
|
|
|
attr = self.class.spammable_attrs.find do |_, options|
|
2016-08-05 18:10:08 -04:00
|
|
|
options.fetch(:spam_description, false)
|
|
|
|
end
|
2016-07-28 20:02:56 -04:00
|
|
|
|
2017-08-03 22:20:34 -04:00
|
|
|
public_send(attr.first) if attr && respond_to?(attr.first.to_sym) # rubocop:disable GitlabSecurity/PublicSend
|
2016-08-05 18:10:08 -04:00
|
|
|
end
|
2016-07-28 20:02:56 -04:00
|
|
|
|
|
|
|
def spammable_text
|
2016-08-09 13:43:47 -04:00
|
|
|
result = self.class.spammable_attrs.map do |attr|
|
2017-08-03 22:20:34 -04:00
|
|
|
public_send(attr.first) # rubocop:disable GitlabSecurity/PublicSend
|
2016-07-28 20:02:56 -04:00
|
|
|
end
|
2016-08-05 18:10:08 -04:00
|
|
|
|
2016-07-28 20:02:56 -04:00
|
|
|
result.reject(&:blank?).join("\n")
|
|
|
|
end
|
|
|
|
|
2016-08-05 18:10:08 -04:00
|
|
|
# Override in Spammable if further checks are necessary
|
2021-07-20 02:08:37 -04:00
|
|
|
def check_for_spam?(user:)
|
2016-08-09 13:43:47 -04:00
|
|
|
true
|
2016-07-21 19:11:53 -04:00
|
|
|
end
|
2019-09-24 23:06:21 -04:00
|
|
|
|
|
|
|
# Override in Spammable if differs
|
|
|
|
def allow_possible_spam?
|
|
|
|
Feature.enabled?(:allow_possible_spam, project)
|
|
|
|
end
|
2016-07-21 19:11:53 -04:00
|
|
|
end
|