diff options
Diffstat (limited to 'app/services/spam')
-rw-r--r-- | app/services/spam/akismet_service.rb | 2 | ||||
-rw-r--r-- | app/services/spam/spam_action_service.rb | 91 | ||||
-rw-r--r-- | app/services/spam/spam_check_service.rb | 68 | ||||
-rw-r--r-- | app/services/spam/spam_constants.rb | 9 | ||||
-rw-r--r-- | app/services/spam/spam_verdict_service.rb | 26 |
5 files changed, 127 insertions, 69 deletions
diff --git a/app/services/spam/akismet_service.rb b/app/services/spam/akismet_service.rb index 7d16743b3ed..ab35fb8700f 100644 --- a/app/services/spam/akismet_service.rb +++ b/app/services/spam/akismet_service.rb @@ -17,7 +17,7 @@ module Spam params = { type: 'comment', text: text, - created_at: DateTime.now, + created_at: DateTime.current, author: owner_name, author_email: owner_email, referrer: options[:referrer] diff --git a/app/services/spam/spam_action_service.rb b/app/services/spam/spam_action_service.rb new file mode 100644 index 00000000000..f0a4aff4443 --- /dev/null +++ b/app/services/spam/spam_action_service.rb @@ -0,0 +1,91 @@ +# frozen_string_literal: true + +module Spam + class SpamActionService + include SpamConstants + + attr_accessor :target, :request, :options + attr_reader :spam_log + + def initialize(spammable:, request:) + @target = spammable + @request = request + @options = {} + + if @request + @options[:ip_address] = @request.env['action_dispatch.remote_ip'].to_s + @options[:user_agent] = @request.env['HTTP_USER_AGENT'] + @options[:referrer] = @request.env['HTTP_REFERRER'] + else + @options[:ip_address] = @target.ip_address + @options[:user_agent] = @target.user_agent + end + end + + def execute(api: false, recaptcha_verified:, spam_log_id:, user:) + if recaptcha_verified + # If it's a request which is already verified through reCAPTCHA, + # update the spam log accordingly. + SpamLog.verify_recaptcha!(user_id: user.id, id: spam_log_id) + else + return if allowlisted?(user) + return unless request + return unless check_for_spam? + + perform_spam_service_check(api) + end + end + + delegate :check_for_spam?, to: :target + + private + + def allowlisted?(user) + user.respond_to?(:gitlab_employee) && user.gitlab_employee? + end + + def perform_spam_service_check(api) + # since we can check for spam, and recaptcha is not verified, + # ask the SpamVerdictService what to do with the target. + spam_verdict_service.execute.tap do |result| + case result + when REQUIRE_RECAPTCHA + create_spam_log(api) + + break if target.allow_possible_spam? + + target.needs_recaptcha! + when DISALLOW + # TODO: remove `unless target.allow_possible_spam?` once this flag has been passed to `SpamVerdictService` + # https://gitlab.com/gitlab-org/gitlab/-/issues/214739 + target.spam! unless target.allow_possible_spam? + create_spam_log(api) + when ALLOW + target.clear_spam_flags! + end + end + end + + def create_spam_log(api) + @spam_log = SpamLog.create!( + { + user_id: target.author_id, + title: target.spam_title, + description: target.spam_description, + source_ip: options[:ip_address], + user_agent: options[:user_agent], + noteable_type: target.class.to_s, + via_api: api + } + ) + + target.spam_log = spam_log + end + + def spam_verdict_service + SpamVerdictService.new(target: target, + request: @request, + options: options) + end + end +end diff --git a/app/services/spam/spam_check_service.rb b/app/services/spam/spam_check_service.rb deleted file mode 100644 index 3269f9d687a..00000000000 --- a/app/services/spam/spam_check_service.rb +++ /dev/null @@ -1,68 +0,0 @@ -# frozen_string_literal: true - -module Spam - class SpamCheckService - include AkismetMethods - - attr_accessor :target, :request, :options - attr_reader :spam_log - - def initialize(spammable:, request:) - @target = spammable - @request = request - @options = {} - - if @request - @options[:ip_address] = @request.env['action_dispatch.remote_ip'].to_s - @options[:user_agent] = @request.env['HTTP_USER_AGENT'] - @options[:referrer] = @request.env['HTTP_REFERRER'] - else - @options[:ip_address] = @target.ip_address - @options[:user_agent] = @target.user_agent - end - end - - def execute(api: false, recaptcha_verified:, spam_log_id:, user_id:) - if recaptcha_verified - # If it's a request which is already verified through recaptcha, - # update the spam log accordingly. - SpamLog.verify_recaptcha!(user_id: user_id, id: spam_log_id) - else - # Otherwise, it goes to Akismet for spam check. - # If so, it assigns spammable object as "spam" and creates a SpamLog record. - possible_spam = check(api) - target.spam = possible_spam unless target.allow_possible_spam? - target.spam_log = spam_log - end - end - - private - - def check(api) - return unless request - return unless check_for_spam? - return unless akismet.spam? - - create_spam_log(api) - true - end - - def check_for_spam? - target.check_for_spam? - end - - def create_spam_log(api) - @spam_log = SpamLog.create!( - { - user_id: target.author_id, - title: target.spam_title, - description: target.spam_description, - source_ip: options[:ip_address], - user_agent: options[:user_agent], - noteable_type: target.class.to_s, - via_api: api - } - ) - end - end -end diff --git a/app/services/spam/spam_constants.rb b/app/services/spam/spam_constants.rb new file mode 100644 index 00000000000..085bac684c4 --- /dev/null +++ b/app/services/spam/spam_constants.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +module Spam + module SpamConstants + REQUIRE_RECAPTCHA = :recaptcha + DISALLOW = :disallow + ALLOW = :allow + end +end diff --git a/app/services/spam/spam_verdict_service.rb b/app/services/spam/spam_verdict_service.rb new file mode 100644 index 00000000000..2b4d5f4a984 --- /dev/null +++ b/app/services/spam/spam_verdict_service.rb @@ -0,0 +1,26 @@ +# frozen_string_literal: true + +module Spam + class SpamVerdictService + include AkismetMethods + include SpamConstants + + def initialize(target:, request:, options:) + @target = target + @request = request + @options = options + end + + def execute + if akismet.spam? + Gitlab::Recaptcha.enabled? ? REQUIRE_RECAPTCHA : DISALLOW + else + ALLOW + end + end + + private + + attr_reader :target, :request, :options + end +end |